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

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 (136) hide show
  1. package/.docs/organized/code-examples/waterfall.md +7 -7
  2. package/.docs/organized/code-examples/with-a2a.md +7 -7
  3. package/.docs/organized/code-examples/with-ag-ui.md +8 -8
  4. package/.docs/organized/code-examples/with-ai-sdk-v7.md +9 -9
  5. package/.docs/organized/code-examples/with-artifacts.md +463 -138
  6. package/.docs/organized/code-examples/with-assistant-transport.md +7 -7
  7. package/.docs/organized/code-examples/with-browser-extension.md +6 -6
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +11 -11
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +9 -9
  10. package/.docs/organized/code-examples/with-cloud.md +9 -9
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +9 -9
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +11 -11
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +11 -11
  14. package/.docs/organized/code-examples/with-eve.md +8 -8
  15. package/.docs/organized/code-examples/with-expo.md +26 -46
  16. package/.docs/organized/code-examples/with-external-store.md +7 -7
  17. package/.docs/organized/code-examples/with-ffmpeg.md +9 -9
  18. package/.docs/organized/code-examples/with-generative-ui.md +10 -10
  19. package/.docs/organized/code-examples/with-google-adk.md +8 -8
  20. package/.docs/organized/code-examples/with-heat-graph.md +6 -6
  21. package/.docs/organized/code-examples/with-image-generation.md +9 -9
  22. package/.docs/organized/code-examples/with-interactables.md +9 -9
  23. package/.docs/organized/code-examples/with-langchain.md +9 -9
  24. package/.docs/organized/code-examples/with-langgraph.md +9 -9
  25. package/.docs/organized/code-examples/with-livekit.md +11 -11
  26. package/.docs/organized/code-examples/with-mcp.md +28 -23
  27. package/.docs/organized/code-examples/with-opencode.md +8 -11
  28. package/.docs/organized/code-examples/with-pi.md +14 -14
  29. package/.docs/organized/code-examples/with-react-hook-form.md +10 -10
  30. package/.docs/organized/code-examples/with-react-ink-web.md +5 -5
  31. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  32. package/.docs/organized/code-examples/with-react-router.md +11 -11
  33. package/.docs/organized/code-examples/with-resumable-stream.md +10 -10
  34. package/.docs/organized/code-examples/with-store.md +6 -6
  35. package/.docs/organized/code-examples/with-tanstack.md +9 -9
  36. package/.docs/organized/code-examples/with-tap-runtime.md +7 -7
  37. package/.docs/organized/code-examples/with-virtualized-thread.md +8 -8
  38. package/.docs/raw/docs/(docs)/cli.mdx +2 -0
  39. package/.docs/raw/docs/(docs)/devtools.mdx +7 -2
  40. package/.docs/raw/docs/(reference)/api-reference/generative-ui/a2ui.mdx +40 -0
  41. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +3 -0
  42. package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +19 -420
  43. package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +4 -1
  44. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +21 -0
  45. package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +1 -9
  46. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +1 -18
  47. package/.docs/raw/docs/cloud/langgraph.mdx +1 -1
  48. package/.docs/raw/docs/copilots/model-context.mdx +1 -1
  49. package/.docs/raw/docs/copilots/motivation.mdx +1 -1
  50. package/.docs/raw/docs/guides/attachments.mdx +3 -3
  51. package/.docs/raw/docs/guides/branching.mdx +2 -2
  52. package/.docs/raw/docs/guides/context-api.mdx +89 -111
  53. package/.docs/raw/docs/guides/editing.mdx +5 -5
  54. package/.docs/raw/docs/guides/electron.mdx +369 -0
  55. package/.docs/raw/docs/guides/index.mdx +10 -0
  56. package/.docs/raw/docs/guides/quoting.mdx +3 -3
  57. package/.docs/raw/docs/guides/resumable-stream-deployment.mdx +2 -2
  58. package/.docs/raw/docs/ink/hooks.mdx +3 -3
  59. package/.docs/raw/docs/ink/primitives.mdx +14 -7
  60. package/.docs/raw/docs/integrations/auth/better-auth.mdx +2 -2
  61. package/.docs/raw/docs/integrations/auth/clerk.mdx +2 -2
  62. package/.docs/raw/docs/integrations/auth/next-auth.mdx +3 -3
  63. package/.docs/raw/docs/integrations/observability/langsmith.mdx +1 -1
  64. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +36 -9
  65. package/.docs/raw/docs/migrations/v0-15.mdx +156 -0
  66. package/.docs/raw/docs/primitives/composer.mdx +1 -1
  67. package/.docs/raw/docs/primitives/thread-list.mdx +2 -2
  68. package/.docs/raw/docs/react-native/hooks.mdx +3 -3
  69. package/.docs/raw/docs/react-native/index.mdx +2 -2
  70. package/.docs/raw/docs/react-native/primitives.mdx +39 -5
  71. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +3 -3
  72. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +4 -4
  73. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +4 -4
  74. package/.docs/raw/docs/runtimes/ai-sdk/v6-legacy.mdx +4 -4
  75. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +2 -2
  76. package/.docs/raw/docs/runtimes/concepts/threads.mdx +10 -10
  77. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +2 -2
  78. package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
  79. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +3 -3
  80. package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
  81. package/.docs/raw/docs/runtimes/langgraph/overview.mdx +1 -1
  82. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +3 -1
  83. package/.docs/raw/docs/tools/a2ui.mdx +107 -0
  84. package/.docs/raw/docs/tools/interactables-legacy.mdx +4 -4
  85. package/.docs/raw/docs/tools/interactables.mdx +3 -3
  86. package/.docs/raw/docs/tools/mcp-apps.mdx +61 -2
  87. package/.docs/raw/docs/tools/user-managed-mcp.mdx +52 -7
  88. package/.docs/raw/docs/ui/follow-up-suggestions.mdx +2 -0
  89. package/.docs/raw/docs/ui/model-selector.mdx +1 -1
  90. package/.docs/raw/docs/ui/part-grouping.mdx +0 -4
  91. package/.docs/raw/docs/ui/reasoning.mdx +1 -1
  92. package/dist/index.d.ts +1 -1
  93. package/dist/index.js +2 -2
  94. package/dist/index.js.map +1 -1
  95. package/dist/prepare-docs/code-examples.js.map +1 -1
  96. package/dist/prepare-docs/prepare.d.ts +1 -1
  97. package/dist/stdio.d.ts +1 -1
  98. package/dist/tools/docs.d.ts +6 -10
  99. package/dist/tools/docs.d.ts.map +1 -1
  100. package/dist/tools/docs.js +2 -2
  101. package/dist/tools/docs.js.map +1 -1
  102. package/dist/tools/examples.d.ts +4 -8
  103. package/dist/tools/examples.d.ts.map +1 -1
  104. package/dist/tools/examples.js +2 -2
  105. package/dist/tools/examples.js.map +1 -1
  106. package/dist/tools/resources.d.ts +1 -1
  107. package/dist/tools/resources.d.ts.map +1 -1
  108. package/dist/tools/resources.js +1 -1
  109. package/dist/tools/resources.js.map +1 -1
  110. package/dist/tools/search.d.ts +4 -10
  111. package/dist/tools/search.d.ts.map +1 -1
  112. package/dist/tools/search.js +2 -2
  113. package/dist/tools/search.js.map +1 -1
  114. package/dist/tools/tests/mcp-test-client.d.ts +15 -0
  115. package/dist/tools/tests/mcp-test-client.d.ts.map +1 -0
  116. package/dist/tools/tests/mcp-test-client.js +68 -0
  117. package/dist/tools/tests/mcp-test-client.js.map +1 -0
  118. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  119. package/dist/tools/xulux-templates.d.ts +9 -23
  120. package/dist/tools/xulux-templates.d.ts.map +1 -1
  121. package/dist/tools/xulux-templates.js +4 -4
  122. package/dist/tools/xulux-templates.js.map +1 -1
  123. package/dist/utils/logger.d.ts.map +1 -1
  124. package/dist/utils/security.js.map +1 -1
  125. package/package.json +4 -3
  126. package/src/index.ts +2 -2
  127. package/src/tools/docs.ts +2 -2
  128. package/src/tools/examples.ts +2 -2
  129. package/src/tools/resources.ts +1 -4
  130. package/src/tools/search.ts +2 -2
  131. package/src/tools/tests/completions.test.ts +40 -26
  132. package/src/tools/tests/integration.test.ts +3 -4
  133. package/src/tools/tests/mcp-protocol.test.ts +160 -175
  134. package/src/tools/tests/mcp-test-client.ts +111 -0
  135. package/src/tools/tests/resources.test.ts +97 -66
  136. package/src/tools/xulux-templates.ts +4 -4
