@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.
Files changed (34) hide show
  1. package/.docs/organized/code-examples/with-ai-sdk-v5.md +3 -1
  2. package/.docs/organized/code-examples/with-cloud.md +3 -1
  3. package/.docs/organized/code-examples/with-external-store.md +3 -1
  4. package/.docs/organized/code-examples/with-ffmpeg.md +3 -1
  5. package/.docs/organized/code-examples/with-langgraph.md +66 -38
  6. package/.docs/organized/code-examples/with-parent-id-grouping.md +3 -1
  7. package/.docs/organized/code-examples/with-react-hook-form.md +3 -1
  8. package/.docs/raw/docs/api-reference/integrations/react-data-stream.mdx +194 -0
  9. package/.docs/raw/docs/api-reference/overview.mdx +6 -0
  10. package/.docs/raw/docs/api-reference/primitives/Composer.mdx +31 -0
  11. package/.docs/raw/docs/api-reference/primitives/Message.mdx +108 -3
  12. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +59 -0
  13. package/.docs/raw/docs/api-reference/primitives/ThreadList.mdx +128 -0
  14. package/.docs/raw/docs/api-reference/primitives/ThreadListItem.mdx +160 -0
  15. package/.docs/raw/docs/api-reference/runtimes/AssistantRuntime.mdx +0 -11
  16. package/.docs/raw/docs/api-reference/runtimes/ComposerRuntime.mdx +3 -3
  17. package/.docs/raw/docs/copilots/assistant-frame.mdx +397 -0
  18. package/.docs/raw/docs/getting-started.mdx +20 -19
  19. package/.docs/raw/docs/guides/Attachments.mdx +6 -13
  20. package/.docs/raw/docs/guides/Tools.mdx +56 -13
  21. package/.docs/raw/docs/guides/context-api.mdx +574 -0
  22. package/.docs/raw/docs/migrations/v0-12.mdx +125 -0
  23. package/.docs/raw/docs/runtimes/custom/local.mdx +16 -3
  24. package/.docs/raw/docs/runtimes/data-stream.mdx +287 -0
  25. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +5 -0
  26. package/.docs/raw/docs/ui/ThreadList.mdx +54 -16
  27. package/dist/{chunk-L4K23SWI.js → chunk-NVNFQ5ZO.js} +4 -1
  28. package/dist/index.js +1 -1
  29. package/dist/prepare-docs/prepare.js +1 -1
  30. package/dist/stdio.js +1 -1
  31. package/package.json +2 -2
  32. package/.docs/raw/docs/concepts/architecture.mdx +0 -19
  33. package/.docs/raw/docs/concepts/runtime-layer.mdx +0 -163
  34. 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 start with a template:
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
- <TooltipProvider>
706
- <Tooltip>
707
- <TooltipTrigger asChild>
708
- <Button
709
- variant="ghost"
710
- size="icon"
711
- {...rest}
712
- className={cn("", className)}
713
- ref={ref}
714
- >
715
- {children}
716
- <span className="aui-sr-only">{tooltip}</span>
717
- </Button>
718
- </TooltipTrigger>
719
- <TooltipContent side={side}>{tooltip}</TooltipContent>
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
- ### Configure Attachment Adapter
44
+ ### Set up Runtime (No Configuration Required)
45
45
 
46
- Set up an attachment adapter in your runtime provider:
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
- // Using AI SDK's MCP support
368
- import { createMCPClient } from "ai/mcp";
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
- const mcpClient = createMCPClient({
371
- servers: {
372
- github: {
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
- // Tools are automatically available through the runtime
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
- tools: await mcpClient.getTools(),
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