mountly-mcp 4.4.0 → 4.5.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 (44) hide show
  1. package/dist/artifact/declaration.d.ts +61 -0
  2. package/dist/artifact/index.d.ts +2 -42
  3. package/dist/artifact/index.js +9 -5
  4. package/dist/chunk-6T5EIQGE.js +104 -0
  5. package/dist/chunk-6T5EIQGE.js.map +1 -0
  6. package/dist/chunk-BLT2MK32.js +35 -0
  7. package/dist/chunk-BLT2MK32.js.map +1 -0
  8. package/dist/{chunk-HIAIQVK5.js → chunk-QIA76O6M.js} +9 -1
  9. package/dist/chunk-QIA76O6M.js.map +1 -0
  10. package/dist/{chunk-DKK26TRS.js → chunk-RLDSMU5M.js} +9 -70
  11. package/dist/chunk-RLDSMU5M.js.map +1 -0
  12. package/dist/chunk-UMQ5OULD.js +243 -0
  13. package/dist/chunk-UMQ5OULD.js.map +1 -0
  14. package/dist/cli.js +1 -1
  15. package/dist/dev/host-entry.js +23 -0
  16. package/dist/{doctor-NB3DE4CG.js → doctor-OTOROLPI.js} +110 -8
  17. package/dist/doctor-OTOROLPI.js.map +1 -0
  18. package/dist/doctor.d.ts +4 -0
  19. package/dist/download.d.ts +17 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +4 -0
  22. package/dist/json-render/index.js +2 -1
  23. package/dist/json-render/index.js.map +1 -1
  24. package/dist/react/hooks.d.ts +7 -0
  25. package/dist/react/index.js +4 -1
  26. package/dist/server/core.d.ts +84 -0
  27. package/dist/server/index.d.ts +2 -72
  28. package/dist/server/index.js +19 -219
  29. package/dist/server/index.js.map +1 -1
  30. package/dist/server/workers.d.ts +7 -0
  31. package/dist/server/workers.js +14 -0
  32. package/dist/server/workers.js.map +1 -0
  33. package/dist/testing/index.js +5 -3
  34. package/dist/testing/index.js.map +1 -1
  35. package/dist/vite/index.d.ts +15 -1
  36. package/dist/vite/index.js +133 -11
  37. package/dist/vite/index.js.map +1 -1
  38. package/dist/vue/index.d.ts +6 -0
  39. package/dist/vue/index.js +8 -0
  40. package/dist/vue/index.js.map +1 -1
  41. package/package.json +14 -6
  42. package/dist/chunk-DKK26TRS.js.map +0 -1
  43. package/dist/chunk-HIAIQVK5.js.map +0 -1
  44. package/dist/doctor-NB3DE4CG.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/json-render/generative-view.tsx","../../src/json-render/index.ts","../../src/json-render/use-spec-stream.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { type ComponentMap, createRenderer } from \"@json-render/react\";\nimport type { Catalog, SchemaDefinition, Spec } from \"@json-render/core\";\nimport { createMcpView, useMcpApp, useToolResult } from \"../react/index.js\";\nimport type { App } from \"@modelcontextprotocol/ext-apps\";\nimport type { AdapterOptions } from \"mountly/adapter\";\nimport type { McpView } from \"../types.js\";\n\n/** The catalog-data constraint createRenderer infers against. */\ntype CatalogData = { components: Record<string, { props: unknown }> };\n\n/**\n * Route a generated UI's actions back to the MCP host. Called with the action\n * name, its (resolved) params, and the view-side `App` handle.\n */\nexport type ActionRouter = (\n name: string,\n params: Record<string, unknown> | undefined,\n mcp: App,\n) => void;\n\n/**\n * Default router: an `ask` action with a string `prompt` param sends a\n * follow-up user turn to the model via `App.sendMessage`. This is the agent\n * loop json-render alone cannot do — it has no concept of an MCP host.\n */\nexport const defaultActionRouter: ActionRouter = (name, params, mcp) => {\n if (name !== \"ask\") return;\n const prompt = params?.prompt;\n const text = typeof prompt === \"string\" ? prompt : \"\";\n if (text) {\n void mcp.sendMessage({ role: \"user\", content: [{ type: \"text\", text }] });\n }\n};\n\n/**\n * Identity helper that types a components map against a catalog (so it can be\n * defined once and reused by both `createGenerativeView` and `createRenderer`)\n * without losing per-component prop inference.\n *\n * ```ts\n * export const components = defineComponents(catalog, {\n * Metric: ({ element }) => <span>{element.props.value}</span>,\n * });\n * ```\n */\nexport function defineComponents<TDef extends SchemaDefinition, TCatalog extends CatalogData>(\n _catalog: Catalog<TDef, TCatalog>,\n components: ComponentMap<TCatalog[\"components\"]>,\n): ComponentMap<TCatalog[\"components\"]> {\n return components;\n}\n\nexport interface GenerativeViewOptions<\n TDef extends SchemaDefinition,\n TCatalog extends CatalogData,\n> extends AdapterOptions {\n /** The json-render catalog — the vocabulary the agent may compose. */\n catalog: Catalog<TDef, TCatalog>;\n /** Native component implementations for each catalog type. */\n components: ComponentMap<TCatalog[\"components\"]>;\n /**\n * How a generated UI's actions reach the agent. Defaults to\n * {@link defaultActionRouter} (`ask` → `App.sendMessage`).\n */\n onAction?: ActionRouter;\n}\n\ninterface ToolResultShape {\n structuredContent?: { spec?: Spec };\n}\n\n/**\n * Turn a json-render catalog + components into a mountly MCP Apps View.\n *\n * Reads the spec from the tool result, renders it natively (resolving `$state`\n * from `spec.state`), and routes actions back to the MCP host.\n *\n * ```ts\n * createGenerativeView({ catalog, components, styles, shadow: true });\n * ```\n */\nexport function createGenerativeView<TDef extends SchemaDefinition, TCatalog extends CatalogData>(\n options: GenerativeViewOptions<TDef, TCatalog>,\n): McpView {\n const { catalog, components, onAction = defaultActionRouter, ...adapter } = options;\n const Rendered = createRenderer(catalog, components);\n\n function GenerativeView() {\n const mcp = useMcpApp();\n const result = useToolResult<ToolResultShape>();\n const spec = result?.structuredContent?.spec ?? null;\n if (!spec) return null;\n return createElement(Rendered, {\n spec,\n state: spec.state,\n onAction: (name: string, params?: Record<string, unknown>) => onAction(name, params, mcp),\n });\n }\n\n return createMcpView(GenerativeView, adapter);\n}\n","export {\n type ActionRouter,\n type GenerativeViewOptions,\n createGenerativeView,\n defaultActionRouter,\n defineComponents,\n} from \"./generative-view.js\";\nexport {\n type JsonRenderToolOptions,\n type RegisterJsonRenderResourceOptions,\n type RegisterJsonRenderToolOptions,\n type CreateJsonRenderMcpAppOptions,\n createJsonRenderMcpApp,\n registerJsonRenderTool,\n registerJsonRenderResource,\n} from \"./mcp.js\";\nexport {\n type BuildAppHtmlOptions,\n type UseJsonRenderAppOptions,\n type UseJsonRenderAppReturn,\n buildAppHtml,\n useJsonRenderApp,\n} from \"./app.js\";\n\n// Convenience re-exports for rendering the same catalog natively (non-MCP) —\n// previews, tests, or a plain mountly feature. Pair with `mountly-react`'s\n// `createWidget` to mount a spec outside an MCP host.\nexport { createRenderer } from \"@json-render/react\";\nexport type { ComponentMap, ComponentRenderProps } from \"@json-render/react\";\n\n// Streaming primitives (json-render's own): replay a known spec as a patch\n// stream, compile patches back into a progressively-built spec, and the AI-SDK\n// transform that classifies a model's UI-message stream into spec patches.\nexport {\n compileSpecStream,\n compileTextStreamToSpecs,\n createJsonRenderTransform,\n createSpecStreamCompiler,\n parseSpecStreamLine,\n specToPatchLines,\n} from \"./spec-stream.js\";\nexport type { Spec } from \"@json-render/core\";\n\n// --- Two ways to stream ---\n//\n// Replay (known spec): `useSpecStream` takes a finished spec — e.g. the one an\n// MCP tool delivered as `structuredContent` — and replays it as a live build,\n// with the compiler, loading flag, and cancellation included.\nexport {\n type SpecStreamState,\n type UseSpecStreamOptions,\n useSpecStream,\n} from \"./use-spec-stream.js\";\n\n// Live (from a model): `useUIStream` / `useChatUI` are json-render's own client\n// hooks — POST a prompt to an endpoint that streams JSONL patches (see\n// `streamSpec` in `mountly-mcp/json-render/server`) and render the spec as it\n// builds. Re-exported so the live path is one import away.\nexport { useChatUI, useUIStream } from \"@json-render/react\";\nexport type { UseUIStreamOptions, UseUIStreamReturn } from \"@json-render/react\";\n","import { useEffect, useState } from \"react\";\nimport type { Spec } from \"@json-render/core\";\nimport { createSpecStreamCompiler } from \"@json-render/core\";\nimport { specToPatchLines } from \"./spec-stream.js\";\n\nexport interface UseSpecStreamOptions {\n /** Delay between patches, ms. Default 90. Set 0 to render instantly. */\n intervalMs?: number;\n}\n\nexport interface SpecStreamState {\n /** The progressively-built spec (partial while streaming, full when done). */\n spec: Spec | null;\n /** Convenience: `spec?.state`, to pass straight to the renderer. */\n state: Record<string, unknown> | undefined;\n /** True while patches are still being applied. */\n loading: boolean;\n}\n\n/**\n * Replay a finished spec as a live json-render stream — and own all the\n * ceremony. Give it the target spec; it scaffolds a `createSpecStreamCompiler`,\n * replays the patches with a delay, exposes the partial spec + `loading` after\n * each step, and cancels cleanly when the target changes (so a self-driving UI\n * that swaps specs mid-stream just works). Re-streams whenever `target` changes.\n *\n * ```tsx\n * const { spec, state, loading } = useSpecStream(specs[view]);\n * return <Renderer spec={spec} state={state} loading={loading} onAction={...} />;\n * ```\n */\nexport function useSpecStream(\n target: Spec | null | undefined,\n options: UseSpecStreamOptions = {},\n): SpecStreamState {\n const { intervalMs = 90 } = options;\n const [spec, setSpec] = useState<Spec | null>(null);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!target) {\n setSpec(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n const compiler = createSpecStreamCompiler<Spec>();\n const lines = specToPatchLines(target);\n setLoading(true);\n\n void (async () => {\n for (const line of lines) {\n if (cancelled) return;\n const { result } = compiler.push(`${line}\\n`);\n setSpec({ ...result });\n if (intervalMs > 0) {\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n }\n if (cancelled) return;\n setSpec(compiler.getResult());\n setLoading(false);\n })();\n\n return () => {\n cancelled = true;\n };\n }, [target, intervalMs]);\n\n return { spec, state: spec?.state, loading };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAA4B,sBAAsB;AAyB3C,IAAM,sBAAoC,CAAC,MAAM,QAAQ,QAAQ;AACtE,MAAI,SAAS,MAAO;AACpB,QAAM,SAAS,QAAQ;AACvB,QAAM,OAAO,OAAO,WAAW,WAAW,SAAS;AACnD,MAAI,MAAM;AACR,SAAK,IAAI,YAAY,EAAE,MAAM,QAAQ,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE,CAAC;AAAA,EAC1E;AACF;AAaO,SAAS,iBACd,UACA,YACsC;AACtC,SAAO;AACT;AA+BO,SAAS,qBACd,SACS;AACT,QAAM,EAAE,SAAS,YAAY,WAAW,qBAAqB,GAAG,QAAQ,IAAI;AAC5E,QAAM,WAAW,eAAe,SAAS,UAAU;AAEnD,WAAS,iBAAiB;AACxB,UAAM,MAAM,UAAU;AACtB,UAAM,SAAS,cAA+B;AAC9C,UAAM,OAAO,QAAQ,mBAAmB,QAAQ;AAChD,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,cAAc,UAAU;AAAA,MAC7B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,UAAU,CAAC,MAAc,WAAqC,SAAS,MAAM,QAAQ,GAAG;AAAA,IAC1F,CAAC;AAAA,EACH;AAEA,SAAO,cAAc,gBAAgB,OAAO;AAC9C;;;AC1EA,SAAS,kBAAAA,uBAAsB;;;AC3B/B,SAAS,WAAW,gBAAgB;AAEpC,SAAS,4BAAAC,iCAAgC;AA6BlC,SAAS,cACd,QACA,UAAgC,CAAC,GAChB;AACjB,QAAM,EAAE,aAAa,GAAG,IAAI;AAC5B,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX,cAAQ,IAAI;AACZ,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,UAAM,WAAWC,0BAA+B;AAChD,UAAM,QAAQ,iBAAiB,MAAM;AACrC,eAAW,IAAI;AAEf,UAAM,YAAY;AAChB,iBAAW,QAAQ,OAAO;AACxB,YAAI,UAAW;AACf,cAAM,EAAE,OAAO,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,CAAI;AAC5C,gBAAQ,EAAE,GAAG,OAAO,CAAC;AACrB,YAAI,aAAa,GAAG;AAClB,gBAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AAAA,QACpD;AAAA,MACF;AACA,UAAI,UAAW;AACf,cAAQ,SAAS,UAAU,CAAC;AAC5B,iBAAW,KAAK;AAAA,IAClB,GAAG;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,CAAC;AAEvB,SAAO,EAAE,MAAM,OAAO,MAAM,OAAO,QAAQ;AAC7C;;;ADZA,SAAS,WAAW,mBAAmB;","names":["createRenderer","createSpecStreamCompiler","createSpecStreamCompiler"]}
