1
- import { Alert , AlertDescription } from "@/components/ui/alert" ;
1
+ import { Alert , AlertDescription , AlertTitle } from "@/components/ui/alert" ;
2
2
import { Button } from "@/components/ui/button" ;
3
3
import { Checkbox } from "@/components/ui/checkbox" ;
4
4
import { Input } from "@/components/ui/input" ;
5
5
import { Label } from "@/components/ui/label" ;
6
6
import { TabsContent } from "@/components/ui/tabs" ;
7
7
import { Textarea } from "@/components/ui/textarea" ;
8
- import DynamicJsonForm from "./DynamicJsonForm" ;
8
+ import DynamicJsonForm , { DynamicJsonFormRef } from "./DynamicJsonForm" ;
9
9
import type { JsonValue , JsonSchemaType } from "@/utils/jsonUtils" ;
10
10
import { generateDefaultValue } from "@/utils/schemaUtils" ;
11
11
import {
12
12
CompatibilityCallToolResult ,
13
13
ListToolsResult ,
14
14
Tool ,
15
15
} from "@modelcontextprotocol/sdk/types.js" ;
16
- import { Loader2 , Send , ChevronDown , ChevronUp } from "lucide-react" ;
17
- import { useEffect , useState } from "react" ;
16
+ import { Loader2 , Send , ChevronDown , ChevronUp , AlertCircle } from "lucide-react" ;
17
+ import { useEffect , useState , useRef } from "react" ;
18
18
import ListPane from "./ListPane" ;
19
19
import JsonView from "./JsonView" ;
20
20
import ToolResults from "./ToolResults" ;
@@ -28,6 +28,7 @@ const ToolsTab = ({
28
28
setSelectedTool,
29
29
toolResult,
30
30
nextCursor,
31
+ error,
31
32
} : {
32
33
tools : Tool [ ] ;
33
34
listTools : ( ) => void ;
@@ -42,6 +43,7 @@ const ToolsTab = ({
42
43
const [ params , setParams ] = useState < Record < string , unknown > > ( { } ) ;
43
44
const [ isToolRunning , setIsToolRunning ] = useState ( false ) ;
44
45
const [ isOutputSchemaExpanded , setIsOutputSchemaExpanded ] = useState ( false ) ;
46
+ const formRefs = useRef < Record < string , DynamicJsonFormRef | null > > ( { } ) ;
45
47
46
48
useEffect ( ( ) => {
47
49
const params = Object . entries (
@@ -84,7 +86,13 @@ const ToolsTab = ({
84
86
</ h3 >
85
87
</ div >
86
88
< div className = "p-4" >
87
- { selectedTool ? (
89
+ { error ? (
90
+ < Alert variant = "destructive" >
91
+ < AlertCircle className = "h-4 w-4" />
92
+ < AlertTitle > Error</ AlertTitle >
93
+ < AlertDescription > { error } </ AlertDescription >
94
+ </ Alert >
95
+ ) : selectedTool ? (
88
96
< div className = "space-y-4" >
89
97
< p className = "text-sm text-gray-600 dark:text-gray-400" >
90
98
{ selectedTool . description }
@@ -137,6 +145,7 @@ const ToolsTab = ({
137
145
) : prop . type === "object" || prop . type === "array" ? (
138
146
< div className = "mt-1" >
139
147
< DynamicJsonForm
148
+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
140
149
schema = { {
141
150
type : prop . type ,
142
151
properties : prop . properties ,
@@ -174,6 +183,7 @@ const ToolsTab = ({
174
183
) : (
175
184
< div className = "mt-1" >
176
185
< DynamicJsonForm
186
+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
177
187
schema = { {
178
188
type : prop . type ,
179
189
properties : prop . properties ,
@@ -232,6 +242,12 @@ const ToolsTab = ({
232
242
) }
233
243
< Button
234
244
onClick = { async ( ) => {
245
+ // Validate JSON inputs before calling tool
246
+ const hasValidationErrors = Object . values ( formRefs . current ) . some (
247
+ ( ref ) => ref && ! ref . validateJson ( ) . isValid
248
+ ) ;
249
+ if ( hasValidationErrors ) return ;
250
+
235
251
try {
236
252
setIsToolRunning ( true ) ;
237
253
await callTool ( selectedTool . name , params ) ;
0 commit comments