mountly-mcp 4.3.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.
- package/README.md +89 -0
- package/dist/artifact/declaration.d.ts +61 -0
- package/dist/artifact/index.d.ts +2 -42
- package/dist/artifact/index.js +9 -5
- package/dist/chunk-6T5EIQGE.js +104 -0
- package/dist/chunk-6T5EIQGE.js.map +1 -0
- package/dist/chunk-BLT2MK32.js +35 -0
- package/dist/chunk-BLT2MK32.js.map +1 -0
- package/dist/{chunk-HIAIQVK5.js → chunk-QIA76O6M.js} +9 -1
- package/dist/chunk-QIA76O6M.js.map +1 -0
- package/dist/{chunk-DKK26TRS.js → chunk-RLDSMU5M.js} +9 -70
- package/dist/chunk-RLDSMU5M.js.map +1 -0
- package/dist/chunk-UMQ5OULD.js +243 -0
- package/dist/chunk-UMQ5OULD.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/dev/host-entry.js +23 -0
- package/dist/{doctor-4MTC6Y4X.js → doctor-OTOROLPI.js} +118 -9
- package/dist/doctor-OTOROLPI.js.map +1 -0
- package/dist/doctor.d.ts +4 -0
- package/dist/download.d.ts +17 -0
- package/dist/events/index.d.ts +97 -0
- package/dist/events/index.js +215 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -3
- package/dist/json-render/index.js +2 -1
- package/dist/json-render/index.js.map +1 -1
- package/dist/react/hooks.d.ts +7 -0
- package/dist/react/index.js +4 -1
- package/dist/server/core.d.ts +84 -0
- package/dist/server/index.d.ts +2 -72
- package/dist/server/index.js +19 -219
- package/dist/server/index.js.map +1 -1
- package/dist/server/workers.d.ts +7 -0
- package/dist/server/workers.js +14 -0
- package/dist/server/workers.js.map +1 -0
- package/dist/testing/index.js +5 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/vite/index.d.ts +15 -1
- package/dist/vite/index.js +133 -11
- package/dist/vite/index.js.map +1 -1
- package/dist/vue/index.d.ts +6 -0
- package/dist/vue/index.js +8 -0
- package/dist/vue/index.js.map +1 -1
- package/package.json +18 -6
- package/templates/react/README.md.tmpl +3 -0
- package/templates/react/package.json.tmpl +6 -3
- package/templates/svelte/README.md.tmpl +2 -0
- package/templates/svelte/package.json.tmpl +5 -3
- package/templates/svelte/src/env.d.ts.tmpl +10 -0
- package/templates/vanilla/README.md.tmpl +2 -0
- package/templates/vanilla/package.json.tmpl +5 -2
- package/templates/vue/README.md.tmpl +2 -0
- package/templates/vue/package.json.tmpl +6 -4
- package/templates/vue/src/env.d.ts.tmpl +10 -0
- package/dist/chunk-DKK26TRS.js.map +0 -1
- package/dist/chunk-HIAIQVK5.js.map +0 -1
- package/dist/doctor-4MTC6Y4X.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/artifact/index.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport {\n McpUiDisplayModeSchema,\n McpUiResourceMetaSchema,\n RESOURCE_MIME_TYPE,\n LATEST_PROTOCOL_VERSION,\n} from \"@modelcontextprotocol/ext-apps\";\nimport type { McpResourceDeclaration } from \"../types.js\";\n\nexport const MCP_APP_MANIFEST_VERSION = 1 as const;\nexport const MCP_APP_MANIFEST_FILE = \"mountly-mcp.manifest.json\";\n\nexport interface McpAppArtifact {\n /** Developer-facing unique key. */\n name: string;\n /** Protocol identity. */\n uri: string;\n /** Absolute path to the self-contained View HTML. */\n htmlPath: string;\n /** Absolute path to the transitional per-View sidecar. */\n metaPath: string;\n declaration: McpResourceDeclaration;\n}\n\nexport interface McpAppManifestEntry {\n name: string;\n uri: string;\n /** Path relative to the manifest, unless explicitly absolute. */\n html: string;\n /** Path relative to the manifest, unless explicitly absolute. */\n meta: string;\n declaration: McpResourceDeclaration;\n}\n\nexport interface McpAppManifest {\n formatVersion: typeof MCP_APP_MANIFEST_VERSION;\n protocolVersion: typeof LATEST_PROTOCOL_VERSION;\n apps: ReadonlyArray<McpAppManifestEntry>;\n}\n\nexport type ConformanceSeverity = \"error\" | \"warning\";\n\nexport interface ConformanceDiagnostic {\n severity: ConformanceSeverity;\n code: string;\n message: string;\n source?: string;\n}\n\nexport class McpAppConformanceError extends Error {\n readonly diagnostics: ReadonlyArray<ConformanceDiagnostic>;\n\n constructor(diagnostics: ReadonlyArray<ConformanceDiagnostic>) {\n super(diagnostics.map((d) => `${d.code}: ${d.message}`).join(\"\\n\"));\n this.name = \"McpAppConformanceError\";\n this.diagnostics = diagnostics;\n }\n}\n\nfunction object(value: unknown): Record<string, unknown> | undefined {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nexport function inspectMcpResourceDeclaration(\n value: unknown,\n source?: string,\n): ReadonlyArray<ConformanceDiagnostic> {\n const diagnostics: ConformanceDiagnostic[] = [];\n const add = (code: string, message: string): void => {\n diagnostics.push({ severity: \"error\", code, message, source });\n };\n const candidate = object(value);\n if (!candidate) {\n add(\"artifact/not-object\", \"resource declaration must be an object\");\n return diagnostics;\n }\n if (candidate.protocolVersion !== LATEST_PROTOCOL_VERSION) {\n add(\n \"artifact/protocol-version\",\n `sidecar protocolVersion must be '${LATEST_PROTOCOL_VERSION}' (received '${String(candidate.protocolVersion)}')`,\n );\n }\n if (typeof candidate.uri !== \"string\" || !candidate.uri.startsWith(\"ui://\")) {\n add(\"artifact/uri\", `uri must use the 'ui://' scheme (received '${String(candidate.uri)}')`);\n }\n if (typeof candidate.name !== \"string\" || candidate.name.trim() === \"\") {\n add(\"artifact/name\", \"name must be a non-empty string\");\n }\n if (candidate.mimeType !== RESOURCE_MIME_TYPE) {\n add(\n \"artifact/mime-type\",\n `sidecar mimeType must be '${RESOURCE_MIME_TYPE}' (received '${String(candidate.mimeType)}')`,\n );\n }\n if (typeof candidate.awaitToolResult !== \"boolean\") {\n add(\"artifact/await-tool-result\", \"awaitToolResult must be a boolean\");\n }\n if (\n !Array.isArray(candidate.displayModes) ||\n candidate.displayModes.length === 0 ||\n candidate.displayModes.some((mode) => !McpUiDisplayModeSchema.safeParse(mode).success)\n ) {\n add(\"artifact/display-modes\", \"displayModes must contain supported MCP Apps display modes\");\n }\n const meta = object(candidate._meta);\n const ui = meta && object(meta.ui);\n if (!ui || !McpUiResourceMetaSchema.safeParse(ui).success) {\n add(\"artifact/resource-meta\", \"_meta.ui must be valid MCP Apps resource metadata\");\n }\n return diagnostics;\n}\n\nexport function parseMcpResourceDeclaration(\n value: unknown,\n source?: string,\n): McpResourceDeclaration {\n const diagnostics = inspectMcpResourceDeclaration(value, source);\n if (diagnostics.length > 0) throw new McpAppConformanceError(diagnostics);\n return value as McpResourceDeclaration;\n}\n\nexport async function readMcpAppArtifact(\n htmlPath: string,\n expectedUri?: string,\n): Promise<McpAppArtifact> {\n const absoluteHtmlPath = resolve(htmlPath);\n const metaPath = `${absoluteHtmlPath}.meta.json`;\n const [html, raw] = await Promise.all([\n readFile(absoluteHtmlPath, \"utf8\"),\n readFile(metaPath, \"utf8\"),\n ]);\n if (!/^\\s*<!doctype html>/i.test(html)) {\n throw new McpAppConformanceError([\n {\n severity: \"error\",\n code: \"artifact/html5\",\n message: \"View HTML must start with an HTML5 doctype\",\n source: absoluteHtmlPath,\n },\n ]);\n }\n let decoded: unknown;\n try {\n decoded = JSON.parse(raw);\n } catch (error) {\n throw new McpAppConformanceError([\n {\n severity: \"error\",\n code: \"artifact/meta-json\",\n message: `metadata is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n source: metaPath,\n },\n ]);\n }\n const declaration = parseMcpResourceDeclaration(decoded, metaPath);\n if (expectedUri !== undefined && declaration.uri !== expectedUri) {\n throw new McpAppConformanceError([\n {\n severity: \"error\",\n code: \"artifact/uri-mismatch\",\n message: `registration uri '${expectedUri}' does not match sidecar uri '${declaration.uri}'`,\n source: metaPath,\n },\n ]);\n }\n return {\n name: declaration.name,\n uri: declaration.uri,\n htmlPath: absoluteHtmlPath,\n metaPath,\n declaration,\n };\n}\n\nfunction manifestPath(path: string, base: string): string {\n return isAbsolute(path) ? path : resolve(base, path);\n}\n\nexport async function writeMcpAppManifest(\n path: string,\n artifacts: ReadonlyArray<McpAppArtifact>,\n): Promise<McpAppManifest> {\n const absolutePath = resolve(path);\n const base = dirname(absolutePath);\n const names = new Set<string>();\n const uris = new Set<string>();\n for (const artifact of artifacts) {\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 }\n const manifest: McpAppManifest = {\n formatVersion: MCP_APP_MANIFEST_VERSION,\n protocolVersion: LATEST_PROTOCOL_VERSION,\n apps: artifacts.map((artifact) => ({\n name: artifact.name,\n uri: artifact.uri,\n html: relative(base, artifact.htmlPath),\n meta: relative(base, artifact.metaPath),\n declaration: artifact.declaration,\n })),\n };\n await writeFile(absolutePath, JSON.stringify(manifest, null, 2), \"utf8\");\n return manifest;\n}\n\nexport async function readMcpAppManifest(path: string): Promise<{\n path: string;\n manifest: McpAppManifest;\n artifacts: ReadonlyArray<McpAppArtifact>;\n}> {\n const absolutePath = resolve(path);\n const base = dirname(absolutePath);\n let decoded: unknown;\n try {\n decoded = JSON.parse(await readFile(absolutePath, \"utf8\"));\n } catch (error) {\n throw new Error(\n `mountly-mcp: could not read manifest '${absolutePath}': ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n const candidate = object(decoded);\n if (\n candidate?.formatVersion !== MCP_APP_MANIFEST_VERSION ||\n candidate.protocolVersion !== LATEST_PROTOCOL_VERSION ||\n !Array.isArray(candidate.apps)\n ) {\n throw new Error(\n `mountly-mcp: '${absolutePath}' is not a supported mountly-mcp manifest (expected formatVersion ${MCP_APP_MANIFEST_VERSION})`,\n );\n }\n const manifest = decoded as McpAppManifest;\n const names = new Set<string>();\n const uris = new Set<string>();\n const artifacts: McpAppArtifact[] = [];\n for (const entry of manifest.apps) {\n if (names.has(entry.name)) throw new Error(`mountly-mcp: duplicate app name '${entry.name}'`);\n if (uris.has(entry.uri)) throw new Error(`mountly-mcp: duplicate app uri '${entry.uri}'`);\n names.add(entry.name);\n uris.add(entry.uri);\n const declaration = parseMcpResourceDeclaration(entry.declaration, absolutePath);\n if (declaration.name !== entry.name || declaration.uri !== entry.uri) {\n throw new Error(\n `mountly-mcp: manifest identity does not match declaration for '${entry.name}'`,\n );\n }\n artifacts.push({\n name: entry.name,\n uri: entry.uri,\n htmlPath: manifestPath(entry.html, base),\n metaPath: manifestPath(entry.meta, base),\n declaration,\n });\n }\n return { path: absolutePath, manifest, artifacts };\n}\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AACpC,SAAS,SAAS,YAAY,UAAU,eAAe;AACvD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,IAAM,2BAA2B;AACjC,IAAM,wBAAwB;AAuC9B,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAGhD,YAAY,aAAmD;AAC7D,UAAM,YAAY,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAClE,SAAK,OAAO;AACZ,SAAK,cAAc;AAAA,EACrB;AACF;AAEA,SAAS,OAAO,OAAqD;AACnE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD;AACN;AAEO,SAAS,8BACd,OACA,QACsC;AACtC,QAAM,cAAuC,CAAC;AAC9C,QAAM,MAAM,CAAC,MAAc,YAA0B;AACnD,gBAAY,KAAK,EAAE,UAAU,SAAS,MAAM,SAAS,OAAO,CAAC;AAAA,EAC/D;AACA,QAAM,YAAY,OAAO,KAAK;AAC9B,MAAI,CAAC,WAAW;AACd,QAAI,uBAAuB,wCAAwC;AACnE,WAAO;AAAA,EACT;AACA,MAAI,UAAU,oBAAoB,yBAAyB;AACzD;AAAA,MACE;AAAA,MACA,oCAAoC,uBAAuB,gBAAgB,OAAO,UAAU,eAAe,CAAC;AAAA,IAC9G;AAAA,EACF;AACA,MAAI,OAAO,UAAU,QAAQ,YAAY,CAAC,UAAU,IAAI,WAAW,OAAO,GAAG;AAC3E,QAAI,gBAAgB,8CAA8C,OAAO,UAAU,GAAG,CAAC,IAAI;AAAA,EAC7F;AACA,MAAI,OAAO,UAAU,SAAS,YAAY,UAAU,KAAK,KAAK,MAAM,IAAI;AACtE,QAAI,iBAAiB,iCAAiC;AAAA,EACxD;AACA,MAAI,UAAU,aAAa,oBAAoB;AAC7C;AAAA,MACE;AAAA,MACA,6BAA6B,kBAAkB,gBAAgB,OAAO,UAAU,QAAQ,CAAC;AAAA,IAC3F;AAAA,EACF;AACA,MAAI,OAAO,UAAU,oBAAoB,WAAW;AAClD,QAAI,8BAA8B,mCAAmC;AAAA,EACvE;AACA,MACE,CAAC,MAAM,QAAQ,UAAU,YAAY,KACrC,UAAU,aAAa,WAAW,KAClC,UAAU,aAAa,KAAK,CAAC,SAAS,CAAC,uBAAuB,UAAU,IAAI,EAAE,OAAO,GACrF;AACA,QAAI,0BAA0B,4DAA4D;AAAA,EAC5F;AACA,QAAM,OAAO,OAAO,UAAU,KAAK;AACnC,QAAM,KAAK,QAAQ,OAAO,KAAK,EAAE;AACjC,MAAI,CAAC,MAAM,CAAC,wBAAwB,UAAU,EAAE,EAAE,SAAS;AACzD,QAAI,0BAA0B,mDAAmD;AAAA,EACnF;AACA,SAAO;AACT;AAEO,SAAS,4BACd,OACA,QACwB;AACxB,QAAM,cAAc,8BAA8B,OAAO,MAAM;AAC/D,MAAI,YAAY,SAAS,EAAG,OAAM,IAAI,uBAAuB,WAAW;AACxE,SAAO;AACT;AAEA,eAAsB,mBACpB,UACA,aACyB;AACzB,QAAM,mBAAmB,QAAQ,QAAQ;AACzC,QAAM,WAAW,GAAG,gBAAgB;AACpC,QAAM,CAAC,MAAM,GAAG,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpC,SAAS,kBAAkB,MAAM;AAAA,IACjC,SAAS,UAAU,MAAM;AAAA,EAC3B,CAAC;AACD,MAAI,CAAC,uBAAuB,KAAK,IAAI,GAAG;AACtC,UAAM,IAAI,uBAAuB;AAAA,MAC/B;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,GAAG;AAAA,EAC1B,SAAS,OAAO;AACd,UAAM,IAAI,uBAAuB;AAAA,MAC/B;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC9F,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,cAAc,4BAA4B,SAAS,QAAQ;AACjE,MAAI,gBAAgB,UAAa,YAAY,QAAQ,aAAa;AAChE,UAAM,IAAI,uBAAuB;AAAA,MAC/B;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS,qBAAqB,WAAW,iCAAiC,YAAY,GAAG;AAAA,QACzF,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL,MAAM,YAAY;AAAA,IAClB,KAAK,YAAY;AAAA,IACjB,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAc,MAAsB;AACxD,SAAO,WAAW,IAAI,IAAI,OAAO,QAAQ,MAAM,IAAI;AACrD;AAEA,eAAsB,oBACpB,MACA,WACyB;AACzB,QAAM,eAAe,QAAQ,IAAI;AACjC,QAAM,OAAO,QAAQ,YAAY;AACjC,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,YAAY,WAAW;AAChC,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;AAAA,EACvB;AACA,QAAM,WAA2B;AAAA,IAC/B,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,MAAM,UAAU,IAAI,CAAC,cAAc;AAAA,MACjC,MAAM,SAAS;AAAA,MACf,KAAK,SAAS;AAAA,MACd,MAAM,SAAS,MAAM,SAAS,QAAQ;AAAA,MACtC,MAAM,SAAS,MAAM,SAAS,QAAQ;AAAA,MACtC,aAAa,SAAS;AAAA,IACxB,EAAE;AAAA,EACJ;AACA,QAAM,UAAU,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,GAAG,MAAM;AACvE,SAAO;AACT;AAEA,eAAsB,mBAAmB,MAItC;AACD,QAAM,eAAe,QAAQ,IAAI;AACjC,QAAM,OAAO,QAAQ,YAAY;AACjC,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,MAAM,SAAS,cAAc,MAAM,CAAC;AAAA,EAC3D,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,yCAAyC,YAAY,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IACnH;AAAA,EACF;AACA,QAAM,YAAY,OAAO,OAAO;AAChC,MACE,WAAW,kBAAkB,4BAC7B,UAAU,oBAAoB,2BAC9B,CAAC,MAAM,QAAQ,UAAU,IAAI,GAC7B;AACA,UAAM,IAAI;AAAA,MACR,iBAAiB,YAAY,qEAAqE,wBAAwB;AAAA,IAC5H;AAAA,EACF;AACA,QAAM,WAAW;AACjB,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,YAA8B,CAAC;AACrC,aAAW,SAAS,SAAS,MAAM;AACjC,QAAI,MAAM,IAAI,MAAM,IAAI,EAAG,OAAM,IAAI,MAAM,oCAAoC,MAAM,IAAI,GAAG;AAC5F,QAAI,KAAK,IAAI,MAAM,GAAG,EAAG,OAAM,IAAI,MAAM,mCAAmC,MAAM,GAAG,GAAG;AACxF,UAAM,IAAI,MAAM,IAAI;AACpB,SAAK,IAAI,MAAM,GAAG;AAClB,UAAM,cAAc,4BAA4B,MAAM,aAAa,YAAY;AAC/E,QAAI,YAAY,SAAS,MAAM,QAAQ,YAAY,QAAQ,MAAM,KAAK;AACpE,YAAM,IAAI;AAAA,QACR,kEAAkE,MAAM,IAAI;AAAA,MAC9E;AAAA,IACF;AACA,cAAU,KAAK;AAAA,MACb,MAAM,MAAM;AAAA,MACZ,KAAK,MAAM;AAAA,MACX,UAAU,aAAa,MAAM,MAAM,IAAI;AAAA,MACvC,UAAU,aAAa,MAAM,MAAM,IAAI;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,EAAE,MAAM,cAAc,UAAU,UAAU;AACnD;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/hooks.ts","../src/react/create-view.ts"],"sourcesContent":["import { useContext } from \"react\";\nimport {\n useAutoResize as useAutoResizeBase,\n useDocumentTheme as useDocumentThemeBase,\n useHostFonts as useHostFontsBase,\n useHostStyleVariables as useHostStyleVariablesBase,\n useHostStyles as useHostStylesBase,\n} from \"@modelcontextprotocol/ext-apps/react\";\nimport type {\n App,\n McpUiDisplayMode,\n McpUiHostContext,\n McpUiUpdateModelContextRequest,\n} from \"@modelcontextprotocol/ext-apps\";\nimport { McpContext } from \"./context.js\";\n\nfunction useEnsuredContext() {\n const ctx = useContext(McpContext);\n if (!ctx) {\n throw new Error(\n \"mountly-mcp/react: useMcpApp/useToolInput/etc must be used inside a View wrapped with createMcpView().\",\n );\n }\n return ctx;\n}\n\n/** The view-side ext-apps App. Use this to call server tools, send messages, open links, etc. */\nexport function useMcpApp(): App {\n return useEnsuredContext().app;\n}\n\n/** Complete notification params; read the tool arguments from `.arguments`. */\nexport function useToolInput<T = unknown>(): T | undefined {\n return useEnsuredContext().toolInput as T | undefined;\n}\n\n/**\n * Streaming tool arguments (`ui/notifications/tool-input-partial`), present only\n * when the bridge runs with `streamToolInput`. Best-effort recovered JSON —\n * fields may be missing or change between notifications, so render loading\n * states from it, never critical operations. Undefined once the complete\n * {@link useToolInput} arrives.\n */\nexport function useToolInputPartial<T = unknown>(): Partial<T> | undefined {\n return useEnsuredContext().toolInputPartial as Partial<T> | undefined;\n}\n\n/** Complete MCP tool result; structured data is available at `.structuredContent`. */\nexport function useToolResult<T = unknown>(): T | undefined {\n return useEnsuredContext().toolResult as T | undefined;\n}\n\n/** Latest host context snapshot (theme, styles, displayMode, container dimensions, etc.). */\nexport function useHostContext(): McpUiHostContext | undefined {\n return useEnsuredContext().hostContext;\n}\n\n/** Current display mode reported by the host. */\nexport function useDisplayMode(): McpUiDisplayMode | undefined {\n return useHostContext()?.displayMode;\n}\n\n/**\n * Request a display mode change, resolving to the mode the host actually\n * applied — which the spec allows to differ from the one asked for.\n *\n * Modes the host didn't list in `availableDisplayModes` are never requested\n * (the spec requires views to check first); the current mode comes back\n * unchanged instead.\n */\nexport function useRequestDisplayMode(): (\n mode: McpUiDisplayMode,\n) => Promise<McpUiDisplayMode | undefined> {\n const { app, hostContext } = useEnsuredContext();\n return async (mode) => {\n const available = hostContext?.availableDisplayModes;\n if (available && !available.includes(mode)) return hostContext?.displayMode;\n const result = await app.requestDisplayMode({ mode });\n return result.mode;\n };\n}\n\n/** Apply host CSS variables (and react to host-context changes). */\nexport function useHostStyleVariables(): void {\n const { app, hostContext } = useEnsuredContext();\n useHostStyleVariablesBase(app, hostContext ?? null);\n}\n\n/** Apply host-provided `@font-face`/`@import` rules. */\nexport function useHostFonts(): void {\n const { app, hostContext } = useEnsuredContext();\n useHostFontsBase(app, hostContext ?? null);\n}\n\n/** One-shot helper: apply both host style variables and host fonts. */\nexport function useHostStyles(): void {\n const { app, hostContext } = useEnsuredContext();\n useHostStylesBase(app, hostContext ?? null);\n}\n\n/** Track the document theme reactively. */\nexport function useDocumentTheme() {\n return useDocumentThemeBase();\n}\n\n/**\n * Return a function that calls `app.updateModelContext(params)`.\n *\n * Context updates are available to the model in future turns without\n * triggering an immediate response. Only the last update is kept.\n */\nexport function useUpdateModelContext(): (\n params: McpUiUpdateModelContextRequest[\"params\"],\n) => Promise<void> {\n const { app } = useEnsuredContext();\n return async (params) => {\n await app.updateModelContext(params);\n };\n}\n\n/** Manually control auto-resize (rarely needed — the bridge calls setupSizeChangedNotifications by default). */\nexport function useAutoResize(...args: Parameters<typeof useAutoResizeBase>) {\n return useAutoResizeBase(...args);\n}\n","/**\n * Wraps a React component as an MCP Apps View and publishes it for the bridge.\n * One call is enough — no manual global assign.\n */\nimport { createElement, type ComponentType } from \"react\";\nimport { createWidget } from \"mountly-react\";\nimport type { AdapterOptions } from \"mountly/adapter\";\nimport type { McpView, McpViewProps } from \"../types.js\";\nimport { publishMcpView } from \"../publish.js\";\nimport { McpContext, type McpContextValue } from \"./context.js\";\n\nexport function createMcpView<P extends object>(\n Component: ComponentType<P>,\n options?: AdapterOptions,\n): McpView {\n const Wrapped = (props: P & McpViewProps) => {\n const { mcp, toolInput, toolInputPartial, toolResult, hostContext, ...rest } =\n props as McpViewProps & P;\n const value: McpContextValue = {\n app: mcp,\n toolInput,\n toolInputPartial,\n toolResult,\n hostContext,\n };\n return createElement(\n McpContext.Provider,\n { value },\n createElement(Component as ComponentType, rest as P),\n );\n };\n return publishMcpView(createWidget(Wrapped as ComponentType<P & McpViewProps>, options));\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,kBAAkB;AAC3B;AAAA,EACE,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,OACZ;AASP,SAAS,oBAAoB;AAC3B,QAAM,MAAM,WAAW,UAAU;AACjC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,YAAiB;AAC/B,SAAO,kBAAkB,EAAE;AAC7B;AAGO,SAAS,eAA2C;AACzD,SAAO,kBAAkB,EAAE;AAC7B;AASO,SAAS,sBAA2D;AACzE,SAAO,kBAAkB,EAAE;AAC7B;AAGO,SAAS,gBAA4C;AAC1D,SAAO,kBAAkB,EAAE;AAC7B;AAGO,SAAS,iBAA+C;AAC7D,SAAO,kBAAkB,EAAE;AAC7B;AAGO,SAAS,iBAA+C;AAC7D,SAAO,eAAe,GAAG;AAC3B;AAUO,SAAS,wBAE2B;AACzC,QAAM,EAAE,KAAK,YAAY,IAAI,kBAAkB;AAC/C,SAAO,OAAO,SAAS;AACrB,UAAM,YAAY,aAAa;AAC/B,QAAI,aAAa,CAAC,UAAU,SAAS,IAAI,EAAG,QAAO,aAAa;AAChE,UAAM,SAAS,MAAM,IAAI,mBAAmB,EAAE,KAAK,CAAC;AACpD,WAAO,OAAO;AAAA,EAChB;AACF;AAGO,SAAS,wBAA8B;AAC5C,QAAM,EAAE,KAAK,YAAY,IAAI,kBAAkB;AAC/C,4BAA0B,KAAK,eAAe,IAAI;AACpD;AAGO,SAAS,eAAqB;AACnC,QAAM,EAAE,KAAK,YAAY,IAAI,kBAAkB;AAC/C,mBAAiB,KAAK,eAAe,IAAI;AAC3C;AAGO,SAAS,gBAAsB;AACpC,QAAM,EAAE,KAAK,YAAY,IAAI,kBAAkB;AAC/C,oBAAkB,KAAK,eAAe,IAAI;AAC5C;AAGO,SAAS,mBAAmB;AACjC,SAAO,qBAAqB;AAC9B;AAQO,SAAS,wBAEG;AACjB,QAAM,EAAE,IAAI,IAAI,kBAAkB;AAClC,SAAO,OAAO,WAAW;AACvB,UAAM,IAAI,mBAAmB,MAAM;AAAA,EACrC;AACF;AAGO,SAAS,iBAAiB,MAA4C;AAC3E,SAAO,kBAAkB,GAAG,IAAI;AAClC;;;ACvHA,SAAS,qBAAyC;AAClD,SAAS,oBAAoB;AAMtB,SAAS,cACd,WACA,SACS;AACT,QAAM,UAAU,CAAC,UAA4B;AAC3C,UAAM,EAAE,KAAK,WAAW,kBAAkB,YAAY,aAAa,GAAG,KAAK,IACzE;AACF,UAAM,QAAyB;AAAA,MAC7B,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,MACL,WAAW;AAAA,MACX,EAAE,MAAM;AAAA,MACR,cAAc,WAA4B,IAAS;AAAA,IACrD;AAAA,EACF;AACA,SAAO,eAAe,aAAa,SAA4C,OAAO,CAAC;AACzF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/doctor.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join, resolve } from \"node:path\";\nimport { CLI_ERROR_CODES, cliError } from \"./errors.js\";\n\nexport interface DoctorCheck {\n id: string;\n ok: boolean;\n detail: string;\n}\n\nexport interface DoctorReport {\n ok: boolean;\n checks: DoctorCheck[];\n}\n\nfunction nodeMajor(): number {\n return Number(process.versions.node.split(\".\")[0] ?? 0);\n}\n\nfunction tryResolve(specifier: string, fromDir: string): string | null {\n try {\n const require = createRequire(resolve(fromDir, \"package.json\"));\n return require.resolve(specifier);\n } catch {\n return null;\n }\n}\n\nconst OPENAI_USAGE =\n /openai\\/ui|useOpenAIExtensions|mountly-mcp\\/openai|mountly-mcp\\/react\\/openai|@openai\\/mcp-extensions|openaiUi\\b|openaiUiToolMeta|enableOpenAiExtensions/;\n\nfunction projectSourcesMentionOpenAi(cwd: string, viteConfig?: string): boolean {\n const candidates: string[] = [];\n if (viteConfig) candidates.push(viteConfig);\n for (const name of [\"server.ts\", \"server.mjs\", \"server.js\", \"src/server.ts\", \"src/view.tsx\"]) {\n const path = resolve(cwd, name);\n if (existsSync(path)) candidates.push(path);\n }\n const srcDir = resolve(cwd, \"src\");\n if (existsSync(srcDir)) {\n try {\n for (const entry of readdirSync(srcDir, { withFileTypes: true })) {\n if (entry.isFile() && /\\.(tsx?|jsx?|mjs|cjs)$/.test(entry.name)) {\n candidates.push(join(srcDir, entry.name));\n }\n }\n } catch {\n // ignore unreadable src\n }\n }\n for (const path of candidates) {\n try {\n if (OPENAI_USAGE.test(readFileSync(path, \"utf8\"))) return true;\n } catch {\n // skip\n }\n }\n return false;\n}\n\n/**\n * Check the local project for Mountly MCP readiness. Exits nonzero via the\n * CLI when `ok` is false.\n */\nexport function runDoctor(cwd = process.cwd()): DoctorReport {\n const checks: DoctorCheck[] = [];\n\n const major = nodeMajor();\n checks.push({\n id: \"node\",\n ok: major >= 20,\n detail:\n major >= 20\n ? `Node ${process.versions.node} (ok; 20+ required, 22+ recommended)`\n : `Node ${process.versions.node} is below 20. Upgrade Node, then re-run mountly-mcp doctor.`,\n });\n\n const viteConfigCandidates = [\n \"vite.config.ts\",\n \"vite.config.mts\",\n \"vite.config.js\",\n \"vite.config.mjs\",\n ].map((name) => resolve(cwd, name));\n const viteConfig = viteConfigCandidates.find((path) => existsSync(path));\n checks.push({\n id: \"vite-config\",\n ok: Boolean(viteConfig),\n detail: viteConfig\n ? `Found ${viteConfig}`\n : \"No vite.config.* in this directory. Run from the View project, or: npx mountly-mcp create my-app --framework react\",\n });\n\n if (viteConfig) {\n const source = readFileSync(viteConfig, \"utf8\");\n const hasPlugin = /mountlyMcpViews\\s*\\(/.test(source);\n checks.push({\n id: \"vite-plugin\",\n ok: hasPlugin,\n detail: hasPlugin\n ? \"vite config imports mountlyMcpViews()\"\n : `Add mountlyMcpViews() from \"mountly-mcp/vite\" to ${viteConfig}`,\n });\n }\n\n const manifest = resolve(cwd, \"dist/mountly-mcp.manifest.json\");\n checks.push({\n id: \"manifest\",\n ok: existsSync(manifest),\n detail: existsSync(manifest)\n ? `Found ${manifest}`\n : \"No dist/mountly-mcp.manifest.json yet. Run: npx mountly-mcp build\",\n });\n\n const playwright = tryResolve(\"playwright\", cwd) ?? tryResolve(\"@playwright/test\", cwd);\n checks.push({\n id: \"playwright\",\n ok: Boolean(playwright),\n detail: playwright\n ? `Playwright resolvable for verify --render (${playwright})`\n : \"Playwright not installed. For CI render checks: pnpm add -D playwright && npx playwright install chromium\",\n });\n\n const pkgPath = resolve(cwd, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.react) {\n const reactPath = tryResolve(\"react/package.json\", cwd);\n if (reactPath) {\n const reactPkg = JSON.parse(readFileSync(reactPath, \"utf8\")) as { version?: string };\n const reactMajor = Number((reactPkg.version ?? \"0\").split(\".\")[0]);\n checks.push({\n id: \"react\",\n ok: reactMajor >= 19,\n detail:\n reactMajor >= 19\n ? `React ${reactPkg.version} (ok)`\n : `React ${reactPkg.version} is below 19. mountly-mcp/react and mountly-react require React 19.`,\n });\n }\n }\n if (deps.vite) {\n const vitePath = tryResolve(\"vite/package.json\", cwd);\n if (vitePath) {\n const vitePkg = JSON.parse(readFileSync(vitePath, \"utf8\")) as { version?: string };\n const viteMajor = Number((vitePkg.version ?? \"0\").split(\".\")[0]);\n checks.push({\n id: \"vite\",\n ok: viteMajor >= 8,\n detail:\n viteMajor >= 8\n ? `Vite ${vitePkg.version} (ok)`\n : `Vite ${vitePkg.version} is below 8. mountly-mcp/vite is built and tested against Vite 8.`,\n });\n }\n }\n }\n\n if (projectSourcesMentionOpenAi(cwd, viteConfig)) {\n const openai = tryResolve(\"@openai/mcp-extensions/package.json\", cwd);\n checks.push({\n id: \"openai-extensions\",\n ok: Boolean(openai),\n detail: openai\n ? `@openai/mcp-extensions resolvable (${openai})`\n : 'Project references OpenAI MCP extensions but @openai/mcp-extensions is not installed. Run: pnpm add @openai/mcp-extensions',\n });\n }\n\n // Manifest missing is advisory for a brand-new scaffold before first build.\n const hard = checks.filter((c) => c.id !== \"manifest\" && c.id !== \"playwright\");\n const ok = hard.every((c) => c.ok);\n\n return { ok, checks };\n}\n\nexport function formatDoctorReport(report: DoctorReport): string {\n const lines = [\"mountly-mcp doctor\", \"\"];\n for (const check of report.checks) {\n lines.push(`${check.ok ? \"ok\" : \"FAIL\"} ${check.id.padEnd(14)} ${check.detail}`);\n }\n lines.push(\"\");\n lines.push(report.ok ? \"Ready for mountly-mcp build / dev / verify.\" : \"Fix FAIL items above.\");\n lines.push(\"\");\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function doctorCommand(cwd = process.cwd()): void {\n const report = runDoctor(cwd);\n process.stdout.write(formatDoctorReport(report));\n if (!report.ok) {\n throw cliError(\n CLI_ERROR_CODES.DOCTOR_FAILED,\n \"one or more doctor checks failed\",\n \"Fix the FAIL lines above, then re-run: mountly-mcp doctor\",\n );\n }\n}\n"],"mappings":"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","names":["require"]}
|