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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -9
  2. package/.docs/organized/code-examples/with-a2a.md +16 -11
  3. package/.docs/organized/code-examples/with-ag-ui.md +16 -11
  4. package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +32 -21
  5. package/.docs/organized/code-examples/with-artifacts.md +17 -10
  6. package/.docs/organized/code-examples/with-assistant-transport.md +15 -8
  7. package/.docs/organized/code-examples/with-browser-extension.md +15 -8
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +17 -10
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -9
  10. package/.docs/organized/code-examples/with-cloud.md +18 -13
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +17 -10
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +20 -13
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +20 -13
  14. package/.docs/organized/code-examples/with-eve.md +16 -9
  15. package/.docs/organized/code-examples/with-expo.md +26 -23
  16. package/.docs/organized/code-examples/with-external-store.md +16 -11
  17. package/.docs/organized/code-examples/with-ffmpeg.md +18 -13
  18. package/.docs/organized/code-examples/with-generative-ui.md +20 -15
  19. package/.docs/organized/code-examples/with-google-adk.md +16 -9
  20. package/.docs/organized/code-examples/with-heat-graph.md +8 -9
  21. package/.docs/organized/code-examples/with-image-generation.md +17 -10
  22. package/.docs/organized/code-examples/with-interactables.md +19 -15
  23. package/.docs/organized/code-examples/with-langchain.md +17 -10
  24. package/.docs/organized/code-examples/with-langgraph.md +17 -10
  25. package/.docs/organized/code-examples/with-livekit.md +21 -14
  26. package/.docs/organized/code-examples/with-mcp.md +40 -18
  27. package/.docs/organized/code-examples/with-opencode.md +22 -17
  28. package/.docs/organized/code-examples/with-pi.md +47 -12
  29. package/.docs/organized/code-examples/with-react-hook-form.md +19 -14
  30. package/.docs/organized/code-examples/with-react-ink-web.md +6 -6
  31. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  32. package/.docs/organized/code-examples/with-react-router.md +20 -15
  33. package/.docs/organized/code-examples/with-resumable-stream.md +19 -12
  34. package/.docs/organized/code-examples/with-store.md +8 -9
  35. package/.docs/organized/code-examples/with-tanstack.md +17 -11
  36. package/.docs/organized/code-examples/with-tap-runtime.md +16 -11
  37. package/.docs/organized/code-examples/with-virtualized-thread.md +17 -12
  38. package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
  39. package/.docs/raw/docs/(docs)/cli.mdx +18 -2
  40. package/.docs/raw/docs/(docs)/installation.mdx +15 -1
  41. package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
  42. package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
  43. package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
  44. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +19 -1
  45. package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
  46. package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
  47. package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
  48. package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
  49. package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
  50. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
  51. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +4 -2
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
  53. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
  54. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +29 -29
  55. package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
  58. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
  59. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
  60. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
  61. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
  62. package/.docs/raw/docs/cloud/langgraph.mdx +4 -2
  63. package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
  64. package/.docs/raw/docs/guides/dictation.mdx +185 -257
  65. package/.docs/raw/docs/guides/index.mdx +10 -0
  66. package/.docs/raw/docs/guides/mentions.mdx +31 -3
  67. package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
  68. package/.docs/raw/docs/guides/speech.mdx +47 -29
  69. package/.docs/raw/docs/guides/suggestions.mdx +70 -1
  70. package/.docs/raw/docs/guides/voice.mdx +197 -267
  71. package/.docs/raw/docs/ink/primitives.mdx +35 -1
  72. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +13 -7
  73. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
  74. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
  75. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
  76. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
  77. package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
  78. package/.docs/raw/docs/integrations/index.mdx +1 -1
  79. package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
  80. package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
  81. package/.docs/raw/docs/integrations/observability/langsmith.mdx +3 -3
  82. package/.docs/raw/docs/migrations/index.mdx +50 -0
  83. package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +2 -2
  84. package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
  85. package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
  86. package/.docs/raw/docs/primitives/composer.mdx +16 -0
  87. package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
  88. package/.docs/raw/docs/primitives/thread-list.mdx +30 -6
  89. package/.docs/raw/docs/react-native/primitives.mdx +23 -0
  90. package/.docs/raw/docs/runtimes/a2a/quickstart.mdx +1 -1
  91. package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
  92. package/.docs/raw/docs/runtimes/ag-ui/quickstart.mdx +1 -1
  93. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +13 -2
  94. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +13 -4
  95. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +11 -11
  96. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
  97. package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +8 -6
  98. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
  99. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
  100. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
  101. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
  102. package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
  103. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +2 -0
  104. package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
  105. package/.docs/raw/docs/runtimes/google-adk/quickstart.mdx +1 -1
  106. package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
  107. package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
  108. package/.docs/raw/docs/runtimes/opencode/hooks.mdx +1 -1
  109. package/.docs/raw/docs/tools/backend.mdx +6 -3
  110. package/.docs/raw/docs/tools/defining-tools.mdx +12 -1
  111. package/.docs/raw/docs/tools/generative-ui.mdx +95 -0
  112. package/.docs/raw/docs/tools/mcp-apps.mdx +37 -10
  113. package/.docs/raw/docs/tools/mcp.mdx +105 -3
  114. package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
  115. package/.docs/raw/docs/tools/user-managed-mcp.mdx +41 -4
  116. package/.docs/raw/docs/ui/accordion.mdx +16 -10
  117. package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
  118. package/.docs/raw/docs/ui/attachment.mdx +5 -1
  119. package/.docs/raw/docs/ui/badge.mdx +23 -12
  120. package/.docs/raw/docs/ui/follow-up-suggestions.mdx +80 -0
  121. package/.docs/raw/docs/ui/model-selector.mdx +69 -6
  122. package/.docs/raw/docs/ui/select.mdx +22 -14
  123. package/.docs/raw/docs/ui/sources.mdx +1 -1
  124. package/.docs/raw/docs/ui/tabs.mdx +25 -14
  125. package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
  126. package/README.md +1 -1
  127. package/dist/constants.d.ts +2 -1
  128. package/dist/constants.d.ts.map +1 -1
  129. package/dist/constants.js +2 -1
  130. package/dist/constants.js.map +1 -1
  131. package/dist/index.d.ts +0 -1
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +51 -0
  134. package/dist/index.js.map +1 -1
  135. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  136. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  137. package/dist/prepare-docs/copy-raw.js +0 -4
  138. package/dist/prepare-docs/copy-raw.js.map +1 -1
  139. package/dist/prompts/xulux-playground.d.ts +12 -0
  140. package/dist/prompts/xulux-playground.d.ts.map +1 -0
  141. package/dist/prompts/xulux-playground.js +33 -0
  142. package/dist/prompts/xulux-playground.js.map +1 -0
  143. package/dist/tools/docs.d.ts +2 -4
  144. package/dist/tools/docs.d.ts.map +1 -1
  145. package/dist/tools/docs.js +38 -10
  146. package/dist/tools/docs.js.map +1 -1
  147. package/dist/tools/examples.d.ts +5 -5
  148. package/dist/tools/examples.d.ts.map +1 -1
  149. package/dist/tools/examples.js +10 -7
  150. package/dist/tools/examples.js.map +1 -1
  151. package/dist/tools/resources.d.ts +6 -0
  152. package/dist/tools/resources.d.ts.map +1 -0
  153. package/dist/tools/resources.js +74 -0
  154. package/dist/tools/resources.js.map +1 -0
  155. package/dist/tools/search.d.ts +30 -0
  156. package/dist/tools/search.d.ts.map +1 -0
  157. package/dist/tools/search.js +39 -0
  158. package/dist/tools/search.js.map +1 -0
  159. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  160. package/dist/tools/tests/test-setup.js +7 -1
  161. package/dist/tools/tests/test-setup.js.map +1 -1
  162. package/dist/tools/xulux-templates.d.ts +72 -0
  163. package/dist/tools/xulux-templates.d.ts.map +1 -0
  164. package/dist/tools/xulux-templates.js +82 -0
  165. package/dist/tools/xulux-templates.js.map +1 -0
  166. package/dist/utils/cache.d.ts +5 -0
  167. package/dist/utils/cache.d.ts.map +1 -0
  168. package/dist/utils/cache.js +18 -0
  169. package/dist/utils/cache.js.map +1 -0
  170. package/dist/utils/logger.d.ts.map +1 -1
  171. package/dist/utils/mcp-format.d.ts +1 -0
  172. package/dist/utils/mcp-format.d.ts.map +1 -1
  173. package/dist/utils/mcp-format.js +7 -4
  174. package/dist/utils/mcp-format.js.map +1 -1
  175. package/dist/utils/mdx.d.ts +2 -1
  176. package/dist/utils/mdx.d.ts.map +1 -1
  177. package/dist/utils/mdx.js +19 -2
  178. package/dist/utils/mdx.js.map +1 -1
  179. package/dist/utils/paths.d.ts +2 -1
  180. package/dist/utils/paths.d.ts.map +1 -1
  181. package/dist/utils/paths.js +20 -1
  182. package/dist/utils/paths.js.map +1 -1
  183. package/dist/utils/search.d.ts +10 -0
  184. package/dist/utils/search.d.ts.map +1 -0
  185. package/dist/utils/search.js +97 -0
  186. package/dist/utils/search.js.map +1 -0
  187. package/dist/utils/security.d.ts.map +1 -1
  188. package/dist/xulux/catalog-client.d.ts +14 -0
  189. package/dist/xulux/catalog-client.d.ts.map +1 -0
  190. package/dist/xulux/catalog-client.js +67 -0
  191. package/dist/xulux/catalog-client.js.map +1 -0
  192. package/dist/xulux/fallback-catalog.d.ts +7 -0
  193. package/dist/xulux/fallback-catalog.d.ts.map +1 -0
  194. package/dist/xulux/fallback-catalog.js +47 -0
  195. package/dist/xulux/fallback-catalog.js.map +1 -0
  196. package/dist/xulux/fetch-sandbox.d.ts +5 -0
  197. package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
  198. package/dist/xulux/fetch-sandbox.js +40 -0
  199. package/dist/xulux/fetch-sandbox.js.map +1 -0
  200. package/dist/xulux/template-service.d.ts +84 -0
  201. package/dist/xulux/template-service.d.ts.map +1 -0
  202. package/dist/xulux/template-service.js +223 -0
  203. package/dist/xulux/template-service.js.map +1 -0
  204. package/dist/xulux/types.d.ts +55 -0
  205. package/dist/xulux/types.d.ts.map +1 -0
  206. package/dist/xulux/types.js +6 -0
  207. package/dist/xulux/types.js.map +1 -0
  208. package/package.json +5 -5
  209. package/src/constants.ts +2 -0
  210. package/src/index.ts +67 -0
  211. package/src/prepare-docs/copy-raw.ts +0 -5
  212. package/src/prompts/xulux-playground.ts +36 -0
  213. package/src/tools/docs.ts +52 -4
  214. package/src/tools/examples.ts +18 -11
  215. package/src/tools/resources.ts +114 -0
  216. package/src/tools/search.ts +46 -0
  217. package/src/tools/tests/completions.test.ts +46 -0
  218. package/src/tools/tests/directory-size-cap.test.ts +50 -0
  219. package/src/tools/tests/docs.test.ts +20 -0
  220. package/src/tools/tests/examples.test.ts +5 -5
  221. package/src/tools/tests/listings-cache.test.ts +19 -0
  222. package/src/tools/tests/mcp-protocol.test.ts +92 -1
  223. package/src/tools/tests/resources.test.ts +102 -0
  224. package/src/tools/tests/search.test.ts +37 -0
  225. package/src/tools/tests/test-setup.ts +10 -0
  226. package/src/tools/tests/xulux-templates.test.ts +262 -0
  227. package/src/tools/xulux-templates.ts +141 -0
  228. package/src/utils/cache.ts +20 -0
  229. package/src/utils/mcp-format.ts +8 -6
  230. package/src/utils/mdx.ts +21 -1
  231. package/src/utils/paths.ts +25 -0
  232. package/src/utils/search.ts +131 -0
  233. package/src/utils/tests/cache.test.ts +51 -0
  234. package/src/utils/tests/mcp-format.test.ts +22 -0
  235. package/src/utils/tests/security.test.ts +1 -1
  236. package/src/xulux/catalog-client.ts +105 -0
  237. package/src/xulux/fallback-catalog.ts +63 -0
  238. package/src/xulux/fetch-sandbox.ts +56 -0
  239. package/src/xulux/template-service.ts +406 -0
  240. package/src/xulux/types.ts +60 -0
  241. package/.docs/raw/blog/2024-07-29-hello/index.mdx +0 -64
  242. package/.docs/raw/blog/2024-09-11/index.mdx +0 -10
  243. package/.docs/raw/blog/2024-12-15/index.mdx +0 -10
  244. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +0 -127
  245. package/.docs/raw/blog/2026-03-launch-week/index.mdx +0 -258
  246. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
