@maravilla-labs/platform 0.11.1 → 0.12.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/CHANGELOG.md +26 -0
- package/dist/mcp.d.ts +23 -16
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/src/mcp.ts +22 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @maravilla-labs/platform
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- da70d05: MCP UI widgets are now **auto-built** by the platform — no second Vite config, no
|
|
8
|
+
`build:mcp-ui` script, no `@source`, no manual `static/` output.
|
|
9
|
+
|
|
10
|
+
Drop your widget source in `mcp-ui/<name>/` (or `src/mcp-ui/<name>/`) — an
|
|
11
|
+
`index.html` + your component + `app.css` (`@import 'tailwindcss';`) — and declare
|
|
12
|
+
`uiTemplates: [{ name }]` (no `htmlPath`). During the build the platform resolves
|
|
13
|
+
your framework's Vite plugin (Svelte/React/Vue) + Tailwind from your project, runs
|
|
14
|
+
`vite-plugin-singlefile`, and emits a self-contained `static/mcp-ui/<name>.html`
|
|
15
|
+
registered for deploy. Tailwind scans the whole project (the build is rooted there),
|
|
16
|
+
so shared components style correctly without `@source`.
|
|
17
|
+
- `functions`: new `buildMcpWidgets` (in `buildMcp`); `BuildMcpOptions` gains
|
|
18
|
+
`framework` + `staticDir`; widget toolchain resolved from the tenant; new
|
|
19
|
+
`vite-plugin-singlefile` dependency. Falls back to detecting the framework from
|
|
20
|
+
`package.json` when the adapter doesn't pass one.
|
|
21
|
+
- `platform`: `uiTemplates[].htmlPath` is now **optional**; added `entry?` to point
|
|
22
|
+
at a non-conventional source. `htmlPath` remains as a legacy pre-built escape hatch.
|
|
23
|
+
- `adapter-core` / `adapter-sveltekit` / `adapter-react-router`: `buildAndIntegrateMcp`
|
|
24
|
+
forwards the framework id + static dir so widgets build with the right toolchain.
|
|
25
|
+
|
|
26
|
+
Back-compat: apps that still point `htmlPath` at a pre-built widget under `static/`
|
|
27
|
+
keep working unchanged. The runtime is unchanged.
|
|
28
|
+
|
|
3
29
|
## 0.11.1
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/dist/mcp.d.ts
CHANGED
|
@@ -149,26 +149,33 @@ interface McpServerSpec {
|
|
|
149
149
|
*/
|
|
150
150
|
public?: boolean;
|
|
151
151
|
/**
|
|
152
|
-
* Mini-app UI templates referenced by tools via `ui.template`. Each
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* (`text/html;profile=mcp-app`), which the host (Claude, ChatGPT) renders inline
|
|
160
|
-
* — the MCP Apps standard. The widget receives its data over the MCP Apps
|
|
161
|
-
* channel (`@modelcontextprotocol/ext-apps`, `ontoolresult` →
|
|
162
|
-
* `structuredContent`), not via cookies.
|
|
152
|
+
* Mini-app UI templates referenced by tools via `ui.template`. Each renders a
|
|
153
|
+
* tool result as a **self-contained single-file HTML widget** the runtime
|
|
154
|
+
* serves inline as the `ui://<tool>/<template>` resource
|
|
155
|
+
* (`text/html;profile=mcp-app`) — the MCP Apps standard — which the host
|
|
156
|
+
* (Claude, ChatGPT) renders in a sandboxed iframe. The widget receives its
|
|
157
|
+
* data over the MCP Apps channel (`@modelcontextprotocol/ext-apps`,
|
|
158
|
+
* `ontoolresult` → `structuredContent`), not via cookies.
|
|
163
159
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
160
|
+
* **The build is automatic.** Put the widget *source* in `mcp-ui/<name>/`
|
|
161
|
+
* (or `src/mcp-ui/<name>/`) — `index.html` + your component + `app.css` with
|
|
162
|
+
* `@import 'tailwindcss';` — and the platform compiles it to a single inlined
|
|
163
|
+
* file during `maravilla build` (framework plugin + Tailwind + singlefile, all
|
|
164
|
+
* resolved for you). No second Vite config, no build script, no `@source`. See
|
|
165
|
+
* the `mcp-ui-mini-app` recipe.
|
|
166
|
+
*
|
|
167
|
+
* - `entry` — override the source location (a dir or an `index.html`); defaults
|
|
168
|
+
* to the `mcp-ui/<name>/` convention.
|
|
169
|
+
* - `htmlPath` — *legacy* escape hatch: point at a pre-built single-file under
|
|
170
|
+
* `static/` you build yourself. Prefer the convention.
|
|
171
|
+
* - `csp` — the resource's Content-Security-Policy ({@link McpUiResourceCsp},
|
|
172
|
+
* emitted at `_meta.ui.csp`): external origins the widget may load (e.g.
|
|
173
|
+
* `resourceDomains` for remote images). Omit for a self-contained widget.
|
|
168
174
|
*/
|
|
169
175
|
uiTemplates?: Array<{
|
|
170
176
|
name: string;
|
|
171
|
-
|
|
177
|
+
entry?: string;
|
|
178
|
+
htmlPath?: string;
|
|
172
179
|
csp?: McpUiResourceCsp;
|
|
173
180
|
}>;
|
|
174
181
|
}
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["/**\n * @fileoverview MCP tool authoring helpers for Maravilla.\n *\n * User apps declare MCP tools in `mcp.ts` or `mcp/*.ts`:\n *\n * ```ts\n * import { defineMcpTool, defineMcpServer } from '@maravilla-labs/platform/mcp';\n *\n * export const server = defineMcpServer({\n * name: 'Acme Tools',\n * version: '1.0.0',\n * instructions: 'Tools for managing Acme orders.',\n * uiTemplates: [{ name: 'order-card', route: '/_mcp/ui/order-card' }],\n * });\n *\n * export const getOrder = defineMcpTool(\n * {\n * name: 'get_order',\n * description: 'Look up an order by id.',\n * inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },\n * scopes: ['acme:read'],\n * ui: { template: 'order-card' },\n * },\n * async (args, ctx) => {\n * const order = await ctx.database.findOne('orders', { _id: args.id });\n * return { content: [{ type: 'text', text: JSON.stringify(order) }] };\n * },\n * );\n * ```\n *\n * These helpers are pure factories. `defineMcpTool` produces a\n * `RegisteredMcpTool` marker object that the build pipeline\n * (`@maravilla-labs/functions` `buildMcp`) detects by its `__maravilla_mcp`\n * property; `defineMcpServer` produces a `RegisteredMcpServer` detected by\n * `__maravilla_mcp_server`. The generated bundle exposes\n * `globalThis.handleMcpTool(toolId, args, ctx)`; the Rust MCP dispatcher\n * (`crates/platform/src/mcp/dispatch.rs`) drives it via a synthetic request\n * whose body is `{ tool_id, args, identity }`.\n */\n\n// ============ Tool handler context ============\n\n/**\n * Context handed to every MCP tool handler. The first seven services mirror\n * the events `EventCtx` (and `globalThis.platform`) exactly. `user`/`client`\n * carry the authenticated identity behind the OAuth token or API key so the\n * handler — and the platform ops it calls — run as the real end-user.\n */\nexport interface McpToolContext {\n /** Per-tenant env vars. */\n env: Record<string, string>;\n /** KV store — same shape as `getPlatform().env.KV` / `platform.kv`. */\n kv?: unknown;\n /** MongoDB-style database — same shape as `getPlatform().env.DB`. */\n database?: unknown;\n /** Object storage. */\n storage?: unknown;\n /** Durable queue producer (`.send(name, payload, opts?)`). */\n queue?: { send: (name: string, payload: unknown, opts?: unknown) => Promise<string> };\n /** Auth service — register/login/logout/user CRUD/etc. */\n auth?: unknown;\n /** Web Push service. */\n push?: unknown;\n /** Full platform object — escape hatch for services not surfaced above. */\n platform?: unknown;\n /** Tenant identifier. */\n tenant: string;\n /** Trace correlation id — propagate through logs. */\n traceId: string;\n /** The end-user behind the token/key, or `null` for a client-only call. */\n user: { id: string; email: string; groups: string[]; scopes: string[] } | null;\n /** The OAuth client (agent) that authenticated, when known. */\n client: { id: string } | null;\n}\n\n// ============ Tool result shapes ============\n\n/** A single content item returned by a tool. */\nexport type McpContentItem =\n | { type: 'text'; text: string }\n | { type: 'json'; json: unknown }\n | { type: 'resource'; resource: Record<string, unknown> };\n\n/**\n * What a tool handler may return:\n * - `{ content }` — explicit MCP content items.\n * - `{ ui }` — render an iframe mini-app template (§7); optional `content`\n * is shown alongside for clients that don't support the UI.\n * - any other value — wrapped as a single `text` content item.\n */\nexport type McpToolResult =\n | { content: McpContentItem[] }\n | { ui: { template: string; data?: unknown }; content?: McpContentItem[] }\n | unknown;\n\n// ============ Registered markers ============\n\nexport const MCP_TOOL_SYMBOL = '__maravilla_mcp' as const;\nexport const MCP_SERVER_SYMBOL = '__maravilla_mcp_server' as const;\n\n/** Spec passed to {@link defineMcpTool}. */\nexport interface McpToolSpec {\n /** Tool name surfaced to the client (defaults to the export name). */\n name: string;\n /** Human-readable description sent in `tools/list`. */\n description: string;\n /** JSON Schema for the tool input, sent verbatim in `tools/list`. */\n inputSchema: Record<string, unknown>;\n /** Required scopes; dispatch enforces `scopes ⊆ identity.scopes`. */\n scopes?: string[];\n /**\n * Per-tool public opt-in. When `true`, this tool is callable with an\n * anonymous identity (no bearer) even on an otherwise-private server — its\n * `scopes` must still be a subset of the caller's, so an anonymous caller can\n * only reach it when it declares no scopes. Defaults to `false`.\n */\n public?: boolean;\n /** Links this tool to a UI template declared on the server (§7). */\n ui?: { template: string };\n}\n\nexport interface RegisteredMcpTool {\n readonly [MCP_TOOL_SYMBOL]: McpToolSpec;\n readonly handler: (args: any, ctx: McpToolContext) => McpToolResult | Promise<McpToolResult>;\n}\n\n/** Spec passed to {@link defineMcpServer}. */\nexport interface McpServerSpec {\n /** Human-readable server name (e.g. \"Acme Tools\"). */\n name: string;\n /** Optional semantic version. */\n version?: string;\n /** Optional natural-language usage instructions for the client/model. */\n instructions?: string;\n /**\n * Server-level public flag. When `true`, unauthenticated MCP requests build\n * an anonymous identity (instead of a 401) so `initialize` / `tools/list` and\n * any no-scope tool work without a bearer. Per-tool `public` opt-in still\n * works on an otherwise-private server. Defaults to `false`.\n */\n public?: boolean;\n /**\n * Mini-app UI templates referenced by tools via `ui.template`. Each
|
|
1
|
+
{"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["/**\n * @fileoverview MCP tool authoring helpers for Maravilla.\n *\n * User apps declare MCP tools in `mcp.ts` or `mcp/*.ts`:\n *\n * ```ts\n * import { defineMcpTool, defineMcpServer } from '@maravilla-labs/platform/mcp';\n *\n * export const server = defineMcpServer({\n * name: 'Acme Tools',\n * version: '1.0.0',\n * instructions: 'Tools for managing Acme orders.',\n * uiTemplates: [{ name: 'order-card', route: '/_mcp/ui/order-card' }],\n * });\n *\n * export const getOrder = defineMcpTool(\n * {\n * name: 'get_order',\n * description: 'Look up an order by id.',\n * inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },\n * scopes: ['acme:read'],\n * ui: { template: 'order-card' },\n * },\n * async (args, ctx) => {\n * const order = await ctx.database.findOne('orders', { _id: args.id });\n * return { content: [{ type: 'text', text: JSON.stringify(order) }] };\n * },\n * );\n * ```\n *\n * These helpers are pure factories. `defineMcpTool` produces a\n * `RegisteredMcpTool` marker object that the build pipeline\n * (`@maravilla-labs/functions` `buildMcp`) detects by its `__maravilla_mcp`\n * property; `defineMcpServer` produces a `RegisteredMcpServer` detected by\n * `__maravilla_mcp_server`. The generated bundle exposes\n * `globalThis.handleMcpTool(toolId, args, ctx)`; the Rust MCP dispatcher\n * (`crates/platform/src/mcp/dispatch.rs`) drives it via a synthetic request\n * whose body is `{ tool_id, args, identity }`.\n */\n\n// ============ Tool handler context ============\n\n/**\n * Context handed to every MCP tool handler. The first seven services mirror\n * the events `EventCtx` (and `globalThis.platform`) exactly. `user`/`client`\n * carry the authenticated identity behind the OAuth token or API key so the\n * handler — and the platform ops it calls — run as the real end-user.\n */\nexport interface McpToolContext {\n /** Per-tenant env vars. */\n env: Record<string, string>;\n /** KV store — same shape as `getPlatform().env.KV` / `platform.kv`. */\n kv?: unknown;\n /** MongoDB-style database — same shape as `getPlatform().env.DB`. */\n database?: unknown;\n /** Object storage. */\n storage?: unknown;\n /** Durable queue producer (`.send(name, payload, opts?)`). */\n queue?: { send: (name: string, payload: unknown, opts?: unknown) => Promise<string> };\n /** Auth service — register/login/logout/user CRUD/etc. */\n auth?: unknown;\n /** Web Push service. */\n push?: unknown;\n /** Full platform object — escape hatch for services not surfaced above. */\n platform?: unknown;\n /** Tenant identifier. */\n tenant: string;\n /** Trace correlation id — propagate through logs. */\n traceId: string;\n /** The end-user behind the token/key, or `null` for a client-only call. */\n user: { id: string; email: string; groups: string[]; scopes: string[] } | null;\n /** The OAuth client (agent) that authenticated, when known. */\n client: { id: string } | null;\n}\n\n// ============ Tool result shapes ============\n\n/** A single content item returned by a tool. */\nexport type McpContentItem =\n | { type: 'text'; text: string }\n | { type: 'json'; json: unknown }\n | { type: 'resource'; resource: Record<string, unknown> };\n\n/**\n * What a tool handler may return:\n * - `{ content }` — explicit MCP content items.\n * - `{ ui }` — render an iframe mini-app template (§7); optional `content`\n * is shown alongside for clients that don't support the UI.\n * - any other value — wrapped as a single `text` content item.\n */\nexport type McpToolResult =\n | { content: McpContentItem[] }\n | { ui: { template: string; data?: unknown }; content?: McpContentItem[] }\n | unknown;\n\n// ============ Registered markers ============\n\nexport const MCP_TOOL_SYMBOL = '__maravilla_mcp' as const;\nexport const MCP_SERVER_SYMBOL = '__maravilla_mcp_server' as const;\n\n/** Spec passed to {@link defineMcpTool}. */\nexport interface McpToolSpec {\n /** Tool name surfaced to the client (defaults to the export name). */\n name: string;\n /** Human-readable description sent in `tools/list`. */\n description: string;\n /** JSON Schema for the tool input, sent verbatim in `tools/list`. */\n inputSchema: Record<string, unknown>;\n /** Required scopes; dispatch enforces `scopes ⊆ identity.scopes`. */\n scopes?: string[];\n /**\n * Per-tool public opt-in. When `true`, this tool is callable with an\n * anonymous identity (no bearer) even on an otherwise-private server — its\n * `scopes` must still be a subset of the caller's, so an anonymous caller can\n * only reach it when it declares no scopes. Defaults to `false`.\n */\n public?: boolean;\n /** Links this tool to a UI template declared on the server (§7). */\n ui?: { template: string };\n}\n\nexport interface RegisteredMcpTool {\n readonly [MCP_TOOL_SYMBOL]: McpToolSpec;\n readonly handler: (args: any, ctx: McpToolContext) => McpToolResult | Promise<McpToolResult>;\n}\n\n/** Spec passed to {@link defineMcpServer}. */\nexport interface McpServerSpec {\n /** Human-readable server name (e.g. \"Acme Tools\"). */\n name: string;\n /** Optional semantic version. */\n version?: string;\n /** Optional natural-language usage instructions for the client/model. */\n instructions?: string;\n /**\n * Server-level public flag. When `true`, unauthenticated MCP requests build\n * an anonymous identity (instead of a 401) so `initialize` / `tools/list` and\n * any no-scope tool work without a bearer. Per-tool `public` opt-in still\n * works on an otherwise-private server. Defaults to `false`.\n */\n public?: boolean;\n /**\n * Mini-app UI templates referenced by tools via `ui.template`. Each renders a\n * tool result as a **self-contained single-file HTML widget** the runtime\n * serves inline as the `ui://<tool>/<template>` resource\n * (`text/html;profile=mcp-app`) — the MCP Apps standard — which the host\n * (Claude, ChatGPT) renders in a sandboxed iframe. The widget receives its\n * data over the MCP Apps channel (`@modelcontextprotocol/ext-apps`,\n * `ontoolresult` → `structuredContent`), not via cookies.\n *\n * **The build is automatic.** Put the widget *source* in `mcp-ui/<name>/`\n * (or `src/mcp-ui/<name>/`) — `index.html` + your component + `app.css` with\n * `@import 'tailwindcss';` — and the platform compiles it to a single inlined\n * file during `maravilla build` (framework plugin + Tailwind + singlefile, all\n * resolved for you). No second Vite config, no build script, no `@source`. See\n * the `mcp-ui-mini-app` recipe.\n *\n * - `entry` — override the source location (a dir or an `index.html`); defaults\n * to the `mcp-ui/<name>/` convention.\n * - `htmlPath` — *legacy* escape hatch: point at a pre-built single-file under\n * `static/` you build yourself. Prefer the convention.\n * - `csp` — the resource's Content-Security-Policy ({@link McpUiResourceCsp},\n * emitted at `_meta.ui.csp`): external origins the widget may load (e.g.\n * `resourceDomains` for remote images). Omit for a self-contained widget.\n */\n uiTemplates?: Array<{ name: string; entry?: string; htmlPath?: string; csp?: McpUiResourceCsp }>;\n}\n\n/**\n * Content-Security-Policy for a UI template resource, emitted at the resource's\n * `_meta.ui.csp` (the MCP Apps contract). The host derives CSP directives from\n * these origin lists; omitting a list blocks that class of request.\n */\nexport interface McpUiResourceCsp {\n /** `connect-src` — fetch / XHR / WebSocket origins. */\n connectDomains?: string[];\n /** `img-src` / `script-src` / `style-src` / `font-src` / `media-src` — static\n * resource origins. Supports wildcard subdomains, e.g. `https://*.example.com`. */\n resourceDomains?: string[];\n /** `frame-src` — origins allowed in nested iframes. */\n frameDomains?: string[];\n /** `base-uri` — allowed document base URIs. */\n baseUriDomains?: string[];\n}\n\nexport interface RegisteredMcpServer {\n readonly [MCP_SERVER_SYMBOL]: McpServerSpec;\n}\n\n// ============ Public factory helpers ============\n\n/**\n * Declare an MCP tool. The runtime advertises it in `tools/list` (using\n * `name`, `description`, `inputSchema`) and dispatches `tools/call` to\n * `handler`, enforcing `scopes` against the caller's granted scopes.\n */\nexport function defineMcpTool(\n spec: McpToolSpec,\n handler: (args: any, ctx: McpToolContext) => McpToolResult | Promise<McpToolResult>,\n): RegisteredMcpTool {\n return { [MCP_TOOL_SYMBOL]: spec, handler };\n}\n\n/**\n * Declare the MCP server identity and its iframe mini-app templates.\n * Optional — at most one per app; the last one discovered wins.\n */\nexport function defineMcpServer(spec: McpServerSpec): RegisteredMcpServer {\n return { [MCP_SERVER_SYMBOL]: spec };\n}\n\n/** Type guard used by the build-time discoverer and the runtime registry. */\nexport function isRegisteredMcpTool(value: unknown): value is RegisteredMcpTool {\n return (\n typeof value === 'object' &&\n value !== null &&\n MCP_TOOL_SYMBOL in value &&\n typeof (value as Record<string, unknown>).handler === 'function'\n );\n}\n\n/** Type guard for a registered MCP server descriptor. */\nexport function isRegisteredMcpServer(value: unknown): value is RegisteredMcpServer {\n return (\n typeof value === 'object' &&\n value !== null &&\n MCP_SERVER_SYMBOL in value\n );\n}\n"],"mappings":";AAiGO,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAkG1B,SAAS,cACd,MACA,SACmB;AACnB,SAAO,EAAE,CAAC,eAAe,GAAG,MAAM,QAAQ;AAC5C;AAMO,SAAS,gBAAgB,MAA0C;AACxE,SAAO,EAAE,CAAC,iBAAiB,GAAG,KAAK;AACrC;AAGO,SAAS,oBAAoB,OAA4C;AAC9E,SACE,OAAO,UAAU,YACjB,UAAU,QACV,mBAAmB,SACnB,OAAQ,MAAkC,YAAY;AAE1D;AAGO,SAAS,sBAAsB,OAA8C;AAClF,SACE,OAAO,UAAU,YACjB,UAAU,QACV,qBAAqB;AAEzB;","names":[]}
|
package/package.json
CHANGED
package/src/mcp.ts
CHANGED
|
@@ -140,24 +140,30 @@ export interface McpServerSpec {
|
|
|
140
140
|
*/
|
|
141
141
|
public?: boolean;
|
|
142
142
|
/**
|
|
143
|
-
* Mini-app UI templates referenced by tools via `ui.template`. Each
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* (`text/html;profile=mcp-app`), which the host (Claude, ChatGPT) renders inline
|
|
151
|
-
* — the MCP Apps standard. The widget receives its data over the MCP Apps
|
|
152
|
-
* channel (`@modelcontextprotocol/ext-apps`, `ontoolresult` →
|
|
153
|
-
* `structuredContent`), not via cookies.
|
|
143
|
+
* Mini-app UI templates referenced by tools via `ui.template`. Each renders a
|
|
144
|
+
* tool result as a **self-contained single-file HTML widget** the runtime
|
|
145
|
+
* serves inline as the `ui://<tool>/<template>` resource
|
|
146
|
+
* (`text/html;profile=mcp-app`) — the MCP Apps standard — which the host
|
|
147
|
+
* (Claude, ChatGPT) renders in a sandboxed iframe. The widget receives its
|
|
148
|
+
* data over the MCP Apps channel (`@modelcontextprotocol/ext-apps`,
|
|
149
|
+
* `ontoolresult` → `structuredContent`), not via cookies.
|
|
154
150
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
151
|
+
* **The build is automatic.** Put the widget *source* in `mcp-ui/<name>/`
|
|
152
|
+
* (or `src/mcp-ui/<name>/`) — `index.html` + your component + `app.css` with
|
|
153
|
+
* `@import 'tailwindcss';` — and the platform compiles it to a single inlined
|
|
154
|
+
* file during `maravilla build` (framework plugin + Tailwind + singlefile, all
|
|
155
|
+
* resolved for you). No second Vite config, no build script, no `@source`. See
|
|
156
|
+
* the `mcp-ui-mini-app` recipe.
|
|
157
|
+
*
|
|
158
|
+
* - `entry` — override the source location (a dir or an `index.html`); defaults
|
|
159
|
+
* to the `mcp-ui/<name>/` convention.
|
|
160
|
+
* - `htmlPath` — *legacy* escape hatch: point at a pre-built single-file under
|
|
161
|
+
* `static/` you build yourself. Prefer the convention.
|
|
162
|
+
* - `csp` — the resource's Content-Security-Policy ({@link McpUiResourceCsp},
|
|
163
|
+
* emitted at `_meta.ui.csp`): external origins the widget may load (e.g.
|
|
164
|
+
* `resourceDomains` for remote images). Omit for a self-contained widget.
|
|
159
165
|
*/
|
|
160
|
-
uiTemplates?: Array<{ name: string; htmlPath
|
|
166
|
+
uiTemplates?: Array<{ name: string; entry?: string; htmlPath?: string; csp?: McpUiResourceCsp }>;
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
/**
|