@assistant-ui/mcp-docs-server 0.1.32 → 0.1.34
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/waterfall.md +20 -22
- package/.docs/organized/code-examples/with-a2a.md +24 -24
- package/.docs/organized/code-examples/with-ag-ui.md +30 -25
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +11 -9
- package/.docs/organized/code-examples/with-artifacts.md +49 -37
- package/.docs/organized/code-examples/with-assistant-transport.md +63 -51
- package/.docs/organized/code-examples/with-browser-extension.md +22 -10
- package/.docs/organized/code-examples/with-chain-of-thought.md +406 -87
- package/.docs/organized/code-examples/with-cloud-standalone.md +25 -24
- package/.docs/organized/code-examples/with-cloud.md +11 -9
- package/.docs/organized/code-examples/with-custom-thread-list.md +14 -12
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +23 -21
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +14 -13
- package/.docs/organized/code-examples/with-expo.md +44 -29
- package/.docs/organized/code-examples/with-external-store.md +9 -7
- package/.docs/organized/code-examples/with-ffmpeg.md +322 -285
- package/.docs/organized/code-examples/with-generative-ui.md +1066 -256
- package/.docs/organized/code-examples/with-google-adk.md +10 -8
- package/.docs/organized/code-examples/with-heat-graph.md +13 -11
- package/.docs/organized/code-examples/with-image-generation.md +19 -17
- package/.docs/organized/code-examples/with-interactables.md +317 -239
- package/.docs/organized/code-examples/with-langchain.md +14 -12
- package/.docs/organized/code-examples/with-langgraph.md +91 -83
- package/.docs/organized/code-examples/with-livekit.md +24 -22
- package/.docs/organized/code-examples/with-mcp.md +18 -12
- package/.docs/organized/code-examples/with-opencode.md +66 -66
- package/.docs/organized/code-examples/with-react-hook-form.md +19 -17
- package/.docs/organized/code-examples/with-react-ink.md +297 -102
- package/.docs/organized/code-examples/with-react-router.md +17 -15
- package/.docs/organized/code-examples/with-resumable-stream.md +15 -14
- package/.docs/organized/code-examples/with-store.md +78 -76
- package/.docs/organized/code-examples/with-tanstack.md +13 -14
- package/.docs/organized/code-examples/with-tap-runtime.md +26 -24
- package/.docs/raw/docs/(docs)/architecture.mdx +94 -42
- package/.docs/raw/docs/(docs)/cli.mdx +1 -2
- package/.docs/raw/docs/(docs)/installation.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +5 -1
- package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +15 -15
- package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +14 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +18 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +33 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/spec.mdx +45 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/composer-triggers.mdx +41 -41
- package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +19 -1
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +122 -122
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +43 -2
- package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +6 -0
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +4 -6
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +30 -0
- package/.docs/raw/docs/(reference)/api-reference/tools/component-tools.mdx +20 -3
- package/.docs/raw/docs/(reference)/api-reference/tools/index.mdx +8 -8
- package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +52 -4
- package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +100 -10
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +7 -59
- package/.docs/raw/docs/cloud/ai-sdk.mdx +0 -2
- package/.docs/raw/docs/{(docs)/copilots → copilots}/model-context.mdx +34 -26
- package/.docs/raw/docs/{(docs)/copilots → copilots}/motivation.mdx +32 -26
- package/.docs/raw/docs/guides/chain-of-thought.mdx +7 -9
- package/.docs/raw/docs/guides/context-api.mdx +2 -1
- package/.docs/raw/docs/guides/index.mdx +3 -12
- package/.docs/raw/docs/guides/mentions.mdx +4 -4
- package/.docs/raw/docs/guides/slash-commands.mdx +1 -1
- package/.docs/raw/docs/guides/suggestions.mdx +1 -1
- package/.docs/raw/docs/ink/adapters.mdx +23 -1
- package/.docs/raw/docs/ink/hooks.mdx +101 -85
- package/.docs/raw/docs/ink/migration.mdx +1 -1
- package/.docs/raw/docs/ink/primitives.mdx +2 -2
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +1 -1
- package/.docs/raw/docs/integrations/index.mdx +2 -2
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +17 -2
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +232 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +10 -16
- package/.docs/raw/docs/primitives/message.mdx +9 -10
- package/.docs/raw/docs/react-native/hooks.mdx +62 -79
- package/.docs/raw/docs/react-native/migration.mdx +1 -1
- package/.docs/raw/docs/react-native/primitives.mdx +2 -2
- package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +3 -0
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +41 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +122 -1
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +46 -4
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +7 -1
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +54 -12
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +62 -4
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +30 -7
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +108 -38
- package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +14 -1
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +64 -50
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +98 -86
- package/.docs/raw/docs/tools/backend.mdx +144 -0
- package/.docs/raw/docs/tools/defining-tools.mdx +538 -0
- package/.docs/raw/docs/tools/dynamic-tools.mdx +110 -0
- package/.docs/raw/docs/tools/generative-ui.mdx +214 -0
- package/.docs/raw/docs/tools/index.mdx +71 -0
- package/.docs/raw/docs/{guides → tools}/interactables.mdx +1 -1
- package/.docs/raw/docs/{integrations/tools → tools}/mcp.mdx +145 -50
- package/.docs/raw/docs/{guides → tools}/multi-agent.mdx +15 -17
- package/.docs/raw/docs/tools/tool-ui.mdx +967 -0
- package/.docs/raw/docs/{integrations/tools/react-mcp.mdx → tools/user-managed-mcp.mdx} +7 -7
- package/.docs/raw/docs/ui/directive-text.mdx +3 -3
- package/.docs/raw/docs/ui/mcp-config.mdx +4 -4
- package/.docs/raw/docs/ui/mermaid.mdx +16 -9
- package/.docs/raw/docs/ui/part-grouping.mdx +84 -50
- package/.docs/raw/docs/ui/reasoning.mdx +4 -5
- package/.docs/raw/docs/ui/tool-fallback.mdx +16 -0
- package/.docs/raw/docs/ui/tool-group.mdx +5 -6
- package/.docs/raw/docs/utilities/heat-graph.mdx +1 -1
- package/.docs/raw/docs/utilities/react-o11y.mdx +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/prepare-docs/code-examples.d.ts.map +1 -1
- package/dist/prepare-docs/code-examples.js.map +1 -1
- package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
- package/dist/prepare-docs/copy-raw.js.map +1 -1
- package/dist/prepare-docs/prepare.js.map +1 -1
- package/dist/stdio.js.map +1 -1
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/examples.js.map +1 -1
- package/dist/tools/tests/test-setup.js.map +1 -1
- package/dist/utils/mdx.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +5 -5
- package/.docs/organized/code-examples/with-parent-id-grouping.md +0 -596
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +0 -151
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +0 -230
- package/.docs/raw/docs/guides/generative-ui.mdx +0 -142
- package/.docs/raw/docs/guides/tool-ui.mdx +0 -858
- package/.docs/raw/docs/guides/tools.mdx +0 -736
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/assistant-frame.mdx +0 -0
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/make-assistant-visible.mdx +0 -0
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/use-assistant-instructions.mdx +0 -0
- /package/.docs/raw/docs/{guides → tools}/mcp-apps.mdx +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Generative UI (JSON spec)
|
|
3
|
+
description: Render agent-described React UI from a JSON spec with a consumer-provided component allowlist.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`MessagePrimitive.GenerativeUI` is a first-class primitive for rendering UI
|
|
7
|
+
described by the agent at runtime as a JSON spec. Instead of hard-coding a
|
|
8
|
+
component per tool, the agent emits a `generative-ui` message part containing
|
|
9
|
+
a tree of components by name. assistant-ui resolves each name against a
|
|
10
|
+
**consumer-provided allowlist** and renders the result.
|
|
11
|
+
|
|
12
|
+
> The allowlist controls **which** components the agent may render: any name
|
|
13
|
+
> not in it throws a typed `GenerativeUIRenderError` (no implicit fallback). It
|
|
14
|
+
> does not constrain the props passed to those components; see [Security](#security).
|
|
15
|
+
|
|
16
|
+
> **Opt-in feature:** The default shadcn `Thread` does **not** render
|
|
17
|
+
> `generative-ui` parts. You must wire the primitive explicitly — see
|
|
18
|
+
> [Opt-in wiring](#opt-in-wiring).
|
|
19
|
+
|
|
20
|
+
## Which generative UI pattern?
|
|
21
|
+
|
|
22
|
+
assistant-ui uses "generative UI" in three different places. Pick the one that
|
|
23
|
+
matches your integration:
|
|
24
|
+
|
|
25
|
+
| Pattern | API | Best for | Streaming |
|
|
26
|
+
|---------|-----|----------|-----------|
|
|
27
|
+
| **Generative UI primitive** | `MessagePrimitive.GenerativeUI` + allowlist | Composing dashboards, cards, and layouts from a component vocabulary you ship | Native `generative-ui` parts update progressively when the part spec changes incrementally |
|
|
28
|
+
| **Tool UI** | `Tools({ toolkit })` with `render` | Interactive widgets tied to a known tool (forms, pickers, charts) | Tool **args** stream while the model fills them in |
|
|
29
|
+
| **LangGraph data UI** | `makeAssistantDataUI` + `ui_message` | LangGraph agents emitting UI via the LangGraph stream | UI messages arrive on the LangGraph custom channel |
|
|
30
|
+
|
|
31
|
+
See also: [Tool UI guide](/docs/tools/tool-ui), [LangGraph generative UI](/docs/runtimes/langgraph/generative-ui).
|
|
32
|
+
|
|
33
|
+
## When not to use the primitive
|
|
34
|
+
|
|
35
|
+
- **User input and two-way interaction** → [Tool UI](/docs/tools/tool-ui) or [Interactables](/docs/tools/interactables)
|
|
36
|
+
- **LangGraph `push_ui_message`** → [LangGraph data UI](/docs/runtimes/langgraph/generative-ui)
|
|
37
|
+
- **Untrusted HTML or third-party widgets** → [MCP Apps](/docs/tools/mcp-apps) (sandboxed frames)
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
### 1. Define your component allowlist
|
|
42
|
+
|
|
43
|
+
```tsx title="components/gui.tsx"
|
|
44
|
+
const Card = ({ title, children }) => (
|
|
45
|
+
<div className="rounded-xl border bg-card p-4 shadow-sm">
|
|
46
|
+
<div className="text-base font-semibold">{title}</div>
|
|
47
|
+
<div className="mt-2">{children}</div>
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const Button = ({ label }) => (
|
|
52
|
+
<button className="rounded-md bg-primary px-3 py-1.5 text-primary-foreground">
|
|
53
|
+
{label}
|
|
54
|
+
</button>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
export const componentsAllowlist = { Card, Button };
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Wire the primitive into your message renderer
|
|
61
|
+
|
|
62
|
+
See [Opt-in wiring](#opt-in-wiring) for all three integration patterns.
|
|
63
|
+
|
|
64
|
+
### 3. Have the agent emit UI
|
|
65
|
+
|
|
66
|
+
**ExternalStore / manual messages** attach a native part:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
{
|
|
70
|
+
type: "generative-ui",
|
|
71
|
+
spec: {
|
|
72
|
+
root: {
|
|
73
|
+
component: "Card",
|
|
74
|
+
props: { title: "Welcome" },
|
|
75
|
+
children: [
|
|
76
|
+
{ component: "Button", props: { label: "Get started" } },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**AI SDK (`useChatRuntime`)** — the adapter maps tool results to `tool-call`
|
|
84
|
+
parts, not `generative-ui` parts. Use the [AI SDK interim bridge](#pattern-3--ai-sdk-interim-bridge) until a native emission helper ships.
|
|
85
|
+
|
|
86
|
+
Live examples in [`examples/with-generative-ui`](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-generative-ui): Tool UI demo (`/`), static primitive (`/primitive`), GUI chat (`/gui-chat`).
|
|
87
|
+
|
|
88
|
+
## Opt-in wiring
|
|
89
|
+
|
|
90
|
+
The stock `@assistant-ui/ui` `Thread` switch returns `null` for unknown part
|
|
91
|
+
types — including `generative-ui`. Add one of these patterns in **your**
|
|
92
|
+
assistant message renderer (~15 lines).
|
|
93
|
+
|
|
94
|
+
### Pattern 1 — `MessagePrimitive.Parts`
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<MessagePrimitive.Parts
|
|
98
|
+
components={{
|
|
99
|
+
generativeUI: {
|
|
100
|
+
components: componentsAllowlist,
|
|
101
|
+
Fallback: UnknownComponentFallback,
|
|
102
|
+
},
|
|
103
|
+
}}
|
|
104
|
+
/>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pattern 2 — `GroupedParts` case (shadcn Thread fork)
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
case "generative-ui":
|
|
111
|
+
return (
|
|
112
|
+
<MessagePrimitive.GenerativeUI
|
|
113
|
+
components={componentsAllowlist}
|
|
114
|
+
Fallback={UnknownComponentFallback}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Also exclude `render_gui` from tool-group chrome in `groupBy` if you use the
|
|
120
|
+
AI SDK bridge (return `null` for that tool name).
|
|
121
|
+
|
|
122
|
+
### Pattern 3 — AI SDK interim bridge
|
|
123
|
+
|
|
124
|
+
When using `useChatRuntime`, map a dedicated tool result to the renderer:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
case "tool-call":
|
|
128
|
+
if (part.toolName === "render_gui") {
|
|
129
|
+
const spec = parseRenderGuiResult(part.result);
|
|
130
|
+
if (spec) {
|
|
131
|
+
return (
|
|
132
|
+
<MessagePrimitive.GenerativeUI
|
|
133
|
+
spec={spec}
|
|
134
|
+
components={componentsAllowlist}
|
|
135
|
+
Fallback={UnknownComponentFallback}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return part.toolUI ?? <ToolFallback {...part} />;
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The message store still holds a `tool-call` on this path — not a
|
|
144
|
+
`generative-ui` part. See `examples/with-generative-ui/app/gui-chat` for a
|
|
145
|
+
working reference.
|
|
146
|
+
|
|
147
|
+
Bare strings act as inline text leaves.
|
|
148
|
+
|
|
149
|
+
## Spec shape
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
type GenerativeUINode =
|
|
153
|
+
| string
|
|
154
|
+
| {
|
|
155
|
+
component: string; // resolved against the allowlist
|
|
156
|
+
props?: Record<string, unknown>;
|
|
157
|
+
children?: GenerativeUINode[];
|
|
158
|
+
key?: string; // optional stable React key
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
type GenerativeUISpec = {
|
|
162
|
+
root: GenerativeUINode | GenerativeUINode[];
|
|
163
|
+
};
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The spec is plain JSON — easy for any agent to emit, and easy to validate
|
|
167
|
+
on the server before delivery.
|
|
168
|
+
|
|
169
|
+
## Streaming
|
|
170
|
+
|
|
171
|
+
When a message contains native `generative-ui` parts whose `spec` updates
|
|
172
|
+
incrementally (for example via ExternalStore), the primitive renders
|
|
173
|
+
progressively as nodes and props arrive.
|
|
174
|
+
|
|
175
|
+
The AI SDK `render_gui` tool path returns the full spec at **tool completion**
|
|
176
|
+
— not incrementally during the tool execute step. For args streaming during
|
|
177
|
+
generation, use [Tool UI](/docs/tools/tool-ui) instead.
|
|
178
|
+
|
|
179
|
+
## Security
|
|
180
|
+
|
|
181
|
+
The allowlist is the boundary on **which** components render: a spec can only instantiate components you put in the registry, with no `eval` and no dynamic import (names are looked up in the registry and nothing else). An unknown name throws `GenerativeUIRenderError` or invokes your `Fallback`.
|
|
182
|
+
|
|
183
|
+
It does **not** constrain the `props` the agent supplies. Spec props are spread directly onto your allowlisted components, so treat every allowlisted component as receiving untrusted input: never forward agent-supplied props into `dangerouslySetInnerHTML`, validate or reject `href` / `src` values (for example block `javascript:` URLs), and avoid passing spec props anywhere they become executable. The safest allowlisted components accept only primitive, display-oriented props.
|
|
184
|
+
|
|
185
|
+
## Error handling
|
|
186
|
+
|
|
187
|
+
Unknown component names throw `GenerativeUIRenderError` with a typed
|
|
188
|
+
`componentName` field. Catch it with a React error boundary, or pass a
|
|
189
|
+
`Fallback` component to opt into a soft-fail UX:
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
<MessagePrimitive.GenerativeUI
|
|
193
|
+
components={componentsAllowlist}
|
|
194
|
+
Fallback={({ component }) => (
|
|
195
|
+
<span className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">
|
|
196
|
+
unknown component: {component}
|
|
197
|
+
</span>
|
|
198
|
+
)}
|
|
199
|
+
/>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Composing with other primitives
|
|
203
|
+
|
|
204
|
+
`generative-ui` is a regular `MessagePart` type, so it composes cleanly with
|
|
205
|
+
`MessagePrimitive.Parts`, `MessagePrimitive.PartByIndex`, and
|
|
206
|
+
`MessagePrimitive.GroupedParts`. Render it alongside text, tool calls, and
|
|
207
|
+
reasoning in the same message.
|
|
208
|
+
|
|
209
|
+
## Why a primitive (not just a tool)
|
|
210
|
+
|
|
211
|
+
Tool-call UI is great when the agent already invoked a known tool. Generative
|
|
212
|
+
UI flips it: the agent _composes_ UI from a vocabulary you ship. Useful for
|
|
213
|
+
dashboards, status panels, and structured layouts — not for collecting user
|
|
214
|
+
input (use Tool UI for that).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Tools
|
|
3
|
+
description: Give the model callable capabilities with assistant-ui toolkits — define frontend, backend, human, and provider tools, render tool calls as interactive UI, and connect MCP servers.
|
|
4
|
+
platforms: ["react"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Tools are how the model takes action: fetch data, call an API, query a database, drive your UI, or run a workflow. In assistant-ui you declare tools in a **toolkit** — a named map where each key is the tool name the model sees and each value describes the tool's schema, where it runs, and how its call renders in the chat.
|
|
8
|
+
|
|
9
|
+
## Start here
|
|
10
|
+
|
|
11
|
+
<Cards>
|
|
12
|
+
<Card title="Defining Tools" href="/docs/tools/defining-tools">
|
|
13
|
+
Author a toolkit with the `"use generative"` directive — frontend, backend, human, and provider tools, with the schema, executor, and renderer in one file.
|
|
14
|
+
</Card>
|
|
15
|
+
<Card title="Backend Tools" href="/docs/tools/backend">
|
|
16
|
+
Wire a toolkit into your AI SDK route with `AISDKToolkit` / `frontendTools`, mix client and server tools, and round-trip multi-modal results.
|
|
17
|
+
</Card>
|
|
18
|
+
<Card title="Tool UI" href="/docs/tools/tool-ui">
|
|
19
|
+
Render tool calls as custom components — loading and result states, human-in-the-loop, approvals, and streaming.
|
|
20
|
+
</Card>
|
|
21
|
+
<Card title="Dynamic Tools" href="/docs/tools/dynamic-tools">
|
|
22
|
+
Tools whose executor closes over React state, via `stubTool()` + `useAuiToolOverrides`.
|
|
23
|
+
</Card>
|
|
24
|
+
</Cards>
|
|
25
|
+
|
|
26
|
+
## Define tools with `"use generative"`
|
|
27
|
+
|
|
28
|
+
<Callout type="info">
|
|
29
|
+
Use `"use generative"` + `defineToolkit` for toolkits. For tools that execute
|
|
30
|
+
elsewhere, spread `defineMcpToolkit({ ... })` for MCP servers or use
|
|
31
|
+
`execute: externalTool()` to attach a renderer to a non-MCP external tool.
|
|
32
|
+
</Callout>
|
|
33
|
+
|
|
34
|
+
In a `"use generative"` file every tool declares an `execute` and the kind is
|
|
35
|
+
**inferred** from it (you never write `type`). See
|
|
36
|
+
[Defining Tools](/docs/tools/defining-tools#define-tools-with-use-generative).
|
|
37
|
+
|
|
38
|
+
## Rendering AI output as UI
|
|
39
|
+
|
|
40
|
+
assistant-ui has a few ways to turn model output into React UI. Pick by **who decides what renders**:
|
|
41
|
+
|
|
42
|
+
| You want… | Use | The decider |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| A custom component for a known tool call (form, picker, chart, status) | [Tool UI](/docs/tools/tool-ui) — `render` on a toolkit entry | the **model**, by calling the tool |
|
|
45
|
+
| Persistent, out-of-thread state the AI can read and write | [Interactables](/docs/tools/interactables) | the **model + the user**, bidirectionally |
|
|
46
|
+
| UI composed from a component vocabulary you ship, described as a JSON spec | [Generative UI (JSON spec)](/docs/tools/generative-ui) — `MessagePrimitive.GenerativeUI` | the **model**, composing a tree |
|
|
47
|
+
| UI pushed by a LangGraph node alongside messages | [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui) — `makeAssistantDataUI` | the **backend / orchestrator** |
|
|
48
|
+
|
|
49
|
+
## Connect external tools
|
|
50
|
+
|
|
51
|
+
<Cards>
|
|
52
|
+
<Card title="MCP (server-side)" href="/docs/tools/mcp">
|
|
53
|
+
Wire one or more MCP servers into your API route as a tool catalog.
|
|
54
|
+
</Card>
|
|
55
|
+
<Card title="User-managed MCP" href="/docs/tools/user-managed-mcp">
|
|
56
|
+
Let end users add and authenticate MCP servers from the browser.
|
|
57
|
+
</Card>
|
|
58
|
+
<Card title="MCP Apps" href="/docs/tools/mcp-apps">
|
|
59
|
+
Render MCP UI resources (`ui://`) inline in sandboxed frames.
|
|
60
|
+
</Card>
|
|
61
|
+
<Card title="Multi-Agent" href="/docs/tools/multi-agent">
|
|
62
|
+
Render sub-agent conversations inside a tool call.
|
|
63
|
+
</Card>
|
|
64
|
+
</Cards>
|
|
65
|
+
|
|
66
|
+
## Reference & components
|
|
67
|
+
|
|
68
|
+
- [Tools API Reference](/docs/api-reference/tools) — `tool`, `Toolkit`, `Tools`, and the tool-status hooks.
|
|
69
|
+
- [`ToolFallback`](/docs/ui/tool-fallback) — a default tool card for tools with no custom UI.
|
|
70
|
+
- [`ToolGroup`](/docs/ui/tool-group) — collapse consecutive tool calls into one container.
|
|
71
|
+
- [Migrating Tools to Toolkits](/docs/migrations/toolkit-tools) — move off the deprecated `makeAssistantTool` / `useAssistantToolUI` APIs.
|
|
@@ -399,5 +399,5 @@ See the complete [with-interactables example](https://github.com/assistant-ui/as
|
|
|
399
399
|
|
|
400
400
|
## Related
|
|
401
401
|
|
|
402
|
-
- [
|
|
402
|
+
- [Tool UI](/docs/tools/tool-ui) — Inline tool call UIs rendered inside messages
|
|
403
403
|
- [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui) — Structured UI components emitted by a LangGraph graph alongside messages
|
|
@@ -13,7 +13,13 @@ client ──► /api/chat ──► MCP client ──► MCP server (HTTP
|
|
|
13
13
|
└─ tools() ──► passed to streamText({ tools })
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
The MCP client lives on the server inside your AI SDK route handler. It connects to one or more MCP servers, calls `tools()` to get a tool map, and hands that map to `streamText`. assistant-ui's existing tool-call UI (`ToolFallback`, `
|
|
16
|
+
The MCP client lives on the server inside your AI SDK route handler. It connects to one or more MCP servers, calls `tools()` to get a tool map, and hands that map to `streamText`. assistant-ui's existing tool-call UI (`ToolFallback`, or toolkit entries with `render`) renders the results.
|
|
17
|
+
|
|
18
|
+
<Callout type="info">
|
|
19
|
+
If you use a `"use generative"` toolkit, spread `defineMcpToolkit({ ... })`
|
|
20
|
+
in the toolkit and use `AISDKToolkit` in your route. It opens the MCP clients,
|
|
21
|
+
merges their tools with your toolkit, and closes them for you.
|
|
22
|
+
</Callout>
|
|
17
23
|
|
|
18
24
|
## Setup
|
|
19
25
|
|
|
@@ -71,9 +77,64 @@ const mcpClient = await createMCPClient({
|
|
|
71
77
|
</Step>
|
|
72
78
|
<Step>
|
|
73
79
|
|
|
80
|
+
### Define MCP servers in your toolkit
|
|
81
|
+
|
|
82
|
+
In a generative toolkit, spread `defineMcpToolkit({ ... })` with one entry per
|
|
83
|
+
MCP server. The entry key names the server connection; the MCP server publishes
|
|
84
|
+
the actual tool names.
|
|
85
|
+
|
|
86
|
+
```tsx title="app/toolkit.tsx"
|
|
87
|
+
"use generative";
|
|
88
|
+
|
|
89
|
+
import { defineMcpToolkit, defineToolkit } from "@assistant-ui/react";
|
|
90
|
+
|
|
91
|
+
export default defineToolkit({
|
|
92
|
+
...defineMcpToolkit({
|
|
93
|
+
github: {
|
|
94
|
+
type: "http",
|
|
95
|
+
url: "https://mcp.example.com/mcp",
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Use `AISDKToolkit` in the route. It opens the MCP clients, merges their tools
|
|
102
|
+
with the rest of your toolkit, and closes them when you call `close()`:
|
|
103
|
+
|
|
104
|
+
```ts title="app/api/chat/route.ts"
|
|
105
|
+
import { AISDKToolkit } from "@assistant-ui/react-ai-sdk";
|
|
106
|
+
import { openai } from "@ai-sdk/openai";
|
|
107
|
+
import { streamText, convertToModelMessages } from "ai";
|
|
108
|
+
import type { UIMessage } from "ai";
|
|
109
|
+
import toolkit from "../../toolkit";
|
|
110
|
+
|
|
111
|
+
export async function POST(req: Request) {
|
|
112
|
+
const { messages, tools }: { messages: UIMessage[]; tools?: Record<string, any> } =
|
|
113
|
+
await req.json();
|
|
114
|
+
|
|
115
|
+
const aiToolkit = new AISDKToolkit({ toolkit });
|
|
116
|
+
|
|
117
|
+
const result = streamText({
|
|
118
|
+
model: openai("gpt-5.4-mini"),
|
|
119
|
+
messages: await convertToModelMessages(messages),
|
|
120
|
+
tools: await aiToolkit.tools({ frontend: tools }),
|
|
121
|
+
onFinish: async () => {
|
|
122
|
+
await aiToolkit.close();
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return result.toUIMessageStreamResponse();
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
</Step>
|
|
131
|
+
<Step>
|
|
132
|
+
|
|
74
133
|
### Wire the tools into the route
|
|
75
134
|
|
|
76
|
-
`mcpClient.tools()` returns an object shaped
|
|
135
|
+
For manual MCP client control, `mcpClient.tools()` returns an object shaped
|
|
136
|
+
exactly like the `tools` argument of `streamText`. Spread it in alongside any of
|
|
137
|
+
your own tools, and close the client when the response finishes:
|
|
77
138
|
|
|
78
139
|
```ts title="app/api/chat/route.ts"
|
|
79
140
|
import { createMCPClient } from "@ai-sdk/mcp";
|
|
@@ -141,31 +202,39 @@ If two servers expose tools with the same name, the later spread wins. Rename or
|
|
|
141
202
|
|
|
142
203
|
### Render results in the UI
|
|
143
204
|
|
|
144
|
-
Tool calls flow through the existing assistant-ui tool-call rendering. With no
|
|
205
|
+
Tool calls flow through the existing assistant-ui tool-call rendering. With no
|
|
206
|
+
setup, the bundled `<ToolFallback>` component renders the call name, arguments,
|
|
207
|
+
and result. To customize the appearance for a specific tool in a generative
|
|
208
|
+
toolkit, add an `externalTool()` renderer whose key matches the MCP tool name:
|
|
145
209
|
|
|
146
210
|
<PlatformTabs>
|
|
147
211
|
<Tab value="React">
|
|
148
212
|
|
|
149
|
-
```tsx title="app/
|
|
150
|
-
"use
|
|
213
|
+
```tsx title="app/toolkit.tsx"
|
|
214
|
+
"use generative";
|
|
151
215
|
|
|
152
|
-
import {
|
|
216
|
+
import { defineMcpToolkit, defineToolkit, externalTool } from "@assistant-ui/react";
|
|
153
217
|
|
|
154
218
|
type Args = { repo: string; number: number };
|
|
155
219
|
type Result = { title: string; state: string; url: string };
|
|
156
220
|
|
|
157
|
-
export
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
</
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
221
|
+
export default defineToolkit({
|
|
222
|
+
...defineMcpToolkit({
|
|
223
|
+
github: { type: "http", url: "https://mcp.example.com/mcp" },
|
|
224
|
+
}),
|
|
225
|
+
github_get_issue: {
|
|
226
|
+
execute: externalTool(),
|
|
227
|
+
render: ({ args, result }: { args: Args; result?: Result }) => (
|
|
228
|
+
<div className="rounded border p-3">
|
|
229
|
+
<div className="font-mono text-sm">{args.repo}#{args.number}</div>
|
|
230
|
+
{result && (
|
|
231
|
+
<a href={result.url} className="underline">
|
|
232
|
+
{result.title} ({result.state})
|
|
233
|
+
</a>
|
|
234
|
+
)}
|
|
235
|
+
</div>
|
|
236
|
+
),
|
|
237
|
+
},
|
|
169
238
|
});
|
|
170
239
|
```
|
|
171
240
|
|
|
@@ -173,28 +242,30 @@ export const GitHubIssueToolUI = makeAssistantToolUI<Args, Result>({
|
|
|
173
242
|
<Tab value="React Native">
|
|
174
243
|
|
|
175
244
|
```tsx title="components/GitHubIssueToolUI.tsx"
|
|
176
|
-
import {
|
|
245
|
+
import { defineToolkit } from "@assistant-ui/react-native";
|
|
177
246
|
import { Linking, Pressable, Text, View } from "react-native";
|
|
178
247
|
|
|
179
248
|
type Args = { repo: string; number: number };
|
|
180
249
|
type Result = { title: string; state: string; url: string };
|
|
181
250
|
|
|
182
|
-
export const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<
|
|
187
|
-
{
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
{
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
251
|
+
export const toolkit = defineToolkit({
|
|
252
|
+
github_get_issue: {
|
|
253
|
+
type: "backend",
|
|
254
|
+
render: ({ args, result }: { args: Args; result?: Result }) => (
|
|
255
|
+
<View style={{ borderWidth: 1, borderRadius: 6, padding: 12 }}>
|
|
256
|
+
<Text style={{ fontFamily: "Menlo", fontSize: 13 }}>
|
|
257
|
+
{args.repo}#{args.number}
|
|
258
|
+
</Text>
|
|
259
|
+
{result && (
|
|
260
|
+
<Pressable onPress={() => Linking.openURL(result.url)}>
|
|
261
|
+
<Text style={{ textDecorationLine: "underline" }}>
|
|
262
|
+
{result.title} ({result.state})
|
|
263
|
+
</Text>
|
|
264
|
+
</Pressable>
|
|
265
|
+
)}
|
|
266
|
+
</View>
|
|
267
|
+
),
|
|
268
|
+
},
|
|
198
269
|
});
|
|
199
270
|
```
|
|
200
271
|
|
|
@@ -202,33 +273,57 @@ export const GitHubIssueToolUI = makeAssistantToolUI<Args, Result>({
|
|
|
202
273
|
<Tab value="React Ink">
|
|
203
274
|
|
|
204
275
|
```tsx title="components/GitHubIssueToolUI.tsx"
|
|
205
|
-
import {
|
|
276
|
+
import { defineToolkit } from "@assistant-ui/react-ink";
|
|
206
277
|
import { Box, Text } from "ink";
|
|
207
278
|
|
|
208
279
|
type Args = { repo: string; number: number };
|
|
209
280
|
type Result = { title: string; state: string; url: string };
|
|
210
281
|
|
|
211
|
-
export const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<
|
|
216
|
-
{args.repo}#{args.number}
|
|
217
|
-
</Text>
|
|
218
|
-
{result && (
|
|
282
|
+
export const toolkit = defineToolkit({
|
|
283
|
+
github_get_issue: {
|
|
284
|
+
type: "backend",
|
|
285
|
+
render: ({ args, result }: { args: Args; result?: Result }) => (
|
|
286
|
+
<Box borderStyle="round" paddingX={1} flexDirection="column">
|
|
219
287
|
<Text>
|
|
220
|
-
{
|
|
288
|
+
{args.repo}#{args.number}
|
|
221
289
|
</Text>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
290
|
+
{result && (
|
|
291
|
+
<Text>
|
|
292
|
+
{result.title} ({result.state}) — {result.url}
|
|
293
|
+
</Text>
|
|
294
|
+
)}
|
|
295
|
+
</Box>
|
|
296
|
+
),
|
|
297
|
+
},
|
|
225
298
|
});
|
|
226
299
|
```
|
|
227
300
|
|
|
228
301
|
</Tab>
|
|
229
302
|
</PlatformTabs>
|
|
230
303
|
|
|
231
|
-
|
|
304
|
+
Register the toolkit once with `Tools({ toolkit })`. Renderer keys such as
|
|
305
|
+
`github_get_issue` must match the tool names your MCP server publishes.
|
|
306
|
+
|
|
307
|
+
```tsx title="app/components/RuntimeProvider.tsx"
|
|
308
|
+
"use client";
|
|
309
|
+
|
|
310
|
+
import { AssistantRuntimeProvider, Tools, useAui } from "@assistant-ui/react";
|
|
311
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
312
|
+
import type { ReactNode } from "react";
|
|
313
|
+
|
|
314
|
+
import { toolkit } from "./GitHubIssueToolUI";
|
|
315
|
+
|
|
316
|
+
export function MyRuntimeProvider({ children }: { children: ReactNode }) {
|
|
317
|
+
const runtime = useChatRuntime({ api: "/api/chat" });
|
|
318
|
+
const aui = useAui({ tools: Tools({ toolkit }) });
|
|
319
|
+
|
|
320
|
+
return (
|
|
321
|
+
<AssistantRuntimeProvider aui={aui} runtime={runtime}>
|
|
322
|
+
{children}
|
|
323
|
+
</AssistantRuntimeProvider>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
```
|
|
232
327
|
|
|
233
328
|
</Step>
|
|
234
329
|
<Step>
|
|
@@ -262,6 +357,6 @@ Start the app and trigger a tool call (e.g., ask the assistant to do something t
|
|
|
262
357
|
<Card
|
|
263
358
|
title="Tools and tool UI"
|
|
264
359
|
description="Build custom renderers for tool calls and approvals."
|
|
265
|
-
href="/docs/
|
|
360
|
+
href="/docs/tools/defining-tools"
|
|
266
361
|
/>
|
|
267
362
|
</Cards>
|
|
@@ -12,7 +12,7 @@ When a tool call includes a `messages` field (`ToolCallMessagePart.messages`), i
|
|
|
12
12
|
|
|
13
13
|
Key behaviors:
|
|
14
14
|
|
|
15
|
-
- **Scope inheritance** — Parent
|
|
15
|
+
- **Scope inheritance** — Parent toolkit renderers are available in sub-agent messages. A `Tools({ toolkit })` registration at the top level works inside sub-agent conversations too.
|
|
16
16
|
- **Recursive** — Sub-agent messages can contain tool calls that themselves have nested messages. Just use `MessagePartPrimitive.Messages` again.
|
|
17
17
|
- **Read-only** — Sub-agent messages are rendered in a readonly context. No editing, branching, or composing.
|
|
18
18
|
|
|
@@ -25,13 +25,15 @@ Key behaviors:
|
|
|
25
25
|
|
|
26
26
|
```tsx
|
|
27
27
|
import {
|
|
28
|
-
|
|
28
|
+
defineToolkit,
|
|
29
|
+
Tools,
|
|
29
30
|
MessagePartPrimitive,
|
|
30
31
|
} from "@assistant-ui/react";
|
|
31
32
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const toolkit = defineToolkit({
|
|
34
|
+
invoke_researcher: {
|
|
35
|
+
type: "backend",
|
|
36
|
+
render: ({ args, status }) => (
|
|
35
37
|
<div className="my-2 rounded-lg border p-4">
|
|
36
38
|
<div className="mb-2 text-sm font-medium text-gray-500">
|
|
37
39
|
Researcher Agent {status.type === "running" && "(working...)"}
|
|
@@ -44,6 +46,7 @@ const ResearchAgentToolUI = makeAssistantToolUI({
|
|
|
44
46
|
</MessagePartPrimitive.Messages>
|
|
45
47
|
</div>
|
|
46
48
|
),
|
|
49
|
+
},
|
|
47
50
|
});
|
|
48
51
|
```
|
|
49
52
|
|
|
@@ -144,23 +147,17 @@ function App() {
|
|
|
144
147
|
|
|
145
148
|
## Subgraph Namespace Events
|
|
146
149
|
|
|
147
|
-
When using LangGraph, subgraph events carry a `namespace` that identifies which sub-agent emitted them
|
|
148
|
-
|
|
149
|
-
- `onSubgraphValues(namespace, values)` fires when a subgraph emits a full state snapshot. Use the `values.messages` array to populate `ToolCallMessagePart.messages` for that sub-agent.
|
|
150
|
-
- `onSubgraphUpdates(namespace, updates)` fires for incremental state patches from a subgraph.
|
|
151
|
-
- `onSubgraphError(namespace, error)` fires when a subgraph fails. The parent message is not marked incomplete; only top-level errors trigger that.
|
|
152
|
-
- `onMessageChunk(chunk, metadata)` includes `metadata.namespace` when the chunk originates from a subgraph. Use this to display per-sub-agent streaming indicators.
|
|
153
|
-
|
|
154
|
-
The `namespace` value mirrors the pipe-separated suffix on the LangGraph event name (e.g. `values|tools:call_abc` gives `"tools:call_abc"`).
|
|
150
|
+
When using LangGraph, subgraph events (`onSubgraphValues` / `onSubgraphUpdates` / `onSubgraphError`, plus the `namespace` on `onMessageChunk`) carry a `namespace` that identifies which sub-agent emitted them, letting you attribute messages and state to specific sub-agents. See [LangGraph Streaming](/docs/runtimes/langgraph/streaming) for the full reference.
|
|
155
151
|
|
|
156
152
|
## Recursive Sub-Agents
|
|
157
153
|
|
|
158
154
|
If a sub-agent's tool calls also have nested messages, the same pattern applies recursively:
|
|
159
155
|
|
|
160
156
|
```tsx
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
const toolkit = defineToolkit({
|
|
158
|
+
invoke_planner: {
|
|
159
|
+
type: "backend",
|
|
160
|
+
render: () => (
|
|
164
161
|
<div className="rounded border p-3">
|
|
165
162
|
<h4>Planner Agent</h4>
|
|
166
163
|
<MessagePartPrimitive.Messages>
|
|
@@ -191,6 +188,7 @@ const OuterAgentToolUI = makeAssistantToolUI({
|
|
|
191
188
|
</MessagePartPrimitive.Messages>
|
|
192
189
|
</div>
|
|
193
190
|
),
|
|
191
|
+
},
|
|
194
192
|
});
|
|
195
193
|
```
|
|
196
194
|
|
|
@@ -227,7 +225,7 @@ function SubConversation({
|
|
|
227
225
|
|
|
228
226
|
## Related
|
|
229
227
|
|
|
230
|
-
- [Generative UI](/docs/
|
|
228
|
+
- [Generative UI](/docs/tools/tool-ui) — Creating tool call UIs
|
|
231
229
|
- [MessagePartPrimitive](/docs/api-reference/primitives/message-part) — API reference for message part primitives
|
|
232
230
|
- [Sub-Agent Model Tracking](/docs/cloud/ai-sdk#sub-agent-model-tracking) — Track delegated model usage and costs in the Cloud dashboard
|
|
233
231
|
- [LangGraph Streaming](/docs/runtimes/langgraph/streaming) — Event handlers, subgraph events, and message metadata
|