diff --git a/.gitignore b/.gitignore index 1c0c47b..6232f39 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ web_modules/ # PNPM .pnpm-store/ +.pnpm-home/ # TypeScript cache *.tsbuildinfo diff --git a/README.md b/README.md index 07a9e52..65d43bf 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,8 @@ It accepts the following props: - **`iframeProps`**: Optional props passed to the iframe element - **`iframeRenderData`**: Optional `Record` to pass data to the iframe upon rendering. This enables advanced use cases where the parent application needs to provide initial state or configuration to the sandboxed iframe content. - **`autoResizeIframe`**: Optional `boolean | { width?: boolean; height?: boolean }` to automatically resize the iframe to the size of the content. +- **`mcp`**: Optional MCP invocation context forwarded to HTML resources (e.g., `toolInput`, `toolOutput`, `toolName`, `toolResponseMetadata`). `toolOutput` values are injected into supported runtimes (like Skybridge) via the widget config and are not merged into `iframeRenderData`. +- **`host`**: Optional host context (e.g., `theme`, `locale`, `userAgent`, `model`, `displayMode`, `maxHeight`, `safeArea`, `capabilities`) exposed to sandboxed HTML content. `capabilities` defaults to `{ hover: true, touch: false }` when unspecified. - **`remoteDomProps`**: Optional props for the internal `` - **`library`**: Optional component library for Remote DOM resources (defaults to `basicComponentLibrary`) - **`remoteElements`**: remote element definitions for Remote DOM resources. diff --git a/docs/src/guide/client/html-resource.md b/docs/src/guide/client/html-resource.md index edb20ca..ce88b1f 100644 --- a/docs/src/guide/client/html-resource.md +++ b/docs/src/guide/client/html-resource.md @@ -6,6 +6,7 @@ The `` component is an internal component used by `; @@ -13,6 +14,8 @@ export interface HTMLResourceRendererProps { style?: React.CSSProperties; proxy?: string; iframeRenderData?: Record; + mcp?: MCPProps; + host?: HostProps; autoResizeIframe?: boolean | { width?: boolean; height?: boolean }; sandboxPermissions?: string; iframeProps?: Omit, 'src' | 'srcDoc' | 'ref' | 'style'>; @@ -40,6 +43,9 @@ The component accepts the following props: - **`style`**: (Optional) Custom styles for the iframe. - **`proxy`**: (Optional) A URL to a proxy script. This is useful for hosts with a strict Content Security Policy (CSP). When provided, external URLs will be rendered in a nested iframe hosted at this URL. For example, if `proxy` is `https://my-proxy.com/`, the final URL will be `https://my-proxy.com/?url=`. For your convenience, mcp-ui hosts a proxy script at `https://proxy.mcpui.dev`, which you can use as a the prop value without any setup (see `examples/external-url-demo`). - **`iframeProps`**: (Optional) Custom props for the iframe. +- **`iframeRenderData`**: (Optional) Additional data merged into the render payload forwarded to the iframe. This data combines with resource metadata but remains separate from `mcp.toolOutput`. When `mcp.toolOutput` is provided, supported runtimes (like Skybridge) treat that context as the iframe's initial render payload, overriding any metadata-derived data instead of merging with it. +- **`mcp`**: (Optional) MCP invocation context forwarded to HTML resources (e.g., `toolInput`, `toolOutput`, `toolName`, `toolResponseMetadata`). These values are exposed to supported runtimes such as Skybridge. +- **`host`**: (Optional) Host configuration forwarded to the sandboxed HTML (supports `theme`, `locale`, `userAgent`, `model`, `displayMode`, `maxHeight`, `safeArea`, and `capabilities`). When omitted, defaults are applied—`capabilities` defaults to `{ hover: true, touch: false }`. - **`autoResizeIframe`**: (Optional) When enabled, the iframe will automatically resize based on messages from the iframe's content. This prop can be a boolean (to enable both width and height resizing) or an object (`{width?: boolean, height?: boolean}`) to control dimensions independently. - **`sandboxPermissions`**: (Optional) Additional iframe sandbox permissions to add to the defaults. These are merged with: - External URLs (`text/uri-list`): `'allow-scripts allow-same-origin'` diff --git a/docs/src/guide/client/resource-renderer.md b/docs/src/guide/client/resource-renderer.md index 2c1c995..988ec7f 100644 --- a/docs/src/guide/client/resource-renderer.md +++ b/docs/src/guide/client/resource-renderer.md @@ -42,13 +42,16 @@ The `UIResourceRenderer` automatically detects and uses metadata from resources ```typescript import type { Resource } from '@modelcontextprotocol/sdk/types'; +import type { MCPProps, HostProps } from '@mcp-ui/client'; interface UIResourceRendererProps { resource: Partial; onUIAction?: (result: UIActionResult) => Promise; supportedContentTypes?: ResourceContentType[]; - htmlProps?: Omit; + htmlProps?: Omit; remoteDomProps?: Omit; + mcp?: MCPProps; + host?: HostProps; } ``` @@ -76,6 +79,8 @@ interface UIResourceRendererProps { - **`ref`**: Optional React ref to access the underlying iframe element - **`iframeRenderData`**: Optional `Record` to pass data to the iframe upon rendering. This enables advanced use cases where the parent application needs to provide initial state or configuration to the sandboxed iframe content. - **`autoResizeIframe`**: Optional `boolean | { width?: boolean; height?: boolean }` to automatically resize the iframe to the size of the content. +- **`mcp`**: Optional MCP invocation context forwarded to HTML resources (e.g., `toolInput`, `toolOutput`, `toolName`, `toolResponseMetadata`). The data is exposed to supported runtimes (like Skybridge) but is **not** merged into the iframe render payload. These can also be provided via `htmlProps` for HTML-only overrides. +- **`host`**: Optional host context for HTML resources (e.g., `theme`, `locale`, `userAgent`, `model`, `displayMode`, `maxHeight`, `safeArea`, `capabilities`). When unspecified, sensible defaults are used (`capabilities` defaults to `{ hover: true, touch: false }`). Like `mcp`, these can be supplied in `htmlProps` to scope them to HTML resources. - **`remoteDomProps`**: Optional props for the `` - **`library`**: Optional component library for Remote DOM resources (defaults to `basicComponentLibrary`) - **`remoteElements`**: Optional remote element definitions for Remote DOM resources. REQUIRED for Remote DOM snippets. diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5a86096..a233797 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - # all packages in subdirs of sdks/typescript/ - - 'sdks/typescript/*' - - 'examples/*' - - 'docs' + - sdks/typescript/* + - examples/* + - docs +onlyBuiltDependencies: + - esbuild diff --git a/sdks/typescript/client/README.md b/sdks/typescript/client/README.md index 07a9e52..2338639 100644 --- a/sdks/typescript/client/README.md +++ b/sdks/typescript/client/README.md @@ -98,6 +98,8 @@ It accepts the following props: - **`iframeProps`**: Optional props passed to the iframe element - **`iframeRenderData`**: Optional `Record` to pass data to the iframe upon rendering. This enables advanced use cases where the parent application needs to provide initial state or configuration to the sandboxed iframe content. - **`autoResizeIframe`**: Optional `boolean | { width?: boolean; height?: boolean }` to automatically resize the iframe to the size of the content. +- **`mcp`**: Optional MCP invocation context forwarded to HTML resources (e.g., `toolInput`, `toolOutput`, `toolName`, `toolResponseMetadata`). +- **`host`**: Optional host context (e.g., `theme`, `locale`, `userAgent`, `model`, `displayMode`, `maxHeight`, `safeArea`, `capabilities`) exposed to sandboxed HTML content. Both context props can also be supplied via `htmlProps` when you need HTML-specific overrides. `capabilities` defaults to `{ hover: true, touch: false }` when unspecified. - **`remoteDomProps`**: Optional props for the internal `` - **`library`**: Optional component library for Remote DOM resources (defaults to `basicComponentLibrary`) - **`remoteElements`**: remote element definitions for Remote DOM resources. diff --git a/sdks/typescript/client/scripts/bundle-open-ai-script.js b/sdks/typescript/client/scripts/bundle-open-ai-script.js new file mode 100644 index 0000000..8fa6c3e --- /dev/null +++ b/sdks/typescript/client/scripts/bundle-open-ai-script.js @@ -0,0 +1,35 @@ +import { build } from 'esbuild'; +import { writeFileSync } from 'fs'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +try { + const result = await build({ + entryPoints: [join(__dirname, '../../client/src/adapters/appssdk/open-ai-runtime-script.ts')], + bundle: true, + write: false, + format: 'iife', + platform: 'browser', + target: 'es2020', + minify: false, + }); + + const bundledCode = result.outputFiles[0].text; + const serializedCode = JSON.stringify(bundledCode); + + const outputContent = `// This file is auto-generated by scripts/bundle-open-ai-script.js +// Do not edit directly - modify client/src/adapters/appssdk/open-ai-runtime-script.ts instead + +export const API_RUNTIME_SCRIPT = ${serializedCode}; +`; + + const outputTsPath = join(__dirname, '../../client/src/adapters/appssdk/open-ai-runtime-script.bundled.ts'); + writeFileSync(outputTsPath, outputContent); + console.log('✅ Successfully bundled API runtime script'); +} catch (error) { + console.error('❌ Failed to bundle API runtime script:', error); + process.exit(1); +} diff --git a/sdks/typescript/client/scripts/proxy/index.html b/sdks/typescript/client/scripts/proxy/index.html index 1888c68..85b81e9 100644 --- a/sdks/typescript/client/scripts/proxy/index.html +++ b/sdks/typescript/client/scripts/proxy/index.html @@ -2,8 +2,6 @@ - - MCP-UI Proxy