@assistant-ui/mcp-docs-server 0.1.7 → 0.1.8
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.
- package/.docs/organized/code-examples/with-ai-sdk-v5.md +3 -1
- package/.docs/organized/code-examples/with-cloud.md +3 -1
- package/.docs/organized/code-examples/with-external-store.md +3 -1
- package/.docs/organized/code-examples/with-ffmpeg.md +3 -1
- package/.docs/organized/code-examples/with-langgraph.md +66 -38
- package/.docs/organized/code-examples/with-parent-id-grouping.md +3 -1
- package/.docs/organized/code-examples/with-react-hook-form.md +3 -1
- package/.docs/raw/docs/api-reference/integrations/react-data-stream.mdx +194 -0
- package/.docs/raw/docs/api-reference/overview.mdx +6 -0
- package/.docs/raw/docs/api-reference/primitives/Composer.mdx +31 -0
- package/.docs/raw/docs/api-reference/primitives/Message.mdx +108 -3
- package/.docs/raw/docs/api-reference/primitives/Thread.mdx +59 -0
- package/.docs/raw/docs/api-reference/primitives/ThreadList.mdx +128 -0
- package/.docs/raw/docs/api-reference/primitives/ThreadListItem.mdx +160 -0
- package/.docs/raw/docs/api-reference/runtimes/AssistantRuntime.mdx +0 -11
- package/.docs/raw/docs/api-reference/runtimes/ComposerRuntime.mdx +3 -3
- package/.docs/raw/docs/copilots/assistant-frame.mdx +397 -0
- package/.docs/raw/docs/getting-started.mdx +20 -19
- package/.docs/raw/docs/guides/Attachments.mdx +6 -13
- package/.docs/raw/docs/guides/Tools.mdx +56 -13
- package/.docs/raw/docs/guides/context-api.mdx +574 -0
- package/.docs/raw/docs/migrations/v0-12.mdx +125 -0
- package/.docs/raw/docs/runtimes/custom/local.mdx +16 -3
- package/.docs/raw/docs/runtimes/data-stream.mdx +287 -0
- package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +5 -0
- package/.docs/raw/docs/ui/ThreadList.mdx +54 -16
- package/dist/{chunk-L4K23SWI.js → chunk-NVNFQ5ZO.js} +4 -1
- package/dist/index.js +1 -1
- package/dist/prepare-docs/prepare.js +1 -1
- package/dist/stdio.js +1 -1
- package/package.json +2 -2
- package/.docs/raw/docs/concepts/architecture.mdx +0 -19
- package/.docs/raw/docs/concepts/runtime-layer.mdx +0 -163
- package/.docs/raw/docs/concepts/why.mdx +0 -9
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Assistant Frame API
|
|
3
|
+
description: Share model context across iframe boundaries
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The Assistant Frame API enables iframes to provide model context (tools and instructions) to a parent window's assistant. This is particularly useful for embedded applications, plugins, or sandboxed components that need to contribute capabilities to the main assistant.
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The Assistant Frame system consists of two main components:
|
|
11
|
+
|
|
12
|
+
- **AssistantFrameProvider**: Runs inside the iframe and provides model context
|
|
13
|
+
- **AssistantFrameHost**: Runs in the parent window and consumes context from iframes
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
### In the iframe (Provider)
|
|
18
|
+
|
|
19
|
+
The iframe acts as a provider of model context using `AssistantFrameProvider`:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// iframe.tsx
|
|
23
|
+
import { AssistantFrameProvider } from "@assistant-ui/react";
|
|
24
|
+
import { ModelContextRegistry } from "@assistant-ui/react";
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
|
|
27
|
+
// Create a registry to manage your model context
|
|
28
|
+
const registry = new ModelContextRegistry();
|
|
29
|
+
|
|
30
|
+
// Expose the registry to the parent window
|
|
31
|
+
AssistantFrameProvider.addModelContextProvider(registry);
|
|
32
|
+
|
|
33
|
+
// Add tools that will be available to the parent assistant
|
|
34
|
+
registry.addTool({
|
|
35
|
+
toolName: "searchProducts",
|
|
36
|
+
description: "Search for products in the catalog",
|
|
37
|
+
parameters: z.object({
|
|
38
|
+
query: z.string(),
|
|
39
|
+
category: z.string().optional(),
|
|
40
|
+
}),
|
|
41
|
+
execute: async ({ query, category }) => {
|
|
42
|
+
// Tool implementation runs in the iframe
|
|
43
|
+
const results = await searchAPI(query, category);
|
|
44
|
+
return { products: results };
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Add system instructions
|
|
49
|
+
const instructionHandle = registry.addInstruction(
|
|
50
|
+
"You are a helpful assistant.",
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// update the instruction
|
|
54
|
+
instructionHandle.update("You have access to a product catalog search tool.");
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### In the parent window (Host)
|
|
58
|
+
|
|
59
|
+
The parent window consumes the iframe's context using `AssistantFrameHost`:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// parent.tsx
|
|
63
|
+
import { useAssistantFrameHost } from "@assistant-ui/react";
|
|
64
|
+
import { useRef } from "react";
|
|
65
|
+
|
|
66
|
+
function ParentComponent() {
|
|
67
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
68
|
+
|
|
69
|
+
// Connect to the iframe's model context
|
|
70
|
+
useAssistantFrameHost({
|
|
71
|
+
iframeRef,
|
|
72
|
+
targetOrigin: "https://trusted-iframe-domain.com", // optional for increased security
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div>
|
|
77
|
+
<Thread /> {/* Your assistant UI */}
|
|
78
|
+
<iframe
|
|
79
|
+
ref={iframeRef}
|
|
80
|
+
src="https://trusted-iframe-domain.com/embed"
|
|
81
|
+
title="Embedded App"
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Advanced Usage
|
|
89
|
+
|
|
90
|
+
### ModelContextRegistry
|
|
91
|
+
|
|
92
|
+
The `ModelContextRegistry` provides a flexible way to manage model context dynamically:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const registry = new ModelContextRegistry();
|
|
96
|
+
|
|
97
|
+
// Add a tool with handle for updates
|
|
98
|
+
const toolHandle = registry.addTool({
|
|
99
|
+
toolName: "convertCurrency",
|
|
100
|
+
description: "Convert between currencies",
|
|
101
|
+
parameters: z.object({
|
|
102
|
+
amount: z.number(),
|
|
103
|
+
from: z.string(),
|
|
104
|
+
to: z.string()
|
|
105
|
+
}),
|
|
106
|
+
execute: async ({ amount, from, to }) => {
|
|
107
|
+
const rate = await fetchExchangeRate(from, to);
|
|
108
|
+
return { result: amount * rate, currency: to };
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Update the tool later
|
|
113
|
+
toolHandle.update({
|
|
114
|
+
toolName: "convertCurrency",
|
|
115
|
+
description: "Convert between currencies with live rates", // Updated description
|
|
116
|
+
parameters: z.object({
|
|
117
|
+
amount: z.number(),
|
|
118
|
+
from: z.string(),
|
|
119
|
+
to: z.string(),
|
|
120
|
+
includesFees: z.boolean().optional()
|
|
121
|
+
}),
|
|
122
|
+
execute: async ({ amount, from, to, includesFees }) => {
|
|
123
|
+
const rate = await fetchExchangeRate(from, to);
|
|
124
|
+
const fee = includesFees ? 0.02 : 0; // 2% fee
|
|
125
|
+
return {
|
|
126
|
+
result: amount * rate * (1 - fee),
|
|
127
|
+
currency: to,
|
|
128
|
+
fee: includesFees ? amount * rate * fee : 0
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Remove the tool when no longer needed
|
|
134
|
+
toolHandle.remove();
|
|
135
|
+
|
|
136
|
+
// Add multiple instructions
|
|
137
|
+
const instruction1 = registry.addInstruction("Be helpful and concise.");
|
|
138
|
+
const instruction2 = registry.addInstruction("Use metric units.");
|
|
139
|
+
|
|
140
|
+
// Remove instructions
|
|
141
|
+
instruction1.remove();
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Multiple Providers
|
|
145
|
+
|
|
146
|
+
You can register multiple model context providers in the same iframe:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
const catalogRegistry = new ModelContextRegistry();
|
|
150
|
+
const analyticsRegistry = new ModelContextRegistry();
|
|
151
|
+
|
|
152
|
+
// Add different tools to each registry
|
|
153
|
+
catalogRegistry.addTool({
|
|
154
|
+
/* ... */
|
|
155
|
+
});
|
|
156
|
+
analyticsRegistry.addTool({
|
|
157
|
+
/* ... */
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Register both providers
|
|
161
|
+
const unsubscribe1 =
|
|
162
|
+
AssistantFrameProvider.addModelContextProvider(catalogRegistry);
|
|
163
|
+
const unsubscribe2 =
|
|
164
|
+
AssistantFrameProvider.addModelContextProvider(analyticsRegistry);
|
|
165
|
+
|
|
166
|
+
// Later, unsubscribe if needed
|
|
167
|
+
unsubscribe1();
|
|
168
|
+
unsubscribe2();
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Security Considerations
|
|
172
|
+
|
|
173
|
+
#### Origin Validation
|
|
174
|
+
|
|
175
|
+
Both the provider and host can specify allowed origins for security:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
// In iframe - only accept messages from specific parent
|
|
179
|
+
AssistantFrameProvider.addModelContextProvider(
|
|
180
|
+
registry,
|
|
181
|
+
"https://parent-app.com",
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// In parent - only accept messages from specific iframe
|
|
185
|
+
useAssistantFrameHost({
|
|
186
|
+
iframeRef,
|
|
187
|
+
targetOrigin: "https://iframe-app.com",
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Tool Execution
|
|
192
|
+
|
|
193
|
+
Tools are executed in the iframe's context, keeping sensitive operations sandboxed:
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
registry.addTool({
|
|
197
|
+
toolName: "accessDatabase",
|
|
198
|
+
description: "Query the database",
|
|
199
|
+
parameters: z.object({ query: z.string() }),
|
|
200
|
+
execute: async ({ query }) => {
|
|
201
|
+
// This runs in the iframe with iframe's permissions
|
|
202
|
+
// Parent cannot directly access the database
|
|
203
|
+
const results = await db.query(query);
|
|
204
|
+
return results;
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## API Reference
|
|
210
|
+
|
|
211
|
+
### AssistantFrameProvider
|
|
212
|
+
|
|
213
|
+
Static class that manages model context providers in an iframe.
|
|
214
|
+
|
|
215
|
+
#### Methods
|
|
216
|
+
|
|
217
|
+
##### `addModelContextProvider(provider, targetOrigin?)`
|
|
218
|
+
|
|
219
|
+
Registers a model context provider to share with parent windows.
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
const unsubscribe = AssistantFrameProvider.addModelContextProvider(
|
|
223
|
+
registry,
|
|
224
|
+
"https://parent-domain.com", // Optional origin restriction
|
|
225
|
+
);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
##### `dispose()`
|
|
229
|
+
|
|
230
|
+
Cleans up all resources and removes all providers.
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
AssistantFrameProvider.dispose();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### AssistantFrameHost
|
|
237
|
+
|
|
238
|
+
Class that connects to an iframe's model context providers.
|
|
239
|
+
|
|
240
|
+
#### Constructor
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
const host = new AssistantFrameHost(
|
|
244
|
+
iframeWindow,
|
|
245
|
+
targetOrigin? // Optional origin restriction
|
|
246
|
+
);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Methods
|
|
250
|
+
|
|
251
|
+
##### `getModelContext()`
|
|
252
|
+
|
|
253
|
+
Returns the current merged model context from the iframe.
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
const context = host.getModelContext();
|
|
257
|
+
// { system: "...", tools: { ... } }
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
##### `subscribe(callback)`
|
|
261
|
+
|
|
262
|
+
Subscribes to model context changes.
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
const unsubscribe = host.subscribe(() => {
|
|
266
|
+
console.log("Context updated:", host.getModelContext());
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
##### `dispose()`
|
|
271
|
+
|
|
272
|
+
Cleans up the connection to the iframe.
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
host.dispose();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### useAssistantFrameHost
|
|
279
|
+
|
|
280
|
+
React hook that manages the lifecycle of an AssistantFrameHost.
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
useAssistantFrameHost({
|
|
284
|
+
iframeRef: RefObject<HTMLIFrameElement>,
|
|
285
|
+
targetOrigin?: string,
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### ModelContextRegistry
|
|
290
|
+
|
|
291
|
+
A flexible registry for managing model context with dynamic updates.
|
|
292
|
+
|
|
293
|
+
#### Methods
|
|
294
|
+
|
|
295
|
+
##### `addTool(tool)`
|
|
296
|
+
|
|
297
|
+
Adds a tool and returns a handle for updates/removal.
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
const handle = registry.addTool({
|
|
301
|
+
toolName: string,
|
|
302
|
+
description?: string,
|
|
303
|
+
parameters: ZodSchema | JSONSchema,
|
|
304
|
+
execute: (args, context) => Promise<any>,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
handle.update(newTool); // Update the tool
|
|
308
|
+
handle.remove(); // Remove the tool
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
##### `addInstruction(instruction)`
|
|
312
|
+
|
|
313
|
+
Adds a system instruction and returns a handle.
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
const handle = registry.addInstruction("Be concise.");
|
|
317
|
+
handle.update("Be detailed."); // Update instruction
|
|
318
|
+
handle.remove(); // Remove instruction
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
##### `addProvider(provider)`
|
|
322
|
+
|
|
323
|
+
Adds another model context provider.
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
const handle = registry.addProvider(anotherProvider);
|
|
327
|
+
handle.remove(); // Remove provider
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Use Cases
|
|
331
|
+
|
|
332
|
+
### Embedded Analytics Dashboard
|
|
333
|
+
|
|
334
|
+
An analytics iframe can provide data query tools to the parent assistant:
|
|
335
|
+
|
|
336
|
+
```tsx
|
|
337
|
+
// In analytics iframe
|
|
338
|
+
registry.addTool({
|
|
339
|
+
toolName: "queryMetrics",
|
|
340
|
+
description: "Query analytics data",
|
|
341
|
+
parameters: z.object({
|
|
342
|
+
metric: z.string(),
|
|
343
|
+
timeRange: z.string(),
|
|
344
|
+
}),
|
|
345
|
+
execute: async ({ metric, timeRange }) => {
|
|
346
|
+
const data = await analyticsAPI.query(metric, timeRange);
|
|
347
|
+
return { data, visualization: createChart(data) };
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Plugin System
|
|
353
|
+
|
|
354
|
+
Third-party plugins can extend the assistant's capabilities:
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
// In plugin iframe
|
|
358
|
+
registry.addTool({
|
|
359
|
+
toolName: "translateText",
|
|
360
|
+
description: "Translate text to another language",
|
|
361
|
+
parameters: z.object({
|
|
362
|
+
text: z.string(),
|
|
363
|
+
targetLanguage: z.string(),
|
|
364
|
+
}),
|
|
365
|
+
execute: async ({ text, targetLanguage }) => {
|
|
366
|
+
return await pluginAPI.translate(text, targetLanguage);
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Data Visualization
|
|
372
|
+
|
|
373
|
+
Provide data visualization tools in an iframe:
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// In visualization iframe
|
|
377
|
+
registry.addTool({
|
|
378
|
+
toolName: "createChart",
|
|
379
|
+
description: "Generate a chart from data",
|
|
380
|
+
parameters: z.object({
|
|
381
|
+
data: z.array(z.object({
|
|
382
|
+
label: z.string(),
|
|
383
|
+
value: z.number()
|
|
384
|
+
})),
|
|
385
|
+
chartType: z.enum(["bar", "line", "pie"]),
|
|
386
|
+
title: z.string().optional()
|
|
387
|
+
}),
|
|
388
|
+
execute: async ({ data, chartType, title }) => {
|
|
389
|
+
// Generate chart using a library like Chart.js or D3
|
|
390
|
+
const chartUrl = await generateChart(data, chartType, title);
|
|
391
|
+
return {
|
|
392
|
+
chartUrl,
|
|
393
|
+
summary: `Created ${chartType} chart with ${data.length} data points`
|
|
394
|
+
};
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
```
|
|
@@ -22,7 +22,10 @@ import { Card, Cards } from "fumadocs-ui/components/card";
|
|
|
22
22
|
# Create a new project with the default template
|
|
23
23
|
npx assistant-ui@latest create
|
|
24
24
|
|
|
25
|
-
# Or
|
|
25
|
+
# Or choose one of the following templates:
|
|
26
|
+
# Assistant Cloud for baked in persistence and thread management
|
|
27
|
+
npx assistant-ui@latest create -t cloud
|
|
28
|
+
|
|
26
29
|
# LangGraph
|
|
27
30
|
npx assistant-ui@latest create -t langgraph
|
|
28
31
|
|
|
@@ -686,11 +689,11 @@ import { ComponentPropsWithoutRef, forwardRef } from "react";
|
|
|
686
689
|
import {
|
|
687
690
|
Tooltip,
|
|
688
691
|
TooltipContent,
|
|
689
|
-
TooltipProvider,
|
|
690
692
|
TooltipTrigger,
|
|
691
693
|
} from "@/components/ui/tooltip";
|
|
692
694
|
import { Button } from "@/components/ui/button";
|
|
693
695
|
import { cn } from "@/lib/utils";
|
|
696
|
+
import { Slottable } from "@radix-ui/react-slot";
|
|
694
697
|
|
|
695
698
|
export type TooltipIconButtonProps = ComponentPropsWithoutRef<typeof Button> & {
|
|
696
699
|
tooltip: string;
|
|
@@ -702,23 +705,21 @@ export const TooltipIconButton = forwardRef<
|
|
|
702
705
|
TooltipIconButtonProps
|
|
703
706
|
>(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
|
|
704
707
|
return (
|
|
705
|
-
<
|
|
706
|
-
<
|
|
707
|
-
<
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
>
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
</Tooltip>
|
|
721
|
-
</TooltipProvider>
|
|
708
|
+
<Tooltip>
|
|
709
|
+
<TooltipTrigger asChild>
|
|
710
|
+
<Button
|
|
711
|
+
variant="ghost"
|
|
712
|
+
size="icon"
|
|
713
|
+
{...rest}
|
|
714
|
+
className={cn("aui-button-icon", className)}
|
|
715
|
+
ref={ref}
|
|
716
|
+
>
|
|
717
|
+
<Slottable>{children}</Slottable>
|
|
718
|
+
<span className="aui-sr-only">{tooltip}</span>
|
|
719
|
+
</Button>
|
|
720
|
+
</TooltipTrigger>
|
|
721
|
+
<TooltipContent side={side}>{tooltip}</TooltipContent>
|
|
722
|
+
</Tooltip>
|
|
722
723
|
);
|
|
723
724
|
});
|
|
724
725
|
|
|
@@ -41,29 +41,22 @@ This adds `/components/assistant-ui/attachment.tsx` to your project.
|
|
|
41
41
|
</Step>
|
|
42
42
|
<Step>
|
|
43
43
|
|
|
44
|
-
###
|
|
44
|
+
### Set up Runtime (No Configuration Required)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
For `useChatRuntime`, attachments work automatically without additional configuration:
|
|
47
47
|
|
|
48
48
|
```tsx title="/app/MyRuntimeProvider.tsx"
|
|
49
49
|
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
50
|
-
import {
|
|
51
|
-
CompositeAttachmentAdapter,
|
|
52
|
-
SimpleImageAttachmentAdapter,
|
|
53
|
-
SimpleTextAttachmentAdapter,
|
|
54
|
-
} from "@assistant-ui/react";
|
|
55
50
|
|
|
56
51
|
const runtime = useChatRuntime({
|
|
57
52
|
api: "/api/chat",
|
|
58
|
-
adapters: {
|
|
59
|
-
attachments: new CompositeAttachmentAdapter([
|
|
60
|
-
new SimpleImageAttachmentAdapter(),
|
|
61
|
-
new SimpleTextAttachmentAdapter(),
|
|
62
|
-
]),
|
|
63
|
-
},
|
|
64
53
|
});
|
|
65
54
|
```
|
|
66
55
|
|
|
56
|
+
<Callout type="info">
|
|
57
|
+
**Note:** The AI SDK runtime handles attachments automatically. For other runtimes like `useLocalRuntime`, you may still need to configure attachment adapters as shown in the [Creating Custom Attachment Adapters](#creating-custom-attachment-adapters) section below.
|
|
58
|
+
</Callout>
|
|
59
|
+
|
|
67
60
|
</Step>
|
|
68
61
|
<Step>
|
|
69
62
|
|
|
@@ -361,25 +361,68 @@ const RefundTool = makeAssistantTool({
|
|
|
361
361
|
|
|
362
362
|
### MCP (Model Context Protocol) Tools
|
|
363
363
|
|
|
364
|
-
Integration with MCP servers:
|
|
364
|
+
Integration with MCP servers using AI SDK v5's experimental MCP support:
|
|
365
|
+
|
|
366
|
+
<Callout type="warning">
|
|
367
|
+
MCP support in AI SDK v5 is experimental. The API may change in future releases.
|
|
368
|
+
Make sure to install the MCP SDK: `npm install @modelcontextprotocol/sdk`
|
|
369
|
+
</Callout>
|
|
365
370
|
|
|
366
371
|
```tsx
|
|
367
|
-
//
|
|
368
|
-
import {
|
|
372
|
+
// Server-side usage (e.g., in your API route)
|
|
373
|
+
import { experimental_createMCPClient, streamText } from "ai";
|
|
374
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
369
375
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
376
|
+
export async function POST(req: Request) {
|
|
377
|
+
// Create MCP client with stdio transport
|
|
378
|
+
const client = await experimental_createMCPClient({
|
|
379
|
+
transport: new StdioClientTransport({
|
|
373
380
|
command: "npx",
|
|
374
381
|
args: ["@modelcontextprotocol/server-github"],
|
|
375
|
-
},
|
|
376
|
-
}
|
|
377
|
-
|
|
382
|
+
}),
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
// Get tools from the MCP server
|
|
387
|
+
const tools = await client.tools();
|
|
388
|
+
|
|
389
|
+
const result = streamText({
|
|
390
|
+
model: openai("gpt-4o"),
|
|
391
|
+
tools,
|
|
392
|
+
messages: convertToModelMessages(messages),
|
|
393
|
+
});
|
|
378
394
|
|
|
379
|
-
|
|
395
|
+
return result.toUIMessageStreamResponse();
|
|
396
|
+
} finally {
|
|
397
|
+
// Always close the client to release resources
|
|
398
|
+
await client.close();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Frontend usage with assistant-ui
|
|
380
403
|
const runtime = useChatRuntime({
|
|
381
|
-
api: "/api/chat",
|
|
382
|
-
|
|
404
|
+
api: "/api/chat", // Your API route that uses MCP tools
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Alternative transport options:
|
|
409
|
+
|
|
410
|
+
```tsx
|
|
411
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
412
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
413
|
+
|
|
414
|
+
// HTTP transport
|
|
415
|
+
const httpClient = await experimental_createMCPClient({
|
|
416
|
+
transport: new StreamableHTTPClientTransport(
|
|
417
|
+
new URL("http://localhost:3000/mcp")
|
|
418
|
+
),
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// Server-Sent Events transport
|
|
422
|
+
const sseClient = await experimental_createMCPClient({
|
|
423
|
+
transport: new SSEClientTransport(
|
|
424
|
+
new URL("http://localhost:3000/sse")
|
|
425
|
+
),
|
|
383
426
|
});
|
|
384
427
|
```
|
|
385
428
|
|
|
@@ -483,7 +526,7 @@ const resilientTool = tool({
|
|
|
483
526
|
} catch (error) {
|
|
484
527
|
lastError = error;
|
|
485
528
|
if (abortSignal.aborted) throw error; // Don't retry on abort
|
|
486
|
-
await new Promise((resolve) => setTimeout(resolve, 1000 * i));
|
|
529
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
|
|
487
530
|
}
|
|
488
531
|
}
|
|
489
532
|
|