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

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 (155) hide show
  1. package/.docs/organized/code-examples/waterfall.md +12 -13
  2. package/.docs/organized/code-examples/with-a2a.md +16 -11
  3. package/.docs/organized/code-examples/with-ag-ui.md +15 -13
  4. package/.docs/organized/code-examples/with-ai-sdk-v7.md +14 -13
  5. package/.docs/organized/code-examples/with-artifacts.md +14 -13
  6. package/.docs/organized/code-examples/with-assistant-transport.md +20 -28
  7. package/.docs/organized/code-examples/with-browser-extension.md +18 -11
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +17 -15
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -11
  10. package/.docs/organized/code-examples/with-cloud.md +19 -14
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +15 -14
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +14 -14
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +19 -17
  14. package/.docs/organized/code-examples/with-eve.md +66 -12
  15. package/.docs/organized/code-examples/with-expo.md +26 -31
  16. package/.docs/organized/code-examples/with-external-store.md +17 -12
  17. package/.docs/organized/code-examples/with-ffmpeg.md +21 -15
  18. package/.docs/organized/code-examples/with-generative-ui.md +271 -36
  19. package/.docs/organized/code-examples/with-google-adk.md +17 -12
  20. package/.docs/organized/code-examples/with-heat-graph.md +6 -7
  21. package/.docs/organized/code-examples/with-image-generation.md +9 -10
  22. package/.docs/organized/code-examples/with-interactables.md +14 -13
  23. package/.docs/organized/code-examples/with-langchain.md +12 -13
  24. package/.docs/organized/code-examples/with-langgraph.md +19 -13
  25. package/.docs/organized/code-examples/with-livekit.md +13 -13
  26. package/.docs/organized/code-examples/with-mcp.md +14 -15
  27. package/.docs/organized/code-examples/with-nuxt.md +2428 -0
  28. package/.docs/organized/code-examples/with-opencode.md +23 -14
  29. package/.docs/organized/code-examples/with-openui.md +449 -0
  30. package/.docs/organized/code-examples/with-pi.md +59 -57
  31. package/.docs/organized/code-examples/with-react-hook-form.md +16 -15
  32. package/.docs/organized/code-examples/with-react-ink-web.md +7 -8
  33. package/.docs/organized/code-examples/with-react-ink.md +6 -6
  34. package/.docs/organized/code-examples/with-react-router.md +17 -11
  35. package/.docs/organized/code-examples/with-resumable-stream.md +12 -13
  36. package/.docs/organized/code-examples/with-store.md +27 -16
  37. package/.docs/organized/code-examples/with-svelte.md +415 -0
  38. package/.docs/organized/code-examples/with-sveltekit.md +1061 -0
  39. package/.docs/organized/code-examples/with-tanstack.md +19 -13
  40. package/.docs/organized/code-examples/with-tap-runtime.md +15 -15
  41. package/.docs/organized/code-examples/with-virtualized-thread.md +8 -9
  42. package/.docs/organized/code-examples/with-vue.md +408 -0
  43. package/.docs/raw/docs/(docs)/cli.mdx +7 -2
  44. package/.docs/raw/docs/(docs)/index.mdx +9 -76
  45. package/.docs/raw/docs/(docs)/installation.mdx +6 -20
  46. package/.docs/raw/docs/(reference)/api-reference/context-providers/assistant-runtime-provider.mdx +24 -4
  47. package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +5 -1
  48. package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +9 -2
  49. package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +2 -2
  50. package/.docs/raw/docs/(reference)/api-reference/integrations/eve.mdx +47 -1
  51. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +29 -4
  52. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +1 -1
  53. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +52 -1
  54. package/.docs/raw/docs/(reference)/api-reference/voice/session.mdx +1 -1
  55. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +2 -2
  56. package/.docs/raw/docs/cloud/ai-sdk.mdx +4 -4
  57. package/.docs/raw/docs/cloud/index.mdx +1 -1
  58. package/.docs/raw/docs/copilots/model-context.mdx +4 -3
  59. package/.docs/raw/docs/copilots/motivation.mdx +4 -4
  60. package/.docs/raw/docs/guides/attachments.mdx +2 -2
  61. package/.docs/raw/docs/guides/chain-of-thought.mdx +1 -1
  62. package/.docs/raw/docs/guides/context-api.mdx +15 -17
  63. package/.docs/raw/docs/guides/dictation.mdx +1 -1
  64. package/.docs/raw/docs/guides/electron.mdx +1 -1
  65. package/.docs/raw/docs/guides/mentions.mdx +2 -0
  66. package/.docs/raw/docs/guides/resumable-streams.mdx +74 -3
  67. package/.docs/raw/docs/guides/suggestions.mdx +15 -12
  68. package/.docs/raw/docs/ink/hooks.mdx +9 -4
  69. package/.docs/raw/docs/ink/primitives.mdx +5 -4
  70. package/.docs/raw/docs/integrations/attachments/custom-adapter.mdx +16 -0
  71. package/.docs/raw/docs/integrations/auth/better-auth.mdx +1 -1
  72. package/.docs/raw/docs/integrations/auth/clerk.mdx +1 -1
  73. package/.docs/raw/docs/integrations/auth/next-auth.mdx +1 -1
  74. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +1 -1
  75. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +2 -2
  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/observability/helicone.mdx +2 -2
  79. package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
  80. package/.docs/raw/docs/integrations/observability/langsmith.mdx +2 -2
  81. package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +146 -128
  82. package/.docs/raw/docs/migrations/toolkit-tools.mdx +15 -13
  83. package/.docs/raw/docs/migrations/v0-15.mdx +118 -4
  84. package/.docs/raw/docs/primitives/attachment.mdx +2 -2
  85. package/.docs/raw/docs/primitives/composer.mdx +2 -2
  86. package/.docs/raw/docs/primitives/message.mdx +33 -1
  87. package/.docs/raw/docs/primitives/suggestion.mdx +4 -2
  88. package/.docs/raw/docs/primitives/thread.mdx +1 -1
  89. package/.docs/raw/docs/react-native/hooks.mdx +14 -4
  90. package/.docs/raw/docs/react-native/index.mdx +1 -1
  91. package/.docs/raw/docs/react-native/primitives.mdx +2 -2
  92. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +35 -5
  93. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +1 -1
  94. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +1 -1
  95. package/.docs/raw/docs/runtimes/ai-sdk/v6-legacy.mdx +9 -10
  96. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +9 -10
  97. package/.docs/raw/docs/runtimes/claude-managed-agents.mdx +118 -0
  98. package/.docs/raw/docs/runtimes/concepts/stability.mdx +2 -1
  99. package/.docs/raw/docs/runtimes/concepts/threads.mdx +106 -27
  100. package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +19 -1
  101. package/.docs/raw/docs/runtimes/custom/external-store.mdx +34 -1
  102. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +36 -9
  103. package/.docs/raw/docs/runtimes/eve/overview.mdx +51 -0
  104. package/.docs/raw/docs/runtimes/eve/quickstart.mdx +51 -2
  105. package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +9 -12
  106. package/.docs/raw/docs/runtimes/langchain.mdx +1 -1
  107. package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +5 -1
  108. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -7
  109. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +4 -4
  110. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +1 -0
  111. package/.docs/raw/docs/runtimes/opencode/overview.mdx +10 -0
  112. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +8 -1
  113. package/.docs/raw/docs/tools/backend.mdx +2 -2
  114. package/.docs/raw/docs/tools/defining-tools.mdx +28 -7
  115. package/.docs/raw/docs/tools/dynamic-tools.mdx +6 -4
  116. package/.docs/raw/docs/tools/generative-ui-primitive.mdx +180 -0
  117. package/.docs/raw/docs/tools/generative-ui-slack.mdx +167 -0
  118. package/.docs/raw/docs/tools/generative-ui-teams.mdx +160 -0
  119. package/.docs/raw/docs/tools/generative-ui.mdx +224 -211
  120. package/.docs/raw/docs/tools/index.mdx +2 -1
  121. package/.docs/raw/docs/tools/interactables.mdx +29 -17
  122. package/.docs/raw/docs/tools/mcp-apps.mdx +35 -6
  123. package/.docs/raw/docs/tools/mcp.mdx +9 -7
  124. package/.docs/raw/docs/tools/openui.mdx +175 -0
  125. package/.docs/raw/docs/tools/tool-ui.mdx +27 -24
  126. package/.docs/raw/docs/tools/user-managed-mcp.mdx +17 -8
  127. package/.docs/raw/docs/ui/attachment.mdx +27 -0
  128. package/.docs/raw/docs/ui/file.mdx +7 -2
  129. package/.docs/raw/docs/ui/image.mdx +1 -1
  130. package/.docs/raw/docs/ui/mcp-config.mdx +8 -3
  131. package/.docs/raw/docs/ui/model-selector.mdx +8 -8
  132. package/.docs/raw/docs/ui/part-grouping.mdx +1 -1
  133. package/.docs/raw/docs/ui/thread.mdx +24 -5
  134. package/.docs/raw/docs/utilities/react-o11y.mdx +7 -9
  135. package/dist/constants.js +2 -2
  136. package/dist/constants.js.map +1 -1
  137. package/dist/index.js.map +1 -1
  138. package/dist/prepare-docs/prepare.js.map +1 -1
  139. package/dist/tools/docs.js +4 -2
  140. package/dist/tools/docs.js.map +1 -1
  141. package/dist/tools/examples.js +2 -1
  142. package/dist/tools/examples.js.map +1 -1
  143. package/dist/tools/resources.js +2 -1
  144. package/dist/tools/resources.js.map +1 -1
  145. package/dist/tools/tests/test-setup.js +2 -1
  146. package/dist/tools/tests/test-setup.js.map +1 -1
  147. package/dist/tools/xulux-templates.js +4 -2
  148. package/dist/tools/xulux-templates.js.map +1 -1
  149. package/dist/utils/mdx.js +2 -1
  150. package/dist/utils/mdx.js.map +1 -1
  151. package/dist/xulux/catalog-client.js +1 -1
  152. package/dist/xulux/catalog-client.js.map +1 -1
  153. package/package.json +4 -4
  154. package/src/tools/tests/docs.test.ts +2 -2
  155. package/.docs/raw/docs/tools/interactables-legacy.mdx +0 -410
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-client.js","names":[],"sources":["../../src/xulux/catalog-client.ts"],"sourcesContent":["import { logger } from \"../utils/logger.js\";\nimport { FALLBACK_CATALOG, FALLBACK_NOTE } from \"./fallback-catalog.js\";\nimport type { XuluxCatalog, XuluxCatalogResult } from \"./types.js\";\n\nexport const DEFAULT_CATALOG_URL =\n \"https://www.assistant-ui.com/api/xulux/mcp-catalog\";\n\nconst CATALOG_TTL_MS = 5 * 60 * 1000;\n\nexport function getCatalogUrl(): string {\n const override = process.env.XULUX_CATALOG_URL?.trim();\n return override || DEFAULT_CATALOG_URL;\n}\n\nfunction validateCatalog(data: unknown): XuluxCatalog {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n throw new Error(\"Catalog response is not a JSON object.\");\n }\n const catalog = data as XuluxCatalog;\n if (catalog.version !== 1) {\n throw new Error(\n `Unsupported catalog version: ${String(catalog.version)}. Expected 1.`,\n );\n }\n if (!Array.isArray(catalog.templates)) {\n throw new Error(\"Catalog response has no templates array.\");\n }\n for (const template of catalog.templates) {\n if (\n !template ||\n typeof template !== \"object\" ||\n typeof template.id !== \"string\" ||\n typeof template.templateId !== \"string\" ||\n (template.kind !== \"template\" && template.kind !== \"example\")\n ) {\n throw new Error(\n \"Catalog response contains a malformed template entry (missing id/templateId/kind).\",\n );\n }\n }\n return catalog;\n}\n\ninterface CacheEntry {\n catalog: XuluxCatalog;\n fetchedAt: number;\n url: string;\n}\n\nlet cache: CacheEntry | null = null;\n\nexport function clearCatalogCache(): void {\n cache = null;\n}\n\nasync function fetchCatalog(url: string): Promise<XuluxCatalog> {\n const res = await fetch(url, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`Catalog fetch failed: HTTP ${res.status}`);\n }\n const data: unknown = await res.json();\n return validateCatalog(data);\n}\n\n/**\n * Returns the assistant-ui template catalog. Uses an in-memory five-minute cache, and falls\n * back to a minimal bundled catalog (marked degraded) when the live fetch\n * fails and no cached copy exists.\n */\nexport async function getXuluxCatalog(): Promise<XuluxCatalogResult> {\n const url = getCatalogUrl();\n const now = Date.now();\n\n if (cache && cache.url === url && now - cache.fetchedAt < CATALOG_TTL_MS) {\n return { catalog: cache.catalog, degraded: false };\n }\n\n try {\n const catalog = await fetchCatalog(url);\n cache = { catalog, fetchedAt: now, url };\n return { catalog, degraded: false };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn(\n `assistant-ui template catalog fetch failed (${url}): ${message}`,\n );\n\n // Prefer a stale cached copy over the minimal fallback.\n if (cache && cache.url === url) {\n return {\n catalog: cache.catalog,\n degraded: true,\n degradedReason: `Live catalog refresh failed (${message}); using previously fetched catalog.`,\n };\n }\n\n return {\n catalog: FALLBACK_CATALOG,\n degraded: true,\n degradedReason: `${message} ${FALLBACK_NOTE}`,\n };\n }\n}\n"],"mappings":";;;AAIA,MAAa,sBACX;AAEF,MAAM,iBAAiB,MAAS;AAEhC,SAAgB,gBAAwB;CAEtC,OADiB,QAAQ,IAAI,mBAAmB,KAAK,KAAA;AAEvD;AAEA,SAAS,gBAAgB,MAA6B;CACpD,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,wCAAwC;CAE1D,MAAM,UAAU;CAChB,IAAI,QAAQ,YAAY,GACtB,MAAM,IAAI,MACR,gCAAgC,OAAO,QAAQ,OAAO,EAAE,cAC1D;CAEF,IAAI,CAAC,MAAM,QAAQ,QAAQ,SAAS,GAClC,MAAM,IAAI,MAAM,0CAA0C;CAE5D,KAAK,MAAM,YAAY,QAAQ,WAC7B,IACE,CAAC,YACD,OAAO,aAAa,YACpB,OAAO,SAAS,OAAO,YACvB,OAAO,SAAS,eAAe,YAC9B,SAAS,SAAS,cAAc,SAAS,SAAS,WAEnD,MAAM,IAAI,MACR,oFACF;CAGJ,OAAO;AACT;AAQA,IAAI,QAA2B;AAE/B,SAAgB,oBAA0B;CACxC,QAAQ;AACV;AAEA,eAAe,aAAa,KAAoC;CAC9D,MAAM,MAAM,MAAM,MAAM,KAAK,EAC3B,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;CACD,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,8BAA8B,IAAI,QAAQ;CAG5D,OAAO,gBAAgB,MADK,IAAI,KAAK,CACV;AAC7B;;;;;;AAOA,eAAsB,kBAA+C;CACnE,MAAM,MAAM,cAAc;CAC1B,MAAM,MAAM,KAAK,IAAI;CAErB,IAAI,SAAS,MAAM,QAAQ,OAAO,MAAM,MAAM,YAAY,gBACxD,OAAO;EAAE,SAAS,MAAM;EAAS,UAAU;CAAM;CAGnD,IAAI;EACF,MAAM,UAAU,MAAM,aAAa,GAAG;EACtC,QAAQ;GAAE;GAAS,WAAW;GAAK;EAAI;EACvC,OAAO;GAAE;GAAS,UAAU;EAAM;CACpC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO,KACL,+CAA+C,IAAI,KAAK,SAC1D;EAGA,IAAI,SAAS,MAAM,QAAQ,KACzB,OAAO;GACL,SAAS,MAAM;GACf,UAAU;GACV,gBAAgB,gCAAgC,QAAQ;EAC1D;EAGF,OAAO;GACL,SAAS;GACT,UAAU;GACV,gBAAgB,GAAG,QAAQ,GAAG;EAChC;CACF;AACF"}
1
+ {"version":3,"file":"catalog-client.js","names":[],"sources":["../../src/xulux/catalog-client.ts"],"sourcesContent":["import { logger } from \"../utils/logger.js\";\nimport { FALLBACK_CATALOG, FALLBACK_NOTE } from \"./fallback-catalog.js\";\nimport type { XuluxCatalog, XuluxCatalogResult } from \"./types.js\";\n\nexport const DEFAULT_CATALOG_URL =\n \"https://www.assistant-ui.com/api/xulux/mcp-catalog\";\n\nconst CATALOG_TTL_MS = 5 * 60 * 1000;\n\nexport function getCatalogUrl(): string {\n const override = process.env.XULUX_CATALOG_URL?.trim();\n return override || DEFAULT_CATALOG_URL;\n}\n\nfunction validateCatalog(data: unknown): XuluxCatalog {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n throw new Error(\"Catalog response is not a JSON object.\");\n }\n const catalog = data as XuluxCatalog;\n if (catalog.version !== 1) {\n throw new Error(\n `Unsupported catalog version: ${String(catalog.version)}. Expected 1.`,\n );\n }\n if (!Array.isArray(catalog.templates)) {\n throw new Error(\"Catalog response has no templates array.\");\n }\n for (const template of catalog.templates) {\n if (\n !template ||\n typeof template !== \"object\" ||\n typeof template.id !== \"string\" ||\n typeof template.templateId !== \"string\" ||\n (template.kind !== \"template\" && template.kind !== \"example\")\n ) {\n throw new Error(\n \"Catalog response contains a malformed template entry (missing id/templateId/kind).\",\n );\n }\n }\n return catalog;\n}\n\ninterface CacheEntry {\n catalog: XuluxCatalog;\n fetchedAt: number;\n url: string;\n}\n\nlet cache: CacheEntry | null = null;\n\nexport function clearCatalogCache(): void {\n cache = null;\n}\n\nasync function fetchCatalog(url: string): Promise<XuluxCatalog> {\n const res = await fetch(url, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`Catalog fetch failed: HTTP ${res.status}`);\n }\n const data: unknown = await res.json();\n return validateCatalog(data);\n}\n\n/**\n * Returns the assistant-ui template catalog. Uses an in-memory five-minute cache, and falls\n * back to a minimal bundled catalog (marked degraded) when the live fetch\n * fails and no cached copy exists.\n */\nexport async function getXuluxCatalog(): Promise<XuluxCatalogResult> {\n const url = getCatalogUrl();\n const now = Date.now();\n\n if (cache && cache.url === url && now - cache.fetchedAt < CATALOG_TTL_MS) {\n return { catalog: cache.catalog, degraded: false };\n }\n\n try {\n const catalog = await fetchCatalog(url);\n cache = { catalog, fetchedAt: now, url };\n return { catalog, degraded: false };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn(\n `assistant-ui template catalog fetch failed (${url}): ${message}`,\n );\n\n // Prefer a stale cached copy over the minimal fallback.\n if (cache && cache.url === url) {\n return {\n catalog: cache.catalog,\n degraded: true,\n degradedReason: `Live catalog refresh failed (${message}); using previously fetched catalog.`,\n };\n }\n\n return {\n catalog: FALLBACK_CATALOG,\n degraded: true,\n degradedReason: `${message} ${FALLBACK_NOTE}`,\n };\n }\n}\n"],"mappings":";;;AAIA,MAAa,sBACX;AAEF,MAAM,iBAAiB;AAEvB,SAAgB,gBAAwB;CAEtC,OADiB,QAAQ,IAAI,mBAAmB,KAAK,KAAA;AAEvD;AAEA,SAAS,gBAAgB,MAA6B;CACpD,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,wCAAwC;CAE1D,MAAM,UAAU;CAChB,IAAI,QAAQ,YAAY,GACtB,MAAM,IAAI,MACR,gCAAgC,OAAO,QAAQ,OAAO,EAAE,cAC1D;CAEF,IAAI,CAAC,MAAM,QAAQ,QAAQ,SAAS,GAClC,MAAM,IAAI,MAAM,0CAA0C;CAE5D,KAAK,MAAM,YAAY,QAAQ,WAC7B,IACE,CAAC,YACD,OAAO,aAAa,YACpB,OAAO,SAAS,OAAO,YACvB,OAAO,SAAS,eAAe,YAC9B,SAAS,SAAS,cAAc,SAAS,SAAS,WAEnD,MAAM,IAAI,MACR,oFACF;CAGJ,OAAO;AACT;AAQA,IAAI,QAA2B;AAE/B,SAAgB,oBAA0B;CACxC,QAAQ;AACV;AAEA,eAAe,aAAa,KAAoC;CAC9D,MAAM,MAAM,MAAM,MAAM,KAAK,EAC3B,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;CACD,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,8BAA8B,IAAI,QAAQ;CAG5D,OAAO,gBAAgB,MADK,IAAI,KAAK,CACV;AAC7B;;;;;;AAOA,eAAsB,kBAA+C;CACnE,MAAM,MAAM,cAAc;CAC1B,MAAM,MAAM,KAAK,IAAI;CAErB,IAAI,SAAS,MAAM,QAAQ,OAAO,MAAM,MAAM,YAAY,gBACxD,OAAO;EAAE,SAAS,MAAM;EAAS,UAAU;CAAM;CAGnD,IAAI;EACF,MAAM,UAAU,MAAM,aAAa,GAAG;EACtC,QAAQ;GAAE;GAAS,WAAW;GAAK;EAAI;EACvC,OAAO;GAAE;GAAS,UAAU;EAAM;CACpC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO,KACL,+CAA+C,IAAI,KAAK,SAC1D;EAGA,IAAI,SAAS,MAAM,QAAQ,KACzB,OAAO;GACL,SAAS,MAAM;GACf,UAAU;GACV,gBAAgB,gCAAgC,QAAQ;EAC1D;EAGF,OAAO;GACL,SAAS;GACT,UAAU;GACV,gBAAgB,GAAG,QAAQ,GAAG;EAChC;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/mcp-docs-server",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "MCP server for assistant-ui documentation and examples",
5
5
  "keywords": [
6
6
  "mcp",
@@ -38,10 +38,10 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@modelcontextprotocol/core": "^2.0.0",
41
- "@types/node": "^26.1.1",
42
- "tsx": "^4.23.1",
41
+ "@types/node": "^26.2.0",
42
+ "tsx": "^4.23.12",
43
43
  "vitest": "^4.1.10",
44
- "@assistant-ui/x-buildutils": "0.0.20"
44
+ "@assistant-ui/x-buildutils": "0.0.23"
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public",
@@ -42,7 +42,7 @@ describe("assistantUIDocs", () => {
42
42
  expect(result.found).toBe(true);
43
43
  expect(result.type).toBe("file");
44
44
  expect(result.content).toBeDefined();
45
- expect(result.content).toContain("assistant-ui");
45
+ expect(result.content).toContain("title: Documentation");
46
46
  });
47
47
 
48
48
  it("should handle non-existent paths", async () => {
@@ -88,7 +88,7 @@ describe("assistantUIDocs", () => {
88
88
 
89
89
  expect(result.content).toBeDefined();
90
90
  expect(result.content).toContain("title:");
91
- expect(result.content).toContain("assistant-ui");
91
+ expect(result.content).toContain("description:");
92
92
  });
93
93
 
94
94
  it("includes title and excerpt on a file response", async () => {
@@ -1,410 +0,0 @@
1
- ---
2
- title: Interactables (legacy)
3
- description: Build persistent UI elements whose state the AI can read and update — copilot interactables in React with assistant-ui for forms, dashboards, and tools.
4
- platforms: ["react"]
5
- ---
6
-
7
- <Callout type="warn">
8
- This legacy API is deprecated. For new code, use the [`unstable_` interactables API](/docs/tools/interactables). We recomment switching beccause this legacy API passes state by mutating the system message, the new, `unstable_` tagged API solves this.
9
- </Callout>
10
-
11
- Interactables are React components that live outside the chat message flow and have state that both the user and the AI can read and write. This enables AI-driven UI patterns where the assistant controls parts of your application beyond the chat window.
12
-
13
-
14
- ## Overview
15
-
16
- Unlike regular tool UIs that appear inline within messages, interactables:
17
-
18
- - **Persist across messages** — they live outside the chat thread
19
- - **Have shared state** — both the user (via React) and the AI (via auto-generated tools) can update them
20
- - **Support partial updates** — the AI only needs to send the fields it wants to change
21
- - **Are developer-placed** — you decide where they render in your app
22
- - **Auto-register tools** — the AI automatically gets a tool to update each interactable's state
23
-
24
- Common use cases:
25
-
26
- - Task boards that the AI can add items to
27
- - Data dashboards that update based on conversation
28
- - Forms that the AI pre-fills
29
- - Canvas/editor components that the AI can manipulate
30
-
31
- ## Quick Start
32
-
33
- ### 1. Register the Interactables scope
34
-
35
- ```tsx
36
- import { useAui, Interactables, AssistantRuntimeProvider } from "@assistant-ui/react";
37
- import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
38
-
39
- function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
40
- const runtime = useChatRuntime();
41
-
42
- const aui = useAui({
43
- interactables: Interactables(), // [!code ++]
44
- });
45
-
46
- return (
47
- <AssistantRuntimeProvider aui={aui} runtime={runtime}>
48
- {children}
49
- </AssistantRuntimeProvider>
50
- );
51
- }
52
- ```
53
-
54
- <Callout type="idea">
55
- The legacy `interactables: Interactables()` scope and the new
56
- `unstable_interactables: unstable_Interactables()` scope are mutually
57
- exclusive. Mount only one interactables API in a single `useAui` provider.
58
- </Callout>
59
-
60
- ### 2. Create an interactable
61
-
62
- ```tsx
63
- import { useAssistantInteractable, useInteractableState } from "@assistant-ui/react";
64
- import { z } from "zod";
65
-
66
- const taskBoardSchema = z.object({
67
- tasks: z.array(
68
- z.object({
69
- id: z.string(),
70
- title: z.string(),
71
- done: z.boolean(),
72
- }),
73
- ),
74
- });
75
-
76
- const taskBoardInitialState = { tasks: [] };
77
-
78
- function TaskBoard() {
79
- const id = useAssistantInteractable("taskBoard", {
80
- description: "A task board showing the user's tasks",
81
- stateSchema: taskBoardSchema,
82
- initialState: taskBoardInitialState,
83
- });
84
- const [state, { setState }] = useInteractableState(id, taskBoardInitialState);
85
-
86
- return (
87
- <div>
88
- <h2>Tasks</h2>
89
- <ul>
90
- {state.tasks.map((task) => (
91
- <li key={task.id}>
92
- <label>
93
- <input
94
- type="checkbox"
95
- checked={task.done}
96
- onChange={() =>
97
- setState((prev) => ({
98
- tasks: prev.tasks.map((t) =>
99
- t.id === task.id ? { ...t, done: !t.done } : t,
100
- ),
101
- }))
102
- }
103
- />
104
- {task.title}
105
- </label>
106
- </li>
107
- ))}
108
- </ul>
109
- </div>
110
- );
111
- }
112
- ```
113
-
114
- <Callout type="warn">
115
- Define the `stateSchema` and `initialState` **outside** the component (or
116
- memoize them). Creating a new schema on every render will cause the
117
- interactable to re-register and reset its state.
118
- </Callout>
119
-
120
- ### 3. Place it in your layout
121
-
122
- ```tsx
123
- function App() {
124
- return (
125
- <MyRuntimeProvider>
126
- <div className="flex">
127
- <Thread className="flex-1" />
128
- <TaskBoard /> {/* Lives outside the chat */}
129
- </div>
130
- </MyRuntimeProvider>
131
- );
132
- }
133
- ```
134
-
135
- Now when the user says _"Add a task called 'Buy groceries'"_, the AI will automatically call the `update_taskBoard` tool to update the state. Thanks to partial updates, the AI only needs to send the fields it wants to change.
136
-
137
- ## Partial Updates
138
-
139
- Auto-generated tools use a partial schema — all fields become optional. The AI only sends the fields it wants to change; omitted fields keep their current values.
140
-
141
- ```tsx
142
- // If the state is { title: "My Note", content: "Hello", color: "yellow" }
143
- // The AI can call: update_note({ color: "blue" })
144
- // Result: { title: "My Note", content: "Hello", color: "blue" }
145
- ```
146
-
147
- This is especially useful for large state objects where regenerating the entire state would be expensive and error-prone.
148
-
149
- <Callout type="info">
150
- Merge is shallow (one level deep). If the AI sends a nested object, it replaces
151
- that entire field rather than deep-merging into it.
152
- </Callout>
153
-
154
- ## Multiple Instances
155
-
156
- You can render multiple interactables with the same `name` but different `id`s. Each gets its own update tool:
157
-
158
- ```tsx
159
- import { useAssistantInteractable, useInteractableState } from "@assistant-ui/react";
160
- import { z } from "zod";
161
-
162
- const noteSchema = z.object({
163
- title: z.string(),
164
- content: z.string(),
165
- color: z.enum(["yellow", "blue", "green", "pink"]),
166
- });
167
-
168
- const noteInitialState = { title: "New Note", content: "", color: "yellow" as const };
169
-
170
- function NoteCard({ noteId }: { noteId: string }) {
171
- useAssistantInteractable("note", {
172
- id: noteId,
173
- description: "A sticky note",
174
- stateSchema: noteSchema,
175
- initialState: noteInitialState,
176
- });
177
- const [state] = useInteractableState(noteId, noteInitialState);
178
-
179
- return <div>{state.title}</div>;
180
- }
181
-
182
- function App() {
183
- return (
184
- <>
185
- <NoteCard noteId="note-1" /> {/* → update_note_note-1 tool */}
186
- <NoteCard noteId="note-2" /> {/* → update_note_note-2 tool */}
187
- </>
188
- );
189
- }
190
- ```
191
-
192
- When only one instance of a name exists, the tool is named `update_{name}` (e.g., `update_note`). When multiple instances exist, tools are named `update_{name}_{id}` (e.g., `update_note_note-1`).
193
-
194
- ## Selection
195
-
196
- When multiple interactables are present, you can mark one as "selected" to tell the AI which one the user is focused on:
197
-
198
- ```tsx
199
- function NoteCard({ noteId }: { noteId: string }) {
200
- useAssistantInteractable("note", {
201
- id: noteId,
202
- description: "A sticky note",
203
- stateSchema: noteSchema,
204
- initialState: noteInitialState,
205
- });
206
- const [state, { setSelected }] = useInteractableState(noteId, noteInitialState);
207
-
208
- return (
209
- <div onClick={() => setSelected(true)}>
210
- {state.title}
211
- </div>
212
- );
213
- }
214
- ```
215
-
216
- The AI sees `(SELECTED)` in the system prompt for the focused interactable, allowing it to prioritize that one in responses. For example, the user can say _"Change the color to blue"_ and the AI knows which note to update.
217
-
218
- ## API Reference
219
-
220
- ### `useAssistantInteractable`
221
-
222
- Registers an interactable with the AI assistant. Returns the instance id.
223
-
224
- ```tsx
225
- const id = useAssistantInteractable(name, config);
226
- ```
227
-
228
- **Parameters:**
229
-
230
- | Parameter | Type | Description |
231
- | --- | --- | --- |
232
- | `name` | `string` | Name for the interactable (used in tool names) |
233
- | `config.description` | `string` | Description shown to the AI |
234
- | `config.stateSchema` | `StandardSchemaV1 \| JSONSchema7` | Schema for the state (e.g., a Zod schema) |
235
- | `config.initialState` | `unknown` | Initial state value |
236
- | `config.id` | `string?` | Optional unique instance ID (auto-generated if omitted) |
237
- | `config.selected` | `boolean?` | Whether this interactable is selected |
238
-
239
- **Returns:** `string` — the instance id (auto-generated or provided).
240
-
241
- ### `useInteractableState`
242
-
243
- Reads and writes the state of a registered interactable.
244
-
245
- ```tsx
246
- const [state, { setState, setSelected, isPending, error, flush }] = useInteractableState<TState>(id, fallback?);
247
- ```
248
-
249
- **Parameters:**
250
-
251
- | Parameter | Type | Description |
252
- | --- | --- | --- |
253
- | `id` | `string` | The interactable instance id (from `useAssistantInteractable`) |
254
- | `fallback` | `TState?` | Fallback value before the interactable is registered |
255
-
256
- **Returns:** `[state, methods]`
257
-
258
- | Return | Type | Description |
259
- | --- | --- | --- |
260
- | `state` | `TState` | Current state |
261
- | `setState` | `(updater: TState \| (prev: TState) => TState) => void` | State setter (like `useState`) |
262
- | `setSelected` | `(selected: boolean) => void` | Mark this interactable as selected |
263
- | `isPending` | `boolean` | Whether a persistence save is in-flight |
264
- | `error` | `unknown` | Error from the last failed save |
265
- | `flush` | `() => Promise<void>` | Force an immediate persistence save |
266
-
267
- ### `Interactables`
268
-
269
- The scope resource that manages all interactables. Register it via `useAui`:
270
-
271
- ```tsx
272
- const aui = useAui({
273
- interactables: Interactables(),
274
- });
275
- ```
276
-
277
- ## How It Works
278
-
279
- When you call `useAssistantInteractable("taskBoard", config)`:
280
-
281
- 1. **Registration** — the interactable is registered in the `interactables` scope with its name, description, schema, and initial state.
282
- 2. **Tool generation** — an `update_taskBoard` frontend tool is automatically created with a partial schema (all fields optional). For multiple instances, tools are named `update_{name}_{id}`.
283
- 3. **System prompt** — the AI receives a system message describing the interactable, its current state, and whether it is selected.
284
- 4. **Streaming updates** — as the AI generates the tool arguments, the interactable's state updates progressively rather than waiting for complete arguments. This gives users immediate visual feedback.
285
- 5. **Partial merge** — only the fields the AI sends are updated; the rest are preserved.
286
- 6. **Bidirectional updates** — when the AI calls the tool, the state updates and React re-renders. When the user updates state via `setState`, the model context is notified so the AI sees the latest state on the next turn.
287
-
288
- ## Persistence
289
-
290
- By default, interactable state is in-memory and lost on page refresh. You can add persistence by providing a save callback:
291
-
292
- ```tsx
293
- import { useEffect } from "react";
294
- import { useAui, Interactables } from "@assistant-ui/react";
295
-
296
- function MyRuntimeProvider({ children }) {
297
- const aui = useAui({ interactables: Interactables() });
298
-
299
- useEffect(() => {
300
- // Set up persistence adapter
301
- aui.interactables.setPersistenceAdapter({
302
- save: async (state) => {
303
- localStorage.setItem("interactables", JSON.stringify(state));
304
- },
305
- });
306
-
307
- // Restore saved state on mount
308
- const saved = localStorage.getItem("interactables");
309
- if (saved) {
310
- aui.interactables.importState(JSON.parse(saved));
311
- }
312
- }, [aui]);
313
-
314
- return /* ... */;
315
- }
316
- ```
317
-
318
- ### Sync Status
319
-
320
- When a persistence adapter is set, `useInteractableState` exposes sync metadata:
321
-
322
- ```tsx
323
- const [state, { setState, isPending, error, flush }] = useInteractableState(id, fallback);
324
-
325
- // isPending — true while a save is in-flight
326
- // error — the error from the last failed save, if any
327
- // flush() — force an immediate save (useful before navigation)
328
- ```
329
-
330
- State changes are automatically debounced (500ms) before saving. When a component unregisters, any pending save is flushed immediately.
331
-
332
- ### Export / Import
333
-
334
- For custom persistence strategies, use `exportState` and `importState` directly:
335
-
336
- ```tsx
337
- const snapshot = aui.interactables.exportState();
338
- // => { "note-1": { name: "note", state: { title: "Hello" } }, ... }
339
-
340
- aui.interactables.importState(snapshot);
341
- // Imported state is picked up when components next register
342
- ```
343
-
344
- ## Combining with Tools
345
-
346
- You can use `Interactables` alongside `Tools`:
347
-
348
- ```tsx
349
- const aui = useAui({
350
- tools: Tools({ toolkit: myToolkit }),
351
- interactables: Interactables(),
352
- });
353
- ```
354
-
355
- ## Streaming Updates
356
-
357
- While the AI is generating tool arguments, `useInteractableState` reflects the partial state in real time as fields stream in. You can use the partial state itself plus the thread's running status to show a skeleton UI while the AI is mid-stream:
358
-
359
- ```tsx
360
- import { useAuiState } from "@assistant-ui/react";
361
-
362
- function TaskBoard() {
363
- const id = useAssistantInteractable("taskBoard", config);
364
- const [state] = useInteractableState(id, taskBoardInitialState);
365
- const isRunning = useAuiState((s) => s.thread.isRunning);
366
-
367
- const isLoading = isRunning && state.tasks.length === 0;
368
-
369
- return (
370
- <div>
371
- <h2>Tasks</h2>
372
- {isLoading ? (
373
- <div className="animate-pulse h-8 rounded bg-muted" />
374
- ) : (
375
- <ul>
376
- {state.tasks.map((task) => (
377
- <li key={task.id}>{task.title}</li>
378
- ))}
379
- </ul>
380
- )}
381
- </div>
382
- );
383
- }
384
- ```
385
-
386
- The state object updates progressively as the AI streams in each field, so partial renders work without any extra wiring. Use the runtime's `isRunning` to distinguish "still streaming, no fields yet" from "model returned an empty result".
387
-
388
- ## Schema Evolution
389
-
390
- <Callout type="warn">
391
- If you change a Zod schema after state has been persisted, the imported snapshot may silently mis-match the new shape. The adapter does a shallow merge, so extra fields are preserved and missing fields keep their initial values, but type mismatches are not caught at runtime. To avoid silent corruption, version your schema key (e.g. `"taskBoard_v2"`) or namespace it by schema hash whenever you make breaking changes. Alternatively, add a migration step in your `importState` call.
392
- </Callout>
393
-
394
- ## Unmount Behavior
395
-
396
- When a component that called `useAssistantInteractable` unmounts, the interactable is unregistered from the AI's tool list and system prompt. However, its state is preserved in the `Interactables` scope. When the component mounts again with the same name and id, the scope re-merges the preserved state rather than resetting to `initialState`. This means transient unmounts (such as React Strict Mode double-mounts or tab switches) do not lose state.
397
-
398
- ## Full Example
399
-
400
- See the complete [with-interactables example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-interactables) for a working implementation featuring:
401
-
402
- - **Task Board** — single-instance interactable with a custom `manage_tasks` tool
403
- - **Sticky Notes** — multi-instance interactables with selection and partial updates
404
- - **localStorage persistence** — state survives page refresh via `setPersistenceAdapter`
405
- - **Sync indicator** — spinning icon while a save is in-flight (`isPending`)
406
-
407
- ## Related
408
-
409
- - [Tool UI](/docs/tools/tool-ui) — Inline tool call UIs rendered inside messages
410
- - [LangGraph Generative UI](/docs/runtimes/langgraph/generative-ui) — Structured UI components emitted by a LangGraph graph alongside messages