@@ -13,11 +13,20 @@ import {
13
13
ListToolsResult ,
14
14
Tool ,
15
15
} from "@modelcontextprotocol/sdk/types.js" ;
16
- import { Loader2 , Send , ChevronDown , ChevronUp } from "lucide-react" ;
16
+ import {
17
+ Loader2 ,
18
+ Send ,
19
+ ChevronDown ,
20
+ ChevronUp ,
21
+ Copy ,
22
+ CheckCheck ,
23
+ } from "lucide-react" ;
17
24
import { useEffect , useState } from "react" ;
18
25
import ListPane from "./ListPane" ;
19
26
import JsonView from "./JsonView" ;
20
27
import ToolResults from "./ToolResults" ;
28
+ import { useToast } from "@/lib/hooks/useToast" ;
29
+ import useCopy from "@/lib/hooks/useCopy" ;
21
30
22
31
const ToolsTab = ( {
23
32
tools,
@@ -46,6 +55,8 @@ const ToolsTab = ({
46
55
const [ params , setParams ] = useState < Record < string , unknown > > ( { } ) ;
47
56
const [ isToolRunning , setIsToolRunning ] = useState ( false ) ;
48
57
const [ isOutputSchemaExpanded , setIsOutputSchemaExpanded ] = useState ( false ) ;
58
+ const { toast } = useToast ( ) ;
59
+ const { copied, setCopied } = useCopy ( ) ;
49
60
50
61
useEffect ( ( ) => {
51
62
const params = Object . entries (
@@ -245,29 +256,54 @@ const ToolsTab = ({
245
256
</ div >
246
257
</ div >
247
258
) }
248
- < Button
249
- onClick = { async ( ) => {
250
- try {
251
- setIsToolRunning ( true ) ;
252
- await callTool ( selectedTool . name , params ) ;
253
- } finally {
254
- setIsToolRunning ( false ) ;
255
- }
256
- } }
257
- disabled = { isToolRunning }
258
- >
259
- { isToolRunning ? (
260
- < >
261
- < Loader2 className = "w-4 h-4 mr-2 animate-spin" />
262
- Running...
263
- </ >
264
- ) : (
265
- < >
266
- < Send className = "w-4 h-4 mr-2" />
267
- Run Tool
268
- </ >
269
- ) }
270
- </ Button >
259
+ < div className = "flex gap-2" >
260
+ < Button
261
+ onClick = { async ( ) => {
262
+ try {
263
+ setIsToolRunning ( true ) ;
264
+ await callTool ( selectedTool . name , params ) ;
265
+ } finally {
266
+ setIsToolRunning ( false ) ;
267
+ }
268
+ } }
269
+ disabled = { isToolRunning }
270
+ >
271
+ { isToolRunning ? (
272
+ < >
273
+ < Loader2 className = "w-4 h-4 mr-2 animate-spin" />
274
+ Running...
275
+ </ >
276
+ ) : (
277
+ < >
278
+ < Send className = "w-4 h-4 mr-2" />
279
+ Run Tool
280
+ </ >
281
+ ) }
282
+ </ Button >
283
+ < Button
284
+ onClick = { async ( ) => {
285
+ try {
286
+ navigator . clipboard . writeText (
287
+ JSON . stringify ( params , null , 2 ) ,
288
+ ) ;
289
+ setCopied ( true ) ;
290
+ } catch ( error ) {
291
+ toast ( {
292
+ title : "Error" ,
293
+ description : `There was an error coping result into the clipboard: ${ error instanceof Error ? error . message : String ( error ) } ` ,
294
+ variant : "destructive" ,
295
+ } ) ;
296
+ }
297
+ } }
298
+ >
299
+ { copied ? (
300
+ < CheckCheck className = "h-4 w-4 mr-2 dark:text-green-700 text-green-600" />
301
+ ) : (
302
+ < Copy className = "h-4 w-4 mr-2" />
303
+ ) }
304
+ Copy Input
305
+ </ Button >
306
+ </ div >
271
307
< ToolResults
272
308
toolResult = { toolResult }
273
309
selectedTool = { selectedTool }
0 commit comments