@@ -0,0 +1,84 @@
1
+ import { XuluxCatalog, XuluxCatalogTemplate, XuluxCatalogVersion } from "./types.js";
2
+ //#region src/xulux/template-service.d.ts
3
+ interface ResolvedTemplate {
4
+ template: XuluxCatalogTemplate;
5
+ version: XuluxCatalogVersion | null;
6
+ }
7
+ /**
8
+ * Resolves a template by id, preserving the app-route semantics:
9
+ * - exact `templateId` match wins
10
+ * - version-specific entry ids (e.g. `webpage-assistant-product-docs`)
11
+ * remain valid inputs
12
+ * - explicit `versionId` wins when provided
13
+ * - otherwise the template's default version is used
14
+ */
15
+ declare function resolveTemplate(catalog: XuluxCatalog, templateId: string, versionId?: string | undefined): ResolvedTemplate | null;
16
+ interface TemplateListItem {
17
+ id: string;
18
+ name: string;
19
+ summary: string;
20
+ assistantPlacement: string;
21
+ features: string[];
22
+ customizable: string[];
23
+ versions: Array<{
24
+ id: string;
25
+ name: string;
26
+ description: string;
27
+ }>;
28
+ kind: "template" | "example";
29
+ }
30
+ declare function listTemplates(catalog: XuluxCatalog): {
31
+ templates: TemplateListItem[];
32
+ };
33
+ interface TemplateDetails {
34
+ id: string;
35
+ name: string;
36
+ selectedVersionId: string | null;
37
+ summary: string;
38
+ assistantPlacement: string;
39
+ configRoots?: Record<string, unknown>;
40
+ rules: {
41
+ required: string[];
42
+ unsupported?: string[];
43
+ };
44
+ tools: {
45
+ builtIn: unknown[];
46
+ customToolSupported: boolean;
47
+ renderers: unknown[];
48
+ };
49
+ exampleConfig: Record<string, unknown> | null;
50
+ previewUrl?: string;
51
+ downloadUrl?: string;
52
+ warnings?: string[];
53
+ exampleConfigNote?: string;
54
+ }
55
+ interface TemplateError {
56
+ error: string;
57
+ retryHint?: string;
58
+ }
59
+ declare function getTemplateDetails(catalog: XuluxCatalog, input: {
60
+ templateId: string;
61
+ versionId?: string | undefined;
62
+ }): Promise<TemplateDetails | TemplateError>;
63
+ interface TemplatePreviewResult {
64
+ success: boolean;
65
+ templateId: string;
66
+ versionId: string | null;
67
+ previewUrl?: string;
68
+ downloadUrl?: string;
69
+ title?: string;
70
+ customized?: boolean;
71
+ validationWarnings?: unknown[];
72
+ error?: string;
73
+ retryHint?: string;
74
+ details?: string;
75
+ summary?: string;
76
+ }
77
+ declare function createTemplatePreview(catalog: XuluxCatalog, input: {
78
+ templateId: string;
79
+ versionId?: string | undefined;
80
+ config?: Record<string, unknown> | undefined;
81
+ }): Promise<TemplatePreviewResult>;
82
+ //#endregion
83
+ export { ResolvedTemplate, TemplateDetails, TemplateError, TemplateListItem, TemplatePreviewResult, createTemplatePreview, getTemplateDetails, listTemplates, resolveTemplate };
84
+ //# sourceMappingURL=template-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-service.d.ts","names":[],"sources":["../../src/xulux/template-service.ts"],"mappings":";;UAYiB;EACf,UAAU;EACV,SAAS;;;;;;;;;;iBAWK,gBACd,SAAS,cACT,oBACA,iCACC;UA6Bc;EACf;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;IAAQ;IAAY;IAAc;;EAC5C;;iBAGc,cAAc,SAAS;EACrC,WAAW;;UAmCI;EACf;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;IACE;IACA;;EAEF;IACE;IACA;IACA;;EAEF,eAAe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;iBAGoB,mBACpB,SAAS,cACT;EAAS;EAAoB;IAC5B,QAAQ,kBAAkB;UAqGZ;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGoB,sBACpB,SAAS,cACT;EACE;EACA;EACA,SAAS;IAEV,QAAQ"}
@@ -0,0 +1,223 @@
1
+ import { fetchSandboxResource } from "./fetch-sandbox.js";
2
+ //#region src/xulux/template-service.ts
3
+ /**
4
+ * Resolves a template by id, preserving the app-route semantics:
5
+ * - exact `templateId` match wins
6
+ * - version-specific entry ids (e.g. `webpage-assistant-product-docs`)
7
+ * remain valid inputs
8
+ * - explicit `versionId` wins when provided
9
+ * - otherwise the template's default version is used
10
+ */
11
+ function resolveTemplate(catalog, templateId, versionId) {
12
+ let template = catalog.templates.find((t) => t.templateId === templateId || t.id === templateId);
13
+ let impliedVersionId;
14
+ if (!template) {
15
+ template = catalog.templates.find((t) => t.versions.some((v) => v.entryId === templateId));
16
+ if (template) impliedVersionId = template.versions.find((v) => v.entryId === templateId)?.id;
17
+ }
18
+ if (!template) return null;
19
+ const effectiveVersionId = versionId ?? impliedVersionId ?? template.versionId;
20
+ const version = effectiveVersionId ? template.versions.find((v) => v.id === effectiveVersionId) ?? null : null;
21
+ return {
22
+ template,
23
+ version
24
+ };
25
+ }
26
+ function listTemplates(catalog) {
27
+ return { templates: catalog.templates.map((t) => ({
28
+ id: t.templateId,
29
+ name: t.name,
30
+ summary: t.summary,
31
+ assistantPlacement: t.assistantPlacement,
32
+ features: t.features,
33
+ customizable: t.customizable,
34
+ versions: t.versions.map((v) => ({
35
+ id: v.id,
36
+ name: v.name,
37
+ description: v.description
38
+ })),
39
+ kind: t.kind
40
+ })) };
41
+ }
42
+ async function fetchTemplateContract(sandboxBaseUrl, versionId) {
43
+ try {
44
+ const url = new URL("/api/template/contract", sandboxBaseUrl);
45
+ if (versionId) url.searchParams.set("v", versionId);
46
+ const res = await fetchSandboxResource(url.toString());
47
+ if (!res.ok) return null;
48
+ return await res.json();
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+ async function getTemplateDetails(catalog, input) {
54
+ const resolved = resolveTemplate(catalog, input.templateId, input.versionId);
55
+ if (!resolved) return {
56
+ error: `Template "${input.templateId}" not found.`,
57
+ retryHint: "Call assistantUITemplates and use one of the returned template ids."
58
+ };
59
+ const { template, version } = resolved;
60
+ if (template.kind === "example") return {
61
+ id: template.templateId,
62
+ name: template.name,
63
+ selectedVersionId: null,
64
+ summary: template.summary,
65
+ assistantPlacement: template.assistantPlacement,
66
+ rules: template.rules ?? { required: ["This entry is a fixed demo and is not schema-customizable.", "Preview and download it as-is. Do not pass a config for this entry."] },
67
+ tools: {
68
+ builtIn: [],
69
+ customToolSupported: false,
70
+ renderers: []
71
+ },
72
+ exampleConfig: null,
73
+ ...template.previewUrl ? { previewUrl: template.previewUrl } : {},
74
+ ...template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}
75
+ };
76
+ const selectedVersionId = version?.id ?? template.versionId;
77
+ if (!template.configRoots || !template.tools) return {
78
+ error: `No authoring schema found for template "${template.templateId}".`,
79
+ retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
80
+ };
81
+ let exampleConfig = null;
82
+ let exampleConfigNote;
83
+ if (template.sandboxBaseUrl) {
84
+ exampleConfig = (await fetchTemplateContract(template.sandboxBaseUrl, selectedVersionId))?.exampleCompleteConfig ?? null;
85
+ exampleConfigNote = exampleConfig ? `Resolved defaults for version "${selectedVersionId}". Use as a complete working starting point.` : "Could not reach the template sandbox to resolve exampleConfig. Use configRoots schemas and defaults to author config manually.";
86
+ } else exampleConfigNote = "This template has no sandbox URL in the catalog, so exampleConfig is unavailable. Use configRoots schemas and defaults.";
87
+ return {
88
+ id: template.templateId,
89
+ name: template.name,
90
+ selectedVersionId,
91
+ summary: template.summary,
92
+ assistantPlacement: template.assistantPlacement,
93
+ configRoots: template.configRoots,
94
+ rules: template.rules ?? { required: [] },
95
+ tools: template.tools,
96
+ exampleConfig,
97
+ exampleConfigNote,
98
+ ...version?.previewUrl ? { previewUrl: version.previewUrl } : template.previewUrl ? { previewUrl: template.previewUrl } : {},
99
+ ...version?.downloadUrl ? { downloadUrl: version.downloadUrl } : template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}
100
+ };
101
+ }
102
+ function toAbsolute(baseUrl, url) {
103
+ if (/^https?:\/\//.test(url)) return url;
104
+ return `${baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
105
+ }
106
+ function withVersion(url, versionId) {
107
+ if (!versionId) return url;
108
+ const [path, query = ""] = url.split("?");
109
+ const params = new URLSearchParams(query);
110
+ if (!params.has("v")) params.set("v", versionId);
111
+ return `${path}?${params.toString()}`;
112
+ }
113
+ function hasConfig(config) {
114
+ return !!config && Object.keys(config).length > 0;
115
+ }
116
+ async function createTemplatePreview(catalog, input) {
117
+ const resolved = resolveTemplate(catalog, input.templateId, input.versionId);
118
+ if (!resolved) return {
119
+ success: false,
120
+ templateId: input.templateId,
121
+ versionId: input.versionId ?? null,
122
+ error: `Template "${input.templateId}" not found.`,
123
+ retryHint: "Call assistantUITemplates and use one of the returned template ids."
124
+ };
125
+ const { template, version } = resolved;
126
+ const tid = template.templateId;
127
+ if (template.kind === "example") {
128
+ if (hasConfig(input.config)) return {
129
+ success: false,
130
+ templateId: tid,
131
+ versionId: null,
132
+ error: `Template "${tid}" is a fixed demo and does not support config.`,
133
+ retryHint: "Call assistantUITemplateDetails for this template. If no configRoots are returned, call assistantUITemplatePreview again without config or choose a configurable hosted template."
134
+ };
135
+ if (!template.previewUrl) return {
136
+ success: false,
137
+ templateId: tid,
138
+ versionId: null,
139
+ error: `Fixed demo "${tid}" has no preview URL in the catalog.`,
140
+ retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
141
+ };
142
+ return {
143
+ success: true,
144
+ templateId: tid,
145
+ versionId: null,
146
+ previewUrl: template.previewUrl,
147
+ ...template.downloadUrl ? { downloadUrl: template.downloadUrl } : {},
148
+ title: template.name,
149
+ customized: false,
150
+ summary: `Resolved ${template.name} as a fixed demo. Preview and download URLs point at hosted resources; nothing was opened in any UI.`
151
+ };
152
+ }
153
+ const baseUrl = template.sandboxBaseUrl;
154
+ if (!baseUrl) return {
155
+ success: false,
156
+ templateId: tid,
157
+ versionId: version?.id ?? template.versionId,
158
+ error: `Template "${tid}" has no sandbox URL in the catalog.`,
159
+ retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
160
+ };
161
+ const effectiveVersionId = version?.id ?? template.versionId;
162
+ if (hasConfig(input.config)) try {
163
+ const sessionUrl = new URL("/api/preview/session", baseUrl);
164
+ if (effectiveVersionId) sessionUrl.searchParams.set("v", effectiveVersionId);
165
+ const res = await fetchSandboxResource(sessionUrl.toString(), {
166
+ method: "POST",
167
+ headers: { "Content-Type": "application/json" },
168
+ body: JSON.stringify(input.config)
169
+ });
170
+ if (!res.ok) {
171
+ const details = await res.text();
172
+ return {
173
+ success: false,
174
+ templateId: tid,
175
+ versionId: effectiveVersionId,
176
+ error: `Preview session failed: HTTP ${res.status}`,
177
+ details,
178
+ retryHint: "Check validationWarnings for the specific fields that failed. Call assistantUITemplateDetails for this template and use configRoots schemas to correct the config. Pass only hostUi, assistant, and brandTheme at the top level."
179
+ };
180
+ }
181
+ const data = await res.json();
182
+ if (!data.previewUrl) return {
183
+ success: false,
184
+ templateId: tid,
185
+ versionId: effectiveVersionId,
186
+ error: "Session endpoint did not return a previewUrl."
187
+ };
188
+ return {
189
+ success: true,
190
+ templateId: tid,
191
+ versionId: effectiveVersionId,
192
+ previewUrl: toAbsolute(baseUrl, withVersion(data.previewUrl, effectiveVersionId ?? void 0)),
193
+ downloadUrl: toAbsolute(baseUrl, withVersion(data.downloadUrl ?? "/api/download", effectiveVersionId ?? void 0)),
194
+ title: version?.name ?? template.name,
195
+ customized: true,
196
+ summary: `Created a configured preview session for ${template.name}. URLs point at the hosted sandbox; nothing was opened in any UI.`,
197
+ validationWarnings: data.validationWarnings ?? []
198
+ };
199
+ } catch (err) {
200
+ return {
201
+ success: false,
202
+ templateId: tid,
203
+ versionId: effectiveVersionId,
204
+ error: err instanceof Error ? err.message : String(err)
205
+ };
206
+ }
207
+ const previewUrl = version?.previewUrl ?? template.previewUrl;
208
+ const downloadUrl = version?.downloadUrl ?? template.downloadUrl ?? `${baseUrl}/api/download`;
209
+ return {
210
+ success: true,
211
+ templateId: tid,
212
+ versionId: effectiveVersionId,
213
+ previewUrl: previewUrl ?? baseUrl,
214
+ downloadUrl,
215
+ title: version?.name ?? template.name,
216
+ customized: false,
217
+ summary: `Resolved preview and download URLs for ${template.name}. Nothing was opened in any UI.`
218
+ };
219
+ }
220
+ //#endregion
221
+ export { createTemplatePreview, getTemplateDetails, listTemplates, resolveTemplate };
222
+
223
+ //# sourceMappingURL=template-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-service.js","names":[],"sources":["../../src/xulux/template-service.ts"],"sourcesContent":["import { fetchSandboxResource } from \"./fetch-sandbox.js\";\nimport type {\n XuluxCatalog,\n XuluxCatalogTemplate,\n XuluxCatalogVersion,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Local, catalog-backed template operations for the assistant-ui template MCP tools.\n// These functions never mutate any UI. Preview operations only return URLs.\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedTemplate {\n template: XuluxCatalogTemplate;\n version: XuluxCatalogVersion | null;\n}\n\n/**\n * Resolves a template by id, preserving the app-route semantics:\n * - exact `templateId` match wins\n * - version-specific entry ids (e.g. `webpage-assistant-product-docs`)\n * remain valid inputs\n * - explicit `versionId` wins when provided\n * - otherwise the template's default version is used\n */\nexport function resolveTemplate(\n catalog: XuluxCatalog,\n templateId: string,\n versionId?: string | undefined,\n): ResolvedTemplate | null {\n let template = catalog.templates.find(\n (t) => t.templateId === templateId || t.id === templateId,\n );\n let impliedVersionId: string | undefined;\n\n if (!template) {\n // Version-specific entry id such as `webpage-assistant-product-docs`.\n template = catalog.templates.find((t) =>\n t.versions.some((v) => v.entryId === templateId),\n );\n if (template) {\n impliedVersionId = template.versions.find(\n (v) => v.entryId === templateId,\n )?.id;\n }\n }\n\n if (!template) return null;\n\n const effectiveVersionId =\n versionId ?? impliedVersionId ?? template.versionId;\n const version = effectiveVersionId\n ? (template.versions.find((v) => v.id === effectiveVersionId) ?? null)\n : null;\n\n return { template, version };\n}\n\nexport interface TemplateListItem {\n id: string;\n name: string;\n summary: string;\n assistantPlacement: string;\n features: string[];\n customizable: string[];\n versions: Array<{ id: string; name: string; description: string }>;\n kind: \"template\" | \"example\";\n}\n\nexport function listTemplates(catalog: XuluxCatalog): {\n templates: TemplateListItem[];\n} {\n return {\n templates: catalog.templates.map((t) => ({\n id: t.templateId,\n name: t.name,\n summary: t.summary,\n assistantPlacement: t.assistantPlacement,\n features: t.features,\n customizable: t.customizable,\n versions: t.versions.map((v) => ({\n id: v.id,\n name: v.name,\n description: v.description,\n })),\n kind: t.kind,\n })),\n };\n}\n\nasync function fetchTemplateContract(\n sandboxBaseUrl: string,\n versionId: string | null,\n): Promise<Record<string, unknown> | null> {\n try {\n const url = new URL(\"/api/template/contract\", sandboxBaseUrl);\n if (versionId) url.searchParams.set(\"v\", versionId);\n const res = await fetchSandboxResource(url.toString());\n if (!res.ok) return null;\n return (await res.json()) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport interface TemplateDetails {\n id: string;\n name: string;\n selectedVersionId: string | null;\n summary: string;\n assistantPlacement: string;\n configRoots?: Record<string, unknown>;\n rules: {\n required: string[];\n unsupported?: string[];\n };\n tools: {\n builtIn: unknown[];\n customToolSupported: boolean;\n renderers: unknown[];\n };\n exampleConfig: Record<string, unknown> | null;\n previewUrl?: string;\n downloadUrl?: string;\n warnings?: string[];\n exampleConfigNote?: string;\n}\n\nexport interface TemplateError {\n error: string;\n retryHint?: string;\n}\n\nexport async function getTemplateDetails(\n catalog: XuluxCatalog,\n input: { templateId: string; versionId?: string | undefined },\n): Promise<TemplateDetails | TemplateError> {\n const resolved = resolveTemplate(catalog, input.templateId, input.versionId);\n if (!resolved) {\n return {\n error: `Template \"${input.templateId}\" not found.`,\n retryHint:\n \"Call assistantUITemplates and use one of the returned template ids.\",\n };\n }\n\n const { template, version } = resolved;\n\n if (template.kind === \"example\") {\n return {\n id: template.templateId,\n name: template.name,\n selectedVersionId: null,\n summary: template.summary,\n assistantPlacement: template.assistantPlacement,\n rules: template.rules ?? {\n required: [\n \"This entry is a fixed demo and is not schema-customizable.\",\n \"Preview and download it as-is. Do not pass a config for this entry.\",\n ],\n },\n tools: { builtIn: [], customToolSupported: false, renderers: [] },\n exampleConfig: null,\n ...(template.previewUrl ? { previewUrl: template.previewUrl } : {}),\n ...(template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}),\n };\n }\n\n const selectedVersionId = version?.id ?? template.versionId;\n\n if (!template.configRoots || !template.tools) {\n return {\n error: `No authoring schema found for template \"${template.templateId}\".`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n let exampleConfig: Record<string, unknown> | null = null;\n let exampleConfigNote: string;\n if (template.sandboxBaseUrl) {\n const contract = await fetchTemplateContract(\n template.sandboxBaseUrl,\n selectedVersionId,\n );\n exampleConfig =\n (contract?.exampleCompleteConfig as Record<string, unknown> | null) ??\n null;\n exampleConfigNote = exampleConfig\n ? `Resolved defaults for version \"${selectedVersionId}\". Use as a complete working starting point.`\n : \"Could not reach the template sandbox to resolve exampleConfig. Use configRoots schemas and defaults to author config manually.\";\n } else {\n exampleConfigNote =\n \"This template has no sandbox URL in the catalog, so exampleConfig is unavailable. Use configRoots schemas and defaults.\";\n }\n\n return {\n id: template.templateId,\n name: template.name,\n selectedVersionId,\n summary: template.summary,\n assistantPlacement: template.assistantPlacement,\n configRoots: template.configRoots,\n rules: template.rules ?? { required: [] },\n tools: template.tools,\n exampleConfig,\n exampleConfigNote,\n ...(version?.previewUrl\n ? { previewUrl: version.previewUrl }\n : template.previewUrl\n ? { previewUrl: template.previewUrl }\n : {}),\n ...(version?.downloadUrl\n ? { downloadUrl: version.downloadUrl }\n : template.downloadUrl\n ? { downloadUrl: template.downloadUrl }\n : {}),\n };\n}\n\nfunction toAbsolute(baseUrl: string, url: string): string {\n if (/^https?:\\/\\//.test(url)) return url;\n return `${baseUrl}${url.startsWith(\"/\") ? \"\" : \"/\"}${url}`;\n}\n\nfunction withVersion(url: string, versionId: string | undefined): string {\n if (!versionId) return url;\n const [path, query = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(query);\n if (!params.has(\"v\")) params.set(\"v\", versionId);\n return `${path}?${params.toString()}`;\n}\n\nfunction hasConfig(config: Record<string, unknown> | undefined): boolean {\n return !!config && Object.keys(config).length > 0;\n}\n\nexport interface TemplatePreviewResult {\n success: boolean;\n templateId: string;\n versionId: string | null;\n previewUrl?: string;\n downloadUrl?: string;\n title?: string;\n customized?: boolean;\n validationWarnings?: unknown[];\n error?: string;\n retryHint?: string;\n details?: string;\n summary?: string;\n}\n\nexport async function createTemplatePreview(\n catalog: XuluxCatalog,\n input: {\n templateId: string;\n versionId?: string | undefined;\n config?: Record<string, unknown> | undefined;\n },\n): Promise<TemplatePreviewResult> {\n const resolved = resolveTemplate(catalog, input.templateId, input.versionId);\n if (!resolved) {\n return {\n success: false,\n templateId: input.templateId,\n versionId: input.versionId ?? null,\n error: `Template \"${input.templateId}\" not found.`,\n retryHint:\n \"Call assistantUITemplates and use one of the returned template ids.\",\n };\n }\n\n const { template, version } = resolved;\n const tid = template.templateId;\n\n if (template.kind === \"example\") {\n if (hasConfig(input.config)) {\n return {\n success: false,\n templateId: tid,\n versionId: null,\n error: `Template \"${tid}\" is a fixed demo and does not support config.`,\n retryHint:\n \"Call assistantUITemplateDetails for this template. If no configRoots are returned, call assistantUITemplatePreview again without config or choose a configurable hosted template.\",\n };\n }\n\n if (!template.previewUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: null,\n error: `Fixed demo \"${tid}\" has no preview URL in the catalog.`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n return {\n success: true,\n templateId: tid,\n versionId: null,\n previewUrl: template.previewUrl,\n ...(template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}),\n title: template.name,\n customized: false,\n summary: `Resolved ${template.name} as a fixed demo. Preview and download URLs point at hosted resources; nothing was opened in any UI.`,\n };\n }\n\n const baseUrl = template.sandboxBaseUrl;\n if (!baseUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: version?.id ?? template.versionId,\n error: `Template \"${tid}\" has no sandbox URL in the catalog.`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n const effectiveVersionId = version?.id ?? template.versionId;\n\n if (hasConfig(input.config)) {\n try {\n const sessionUrl = new URL(\"/api/preview/session\", baseUrl);\n if (effectiveVersionId)\n sessionUrl.searchParams.set(\"v\", effectiveVersionId);\n const res = await fetchSandboxResource(sessionUrl.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input.config),\n });\n if (!res.ok) {\n const details = await res.text();\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: `Preview session failed: HTTP ${res.status}`,\n details,\n retryHint:\n \"Check validationWarnings for the specific fields that failed. \" +\n \"Call assistantUITemplateDetails for this template and use configRoots schemas to correct the config. \" +\n \"Pass only hostUi, assistant, and brandTheme at the top level.\",\n };\n }\n const data = (await res.json()) as {\n previewUrl?: string;\n downloadUrl?: string;\n validationWarnings?: unknown[];\n };\n if (!data.previewUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: \"Session endpoint did not return a previewUrl.\",\n };\n }\n return {\n success: true,\n templateId: tid,\n versionId: effectiveVersionId,\n previewUrl: toAbsolute(\n baseUrl,\n withVersion(data.previewUrl, effectiveVersionId ?? undefined),\n ),\n downloadUrl: toAbsolute(\n baseUrl,\n withVersion(\n data.downloadUrl ?? \"/api/download\",\n effectiveVersionId ?? undefined,\n ),\n ),\n title: version?.name ?? template.name,\n customized: true,\n summary: `Created a configured preview session for ${template.name}. URLs point at the hosted sandbox; nothing was opened in any UI.`,\n validationWarnings: data.validationWarnings ?? [],\n };\n } catch (err) {\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const previewUrl = version?.previewUrl ?? template.previewUrl;\n const downloadUrl =\n version?.downloadUrl ?? template.downloadUrl ?? `${baseUrl}/api/download`;\n\n return {\n success: true,\n templateId: tid,\n versionId: effectiveVersionId,\n previewUrl: previewUrl ?? baseUrl,\n downloadUrl,\n title: version?.name ?? template.name,\n customized: false,\n summary: `Resolved preview and download URLs for ${template.name}. Nothing was opened in any UI.`,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ //#region src/xulux/types.d.ts
2
+ declare const XULUX_MCP_CATALOG_VERSION = 1;
3
+ interface XuluxCatalogVersion {
4
+ id: string;
5
+ entryId: string;
6
+ name: string;
7
+ description: string;
8
+ previewUrl: string;
9
+ downloadUrl: string;
10
+ }
11
+ interface XuluxCatalogTemplate {
12
+ id: string;
13
+ templateId: string;
14
+ versionId: string | null;
15
+ kind: "template" | "example";
16
+ name: string;
17
+ summary: string;
18
+ assistantPlacement: string;
19
+ features: string[];
20
+ customizable: string[];
21
+ versions: XuluxCatalogVersion[];
22
+ previewUrl?: string;
23
+ downloadUrl?: string;
24
+ sandboxBaseUrl?: string;
25
+ configRoots?: Record<string, unknown>;
26
+ rules?: {
27
+ required: string[];
28
+ unsupported?: string[];
29
+ };
30
+ tools?: {
31
+ builtIn: unknown[];
32
+ customToolSupported: boolean;
33
+ renderers: unknown[];
34
+ };
35
+ }
36
+ interface XuluxCatalog {
37
+ version: number;
38
+ generatedAt: string;
39
+ docsOrigin: string;
40
+ templates: XuluxCatalogTemplate[];
41
+ }
42
+ interface XuluxCatalogResult {
43
+ catalog: XuluxCatalog;
44
+ /** True when the bundled fallback catalog was used instead of live data. */
45
+ degraded: boolean;
46
+ /** Present when the live fetch failed and the fallback was used. */
47
+ degradedReason?: string;
48
+ }
49
+ interface XuluxCatalogError {
50
+ error: string;
51
+ hint?: string;
52
+ }
53
+ //#endregion
54
+ export { XULUX_MCP_CATALOG_VERSION, XuluxCatalog, XuluxCatalogError, XuluxCatalogResult, XuluxCatalogTemplate, XuluxCatalogVersion };
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/xulux/types.ts"],"mappings":";cAIa;UAEI;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA,cAAc;EACd;IACE;IACA;;EAEF;IACE;IACA;IACA;;;UAIa;EACf;EACA;EACA;EACA,WAAW;;UAGI;EACf,SAAS;;EAET;;EAEA;;UAGe;EACf;EACA"}
@@ -0,0 +1,6 @@
1
+ //#region src/xulux/types.ts
2
+ const XULUX_MCP_CATALOG_VERSION = 1;
3
+ //#endregion
4
+ export { XULUX_MCP_CATALOG_VERSION };
5
+
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/xulux/types.ts"],"sourcesContent":["// MCP-safe assistant-ui template catalog types. These mirror the payload served by the docs\n// app at GET /api/xulux/mcp-catalog. The MCP package never imports docs-app\n// internals; the endpoint payload is the contract.\n\nexport const XULUX_MCP_CATALOG_VERSION = 1;\n\nexport interface XuluxCatalogVersion {\n id: string;\n entryId: string;\n name: string;\n description: string;\n previewUrl: string;\n downloadUrl: string;\n}\n\nexport interface XuluxCatalogTemplate {\n id: string;\n templateId: string;\n versionId: string | null;\n kind: \"template\" | \"example\";\n name: string;\n summary: string;\n assistantPlacement: string;\n features: string[];\n customizable: string[];\n versions: XuluxCatalogVersion[];\n previewUrl?: string;\n downloadUrl?: string;\n sandboxBaseUrl?: string;\n configRoots?: Record<string, unknown>;\n rules?: {\n required: string[];\n unsupported?: string[];\n };\n tools?: {\n builtIn: unknown[];\n customToolSupported: boolean;\n renderers: unknown[];\n };\n}\n\nexport interface XuluxCatalog {\n version: number;\n generatedAt: string;\n docsOrigin: string;\n templates: XuluxCatalogTemplate[];\n}\n\nexport interface XuluxCatalogResult {\n catalog: XuluxCatalog;\n /** True when the bundled fallback catalog was used instead of live data. */\n degraded: boolean;\n /** Present when the live fetch failed and the fallback was used. */\n degradedReason?: string;\n}\n\nexport interface XuluxCatalogError {\n error: string;\n hint?: string;\n}\n"],"mappings":";AAIA,MAAa,4BAA4B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/mcp-docs-server",
3
- "version": "0.1.36",
3
+ "version": "0.1.39",
4
4
  "description": "MCP server for assistant-ui documentation and examples",
5
5
  "keywords": [
6
6
  "mcp",
@@ -37,10 +37,10 @@
37
37
  "zod": "^4.4.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@types/node": "^26.0.0",
41
- "tsx": "^4.22.4",
42
- "vitest": "^4.1.9",
43
- "@assistant-ui/x-buildutils": "0.0.16"
40
+ "@types/node": "^26.1.1",
41
+ "tsx": "^4.23.1",
42
+ "vitest": "^4.1.10",
43
+ "@assistant-ui/x-buildutils": "0.0.18"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public",
package/src/constants.ts CHANGED
@@ -17,6 +17,8 @@ export const MD_EXTENSION = ".md";
17
17
 
18
18
  export const MAX_FILE_SIZE = 10 * 1024 * 1024;
19
19
 
20
+ export const MAX_DIRECTORY_CONTENT_SIZE = 1024 * 1024;
21
+
20
22
  export const IS_PREPARE_MODE = process.argv[1]?.includes(
21
23
  "prepare-docs/prepare",
22
24
  );
package/src/index.ts CHANGED
@@ -2,6 +2,14 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { docsTools } from "./tools/docs.js";
4
4
  import { examplesTools } from "./tools/examples.js";
5
+ import { searchTools } from "./tools/search.js";
6
+ import {
7
+ xuluxTemplatesListTool,
8
+ xuluxTemplateDetailsTool,
9
+ xuluxTemplatePreviewTool,
10
+ } from "./tools/xulux-templates.js";
11
+ import { xuluxPlaygroundPrompt } from "./prompts/xulux-playground.js";
12
+ import { registerResources } from "./tools/resources.js";
5
13
  import { logger } from "./utils/logger.js";
6
14
  import { PACKAGE_DIR } from "./constants.js";
7
15
 
@@ -37,6 +45,65 @@ server.registerTool(
37
45
  },
38
46
  examplesTools.execute,
39
47
  );
48
+ server.registerTool(
49
+ searchTools.name,
50
+ {
51
+ title: "Search assistant-ui Documentation",
52
+ description: searchTools.description,
53
+ inputSchema: searchTools.parameters,
54
+ annotations: { readOnlyHint: true, openWorldHint: false },
55
+ },
56
+ searchTools.execute,
57
+ );
58
+
59
+ server.registerTool(
60
+ xuluxTemplatesListTool.name,
61
+ {
62
+ title: "assistant-ui Templates",
63
+ description: xuluxTemplatesListTool.description,
64
+ inputSchema: xuluxTemplatesListTool.parameters,
65
+ annotations: { readOnlyHint: true, openWorldHint: true },
66
+ },
67
+ xuluxTemplatesListTool.execute,
68
+ );
69
+ server.registerTool(
70
+ xuluxTemplateDetailsTool.name,
71
+ {
72
+ title: "assistant-ui Template Details",
73
+ description: xuluxTemplateDetailsTool.description,
74
+ inputSchema: xuluxTemplateDetailsTool.parameters,
75
+ annotations: { readOnlyHint: true, openWorldHint: true },
76
+ },
77
+ xuluxTemplateDetailsTool.execute,
78
+ );
79
+ server.registerTool(
80
+ xuluxTemplatePreviewTool.name,
81
+ {
82
+ title: "assistant-ui Template Preview URLs",
83
+ description: xuluxTemplatePreviewTool.description,
84
+ inputSchema: xuluxTemplatePreviewTool.parameters,
85
+ annotations: { readOnlyHint: false, openWorldHint: true },
86
+ },
87
+ xuluxTemplatePreviewTool.execute,
88
+ );
89
+
90
+ server.registerPrompt(
91
+ xuluxPlaygroundPrompt.name,
92
+ {
93
+ title: "assistant-ui Template Workflow",
94
+ description: xuluxPlaygroundPrompt.description,
95
+ },
96
+ () => ({
97
+ messages: [
98
+ {
99
+ role: "user" as const,
100
+ content: { type: "text" as const, text: xuluxPlaygroundPrompt.text },
101
+ },
102
+ ],
103
+ }),
104
+ );
105
+
106
+ registerResources(server);
40
107
 
41
108
  export async function runServer() {
42
109
  try {
@@ -4,7 +4,6 @@ import { logger } from "../utils/logger.js";
4
4
  import { ROOT_DIR } from "../constants.js";
5
5
 
6
6
  const DOCS_SOURCE = join(ROOT_DIR, "apps/docs/content/docs");
7
- const BLOG_SOURCE = join(ROOT_DIR, "apps/docs/content/blog");
8
7
  const DOCS_DEST = join(ROOT_DIR, "packages/mcp-docs-server/.docs/raw");
9
8
 
10
9
  async function copyDir(src: string, dest: string): Promise<void> {
@@ -43,10 +42,6 @@ export async function copyRaw(): Promise<void> {
43
42
  await copyDir(DOCS_SOURCE, docsPath);
44
43
  logger.info(`Copied documentation to ${docsPath}`);
45
44
 
46
- const blogPath = join(DOCS_DEST, "blog");
47
- await copyDir(BLOG_SOURCE, blogPath);
48
- logger.info(`Copied blog posts to ${blogPath}`);
49
-
50
45
  logger.info("Raw documentation copy complete");
51
46
  } catch (error) {
52
47
  logger.error("Failed to copy raw documentation", error);
@@ -0,0 +1,36 @@
1
+ // Skill-style MCP prompt teaching agents the assistant-ui template workflow.
2
+ // Adapted for MCP clients: tools return URLs and data only; there is no
3
+ // browser canvas UI here.
4
+
5
+ export const XULUX_PLAYGROUND_PROMPT_NAME = "assistant-ui-template-workflow";
6
+
7
+ export const XULUX_PLAYGROUND_PROMPT_DESCRIPTION =
8
+ "How to use the assistant-ui template tools to discover hosted templates, inspect their customization contracts, and retrieve preview/download URLs.";
9
+
10
+ export const XULUX_PLAYGROUND_PROMPT = `You have access to assistant-ui template tools for hosted app templates.
11
+
12
+ <workflow>
13
+ Follow this template-first workflow for any assistant-ui app-building request:
14
+
15
+ 1. Call **assistantUITemplates** FIRST. Never decide on a template or claim one exists without listing.
16
+ 2. Call **assistantUITemplateDetails** on any candidate template before deciding whether it fits.
17
+ - Review the whole template shape: features, assistantPlacement, configRoots schemas, rules, built-in tools, renderers, and exampleConfig.
18
+ - If \`customizable\` is empty, the entry is a fixed demo. Use it as-is; never pass a config for it.
19
+ 3. Decide one of three paths:
20
+ - The template fits as-is: call **assistantUITemplatePreview** with templateId and optional versionId.
21
+ - The template fits with supported customization: author a config using the configRoots schemas and rules from assistantUITemplateDetails, then call **assistantUITemplatePreview** with that config.
22
+ - No template fits: do NOT call assistantUITemplatePreview. Do not force the request into a template or fake domain content with mock config. Instead, ground yourself in the assistant-ui docs (assistantUIDocs, assistantUISearch, assistantUIExamples) and produce an honest, docs-grounded build guide or prompt for the user.
23
+ </workflow>
24
+
25
+ <important_constraints>
26
+ - Only use URLs copied exactly from tool results. Never guess, fabricate, or use placeholder URLs.
27
+ - If assistantUITemplatePreview returns validationWarnings or an error, call assistantUITemplateDetails again and correct the config against configRoots. Pass only the documented top-level config roots.
28
+ - Customization is for supported adaptation within a template's shape, not for turning it into a completely different kind of product.
29
+ - Responses may include \`catalogDegraded: true\` when the live template catalog is unreachable. In that mode, template details and preview URLs may be unavailable; tell the user rather than improvising.
30
+ </important_constraints>`;
31
+
32
+ export const xuluxPlaygroundPrompt = {
33
+ name: XULUX_PLAYGROUND_PROMPT_NAME,
34
+ description: XULUX_PLAYGROUND_PROMPT_DESCRIPTION,
35
+ text: XULUX_PLAYGROUND_PROMPT,
36
+ };