@assistant-ui/mcp-docs-server 0.1.36 → 0.1.39

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 (246) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -9
  2. package/.docs/organized/code-examples/with-a2a.md +16 -11
  3. package/.docs/organized/code-examples/with-ag-ui.md +16 -11
  4. package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +32 -21
  5. package/.docs/organized/code-examples/with-artifacts.md +17 -10
  6. package/.docs/organized/code-examples/with-assistant-transport.md +15 -8
  7. package/.docs/organized/code-examples/with-browser-extension.md +15 -8
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +17 -10
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -9
  10. package/.docs/organized/code-examples/with-cloud.md +18 -13
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +17 -10
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +20 -13
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +20 -13
  14. package/.docs/organized/code-examples/with-eve.md +16 -9
  15. package/.docs/organized/code-examples/with-expo.md +26 -23
  16. package/.docs/organized/code-examples/with-external-store.md +16 -11
  17. package/.docs/organized/code-examples/with-ffmpeg.md +18 -13
  18. package/.docs/organized/code-examples/with-generative-ui.md +20 -15
  19. package/.docs/organized/code-examples/with-google-adk.md +16 -9
  20. package/.docs/organized/code-examples/with-heat-graph.md +8 -9
  21. package/.docs/organized/code-examples/with-image-generation.md +17 -10
  22. package/.docs/organized/code-examples/with-interactables.md +19 -15
  23. package/.docs/organized/code-examples/with-langchain.md +17 -10
  24. package/.docs/organized/code-examples/with-langgraph.md +17 -10
  25. package/.docs/organized/code-examples/with-livekit.md +21 -14
  26. package/.docs/organized/code-examples/with-mcp.md +40 -18
  27. package/.docs/organized/code-examples/with-opencode.md +22 -17
  28. package/.docs/organized/code-examples/with-pi.md +47 -12
  29. package/.docs/organized/code-examples/with-react-hook-form.md +19 -14
  30. package/.docs/organized/code-examples/with-react-ink-web.md +6 -6
  31. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  32. package/.docs/organized/code-examples/with-react-router.md +20 -15
  33. package/.docs/organized/code-examples/with-resumable-stream.md +19 -12
  34. package/.docs/organized/code-examples/with-store.md +8 -9
  35. package/.docs/organized/code-examples/with-tanstack.md +17 -11
  36. package/.docs/organized/code-examples/with-tap-runtime.md +16 -11
  37. package/.docs/organized/code-examples/with-virtualized-thread.md +17 -12
  38. package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
  39. package/.docs/raw/docs/(docs)/cli.mdx +18 -2
  40. package/.docs/raw/docs/(docs)/installation.mdx +15 -1
  41. package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
  42. package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
  43. package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
  44. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +19 -1
  45. package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
  46. package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
  47. package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
  48. package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
  49. package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
  50. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
  51. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +4 -2
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
  53. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
  54. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +29 -29
  55. package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
  58. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
  59. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
  60. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
  61. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
  62. package/.docs/raw/docs/cloud/langgraph.mdx +4 -2
  63. package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
  64. package/.docs/raw/docs/guides/dictation.mdx +185 -257
  65. package/.docs/raw/docs/guides/index.mdx +10 -0
  66. package/.docs/raw/docs/guides/mentions.mdx +31 -3
  67. package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
  68. package/.docs/raw/docs/guides/speech.mdx +47 -29
  69. package/.docs/raw/docs/guides/suggestions.mdx +70 -1
  70. package/.docs/raw/docs/guides/voice.mdx +197 -267
  71. package/.docs/raw/docs/ink/primitives.mdx +35 -1
  72. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +13 -7
  73. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
  74. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
  75. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
  76. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
  77. package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
  78. package/.docs/raw/docs/integrations/index.mdx +1 -1
  79. package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
  80. package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
  81. package/.docs/raw/docs/integrations/observability/langsmith.mdx +3 -3
  82. package/.docs/raw/docs/migrations/index.mdx +50 -0
  83. package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +2 -2
  84. package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
  85. package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
  86. package/.docs/raw/docs/primitives/composer.mdx +16 -0
  87. package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
  88. package/.docs/raw/docs/primitives/thread-list.mdx +30 -6
  89. package/.docs/raw/docs/react-native/primitives.mdx +23 -0
  90. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +1 -1
  91. package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
  92. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +1 -1
  93. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +13 -2
  94. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +13 -4
  95. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +11 -11
  96. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
  97. package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +8 -6
  98. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
  99. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
  100. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
  101. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
  102. package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
  103. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +2 -0
  104. package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
  105. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +1 -1
  106. package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
  107. package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
  108. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +1 -1
  109. package/.docs/raw/docs/tools/backend.mdx +6 -3
  110. package/.docs/raw/docs/tools/defining-tools.mdx +12 -1
  111. package/.docs/raw/docs/tools/generative-ui.mdx +95 -0
  112. package/.docs/raw/docs/tools/mcp-apps.mdx +37 -10
  113. package/.docs/raw/docs/tools/mcp.mdx +105 -3
  114. package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
  115. package/.docs/raw/docs/tools/user-managed-mcp.mdx +41 -4
  116. package/.docs/raw/docs/ui/accordion.mdx +16 -10
  117. package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
  118. package/.docs/raw/docs/ui/attachment.mdx +5 -1
  119. package/.docs/raw/docs/ui/badge.mdx +23 -12
  120. package/.docs/raw/docs/ui/follow-up-suggestions.mdx +80 -0
  121. package/.docs/raw/docs/ui/model-selector.mdx +69 -6
  122. package/.docs/raw/docs/ui/select.mdx +22 -14
  123. package/.docs/raw/docs/ui/sources.mdx +1 -1
  124. package/.docs/raw/docs/ui/tabs.mdx +25 -14
  125. package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
  126. package/README.md +1 -1
  127. package/dist/constants.d.ts +2 -1
  128. package/dist/constants.d.ts.map +1 -1
  129. package/dist/constants.js +2 -1
  130. package/dist/constants.js.map +1 -1
  131. package/dist/index.d.ts +0 -1
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +51 -0
  134. package/dist/index.js.map +1 -1
  135. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  136. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  137. package/dist/prepare-docs/copy-raw.js +0 -4
  138. package/dist/prepare-docs/copy-raw.js.map +1 -1
  139. package/dist/prompts/xulux-playground.d.ts +12 -0
  140. package/dist/prompts/xulux-playground.d.ts.map +1 -0
  141. package/dist/prompts/xulux-playground.js +33 -0
  142. package/dist/prompts/xulux-playground.js.map +1 -0
  143. package/dist/tools/docs.d.ts +2 -4
  144. package/dist/tools/docs.d.ts.map +1 -1
  145. package/dist/tools/docs.js +38 -10
  146. package/dist/tools/docs.js.map +1 -1
  147. package/dist/tools/examples.d.ts +5 -5
  148. package/dist/tools/examples.d.ts.map +1 -1
  149. package/dist/tools/examples.js +10 -7
  150. package/dist/tools/examples.js.map +1 -1
  151. package/dist/tools/resources.d.ts +6 -0
  152. package/dist/tools/resources.d.ts.map +1 -0
  153. package/dist/tools/resources.js +74 -0
  154. package/dist/tools/resources.js.map +1 -0
  155. package/dist/tools/search.d.ts +30 -0
  156. package/dist/tools/search.d.ts.map +1 -0
  157. package/dist/tools/search.js +39 -0
  158. package/dist/tools/search.js.map +1 -0
  159. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  160. package/dist/tools/tests/test-setup.js +7 -1
  161. package/dist/tools/tests/test-setup.js.map +1 -1
  162. package/dist/tools/xulux-templates.d.ts +72 -0
  163. package/dist/tools/xulux-templates.d.ts.map +1 -0
  164. package/dist/tools/xulux-templates.js +82 -0
  165. package/dist/tools/xulux-templates.js.map +1 -0
  166. package/dist/utils/cache.d.ts +5 -0
  167. package/dist/utils/cache.d.ts.map +1 -0
  168. package/dist/utils/cache.js +18 -0
  169. package/dist/utils/cache.js.map +1 -0
  170. package/dist/utils/logger.d.ts.map +1 -1
  171. package/dist/utils/mcp-format.d.ts +1 -0
  172. package/dist/utils/mcp-format.d.ts.map +1 -1
  173. package/dist/utils/mcp-format.js +7 -4
  174. package/dist/utils/mcp-format.js.map +1 -1
  175. package/dist/utils/mdx.d.ts +2 -1
  176. package/dist/utils/mdx.d.ts.map +1 -1
  177. package/dist/utils/mdx.js +19 -2
  178. package/dist/utils/mdx.js.map +1 -1
  179. package/dist/utils/paths.d.ts +2 -1
  180. package/dist/utils/paths.d.ts.map +1 -1
  181. package/dist/utils/paths.js +20 -1
  182. package/dist/utils/paths.js.map +1 -1
  183. package/dist/utils/search.d.ts +10 -0
  184. package/dist/utils/search.d.ts.map +1 -0
  185. package/dist/utils/search.js +97 -0
  186. package/dist/utils/search.js.map +1 -0
  187. package/dist/utils/security.d.ts.map +1 -1
  188. package/dist/xulux/catalog-client.d.ts +14 -0
  189. package/dist/xulux/catalog-client.d.ts.map +1 -0
  190. package/dist/xulux/catalog-client.js +67 -0
  191. package/dist/xulux/catalog-client.js.map +1 -0
  192. package/dist/xulux/fallback-catalog.d.ts +7 -0
  193. package/dist/xulux/fallback-catalog.d.ts.map +1 -0
  194. package/dist/xulux/fallback-catalog.js +47 -0
  195. package/dist/xulux/fallback-catalog.js.map +1 -0
  196. package/dist/xulux/fetch-sandbox.d.ts +5 -0
  197. package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
  198. package/dist/xulux/fetch-sandbox.js +40 -0
  199. package/dist/xulux/fetch-sandbox.js.map +1 -0
  200. package/dist/xulux/template-service.d.ts +84 -0
  201. package/dist/xulux/template-service.d.ts.map +1 -0
  202. package/dist/xulux/template-service.js +223 -0
  203. package/dist/xulux/template-service.js.map +1 -0
  204. package/dist/xulux/types.d.ts +55 -0
  205. package/dist/xulux/types.d.ts.map +1 -0
  206. package/dist/xulux/types.js +6 -0
  207. package/dist/xulux/types.js.map +1 -0
  208. package/package.json +5 -5
  209. package/src/constants.ts +2 -0
  210. package/src/index.ts +67 -0
  211. package/src/prepare-docs/copy-raw.ts +0 -5
  212. package/src/prompts/xulux-playground.ts +36 -0
  213. package/src/tools/docs.ts +52 -4
  214. package/src/tools/examples.ts +18 -11
  215. package/src/tools/resources.ts +114 -0
  216. package/src/tools/search.ts +46 -0
  217. package/src/tools/tests/completions.test.ts +46 -0
  218. package/src/tools/tests/directory-size-cap.test.ts +50 -0
  219. package/src/tools/tests/docs.test.ts +20 -0
  220. package/src/tools/tests/examples.test.ts +5 -5
  221. package/src/tools/tests/listings-cache.test.ts +19 -0
  222. package/src/tools/tests/mcp-protocol.test.ts +92 -1
  223. package/src/tools/tests/resources.test.ts +102 -0
  224. package/src/tools/tests/search.test.ts +37 -0
  225. package/src/tools/tests/test-setup.ts +10 -0
  226. package/src/tools/tests/xulux-templates.test.ts +262 -0
  227. package/src/tools/xulux-templates.ts +141 -0
  228. package/src/utils/cache.ts +20 -0
  229. package/src/utils/mcp-format.ts +8 -6
  230. package/src/utils/mdx.ts +21 -1
  231. package/src/utils/paths.ts +25 -0
  232. package/src/utils/search.ts +131 -0
  233. package/src/utils/tests/cache.test.ts +51 -0
  234. package/src/utils/tests/mcp-format.test.ts +22 -0
  235. package/src/utils/tests/security.test.ts +1 -1
  236. package/src/xulux/catalog-client.ts +105 -0
  237. package/src/xulux/fallback-catalog.ts +63 -0
  238. package/src/xulux/fetch-sandbox.ts +56 -0
  239. package/src/xulux/template-service.ts +406 -0
  240. package/src/xulux/types.ts +60 -0
  241. package/.docs/raw/blog/2024-07-29-hello/index.mdx +0 -64
  242. package/.docs/raw/blog/2024-09-11/index.mdx +0 -10
  243. package/.docs/raw/blog/2024-12-15/index.mdx +0 -10
  244. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +0 -127
  245. package/.docs/raw/blog/2026-03-launch-week/index.mdx +0 -258
  246. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
