@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.
Files changed (134) hide show
  1. package/.docs/organized/code-examples/waterfall.md +20 -22
  2. package/.docs/organized/code-examples/with-a2a.md +24 -24
  3. package/.docs/organized/code-examples/with-ag-ui.md +30 -25
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +11 -9
  5. package/.docs/organized/code-examples/with-artifacts.md +49 -37
  6. package/.docs/organized/code-examples/with-assistant-transport.md +63 -51
  7. package/.docs/organized/code-examples/with-browser-extension.md +22 -10
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +406 -87
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +25 -24
  10. package/.docs/organized/code-examples/with-cloud.md +11 -9
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +14 -12
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +23 -21
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +14 -13
  14. package/.docs/organized/code-examples/with-expo.md +44 -29
  15. package/.docs/organized/code-examples/with-external-store.md +9 -7
  16. package/.docs/organized/code-examples/with-ffmpeg.md +322 -285
  17. package/.docs/organized/code-examples/with-generative-ui.md +1066 -256
  18. package/.docs/organized/code-examples/with-google-adk.md +10 -8
  19. package/.docs/organized/code-examples/with-heat-graph.md +13 -11
  20. package/.docs/organized/code-examples/with-image-generation.md +19 -17
  21. package/.docs/organized/code-examples/with-interactables.md +317 -239
  22. package/.docs/organized/code-examples/with-langchain.md +14 -12
  23. package/.docs/organized/code-examples/with-langgraph.md +91 -83
  24. package/.docs/organized/code-examples/with-livekit.md +24 -22
  25. package/.docs/organized/code-examples/with-mcp.md +18 -12
  26. package/.docs/organized/code-examples/with-opencode.md +66 -66
  27. package/.docs/organized/code-examples/with-react-hook-form.md +19 -17
  28. package/.docs/organized/code-examples/with-react-ink.md +297 -102
  29. package/.docs/organized/code-examples/with-react-router.md +17 -15
  30. package/.docs/organized/code-examples/with-resumable-stream.md +15 -14
  31. package/.docs/organized/code-examples/with-store.md +78 -76
  32. package/.docs/organized/code-examples/with-tanstack.md +13 -14
  33. package/.docs/organized/code-examples/with-tap-runtime.md +26 -24
  34. package/.docs/raw/docs/(docs)/architecture.mdx +94 -42
  35. package/.docs/raw/docs/(docs)/cli.mdx +1 -2
  36. package/.docs/raw/docs/(docs)/installation.mdx +1 -1
  37. package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +5 -1
  38. package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +15 -15
  39. package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +14 -1
  40. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +18 -0
  41. package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +33 -0
  42. package/.docs/raw/docs/(reference)/api-reference/generative-ui/spec.mdx +45 -0
  43. package/.docs/raw/docs/(reference)/api-reference/hooks/composer-triggers.mdx +41 -41
  44. package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +19 -1
  45. package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +122 -122
  46. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +43 -2
  47. package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +6 -0
  48. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +4 -6
  49. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +30 -0
  50. package/.docs/raw/docs/(reference)/api-reference/tools/component-tools.mdx +20 -3
  51. package/.docs/raw/docs/(reference)/api-reference/tools/index.mdx +8 -8
  52. package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +52 -4
  53. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +100 -10
  54. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +7 -59
  55. package/.docs/raw/docs/cloud/ai-sdk.mdx +0 -2
  56. package/.docs/raw/docs/{(docs)/copilots → copilots}/model-context.mdx +34 -26
  57. package/.docs/raw/docs/{(docs)/copilots → copilots}/motivation.mdx +32 -26
  58. package/.docs/raw/docs/guides/chain-of-thought.mdx +7 -9
  59. package/.docs/raw/docs/guides/context-api.mdx +2 -1
  60. package/.docs/raw/docs/guides/index.mdx +3 -12
  61. package/.docs/raw/docs/guides/mentions.mdx +4 -4
  62. package/.docs/raw/docs/guides/slash-commands.mdx +1 -1
  63. package/.docs/raw/docs/guides/suggestions.mdx +1 -1
  64. package/.docs/raw/docs/ink/adapters.mdx +23 -1
  65. package/.docs/raw/docs/ink/hooks.mdx +101 -85
  66. package/.docs/raw/docs/ink/migration.mdx +1 -1
  67. package/.docs/raw/docs/ink/primitives.mdx +2 -2
  68. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +1 -1
  69. package/.docs/raw/docs/integrations/index.mdx +2 -2
  70. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +17 -2
  71. package/.docs/raw/docs/migrations/toolkit-tools.mdx +232 -0
  72. package/.docs/raw/docs/primitives/chain-of-thought.mdx +10 -16
  73. package/.docs/raw/docs/primitives/message.mdx +9 -10
  74. package/.docs/raw/docs/react-native/hooks.mdx +62 -79
  75. package/.docs/raw/docs/react-native/migration.mdx +1 -1
  76. package/.docs/raw/docs/react-native/primitives.mdx +2 -2
  77. package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +3 -0
  78. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +41 -0
  79. package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +122 -1
  80. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +46 -4
  81. package/.docs/raw/docs/runtimes/concepts/threads.mdx +7 -1
  82. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +54 -12
  83. package/.docs/raw/docs/runtimes/custom/external-store.mdx +62 -4
  84. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +30 -7
  85. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +108 -38
  86. package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +2 -2
  87. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +14 -1
  88. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +64 -50
  89. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +98 -86
  90. package/.docs/raw/docs/tools/backend.mdx +144 -0
  91. package/.docs/raw/docs/tools/defining-tools.mdx +538 -0
  92. package/.docs/raw/docs/tools/dynamic-tools.mdx +110 -0
  93. package/.docs/raw/docs/tools/generative-ui.mdx +214 -0
  94. package/.docs/raw/docs/tools/index.mdx +71 -0
  95. package/.docs/raw/docs/{guides → tools}/interactables.mdx +1 -1
  96. package/.docs/raw/docs/{integrations/tools → tools}/mcp.mdx +145 -50
  97. package/.docs/raw/docs/{guides → tools}/multi-agent.mdx +15 -17
  98. package/.docs/raw/docs/tools/tool-ui.mdx +967 -0
  99. package/.docs/raw/docs/{integrations/tools/react-mcp.mdx → tools/user-managed-mcp.mdx} +7 -7
  100. package/.docs/raw/docs/ui/directive-text.mdx +3 -3
  101. package/.docs/raw/docs/ui/mcp-config.mdx +4 -4
  102. package/.docs/raw/docs/ui/mermaid.mdx +16 -9
  103. package/.docs/raw/docs/ui/part-grouping.mdx +84 -50
  104. package/.docs/raw/docs/ui/reasoning.mdx +4 -5
  105. package/.docs/raw/docs/ui/tool-fallback.mdx +16 -0
  106. package/.docs/raw/docs/ui/tool-group.mdx +5 -6
  107. package/.docs/raw/docs/utilities/heat-graph.mdx +1 -1
  108. package/.docs/raw/docs/utilities/react-o11y.mdx +2 -2
  109. package/dist/constants.js.map +1 -1
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js.map +1 -1
  112. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  113. package/dist/prepare-docs/code-examples.js.map +1 -1
  114. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  115. package/dist/prepare-docs/copy-raw.js.map +1 -1
  116. package/dist/prepare-docs/prepare.js.map +1 -1
  117. package/dist/stdio.js.map +1 -1
  118. package/dist/tools/docs.js.map +1 -1
  119. package/dist/tools/examples.js.map +1 -1
  120. package/dist/tools/tests/test-setup.js.map +1 -1
  121. package/dist/utils/mdx.js.map +1 -1
  122. package/dist/utils/paths.d.ts.map +1 -1
  123. package/dist/utils/paths.js.map +1 -1
  124. package/package.json +5 -5
  125. package/.docs/organized/code-examples/with-parent-id-grouping.md +0 -596
  126. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +0 -151
  127. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +0 -230
  128. package/.docs/raw/docs/guides/generative-ui.mdx +0 -142
  129. package/.docs/raw/docs/guides/tool-ui.mdx +0 -858
  130. package/.docs/raw/docs/guides/tools.mdx +0 -736
  131. /package/.docs/raw/docs/{(docs)/copilots → copilots}/assistant-frame.mdx +0 -0
  132. /package/.docs/raw/docs/{(docs)/copilots → copilots}/make-assistant-visible.mdx +0 -0
  133. /package/.docs/raw/docs/{(docs)/copilots → copilots}/use-assistant-instructions.mdx +0 -0
  134. /package/.docs/raw/docs/{guides → tools}/mcp-apps.mdx +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Adapters
