11import { Icon } from '@iconify/react' ;
2+ import { Dialog } from '@kinvolk/headlamp-plugin/lib/CommonComponents' ;
23import {
4+ Accordion ,
5+ AccordionDetails ,
6+ AccordionSummary ,
37 Box ,
48 Button ,
59 Chip ,
610 CircularProgress ,
7- Dialog ,
811 DialogActions ,
912 DialogContent ,
1013 DialogTitle ,
1114 Divider ,
15+ InputAdornment ,
1216 List ,
1317 ListItem ,
1418 ListItemSecondaryAction ,
1519 ListItemText ,
1620 Switch ,
21+ TextField ,
1722 Typography ,
1823} from '@mui/material' ;
1924import React , { useEffect , useState } from 'react' ;
20- import tools from '../../ai/mcp/electron-client' ;
25+ import { ElectronMCPClient } from '../../ai/mcp/electron-client' ;
2126import { AVAILABLE_TOOLS } from '../../langchain/tools/registry' ;
2227
2328interface MCPTool {
@@ -41,7 +46,9 @@ export const ToolsDialog: React.FC<ToolsDialogProps> = ({
4146} ) => {
4247 const [ localEnabledTools , setLocalEnabledTools ] = useState < string [ ] > ( enabledTools ) ;
4348 const [ mcpTools , setMcpTools ] = useState < MCPTool [ ] > ( [ ] ) ;
44- const [ loadingMcpTools , setLoadingMcpTools ] = useState < boolean > ( false ) ;
49+ const [ isLoadingMcp , setIsLoadingMcp ] = useState < boolean > ( true ) ;
50+ const [ searchQuery , setSearchQuery ] = useState < string > ( '' ) ;
51+ const [ expandedServers , setExpandedServers ] = useState < Set < string > > ( new Set ( [ 'MCP Tools' ] ) ) ;
4552
4653 // Load MCP tools when dialog opens
4754 useEffect ( ( ) => {
@@ -56,22 +63,48 @@ export const ToolsDialog: React.FC<ToolsDialogProps> = ({
5663 } , [ enabledTools ] ) ;
5764
5865 const loadMcpTools = async ( ) => {
59- setLoadingMcpTools ( true ) ;
66+ console . log ( 'ToolsDialog: Starting to load MCP tools...' ) ;
67+ setIsLoadingMcp ( true ) ;
6068 try {
61- const mcpToolsData = await tools ( ) ;
62- setMcpTools ( mcpToolsData || [ ] ) ;
69+ const mcpClient = new ElectronMCPClient ( ) ;
70+ console . log ( 'ToolsDialog: Created MCP client, isAvailable:' , mcpClient . isAvailable ( ) ) ;
71+ const tools = await mcpClient . getTools ( ) ;
72+ console . log ( 'ToolsDialog: Received tools from client:' , tools . length , 'tools' ) ;
73+ console . log ( 'ToolsDialog: Tools:' , tools ) ;
74+ setMcpTools ( tools ) ;
6375 } catch ( error ) {
64- console . warn ( ' Failed to load MCP tools:', error ) ;
76+ console . error ( 'ToolsDialog: Failed to load MCP tools:', error ) ;
6577 setMcpTools ( [ ] ) ;
6678 } finally {
67- setLoadingMcpTools ( false ) ;
79+ setIsLoadingMcp ( false ) ;
6880 }
6981 } ;
7082
7183 const handleToggleTool = ( toolName : string ) => {
72- setLocalEnabledTools ( prev =>
73- prev . includes ( toolName ) ? prev . filter ( name => name !== toolName ) : [ ...prev , toolName ]
74- ) ;
84+ const newEnabledTools = localEnabledTools . includes ( toolName )
85+ ? localEnabledTools . filter ( name => name !== toolName )
86+ : [ ...localEnabledTools , toolName ] ;
87+ setLocalEnabledTools ( newEnabledTools ) ;
88+ } ;
89+
90+ // Filter tools based on search query
91+ const filteredMcpTools = mcpTools . filter (
92+ tool =>
93+ tool . name . toLowerCase ( ) . includes ( searchQuery . toLowerCase ( ) ) ||
94+ ( tool . description && tool . description . toLowerCase ( ) . includes ( searchQuery . toLowerCase ( ) ) )
95+ ) ;
96+
97+ // Group tools by server (simplified version for now)
98+ const groupedTools = { 'MCP Tools' : filteredMcpTools } ;
99+
100+ const handleToggleServer = ( serverName : string ) => {
101+ const newExpanded = new Set ( expandedServers ) ;
102+ if ( newExpanded . has ( serverName ) ) {
103+ newExpanded . delete ( serverName ) ;
104+ } else {
105+ newExpanded . add ( serverName ) ;
106+ }
107+ setExpandedServers ( newExpanded ) ;
75108 } ;
76109
77110 const handleSave = ( ) => {
@@ -101,71 +134,118 @@ export const ToolsDialog: React.FC<ToolsDialogProps> = ({
101134 MCP Tools
102135 </ Typography >
103136 < Typography variant = "body2" color = "text.secondary" >
104- External Model Context Protocol tools (always enabled)
137+ These are Model Context Protocol tools that provide additional capabilities to the
138+ assistant.
105139 </ Typography >
140+
141+ { /* Search Bar */ }
142+ < TextField
143+ fullWidth
144+ placeholder = "Search MCP tools..."
145+ value = { searchQuery }
146+ onChange = { e => setSearchQuery ( e . target . value ) }
147+ size = "small"
148+ sx = { { mt : 2 } }
149+ InputProps = { {
150+ startAdornment : (
151+ < InputAdornment position = "start" >
152+ < Icon icon = "mdi:magnify" style = { { fontSize : 20 } } />
153+ </ InputAdornment >
154+ ) ,
155+ } }
156+ />
106157 </ Box >
107158
108- { loadingMcpTools ? (
159+ { isLoadingMcp ? (
109160 < Box sx = { { display : 'flex' , justifyContent : 'center' , my : 3 } } >
110161 < CircularProgress size = { 24 } />
111162 < Typography variant = "body2" sx = { { ml : 2 } } >
112163 Loading MCP tools...
113164 </ Typography >
114165 </ Box >
115166 ) : (
116- < List >
117- { mcpTools . length > 0 ? (
118- mcpTools . map ( ( tool , index ) => (
119- < ListItem key = { `mcp-${ index } ` } >
120- < Box
121- sx = { {
122- display : 'flex' ,
123- alignItems : 'center' ,
124- minWidth : 40 ,
125- justifyContent : 'center' ,
126- } }
127- >
128- < Icon
129- icon = { getToolIcon ( tool . name , 'mcp' ) }
130- style = { { fontSize : 20 , marginRight : 8 } }
131- />
132- </ Box >
133- < ListItemText
134- primary = {
135- < Box sx = { { display : 'flex' , alignItems : 'center' , gap : 1 } } >
136- < Typography variant = "body1" > { tool . name } </ Typography >
137- < Chip label = "MCP" size = "small" color = "info" variant = "outlined" />
138- </ Box >
139- }
140- secondary = { tool . description || 'External MCP tool' }
141- />
142- < ListItemSecondaryAction >
143- < Switch
144- edge = "end"
145- onChange = { ( ) => handleToggleTool ( tool . name ) }
146- checked = { localEnabledTools . includes ( tool . name ) }
147- color = "primary"
148- />
149- </ ListItemSecondaryAction >
150- </ ListItem >
151- ) )
152- ) : (
153- < ListItem >
154- < ListItemText
155- primary = {
156- < Typography variant = "body2" color = "text.secondary" sx = { { fontStyle : 'italic' } } >
157- No MCP tools available. Configure MCP servers to see tools here.
158- </ Typography >
159- }
160- />
161- </ ListItem >
167+ < >
168+ { Object . entries ( groupedTools ) . map ( ( [ serverName , tools ] ) => (
169+ < Accordion
170+ key = { serverName }
171+ expanded = { expandedServers . has ( serverName ) }
172+ onChange = { ( ) => handleToggleServer ( serverName ) }
173+ sx = { { mb : 1 } }
174+ >
175+ < AccordionSummary expandIcon = { < Icon icon = "mdi:chevron-down" /> } >
176+ < Typography variant = "subtitle1" >
177+ { serverName } ({ tools . length } )
178+ </ Typography >
179+ </ AccordionSummary >
180+ < AccordionDetails sx = { { p : 0 } } >
181+ < List >
182+ { tools . map ( ( tool , index ) => (
183+ < >
184+ < ListItem key = { `${ serverName } -${ index } ` } >
185+ < Box
186+ sx = { {
187+ display : 'flex' ,
188+ alignItems : 'center' ,
189+ minWidth : 40 ,
190+ justifyContent : 'center' ,
191+ mr : 1 ,
192+ } }
193+ >
194+ < Icon
195+ icon = { getToolIcon ( tool . name , 'mcp' ) }
196+ style = { { fontSize : 20 , marginRight : 8 } }
197+ />
198+ </ Box >
199+
200+ < ListItemText
201+ primary = {
202+ < Box sx = { { display : 'flex' , alignItems : 'center' , gap : 1 } } >
203+ < Typography variant = "body1" > { tool . name } </ Typography >
204+ < Chip label = "MCP" size = "small" color = "info" variant = "outlined" />
205+ </ Box >
206+ }
207+ secondary = { tool . description }
208+ />
209+
210+ < ListItemSecondaryAction >
211+ < Switch
212+ edge = "end"
213+ onChange = { ( ) => handleToggleTool ( tool . name ) }
214+ checked = { localEnabledTools . includes ( tool . name ) }
215+ />
216+ </ ListItemSecondaryAction >
217+ </ ListItem >
218+ { index < tools . length - 1 && < Divider component = "li" /> }
219+ </ >
220+ ) ) }
221+ </ List >
222+ </ AccordionDetails >
223+ </ Accordion >
224+ ) ) }
225+
226+ { filteredMcpTools . length === 0 && mcpTools . length > 0 && (
227+ < Typography
228+ variant = "body2"
229+ color = "text.secondary"
230+ sx = { { fontStyle : 'italic' , textAlign : 'center' , py : 3 } }
231+ >
232+ No tools match your search query.
233+ </ Typography >
234+ ) }
235+
236+ { mcpTools . length === 0 && (
237+ < Typography
238+ variant = "body2"
239+ color = "text.secondary"
240+ sx = { { fontStyle : 'italic' , textAlign : 'center' , py : 3 } }
241+ >
242+ No MCP tools available. Connect to MCP servers to see available tools.
243+ </ Typography >
162244 ) }
163- </ List >
245+ </ >
164246 ) }
165247 </ >
166- ) ;
167-
168- // Get tool categories
248+ ) ; // Get tool categories
169249 const kubernetesTools = AVAILABLE_TOOLS . filter ( ToolClass => {
170250 const tempTool = new ToolClass ( ) ;
171251 return tempTool . config . name . includes ( 'kubernetes' ) || tempTool . config . name . includes ( 'k8s' ) ;
0 commit comments