@@ -595,7 +595,7 @@ async function* createCustomStream(): AsyncGenerator<ChatModelRunResult> {
595
595
  };
596
596
  }
597
597
 
598
- aui.thread().resumeRun({
598
+ aui.thread.resumeRun({
599
599
  parentId: "message-id",
600
600
  stream: createCustomStream,
601
601
  });
@@ -617,8 +617,8 @@ function useStreamReconnect(threadId: string) {
617
617
  r.json(),
618
618
  );
619
619
  if (status.isRunning) {
620
- const parentId = aui.thread().getState().messages.at(-1)?.id ?? null;
621
- aui.thread().resumeRun({ parentId });
620
+ const parentId = aui.thread.getState().messages.at(-1)?.id ?? null;
621
+ aui.thread.resumeRun({ parentId });
622
622
  }
623
623
  })();
624
624
  }, [aui, threadId]);
@@ -5,7 +5,7 @@ description: Use LangChain's useStream hook with a React chat UI through assista
5
5
 
6
6
  import { LangGraphIcon } from "@/components/icons/langgraph";
7
7
 
8
- `@assistant-ui/react-langchain` wraps [`useStream`](https://docs.langchain.com/oss/javascript/langgraph-sdk/react-stream) from `@langchain/react` and exposes it as an assistant-ui runtime. It targets the same backend as [`@assistant-ui/react-langgraph`](/docs/runtimes/langgraph/overview) (LangGraph Cloud) but at a higher level, delegating stream plumbing to the upstream hook.
8
+ `@assistant-ui/react-langchain` wraps [`useStream`](https://reference.langchain.com/javascript/langchain-react/use-stream) from `@langchain/react` and exposes it as an assistant-ui runtime. It targets the same backend as [`@assistant-ui/react-langgraph`](/docs/runtimes/langgraph/overview) (LangGraph Cloud) but at a higher level, delegating stream plumbing to the upstream hook.
9
9
 
10
10
  ## When to use it
11
11
 
@@ -32,7 +32,7 @@ Shared adapters (attachments, speech, feedback) work the same way described in [
32
32
 
33
33
  ## Requirements
34
34
 
35
- - A LangGraph Cloud API server (locally via [LangGraph Studio](https://github.com/langchain-ai/langgraph-studio) or hosted via [LangSmith](https://www.langchain.com/langsmith)).
35
+ - A LangGraph Cloud API server (locally via [LangGraph Studio](https://docs.langchain.com/langsmith/quick-start-studio) or hosted via [LangSmith](https://www.langchain.com/langsmith)).
36
36
  - The graph state must include a `messages` key with LangChain-alike messages, or pass a custom `messagesKey`.
37
37
 
38
38
  ## Quickstart
@@ -13,7 +13,7 @@ description: Build a chat UI for LangGraph agents in React with assistant-ui —
13
13
 
14
14
  Pick the LangGraph runtime when:
15
15
 
16
- - You have (or want) a LangGraph Cloud server, locally via [LangGraph Studio](https://github.com/langchain-ai/langgraph-studio) or hosted via [LangSmith](https://www.langchain.com/langsmith).
16
+ - You have (or want) a LangGraph Cloud server, locally via [LangGraph Studio](https://docs.langchain.com/langsmith/quick-start-studio) or hosted via [LangSmith](https://www.langchain.com/langsmith).
17
17
  - Your graph state has a `messages` key with LangChain-alike messages.
18
18
  - You want generative UI (`ui_message`), per-message metadata, subgraph events, or checkpoint-based message editing.
19
19
 
@@ -9,7 +9,9 @@ OpenCode-specific React hooks for interacting with the running session. All hook
9
9
 
10
10
  ## Permissions
11
11
 
12
- OpenCode pauses tool execution to ask the user for permission (e.g. running shell commands, writing files). `useOpenCodePermissions` returns the pending permission requests and a reply function:
12
+ OpenCode pauses tool execution to ask the user for permission (e.g. running shell commands, writing files). Permissions linked to a tool call are projected into assistant-ui's standard tool approval contract, so the default `ToolFallback` renders working **Allow**, **Always allow**, and **Deny** actions without a custom permission component. The always option only appears when OpenCode offers patterns to persist.
13
+
14
+ `useOpenCodePermissions` remains available for custom tool renderers and permission requests that are not linked to a tool call. It returns the pending permission requests and a reply function:
13
15
 
14
16
  ```tsx
15
17
  import { useOpenCodePermissions } from "@assistant-ui/react-opencode";
@@ -0,0 +1,107 @@
1
+ ---
2
+ title: A2UI over AG-UI
3
+ description: Render A2UI surfaces from AG-UI activity snapshots as generative UI, using the community a2ui-surface convention.
4
+ platforms: ["react"]
5
+ ---
6
+
7
+ [A2UI](https://a2ui.org/) is a declarative generative UI protocol: the agent streams surface operations (create a surface, upsert components, update a data model) and the host renders them from a pre-approved component catalog, with no code over the wire. The AG-UI ecosystem carries A2UI as `ACTIVITY_SNAPSHOT` events with `activityType: "a2ui-surface"` and the operations under `content.a2ui_operations`; this is the convention emitted by [`@ag-ui/a2ui-middleware`](https://github.com/ag-ui-protocol/ag-ui/tree/main/middlewares/a2ui-middleware).
8
+
9
+ `useAgUiRuntime` consumes these snapshots natively. Each surface becomes one tool-call part with `toolCallId` `a2ui:<surfaceId>` and `toolName` `"present"`, whose args are the converted generative UI spec, so surfaces render through the same path as the [`present` frontend tool](/docs/tools/generative-ui). Snapshots with any other `activityType` are ignored, and the MCP Apps activity path is unaffected.
10
+
11
+ ## Wire contract
12
+
13
+ A backend paints or updates a surface by emitting an activity snapshot on the AG-UI stream:
14
+
15
+ ```json
16
+ {
17
+ "type": "ACTIVITY_SNAPSHOT",
18
+ "messageId": "a2ui-surface-call_1",
19
+ "activityType": "a2ui-surface",
20
+ "replace": true,
21
+ "content": {
22
+ "a2ui_operations": [
23
+ { "version": "v0.9", "createSurface": { "surfaceId": "s1" } },
24
+ {
25
+ "version": "v0.9",
26
+ "updateComponents": {
27
+ "surfaceId": "s1",
28
+ "components": [
29
+ { "id": "root", "component": "Card", "title": "Order", "children": ["total"] },
30
+ { "id": "total", "component": "Text", "text": { "path": "/total" } }
31
+ ]
32
+ }
33
+ },
34
+ {
35
+ "version": "v0.9",
36
+ "updateDataModel": { "surfaceId": "s1", "path": "/", "contents": { "total": "$42" } }
37
+ }
38
+ ]
39
+ }
40
+ }
41
+ ```
42
+
43
+ - A snapshot with `replace: true` (the schema default) rebuilds that `messageId`'s surface state from the operations it carries. `replace: false` means the snapshot is ignored when that `messageId` has already been seen, matching the AG-UI event spec. The middleware always emits `replace: true`.
44
+ - Surfaces are keyed by the `surfaceId` inside the operations, not by `messageId`. Multiple snapshots that share a `messageId` update their surfaces in place, and the synthesized part keeps its `toolCallId`, so the rendered surface updates without duplicating parts.
45
+ - Component trees use the A2UI adjacency-list model: nodes reference children by id, the root node has id `root`, and props of shape `{ "path": "/x/y" }` are JSON Pointer bindings resolved against the surface data model. Both v0.9 and v1.0 operation payloads are accepted, including the v1.0 inline `components` and `dataModel` on `createSurface`.
46
+ - Lifecycle snapshots that carry a `status` (such as `"building"`) but no `a2ui_operations` are tolerated and produce no part until operations arrive. A `deleteSurface` operation removes the surface's part.
47
+ - The `a2ui:` tool-call id prefix is reserved for synthesized surface parts: they are client-side render artifacts and are excluded from the history sent back to the agent, so genuine agent tool calls must not use ids starting with `a2ui:`.
48
+
49
+ ## Quick start
50
+
51
+ Register the `present` frontend tool from `@assistant-ui/react-generative-ui`; incoming surfaces then render with the default vocabulary:
52
+
53
+ ```tsx
54
+ import {
55
+ JSONGenerativeUI,
56
+ defaultGenerativeUILibrary,
57
+ } from "@assistant-ui/react-generative-ui";
58
+
59
+ const generative = new JSONGenerativeUI({
60
+ library: defaultGenerativeUILibrary,
61
+ });
62
+
63
+ const toolkit = {
64
+ present: generative.present({ display: "standalone" }),
65
+ };
66
+ ```
67
+
68
+ Pass the toolkit to your assistant as on the [Generative UI](/docs/tools/generative-ui) page; no other configuration is needed on `useAgUiRuntime`.
69
+
70
+ ## Actions
71
+
72
+ `Button` nodes dispatch `$action` objects with type `"a2ui:action"` through the action registry. Wire the registry to `useAgUiSendA2uiAction` inside a component; the hook returns a stable function, so the toolkit can be memoized on it:
73
+
74
+ ```tsx
75
+ import { useMemo } from "react";
76
+ import { useAgUiSendA2uiAction } from "@assistant-ui/react-ag-ui";
77
+ import {
78
+ JSONGenerativeUI,
79
+ createActionRegistry,
80
+ defaultGenerativeUILibrary,
81
+ } from "@assistant-ui/react-generative-ui";
82
+
83
+ function useA2uiToolkit() {
84
+ const sendA2uiAction = useAgUiSendA2uiAction();
85
+ return useMemo(() => {
86
+ const generative = new JSONGenerativeUI({
87
+ library: defaultGenerativeUILibrary,
88
+ actions: createActionRegistry({
89
+ "a2ui:action": ({ payload }) => sendA2uiAction(payload),
90
+ }),
91
+ });
92
+ return { present: generative.present({ display: "standalone" }) };
93
+ }, [sendA2uiAction]);
94
+ }
95
+ ```
96
+
97
+ Sending an action triggers a run with no new user message, and the agent receives it as `forwardedProps.a2uiAction.userAction`, the convention `@ag-ui/a2ui-middleware` consumes. The action rides exactly one run; the `type` field is stripped and a `timestamp` is added when absent.
98
+
99
+ The middleware turns the action into a synthetic `log_a2ui_event` tool-call pair that is never declared in `input.tools`; a backend that validates tool calls against the declared tool list will reject it.
100
+
101
+ ## Component mapping
102
+
103
+ The converter maps the A2UI basic catalog onto the default generative UI vocabulary: `Text` becomes `Markdown` (`h1` to `h6` variants become `Header`, `caption` becomes `Caption`), `Column` becomes `Col`, `TextField` becomes `Input` (the control name is derived from the last segment of its binding path), `CheckBox` becomes `Checkbox`, and `Image`, `Row`, `Card`, `Divider`, `Button` map one to one. A node with template children expands into a `ListView` over the bound list. `Button` actions become `$action` objects with type `"a2ui:action"` carrying the action name, `surfaceId`, and `sourceComponentId`, which is how your action registry receives them. Unknown components and operations are skipped with a debug warning, and conversion is bounded (depth 32, 100 template items, 5000 nodes) so a malformed stream cannot hang the client.
104
+
105
+ ## Limitations
106
+
107
+ - The upstream middleware currently emits v0.9 operation payloads; the renderer accepts v0.9 and v1.0 shapes.
@@ -298,7 +298,7 @@ function MyRuntimeProvider({ children }) {
298
298
 
299
299
  useEffect(() => {
300
300
  // Set up persistence adapter
301
- aui.interactables().setPersistenceAdapter({
301
+ aui.interactables.setPersistenceAdapter({
302
302
  save: async (state) => {
303
303
  localStorage.setItem("interactables", JSON.stringify(state));
304
304
  },
@@ -307,7 +307,7 @@ function MyRuntimeProvider({ children }) {
307
307
  // Restore saved state on mount
308
308
  const saved = localStorage.getItem("interactables");
309
309
  if (saved) {
310
- aui.interactables().importState(JSON.parse(saved));
310
+ aui.interactables.importState(JSON.parse(saved));
311
311
  }
312
312
  }, [aui]);
313
313
 
@@ -334,10 +334,10 @@ State changes are automatically debounced (500ms) before saving. When a componen
334
334
  For custom persistence strategies, use `exportState` and `importState` directly:
335
335
 
336
336
  ```tsx
337
- const snapshot = aui.interactables().exportState();
337
+ const snapshot = aui.interactables.exportState();
338
338
  // => { "note-1": { name: "note", state: { title: "Hello" } }, ... }
339
339
 
340
- aui.interactables().importState(snapshot);
340
+ aui.interactables.importState(snapshot);
341
341
  // Imported state is picked up when components next register
342
342
  ```
343
343
 
@@ -618,7 +618,7 @@ function MyRuntimeProvider({ children }) {
618
618
 
619
619
  `load` is called when the adapter is attached and may be async. Loaded state seeds interactables as they register; a local edit made while a slow `load` is still in flight wins over the loaded value. Thread-scoped interactables are not touched by the adapter; they persist via thread history.
620
620
 
621
- For dynamic setups (an adapter that depends on auth), call `aui.interactables().setPersistenceAdapter(adapter)` imperatively instead.
621
+ For dynamic setups (an adapter that depends on auth), call `aui.interactables.setPersistenceAdapter(adapter)` imperatively instead.
622
622
 
623
623
  ### Sync Status
624
624
 
@@ -640,10 +640,10 @@ State changes are automatically debounced (500ms) before saving. When the owning
640
640
  For custom persistence strategies, use `exportState` and `importState` directly:
641
641
 
642
642
  ```tsx
643
- const snapshot = aui.interactables().exportState();
643
+ const snapshot = aui.interactables.exportState();
644
644
  // => { "note-1": { name: "note", state: { title: "Hello" } }, ... }
645
645
 
646
- aui.interactables().importState(snapshot);
646
+ aui.interactables.importState(snapshot);
647
647
  // Imported state is picked up when components next register
648
648
  ```
649
649
 
@@ -164,7 +164,7 @@ const result = streamText({
164
164
 
165
165
  [OpenAI Apps SDK](https://developers.openai.com/apps-sdk) servers carry the same `ui://` template under a different convention: the pointer is `_meta["openai/outputTemplate"]` on the tool definition (not `_meta.ui.resourceUri`), and the resource is served as `text/html+skybridge` rather than `text/html;profile=mcp-app`. `@ai-sdk/mcp` does not recognize `openai/outputTemplate`, so it never populates `callProviderMetadata.mcp.app` and the renderer stays idle.
166
166
 
167
- The renderer needs no change; you only have to surface the pointer. assistant-ui already reads `result._meta["ui/resourceUri"]` off tool results, so the smallest bridge is to copy the template onto the result by tool name. Build the map once from the tool listing, then stamp it inside each tool's `execute`:
167
+ The renderer needs no change; you only have to surface the pointer. assistant-ui reads the canonical `result._meta.ui.resourceUri` off tool results (and still accepts the deprecated flat `result._meta["ui/resourceUri"]`), so the smallest bridge is to copy the template onto the result by tool name. Build the map once from the tool listing, then stamp it inside each tool's `execute`:
168
168
 
169
169
  ```ts
170
170
  import type { Tool } from "ai";
@@ -184,7 +184,13 @@ const withTemplateUri = (tool: Tool, name: string): Tool => {
184
184
  ...tool,
185
185
  execute: async (args, options) => {
186
186
  const result = (await exec(args, options)) as { _meta?: Record<string, unknown> };
187
- return { ...result, _meta: { ...result._meta, "ui/resourceUri": uri } };
187
+ return {
188
+ ...result,
189
+ _meta: {
190
+ ...result._meta,
191
+ ui: { ...(result._meta?.["ui"] as Record<string, unknown>), resourceUri: uri },
192
+ },
193
+ };
188
194
  },
189
195
  } satisfies Tool;
190
196
  };
@@ -204,6 +210,59 @@ Your `mcp-apps/read-resource` handler reads the `ui://` resource as in the route
204
210
 
205
211
  The cleaner long-term fix is upstream: if `@ai-sdk/mcp`'s `getMCPAppToolMeta` also read `openai/outputTemplate`, then `callProviderMetadata.mcp.app` would populate automatically and this bridge would be unnecessary.
206
212
 
213
+ ## AG-UI integration
214
+
215
+ With `@assistant-ui/react-ag-ui`, the backend associates an MCP App with a tool call through an `ACTIVITY_SNAPSHOT`. Include the tool call ID, the app's `ui://` resource URI, and the MCP server identity when routing across multiple servers:
216
+
217
+ ```json
218
+ {
219
+ "type": "ACTIVITY_SNAPSHOT",
220
+ "activityType": "mcp-apps",
221
+ "content": {
222
+ "toolCallId": "call-1",
223
+ "resourceUri": "ui://maps/result.html",
224
+ "serverId": "maps",
225
+ "result": {
226
+ "content": [{ "type": "text", "text": "Map ready" }],
227
+ "structuredContent": { "center": [37.77, -122.42] },
228
+ "_meta": { "initialView": "street" },
229
+ "isError": false
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ `serverId` is optional. If it is absent, the runtime accepts `serverHash` as a fallback. Older middleware may omit `toolCallId`, in which case the snapshot applies to the last resolved tool call; new integrations should include it so concurrent tool calls are correlated unambiguously. Emit the snapshot after the tool call's `TOOL_CALL_START`. A snapshot that names a tool call restored from prior history applies to that message directly, so re-emitting the activity after a `MESSAGES_SNAPSHOT` rehydrates its widget; a snapshot for a tool call ID the runtime has never seen is silently ignored.
236
+
237
+ Send the normal `TOOL_CALL_RESULT` with a concise, model-visible summary:
238
+
239
+ ```json
240
+ {
241
+ "type": "TOOL_CALL_RESULT",
242
+ "toolCallId": "call-1",
243
+ "content": "Map ready"
244
+ }
245
+ ```
246
+
247
+ The snapshot's `result` becomes the widget-visible `part.result`, while the `TOOL_CALL_RESULT.content` string is retained for the model as `part.modelContent`, a text content-part array (`[{ "type": "text", "text": "Map ready" }]`).
248
+
249
+ Alternatively, AG-UI servers can place MCP host fields directly on `TOOL_CALL_RESULT`:
250
+
251
+ ```json
252
+ {
253
+ "type": "TOOL_CALL_RESULT",
254
+ "toolCallId": "call-1",
255
+ "content": "Map ready",
256
+ "structuredContent": { "center": [37.77, -122.42] },
257
+ "_meta": { "initialView": "street" },
258
+ "isError": false
259
+ }
260
+ ```
261
+
262
+ In this form, the runtime assembles a `CallToolResult`-shaped `part.result` from `content`, `structuredContent`, `_meta`, and `isError`. At least one of `structuredContent` or `_meta` must be present; when both are absent the enriched path does not activate and the result falls back to the plain `content` string. The `_meta` can also carry the app pointer itself (canonical `ui.resourceUri`, or the deprecated flat `"ui/resourceUri"`), in which case no `ACTIVITY_SNAPSHOT` is needed to activate the widget. A snapshot remains the only carrier for server identity (`serverId`), and when both provide a `resourceUri` the snapshot wins.
263
+
264
+ The visibility split follows the MCP Apps contract: `content` is model-visible; `structuredContent` and `_meta` are available only to the host and widget. When assistant-ui serializes history into a later AG-UI request, it sends the saved model-visible text and never includes `structuredContent` or `_meta`.
265
+
207
266
  ## Bridge protocol
208
267
 
209
268
  The bridge implements the MCP UI JSON-RPC protocol over `window.postMessage`, filtered by both `event.source === frame.iframe.contentWindow` AND `event.origin === frame.origin` — the cross-origin domain `SafeContentFrame` issues per render. Messages from any other origin or window are dropped silently.
@@ -114,7 +114,7 @@ Pass children to override the trigger:
114
114
  </McpConfigDialog>
115
115
  ```
116
116
 
117
- **Compose your own from primitives** — three namespaces, all unstyled and `data-*`-driven. The iteration primitives take a **render function** so the body re-runs per server with the right scope:
117
+ **Compose your own from primitives.** Four namespaces are available, all unstyled and `data-*`-driven. The iteration primitives take a **render function** so the body re-runs per server with the right scope:
118
118
 
119
119
  ```tsx title="app/mcp/page.tsx"
120
120
  "use client";
@@ -179,7 +179,7 @@ The iteration primitives wrap each item in an `McpServerByIdProvider`, so the ne
179
179
  </McpAddFormPrimitive.Root>
180
180
  ```
181
181
 
182
- The form owns its own draft state and submits via `aui.mcp().addCustomServer(...)`. Pass a render function to `AuthFields` to fully customize it.
182
+ The form owns its own draft state and submits via `aui.mcp.addCustomServer(...)`. Pass a render function to `AuthFields` to fully customize it.
183
183
 
184
184
  </Step>
185
185
  <Step>
@@ -236,12 +236,56 @@ If no chat runtime is mounted, `McpManagerResource` brings its own minimal `mode
236
236
  ```ts
237
237
  // In an event handler, never in render.
238
238
  const aui = useAui();
239
- const out = await aui.mcp().server({ id: "linear" }).callTool("search", { q });
239
+ const out = await aui.mcp.server({ id: "linear" }).callTool("search", { q });
240
240
  ```
241
241
 
242
242
  </Step>
243
243
  </Steps>
244
244
 
245
+ ## Form elicitation
246
+
247
+ Connected servers can request structured user input through form-mode elicitation. Render `McpElicitationPrimitive.Items` inside a server-scoped subtree, then compose fields and response actions from the unstyled primitives:
248
+
249
+ Answering a request requires composing `McpElicitationPrimitive`, because the server waits for the form response otherwise. Set `elicitation: false` on a connector or custom server to opt it out of advertising the capability. Numeric fields can stay text inputs (parseable strings are coerced); boolean fields must compose a checkbox, because string drafts for booleans are flagged invalid rather than coerced. Clearing a field returns it to the unanswered state, so an empty text input is omitted from the response rather than submitted as `""` or flagged invalid, unless the schema admits `""` for that property through an `enum` member or a `""` default. Render `enum` properties as a select; when `""` is not a member, its blank option is the unanswered state.
250
+
251
+ ```tsx
252
+ import { McpElicitationPrimitive } from "@assistant-ui/react-mcp";
253
+
254
+ <McpElicitationPrimitive.Items>
255
+ {() => (
256
+ <McpElicitationPrimitive.Root>
257
+ <McpElicitationPrimitive.Message />
258
+ <McpElicitationPrimitive.Error />
259
+ <McpElicitationPrimitive.Fields>
260
+ {({ name, schema, value, setValue }) =>
261
+ (schema as { type?: string } | undefined)?.type === "boolean" ? (
262
+ <label>
263
+ {name}
264
+ <input
265
+ type="checkbox"
266
+ checked={value === true}
267
+ onChange={(event) => setValue(event.target.checked)}
268
+ />
269
+ </label>
270
+ ) : (
271
+ <input
272
+ name={name}
273
+ value={typeof value === "string" ? value : ""}
274
+ onChange={(event) => setValue(event.target.value)}
275
+ />
276
+ )
277
+ }
278
+ </McpElicitationPrimitive.Fields>
279
+ <McpElicitationPrimitive.Accept>Submit</McpElicitationPrimitive.Accept>
280
+ <McpElicitationPrimitive.Decline>Decline</McpElicitationPrimitive.Decline>
281
+ <McpElicitationPrimitive.Cancel>Cancel</McpElicitationPrimitive.Cancel>
282
+ </McpElicitationPrimitive.Root>
283
+ )}
284
+ </McpElicitationPrimitive.Items>
285
+ ```
286
+
287
+ Client-side validation errors keep the elicitation pending so the user can correct the form, and `McpElicitationPrimitive.Error` renders the resulting message.
288
+
245
289
  ## Storage
246
290
 
247
291
  All persisted state — custom server records, OAuth tokens, PKCE verifiers, DCR client info — goes through a single `MCPStorage` resource. Three built-ins:
@@ -312,9 +356,9 @@ Imperative methods: `useAui` + resolve in a callback (never during render):
312
356
  const aui = useAui();
313
357
 
314
358
  // inside an event handler:
315
- await aui.mcp().addCustomServer({ name, url, auth: { type: "bearer", token } });
316
- await aui.mcp().server({ id }).connect();
317
- await aui.mcp().server({ id }).callTool("echo", { text: "hi" });
359
+ await aui.mcp.addCustomServer({ name, url, auth: { type: "bearer", token } });
360
+ await aui.mcp.server({ id }).connect();
361
+ await aui.mcp.server({ id }).callTool("echo", { text: "hi" });
318
362
 
319
363
  // Build a paginated resource browser/preview UI.
320
364
  type ResourcePage = {
@@ -322,7 +366,7 @@ type ResourcePage = {
322
366
  nextCursor?: string;
323
367
  };
324
368
 
325
- const server = aui.mcp().server({ id });
369
+ const server = aui.mcp.server({ id });
326
370
  const resources: ResourcePage["resources"] = [];
327
371
  let nextCursor: string | undefined;
328
372
 
@@ -346,6 +390,7 @@ What ships:
346
390
 
347
391
  - Tool listing and invocation, auto-registered as frontend tools
348
392
  - Resource listing and reads for app-built browsers or preview panes
393
+ - Form-mode elicitation with app-composed fields and response actions
349
394
  - OAuth (PKCE + DCR), bearer, none
350
395
  - StreamableHTTP transport
351
396
  - Manual connect/disconnect
@@ -74,6 +74,8 @@ const ThreadViewportFooter = () => {
74
74
 
75
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
76
 
77
+ Suggestions stay on a single line. When they overflow, the row scrolls horizontally without a scrollbar, and each edge with clipped content fades out — so no fade shows at the start edge until you scroll.
78
+
77
79
  ## Related Components
78
80
 
79
81
  - [Thread](/docs/ui/thread) - Complete chat interface with message list and composer
@@ -308,7 +308,7 @@ The picker implements the WAI-ARIA combobox pattern over Popover + Command.
308
308
 
309
309
  The default `ModelSelector` export registers the selection with assistant-ui's `ModelContext` system:
310
310
 
311
- 1. The component calls `aui.modelContext().register()` with `config.modelName`, plus `config.reasoningEffort` when the selected model supports the chosen level
311
+ 1. The component calls `aui.modelContext.register()` with `config.modelName`, plus `config.reasoningEffort` when the selected model supports the chosen level
312
312
  2. The `AssistantChatTransport` includes `config` in the request body of every chat request
313
313
  3. Your API route reads `config.modelName` and `config.reasoningEffort`
314
314
 
@@ -248,10 +248,6 @@ The synthetic `"standalone-tool-call"` key on `groupPartByType` matches all of t
248
248
  </MessagePrimitive.GroupedParts>;
249
249
  ```
250
250
 
251
- <Callout type="info">
252
- The `"mcp-app"` key is deprecated in favor of `"standalone-tool-call"`, which is a superset (it also matches MCP-app tool calls). Existing `"mcp-app"` usage keeps working.
253
- </Callout>
254
-
255
251
  ### Render Tool Calls as Flat Rows
256
252
 
257
253
  The previous section keeps `"tool-call"` folded into the chain-of-thought and only lifts standalone tool UIs out. To keep reasoning collapsed in a group while every tool call renders as its own row in the message flow, map both tool keys to `[]`:
@@ -28,7 +28,7 @@ Previously, reasoning parts were rendered via `components.Reasoning` and grouped
28
28
 
29
29
  Render reasoning parts through `MessagePrimitive.GroupedParts`. Group consecutive reasoning parts with `"group-reasoning"`, then compose `ReasoningRoot`, `ReasoningTrigger`, `ReasoningContent`, and `ReasoningText` around the grouped children.
30
30
 
31
- While reasoning is streaming, `part.status.type === "running"`. Pass that to `streaming` so the accordion auto-opens during streaming with a bottom-pinned live preview of the newest tokens, auto-collapses when the model moves on, and permanently defers to the first manual toggle. When `streaming` is provided it supersedes `defaultOpen`.
31
+ While reasoning is streaming, `part.status.type === "running"`. Pass that to `streaming` so the accordion auto-opens during streaming with a bottom-pinned live preview of the newest tokens, and permanently defers to the first manual toggle. `streaming` only holds the disclosure open; when it ends the accordion returns to `defaultOpen`, which is `false` by default and therefore collapses. Pass `defaultOpen` to keep reasoning expanded once the run finishes.
32
32
 
33
33
  ```tsx title="/app/components/assistant-ui/thread.tsx"
34
34
  import { MessagePrimitive, groupPartByType } from "@assistant-ui/react";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
2
  //#region src/index.d.ts
3
3
  declare const server: McpServer;
4
4
  declare function runServer(): Promise<void>;
package/dist/index.js CHANGED
@@ -7,8 +7,8 @@ import { xuluxTemplateDetailsTool, xuluxTemplatePreviewTool, xuluxTemplatesListT
7
7
  import { xuluxPlaygroundPrompt } from "./prompts/xulux-playground.js";
8
8
  import { registerResources } from "./tools/resources.js";
9
9
  import { join } from "node:path";
10
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import { McpServer } from "@modelcontextprotocol/server";
11
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
12
12
  import { readFileSync } from "node:fs";
13
13
  //#region src/index.ts
14
14
  const packageJson = JSON.parse(readFileSync(join(PACKAGE_DIR, "package.json"), "utf-8"));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { docsTools } from \"./tools/docs.js\";\nimport { examplesTools } from \"./tools/examples.js\";\nimport { searchTools } from \"./tools/search.js\";\nimport {\n xuluxTemplatesListTool,\n xuluxTemplateDetailsTool,\n xuluxTemplatePreviewTool,\n} from \"./tools/xulux-templates.js\";\nimport { xuluxPlaygroundPrompt } from \"./prompts/xulux-playground.js\";\nimport { registerResources } from \"./tools/resources.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { PACKAGE_DIR } from \"./constants.js\";\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst packageJson = JSON.parse(\n readFileSync(join(PACKAGE_DIR, \"package.json\"), \"utf-8\"),\n);\n\nexport const server = new McpServer({\n name: \"assistant-ui-docs\",\n version: packageJson.version,\n});\n\nserver.registerTool(\n docsTools.name,\n {\n title: \"assistant-ui Documentation\",\n description: docsTools.description,\n inputSchema: docsTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n docsTools.execute,\n);\nserver.registerTool(\n examplesTools.name,\n {\n title: \"assistant-ui Examples\",\n description: examplesTools.description,\n inputSchema: examplesTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n examplesTools.execute,\n);\nserver.registerTool(\n searchTools.name,\n {\n title: \"Search assistant-ui Documentation\",\n description: searchTools.description,\n inputSchema: searchTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n searchTools.execute,\n);\n\nserver.registerTool(\n xuluxTemplatesListTool.name,\n {\n title: \"assistant-ui Templates\",\n description: xuluxTemplatesListTool.description,\n inputSchema: xuluxTemplatesListTool.parameters,\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n xuluxTemplatesListTool.execute,\n);\nserver.registerTool(\n xuluxTemplateDetailsTool.name,\n {\n title: \"assistant-ui Template Details\",\n description: xuluxTemplateDetailsTool.description,\n inputSchema: xuluxTemplateDetailsTool.parameters,\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n xuluxTemplateDetailsTool.execute,\n);\nserver.registerTool(\n xuluxTemplatePreviewTool.name,\n {\n title: \"assistant-ui Template Preview URLs\",\n description: xuluxTemplatePreviewTool.description,\n inputSchema: xuluxTemplatePreviewTool.parameters,\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n xuluxTemplatePreviewTool.execute,\n);\n\nserver.registerPrompt(\n xuluxPlaygroundPrompt.name,\n {\n title: \"assistant-ui Template Workflow\",\n description: xuluxPlaygroundPrompt.description,\n },\n () => ({\n messages: [\n {\n role: \"user\" as const,\n content: { type: \"text\" as const, text: xuluxPlaygroundPrompt.text },\n },\n ],\n }),\n);\n\nregisterResources(server);\n\nexport async function runServer() {\n try {\n logger.info(\n `Starting assistant-ui MCP docs server v${packageJson.version}`,\n );\n const transport = new StdioServerTransport();\n await server.connect(transport);\n } catch (error) {\n logger.error(\"Failed to start MCP server\", error);\n process.exit(1);\n }\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n void runServer().catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,cAAc,KAAK,MACvB,aAAa,KAAK,aAAa,cAAc,GAAG,OAAO,CACzD;AAEA,MAAa,SAAS,IAAI,UAAU;CAClC,MAAM;CACN,SAAS,YAAY;AACvB,CAAC;AAED,OAAO,aACL,UAAU,MACV;CACE,OAAO;CACP,aAAa,UAAU;CACvB,aAAa,UAAU;CACvB,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,UAAU,OACZ;AACA,OAAO,aACL,cAAc,MACd;CACE,OAAO;CACP,aAAa,cAAc;CAC3B,aAAa,cAAc;CAC3B,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,cAAc,OAChB;AACA,OAAO,aACL,YAAY,MACZ;CACE,OAAO;CACP,aAAa,YAAY;CACzB,aAAa,YAAY;CACzB,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,YAAY,OACd;AAEA,OAAO,aACL,uBAAuB,MACvB;CACE,OAAO;CACP,aAAa,uBAAuB;CACpC,aAAa,uBAAuB;CACpC,aAAa;EAAE,cAAc;EAAM,eAAe;CAAK;AACzD,GACA,uBAAuB,OACzB;AACA,OAAO,aACL,yBAAyB,MACzB;CACE,OAAO;CACP,aAAa,yBAAyB;CACtC,aAAa,yBAAyB;CACtC,aAAa;EAAE,cAAc;EAAM,eAAe;CAAK;AACzD,GACA,yBAAyB,OAC3B;AACA,OAAO,aACL,yBAAyB,MACzB;CACE,OAAO;CACP,aAAa,yBAAyB;CACtC,aAAa,yBAAyB;CACtC,aAAa;EAAE,cAAc;EAAO,eAAe;CAAK;AAC1D,GACA,yBAAyB,OAC3B;AAEA,OAAO,eACL,sBAAsB,MACtB;CACE,OAAO;CACP,aAAa,sBAAsB;AACrC,UACO,EACL,UAAU,CACR;CACE,MAAM;CACN,SAAS;EAAE,MAAM;EAAiB,MAAM,sBAAsB;CAAK;AACrE,CACF,EACF,EACF;AAEA,kBAAkB,MAAM;AAExB,eAAsB,YAAY;CAChC,IAAI;EACF,OAAO,KACL,0CAA0C,YAAY,SACxD;EACA,MAAM,YAAY,IAAI,qBAAqB;EAC3C,MAAM,OAAO,QAAQ,SAAS;CAChC,SAAS,OAAO;EACd,OAAO,MAAM,8BAA8B,KAAK;EAChD,QAAQ,KAAK,CAAC;CAChB;AACF;AAEA,IAAI,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,MAC7C,UAAe,CAAC,CAAC,OAAO,UAAU;CAChC,QAAQ,MAAM,2BAA2B,KAAK;CAC9C,QAAQ,KAAK,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/server\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/server/stdio\";\nimport { docsTools } from \"./tools/docs.js\";\nimport { examplesTools } from \"./tools/examples.js\";\nimport { searchTools } from \"./tools/search.js\";\nimport {\n xuluxTemplatesListTool,\n xuluxTemplateDetailsTool,\n xuluxTemplatePreviewTool,\n} from \"./tools/xulux-templates.js\";\nimport { xuluxPlaygroundPrompt } from \"./prompts/xulux-playground.js\";\nimport { registerResources } from \"./tools/resources.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { PACKAGE_DIR } from \"./constants.js\";\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst packageJson = JSON.parse(\n readFileSync(join(PACKAGE_DIR, \"package.json\"), \"utf-8\"),\n);\n\nexport const server = new McpServer({\n name: \"assistant-ui-docs\",\n version: packageJson.version,\n});\n\nserver.registerTool(\n docsTools.name,\n {\n title: \"assistant-ui Documentation\",\n description: docsTools.description,\n inputSchema: docsTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n docsTools.execute,\n);\nserver.registerTool(\n examplesTools.name,\n {\n title: \"assistant-ui Examples\",\n description: examplesTools.description,\n inputSchema: examplesTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n examplesTools.execute,\n);\nserver.registerTool(\n searchTools.name,\n {\n title: \"Search assistant-ui Documentation\",\n description: searchTools.description,\n inputSchema: searchTools.parameters,\n annotations: { readOnlyHint: true, openWorldHint: false },\n },\n searchTools.execute,\n);\n\nserver.registerTool(\n xuluxTemplatesListTool.name,\n {\n title: \"assistant-ui Templates\",\n description: xuluxTemplatesListTool.description,\n inputSchema: xuluxTemplatesListTool.parameters,\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n xuluxTemplatesListTool.execute,\n);\nserver.registerTool(\n xuluxTemplateDetailsTool.name,\n {\n title: \"assistant-ui Template Details\",\n description: xuluxTemplateDetailsTool.description,\n inputSchema: xuluxTemplateDetailsTool.parameters,\n annotations: { readOnlyHint: true, openWorldHint: true },\n },\n xuluxTemplateDetailsTool.execute,\n);\nserver.registerTool(\n xuluxTemplatePreviewTool.name,\n {\n title: \"assistant-ui Template Preview URLs\",\n description: xuluxTemplatePreviewTool.description,\n inputSchema: xuluxTemplatePreviewTool.parameters,\n annotations: { readOnlyHint: false, openWorldHint: true },\n },\n xuluxTemplatePreviewTool.execute,\n);\n\nserver.registerPrompt(\n xuluxPlaygroundPrompt.name,\n {\n title: \"assistant-ui Template Workflow\",\n description: xuluxPlaygroundPrompt.description,\n },\n () => ({\n messages: [\n {\n role: \"user\" as const,\n content: { type: \"text\" as const, text: xuluxPlaygroundPrompt.text },\n },\n ],\n }),\n);\n\nregisterResources(server);\n\nexport async function runServer() {\n try {\n logger.info(\n `Starting assistant-ui MCP docs server v${packageJson.version}`,\n );\n const transport = new StdioServerTransport();\n await server.connect(transport);\n } catch (error) {\n logger.error(\"Failed to start MCP server\", error);\n process.exit(1);\n }\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n void runServer().catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,cAAc,KAAK,MACvB,aAAa,KAAK,aAAa,cAAc,GAAG,OAAO,CACzD;AAEA,MAAa,SAAS,IAAI,UAAU;CAClC,MAAM;CACN,SAAS,YAAY;AACvB,CAAC;AAED,OAAO,aACL,UAAU,MACV;CACE,OAAO;CACP,aAAa,UAAU;CACvB,aAAa,UAAU;CACvB,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,UAAU,OACZ;AACA,OAAO,aACL,cAAc,MACd;CACE,OAAO;CACP,aAAa,cAAc;CAC3B,aAAa,cAAc;CAC3B,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,cAAc,OAChB;AACA,OAAO,aACL,YAAY,MACZ;CACE,OAAO;CACP,aAAa,YAAY;CACzB,aAAa,YAAY;CACzB,aAAa;EAAE,cAAc;EAAM,eAAe;CAAM;AAC1D,GACA,YAAY,OACd;AAEA,OAAO,aACL,uBAAuB,MACvB;CACE,OAAO;CACP,aAAa,uBAAuB;CACpC,aAAa,uBAAuB;CACpC,aAAa;EAAE,cAAc;EAAM,eAAe;CAAK;AACzD,GACA,uBAAuB,OACzB;AACA,OAAO,aACL,yBAAyB,MACzB;CACE,OAAO;CACP,aAAa,yBAAyB;CACtC,aAAa,yBAAyB;CACtC,aAAa;EAAE,cAAc;EAAM,eAAe;CAAK;AACzD,GACA,yBAAyB,OAC3B;AACA,OAAO,aACL,yBAAyB,MACzB;CACE,OAAO;CACP,aAAa,yBAAyB;CACtC,aAAa,yBAAyB;CACtC,aAAa;EAAE,cAAc;EAAO,eAAe;CAAK;AAC1D,GACA,yBAAyB,OAC3B;AAEA,OAAO,eACL,sBAAsB,MACtB;CACE,OAAO;CACP,aAAa,sBAAsB;AACrC,UACO,EACL,UAAU,CACR;CACE,MAAM;CACN,SAAS;EAAE,MAAM;EAAiB,MAAM,sBAAsB;CAAK;AACrE,CACF,EACF,EACF;AAEA,kBAAkB,MAAM;AAExB,eAAsB,YAAY;CAChC,IAAI;EACF,OAAO,KACL,0CAA0C,YAAY,SACxD;EACA,MAAM,YAAY,IAAI,qBAAqB;EAC3C,MAAM,OAAO,QAAQ,SAAS;CAChC,SAAS,OAAO;EACd,OAAO,MAAM,8BAA8B,KAAK;EAChD,QAAQ,KAAK,CAAC;CAChB;AACF;AAEA,IAAI,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,MAC7C,UAAe,CAAC,CAAC,OAAO,UAAU;CAChC,QAAQ,MAAM,2BAA2B,KAAK;CAC9C,QAAQ,KAAK,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"code-examples.js","names":[],"sources":["../../src/prepare-docs/code-examples.ts"],"sourcesContent":["import { rm, mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, relative, extname } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport { ROOT_DIR, EXAMPLES_PATH } from \"../constants.js\";\n\nconst OUTPUT_DIR = join(\n ROOT_DIR,\n \"packages/mcp-docs-server/.docs/organized/code-examples\",\n);\nconst MAX_LINES = 10000;\n\ninterface FileContent {\n path: string;\n content: string;\n}\n\nasync function scanDirectory(\n dir: string,\n baseDir: string,\n): Promise<FileContent[]> {\n const files: FileContent[] = [];\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n const skipDirs = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \".git\",\n \".turbo\",\n ];\n if (!skipDirs.includes(entry.name)) {\n const subFiles = await scanDirectory(fullPath, baseDir);\n files.push(...subFiles);\n }\n } else if (entry.isFile()) {\n const includeExts = [\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".css\",\n \".md\",\n \".mdx\",\n ];\n const ext = extname(entry.name).toLowerCase();\n\n if (\n includeExts.includes(ext) ||\n entry.name === \"package.json\" ||\n entry.name === \"tsconfig.json\"\n ) {\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const relativePath = relative(baseDir, fullPath);\n files.push({ path: relativePath, content });\n } catch (error) {\n logger.warn(`Failed to read file: ${fullPath}`, error);\n }\n }\n }\n }\n } catch (error) {\n logger.error(`Failed to scan directory: ${dir}`, error);\n }\n\n return files;\n}\n\nfunction getFileType(filename: string): string {\n const ext = extname(filename).toLowerCase();\n const extMap: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"tsx\",\n \".js\": \"javascript\",\n \".jsx\": \"jsx\",\n \".json\": \"json\",\n \".css\": \"css\",\n \".md\": \"markdown\",\n \".mdx\": \"mdx\",\n };\n return extMap[ext] || \"text\";\n}\n\nexport async function prepareCodeExamples(): Promise<void> {\n logger.info(\"Preparing code examples...\");\n\n try {\n await rm(OUTPUT_DIR, { recursive: true, force: true });\n await mkdir(OUTPUT_DIR, { recursive: true });\n\n const exampleDirs = await readdir(EXAMPLES_PATH, { withFileTypes: true });\n\n for (const dir of exampleDirs) {\n if (dir.isDirectory() && !dir.name.startsWith(\".\")) {\n const examplePath = join(EXAMPLES_PATH, dir.name);\n logger.info(`Processing example: ${dir.name}`);\n\n let description = \"\";\n try {\n const packageJsonPath = join(examplePath, \"package.json\");\n const packageJson = JSON.parse(\n await readFile(packageJsonPath, \"utf-8\"),\n );\n description = packageJson.description || \"\";\n } catch (error: any) {\n if (error?.code !== \"ENOENT\") {\n logger.warn(`Failed to read package.json for ${dir.name}:`, error);\n } else {\n logger.debug(`No package.json found for example: ${dir.name}`);\n }\n }\n\n const files = await scanDirectory(examplePath, examplePath);\n\n files.sort((a, b) => a.path.localeCompare(b.path));\n\n let markdown = `# Example: ${dir.name}\\n\\n`;\n if (description) {\n markdown += `${description}\\n\\n`;\n }\n\n let totalLines = 0;\n for (const file of files) {\n const lines = file.content.split(\"\\n\").length;\n if (totalLines + lines > MAX_LINES) {\n markdown += `\\n_Note: Additional files truncated due to size limits_\\n`;\n break;\n }\n\n // Normalize Windows backslashes to forward slashes for consistent markdown output\n markdown += `## ${file.path.replace(/\\\\/g, \"/\")}\\n\\n`;\n markdown += `\\`\\`\\`${getFileType(file.path)}\\n`;\n markdown += file.content;\n markdown += `\\n\\`\\`\\`\\n\\n`;\n\n totalLines += lines;\n }\n\n const outputPath = join(OUTPUT_DIR, `${dir.name}.md`);\n await writeFile(outputPath, markdown, \"utf-8\");\n logger.debug(`Created example: ${outputPath}`);\n }\n }\n\n logger.info(\"Code examples preparation complete\");\n } catch (error) {\n logger.error(\"Failed to prepare code examples\", error);\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"code-examples.js","names":[],"sources":["../../src/prepare-docs/code-examples.ts"],"sourcesContent":["import { rm, mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, relative, extname } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport { ROOT_DIR, EXAMPLES_PATH } from \"../constants.js\";\n\nconst OUTPUT_DIR = join(\n ROOT_DIR,\n \"packages/mcp-docs-server/.docs/organized/code-examples\",\n);\nconst MAX_LINES = 10000;\n\ninterface FileContent {\n path: string;\n content: string;\n}\n\nasync function scanDirectory(\n dir: string,\n baseDir: string,\n): Promise<FileContent[]> {\n const files: FileContent[] = [];\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n const skipDirs = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \".git\",\n \".turbo\",\n ];\n if (!skipDirs.includes(entry.name)) {\n const subFiles = await scanDirectory(fullPath, baseDir);\n files.push(...subFiles);\n }\n } else if (entry.isFile()) {\n const includeExts = [\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".json\",\n \".css\",\n \".md\",\n \".mdx\",\n ];\n const ext = extname(entry.name).toLowerCase();\n\n if (\n includeExts.includes(ext) ||\n entry.name === \"package.json\" ||\n entry.name === \"tsconfig.json\"\n ) {\n try {\n const content = await readFile(fullPath, \"utf-8\");\n const relativePath = relative(baseDir, fullPath);\n files.push({ path: relativePath, content });\n } catch (error) {\n logger.warn(`Failed to read file: ${fullPath}`, error);\n }\n }\n }\n }\n } catch (error) {\n logger.error(`Failed to scan directory: ${dir}`, error);\n }\n\n return files;\n}\n\nfunction getFileType(filename: string): string {\n const ext = extname(filename).toLowerCase();\n const extMap: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"tsx\",\n \".js\": \"javascript\",\n \".jsx\": \"jsx\",\n \".json\": \"json\",\n \".css\": \"css\",\n \".md\": \"markdown\",\n \".mdx\": \"mdx\",\n };\n return extMap[ext] || \"text\";\n}\n\nexport async function prepareCodeExamples(): Promise<void> {\n logger.info(\"Preparing code examples...\");\n\n try {\n await rm(OUTPUT_DIR, { recursive: true, force: true });\n await mkdir(OUTPUT_DIR, { recursive: true });\n\n const exampleDirs = await readdir(EXAMPLES_PATH, { withFileTypes: true });\n\n for (const dir of exampleDirs) {\n if (dir.isDirectory() && !dir.name.startsWith(\".\")) {\n const examplePath = join(EXAMPLES_PATH, dir.name);\n logger.info(`Processing example: ${dir.name}`);\n\n let description = \"\";\n try {\n const packageJsonPath = join(examplePath, \"package.json\");\n const packageJson = JSON.parse(\n await readFile(packageJsonPath, \"utf-8\"),\n );\n description = packageJson.description || \"\";\n } catch (error: any) {\n if (error?.code !== \"ENOENT\") {\n logger.warn(`Failed to read package.json for ${dir.name}:`, error);\n } else {\n logger.debug(`No package.json found for example: ${dir.name}`);\n }\n }\n\n const files = await scanDirectory(examplePath, examplePath);\n\n files.sort((a, b) => a.path.localeCompare(b.path));\n\n let markdown = `# Example: ${dir.name}\\n\\n`;\n if (description) {\n markdown += `${description}\\n\\n`;\n }\n\n let totalLines = 0;\n for (const file of files) {\n const lines = file.content.split(\"\\n\").length;\n if (totalLines + lines > MAX_LINES) {\n markdown += `\\n_Note: Additional files truncated due to size limits_\\n`;\n break;\n }\n\n // Normalize Windows backslashes to forward slashes for consistent markdown output\n markdown += `## ${file.path.replace(/\\\\/g, \"/\")}\\n\\n`;\n markdown += `\\`\\`\\`${getFileType(file.path)}\\n`;\n markdown += file.content;\n markdown += `\\n\\`\\`\\`\\n\\n`;\n\n totalLines += lines;\n }\n\n const outputPath = join(OUTPUT_DIR, `${dir.name}.md`);\n await writeFile(outputPath, markdown, \"utf-8\");\n logger.debug(`Created example: ${outputPath}`);\n }\n }\n\n logger.info(\"Code examples preparation complete\");\n } catch (error) {\n logger.error(\"Failed to prepare code examples\", error);\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/stdio.d.ts CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export {}
@@ -1,18 +1,14 @@
1
- import { z } from "zod/v3";
1
+ import { z } from "zod";
2
2
  //#region src/tools/docs.d.ts
3
3
  declare const docsInputSchema: z.ZodObject<{
4
- paths: z.ZodArray<z.ZodString, "many">;
5
- }, "strip", z.ZodTypeAny, {
6
- paths: string[];
7
- }, {
8
- paths: string[];
9
- }>;
4
+ paths: z.ZodArray<z.ZodString>;
5
+ }, z.core.$strip>;
10
6
  declare const docsTools: {
11
7
  name: string;
12
8
  description: string;
13
- parameters: {
14
- paths: z.ZodArray<z.ZodString, "many">;
15
- };
9
+ parameters: z.ZodObject<{
10
+ paths: z.ZodArray<z.ZodString>;
11
+ }, z.core.$strip>;
16
12
  execute: ({ paths }: z.infer<typeof docsInputSchema>) => Promise<{
17
13
  content: Array<{
18
14
  type: "text";
@@ -1 +1 @@
1
- {"version":3,"file":"docs.d.ts","names":[],"sources":["../../src/tools/docs.ts"],"mappings":";;cAoBM,iBAAe,EAAA;;;;;;;cA+LR;;;;;;uBAKgB,EAAE,aAAa,qBAAgB"}
1
+ {"version":3,"file":"docs.d.ts","names":[],"sources":["../../src/tools/docs.ts"],"mappings":";;cAoBM,iBAAe,EAAA;;GAOnB,EAAA,KAAA;cAwLW;;;;;;EAKgB,YAAA,SAAA,EAAE,aAAa,qBAAgB"}
@@ -5,7 +5,7 @@ import { formatMDXContent, readMDXFile } from "../utils/mdx.js";
5
5
  import { formatMCPResponse } from "../utils/mcp-format.js";
6
6
  import { sanitizePath } from "../utils/security.js";
7
7
  import { extname, join } from "node:path";
8
- import { z } from "zod/v3";
8
+ import { z } from "zod";
9
9
  import { lstat, stat } from "node:fs/promises";
10
10
  //#region src/tools/docs.ts
11
11
  const docsInputSchema = z.object({ paths: z.array(z.string()).min(1).describe("Documentation paths to retrieve (e.g., [\"getting-started\", \"api-reference/primitives/thread\"])") });
@@ -138,7 +138,7 @@ async function readDocumentation(docPath) {
138
138
  const docsTools = {
139
139
  name: "assistantUIDocs",
140
140
  description: "Retrieve assistant-ui documentation by path. Use \"/\" to list all sections. Supports multiple paths in a single request.",
141
- parameters: docsInputSchema.shape,
141
+ parameters: docsInputSchema,
142
142
  execute: async ({ paths }) => {
143
143
  logger.info(`Retrieving documentation for paths: ${paths.join(", ")}`);
144
144
  try {