3
- description: Title generation and storage adapters for React Ink.
3
+ description: Attachment, title generation, and storage adapters for React Ink.
4
4
  ---
5
5
 
6
6
  Adapters customize runtime behavior. They can be passed as options to `useLocalRuntime` or `useRemoteThreadListRuntime`.
@@ -17,6 +17,28 @@ const adapter = createFileStorageAdapter({
17
17
  });
18
18
  ```
19
19
 
20
+ ## Attachment adapters
21
+
22
+ `SimpleTextAttachmentAdapter` and `SimpleImageAttachmentAdapter` work the same in the terminal as on web and React Native. Text contents are sent to the model wrapped in `<attachment name=...>` tags, and images are sent as base64 data URLs.
23
+
24
+ ```ts
25
+ import {
26
+ CompositeAttachmentAdapter,
27
+ SimpleImageAttachmentAdapter,
28
+ SimpleTextAttachmentAdapter,
29
+ useLocalRuntime,
30
+ } from "@assistant-ui/react-ink";
31
+
32
+ const runtime = useLocalRuntime(chatModelAdapter, {
33
+ adapters: {
34
+ attachments: new CompositeAttachmentAdapter([
35
+ new SimpleTextAttachmentAdapter(),
36
+ new SimpleImageAttachmentAdapter(),
37
+ ]),
38
+ },
39
+ });
40
+ ```
41
+
20
42
  ## TitleGenerationAdapter
21
43
 
22
44
  Produces a thread title from a thread's messages. Pass one as the `titleGenerator` option to `createFileStorageAdapter`, or call it from a custom `RemoteThreadListAdapter`.
@@ -60,6 +60,51 @@ useAuiEvent("thread.runStart", (payload) => {
60
60
  });
61
61
  ```
