1
1
import { Client } from "@modelcontextprotocol/sdk/client/index.js" ;
2
2
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js" ;
3
3
import {
4
- CompatibilityCallToolResultSchema ,
4
+ ClientNotification ,
5
5
ClientRequest ,
6
+ CompatibilityCallToolResult ,
7
+ CompatibilityCallToolResultSchema ,
6
8
CreateMessageRequestSchema ,
7
9
CreateMessageResult ,
8
10
EmptyResultSchema ,
@@ -19,8 +21,6 @@ import {
19
21
Root ,
20
22
ServerNotification ,
21
23
Tool ,
22
- CompatibilityCallToolResult ,
23
- ClientNotification ,
24
24
} from "@modelcontextprotocol/sdk/types.js" ;
25
25
import { useCallback , useEffect , useRef , useState } from "react" ;
26
26
// Add dark mode class based on system preference
@@ -32,21 +32,21 @@ import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
32
32
import {
33
33
Bell ,
34
34
Files ,
35
+ FolderTree ,
35
36
Hammer ,
36
37
Hash ,
37
38
MessageSquare ,
38
39
Send ,
39
40
Terminal ,
40
- FolderTree ,
41
41
} from "lucide-react" ;
42
42
43
+ import { toast } from "react-toastify" ;
43
44
import { ZodType } from "zod" ;
44
45
import "./App.css" ;
45
46
import ConsoleTab from "./components/ConsoleTab" ;
46
47
import HistoryAndNotifications from "./components/History" ;
47
48
import PingTab from "./components/PingTab" ;
48
49
import PromptsTab , { Prompt } from "./components/PromptsTab" ;
49
- import RequestsTab from "./components/RequestsTabs" ;
50
50
import ResourcesTab from "./components/ResourcesTab" ;
51
51
import RootsTab from "./components/RootsTab" ;
52
52
import SamplingTab , { PendingRequest } from "./components/SamplingTab" ;
@@ -67,7 +67,11 @@ const App = () => {
67
67
const [ tools , setTools ] = useState < Tool [ ] > ( [ ] ) ;
68
68
const [ toolResult , setToolResult ] =
69
69
useState < CompatibilityCallToolResult | null > ( null ) ;
70
- const [ error , setError ] = useState < string | null > ( null ) ;
70
+ const [ errors , setErrors ] = useState < Record < string , string | null > > ( {
71
+ resources : null ,
72
+ prompts : null ,
73
+ tools : null ,
74
+ } ) ;
71
75
const [ command , setCommand ] = useState < string > ( ( ) => {
72
76
return localStorage . getItem ( "lastCommand" ) || "mcp-server-everything" ;
73
77
} ) ;
@@ -202,9 +206,14 @@ const App = () => {
202
206
] ) ;
203
207
} ;
204
208
209
+ const clearError = ( tabKey : keyof typeof errors ) => {
210
+ setErrors ( ( prev ) => ( { ...prev , [ tabKey ] : null } ) ) ;
211
+ } ;
212
+
205
213
const makeRequest = async < T extends ZodType < object > > (
206
214
request : ClientRequest ,
207
215
schema : T ,
216
+ tabKey ?: keyof typeof errors ,
208
217
) => {
209
218
if ( ! mcpClient ) {
210
219
throw new Error ( "MCP client not connected" ) ;
@@ -213,9 +222,19 @@ const App = () => {
213
222
try {
214
223
const response = await mcpClient . request ( request , schema ) ;
215
224
pushHistory ( request , response ) ;
225
+
226
+ if ( tabKey !== undefined ) {
227
+ clearError ( tabKey ) ;
228
+ }
229
+
216
230
return response ;
217
231
} catch ( e : unknown ) {
218
- setError ( ( e as Error ) . message ) ;
232
+ if ( tabKey === undefined ) {
233
+ toast . error ( ( e as Error ) . message ) ;
234
+ } else {
235
+ setErrors ( ( prev ) => ( { ...prev , [ tabKey ] : ( e as Error ) . message } ) ) ;
236
+ }
237
+
219
238
throw e ;
220
239
}
221
240
} ;
@@ -229,7 +248,7 @@ const App = () => {
229
248
await mcpClient . notification ( notification ) ;
230
249
pushHistory ( notification ) ;
231
250
} catch ( e : unknown ) {
232
- setError ( ( e as Error ) . message ) ;
251
+ toast . error ( ( e as Error ) . message ) ;
233
252
throw e ;
234
253
}
235
254
} ;
@@ -241,6 +260,7 @@ const App = () => {
241
260
params : nextResourceCursor ? { cursor : nextResourceCursor } : { } ,
242
261
} ,
243
262
ListResourcesResultSchema ,
263
+ "resources" ,
244
264
) ;
245
265
setResources ( resources . concat ( response . resources ?? [ ] ) ) ;
246
266
setNextResourceCursor ( response . nextCursor ) ;
@@ -255,6 +275,7 @@ const App = () => {
255
275
: { } ,
256
276
} ,
257
277
ListResourceTemplatesResultSchema ,
278
+ "resources" ,
258
279
) ;
259
280
setResourceTemplates (
260
281
resourceTemplates . concat ( response . resourceTemplates ?? [ ] ) ,
@@ -269,6 +290,7 @@ const App = () => {
269
290
params : { uri } ,
270
291
} ,
271
292
ReadResourceResultSchema ,
293
+ "resources" ,
272
294
) ;
273
295
setResourceContent ( JSON . stringify ( response , null , 2 ) ) ;
274
296
} ;
@@ -280,6 +302,7 @@ const App = () => {
280
302
params : nextPromptCursor ? { cursor : nextPromptCursor } : { } ,
281
303
} ,
282
304
ListPromptsResultSchema ,
305
+ "prompts" ,
283
306
) ;
284
307
setPrompts ( response . prompts ) ;
285
308
setNextPromptCursor ( response . nextCursor ) ;
@@ -292,6 +315,7 @@ const App = () => {
292
315
params : { name, arguments : args } ,
293
316
} ,
294
317
GetPromptResultSchema ,
318
+ "prompts" ,
295
319
) ;
296
320
setPromptContent ( JSON . stringify ( response , null , 2 ) ) ;
297
321
} ;
@@ -303,6 +327,7 @@ const App = () => {
303
327
params : nextToolCursor ? { cursor : nextToolCursor } : { } ,
304
328
} ,
305
329
ListToolsResultSchema ,
330
+ "tools" ,
306
331
) ;
307
332
setTools ( response . tools ) ;
308
333
setNextToolCursor ( response . nextCursor ) ;
@@ -321,6 +346,7 @@ const App = () => {
321
346
} ,
322
347
} ,
323
348
CompatibilityCallToolResultSchema ,
349
+ "tools" ,
324
350
) ;
325
351
setToolResult ( response ) ;
326
352
} ;
@@ -445,39 +471,66 @@ const App = () => {
445
471
< ResourcesTab
446
472
resources = { resources }
447
473
resourceTemplates = { resourceTemplates }
448
- listResources = { listResources }
449
- listResourceTemplates = { listResourceTemplates }
450
- readResource = { readResource }
474
+ listResources = { ( ) => {
475
+ clearError ( "resources" ) ;
476
+ listResources ( ) ;
477
+ } }
478
+ listResourceTemplates = { ( ) => {
479
+ clearError ( "resources" ) ;
480
+ listResourceTemplates ( ) ;
481
+ } }
482
+ readResource = { ( uri ) => {
483
+ clearError ( "resources" ) ;
484
+ readResource ( uri ) ;
485
+ } }
451
486
selectedResource = { selectedResource }
452
- setSelectedResource = { setSelectedResource }
487
+ setSelectedResource = { ( resource ) => {
488
+ clearError ( "resources" ) ;
489
+ setSelectedResource ( resource ) ;
490
+ } }
453
491
resourceContent = { resourceContent }
454
492
nextCursor = { nextResourceCursor }
455
493
nextTemplateCursor = { nextResourceTemplateCursor }
456
- error = { error }
494
+ error = { errors . resources }
457
495
/>
458
496
< PromptsTab
459
497
prompts = { prompts }
460
- listPrompts = { listPrompts }
461
- getPrompt = { getPrompt }
498
+ listPrompts = { ( ) => {
499
+ clearError ( "prompts" ) ;
500
+ listPrompts ( ) ;
501
+ } }
502
+ getPrompt = { ( name , args ) => {
503
+ clearError ( "prompts" ) ;
504
+ getPrompt ( name , args ) ;
505
+ } }
462
506
selectedPrompt = { selectedPrompt }
463
- setSelectedPrompt = { setSelectedPrompt }
507
+ setSelectedPrompt = { ( prompt ) => {
508
+ clearError ( "prompts" ) ;
509
+ setSelectedPrompt ( prompt ) ;
510
+ } }
464
511
promptContent = { promptContent }
465
512
nextCursor = { nextPromptCursor }
466
- error = { error }
513
+ error = { errors . prompts }
467
514
/>
468
- < RequestsTab />
469
515
< ToolsTab
470
516
tools = { tools }
471
- listTools = { listTools }
472
- callTool = { callTool }
517
+ listTools = { ( ) => {
518
+ clearError ( "tools" ) ;
519
+ listTools ( ) ;
520
+ } }
521
+ callTool = { ( name , params ) => {
522
+ clearError ( "tools" ) ;
523
+ callTool ( name , params ) ;
524
+ } }
473
525
selectedTool = { selectedTool }
474
526
setSelectedTool = { ( tool ) => {
527
+ clearError ( "tools" ) ;
475
528
setSelectedTool ( tool ) ;
476
529
setToolResult ( null ) ;
477
530
} }
478
531
toolResult = { toolResult }
479
532
nextCursor = { nextToolCursor }
480
- error = { error }
533
+ error = { errors . tools }
481
534
/>
482
535
< ConsoleTab />
483
536
< PingTab
0 commit comments