@@ -81,7 +81,8 @@ const mcpClient = await createMCPClient({
81
81
 
82
82
  In a generative toolkit, spread `defineMcpToolkit({ ... })` with one entry per
83
83
  MCP server. The entry key names the server connection; the MCP server publishes
84
- the actual tool names.
84
+ the actual tool names. Use a readable key because it appears in connection,
85
+ tool-listing, and close errors for debugging.
85
86
 
86
87
  ```tsx title="app/toolkit.tsx"
87
88
  "use generative";
@@ -93,14 +94,75 @@ export default defineToolkit({
93
94
  github: {
94
95
  type: "http",
95
96
  url: "https://mcp.example.com/mcp",
97
+ connectionTimeout: 10_000,
96
98
  },
97
99
  }),
98
100
  });
99
101
  ```
100
102
 
103
+ Use `{ server, disabled }` when a whole MCP server should stay configured but
104
+ not expose tools for the current request, such as missing credentials, feature
105
+ flags, or plan gating:
106
+
107
+ ```tsx
108
+ defineMcpToolkit({
109
+ docs: {
110
+ server: {
111
+ type: "http",
112
+ url: process.env.DOCS_MCP_URL!,
113
+ },
114
+ disabled: !process.env.DOCS_MCP_URL,
115
+ },
116
+ });
117
+ ```
118
+
119
+ Use `tools` when the server should stay enabled but specific MCP tools should
120
+ be hidden from the model:
121
+
122
+ ```tsx
123
+ defineMcpToolkit({
124
+ docs: {
125
+ server: {
126
+ type: "http",
127
+ url: process.env.DOCS_MCP_URL!,
128
+ },
129
+ tools: {
130
+ deleteDocument: {
131
+ disabled: !userCanDelete,
132
+ },
133
+ },
134
+ },
135
+ });
136
+ ```
137
+
138
+ If multiple MCP servers expose the same tool name, wrap the entry with
139
+ `{ server, prefix }` to give each server's tools distinct model-visible names:
140
+
141
+ ```tsx
142
+ export default defineToolkit({
143
+ ...defineMcpToolkit({
144
+ docs: {
145
+ server: { type: "http", url: "https://docs.example.com/mcp" },
146
+ prefix: "docs_",
147
+ },
148
+ github: {
149
+ server: { type: "http", url: "https://github.example.com/mcp" },
150
+ prefix: "github_",
151
+ },
152
+ }),
153
+ });
154
+ ```
155
+
156
+ If both servers publish `search`, the model receives `docs_search` and
157
+ `github_search` instead of an ambiguous duplicate.
158
+
101
159
  Use `AISDKToolkit` in the route. It opens the MCP clients, merges their tools
102
160
  with the rest of your toolkit, and closes them when you call `close()`:
103
161
 
162
+ `connectionTimeout` is optional and measured in milliseconds. Set it to fail
163
+ the server-side MCP readiness flow (`createMCPClient()` plus `tools()`) before
164
+ a bad URL or hanging local process can stall the route.
165
+
104
166
  ```ts title="app/api/chat/route.ts"
105
167
  import { AISDKToolkit } from "@assistant-ui/react-ai-sdk";
106
168
  import { openai } from "@ai-sdk/openai";
@@ -314,7 +376,7 @@ import type { ReactNode } from "react";
314
376
  import { toolkit } from "./GitHubIssueToolUI";
315
377
 
316
378
  export function MyRuntimeProvider({ children }: { children: ReactNode }) {
317
- const runtime = useChatRuntime({ api: "/api/chat" });
379
+ const runtime = useChatRuntime();
318
380
  const aui = useAui({ tools: Tools({ toolkit }) });
319
381
 
320
382
  return (
@@ -325,6 +387,46 @@ export function MyRuntimeProvider({ children }: { children: ReactNode }) {
325
387
  }
326
388
  ```
327
389
 
390
+ `useChatRuntime()` targets `/api/chat` by default. To point at a different endpoint or customize requests, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
391
+
392
+ </Step>
393
+ <Step>
394
+
395
+ ### Require approval before an MCP tool runs
396
+
397
+ MCP tools execute on the server, so approval is a server-side tool gate, not a `humanTool()` result. Gate the call with AI SDK v7's call-level `toolApproval` option, keyed by the tool's model-visible name. The tool name stays the same, so your custom renderer or the default `ToolFallback` receives `approval` and `respondToApproval` like any other backend tool:
398
+
399
+ ```ts title="app/api/chat/route.ts"
400
+ const tools = await mcpClient.tools();
401
+
402
+ const result = streamText({
403
+ model: openai("gpt-5.4-mini"),
404
+ messages: await convertToModelMessages(messages),
405
+ tools,
406
+ toolApproval: {
407
+ github_delete_repository: "user-approval",
408
+ },
409
+ onFinish: async () => {
410
+ await mcpClient.close();
411
+ },
412
+ });
413
+ ```
414
+
415
+ With `AISDKToolkit`, pass the same `toolApproval` option alongside the tools returned by `await aiToolkit.tools(...)`; key it by the prefixed name when the entry sets one.
416
+
417
+ On the client, let the AI SDK send the recorded approval decision back to the
418
+ route:
419
+
420
+ ```tsx title="app/components/RuntimeProvider.tsx"
421
+ import { lastAssistantMessageIsCompleteWithApprovalResponses } from "ai";
422
+
423
+ const runtime = useChatRuntime({
424
+ sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
425
+ });
426
+ ```
427
+
428
+ Use this pattern for backend-owned actions such as deleting, writing, deploying, or calling privileged MCP tools. Use `humanTool()` only when the user supplies the tool result itself. For custom approval UIs, see [Server-side approval gates](/docs/tools/tool-ui#server-side-approval-gates); for the full wire setup, see [Server-side tool approval](/docs/runtimes/ai-sdk/v7#server-side-tool-approval).
429
+
328
430
  </Step>
329
431
  <Step>
330
432
 
@@ -352,7 +454,7 @@ Start the app and trigger a tool call (e.g., ask the assistant to do something t
352
454
  <Card
353
455
  title="AI SDK runtime"
354
456
  description="The runtime that ferries MCP tool calls to the chat UI."
355
- href="/docs/runtimes/ai-sdk/v6"
457
+ href="/docs/runtimes/ai-sdk/v7"
356
458
  />
357
459
  <Card
358
460
  title="Tools and tool UI"
@@ -74,7 +74,7 @@ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
74
74
  import toolkit from "./toolkit";
75
75
 
76
76
  function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
77
- const runtime = useChatRuntime({ api: "/api/chat" });
77
+ const runtime = useChatRuntime();
78
78
  const aui = useAui({ tools: Tools({ toolkit }) });
79
79
  return (
80
80
  <AssistantRuntimeProvider aui={aui} runtime={runtime}>
@@ -84,6 +84,8 @@ function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
84
84
  }
85
85
  ```
86
86
 
87
+ `useChatRuntime()` targets `/api/chat` by default. To point at a different endpoint or customize requests, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
88
+
87
89
  <Callout type="tip">
88
90
  Frontend toolkit entries can be passed to your backend using the
89
91
  `frontendTools` utility.
@@ -537,7 +539,7 @@ export default defineToolkit({
537
539
 
538
540
  ### Server-side approval gates
539
541
 
540
- Some runtimes (notably AI SDK v6's `needsApproval` tools) pause on the server and emit an approval request that the client must acknowledge before the tool runs. assistant-ui surfaces this on the tool part as `approval` and exposes `respondToApproval({ approved, reason? })` on the renderer:
542
+ Some runtimes (notably AI SDK v7's `toolApproval`-gated tools) pause on the server and emit an approval request that the client must acknowledge before the tool runs. assistant-ui surfaces this on the tool part as `approval` and exposes `respondToApproval({ approved, reason? })` on the renderer:
541
543
 
542
544
  ```tsx
543
545
  const toolkit = defineToolkit({
@@ -581,9 +583,9 @@ const toolkit = defineToolkit({
581
583
 
582
584
  `approval.isAutomatic` is `true` when the runtime granted the decision from a server-side policy rather than the user; render a "auto-approved" badge instead of buttons in that case.
583
585
 
584
- Approval gates require a runtime that implements them: the AI SDK v6 runtime emits them for `needsApproval` tools, and `LocalRuntime` supports gates emitted by your `ChatModelAdapter`; see [LocalRuntime approval gates](/docs/runtimes/custom/local-runtime#approval-gates). For tools where the user supplies the result itself, use `unstable_humanToolNames` with `addResult` instead; see [human-in-the-loop tools](/docs/runtimes/custom/local-runtime#human-in-the-loop-tools).
586
+ Approval gates require a runtime that implements them: the AI SDK v7 runtime emits them for `toolApproval`-gated tools, and `LocalRuntime` supports gates emitted by your `ChatModelAdapter`; see [LocalRuntime approval gates](/docs/runtimes/custom/local-runtime#approval-gates). For tools where the user supplies the result itself, use `unstable_humanToolNames` with `addResult` instead; see [human-in-the-loop tools](/docs/runtimes/custom/local-runtime#human-in-the-loop-tools).
585
587
 
586
- For the wire-side setup (`needsApproval`, `sendAutomaticallyWhen`), see [AI SDK v6 server-side tool approval](/docs/runtimes/ai-sdk/v6#server-side-tool-approval).
588
+ For the wire-side setup (`needsApproval`, `sendAutomaticallyWhen`), see [AI SDK v7 server-side tool approval](/docs/runtimes/ai-sdk/v7#server-side-tool-approval).
587
589
 
588
590
  ### Approval options
589
591
 
@@ -59,20 +59,28 @@ const connectors = [
59
59
  name: "Weather",
60
60
  url: "https://mcp.example.com/weather",
61
61
  auth: { type: "none" },
62
+ connectionTimeout: 10_000,
62
63
  }),
63
64
  ];
64
65
 
65
66
  export function Providers({ children }: { children: React.ReactNode }) {
66
- const aui = useAui({ mcp: McpManagerResource({ connectors }) });
67
+ const aui = useAui({
68
+ mcp: McpManagerResource({
69
+ connectors,
70
+ connectionTimeout: 15_000,
71
+ }),
72
+ });
67
73
  return <AuiProvider value={aui}>{children}</AuiProvider>;
68
74
  }
69
75
  ```
70
76
 
71
- Defaults baked in:
77
+ Defaults and useful options:
72
78
 
73
79
  - `storage` — `McpLocalStorage()` (override for production; see [Storage](#storage))
74
80
  - `oauthRedirectUri` — `${window.location.origin}/mcp/callback`
75
81
  - `autoConnect` — `true` (connect on mount when usable auth is persisted)
82
+ - `connectionTimeout` — optional timeout in milliseconds. Set it on the manager as a default or on a connector/custom server to bound the MCP readiness flow (`connect()` plus `listTools()`) with a clear error.
83
+ - Connector `id` values must be unique. The id is used for server lookup, OAuth routing, and model-visible tool names such as `linear__search`.
76
84
 
77
85
  </Step>
78
86
  <Step>
@@ -208,14 +216,19 @@ The callback reads `?state=...&code=...` from the URL, derives the target server
208
216
 
209
217
  ```tsx
210
218
  "use client";
219
+ import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
211
220
  import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
212
221
 
213
222
  export function Chat() {
214
- const runtime = useChatRuntime({ api: "/api/chat" });
223
+ const runtime = useChatRuntime({
224
+ sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
225
+ });
215
226
  /* … */
216
227
  }
217
228
  ```
218
229
 
230
+ `sendAutomaticallyWhen` sends completed frontend tool results back to the server so the model can continue after a tool call. `useChatRuntime()` targets `/api/chat` by default; to point at a different endpoint, see [Custom transport](/docs/runtimes/ai-sdk/v7#custom-transport).
231
+
219
232
  Tool names are prefixed `serverId__toolName` to avoid collisions across connected servers. The toolkit re-registers whenever a server connects / disconnects or its tool list changes.
220
233
 
221
234
  If no chat runtime is mounted, `McpManagerResource` brings its own minimal `modelContext` along. Tools are still callable directly:
@@ -302,6 +315,29 @@ const aui = useAui();
302
315
  await aui.mcp().addCustomServer({ name, url, auth: { type: "bearer", token } });
303
316
  await aui.mcp().server({ id }).connect();
304
317
  await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
318
+
319
+ // Build a paginated resource browser/preview UI.
320
+ type ResourcePage = {
321
+ resources: Array<{ uri: string; name?: string }>;
322
+ nextCursor?: string;
323
+ };
324
+
325
+ const server = aui.mcp().server({ id });
326
+ const resources: ResourcePage["resources"] = [];
327
+ let nextCursor: string | undefined;
328
+
329
+ do {
330
+ const page = (await (nextCursor === undefined
331
+ ? server.listResources()
332
+ : server.listResources({ cursor: nextCursor }))) as ResourcePage;
333
+ resources.push(...page.resources);
334
+ nextCursor = page.nextCursor;
335
+ } while (nextCursor !== undefined);
336
+
337
+ const firstResource = resources[0];
338
+ if (firstResource) {
339
+ const preview = await server.readResource(firstResource.uri);
340
+ }
305
341
  ```
306
342
 
307
343
  ## v1 scope
@@ -309,13 +345,14 @@ await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
309
345
  What ships:
310
346
 
311
347
  - Tool listing and invocation, auto-registered as frontend tools
348
+ - Resource listing and reads for app-built browsers or preview panes
312
349
  - OAuth (PKCE + DCR), bearer, none
313
350
  - StreamableHTTP transport
314
351
  - Manual connect/disconnect
315
352
 
316
353
  What's deferred:
317
354
 
318
- - Resources, prompts, sampling
355
+ - Prompts, sampling
319
356
  - Auto-reconnect with backoff
320
357
  - Per-tool enable/disable persistence
321
358
  - Per-tool consent prompts
@@ -2,8 +2,10 @@
2
2
  title: Accordion
3
3
  description: A vertically stacked set of interactive headings that reveal or hide content sections.
4
4
  links:
5
- - label: Radix UI Accordion
5
+ - label: Radix UI Accordion (Radix styles)
6
6
  url: https://www.radix-ui.com/primitives/docs/components/accordion
7
+ - label: Base UI Accordion (base styles)
8
+ url: https://base-ui.com/react/components/accordion
7
9
  platforms: ["react"]
8
10
  ---
9
11
 
@@ -16,12 +18,16 @@ import {
16
18
  AccordionControlledSample,
17
19
  AccordionFAQSample,
18
20
  } from "@/components/docs/samples/accordion";
21
+ import * as AccordionRadixSamples from "@/components/docs/samples/accordion.radix";
22
+ import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
19
23
 
20
24
  <Callout>
21
25
  This is a **standalone component** that does not depend on the assistant-ui runtime. Use it anywhere in your application.
22
26
  </Callout>
23
27
 
24
- <AccordionSample />
28
+ <FlavorSwitcher />
29
+
30
+ <Flavored radix={<AccordionRadixSamples.AccordionSample />} base={<AccordionSample />} />
25
31
 
26
32
  ## Installation
27
33
 
@@ -59,7 +65,7 @@ export function Example() {
59
65
 
60
66
  Use the `variant` prop on `Accordion` to change the visual style. Child components inherit the variant automatically.
61
67
 
62
- <AccordionVariantsSample />
68
+ <Flavored radix={<AccordionRadixSamples.AccordionVariantsSample />} base={<AccordionVariantsSample />} />
63
69
 
64
70
  ```tsx
65
71
  // Default - border-bottom separator
@@ -91,7 +97,7 @@ Use the `variant` prop on `Accordion` to change the visual style. Child componen
91
97
 
92
98
  Use `type="multiple"` to allow multiple items to be open simultaneously.
93
99
 
94
- <AccordionMultipleSample />
100
+ <Flavored radix={<AccordionRadixSamples.AccordionMultipleSample />} base={<AccordionMultipleSample />} />
95
101
 
96
102
  ```tsx
97
103
  <Accordion type="multiple">
@@ -110,24 +116,24 @@ Use `type="multiple"` to allow multiple items to be open simultaneously.
110
116
 
111
117
  Add icons or custom elements inside the trigger.
112
118
 
113
- <PreviewCode file="components/docs/samples/accordion" name="AccordionWithIconsSample">
114
- <AccordionWithIconsSample />
119
+ <PreviewCode file="components/docs/samples/accordion" name="AccordionWithIconsSample" base={<AccordionWithIconsSample />}>
120
+ <AccordionRadixSamples.AccordionWithIconsSample />
115
121
  </PreviewCode>
116
122
 
117
123
  ### Controlled
118
124
 
119
125
  Use `value` and `onValueChange` for controlled accordion state.
120
126
 
121
- <PreviewCode file="components/docs/samples/accordion" name="AccordionControlledSample">
122
- <AccordionControlledSample />
127
+ <PreviewCode file="components/docs/samples/accordion" name="AccordionControlledSample" base={<AccordionControlledSample />}>
128
+ <AccordionRadixSamples.AccordionControlledSample />
123
129
  </PreviewCode>
124
130
 
125
131
  ### FAQ Section
126
132
 
127
133
  A practical example of using accordion for a FAQ section.
128
134
 
129
- <PreviewCode file="components/docs/samples/accordion" name="AccordionFAQSample">
130
- <AccordionFAQSample />
135
+ <PreviewCode file="components/docs/samples/accordion" name="AccordionFAQSample" base={<AccordionFAQSample />}>
136
+ <AccordionRadixSamples.AccordionFAQSample />
131
137
  </PreviewCode>
132
138
 
133
139
  ## API Reference
@@ -5,10 +5,14 @@ platforms: ["react"]
5
5
  ---
6
6
 
7
7
  import { AssistantModalSample } from "@/components/docs/samples/assistant-modal";
8
+ import * as AssistantModalRadixSamples from "@/components/docs/samples/assistant-modal.radix";
9
+ import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
8
10
 
9
- A floating chat modal built on Radix UI Popover. Ideal for support widgets, help desks, and embedded assistants.
11
+ A floating chat modal built on the popover primitive of your configured style (Radix UI Popover on Radix styles, Base UI Popover on `base-*` styles). Ideal for support widgets, help desks, and embedded assistants.
10
12
 
11
- <AssistantModalSample />
13
+ <FlavorSwitcher />
14
+
15
+ <Flavored radix={<AssistantModalRadixSamples.AssistantModalSample />} base={<AssistantModalSample />} />
12
16
 
13
17
  ## Getting Started
14
18
 
@@ -43,7 +47,7 @@ export default function Home() {
43
47
 
44
48
  ## Anatomy
45
49
 
46
- The `AssistantModal` component is built with the following primitives:
50
+ The Radix flavor of `AssistantModal` is built with the following primitives. The Base UI flavor composes your project's Base UI Popover instead.
47
51
 
48
52
  ```tsx
49
53
  import { AssistantModalPrimitive } from "@assistant-ui/react";
@@ -61,7 +65,7 @@ import { AssistantModalPrimitive } from "@assistant-ui/react";
61
65
 
62
66
  ### Root
63
67
 
64
- Contains all parts of the modal. Based on Radix UI Popover.
68
+ Contains all parts of the modal when using `AssistantModalPrimitive` (the Radix flavor). The Base UI flavor uses your project's Base UI Popover instead.
65
69
 
66
70
  <ParametersTable
67
71
  type="AssistantModalPrimitiveRootProps"
@@ -5,8 +5,12 @@ platforms: ["react"]
5
5
  ---
6
6
 
7
7
  import { AttachmentSample } from "@/components/docs/samples/attachment";
8
+ import * as AttachmentRadixSamples from "@/components/docs/samples/attachment.radix";
9
+ import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
8
10
 
9
- <AttachmentSample />
11
+ <FlavorSwitcher />
12
+
13
+ <Flavored radix={<AttachmentRadixSamples.AttachmentSample />} base={<AttachmentSample />} />
10
14
 
11
15
  <Callout type="info">
12
16
  **Note:** These components provide the UI for attachments, but you also need
@@ -2,8 +2,10 @@
2
2
  title: Badge
3
3
  description: A small label component for displaying status, categories, or metadata.
4
4
  links:
5
- - label: Radix UI Slot
5
+ - label: Radix UI Slot (Radix styles)
6
6
  url: https://www.radix-ui.com/primitives/docs/utilities/slot
7
+ - label: Base UI useRender (base styles)
8
+ url: https://base-ui.com/react/utils/use-render
7
9
  platforms: ["react"]
8
10
  ---
9
11
 
@@ -15,12 +17,16 @@ import {
15
17
  BadgeAsLinkSample,
16
18
  BadgeAnimatedSample,
17
19
  } from "@/components/docs/samples/badge";
20
+ import * as BadgeRadixSamples from "@/components/docs/samples/badge.radix";
21
+ import { Flavored, FlavorSwitcher } from "@/components/docs/contexts/flavor.server";
18
22
 
19
23
  <Callout>
20
24
  This is a **standalone component** that does not depend on the assistant-ui runtime. Use it anywhere in your application.
21
25
  </Callout>
22
26
 
23
- <BadgeSample />
27
+ <FlavorSwitcher />
28
+
29
+ <Flavored radix={<BadgeRadixSamples.BadgeSample />} base={<BadgeSample />} />
24
30
 
25
31
  ## Installation
26
32
 
@@ -42,7 +48,7 @@ export function Example() {
42
48
 
43
49
  Use the `variant` prop to change the visual style.
44
50
 
45
- <BadgeSample />
51
+ <Flavored radix={<BadgeRadixSamples.BadgeSample />} base={<BadgeSample />} />
46
52
 
47
53
  ```tsx
48
54
  <Badge variant="outline" /> // Border (default)
@@ -59,7 +65,7 @@ Use the `variant` prop to change the visual style.
59
65
 
60
66
  Use the `size` prop to change the badge size.
61
67
 
62
- <BadgeSizesSample />
68
+ <Flavored radix={<BadgeRadixSamples.BadgeSizesSample />} base={<BadgeSizesSample />} />
63
69
 
64
70
  ```tsx
65
71
  <Badge size="sm" /> // Small
@@ -71,24 +77,24 @@ Use the `size` prop to change the badge size.
71
77
 
72
78
  Badges automatically style SVG icons.
73
79
 
74
- <PreviewCode file="components/docs/samples/badge" name="BadgeWithIconSample">
75
- <BadgeWithIconSample />
80
+ <PreviewCode file="components/docs/samples/badge" name="BadgeWithIconSample" base={<BadgeWithIconSample />}>
81
+ <BadgeRadixSamples.BadgeWithIconSample />
76
82
  </PreviewCode>
77
83
 
78
84
  ### As Link
79
85
 
80
- Use the `asChild` prop to render the badge as a different element, like a link.
86
+ Compose with `render` (Base UI) or `asChild` (Radix) to render the badge as a different element, like a link.
81
87
 
82
- <PreviewCode file="components/docs/samples/badge" name="BadgeAsLinkSample">
83
- <BadgeAsLinkSample />
88
+ <PreviewCode file="components/docs/samples/badge" name="BadgeAsLinkSample" base={<BadgeAsLinkSample />}>
89
+ <BadgeRadixSamples.BadgeAsLinkSample />
84
90
  </PreviewCode>
85
91
 
86
92
  ### Animated
87
93
 
88
94
  Combine with CSS transitions for scroll and color animations.
89
95
 
90
- <PreviewCode file="components/docs/samples/badge" name="BadgeAnimatedSample">
91
- <BadgeAnimatedSample />
96
+ <PreviewCode file="components/docs/samples/badge" name="BadgeAnimatedSample" base={<BadgeAnimatedSample />}>
97
+ <BadgeRadixSamples.BadgeAnimatedSample />
92
98
  </PreviewCode>
93
99
 
94
100
  ## API Reference
@@ -110,11 +116,16 @@ Combine with CSS transitions for scroll and color animations.
110
116
  default: '"default"',
111
117
  description: "The size of the badge.",
112
118
  },
119
+ {
120
+ name: "render",
121
+ type: "ReactElement | function",
122
+ description: "Base UI: compose as a different element instead of rendering a span.",
123
+ },
113
124
  {
114
125
  name: "asChild",
115
126
  type: "boolean",
116
127
  default: "false",
117
- description: "Merge props with child element instead of rendering a span.",
128
+ description: "Radix: merge props with a child element instead of rendering a span.",
118
129
  },
119
130
  {
120
131
  name: "className",
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: Follow-Up Suggestions
3
+ description: Render runtime-generated follow-up prompt chips after an assistant response.
4
+ platforms: ["react"]
5
+ ---
6
+
7
+ import { FollowUpSuggestionsSample } from "@/components/docs/samples/follow-up-suggestions";
8
+
9
+ <FollowUpSuggestionsSample />
10
+
11
+ `ThreadFollowupSuggestions` renders the current thread's runtime suggestions as clickable prompt chips. Use it for follow-up prompts that arrive after a response, such as suggested next questions, refinements, or task shortcuts.
12
+
13
+ <Callout type="info">
14
+ This component reads from `thread.suggestions`. For static welcome-screen prompts, use `ThreadPrimitive.Suggestions` instead.
15
+ </Callout>
16
+
17
+ ## Getting Started
18
+
19
+ <Steps>
20
+ <Step>
21
+
22
+ ### Add `follow-up-suggestions`
23
+
24
+ <InstallCommand shadcn={["follow-up-suggestions"]} />
25
+
26
+ This adds a `/components/assistant-ui/follow-up-suggestions.tsx` file to your project. The default `thread` component already renders `ThreadFollowupSuggestions`, so installing it standalone is only needed when you build your own thread layout.
27
+
28
+ </Step>
29
+ <Step>
30
+
31
+ ### Provide runtime suggestions
32
+
33
+ Pass suggestions through your runtime. External-store runtimes, AI SDK runtimes, and local runtimes can all surface follow-up prompts through `thread.suggestions`.
34
+
35
+ ```tsx title="/app/assistant.tsx" {7-10}
36
+ const runtime = useExternalStoreRuntime({
37
+ messages,
38
+ convertMessage,
39
+ onNew: async (message) => {
40
+ // append the message in your store
41
+ },
42
+ suggestions: [
43
+ { prompt: "Summarize this as action items" },
44
+ { prompt: "Write a shorter version" },
45
+ ],
46
+ });
47
+ ```
48
+
49
+ </Step>
50
+ <Step>
51
+
52
+ ### Render after messages
53
+
54
+ Place `ThreadFollowupSuggestions` near the bottom of your thread viewport, after the assistant message list and before the composer.
55
+
56
+ ```tsx title="/components/assistant-ui/thread.tsx" {1,10}
57
+ import { ThreadFollowupSuggestions } from "@/components/assistant-ui/follow-up-suggestions";
58
+
59
+ const ThreadViewportFooter = () => {
60
+ return (
61
+ <ThreadPrimitive.ViewportFooter>
62
+ <ThreadPrimitive.ScrollToBottom />
63
+ <ThreadFollowupSuggestions />
64
+ <Composer />
65
+ </ThreadPrimitive.ViewportFooter>
66
+ );
67
+ };
68
+ ```
69
+
70
+ </Step>
71
+ </Steps>
72
+
73
+ ## Behavior
74
+
75
+ The component only renders when the thread is not empty, not currently running, and has at least one suggestion. Each suggestion uses `ThreadPrimitive.Suggestion`, replaces the composer text with the prompt, and sends it immediately.
76
+
77
+ ## Related Components
78
+
79
+ - [Thread](/docs/ui/thread) - Complete chat interface with message list and composer
80
+ - [Suggestions guide](/docs/guides/suggestions) - Runtime and static suggestion patterns