62
62
 
63
+ ### useNotification
64
+
65
+ Ring the terminal bell and emit an OSC desktop notification when the assistant finishes a run, stops with an error, or pauses for human approval.
66
+
67
+ ```tsx
68
+ import { useNotification } from "@assistant-ui/react-ink";
69
+
70
+ useNotification();
71
+ ```
72
+
73
+ Defaults:
74
+
75
+ - `task-complete`: bell + OSC 9
76
+ - `task-incomplete`: bell
77
+ - `needs-input` (assistant message in `requires-action` with `reason: "interrupt"`): bell
78
+
79
+ Pass `false` to suppress one trigger, or a `NotificationHandler` to override it:
80
+
81
+ ```tsx
82
+ useNotification({
83
+ onTaskComplete: { osc: "osc99" },
84
+ onTaskIncomplete: false,
85
+ onNeedsInput: {
86
+ custom: (event) => myLogger.log(event),
87
+ },
88
+ });
89
+ ```
90
+
91
+ | Option | Type | Description |
92
+ |--------|------|-------------|
93
+ | `enabled` | `boolean` | Master switch. Defaults to `true`. |
94
+ | `onTaskComplete` | `NotificationHandler<"task-complete"> \| false` | Fired when the latest assistant message status flips to `complete` after a run was observed. |
95
+ | `onTaskIncomplete` | `NotificationHandler<"task-incomplete"> \| false` | Fired when the latest assistant message status flips to `incomplete` after a run was observed. |
96
+ | `onNeedsInput` | `NotificationHandler<"needs-input"> \| false` | Fired when the latest assistant message enters `requires-action` with `reason: "interrupt"`. Tool-call pauses are skipped. |
97
+
98
+ `NotificationHandler<T>` fields (all optional, any combination):
99
+
100
+ | Field | Type | Description |
101
+ |-------|------|-------------|
102
+ | `bell` | `boolean` | Ring the terminal bell (`\x07`). |
103
+ | `osc` | `boolean \| "osc9" \| "osc99" \| "osc777"` | Send an OSC notification. `true` is equivalent to `"osc9"`. |
104
+ | `custom` | `(event: Extract<NotificationEvent, { type: T }>) => void` | User callback invoked with the event payload narrowed to this handler's type. |
105
+
106
+ Notifications are deduplicated per `thread:message:status:reason` tuple, so passing an inline config object does not produce duplicate fires. `ringBell` and `sendOSCNotification(title, body?, variant?)` are also exported for imperative use. OSC support depends on the terminal emulator.
107
+
63
108
  ## Runtime Hooks
64
109
 
65
110
  ### useLocalRuntime