1
+ {"version":3,"sources":["../../src/json-render/generative-view.tsx","../../src/json-render/index.ts","../../src/json-render/use-spec-stream.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { type ComponentMap, createRenderer } from \"@json-render/react\";\nimport type { Catalog, SchemaDefinition, Spec } from \"@json-render/core\";\nimport { createMcpView, useMcpApp, useToolResult } from \"../react/index.js\";\nimport type { App } from \"@modelcontextprotocol/ext-apps\";\nimport type { AdapterOptions } from \"mountly/adapter\";\nimport type { McpView } from \"../types.js\";\n\n/** The catalog-data constraint createRenderer infers against. */\ntype CatalogData = { components: Record<string, { props: unknown }> };\n\n/**\n * Route a generated UI's actions back to the MCP host. Called with the action\n * name, its (resolved) params, and the view-side `App` handle.\n */\nexport type ActionRouter = (\n name: string,\n params: Record<string, unknown> | undefined,\n mcp: App,\n) => void;\n\n/**\n * Default router: an `ask` action with a string `prompt` param sends a\n * follow-up user turn to the model via `App.sendMessage`. This is the agent\n * loop json-render alone cannot do — it has no concept of an MCP host.\n */\nexport const defaultActionRouter: ActionRouter = (name, params, mcp) => {\n if (name !== \"ask\") return;\n const prompt = params?.prompt;\n const text = typeof prompt === \"string\" ? prompt : \"\";\n if (text) {\n void mcp.sendMessage({ role: \"user\", content: [{ type: \"text\", text }] });\n }\n};\n\n/**\n * Identity helper that types a components map against a catalog (so it can be\n * defined once and reused by both `createGenerativeView` and `createRenderer`)\n * without losing per-component prop inference.\n *\n * ```ts\n * export const components = defineComponents(catalog, {\n * Metric: ({ element }) => <span>{element.props.value}</span>,\n * });\n * ```\n */\nexport function defineComponents<TDef extends SchemaDefinition, TCatalog extends CatalogData>(\n _catalog: Catalog<TDef, TCatalog>,\n components: ComponentMap<TCatalog[\"components\"]>,\n): ComponentMap<TCatalog[\"components\"]> {\n return components;\n}\n\nexport interface GenerativeViewOptions<\n TDef extends SchemaDefinition,\n TCatalog extends CatalogData,\n> extends AdapterOptions {\n /** The json-render catalog — the vocabulary the agent may compose. */\n catalog: Catalog<TDef, TCatalog>;\n /** Native component implementations for each catalog type. */\n components: ComponentMap<TCatalog[\"components\"]>;\n /**\n * How a generated UI's actions reach the agent. Defaults to\n * {@link defaultActionRouter} (`ask` → `App.sendMessage`).\n */\n onAction?: ActionRouter;\n}\n\ninterface ToolResultShape {\n structuredContent?: { spec?: Spec };\n}\n\n/**\n * Turn a json-render catalog + components into a mountly MCP Apps View.\n *\n * Reads the spec from the tool result, renders it natively (resolving `$state`\n * from `spec.state`), and routes actions back to the MCP host.\n *\n * ```ts\n * createGenerativeView({ catalog, components, styles, shadow: true });\n * ```\n */\nexport function createGenerativeView<TDef extends SchemaDefinition, TCatalog extends CatalogData>(\n options: GenerativeViewOptions<TDef, TCatalog>,\n): McpView {\n const { catalog, components, onAction = defaultActionRouter, ...adapter } = options;\n const Rendered = createRenderer(catalog, components);\n\n function GenerativeView() {\n const mcp = useMcpApp();\n const result = useToolResult<ToolResultShape>();\n const spec = result?.structuredContent?.spec ?? null;\n if (!spec) return null;\n return createElement(Rendered, {\n spec,\n state: spec.state,\n onAction: (name: string, params?: Record<string, unknown>) => onAction(name, params, mcp),\n });\n }\n\n return createMcpView(GenerativeView, adapter);\n}\n","export {\n type ActionRouter,\n type GenerativeViewOptions,\n createGenerativeView,\n defaultActionRouter,\n defineComponents,\n} from \"./generative-view.js\";\nexport {\n type JsonRenderToolOptions,\n type RegisterJsonRenderResourceOptions,\n type RegisterJsonRenderToolOptions,\n type CreateJsonRenderMcpAppOptions,\n createJsonRenderMcpApp,\n registerJsonRenderTool,\n registerJsonRenderResource,\n} from \"./mcp.js\";\nexport {\n type BuildAppHtmlOptions,\n type UseJsonRenderAppOptions,\n type UseJsonRenderAppReturn,\n buildAppHtml,\n useJsonRenderApp,\n} from \"./app.js\";\n\n// Convenience re-exports for rendering the same catalog natively (non-MCP) —\n// previews, tests, or a plain mountly feature. Pair with `mountly-react`'s\n// `createWidget` to mount a spec outside an MCP host.\nexport { createRenderer } from \"@json-render/react\";\nexport type { ComponentMap, ComponentRenderProps } from \"@json-render/react\";\n\n// Streaming primitives (json-render's own): replay a known spec as a patch\n// stream, compile patches back into a progressively-built spec, and the AI-SDK\n// transform that classifies a model's UI-message stream into spec patches.\nexport {\n compileSpecStream,\n compileTextStreamToSpecs,\n createJsonRenderTransform,\n createSpecStreamCompiler,\n parseSpecStreamLine,\n specToPatchLines,\n} from \"./spec-stream.js\";\nexport type { Spec } from \"@json-render/core\";\n\n// --- Two ways to stream ---\n//\n// Replay (known spec): `useSpecStream` takes a finished spec — e.g. the one an\n// MCP tool delivered as `structuredContent` — and replays it as a live build,\n// with the compiler, loading flag, and cancellation included.\nexport {\n type SpecStreamState,\n type UseSpecStreamOptions,\n useSpecStream,\n} from \"./use-spec-stream.js\";\n\n// Live (from a model): `useUIStream` / `useChatUI` are json-render's own client\n// hooks — POST a prompt to an endpoint that streams JSONL patches (see\n// `streamSpec` in `mountly-mcp/json-render/server`) and render the spec as it\n// builds. Re-exported so the live path is one import away.\nexport { useChatUI, useUIStream } from \"@json-render/react\";\nexport type { UseUIStreamOptions, UseUIStreamReturn } from \"@json-render/react\";\n","import { useEffect, useState } from \"react\";\nimport type { Spec } from \"@json-render/core\";\nimport { createSpecStreamCompiler } from \"@json-render/core\";\nimport { specToPatchLines } from \"./spec-stream.js\";\n\nexport interface UseSpecStreamOptions {\n /** Delay between patches, ms. Default 90. Set 0 to render instantly. */\n intervalMs?: number;\n}\n\nexport interface SpecStreamState {\n /** The progressively-built spec (partial while streaming, full when done). */\n spec: Spec | null;\n /** Convenience: `spec?.state`, to pass straight to the renderer. */\n state: Record<string, unknown> | undefined;\n /** True while patches are still being applied. */\n loading: boolean;\n}\n\n/**\n * Replay a finished spec as a live json-render stream — and own all the\n * ceremony. Give it the target spec; it scaffolds a `createSpecStreamCompiler`,\n * replays the patches with a delay, exposes the partial spec + `loading` after\n * each step, and cancels cleanly when the target changes (so a self-driving UI\n * that swaps specs mid-stream just works). Re-streams whenever `target` changes.\n *\n * ```tsx\n * const { spec, state, loading } = useSpecStream(specs[view]);\n * return <Renderer spec={spec} state={state} loading={loading} onAction={...} />;\n * ```\n */\nexport function useSpecStream(\n target: Spec | null | undefined,\n options: UseSpecStreamOptions = {},\n): SpecStreamState {\n const { intervalMs = 90 } = options;\n const [spec, setSpec] = useState<Spec | null>(null);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!target) {\n setSpec(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n const compiler = createSpecStreamCompiler<Spec>();\n const lines = specToPatchLines(target);\n setLoading(true);\n\n void (async () => {\n for (const line of lines) {\n if (cancelled) return;\n const { result } = compiler.push(`${line}\\n`);\n setSpec({ ...result });\n if (intervalMs > 0) {\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n }\n if (cancelled) return;\n setSpec(compiler.getResult());\n setLoading(false);\n })();\n\n return () => {\n cancelled = true;\n };\n }, [target, intervalMs]);\n\n return { spec, state: spec?.state, loading };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAA4B,sBAAsB;AAyB3C,IAAM,sBAAoC,CAAC,MAAM,QAAQ,QAAQ;AACtE,MAAI,SAAS,MAAO;AACpB,QAAM,SAAS,QAAQ;AACvB,QAAM,OAAO,OAAO,WAAW,WAAW,SAAS;AACnD,MAAI,MAAM;AACR,SAAK,IAAI,YAAY,EAAE,MAAM,QAAQ,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE,CAAC;AAAA,EAC1E;AACF;AAaO,SAAS,iBACd,UACA,YACsC;AACtC,SAAO;AACT;AA+BO,SAAS,qBACd,SACS;AACT,QAAM,EAAE,SAAS,YAAY,WAAW,qBAAqB,GAAG,QAAQ,IAAI;AAC5E,QAAM,WAAW,eAAe,SAAS,UAAU;AAEnD,WAAS,iBAAiB;AACxB,UAAM,MAAM,UAAU;AACtB,UAAM,SAAS,cAA+B;AAC9C,UAAM,OAAO,QAAQ,mBAAmB,QAAQ;AAChD,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,cAAc,UAAU;AAAA,MAC7B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,UAAU,CAAC,MAAc,WAAqC,SAAS,MAAM,QAAQ,GAAG;AAAA,IAC1F,CAAC;AAAA,EACH;AAEA,SAAO,cAAc,gBAAgB,OAAO;AAC9C;;;AC1EA,SAAS,kBAAAA,uBAAsB;;;AC3B/B,SAAS,WAAW,gBAAgB;AAEpC,SAAS,4BAAAC,iCAAgC;AA6BlC,SAAS,cACd,QACA,UAAgC,CAAC,GAChB;AACjB,QAAM,EAAE,aAAa,GAAG,IAAI;AAC5B,QAAM,CAAC,MAAM,OAAO,IAAI,SAAsB,IAAI;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ;AACX,cAAQ,IAAI;AACZ,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,QAAI,YAAY;AAChB,UAAM,WAAWC,0BAA+B;AAChD,UAAM,QAAQ,iBAAiB,MAAM;AACrC,eAAW,IAAI;AAEf,UAAM,YAAY;AAChB,iBAAW,QAAQ,OAAO;AACxB,YAAI,UAAW;AACf,cAAM,EAAE,OAAO,IAAI,SAAS,KAAK,GAAG,IAAI;AAAA,CAAI;AAC5C,gBAAQ,EAAE,GAAG,OAAO,CAAC;AACrB,YAAI,aAAa,GAAG;AAClB,gBAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AAAA,QACpD;AAAA,MACF;AACA,UAAI,UAAW;AACf,cAAQ,SAAS,UAAU,CAAC;AAC5B,iBAAW,KAAK;AAAA,IAClB,GAAG;AAEH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,CAAC;AAEvB,SAAO,EAAE,MAAM,OAAO,MAAM,OAAO,QAAQ;AAC7C;;;ADZA,SAAS,WAAW,mBAAmB;","names":["createRenderer","createSpecStreamCompiler","createSpecStreamCompiler"]}
@@ -1,5 +1,6 @@
1
1
  import { useAutoResize as useAutoResizeBase } from "@modelcontextprotocol/ext-apps/react";
2
2
  import type { App, McpUiDisplayMode, McpUiHostContext, McpUiUpdateModelContextRequest } from "@modelcontextprotocol/ext-apps";
3
+ import { type DownloadableFile } from "../download.js";
3
4
  /** The view-side ext-apps App. Use this to call server tools, send messages, open links, etc. */
4
5
  export declare function useMcpApp(): App;
5
6
  /** Complete notification params; read the tool arguments from `.arguments`. */
@@ -42,5 +43,11 @@ export declare function useDocumentTheme(): import("@modelcontextprotocol/ext-ap
42
43
  * triggering an immediate response. Only the last update is kept.
43
44
  */
44
45
  export declare function useUpdateModelContext(): (params: McpUiUpdateModelContextRequest["params"]) => Promise<void>;
46
+ /**
47
+ * Return a function that hands the user a file: through the host's
48
+ * `ui/download-file` where it has one, else an ordinary `<a download>`.
49
+ * Resolves `false` when the host declined or the user cancelled.
50
+ */
51
+ export declare function useDownload(): (file: DownloadableFile) => Promise<boolean>;
45
52
  /** Manually control auto-resize (rarely needed — the bridge calls setupSizeChangedNotifications by default). */
46
53
  export declare function useAutoResize(...args: Parameters<typeof useAutoResizeBase>): void;
@@ -3,6 +3,7 @@ import {
3
3
  useAutoResize,
4
4
  useDisplayMode,
5
5
  useDocumentTheme,
6
+ useDownload,
6
7
  useHostContext,
7
8
  useHostFonts,
8
9
  useHostStyleVariables,
@@ -13,10 +14,11 @@ import {
13
14
  useToolInputPartial,
14
15
  useToolResult,
15
16
  useUpdateModelContext
16
- } from "../chunk-HIAIQVK5.js";
17
+ } from "../chunk-QIA76O6M.js";
17
18
  import {
18
19
  McpContext
19
20
  } from "../chunk-4SZHJ4MK.js";
21
+ import "../chunk-BLT2MK32.js";
20
22
  import "../chunk-5L3QHYWK.js";
21
23
  export {
22
24
  McpContext,
@@ -24,6 +26,7 @@ export {
24
26
  useAutoResize,
25
27
  useDisplayMode,
26
28
  useDocumentTheme,
29
+ useDownload,
27
30
  useHostContext,
28
31
  useHostFonts,
29
32
  useHostStyleVariables,
@@ -0,0 +1,84 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
+ import { EXTENSION_ID, RESOURCE_MIME_TYPE, type McpUiAppToolConfig } from "@modelcontextprotocol/ext-apps/server";
5
+ import type { McpUiToolVisibility } from "@modelcontextprotocol/ext-apps";
6
+ import { type McpAppArtifact, type McpAppSource } from "../artifact/declaration.js";
7
+ export interface McpAppToolResult {
8
+ structuredContent?: unknown;
9
+ content?: ReadonlyArray<{
10
+ type: string;
11
+ [key: string]: unknown;
12
+ }>;
13
+ isError?: boolean;
14
+ }
15
+ /** Complete official tool configuration, plus JSON Schema support at Mountly's seam. */
16
+ export interface McpAppToolConfig extends Omit<McpUiAppToolConfig, "_meta" | "inputSchema" | "outputSchema"> {
17
+ inputSchema?: object;
18
+ outputSchema?: object;
19
+ /** Additional metadata is preserved; Mountly only merges `_meta.ui`. */
20
+ _meta?: Record<string, unknown>;
21
+ }
22
+ /** A View is independent of the tools that reference it. */
23
+ export interface McpAppViewRegistration {
24
+ /**
25
+ * Built artifact or the path to its self-contained HTML — or, on a runtime
26
+ * with no filesystem such as Cloudflare Workers, the View itself, as
27
+ * `mountly-mcp.views.js` exports it.
28
+ */
29
+ artifact: McpAppArtifact | McpAppSource | string;
30
+ /** Optional assertion used by migration adapters; artifacts already own identity. */
31
+ uri?: string;
32
+ }
33
+ /** A tool links to a separately declared View through the protocol resource URI. */
34
+ export interface McpAppToolRegistration<Args = unknown> {
35
+ name: string;
36
+ resourceUri: string;
37
+ config?: McpAppToolConfig;
38
+ /** Convenience override for `_meta.ui.visibility`. */
39
+ visibility?: McpUiToolVisibility | ReadonlyArray<McpUiToolVisibility>;
40
+ handler: (args: Args, extra?: unknown) => Promise<McpAppToolResult>;
41
+ }
42
+ export interface RegisterMcpAppsOptions {
43
+ views: ReadonlyArray<McpAppViewRegistration>;
44
+ tools?: ReadonlyArray<McpAppToolRegistration>;
45
+ }
46
+ /**
47
+ * `createMcpAppServer` declares Views and tools exactly as `registerMcpApps`
48
+ * does; it only owns the `McpServer` for you. One vocabulary, two entry points.
49
+ */
50
+ export interface CreateMcpAppServerOptions extends RegisterMcpAppsOptions {
51
+ name: string;
52
+ version: string;
53
+ }
54
+ export interface RegisteredMcpApps {
55
+ /** File-backed Views carry `htmlPath`; in-memory ones carry `html`. */
56
+ artifacts: ReadonlyArray<McpAppArtifact | McpAppSource>;
57
+ /** Remove every resource and tool installed by this registration. */
58
+ remove(): void;
59
+ }
60
+ /** Reads a View from disk. Only the Node entry installs one; a Worker has no disk. */
61
+ export type DiskViewLoader = (artifact: McpAppArtifact | string, uri: string | undefined) => Promise<{
62
+ artifact: McpAppArtifact;
63
+ html: string;
64
+ }>;
65
+ /** @internal Called once by the Node entry. */
66
+ export declare function installDiskViewLoader(loader: DiskViewLoader): void;
67
+ /**
68
+ * Install Mountly Views and their independently declared tools into an existing,
69
+ * unconnected MCP server. The caller retains ownership of identity, auth,
70
+ * transports, prompts, ordinary tools, and deployment.
71
+ */
72
+ export declare function registerMcpApps(server: McpServer, options: RegisterMcpAppsOptions): Promise<RegisteredMcpApps>;
73
+ export interface RunningMcpAppServer {
74
+ connectInProcess(options?: {
75
+ ui?: boolean;
76
+ }): Promise<{
77
+ client: Client;
78
+ }>;
79
+ listen(transport: Transport): Promise<void>;
80
+ close(): Promise<void>;
81
+ }
82
+ /** Convenience adapter that retains the original one-call server experience. */
83
+ export declare function createMcpAppServer(options: CreateMcpAppServerOptions): RunningMcpAppServer;
84
+ export { EXTENSION_ID, RESOURCE_MIME_TYPE };
@@ -1,73 +1,3 @@
1
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
4
- import { EXTENSION_ID, RESOURCE_MIME_TYPE, type McpUiAppToolConfig } from "@modelcontextprotocol/ext-apps/server";
5
- import type { McpUiToolVisibility } from "@modelcontextprotocol/ext-apps";
6
- import { type McpAppArtifact } from "../artifact/index.js";
7
- export interface McpAppToolResult {
8
- structuredContent?: unknown;
9
- content?: ReadonlyArray<{
10
- type: string;
11
- [key: string]: unknown;
12
- }>;
13
- isError?: boolean;
14
- }
15
- /** Complete official tool configuration, plus JSON Schema support at Mountly's seam. */
16
- export interface McpAppToolConfig extends Omit<McpUiAppToolConfig, "_meta" | "inputSchema" | "outputSchema"> {
17
- inputSchema?: object;
18
- outputSchema?: object;
19
- /** Additional metadata is preserved; Mountly only merges `_meta.ui`. */
20
- _meta?: Record<string, unknown>;
21
- }
22
- /** A View is independent of the tools that reference it. */
23
- export interface McpAppViewRegistration {
24
- /** Built artifact or the path to its self-contained HTML. */
25
- artifact: McpAppArtifact | string;
26
- /** Optional assertion used by migration adapters; artifacts already own identity. */
27
- uri?: string;
28
- }
29
- /** A tool links to a separately declared View through the protocol resource URI. */
30
- export interface McpAppToolRegistration<Args = unknown> {
31
- name: string;
32
- resourceUri: string;
33
- config?: McpAppToolConfig;
34
- /** Convenience override for `_meta.ui.visibility`. */
35
- visibility?: McpUiToolVisibility | ReadonlyArray<McpUiToolVisibility>;
36
- handler: (args: Args, extra?: unknown) => Promise<McpAppToolResult>;
37
- }
38
- export interface RegisterMcpAppsOptions {
39
- views: ReadonlyArray<McpAppViewRegistration>;
40
- tools?: ReadonlyArray<McpAppToolRegistration>;
41
- }
42
- /**
43
- * `createMcpAppServer` declares Views and tools exactly as `registerMcpApps`
44
- * does; it only owns the `McpServer` for you. One vocabulary, two entry points.
45
- */
46
- export interface CreateMcpAppServerOptions extends RegisterMcpAppsOptions {
47
- name: string;
48
- version: string;
49
- }
50
- export interface RegisteredMcpApps {
51
- artifacts: ReadonlyArray<McpAppArtifact>;
52
- /** Remove every resource and tool installed by this registration. */
53
- remove(): void;
54
- }
55
- /**
56
- * Install Mountly Views and their independently declared tools into an existing,
57
- * unconnected MCP server. The caller retains ownership of identity, auth,
58
- * transports, prompts, ordinary tools, and deployment.
59
- */
60
- export declare function registerMcpApps(server: McpServer, options: RegisterMcpAppsOptions): Promise<RegisteredMcpApps>;
61
- export interface RunningMcpAppServer {
62
- connectInProcess(options?: {
63
- ui?: boolean;
64
- }): Promise<{
65
- client: Client;
66
- }>;
67
- listen(transport: Transport): Promise<void>;
68
- close(): Promise<void>;
69
- }
70
- /** Convenience adapter that retains the original one-call server experience. */
71
- export declare function createMcpAppServer(options: CreateMcpAppServerOptions): RunningMcpAppServer;
1
+ import { type CreateMcpAppServerOptions, type RunningMcpAppServer } from "./core.js";
2
+ export { EXTENSION_ID, RESOURCE_MIME_TYPE, createMcpAppServer, registerMcpApps, type CreateMcpAppServerOptions, type McpAppToolConfig, type McpAppToolRegistration, type McpAppToolResult, type McpAppViewRegistration, type RegisterMcpAppsOptions, type RegisteredMcpApps, type RunningMcpAppServer, } from "./core.js";
72
3
  export declare function serveStdio(options: CreateMcpAppServerOptions): Promise<RunningMcpAppServer>;
73
- export { EXTENSION_ID, RESOURCE_MIME_TYPE };
@@ -1,229 +1,29 @@
1
+ import {
2
+ EXTENSION_ID,
3
+ RESOURCE_MIME_TYPE,
4
+ createMcpAppServer,
5
+ installDiskViewLoader,
6
+ registerMcpApps
7
+ } from "../chunk-UMQ5OULD.js";
1
8
  import {
2
9
  readMcpAppArtifact
3
- } from "../chunk-DKK26TRS.js";
10
+ } from "../chunk-RLDSMU5M.js";
11
+ import "../chunk-6T5EIQGE.js";
4
12
 
5
13
  // src/server/index.ts
6
14
  import { readFile } from "fs/promises";
7
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
- import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
10
- import {
11
- EXTENSION_ID,
12
- RESOURCE_MIME_TYPE,
13
- getUiCapability,
14
- registerAppResource,
15
- registerAppTool
16
- } from "@modelcontextprotocol/ext-apps/server";
17
- import { z } from "zod";
18
- function normalizeVisibility(visibility) {
19
- if (visibility === void 0) return void 0;
20
- return typeof visibility === "string" ? [visibility] : [...visibility];
21
- }
22
- function isSchemaLibraryValue(value) {
23
- return typeof value === "object" && value !== null && ("~standard" in value || "_def" in value);
24
- }
25
- function normalizeToolSchema(schema) {
26
- if (!schema || Object.keys(schema).length === 0) return schema;
27
- const candidate = schema;
28
- if (isSchemaLibraryValue(candidate) || Object.values(candidate).some(isSchemaLibraryValue)) {
29
- return schema;
30
- }
31
- const jsonSchemaKeys = [
32
- "$schema",
33
- "$ref",
34
- "$defs",
35
- "type",
36
- "properties",
37
- "required",
38
- "additionalProperties",
39
- "allOf",
40
- "anyOf",
41
- "oneOf"
42
- ];
43
- return jsonSchemaKeys.some((key) => key in candidate) ? z.fromJSONSchema(schema) : schema;
44
- }
45
- function withTextFallback(result) {
46
- if (result.content && result.content.length > 0) return result;
47
- if (result.structuredContent === void 0) return result;
48
- return {
49
- ...result,
50
- content: [{ type: "text", text: JSON.stringify(result.structuredContent) }]
51
- };
52
- }
53
- function withoutUiMetadata(meta) {
54
- const copy = { ...meta };
55
- delete copy.ui;
56
- delete copy["ui/resourceUri"];
57
- return copy;
58
- }
59
- function mergedToolMetadata(tool) {
60
- const base = { ...tool.config?._meta ?? {} };
61
- const existingUi = typeof base.ui === "object" && base.ui !== null ? base.ui : {};
62
- const visibility = normalizeVisibility(tool.visibility) ?? [
63
- ...existingUi.visibility ?? ["model", "app"]
64
- ];
65
- const meta = {
66
- ...base,
67
- ui: { ...existingUi, resourceUri: tool.resourceUri, visibility }
68
- };
69
- return { meta, withoutUi: withoutUiMetadata(base), visibility };
70
- }
71
- async function loadViews(registrations) {
72
- const loaded = [];
73
- const names = /* @__PURE__ */ new Set();
74
- const uris = /* @__PURE__ */ new Set();
75
- for (const registration of registrations) {
76
- if (registration.uri !== void 0 && !registration.uri.startsWith("ui://")) {
77
- throw new Error(
78
- `mountly-mcp/server: registration uri must use the 'ui://' scheme (received '${registration.uri}')`
79
- );
80
- }
81
- const supplied = typeof registration.artifact === "string" ? void 0 : registration.artifact;
82
- const artifact = await readMcpAppArtifact(
83
- typeof registration.artifact === "string" ? registration.artifact : registration.artifact.htmlPath,
84
- registration.uri ?? supplied?.uri
85
- );
86
- if (supplied && supplied.name !== artifact.name) {
87
- throw new Error(
88
- `mountly-mcp: supplied artifact name '${supplied.name}' does not match file artifact name '${artifact.name}'`
89
- );
90
- }
91
- if (names.has(artifact.name))
92
- throw new Error(`mountly-mcp: duplicate app name '${artifact.name}'`);
93
- if (uris.has(artifact.uri)) throw new Error(`mountly-mcp: duplicate app uri '${artifact.uri}'`);
94
- names.add(artifact.name);
95
- uris.add(artifact.uri);
96
- loaded.push({ artifact, html: await readFile(artifact.htmlPath, "utf8") });
97
- }
98
- return loaded;
99
- }
100
- async function registerMcpApps(server, options) {
101
- if (server.isConnected()) {
102
- throw new Error("mountly-mcp: registerMcpApps() must run before the server connects");
103
- }
104
- if (options.views.length === 0) {
105
- throw new Error("mountly-mcp: registerMcpApps() requires at least one View");
106
- }
107
- const views = await loadViews(options.views);
108
- const byUri = new Map(views.map((view) => [view.artifact.uri, view]));
109
- for (const tool of options.tools ?? []) {
110
- if (!byUri.has(tool.resourceUri)) {
111
- throw new Error(
112
- `mountly-mcp: tool '${tool.name}' references undeclared View '${tool.resourceUri}'`
113
- );
114
- }
115
- }
116
- server.server.registerCapabilities({
117
- extensions: { [EXTENSION_ID]: { mimeTypes: [RESOURCE_MIME_TYPE] } }
118
- });
119
- const resources = views.map(({ artifact, html }) => {
120
- const resourceMeta = {
121
- ui: artifact.declaration._meta.ui
122
- };
123
- const openaiUi = artifact.declaration._meta["openai/ui"];
124
- if (openaiUi !== void 0) resourceMeta["openai/ui"] = openaiUi;
125
- return registerAppResource(
126
- server,
127
- artifact.name,
128
- artifact.uri,
129
- {
130
- mimeType: artifact.declaration.mimeType,
131
- description: artifact.declaration.description,
132
- _meta: resourceMeta
133
- },
134
- async () => ({
135
- contents: [
136
- {
137
- uri: artifact.uri,
138
- mimeType: artifact.declaration.mimeType,
139
- text: html,
140
- _meta: resourceMeta
141
- }
142
- ]
143
- })
144
- );
145
- });
146
- const tools = (options.tools ?? []).map((registration) => {
147
- const { meta, withoutUi, visibility } = mergedToolMetadata(registration);
148
- const config = registration.config ?? {};
149
- const registered = registerAppTool(
150
- server,
151
- registration.name,
152
- {
153
- ...config,
154
- inputSchema: normalizeToolSchema(config.inputSchema),
155
- outputSchema: normalizeToolSchema(config.outputSchema),
156
- _meta: meta
157
- },
158
- (async (args, extra) => withTextFallback(await registration.handler(args, extra)))
159
- );
160
- return { registration, registered, metadataWithoutUi: withoutUi, visibility };
161
- });
162
- const previousInitialized = server.server.oninitialized;
163
- const handleInitialized = () => {
164
- previousInitialized?.();
165
- const ui = getUiCapability(server.server.getClientCapabilities());
166
- if (ui?.mimeTypes?.includes(RESOURCE_MIME_TYPE)) return;
167
- for (const resource of resources) resource.remove();
168
- for (const tool of tools) {
169
- if (tool.visibility.includes("model")) {
170
- tool.registered.update({ _meta: tool.metadataWithoutUi });
171
- } else {
172
- tool.registered.remove();
173
- }
174
- }
175
- };
176
- server.server.oninitialized = handleInitialized;
177
- return {
178
- artifacts: views.map((view) => view.artifact),
179
- remove() {
180
- for (const resource of resources) resource.remove();
181
- for (const tool of tools) tool.registered.remove();
182
- if (server.server.oninitialized === handleInitialized) {
183
- server.server.oninitialized = previousInitialized;
184
- }
185
- }
186
- };
187
- }
188
- function createConfiguredServer(options) {
189
- return new McpServer(
190
- { name: options.name, version: options.version },
191
- { capabilities: { resources: {}, tools: {} } }
15
+ installDiskViewLoader(async (supplied, uri) => {
16
+ const artifact = await readMcpAppArtifact(
17
+ typeof supplied === "string" ? supplied : supplied.htmlPath,
18
+ uri ?? (typeof supplied === "string" ? void 0 : supplied.uri)
192
19
  );
193
- }
194
- function createMcpAppServer(options) {
195
- let server;
196
- async function build() {
197
- const next = createConfiguredServer(options);
198
- await registerMcpApps(next, { views: options.views, tools: options.tools });
199
- server = next;
200
- return next;
20
+ if (typeof supplied !== "string" && supplied.name !== artifact.name) {
21
+ throw new Error(
22
+ `mountly-mcp: supplied artifact name '${supplied.name}' does not match file artifact name '${artifact.name}'`
23
+ );
201
24
  }
202
- return {
203
- async connectInProcess(connectOptions) {
204
- const next = await build();
205
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
206
- await next.connect(serverTransport);
207
- const client = new Client(
208
- { name: `${options.name}-inprocess-client`, version: options.version },
209
- connectOptions?.ui ?? true ? {
210
- capabilities: {
211
- extensions: { [EXTENSION_ID]: { mimeTypes: [RESOURCE_MIME_TYPE] } }
212
- }
213
- } : void 0
214
- );
215
- await client.connect(clientTransport);
216
- return { client };
217
- },
218
- async listen(transport) {
219
- const next = await build();
220
- await next.connect(transport);
221
- },
222
- async close() {
223
- await server?.close();
224
- }
225
- };
226
- }
25
+ return { artifact, html: await readFile(artifact.htmlPath, "utf8") };
26
+ });
227
27
  async function serveStdio(options) {
228
28
  const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
229
29
  const server = createMcpAppServer(options);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n EXTENSION_ID,\n RESOURCE_MIME_TYPE,\n getUiCapability,\n registerAppResource,\n registerAppTool,\n type McpUiAppToolConfig,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport type { McpUiToolMeta, McpUiToolVisibility } from \"@modelcontextprotocol/ext-apps\";\nimport { z } from \"zod\";\nimport { readMcpAppArtifact, type McpAppArtifact } from \"../artifact/index.js\";\n\nexport interface McpAppToolResult {\n structuredContent?: unknown;\n content?: ReadonlyArray<{ type: string; [key: string]: unknown }>;\n isError?: boolean;\n}\n\n/** Complete official tool configuration, plus JSON Schema support at Mountly's seam. */\nexport interface McpAppToolConfig extends Omit<\n McpUiAppToolConfig,\n \"_meta\" | \"inputSchema\" | \"outputSchema\"\n> {\n inputSchema?: object;\n outputSchema?: object;\n /** Additional metadata is preserved; Mountly only merges `_meta.ui`. */\n _meta?: Record<string, unknown>;\n}\n\n/** A View is independent of the tools that reference it. */\nexport interface McpAppViewRegistration {\n /** Built artifact or the path to its self-contained HTML. */\n artifact: McpAppArtifact | string;\n /** Optional assertion used by migration adapters; artifacts already own identity. */\n uri?: string;\n}\n\n/** A tool links to a separately declared View through the protocol resource URI. */\nexport interface McpAppToolRegistration<Args = unknown> {\n name: string;\n resourceUri: string;\n config?: McpAppToolConfig;\n /** Convenience override for `_meta.ui.visibility`. */\n visibility?: McpUiToolVisibility | ReadonlyArray<McpUiToolVisibility>;\n handler: (args: Args, extra?: unknown) => Promise<McpAppToolResult>;\n}\n\nexport interface RegisterMcpAppsOptions {\n views: ReadonlyArray<McpAppViewRegistration>;\n tools?: ReadonlyArray<McpAppToolRegistration>;\n}\n\n/**\n * `createMcpAppServer` declares Views and tools exactly as `registerMcpApps`\n * does; it only owns the `McpServer` for you. One vocabulary, two entry points.\n */\nexport interface CreateMcpAppServerOptions extends RegisterMcpAppsOptions {\n name: string;\n version: string;\n}\n\ninterface LoadedView {\n artifact: McpAppArtifact;\n html: string;\n}\n\ninterface InstalledTool {\n registration: McpAppToolRegistration;\n registered: { remove(): void; update(u: { _meta?: object }): void };\n metadataWithoutUi: Record<string, unknown>;\n visibility: ReadonlyArray<McpUiToolVisibility>;\n}\n\nexport interface RegisteredMcpApps {\n artifacts: ReadonlyArray<McpAppArtifact>;\n /** Remove every resource and tool installed by this registration. */\n remove(): void;\n}\n\nfunction normalizeVisibility(\n visibility: McpAppToolRegistration[\"visibility\"],\n): McpUiToolVisibility[] | undefined {\n if (visibility === undefined) return undefined;\n return typeof visibility === \"string\" ? [visibility] : [...visibility];\n}\n\nfunction isSchemaLibraryValue(value: unknown): boolean {\n return typeof value === \"object\" && value !== null && (\"~standard\" in value || \"_def\" in value);\n}\n\n/** Convert documented JSON Schema while preserving Zod and Standard Schema values. */\nfunction normalizeToolSchema(schema: object | undefined): object | undefined {\n if (!schema || Object.keys(schema).length === 0) return schema;\n const candidate = schema as Record<string, unknown>;\n if (isSchemaLibraryValue(candidate) || Object.values(candidate).some(isSchemaLibraryValue)) {\n return schema;\n }\n const jsonSchemaKeys = [\n \"$schema\",\n \"$ref\",\n \"$defs\",\n \"type\",\n \"properties\",\n \"required\",\n \"additionalProperties\",\n \"allOf\",\n \"anyOf\",\n \"oneOf\",\n ];\n return jsonSchemaKeys.some((key) => key in candidate)\n ? z.fromJSONSchema(schema as never)\n : schema;\n}\n\nfunction withTextFallback(result: McpAppToolResult): McpAppToolResult {\n if (result.content && result.content.length > 0) return result;\n if (result.structuredContent === undefined) return result;\n return {\n ...result,\n content: [{ type: \"text\", text: JSON.stringify(result.structuredContent) }],\n };\n}\n\nfunction withoutUiMetadata(meta: Record<string, unknown>): Record<string, unknown> {\n const copy = { ...meta };\n delete copy.ui;\n delete copy[\"ui/resourceUri\"];\n return copy;\n}\n\nfunction mergedToolMetadata(tool: McpAppToolRegistration): {\n meta: Record<string, unknown> & { ui: McpUiToolMeta };\n withoutUi: Record<string, unknown>;\n visibility: McpUiToolVisibility[];\n} {\n const base = { ...(tool.config?._meta ?? {}) };\n const existingUi =\n typeof base.ui === \"object\" && base.ui !== null ? (base.ui as Partial<McpUiToolMeta>) : {};\n const visibility = normalizeVisibility(tool.visibility) ?? [\n ...(existingUi.visibility ?? [\"model\", \"app\"]),\n ];\n const meta = {\n ...base,\n ui: { ...existingUi, resourceUri: tool.resourceUri, visibility },\n };\n return { meta, withoutUi: withoutUiMetadata(base), visibility };\n}\n\nasync function loadViews(\n registrations: ReadonlyArray<McpAppViewRegistration>,\n): Promise<ReadonlyArray<LoadedView>> {\n const loaded: LoadedView[] = [];\n const names = new Set<string>();\n const uris = new Set<string>();\n for (const registration of registrations) {\n if (registration.uri !== undefined && !registration.uri.startsWith(\"ui://\")) {\n throw new Error(\n `mountly-mcp/server: registration uri must use the 'ui://' scheme (received '${registration.uri}')`,\n );\n }\n const supplied = typeof registration.artifact === \"string\" ? undefined : registration.artifact;\n const artifact = await readMcpAppArtifact(\n typeof registration.artifact === \"string\"\n ? registration.artifact\n : registration.artifact.htmlPath,\n registration.uri ?? supplied?.uri,\n );\n if (supplied && supplied.name !== artifact.name) {\n throw new Error(\n `mountly-mcp: supplied artifact name '${supplied.name}' does not match file artifact name '${artifact.name}'`,\n );\n }\n if (names.has(artifact.name))\n throw new Error(`mountly-mcp: duplicate app name '${artifact.name}'`);\n if (uris.has(artifact.uri)) throw new Error(`mountly-mcp: duplicate app uri '${artifact.uri}'`);\n names.add(artifact.name);\n uris.add(artifact.uri);\n loaded.push({ artifact, html: await readFile(artifact.htmlPath, \"utf8\") });\n }\n return loaded;\n}\n\n/**\n * Install Mountly Views and their independently declared tools into an existing,\n * unconnected MCP server. The caller retains ownership of identity, auth,\n * transports, prompts, ordinary tools, and deployment.\n */\nexport async function registerMcpApps(\n server: McpServer,\n options: RegisterMcpAppsOptions,\n): Promise<RegisteredMcpApps> {\n if (server.isConnected()) {\n throw new Error(\"mountly-mcp: registerMcpApps() must run before the server connects\");\n }\n if (options.views.length === 0) {\n throw new Error(\"mountly-mcp: registerMcpApps() requires at least one View\");\n }\n const views = await loadViews(options.views);\n const byUri = new Map(views.map((view) => [view.artifact.uri, view]));\n for (const tool of options.tools ?? []) {\n if (!byUri.has(tool.resourceUri)) {\n throw new Error(\n `mountly-mcp: tool '${tool.name}' references undeclared View '${tool.resourceUri}'`,\n );\n }\n }\n\n server.server.registerCapabilities({\n extensions: { [EXTENSION_ID]: { mimeTypes: [RESOURCE_MIME_TYPE] } },\n } as never);\n\n const resources = views.map(({ artifact, html }) => {\n const resourceMeta: Record<string, unknown> = {\n ui: artifact.declaration._meta.ui,\n };\n const openaiUi = artifact.declaration._meta[\"openai/ui\"];\n if (openaiUi !== undefined) resourceMeta[\"openai/ui\"] = openaiUi;\n return registerAppResource(\n server,\n artifact.name,\n artifact.uri,\n {\n mimeType: artifact.declaration.mimeType,\n description: artifact.declaration.description,\n _meta: resourceMeta,\n },\n async () => ({\n contents: [\n {\n uri: artifact.uri,\n mimeType: artifact.declaration.mimeType,\n text: html,\n _meta: resourceMeta,\n },\n ],\n }),\n );\n });\n\n const tools: InstalledTool[] = (options.tools ?? []).map((registration) => {\n const { meta, withoutUi, visibility } = mergedToolMetadata(registration);\n const config = registration.config ?? {};\n const registered = registerAppTool(\n server,\n registration.name,\n {\n ...config,\n inputSchema: normalizeToolSchema(config.inputSchema) as never,\n outputSchema: normalizeToolSchema(config.outputSchema) as never,\n _meta: meta,\n },\n (async (args: unknown, extra: unknown) =>\n withTextFallback(await registration.handler(args, extra))) as never,\n );\n return { registration, registered, metadataWithoutUi: withoutUi, visibility };\n });\n\n const previousInitialized = server.server.oninitialized;\n const handleInitialized = () => {\n previousInitialized?.();\n const ui = getUiCapability(server.server.getClientCapabilities());\n if (ui?.mimeTypes?.includes(RESOURCE_MIME_TYPE)) return;\n for (const resource of resources) resource.remove();\n for (const tool of tools) {\n if (tool.visibility.includes(\"model\")) {\n tool.registered.update({ _meta: tool.metadataWithoutUi });\n } else {\n tool.registered.remove();\n }\n }\n };\n server.server.oninitialized = handleInitialized;\n\n return {\n artifacts: views.map((view) => view.artifact),\n remove() {\n for (const resource of resources) resource.remove();\n for (const tool of tools) tool.registered.remove();\n if (server.server.oninitialized === handleInitialized) {\n server.server.oninitialized = previousInitialized;\n }\n },\n };\n}\n\nexport interface RunningMcpAppServer {\n connectInProcess(options?: { ui?: boolean }): Promise<{ client: Client }>;\n listen(transport: Transport): Promise<void>;\n close(): Promise<void>;\n}\n\nfunction createConfiguredServer(options: CreateMcpAppServerOptions): McpServer {\n return new McpServer(\n { name: options.name, version: options.version },\n { capabilities: { resources: {}, tools: {} } },\n );\n}\n\n/** Convenience adapter that retains the original one-call server experience. */\nexport function createMcpAppServer(options: CreateMcpAppServerOptions): RunningMcpAppServer {\n let server: McpServer | undefined;\n async function build(): Promise<McpServer> {\n const next = createConfiguredServer(options);\n await registerMcpApps(next, { views: options.views, tools: options.tools });\n server = next;\n return next;\n }\n return {\n async connectInProcess(connectOptions) {\n const next = await build();\n const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();\n await next.connect(serverTransport);\n const client = new Client(\n { name: `${options.name}-inprocess-client`, version: options.version },\n (connectOptions?.ui ?? true)\n ? ({\n capabilities: {\n extensions: { [EXTENSION_ID]: { mimeTypes: [RESOURCE_MIME_TYPE] } },\n },\n } as never)\n : undefined,\n );\n await client.connect(clientTransport);\n return { client };\n },\n async listen(transport) {\n const next = await build();\n await next.connect(transport);\n },\n async close() {\n await server?.close();\n },\n };\n}\n\nexport async function serveStdio(options: CreateMcpAppServerOptions): Promise<RunningMcpAppServer> {\n const { StdioServerTransport } = await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n const server = createMcpAppServer(options);\n await server.listen(new StdioServerTransport());\n return server;\n}\n\nexport { EXTENSION_ID, RESOURCE_MIME_TYPE };\n"],"mappings":";;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAElC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,SAAS;AAsElB,SAAS,oBACP,YACmC;AACnC,MAAI,eAAe,OAAW,QAAO;AACrC,SAAO,OAAO,eAAe,WAAW,CAAC,UAAU,IAAI,CAAC,GAAG,UAAU;AACvE;AAEA,SAAS,qBAAqB,OAAyB;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,SAAS,eAAe,SAAS,UAAU;AAC3F;AAGA,SAAS,oBAAoB,QAAgD;AAC3E,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AACxD,QAAM,YAAY;AAClB,MAAI,qBAAqB,SAAS,KAAK,OAAO,OAAO,SAAS,EAAE,KAAK,oBAAoB,GAAG;AAC1F,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,eAAe,KAAK,CAAC,QAAQ,OAAO,SAAS,IAChD,EAAE,eAAe,MAAe,IAChC;AACN;AAEA,SAAS,iBAAiB,QAA4C;AACpE,MAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,EAAG,QAAO;AACxD,MAAI,OAAO,sBAAsB,OAAW,QAAO;AACnD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,iBAAiB,EAAE,CAAC;AAAA,EAC5E;AACF;AAEA,SAAS,kBAAkB,MAAwD;AACjF,QAAM,OAAO,EAAE,GAAG,KAAK;AACvB,SAAO,KAAK;AACZ,SAAO,KAAK,gBAAgB;AAC5B,SAAO;AACT;AAEA,SAAS,mBAAmB,MAI1B;AACA,QAAM,OAAO,EAAE,GAAI,KAAK,QAAQ,SAAS,CAAC,EAAG;AAC7C,QAAM,aACJ,OAAO,KAAK,OAAO,YAAY,KAAK,OAAO,OAAQ,KAAK,KAAgC,CAAC;AAC3F,QAAM,aAAa,oBAAoB,KAAK,UAAU,KAAK;AAAA,IACzD,GAAI,WAAW,cAAc,CAAC,SAAS,KAAK;AAAA,EAC9C;AACA,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,IAAI,EAAE,GAAG,YAAY,aAAa,KAAK,aAAa,WAAW;AAAA,EACjE;AACA,SAAO,EAAE,MAAM,WAAW,kBAAkB,IAAI,GAAG,WAAW;AAChE;AAEA,eAAe,UACb,eACoC;AACpC,QAAM,SAAuB,CAAC;AAC9B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,gBAAgB,eAAe;AACxC,QAAI,aAAa,QAAQ,UAAa,CAAC,aAAa,IAAI,WAAW,OAAO,GAAG;AAC3E,YAAM,IAAI;AAAA,QACR,+EAA+E,aAAa,GAAG;AAAA,MACjG;AAAA,IACF;AACA,UAAM,WAAW,OAAO,aAAa,aAAa,WAAW,SAAY,aAAa;AACtF,UAAM,WAAW,MAAM;AAAA,MACrB,OAAO,aAAa,aAAa,WAC7B,aAAa,WACb,aAAa,SAAS;AAAA,MAC1B,aAAa,OAAO,UAAU;AAAA,IAChC;AACA,QAAI,YAAY,SAAS,SAAS,SAAS,MAAM;AAC/C,YAAM,IAAI;AAAA,QACR,wCAAwC,SAAS,IAAI,wCAAwC,SAAS,IAAI;AAAA,MAC5G;AAAA,IACF;AACA,QAAI,MAAM,IAAI,SAAS,IAAI;AACzB,YAAM,IAAI,MAAM,oCAAoC,SAAS,IAAI,GAAG;AACtE,QAAI,KAAK,IAAI,SAAS,GAAG,EAAG,OAAM,IAAI,MAAM,mCAAmC,SAAS,GAAG,GAAG;AAC9F,UAAM,IAAI,SAAS,IAAI;AACvB,SAAK,IAAI,SAAS,GAAG;AACrB,WAAO,KAAK,EAAE,UAAU,MAAM,MAAM,SAAS,SAAS,UAAU,MAAM,EAAE,CAAC;AAAA,EAC3E;AACA,SAAO;AACT;AAOA,eAAsB,gBACpB,QACA,SAC4B;AAC5B,MAAI,OAAO,YAAY,GAAG;AACxB,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,MAAI,QAAQ,MAAM,WAAW,GAAG;AAC9B,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,QAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK;AAC3C,QAAM,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC;AACpE,aAAW,QAAQ,QAAQ,SAAS,CAAC,GAAG;AACtC,QAAI,CAAC,MAAM,IAAI,KAAK,WAAW,GAAG;AAChC,YAAM,IAAI;AAAA,QACR,sBAAsB,KAAK,IAAI,iCAAiC,KAAK,WAAW;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,qBAAqB;AAAA,IACjC,YAAY,EAAE,CAAC,YAAY,GAAG,EAAE,WAAW,CAAC,kBAAkB,EAAE,EAAE;AAAA,EACpE,CAAU;AAEV,QAAM,YAAY,MAAM,IAAI,CAAC,EAAE,UAAU,KAAK,MAAM;AAClD,UAAM,eAAwC;AAAA,MAC5C,IAAI,SAAS,YAAY,MAAM;AAAA,IACjC;AACA,UAAM,WAAW,SAAS,YAAY,MAAM,WAAW;AACvD,QAAI,aAAa,OAAW,cAAa,WAAW,IAAI;AACxD,WAAO;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,QACE,UAAU,SAAS,YAAY;AAAA,QAC/B,aAAa,SAAS,YAAY;AAAA,QAClC,OAAO;AAAA,MACT;AAAA,MACA,aAAa;AAAA,QACX,UAAU;AAAA,UACR;AAAA,YACE,KAAK,SAAS;AAAA,YACd,UAAU,SAAS,YAAY;AAAA,YAC/B,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,SAA0B,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,iBAAiB;AACzE,UAAM,EAAE,MAAM,WAAW,WAAW,IAAI,mBAAmB,YAAY;AACvE,UAAM,SAAS,aAAa,UAAU,CAAC;AACvC,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,aAAa;AAAA,MACb;AAAA,QACE,GAAG;AAAA,QACH,aAAa,oBAAoB,OAAO,WAAW;AAAA,QACnD,cAAc,oBAAoB,OAAO,YAAY;AAAA,QACrD,OAAO;AAAA,MACT;AAAA,OACC,OAAO,MAAe,UACrB,iBAAiB,MAAM,aAAa,QAAQ,MAAM,KAAK,CAAC;AAAA,IAC5D;AACA,WAAO,EAAE,cAAc,YAAY,mBAAmB,WAAW,WAAW;AAAA,EAC9E,CAAC;AAED,QAAM,sBAAsB,OAAO,OAAO;AAC1C,QAAM,oBAAoB,MAAM;AAC9B,0BAAsB;AACtB,UAAM,KAAK,gBAAgB,OAAO,OAAO,sBAAsB,CAAC;AAChE,QAAI,IAAI,WAAW,SAAS,kBAAkB,EAAG;AACjD,eAAW,YAAY,UAAW,UAAS,OAAO;AAClD,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,WAAW,SAAS,OAAO,GAAG;AACrC,aAAK,WAAW,OAAO,EAAE,OAAO,KAAK,kBAAkB,CAAC;AAAA,MAC1D,OAAO;AACL,aAAK,WAAW,OAAO;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACA,SAAO,OAAO,gBAAgB;AAE9B,SAAO;AAAA,IACL,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,QAAQ;AAAA,IAC5C,SAAS;AACP,iBAAW,YAAY,UAAW,UAAS,OAAO;AAClD,iBAAW,QAAQ,MAAO,MAAK,WAAW,OAAO;AACjD,UAAI,OAAO,OAAO,kBAAkB,mBAAmB;AACrD,eAAO,OAAO,gBAAgB;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AACF;AAQA,SAAS,uBAAuB,SAA+C;AAC7E,SAAO,IAAI;AAAA,IACT,EAAE,MAAM,QAAQ,MAAM,SAAS,QAAQ,QAAQ;AAAA,IAC/C,EAAE,cAAc,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,EAAE,EAAE;AAAA,EAC/C;AACF;AAGO,SAAS,mBAAmB,SAAyD;AAC1F,MAAI;AACJ,iBAAe,QAA4B;AACzC,UAAM,OAAO,uBAAuB,OAAO;AAC3C,UAAM,gBAAgB,MAAM,EAAE,OAAO,QAAQ,OAAO,OAAO,QAAQ,MAAM,CAAC;AAC1E,aAAS;AACT,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,MAAM,iBAAiB,gBAAgB;AACrC,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,CAAC,iBAAiB,eAAe,IAAI,kBAAkB,iBAAiB;AAC9E,YAAM,KAAK,QAAQ,eAAe;AAClC,YAAM,SAAS,IAAI;AAAA,QACjB,EAAE,MAAM,GAAG,QAAQ,IAAI,qBAAqB,SAAS,QAAQ,QAAQ;AAAA,QACpE,gBAAgB,MAAM,OAClB;AAAA,UACC,cAAc;AAAA,YACZ,YAAY,EAAE,CAAC,YAAY,GAAG,EAAE,WAAW,CAAC,kBAAkB,EAAE,EAAE;AAAA,UACpE;AAAA,QACF,IACA;AAAA,MACN;AACA,YAAM,OAAO,QAAQ,eAAe;AACpC,aAAO,EAAE,OAAO;AAAA,IAClB;AAAA,IACA,MAAM,OAAO,WAAW;AACtB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,KAAK,QAAQ,SAAS;AAAA,IAC9B;AAAA,IACA,MAAM,QAAQ;AACZ,YAAM,QAAQ,MAAM;AAAA,IACtB;AAAA,EACF;AACF;AAEA,eAAsB,WAAW,SAAkE;AACjG,QAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,2CAA2C;AACzF,QAAM,SAAS,mBAAmB,OAAO;AACzC,QAAM,OAAO,OAAO,IAAI,qBAAqB,CAAC;AAC9C,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * The Node entry: Views may be paths on disk. Runtimes without a filesystem\n * (Cloudflare Workers) resolve `mountly-mcp/server` to `./workers.js` instead,\n * through the `workerd` and `worker` export conditions.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { readMcpAppArtifact } from \"../artifact/index.js\";\nimport {\n createMcpAppServer,\n installDiskViewLoader,\n type CreateMcpAppServerOptions,\n type RunningMcpAppServer,\n} from \"./core.js\";\n\ninstallDiskViewLoader(async (supplied, uri) => {\n const artifact = await readMcpAppArtifact(\n typeof supplied === \"string\" ? supplied : supplied.htmlPath,\n uri ?? (typeof supplied === \"string\" ? undefined : supplied.uri),\n );\n if (typeof supplied !== \"string\" && supplied.name !== artifact.name) {\n throw new Error(\n `mountly-mcp: supplied artifact name '${supplied.name}' does not match file artifact name '${artifact.name}'`,\n );\n }\n return { artifact, html: await readFile(artifact.htmlPath, \"utf8\") };\n});\n\nexport {\n EXTENSION_ID,\n RESOURCE_MIME_TYPE,\n createMcpAppServer,\n registerMcpApps,\n type CreateMcpAppServerOptions,\n type McpAppToolConfig,\n type McpAppToolRegistration,\n type McpAppToolResult,\n type McpAppViewRegistration,\n type RegisterMcpAppsOptions,\n type RegisteredMcpApps,\n type RunningMcpAppServer,\n} from \"./core.js\";\n\nexport async function serveStdio(options: CreateMcpAppServerOptions): Promise<RunningMcpAppServer> {\n const { StdioServerTransport } = await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n const server = createMcpAppServer(options);\n await server.listen(new StdioServerTransport());\n return server;\n}\n"],"mappings":";;;;;;;;;;;;;AAKA,SAAS,gBAAgB;AASzB,sBAAsB,OAAO,UAAU,QAAQ;AAC7C,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO,aAAa,WAAW,WAAW,SAAS;AAAA,IACnD,QAAQ,OAAO,aAAa,WAAW,SAAY,SAAS;AAAA,EAC9D;AACA,MAAI,OAAO,aAAa,YAAY,SAAS,SAAS,SAAS,MAAM;AACnE,UAAM,IAAI;AAAA,MACR,wCAAwC,SAAS,IAAI,wCAAwC,SAAS,IAAI;AAAA,IAC5G;AAAA,EACF;AACA,SAAO,EAAE,UAAU,MAAM,MAAM,SAAS,SAAS,UAAU,MAAM,EAAE;AACrE,CAAC;AAiBD,eAAsB,WAAW,SAAkE;AACjG,QAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,2CAA2C;AACzF,QAAM,SAAS,mBAAmB,OAAO;AACzC,QAAM,OAAO,OAAO,IAAI,qBAAqB,CAAC;AAC9C,SAAO;AACT;","names":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `mountly-mcp/server` on a runtime with no filesystem — Cloudflare Workers,
3
+ * via the `workerd` and `worker` export conditions. Same API as the Node entry,
4
+ * except Views come from `mountly-mcp.views.js` rather than paths, and there is
5
+ * no `serveStdio`: pair it with the SDK's `WebStandardStreamableHTTPServerTransport`.
6
+ */
7
+ export { EXTENSION_ID, RESOURCE_MIME_TYPE, createMcpAppServer, registerMcpApps, type CreateMcpAppServerOptions, type McpAppToolConfig, type McpAppToolRegistration, type McpAppToolResult, type McpAppViewRegistration, type RegisterMcpAppsOptions, type RegisteredMcpApps, type RunningMcpAppServer, } from "./core.js";
@@ -0,0 +1,14 @@
1
+ import {
2
+ EXTENSION_ID,
3
+ RESOURCE_MIME_TYPE,
4
+ createMcpAppServer,
5
+ registerMcpApps
6
+ } from "../chunk-UMQ5OULD.js";
7
+ import "../chunk-6T5EIQGE.js";
8
+ export {
9
+ EXTENSION_ID,
10
+ RESOURCE_MIME_TYPE,
11
+ createMcpAppServer,
12
+ registerMcpApps
13
+ };
14
+ //# sourceMappingURL=workers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,9 +1,11 @@
1
1
  import {
2
- MCP_APP_MANIFEST_FILE,
3
- McpAppConformanceError,
4
2
  readMcpAppArtifact,
5
3
  readMcpAppManifest
6
- } from "../chunk-DKK26TRS.js";
4
+ } from "../chunk-RLDSMU5M.js";
5
+ import {
6
+ MCP_APP_MANIFEST_FILE,
7
+ McpAppConformanceError
8
+ } from "../chunk-6T5EIQGE.js";
7
9
 
8
10
  // src/testing/index.ts
9
11
  import { access, readFile } from "fs/promises";