@gradio/core 0.23.2 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,571 @@
1
+ <script>import { Block } from "@gradio/atoms";
2
+ import CopyButton from "./CopyButton.svelte";
3
+ export let mcp_server_active;
4
+ export let mcp_server_url;
5
+ export let mcp_server_url_streamable;
6
+ export let tools;
7
+ export let all_tools = [];
8
+ export let selected_tools = /* @__PURE__ */ new Set();
9
+ export let mcp_json_sse;
10
+ export let mcp_json_stdio;
11
+ export let file_data_present;
12
+ export let mcp_docs;
13
+ let current_transport = "streamable_http";
14
+ let include_file_upload = true;
15
+ const transports = [
16
+ ["streamable_http", "Streamable HTTP"],
17
+ ["sse", "SSE"],
18
+ ["stdio", "STDIO"]
19
+ ];
20
+ $:
21
+ display_url = current_transport === "sse" ? mcp_server_url : mcp_server_url_streamable;
22
+ function update_config_with_file_upload(base_config, include_upload) {
23
+ if (!base_config)
24
+ return null;
25
+ const config = JSON.parse(JSON.stringify(base_config));
26
+ if (include_upload && file_data_present) {
27
+ const upload_file_mcp_server = {
28
+ command: "uvx",
29
+ args: [
30
+ "--from",
31
+ "gradio[mcp]",
32
+ "gradio",
33
+ "upload-mcp",
34
+ current_transport === "sse" ? mcp_server_url : mcp_server_url_streamable,
35
+ "<UPLOAD_DIRECTORY>"
36
+ ]
37
+ };
38
+ config.mcpServers.upload_files_to_gradio = upload_file_mcp_server;
39
+ } else {
40
+ delete config.mcpServers?.upload_files_to_gradio;
41
+ }
42
+ return config;
43
+ }
44
+ $:
45
+ mcp_json_streamable_http = update_config_with_file_upload(
46
+ mcp_json_sse ? {
47
+ ...mcp_json_sse,
48
+ mcpServers: {
49
+ ...mcp_json_sse.mcpServers,
50
+ gradio: {
51
+ ...mcp_json_sse.mcpServers.gradio,
52
+ url: mcp_server_url_streamable
53
+ }
54
+ }
55
+ } : null,
56
+ include_file_upload
57
+ );
58
+ $:
59
+ mcp_json_sse_updated = update_config_with_file_upload(
60
+ mcp_json_sse,
61
+ include_file_upload
62
+ );
63
+ $:
64
+ mcp_json_stdio_updated = update_config_with_file_upload(
65
+ mcp_json_stdio,
66
+ include_file_upload
67
+ );
68
+ </script>
69
+
70
+ {#if mcp_server_active}
71
+ <div class="transport-selection">
72
+ <div class="snippets">
73
+ <span class="transport-label">Transport:</span>
74
+ {#each transports as [transport, display_name]}
75
+ <button
76
+ type="button"
77
+ class="snippet {current_transport === transport
78
+ ? 'current-lang'
79
+ : 'inactive-lang'}"
80
+ on:click={() => (current_transport = transport)}
81
+ >
82
+ {display_name}
83
+ </button>
84
+ {/each}
85
+ </div>
86
+ </div>
87
+
88
+ {#if current_transport !== "stdio"}
89
+ <Block>
90
+ <div class="mcp-url">
91
+ <label for="mcp-server-url"
92
+ ><span class="status-indicator active">●</span>MCP Server URL ({current_transport ===
93
+ "sse"
94
+ ? "SSE"
95
+ : "Streamable HTTP"})</label
96
+ >
97
+ <div class="textbox">
98
+ <input id="mcp-server-url" type="text" readonly value={display_url} />
99
+ <CopyButton code={display_url} />
100
+ </div>
101
+ </div>
102
+ </Block>
103
+ <p>&nbsp;</p>
104
+ {/if}
105
+
106
+ <div class="tool-selection">
107
+ <strong
108
+ >{all_tools.length > 0 ? all_tools.length : tools.length} Available MCP Tools</strong
109
+ >
110
+ {#if all_tools.length > 0}
111
+ <div class="tool-selection-controls">
112
+ <button
113
+ class="select-all-btn"
114
+ on:click={() => {
115
+ selected_tools = new Set(all_tools.map((t) => t.name));
116
+ }}
117
+ >
118
+ Select All
119
+ </button>
120
+ <button
121
+ class="select-none-btn"
122
+ on:click={() => {
123
+ selected_tools = new Set();
124
+ }}
125
+ >
126
+ Select None
127
+ </button>
128
+ </div>
129
+ {/if}
130
+ </div>
131
+ <div class="mcp-tools">
132
+ {#each all_tools.length > 0 ? all_tools : tools as tool}
133
+ <div class="tool-item">
134
+ <div class="tool-header-wrapper">
135
+ {#if all_tools.length > 0}
136
+ <input
137
+ type="checkbox"
138
+ class="tool-checkbox"
139
+ checked={selected_tools.has(tool.name) ||
140
+ current_transport !== "streamable_http"}
141
+ disabled={current_transport !== "streamable_http"}
142
+ style={current_transport !== "streamable_http"
143
+ ? "opacity: 0.5; cursor: not-allowed;"
144
+ : ""}
145
+ on:change={(e) => {
146
+ if (e.currentTarget.checked) {
147
+ selected_tools.add(tool.name);
148
+ } else {
149
+ selected_tools.delete(tool.name);
150
+ }
151
+ selected_tools = selected_tools;
152
+ }}
153
+ />
154
+ {/if}
155
+ <button
156
+ class="tool-header"
157
+ on:click={() => (tool.expanded = !tool.expanded)}
158
+ >
159
+ <span
160
+ ><span class="tool-name">{tool.name}</span> &nbsp;
161
+ <span class="tool-description"
162
+ >{tool.description
163
+ ? tool.description
164
+ : "⚠︎ No description provided in function docstring"}</span
165
+ ></span
166
+ >
167
+ <span class="tool-arrow">{tool.expanded ? "▼" : "▶"}</span>
168
+ </button>
169
+ </div>
170
+ {#if tool.expanded}
171
+ <div class="tool-content">
172
+ {#if Object.keys(tool.parameters).length > 0}
173
+ <div class="tool-parameters">
174
+ {#each Object.entries(tool.parameters) as [name, param]}
175
+ <div class="parameter">
176
+ <code>{name}</code>
177
+ <span class="parameter-type">
178
+ ({param.type}{param.default !== undefined
179
+ ? `, default: ${JSON.stringify(param.default)}`
180
+ : ""})
181
+ </span>
182
+ <p class="parameter-description">
183
+ {param.description
184
+ ? param.description
185
+ : "⚠︎ No description for this parameter in function docstring"}
186
+ </p>
187
+ </div>
188
+ {/each}
189
+ </div>
190
+ {:else}
191
+ <p>Takes no input parameters</p>
192
+ {/if}
193
+ </div>
194
+ {/if}
195
+ </div>
196
+ {/each}
197
+ </div>
198
+ <p>&nbsp;</p>
199
+
200
+ {#if current_transport === "streamable_http"}
201
+ <strong>Streamable HTTP Transport</strong>: To add this MCP to clients that
202
+ support Streamable HTTP, simply add the following configuration to your MCP
203
+ config.
204
+ <p>&nbsp;</p>
205
+ <Block>
206
+ <code>
207
+ <div class="copy">
208
+ <CopyButton
209
+ code={JSON.stringify(mcp_json_streamable_http, null, 2)}
210
+ />
211
+ </div>
212
+ <div>
213
+ <pre>{JSON.stringify(mcp_json_streamable_http, null, 2)}</pre>
214
+ </div>
215
+ </code>
216
+ </Block>
217
+ {:else if current_transport === "sse"}
218
+ <strong>SSE Transport</strong>: The SSE transport has been deprecated by the
219
+ MCP spec. We recommend using the Streamable HTTP transport instead. But to
220
+ add this MCP to clients that only support server-sent events (SSE), simply
221
+ add the following configuration to your MCP config.
222
+ <p>&nbsp;</p>
223
+ <Block>
224
+ <code>
225
+ <div class="copy">
226
+ <CopyButton code={JSON.stringify(mcp_json_sse_updated, null, 2)} />
227
+ </div>
228
+ <div>
229
+ <pre>{JSON.stringify(mcp_json_sse_updated, null, 2)}</pre>
230
+ </div>
231
+ </code>
232
+ </Block>
233
+ {:else if current_transport === "stdio"}
234
+ <strong>STDIO Transport</strong>: For clients that only support stdio (e.g.
235
+ Claude Desktop), first
236
+ <a href="https://nodejs.org/en/download/" target="_blank">install Node.js</a
237
+ >. Then, you can use the following command:
238
+ <p>&nbsp;</p>
239
+ <Block>
240
+ <code>
241
+ <div class="copy">
242
+ <CopyButton code={JSON.stringify(mcp_json_stdio_updated, null, 2)} />
243
+ </div>
244
+ <div>
245
+ <pre>{JSON.stringify(mcp_json_stdio_updated, null, 2)}</pre>
246
+ </div>
247
+ </code>
248
+ </Block>
249
+ {/if}
250
+ {#if file_data_present}
251
+ <div class="file-upload-section">
252
+ <label class="checkbox-label">
253
+ <input
254
+ type="checkbox"
255
+ bind:checked={include_file_upload}
256
+ class="checkbox"
257
+ />
258
+ Include Gradio file upload tool
259
+ </label>
260
+ <p class="file-upload-explanation">
261
+ The <code>upload_files_to_gradio</code> tool uploads files from your
262
+ local <code>UPLOAD_DIRECTORY</code> (or any of its subdirectories) to
263
+ the Gradio app. This is needed because MCP servers require files to be
264
+ provided as URLs. You can omit this tool if you prefer to upload files
265
+ manually. This tool requires
266
+ <a
267
+ href="https://docs.astral.sh/uv/getting-started/installation/"
268
+ target="_blank">uv</a
269
+ > to be installed.
270
+ </p>
271
+ </div>
272
+ {/if}
273
+
274
+ <p>&nbsp;</p>
275
+ <p>
276
+ <a href={mcp_docs} target="_blank">
277
+ Read more about MCP in the Gradio docs
278
+ </a>
279
+ </p>
280
+ {:else}
281
+ This Gradio app can also serve as an MCP server, with an MCP tool
282
+ corresponding to each API endpoint. To enable this, launch this Gradio app
283
+ with <code>.launch(mcp_server=True)</code> or set the
284
+ <code>GRADIO_MCP_SERVER</code>
285
+ env variable to
286
+ <code>"True"</code>.
287
+ {/if}
288
+
289
+ <style>
290
+ .transport-selection {
291
+ margin-bottom: var(--size-4);
292
+ }
293
+
294
+ .snippets {
295
+ display: flex;
296
+ align-items: center;
297
+ margin-bottom: var(--size-4);
298
+ }
299
+
300
+ .snippets > * + * {
301
+ margin-left: var(--size-2);
302
+ }
303
+
304
+ .transport-label {
305
+ font-weight: 600;
306
+ color: var(--body-text-color);
307
+ margin-right: var(--size-2);
308
+ }
309
+
310
+ .file-upload-section {
311
+ margin-top: var(--size-4);
312
+ padding: var(--size-3);
313
+ border: 1px solid var(--border-color-primary);
314
+ border-radius: var(--radius-md);
315
+ background: var(--background-fill-secondary);
316
+ }
317
+
318
+ .checkbox-label {
319
+ display: flex;
320
+ align-items: center;
321
+ font-weight: 600;
322
+ color: var(--body-text-color);
323
+ cursor: pointer;
324
+ margin-bottom: var(--size-2);
325
+ }
326
+
327
+ .checkbox {
328
+ margin-right: var(--size-2);
329
+ width: var(--size-4);
330
+ height: var(--size-4);
331
+ cursor: pointer;
332
+ accent-color: var(--color-accent);
333
+ }
334
+
335
+ .checkbox:checked {
336
+ background-color: var(--color-accent);
337
+ border-color: var(--color-accent);
338
+ }
339
+
340
+ .file-upload-explanation {
341
+ margin: 0;
342
+ color: var(--body-text-color);
343
+ }
344
+
345
+ .snippet {
346
+ display: flex;
347
+ align-items: center;
348
+ border: 1px solid var(--border-color-primary);
349
+ border-radius: var(--radius-md);
350
+ padding: var(--size-1) var(--size-1-5);
351
+ color: var(--body-text-color-subdued);
352
+ color: var(--body-text-color);
353
+ line-height: 1;
354
+ user-select: none;
355
+ }
356
+
357
+ .current-lang {
358
+ border: 1px solid var(--body-text-color-subdued);
359
+ color: var(--body-text-color);
360
+ }
361
+
362
+ .inactive-lang {
363
+ cursor: pointer;
364
+ color: var(--body-text-color-subdued);
365
+ }
366
+
367
+ .inactive-lang:hover,
368
+ .inactive-lang:focus {
369
+ box-shadow: var(--shadow-drop);
370
+ color: var(--body-text-color);
371
+ }
372
+
373
+ code pre {
374
+ overflow-x: auto;
375
+ color: var(--body-text-color);
376
+ font-family: var(--font-mono);
377
+ tab-size: 2;
378
+ }
379
+
380
+ .copy {
381
+ position: absolute;
382
+ top: 0;
383
+ right: 0;
384
+ margin-top: 5px;
385
+ margin-right: 5px;
386
+ z-index: 10;
387
+ }
388
+
389
+ .mcp-url {
390
+ padding: var(--size-2);
391
+ position: relative;
392
+ }
393
+
394
+ .mcp-url label {
395
+ display: block;
396
+ margin-bottom: var(--size-2);
397
+ font-weight: 600;
398
+ color: var(--body-text-color);
399
+ }
400
+
401
+ .mcp-url .textbox {
402
+ display: flex;
403
+ align-items: center;
404
+ gap: var(--size-2);
405
+ border: 1px solid var(--border-color-primary);
406
+ border-radius: var(--radius-sm);
407
+ padding: var(--size-2);
408
+ background: var(--background-fill-primary);
409
+ }
410
+
411
+ .mcp-url input {
412
+ flex: 1;
413
+ border: none;
414
+ background: none;
415
+ color: var(--body-text-color);
416
+ font-family: var(--font-mono);
417
+ font-size: var(--text-md);
418
+ width: 100%;
419
+ }
420
+
421
+ .mcp-url input:focus {
422
+ outline: none;
423
+ }
424
+
425
+ .status-indicator {
426
+ display: inline-block;
427
+ margin-right: var(--size-1-5);
428
+ position: relative;
429
+ top: -1px;
430
+ font-size: 0.8em;
431
+ }
432
+
433
+ .status-indicator.active {
434
+ color: #4caf50;
435
+ animation: pulse 1s infinite;
436
+ }
437
+
438
+ @keyframes pulse {
439
+ 0% {
440
+ opacity: 1;
441
+ }
442
+ 50% {
443
+ opacity: 0.6;
444
+ }
445
+ 100% {
446
+ opacity: 1;
447
+ }
448
+ }
449
+
450
+ .mcp-tools {
451
+ margin-top: var(--size-4);
452
+ border: 1px solid var(--border-color-primary);
453
+ border-radius: var(--radius-md);
454
+ overflow: hidden;
455
+ }
456
+
457
+ .tool-selection {
458
+ display: flex;
459
+ justify-content: space-between;
460
+ align-items: center;
461
+ margin-bottom: var(--size-2);
462
+ }
463
+
464
+ .tool-selection-controls {
465
+ display: flex;
466
+ gap: var(--size-2);
467
+ }
468
+
469
+ .select-all-btn,
470
+ .select-none-btn {
471
+ padding: var(--size-1) var(--size-2);
472
+ border: 1px solid var(--border-color-primary);
473
+ border-radius: var(--radius-sm);
474
+ background: var(--background-fill-primary);
475
+ color: var(--body-text-color);
476
+ cursor: pointer;
477
+ font-size: var(--text-sm);
478
+ }
479
+
480
+ .select-all-btn:hover,
481
+ .select-none-btn:hover {
482
+ background: var(--background-fill-secondary);
483
+ }
484
+
485
+ .tool-item {
486
+ border-bottom: 1px solid var(--border-color-primary);
487
+ }
488
+
489
+ .tool-item:last-child {
490
+ border-bottom: none;
491
+ }
492
+
493
+ .tool-header-wrapper {
494
+ display: flex;
495
+ align-items: center;
496
+ }
497
+
498
+ .tool-checkbox {
499
+ margin-left: var(--size-3);
500
+ margin-right: var(--size-2);
501
+ width: var(--size-4);
502
+ height: var(--size-4);
503
+ cursor: pointer;
504
+ accent-color: var(--color-accent);
505
+ }
506
+
507
+ .tool-checkbox:checked {
508
+ background-color: var(--color-accent);
509
+ border-color: var(--color-accent);
510
+ }
511
+
512
+ .tool-header {
513
+ flex: 1;
514
+ display: flex;
515
+ justify-content: space-between;
516
+ align-items: center;
517
+ padding: var(--size-3);
518
+ background: var(--background-fill-primary);
519
+ border: none;
520
+ cursor: pointer;
521
+ text-align: left;
522
+ }
523
+
524
+ .tool-header:hover {
525
+ background: var(--background-fill-secondary);
526
+ }
527
+
528
+ .tool-name {
529
+ font-family: var(--font-mono);
530
+ font-weight: 600;
531
+ }
532
+
533
+ .tool-arrow {
534
+ color: var(--body-text-color-subdued);
535
+ }
536
+
537
+ .tool-content {
538
+ padding: var(--size-3);
539
+ background: var(--background-fill-secondary);
540
+ }
541
+
542
+ .tool-description {
543
+ margin-bottom: var(--size-3);
544
+ color: var(--body-text-color);
545
+ }
546
+ .parameter {
547
+ margin-bottom: var(--size-2);
548
+ padding: var(--size-2);
549
+ background: var(--background-fill-primary);
550
+ border-radius: var(--radius-sm);
551
+ }
552
+
553
+ .parameter code {
554
+ font-weight: 600;
555
+ color: var(--color-accent);
556
+ }
557
+
558
+ .parameter-type {
559
+ color: var(--body-text-color-subdued);
560
+ margin-left: var(--size-1);
561
+ }
562
+
563
+ .parameter-description {
564
+ margin-top: var(--size-1);
565
+ color: var(--body-text-color);
566
+ }
567
+
568
+ a {
569
+ text-decoration: underline;
570
+ }
571
+ </style>
@@ -0,0 +1,47 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ mcp_server_active: boolean;
5
+ mcp_server_url: string;
6
+ mcp_server_url_streamable: string;
7
+ tools: {
8
+ name: string;
9
+ description: string;
10
+ parameters: Record<string, {
11
+ title?: string;
12
+ type: string;
13
+ description: string;
14
+ format?: string;
15
+ default?: any;
16
+ }>;
17
+ expanded?: boolean;
18
+ }[];
19
+ all_tools?: {
20
+ name: string;
21
+ description: string;
22
+ parameters: Record<string, {
23
+ title?: string;
24
+ type: string;
25
+ description: string;
26
+ format?: string;
27
+ default?: any;
28
+ }>;
29
+ expanded?: boolean;
30
+ }[] | undefined;
31
+ selected_tools?: Set<string> | undefined;
32
+ mcp_json_sse: any;
33
+ mcp_json_stdio: any;
34
+ file_data_present: boolean;
35
+ mcp_docs: string;
36
+ };
37
+ events: {
38
+ [evt: string]: CustomEvent<any>;
39
+ };
40
+ slots: {};
41
+ };
42
+ export type McpSnippetProps = typeof __propDef.props;
43
+ export type McpSnippetEvents = typeof __propDef.events;
44
+ export type McpSnippetSlots = typeof __propDef.slots;
45
+ export default class McpSnippet extends SvelteComponent<McpSnippetProps, McpSnippetEvents, McpSnippetSlots> {
46
+ }
47
+ export {};