@@ -108,52 +153,47 @@ const runtime = useRemoteThreadListRuntime({
108
153
 
109
154
  ## Model Context Hooks
110
155
 
111
- ### useAssistantTool
156
+ ### Tools
112
157
 
113
- Register a tool with an optional UI renderer. The tool definition is forwarded to the model, and when the model calls it, the `execute` function runs and the `render` component displays the result.
158
+ Author tools with `defineToolkit`, the same API as on the web ([Defining Tools](/docs/tools/defining-tools)). The tool definition is forwarded to the model; when the model calls it, the `execute` function runs and the `render` component displays the result.
114
159
 
115
- ```tsx
116
- import { useAssistantTool } from "@assistant-ui/react-ink";
117
- import { Text } from "ink";
160
+ <Callout type="info">
161
+ An Ink app runs in a single Node process, so there is no client/server
162
+ boundary to split and no build step. `defineToolkit` from
163
+ `@assistant-ui/react-ink` runs at runtime: import it as a value, with no
164
+ `"use generative"` directive and no `"use client"` inside `execute`.
165
+ </Callout>
118
166
 
119
- useAssistantTool({
120
- toolName: "get_weather",
121
- description: "Get the current weather for a city",
122
- parameters: {
123
- type: "object",
124
- properties: {
125
- city: { type: "string" },
167
+ ```tsx title="weather-toolkit.tsx"
168
+ import { defineToolkit } from "@assistant-ui/react-ink";
169
+ import { Text } from "ink";
170
+ import { z } from "zod";
171
+
172
+ export default defineToolkit({
173
+ get_weather: {
174
+ description: "Get the current weather for a city",
175
+ parameters: z.object({ city: z.string() }),
176
+ execute: async ({ city }) => {
177
+ const res = await fetch(`https://api.weather.example/${city}`);
178
+ return res.json();
126
179
  },
127
- required: ["city"],
180
+ render: ({ args, result }) => (
181
+ <Text>
182
+ {args.city}: {result?.temperature}°F
183
+ </Text>
184
+ ),
128
185
  },
129
- execute: async ({ city }) => {
130
- const res = await fetch(`https://api.weather.example/${city}`);
131
- return res.json();
132
- },
133
- render: ({ args, result }) => (
134
- <Text>{args.city}: {result?.temperature}°F</Text>
135
- ),
136
186
  });
137
187
  ```
138
188
 
139
- ### useAssistantToolUI
140
-
141
- Register only a UI renderer for a tool (without tool definition or execute function).
142
-
143
- ```tsx
144
- import { useAssistantToolUI } from "@assistant-ui/react-ink";
145
- import { Text } from "ink";
189
+ ```tsx title="ToolProvider.tsx"
190
+ import { AuiProvider, Tools, useAui } from "@assistant-ui/react-ink";
191
+ import toolkit from "./weather-toolkit";
146
192
 
147
- useAssistantToolUI({
148
- toolName: "get_weather",
149
- render: ({ args, result, status }) => (
150
- <Text>
151
- {status?.type === "running"
152
- ? `Loading weather for ${args.city}...`
153
- : `${args.city}: ${result?.temperature}°F`}
154
- </Text>
155
- ),
156
- });
193
+ function ToolProvider({ children }: { children: React.ReactNode }) {
194
+ const aui = useAui({ tools: Tools({ toolkit }) });
195
+ return <AuiProvider value={aui}>{children}</AuiProvider>;
196
+ }
157
197
  ```
158
198
 
159
199
  ### useAssistantInstructions
@@ -181,48 +221,9 @@ useAssistantDataUI({
181
221
  ),
182
222
  });
183
223
  ```
184
- ### makeAssistantTool
185
-
186
- Create a component that registers a tool when mounted.
187
-
188
- ```tsx
189
- import { makeAssistantTool } from "@assistant-ui/react-ink";
190
- import { Text } from "ink";
191
-
192
- const WeatherTool = makeAssistantTool({
193
- toolName: "get_weather",
194
- description: "Get weather",
195
- parameters: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
196
- execute: async ({ city }) => ({ temperature: 72 }),
197
- render: ({ args, result }) => <Text>{args.city}: {result?.temperature}°F</Text>,
198
- });
199
-
200
- // Mount inside AssistantRuntimeProvider to register
201
- <WeatherTool />
202
- ```
203
-
204
- ### makeAssistantToolUI
224
+ ### Dynamic Tool Renderers
205
225
 
206
- Create a component that registers only a tool UI renderer (no tool definition or execute) when mounted.
207
-
208
- ```tsx
209
- import { makeAssistantToolUI } from "@assistant-ui/react-ink";
210
- import { Text } from "ink";
211
-
212
- const WeatherToolUI = makeAssistantToolUI({
213
- toolName: "get_weather",
214
- render: ({ args, result, status }) => (
215
- <Text>
216
- {status?.type === "running"
217
- ? `Loading weather for ${args.city}...`
218
- : `${args.city}: ${result?.temperature}°F`}
219
- </Text>
220
- ),
221
- });
222
-
223
- // Mount inside AssistantRuntimeProvider to register
224
- <WeatherToolUI />
225
- ```
226
+ Use a toolkit with `useInlineRender` when the renderer closes over changing props.
226
227
 
227
228
  ### makeAssistantDataUI
228
229
 
@@ -247,16 +248,31 @@ const WeatherCardUI = makeAssistantDataUI({
247
248
 
248
249
  Wrap a render function component so that it always uses the latest version without re-creating a stable reference. Useful when passing a render prop inline and the function closes over changing state.
249
250
 
250
- ```tsx
251
- import { useInlineRender } from "@assistant-ui/react-ink";
252
-
253
- const render = useInlineRender(({ args, result }) => (
254
- <Text>{args.city}: {result?.temperature}°F</Text>
255
- ));
251
+ ```tsx title="weather-toolkit.tsx"
252
+ import { defineToolkit, useInlineRender } from "@assistant-ui/react-ink";
253
+ import { Text } from "ink";
254
+ import { useMemo } from "react";
256
255
 
257
- useAssistantToolUI({ toolName: "get_weather", render });
256
+ export function useWeatherToolkit() {
257
+ const render = useInlineRender(({ args, result }) => (
258
+ <Text>{args.city}: {result?.temperature}°F</Text>
259
+ ));
260
+
261
+ return useMemo(
262
+ () =>
263
+ defineToolkit({
264
+ get_weather: {
265
+ type: "backend",
266
+ render,
267
+ },
268
+ }),
269
+ [render],
270
+ );
271
+ }
258
272
  ```
259
273
 
274
+ Import the toolkit hook, pass its result to `useAui({ tools: Tools({ toolkit }) })`, and provide the returned `aui` with `AuiProvider`, as shown in the [Tools](#tools) section above.
275
+
260
276
  ## Runtime Providers
261
277
 
262
278
  ### AssistantRuntimeProvider
@@ -9,7 +9,7 @@ If you already have an assistant-ui web app, most of your code transfers directl
9
9
 
10
10
  - **Runtime setup** — `useLocalRuntime`, `ChatModelAdapter`, and all runtime options work identically.
11
11
  - **AI SDK integration** — `@assistant-ui/react-ai-sdk` works with React Ink. Your runtime setup transfers directly.
12
- - **Tool definitions** — `useAssistantTool`, `makeAssistantTool`, and tool UI renderers use the same API.
12
+ - **Tool definitions** — `Tools({ toolkit })` and toolkit renderers use the same API.
13
13
  - **State hooks** — `useAuiState`, `useAui`, and selector patterns are the same.
14
14
  - **Backend code** — Your API routes, streaming endpoints, and server-side logic need zero changes.
15
15
 
@@ -475,7 +475,7 @@ Container `Box` for a single message.
475
475
 
476
476
  ### Parts
477
477
 
478
- Renders message content parts via a `components` prop. Tool call and data parts automatically render registered tool UIs (via `useAssistantTool` / `useAssistantDataUI`), falling back to components provided here. Default terminal-safe renderers are provided for text, reasoning, source, image, file, and data parts.
478
+ Renders message content parts via a `components` prop. Tool call and data parts automatically render registered toolkit renderers and data UIs (via `useAssistantDataUI`), falling back to components provided here. Default terminal-safe renderers are provided for text, reasoning, source, image, file, and data parts.
479
479
 
480
480
  ```tsx
481
481
  <MessagePrimitive.Parts>
@@ -509,7 +509,7 @@ Override part rendering with app-owned components when you need richer terminal
509
509
  Deprecated. Use `MessagePrimitive.Parts` instead. See the [v0.11 migration guide](/docs/migrations/v0-11) for details.
510
510
  </Callout>
511
511
 
512
- Renders message content parts using render props. Tool call and data parts automatically render registered tool UIs (via `useAssistantTool` / `useAssistantDataUI`), falling back to render props if provided.
512
+ Renders message content parts using render props. Tool call and data parts automatically render registered toolkit renderers and data UIs (via `useAssistantDataUI`), falling back to render props if provided.
513
513
 
514
514
  ```tsx
515
515
  <MessagePrimitive.Content
@@ -52,7 +52,7 @@ Three versions of `ai` are supported. New projects should pick **v6**; v5 and v4
52
52
  AI SDK is the default choice for new projects on Next.js, Remix, or any framework with a Node-compatible API route. Pick it when:
53
53
 
54
54
  - You want a single direct path from the chat UI to your model with the smallest possible code surface.
55
- - You will compose with a framework like [Mastra](/docs/integrations/frameworks/mastra/overview), an [observability tool](/docs/integrations/observability/helicone), an [LLM gateway](/docs/integrations/gateways), or [tools through MCP](/docs/integrations/tools/mcp), all of which assume an AI SDK route.
55
+ - You will compose with a framework like [Mastra](/docs/integrations/frameworks/mastra/overview), an [observability tool](/docs/integrations/observability/helicone), an [LLM gateway](/docs/integrations/gateways), or [tools through MCP](/docs/tools/mcp), all of which assume an AI SDK route.
56
56
  - You want first-party `frontendTools`, attachments, multi-step tool calls, token-usage metadata, and persisted history via `withFormat`.
57
57
 
58
58
  If you need streaming agent state (subgraph events, generative UI messages), look at [LangGraph](/docs/runtimes/langgraph) instead. If you have a different protocol-shaped backend (A2A, AG-UI, OpenCode), see [pick a runtime](/docs/runtimes/pick-a-runtime).
@@ -60,14 +60,14 @@ Framework integrations that pair with assistant-ui at the API-route layer.
60
60
 
61
61
  ## Tools
62
62
 
63
- Pluggable tool catalogs and protocols.
63
+ Tool catalogs and protocols have their own [Tools](/docs/tools) section.
64
64
 
65
65
  <Cards>
66
66
  <Card
67
67
  icon={<McpIcon width={20} height={20} />}
68
68
  title="Model Context Protocol (MCP)"
69
69
  description="Connect any MCP server as a tool catalog through the AI SDK MCP client."
70
- href="/docs/integrations/tools/mcp"
70
+ href="/docs/tools/mcp"
71
71
  />
72
72
  </Cards>
73
73
 
@@ -65,7 +65,22 @@ export const messages = pgTable(
65
65
  );
66
66
  ```
67
67
 
68
- The four message columns (`id`, `parent_id`, `format`, `content`) are the contract `withFormat` writes against. `format` lets multiple runtimes coexist on one row (e.g., `"aisdk-v6"` from `useChatRuntime`, a different value from another runtime).
68
+ The four message columns (`id`, `parent_id`, `format`, `content`) are the contract `withFormat` writes against. `format` records which adapter encoded the row so multiple runtimes can coexist on one table; `useChatRuntime` sets it from `fmt.format`.
69
+
70
+ <Callout type="warn">
71
+ `content` is not arbitrary JSON. It must be the payload the active format adapter produced via `fmt.encode(item)`, and it is read back through `fmt.decode`; the route handlers below are a pass-through that never inspects it. For `useChatRuntime` (AI SDK v6) a valid stored row looks like:
72
+
73
+ ```json
74
+ {
75
+ "id": "msg_abc",
76
+ "parent_id": null,
77
+ "format": "ai-sdk/v6",
78
+ "content": { "role": "user", "parts": [{ "type": "text", "text": "hello" }] }
79
+ }
80
+ ```
81
+
82
+ A row that satisfies the column types but carries a different shape (e.g. `{ "foo": "bar" }`) is accepted on write, then fails history reload. Seed test data through the adapter, not by hand-crafting `content`.
83
+ </Callout>
69
84
 
70
85
  ## Setup
71
86
 
@@ -678,7 +693,7 @@ Send a message in a fresh thread. Check the database:
678
693
 
679
694
  - The `threads` table has a new row with the current `userId`.
680
695
  - The `messages` table has at least two rows (user + assistant) for that thread.
681
- - `format` is `"aisdk-v6"` (or whatever AI SDK's current format string is).
696
+ - `format` matches what `fmt.format` wrote (`"ai-sdk/v6"` for AI SDK v6) and `content` is the encoded `UIMessage` (a `role` plus `parts`), not a placeholder blob.
682
697
  - Reload the page; the thread list and the messages survive.
683
698
 
684
699
  </Step>
@@ -0,0 +1,232 @@
1
+ ---
2
+ title: Migrating Tools to Toolkits
3
+ description: Move makeAssistantTool, useAssistantTool, makeAssistantToolUI, and useAssistantToolUI registrations to the toolkit API.
4
+ ---
5
+
6
+ The component and hook based tool APIs are deprecated:
7
+
8
+ - `makeAssistantTool`
9
+ - `useAssistantTool`
10
+ - `makeAssistantToolUI`
11
+ - `useAssistantToolUI`
12
+
13
+ Use a toolkit registered with `Tools({ toolkit })` instead. Toolkits keep the model contract, browser execution, and tool-call rendering in one named map, which avoids duplicate registrations and makes the client/backend split explicit.
14
+
15
+ ## Before
16
+
17
+ ```tsx
18
+ import { AssistantRuntimeProvider, makeAssistantTool } from "@assistant-ui/react";
19
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
20
+ import { z } from "zod";
21
+
22
+ const WeatherTool = makeAssistantTool({
23
+ toolName: "get_weather",
24
+ description: "Get the current weather for a city.",
25
+ parameters: z.object({
26
+ city: z.string(),
27
+ }),
28
+ execute: async ({ city }) => fetchWeather(city),
29
+ render: ({ args, result }) => (
30
+ <WeatherCard city={args.city} weather={result} />
31
+ ),
32
+ });
33
+
34
+ export function App() {
35
+ const runtime = useChatRuntime({ api: "/api/chat" });
36
+
37
+ return (
38
+ <AssistantRuntimeProvider runtime={runtime}>
39
+ <WeatherTool />
40
+ <Thread />
41
+ </AssistantRuntimeProvider>
42
+ );
43
+ }
44
+ ```
45
+
46
+ ## After
47
+
48
+ ```tsx title="app/toolkit.tsx"
49
+ "use generative";
50
+
51
+ import { defineToolkit } from "@assistant-ui/react";
52
+ import { z } from "zod";
53
+
54
+ export default defineToolkit({
55
+ get_weather: {
56
+ description: "Get the current weather for a city.",
57
+ parameters: z.object({
58
+ city: z.string(),
59
+ }),
60
+ execute: async ({ city }) => {
61
+ "use client";
62
+ return fetchWeather(city);
63
+ },
64
+ render: ({ args, result }) => (
65
+ <WeatherCard city={args.city} weather={result} />
66
+ ),
67
+ },
68
+ });
69
+ ```
70
+
71
+ ```tsx title="app/MyRuntimeProvider.tsx"
72
+ "use client";
73
+
74
+ import {
75
+ AssistantRuntimeProvider,
76
+ Tools,
77
+ useAui,
78
+ } from "@assistant-ui/react";
79
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
80
+ import toolkit from "./toolkit";
81
+
82
+ export function App() {
83
+ const runtime = useChatRuntime({ api: "/api/chat" });
84
+ const aui = useAui({
85
+ tools: Tools({ toolkit }),
86
+ });
87
+
88
+ return (
89
+ <AssistantRuntimeProvider aui={aui} runtime={runtime}>
90
+ <Thread />
91
+ </AssistantRuntimeProvider>
92
+ );
93
+ }
94
+ ```
95
+
96
+ ## Mechanical Steps
97
+
98
+ 1. Create a `Toolkit` object.
99
+ 2. Move each `toolName` into the toolkit key.
100
+ 3. Move `description`, `parameters`, `execute`, `providerOptions`, `render`, `renderText`, and `display` onto the toolkit entry.
101
+ 4. Register the toolkit once with `useAui({ tools: Tools({ toolkit }) })`.
102
+ 5. Remove `<Tool />`, `<ToolUI />`, `useAssistantTool(...)`, and `useAssistantToolUI(...)` registrations.
103
+
104
+ ## UI-Only Tool Renderers
105
+
106
+ If you used `makeAssistantToolUI` or `useAssistantToolUI` for a backend, MCP, or
107
+ LangGraph tool, the tool executes elsewhere. Prefer a `"use generative"` toolkit
108
+ with `execute: externalTool()` so the compiler omits the server entry, while the
109
+ client keeps your renderer as `type: "backend"`:
110
+
111
+ ```tsx
112
+ // app/toolkit.tsx
113
+ "use generative";
114
+
115
+ import { defineToolkit, externalTool } from "@assistant-ui/react";
116
+
117
+ export default defineToolkit({
118
+ web_search: {
119
+ execute: externalTool(),
120
+ render: ({ args, result }) => (
121
+ <SearchResults query={args.query} results={result?.results ?? []} />
122
+ ),
123
+ },
124
+ });
125
+ ```
126
+
127
+ Register it like any toolkit: `useAui({ tools: Tools({ toolkit }) })`.
128
+ Render-only entries upload no schema and run no browser code — they only attach
129
+ UI for matching tool-call message parts. For MCP server catalogs, spread
130
+ `defineMcpToolkit({ ... })` in the same generative toolkit.
131
+
132
+ For a one-off renderer that should only affect a particular message surface, use `MessagePrimitive.Parts` inline tool render overrides instead of a global registration.
133
+
134
+ ## Dynamic Tools
135
+
136
+ If a tool needs component state or props, keep the toolkit contract in a `"use generative"` file and use `stubTool()` for the executor. The component that owns the state supplies the real executor with `useAuiToolOverrides(...)`:
137
+
138
+ <Callout type="warn">
139
+ `useAuiToolOverrides` is experimental and its API may change.
140
+ </Callout>
141
+
142
+ ```tsx title="task-board-toolkit.tsx"
143
+ "use generative";
144
+
145
+ import { defineToolkit, stubTool } from "@assistant-ui/react";
146
+ import { z } from "zod";
147
+
148
+ export type Task = { id: string; title: string };
149
+
150
+ export default defineToolkit({
151
+ add_task: {
152
+ description: "Add a task to the board.",
153
+ parameters: z.object({ title: z.string() }),
154
+ execute: stubTool(),
155
+ renderText: {
156
+ running: "Adding task",
157
+ complete: "Task added",
158
+ },
159
+ },
160
+ });
161
+ ```
162
+
163
+ ```tsx title="TaskBoard.tsx"
164
+ import { AuiProvider, Tools, useAui, useAuiToolOverrides } from "@assistant-ui/react";
165
+ import { useState, type Dispatch, type SetStateAction } from "react";
166
+ import type { Task } from "./task-board-toolkit";
167
+ import toolkit from "./task-board-toolkit";
168
+
169
+ function TaskBoard() {
170
+ const [tasks, setTasks] = useState<Task[]>([]);
171
+
172
+ const aui = useAui({
173
+ tools: Tools({ toolkit }),
174
+ });
175
+
176
+ return (
177
+ <AuiProvider value={aui}>
178
+ <TaskBoardToolOverrides setTasks={setTasks} />
179
+ <TaskList tasks={tasks} />
180
+ </AuiProvider>
181
+ );
182
+ }
183
+
184
+ function TaskBoardToolOverrides({
185
+ setTasks,
186
+ }: {
187
+ setTasks: Dispatch<SetStateAction<Task[]>>;
188
+ }) {
189
+ useAuiToolOverrides({
190
+ add_task: {
191
+ execute: async ({ title }) => {
192
+ setTasks((prev) => [
193
+ ...prev,
194
+ { id: crypto.randomUUID(), title },
195
+ ]);
196
+ return { ok: true };
197
+ },
198
+ },
199
+ });
200
+ return null;
201
+ }
202
+ ```
203
+
204
+ This keeps the model-facing contract in the toolkit file while the component owns the stateful executor.
205
+
206
+ ## Generative Toolkits
207
+
208
+ For tools authored in a `"use generative"` file, export a toolkit with `defineToolkit(...)`. The compiler splits backend, frontend, and human tools for you. This is the default shape to use for docs and copy-paste examples:
209
+
210
+ ```tsx
211
+ "use generative";
212
+
213
+ import { defineToolkit } from "@assistant-ui/react";
214
+ import { z } from "zod";
215
+
216
+ export default defineToolkit({
217
+ create_chart: {
218
+ description: "Create a chart for the user.",
219
+ parameters: z.object({
220
+ title: z.string(),
221
+ values: z.array(z.number()),
222
+ }),
223
+ execute: async ({ title, values }) => {
224
+ "use client";
225
+ return renderChart(title, values);
226
+ },
227
+ render: ChartTool,
228
+ },
229
+ });
230
+ ```
231
+
232
+ Frontend and human tools produced by the generative compiler already have their schema defaults on the backend, so the client no longer re-uploads those schemas.
@@ -22,19 +22,16 @@ For new grouped reasoning/tool-call UI, use `MessagePrimitive.GroupedParts`. `Ch
22
22
  </Tab>
23
23
  <Tab>
24
24
  ```tsx
25
- import { MessagePrimitive } from "@assistant-ui/react";
25
+ import { MessagePrimitive, groupPartByType } from "@assistant-ui/react";
26
26
 
27
27
  function AssistantMessage() {
28
28
  return (
29
29
  <MessagePrimitive.Root>
30
30
  <MessagePrimitive.GroupedParts
31
- groupBy={(part) => {
32
- if (part.type === "reasoning")
33
- return ["group-chainOfThought", "group-reasoning"];
34
- if (part.type === "tool-call")
35
- return ["group-chainOfThought", "group-tool"];
36
- return null;
37
- }}
31
+ groupBy={groupPartByType({
32
+ reasoning: ["group-chainOfThought", "group-reasoning"],
33
+ "tool-call": ["group-chainOfThought", "group-tool"],
34
+ })}
38
35
  >
39
36
  {({ part, children }) => {
40
37
  switch (part.type) {
@@ -67,17 +64,14 @@ function AssistantMessage() {
67
64
  Group reasoning and tool-call parts directly in your assistant message:
68
65
 
69
66
  ```tsx
70
- import { MessagePrimitive } from "@assistant-ui/react";
67
+ import { MessagePrimitive, groupPartByType } from "@assistant-ui/react";
71
68
 
72
69
  <MessagePrimitive.Root>
73
70
  <MessagePrimitive.GroupedParts
74
- groupBy={(part) => {
75
- if (part.type === "reasoning")
76
- return ["group-chainOfThought", "group-reasoning"];
77
- if (part.type === "tool-call")
78
- return ["group-chainOfThought", "group-tool"];
79
- return null;
80
- }}
71
+ groupBy={groupPartByType({
72
+ reasoning: ["group-chainOfThought", "group-reasoning"],
73
+ "tool-call": ["group-chainOfThought", "group-tool"],
74
+ })}
81
75
  >
82
76
  {({ part, children }) => {
83
77
  switch (part.type) {