diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 67a8d3ae..360fb9f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,9 +23,12 @@ jobs:
example_files: ${{ steps.filter.outputs.example_files }}
steps:
- uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- uses: dorny/paths-filter@v2
id: filter
with:
+ base: ${{ github.event_name == 'push' && github.event.before || github.base_ref }}
filters: |
ts_client_files:
- 'sdks/typescript/client/**'
@@ -152,6 +155,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
+ - name: Fetch all tags
+ run: git fetch --tags --force
- name: Setup pnpm
uses: pnpm/action-setup@v2
with: { version: 10 }
@@ -184,6 +189,8 @@ jobs:
with: { fetch-depth: 0 }
- name: Pull latest changes
run: git pull --rebase origin ${{ github.ref_name }}
+ - name: Fetch all tags
+ run: git fetch --tags --force
- name: Setup pnpm
uses: pnpm/action-setup@v2
with: { version: 10 }
@@ -201,7 +208,7 @@ jobs:
release_ruby_sdk:
name: Release Ruby SDK
- needs: [ruby_sdk_test, release_ts_server, filter_changed_paths]
+ needs: [ruby_sdk_test, filter_changed_paths, release_ts_server]
if: >
always() &&
(github.ref == 'refs/heads/main' || github.ref == 'refs/heads/alpha') &&
@@ -244,7 +251,7 @@ jobs:
release_python_sdk:
name: Release Python SDK
- needs: [python_sdk_test, release_ruby_sdk, filter_changed_paths]
+ needs: [python_sdk_test, filter_changed_paths, release_ruby_sdk]
if: >
always() &&
(github.ref == 'refs/heads/main' || github.ref == 'refs/heads/alpha') &&
diff --git a/.gitignore b/.gitignore
index d62e6e4f..1c0c47b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -193,4 +193,7 @@ __pycache__/
# Husky
.husky/_/
-.husky/.gitignore
\ No newline at end of file
+.husky/.gitignore
+
+# Auto-generated files
+adapter-runtime.bundled.ts
\ No newline at end of file
diff --git a/README.md b/README.md
index b8ae03bc..e162dab2 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@
## π‘ What's `mcp-ui`?
-`mcp-ui` is a collection of SDKs comprising:
+`mcp-ui` is a playground for the open spec of UI over MCP. It offers a collection of community SDKs comprising:
* **`@mcp-ui/server` (TypeScript)**: Utilities to generate UI resources (`UIResource`) on your MCP server.
* **`@mcp-ui/client` (TypeScript)**: UI components (e.g., ` `) to render the UI resources and handle their events.
@@ -143,6 +143,82 @@ Rendered using the internal ` ` component, which uti
UI snippets must be able to interact with the agent. In `mcp-ui`, this is done by hooking into events sent from the UI snippet and reacting to them in the host (see `onUIAction` prop). For example, an HTML may trigger a tool call when a button is clicked by sending an event which will be caught handled by the client.
+
+### Platform Adapters
+
+MCP-UI SDKs includes adapter support for host-specific implementations, enabling your open MCP-UI widgets to work seamlessly regardless of host. Adapters automatically translate between MCP-UI's `postMessage` protocol and host-specific APIs. Over time, as hosts become compatible with the open spec, these adapters wouldn't be needed.
+
+#### Available Adapters
+
+##### Apps SDK Adapter
+
+For Apps SDK environments (e.g., ChatGPT), this adapter translates MCP-UI protocol to Apps SDK API calls (e.g., `window.openai`).
+
+**How it Works:**
+- Intercepts MCP-UI `postMessage` calls from your widgets
+- Translates them to appropriate Apps SDK API calls
+- Handles bidirectional communication (tools, prompts, state management)
+- Works transparently - your existing MCP-UI code continues to work without changes
+
+**Usage:**
+
+```ts
+import { createUIResource } from '@mcp-ui/server';
+
+const htmlResource = createUIResource({
+ uri: 'ui://greeting/1',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+ Call Tool
+
+ `
+ },
+ encoding: 'text',
+ // Enable adapters
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: ...
+ }
+ // Future adapters can be enabled here
+ }
+});
+```
+
+The adapter scripts are automatically injected into your HTML content and handle all protocol translation.
+
+**Supported Actions:**
+- β
**Tool calls** - `{ type: 'tool', payload: { toolName, params } }`
+- β
**Prompts** - `{ type: 'prompt', payload: { prompt } }`
+- β
**Intents** - `{ type: 'intent', payload: { intent, params } }` (converted to prompts)
+- β
**Notifications** - `{ type: 'notify', payload: { message } }`
+- β
**Render data** - Access to `toolInput`, `toolOutput`, `widgetState`, `theme`, `locale`
+- β οΈ **Links** - `{ type: 'link', payload: { url } }` (may not be supported, returns error in some environments)
+
+#### Advanced Usage
+
+You can manually wrap HTML with adapters or access adapter scripts directly:
+
+```ts
+import { wrapHtmlWithAdapters, getAppsSdkAdapterScript } from '@mcp-ui/server';
+
+// Manually wrap HTML with adapters
+const wrappedHtml = wrapHtmlWithAdapters(
+ 'Click me ',
+ {
+ appsSdk: {
+ enabled: true,
+ config: { intentHandling: 'ignore' }
+ }
+ }
+);
+
+// Get a specific adapter script
+const appsSdkScript = getAppsSdkAdapterScript({ timeout: 60000 });
+```
+
## ποΈ Installation
### TypeScript
diff --git a/docs/src/guide/apps-sdk.md b/docs/src/guide/apps-sdk.md
new file mode 100644
index 00000000..421799cc
--- /dev/null
+++ b/docs/src/guide/apps-sdk.md
@@ -0,0 +1,85 @@
+# OpenAI Apps SDK Integration
+
+The Apps SDK adapter in `@mcp-ui/server` ensures your MCP-UI HTML runs inside ChatGPT. However, for now, you still need to manually wire the resource according to the Apps SDK resource pattern. This guide walks through the manual flow the adapter expects today.
+
+## Why two resources?
+
+- **Static template for Apps SDK** β referenced from your tool descriptor via `_meta["openai/outputTemplate"]`. This version must enable the Apps SDK adapter so ChatGPT injects the bridge script and uses the `text/html+skybridge` MIME type.
+- **Embedded resource in tool results** β returned each time your tool runs. This version should *not* enable the adapter so MCP-native hosts continue to receive standard MCP-UI HTML.
+
+## Step-by-step workflow
+
+### 1. Register the Apps SDK template
+
+Use `createUIResource` with `adapters.appsSdk.enabled: true` and expose it through the MCP Resources API so both Apps SDK and traditional MCP hosts can fetch it.
+
+```ts
+import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
+import { createUIResource } from '@mcp-ui/server';
+
+const server = new McpServer({ name: 'weather-bot', version: '1.0.0' });
+const TEMPLATE_URI = 'ui://widgets/weather';
+
+const appsSdkTemplate = createUIResource({
+ uri: TEMPLATE_URI,
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: { intentHandling: 'prompt' },
+ },
+ },
+ content: {
+ type: 'rawHtml',
+ htmlString: renderInitialShell(),
+ },
+});
+
+server.registerResource(TEMPLATE_URI, async () => appsSdkTemplate.resource);
+```
+
+> **Note:** The adapter switches the MIME type to `text/html+skybridge` and injects the Apps bridge script automatically. No extra HTML changes are required.
+
+### 2. Reference the template in your tool descriptor
+
+The Apps SDK looks for `_meta["openai/outputTemplate"]` to know which resource to render. Mirror the rest of the Apps-specific metadata you need (status text, accessibility hints, security schemes, etc.).
+
+```ts
+server.registerTool(
+ 'forecast',
+ {
+ title: 'Get the forecast',
+ description: 'Returns a UI that displays the current weather.',
+ inputSchema: {
+ type: 'object',
+ properties: { city: { type: 'string' } },
+ required: ['city'],
+ },
+ _meta: {
+ 'openai/outputTemplate': TEMPLATE_URI,
+ 'openai/toolInvocation/invoking': 'Fetching forecastβ¦',
+ 'openai/toolInvocation/invoked': 'Forecast ready',
+ 'openai/widgetAccessible': true,
+ },
+ },
+ async ({ city }) => {
+ const forecast = await fetchForecast(city);
+
+ // Step 3 happens inside the handler.
+ return {
+ content: [
+ {
+ type: 'text',
+ text: `Forecast prepared for ${city}.`,
+ },
+ ],
+ structuredContent: {
+ forecast,
+ },
+ };
+ },
+);
+```
+
+For the complete list of supported metadata fields, refer to the official documentation. [Apps SDK Reference](https://developers.openai.com/apps-sdk/reference)
+
diff --git a/docs/src/guide/introduction.md b/docs/src/guide/introduction.md
index a4b27d94..805a0a70 100644
--- a/docs/src/guide/introduction.md
+++ b/docs/src/guide/introduction.md
@@ -156,4 +156,5 @@ This project is an experimental playground for MCP-UI ideas, that aims to test o
- [Client SDK](./client/overview.md) - Learn to render UI resources
- [Typescript Server SDK](./server/typescript/overview.md) - Learn to create UI resources in Typescript
- [Ruby Server SDK](./server/ruby/overview.md) - Learn to create UI resources in Ruby
+- [Apps SDK Integration](./apps-sdk.md) - Wire the existing adapter into ChatGPT's Apps SDK
- [Protocol Details](./protocol-details.md) - Understand the underlying protocol
diff --git a/docs/src/index.md b/docs/src/index.md
index 9a3d6d45..3675cccc 100644
--- a/docs/src/index.md
+++ b/docs/src/index.md
@@ -24,6 +24,8 @@ hero:
link: /about
features:
+ - title: π Open Protocol
+ details: MCP-UI is an open spec to standardize UI over MCP. Write once, run everywhere!
- title: βοΈ Client SDK
details: Provides a React component and Web Component for easy frontend integration. Render interactive UI resources and handle UI actions effortlessly.
- title: π οΈ Server SDKs
diff --git a/examples/appssdk-adapter-demo/README.md b/examples/appssdk-adapter-demo/README.md
new file mode 100644
index 00000000..42494c71
--- /dev/null
+++ b/examples/appssdk-adapter-demo/README.md
@@ -0,0 +1,244 @@
+# Apps SDK Adapter Demo
+
+This example demonstrates how to use platform adapters in `@mcp-ui/server` to make MCP-UI widgets compatible with different environments. Specifically, this shows the Apps SDK adapter for environments like ChatGPT.
+
+## What are Adapters?
+
+Adapters enable MCP-UI widgets to work seamlessly across different platform environments by:
+- Translating MCP-UI `postMessage` calls to platform-specific API calls (e.g., `window.openai` in ChatGPT)
+- Handling bidirectional communication (tools, prompts, state management)
+- Working transparently without requiring changes to your existing MCP-UI code
+
+The adapters architecture supports multiple platforms, with Apps SDK being the first example.
+
+## Example Code
+
+```typescript
+import { createUIResource } from '@mcp-ui/server';
+
+// Example 1: Simple button with tool call
+const simpleButtonResource = createUIResource({
+ uri: 'ui://appssdk-demo/button',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+ Apps SDK Adapter Demo
+ Call Tool
+
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ // Enable adapters
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: {
+ intentHandling: 'prompt',
+ timeout: 30000
+ }
+ }
+ }
+});
+
+// Example 2: Widget that uses render data from Apps SDK
+const renderDataResource = createUIResource({
+ uri: 'ui://appssdk-demo/render-data',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+ Render Data Demo
+ Loading...
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true
+ }
+ }
+});
+
+// Example 3: Interactive form with multiple actions
+const interactiveFormResource = createUIResource({
+ uri: 'ui://appssdk-demo/form',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+ Interactive Form
+
+
+ Send Prompt
+ Notify
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: {
+ intentHandling: 'prompt'
+ }
+ }
+ }
+});
+```
+
+## How to Use
+
+1. Install dependencies:
+```bash
+npm install @mcp-ui/server
+```
+
+2. Create your MCP server with the examples above.
+
+3. **Register an Apps SDK template resource** β call `createUIResource` with the adapter enabled and expose it via `server.registerResource` (or the equivalent in your language SDK). The adapter wraps the HTML and switches the MIME type to `text/html+skybridge` so ChatGPT accepts it as an output template.
+
+4. **Reference that template from your tool definition** β when calling `registerTool`, set `_meta["openai/outputTemplate"]` to the template URI and include any other Apps SDK metadata (`openai/toolInvocation/*`, `openai/widgetAccessible`, `securitySchemes`, etc.).
+
+5. **Return plain MCP content from the tool runtime** β send text parts and/or `structuredContent` that match your declared schema. The template from step 3 is what ChatGPT actually renders, while other MCP hosts can still consume the textual/structured result.
+
+6. Deploy your server and connect it to the target environment (e.g., ChatGPT). The manual wiring ensures both MCP-UI-native clients and Apps SDK clients share the same UI implementation.
+
+## Supported Features
+
+β
**Tool Calls** - Call tools using `{ type: 'tool', payload: { toolName, params } }`
+
+β
**Prompts** - Send follow-up messages using `{ type: 'prompt', payload: { prompt } }`
+
+β
**Intents** - Express user intents (automatically converted to prompts)
+
+β
**Notifications** - Send notifications to the host
+
+β
**Render Data** - Access context like `toolInput`, `toolOutput`, `theme`, `locale`
+
+β οΈ **Links** - Navigation may not be supported in all Apps SDK environments
+
+## Configuration Options
+
+```typescript
+adapters: {
+ appsSdk?: {
+ enabled: boolean, // Enable/disable the Apps SDK adapter
+ config?: {
+ intentHandling?: 'prompt' | 'ignore', // How to handle intent messages
+ timeout?: number, // Timeout for async operations (ms)
+ hostOrigin?: string // Origin for MessageEvents
+ }
+ }
+ // Future adapters can be added here
+ // anotherPlatform?: { ... }
+}
+```
+
+## Learn More
+
+- [Apps SDK Documentation](https://developers.openai.com/apps-sdk/)
+- [MCP-UI Documentation](https://mcpui.dev)
+
diff --git a/examples/appssdk-adapter-demo/example.ts b/examples/appssdk-adapter-demo/example.ts
new file mode 100644
index 00000000..8c9c6b0a
--- /dev/null
+++ b/examples/appssdk-adapter-demo/example.ts
@@ -0,0 +1,408 @@
+/**
+ * Platform Adapters Example
+ *
+ * This example demonstrates how to create MCP-UI resources that work
+ * seamlessly across multiple platforms using adapters. The Apps SDK adapter
+ * enables compatibility with environments like ChatGPT.
+ */
+
+import { createUIResource } from '@mcp-ui/server';
+
+// Example 1: Simple interactive button
+export const simpleButtonExample = createUIResource({
+ uri: 'ui://appssdk-demo/button',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+
+
+
+
π€οΈ Weather Tool
+
Click the button to call the weather tool
+
Get Weather
+
+
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ // Enable adapters
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: {
+ intentHandling: 'prompt',
+ timeout: 30000
+ }
+ }
+ }
+});
+
+// Example 2: Accessing Apps SDK render data
+export const renderDataExample = createUIResource({
+ uri: 'ui://appssdk-demo/render-data',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+
+
+
+
π Apps SDK Context
+
Loading render data...
+
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true
+ }
+ }
+});
+
+// Example 3: Interactive form with multiple action types
+export const interactiveFormExample = createUIResource({
+ uri: 'ui://appssdk-demo/interactive-form',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+
+
+
+
+
+
+
+
+
π¬ Interactive Demo
+
+
+
+
+ Send Prompt
+ Notify
+ Send Intent
+
+
+
+
+
+
+
+
+ `
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: {
+ intentHandling: 'prompt', // Intents will be converted to prompts
+ timeout: 30000
+ }
+ }
+ }
+});
+
+// Export all examples
+export const appsSdkAdapterExamples = {
+ simpleButton: simpleButtonExample,
+ renderData: renderDataExample,
+ interactiveForm: interactiveFormExample
+};
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cc152c0b..457387d1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -450,6 +450,9 @@ importers:
'@vitest/coverage-v8':
specifier: ^1.0.0
version: 1.6.1(vitest@1.6.1(@types/node@18.19.112)(jsdom@23.2.0)(lightningcss@1.30.1))
+ esbuild:
+ specifier: ^0.19.0
+ version: 0.19.12
typescript:
specifier: ^5.0.0
version: 5.8.3
@@ -967,6 +970,12 @@ packages:
'@emnapi/wasi-threads@1.0.2':
resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==}
+ '@esbuild/aix-ppc64@0.19.12':
+ resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
@@ -985,6 +994,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/android-arm64@0.19.12':
+ resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm64@0.21.5':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
@@ -1003,6 +1018,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm@0.19.12':
+ resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-arm@0.21.5':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
@@ -1021,6 +1042,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-x64@0.19.12':
+ resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/android-x64@0.21.5':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
@@ -1039,6 +1066,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/darwin-arm64@0.19.12':
+ resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-arm64@0.21.5':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
@@ -1057,6 +1090,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-x64@0.19.12':
+ resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.21.5':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
@@ -1075,6 +1114,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/freebsd-arm64@0.19.12':
+ resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-arm64@0.21.5':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
@@ -1093,6 +1138,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.19.12':
+ resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.21.5':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
@@ -1111,6 +1162,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/linux-arm64@0.19.12':
+ resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm64@0.21.5':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
@@ -1129,6 +1186,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm@0.19.12':
+ resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-arm@0.21.5':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
@@ -1147,6 +1210,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-ia32@0.19.12':
+ resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-ia32@0.21.5':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
@@ -1165,6 +1234,12 @@ packages:
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-loong64@0.19.12':
+ resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-loong64@0.21.5':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
@@ -1183,6 +1258,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-mips64el@0.19.12':
+ resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.21.5':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
@@ -1201,6 +1282,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-ppc64@0.19.12':
+ resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.21.5':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
@@ -1219,6 +1306,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-riscv64@0.19.12':
+ resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.21.5':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
@@ -1237,6 +1330,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-s390x@0.19.12':
+ resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-s390x@0.21.5':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
@@ -1255,6 +1354,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-x64@0.19.12':
+ resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/linux-x64@0.21.5':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
@@ -1285,6 +1390,12 @@ packages:
cpu: [arm64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.19.12':
+ resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
@@ -1315,6 +1426,12 @@ packages:
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.19.12':
+ resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.21.5':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
@@ -1333,6 +1450,12 @@ packages:
cpu: [x64]
os: [openbsd]
+ '@esbuild/sunos-x64@0.19.12':
+ resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/sunos-x64@0.21.5':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
@@ -1351,6 +1474,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/win32-arm64@0.19.12':
+ resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-arm64@0.21.5':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
@@ -1369,6 +1498,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-ia32@0.19.12':
+ resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-ia32@0.21.5':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
@@ -1387,6 +1522,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-x64@0.19.12':
+ resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
'@esbuild/win32-x64@0.21.5':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
@@ -4460,6 +4601,11 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
+ esbuild@0.19.12:
+ resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
+ engines: {node: '>=12'}
+ hasBin: true
+
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
@@ -8728,6 +8874,9 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@esbuild/aix-ppc64@0.19.12':
+ optional: true
+
'@esbuild/aix-ppc64@0.21.5':
optional: true
@@ -8737,6 +8886,9 @@ snapshots:
'@esbuild/aix-ppc64@0.25.5':
optional: true
+ '@esbuild/android-arm64@0.19.12':
+ optional: true
+
'@esbuild/android-arm64@0.21.5':
optional: true
@@ -8746,6 +8898,9 @@ snapshots:
'@esbuild/android-arm64@0.25.5':
optional: true
+ '@esbuild/android-arm@0.19.12':
+ optional: true
+
'@esbuild/android-arm@0.21.5':
optional: true
@@ -8755,6 +8910,9 @@ snapshots:
'@esbuild/android-arm@0.25.5':
optional: true
+ '@esbuild/android-x64@0.19.12':
+ optional: true
+
'@esbuild/android-x64@0.21.5':
optional: true
@@ -8764,6 +8922,9 @@ snapshots:
'@esbuild/android-x64@0.25.5':
optional: true
+ '@esbuild/darwin-arm64@0.19.12':
+ optional: true
+
'@esbuild/darwin-arm64@0.21.5':
optional: true
@@ -8773,6 +8934,9 @@ snapshots:
'@esbuild/darwin-arm64@0.25.5':
optional: true
+ '@esbuild/darwin-x64@0.19.12':
+ optional: true
+
'@esbuild/darwin-x64@0.21.5':
optional: true
@@ -8782,6 +8946,9 @@ snapshots:
'@esbuild/darwin-x64@0.25.5':
optional: true
+ '@esbuild/freebsd-arm64@0.19.12':
+ optional: true
+
'@esbuild/freebsd-arm64@0.21.5':
optional: true
@@ -8791,6 +8958,9 @@ snapshots:
'@esbuild/freebsd-arm64@0.25.5':
optional: true
+ '@esbuild/freebsd-x64@0.19.12':
+ optional: true
+
'@esbuild/freebsd-x64@0.21.5':
optional: true
@@ -8800,6 +8970,9 @@ snapshots:
'@esbuild/freebsd-x64@0.25.5':
optional: true
+ '@esbuild/linux-arm64@0.19.12':
+ optional: true
+
'@esbuild/linux-arm64@0.21.5':
optional: true
@@ -8809,6 +8982,9 @@ snapshots:
'@esbuild/linux-arm64@0.25.5':
optional: true
+ '@esbuild/linux-arm@0.19.12':
+ optional: true
+
'@esbuild/linux-arm@0.21.5':
optional: true
@@ -8818,6 +8994,9 @@ snapshots:
'@esbuild/linux-arm@0.25.5':
optional: true
+ '@esbuild/linux-ia32@0.19.12':
+ optional: true
+
'@esbuild/linux-ia32@0.21.5':
optional: true
@@ -8827,6 +9006,9 @@ snapshots:
'@esbuild/linux-ia32@0.25.5':
optional: true
+ '@esbuild/linux-loong64@0.19.12':
+ optional: true
+
'@esbuild/linux-loong64@0.21.5':
optional: true
@@ -8836,6 +9018,9 @@ snapshots:
'@esbuild/linux-loong64@0.25.5':
optional: true
+ '@esbuild/linux-mips64el@0.19.12':
+ optional: true
+
'@esbuild/linux-mips64el@0.21.5':
optional: true
@@ -8845,6 +9030,9 @@ snapshots:
'@esbuild/linux-mips64el@0.25.5':
optional: true
+ '@esbuild/linux-ppc64@0.19.12':
+ optional: true
+
'@esbuild/linux-ppc64@0.21.5':
optional: true
@@ -8854,6 +9042,9 @@ snapshots:
'@esbuild/linux-ppc64@0.25.5':
optional: true
+ '@esbuild/linux-riscv64@0.19.12':
+ optional: true
+
'@esbuild/linux-riscv64@0.21.5':
optional: true
@@ -8863,6 +9054,9 @@ snapshots:
'@esbuild/linux-riscv64@0.25.5':
optional: true
+ '@esbuild/linux-s390x@0.19.12':
+ optional: true
+
'@esbuild/linux-s390x@0.21.5':
optional: true
@@ -8872,6 +9066,9 @@ snapshots:
'@esbuild/linux-s390x@0.25.5':
optional: true
+ '@esbuild/linux-x64@0.19.12':
+ optional: true
+
'@esbuild/linux-x64@0.21.5':
optional: true
@@ -8887,6 +9084,9 @@ snapshots:
'@esbuild/netbsd-arm64@0.25.5':
optional: true
+ '@esbuild/netbsd-x64@0.19.12':
+ optional: true
+
'@esbuild/netbsd-x64@0.21.5':
optional: true
@@ -8902,6 +9102,9 @@ snapshots:
'@esbuild/openbsd-arm64@0.25.5':
optional: true
+ '@esbuild/openbsd-x64@0.19.12':
+ optional: true
+
'@esbuild/openbsd-x64@0.21.5':
optional: true
@@ -8911,6 +9114,9 @@ snapshots:
'@esbuild/openbsd-x64@0.25.5':
optional: true
+ '@esbuild/sunos-x64@0.19.12':
+ optional: true
+
'@esbuild/sunos-x64@0.21.5':
optional: true
@@ -8920,6 +9126,9 @@ snapshots:
'@esbuild/sunos-x64@0.25.5':
optional: true
+ '@esbuild/win32-arm64@0.19.12':
+ optional: true
+
'@esbuild/win32-arm64@0.21.5':
optional: true
@@ -8929,6 +9138,9 @@ snapshots:
'@esbuild/win32-arm64@0.25.5':
optional: true
+ '@esbuild/win32-ia32@0.19.12':
+ optional: true
+
'@esbuild/win32-ia32@0.21.5':
optional: true
@@ -8938,6 +9150,9 @@ snapshots:
'@esbuild/win32-ia32@0.25.5':
optional: true
+ '@esbuild/win32-x64@0.19.12':
+ optional: true
+
'@esbuild/win32-x64@0.21.5':
optional: true
@@ -12610,6 +12825,32 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
+ esbuild@0.19.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.12
+ '@esbuild/android-arm': 0.19.12
+ '@esbuild/android-arm64': 0.19.12
+ '@esbuild/android-x64': 0.19.12
+ '@esbuild/darwin-arm64': 0.19.12
+ '@esbuild/darwin-x64': 0.19.12
+ '@esbuild/freebsd-arm64': 0.19.12
+ '@esbuild/freebsd-x64': 0.19.12
+ '@esbuild/linux-arm': 0.19.12
+ '@esbuild/linux-arm64': 0.19.12
+ '@esbuild/linux-ia32': 0.19.12
+ '@esbuild/linux-loong64': 0.19.12
+ '@esbuild/linux-mips64el': 0.19.12
+ '@esbuild/linux-ppc64': 0.19.12
+ '@esbuild/linux-riscv64': 0.19.12
+ '@esbuild/linux-s390x': 0.19.12
+ '@esbuild/linux-x64': 0.19.12
+ '@esbuild/netbsd-x64': 0.19.12
+ '@esbuild/openbsd-x64': 0.19.12
+ '@esbuild/sunos-x64': 0.19.12
+ '@esbuild/win32-arm64': 0.19.12
+ '@esbuild/win32-ia32': 0.19.12
+ '@esbuild/win32-x64': 0.19.12
+
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
diff --git a/sdks/ruby/release.config.js b/sdks/ruby/release.config.js
index 1636704b..007eeb23 100644
--- a/sdks/ruby/release.config.js
+++ b/sdks/ruby/release.config.js
@@ -1,5 +1,11 @@
module.exports = {
- branches: ['main'],
+ branches: [
+ 'main',
+ {
+ name: 'alpha',
+ prerelease: true,
+ },
+ ],
repositoryUrl: 'https://github.com/idosal/mcp-ui',
tagFormat: 'ruby-server-sdk/v${version}',
plugins: [
diff --git a/sdks/typescript/client/CHANGELOG.md b/sdks/typescript/client/CHANGELOG.md
index 0174399f..b499064f 100644
--- a/sdks/typescript/client/CHANGELOG.md
+++ b/sdks/typescript/client/CHANGELOG.md
@@ -1,3 +1,139 @@
+# [5.13.0-alpha.4](https://github.com/idosal/mcp-ui/compare/client/v5.13.0-alpha.3...client/v5.13.0-alpha.4) (2025-10-12)
+
+
+### Bug Fixes
+
+* exports vite ([4de2b0c](https://github.com/idosal/mcp-ui/commit/4de2b0cfae91813ad68fb1ce68b1cf7c2a161baf))
+
+# [5.13.0-alpha.3](https://github.com/idosal/mcp-ui/compare/client/v5.13.0-alpha.2...client/v5.13.0-alpha.3) (2025-10-11)
+
+
+### Bug Fixes
+
+* exports ([0018c17](https://github.com/idosal/mcp-ui/commit/0018c17dd8b184ee549327f1742d9da71edfd576))
+* version ([767a245](https://github.com/idosal/mcp-ui/commit/767a245d2374f05e27ece090dc5af8613a9a6b96))
+
+# [5.13.0-alpha.2](https://github.com/idosal/mcp-ui/compare/client/v5.13.0-alpha.1...client/v5.13.0-alpha.2) (2025-10-10)
+
+
+### Bug Fixes
+
+* set the mime type as text/html+skybridge for apps SDK ([bc47423](https://github.com/idosal/mcp-ui/commit/bc474232a249e5cc40f348e3a26f93c806fcc602))
+
+# [5.13.0-alpha.1](https://github.com/idosal/mcp-ui/compare/client/v5.12.1...client/v5.13.0-alpha.1) (2025-10-10)
+
+
+### Bug Fixes
+
+* adapter version ([259c842](https://github.com/idosal/mcp-ui/commit/259c84247a00933575e1fff08674cce52be59973))
+* release ([420efc0](https://github.com/idosal/mcp-ui/commit/420efc0a82bf8de2731514648268cad1209320e2))
+* server alpha versioning ([7f35d3b](https://github.com/idosal/mcp-ui/commit/7f35d3be2cfa6a535d3fbd5f86fbec1b20432dca))
+* server versioning ([2324371](https://github.com/idosal/mcp-ui/commit/2324371ed636381bb44a1feae1b59a87c84c6666))
+
+
+### Features
+
+* add adapters infra (appssdk) ([#125](https://github.com/idosal/mcp-ui/issues/125)) ([2e016cd](https://github.com/idosal/mcp-ui/commit/2e016cdc05d08c2f7c2e4a40efbec2b0704e7ef6))
+
+# [1.0.0-alpha.2](https://github.com/idosal/mcp-ui/compare/client/v1.0.0-alpha.1...client/v1.0.0-alpha.2) (2025-10-10)
+
+
+### Bug Fixes
+
+* server versioning ([2324371](https://github.com/idosal/mcp-ui/commit/2324371ed636381bb44a1feae1b59a87c84c6666))
+
+# 1.0.0-alpha.1 (2025-10-10)
+
+
+### Bug Fixes
+
+* adapter version ([259c842](https://github.com/idosal/mcp-ui/commit/259c84247a00933575e1fff08674cce52be59973))
+* add a bridge to pass messages in and out of the proxy ([#38](https://github.com/idosal/mcp-ui/issues/38)) ([30ccac0](https://github.com/idosal/mcp-ui/commit/30ccac0706ad8e02ebcd8960924ed1d58ddedf85))
+* bump client version ([75c9236](https://github.com/idosal/mcp-ui/commit/75c923689654b4443ad1093fafc0bad16902e4cc))
+* **client:** specify iframe ([fd0b70a](https://github.com/idosal/mcp-ui/commit/fd0b70a84948d3aa5d7a79269ff7c3bcd0946689))
+* **client:** styling ([6ff9b68](https://github.com/idosal/mcp-ui/commit/6ff9b685fd1be770fd103943e45275e9ec86905c))
+* dependencies ([887f61f](https://github.com/idosal/mcp-ui/commit/887f61f827b4585c17493d4fa2dfb251ea598587))
+* export RemoteDomResource ([2b86f2d](https://github.com/idosal/mcp-ui/commit/2b86f2dd4506de49c69908e23d84a2a323170446))
+* export ResourceRenderer and HtmlResource ([2b841a5](https://github.com/idosal/mcp-ui/commit/2b841a556c1111ed70ccb3d3987afd21fe7df897))
+* exports ([3a93a16](https://github.com/idosal/mcp-ui/commit/3a93a16e1b7438ba7b2ef49ca854479f755abcc6))
+* iframe handle ([#15](https://github.com/idosal/mcp-ui/issues/15)) ([66bd4fd](https://github.com/idosal/mcp-ui/commit/66bd4fd3d04f82e3e4557f064e701b68e1d8af11))
+* lint ([4487820](https://github.com/idosal/mcp-ui/commit/44878203a71c3c9173d463b809be36769e996ba9))
+* lint ([d0a91f9](https://github.com/idosal/mcp-ui/commit/d0a91f9a07ec0042690240c3d8d0bad620f8c765))
+* minor typo ([a0bee9c](https://github.com/idosal/mcp-ui/commit/a0bee9c85e5ee02e021ba687940ced38220445fe))
+* move react dependencies to be peer dependencies ([#91](https://github.com/idosal/mcp-ui/issues/91)) ([f672f3e](https://github.com/idosal/mcp-ui/commit/f672f3efc1c2ba2fbae16f9dcdc2142c2b4bd920)), closes [#90](https://github.com/idosal/mcp-ui/issues/90)
+* package config ([8dc1e53](https://github.com/idosal/mcp-ui/commit/8dc1e5358c3c8e641206a5e6851427d360cc1955))
+* packaging ([9e6babd](https://github.com/idosal/mcp-ui/commit/9e6babd3a587213452ea7aec4cc9ae3a50fa1965))
+* pass ref explicitly using iframeProps ([#33](https://github.com/idosal/mcp-ui/issues/33)) ([d01b5d1](https://github.com/idosal/mcp-ui/commit/d01b5d1e4cdaedc436ba2fa8984d866d93d59087))
+* publish ([0943e7a](https://github.com/idosal/mcp-ui/commit/0943e7acaf17f32aae085c2313bfbec47bc59f1f))
+* ref passing to UIResourceRenderer ([#32](https://github.com/idosal/mcp-ui/issues/32)) ([d28c23f](https://github.com/idosal/mcp-ui/commit/d28c23f9b8ee320f4e361200ae02a23f0d2a1c0c))
+* release ([420efc0](https://github.com/idosal/mcp-ui/commit/420efc0a82bf8de2731514648268cad1209320e2))
+* remove shared dependency ([e66e8f4](https://github.com/idosal/mcp-ui/commit/e66e8f49b1ba46090db6e4682060488566f4fe41))
+* rename components and methods to fit new scope ([#22](https://github.com/idosal/mcp-ui/issues/22)) ([6bab1fe](https://github.com/idosal/mcp-ui/commit/6bab1fe3a168a18e7ba4762e23478abf4e0cc84c))
+* rename delivery -> encoding and flavor -> framework ([#36](https://github.com/idosal/mcp-ui/issues/36)) ([9a509ed](https://github.com/idosal/mcp-ui/commit/9a509ed80d051b0a8042b36958b401a0a7c1e138))
+* Ruby comment ([b22dc2e](https://github.com/idosal/mcp-ui/commit/b22dc2e0a0db20d98ada884649ad408ebaf72d22))
+* support react-router ([21ffb95](https://github.com/idosal/mcp-ui/commit/21ffb95fe6d77a348b95b38dbf3741ba6442894e))
+* text and blob support in RemoteDOM resources ([ec68eb9](https://github.com/idosal/mcp-ui/commit/ec68eb90df984da8b492cc25eafdafdeda79f299))
+* trigger release ([aaca831](https://github.com/idosal/mcp-ui/commit/aaca83125c3f7825ccdebf0f04f8553e953c5249))
+* typescript ci publish ([e7c0ebf](https://github.com/idosal/mcp-ui/commit/e7c0ebfa7f7b552f9763743fda659d1441f21692))
+* typescript types to be compatible with MCP SDK ([#10](https://github.com/idosal/mcp-ui/issues/10)) ([74365d7](https://github.com/idosal/mcp-ui/commit/74365d7ed6422beef6cd9ee0f5a97c847bd9827b))
+* update deps ([4091ef4](https://github.com/idosal/mcp-ui/commit/4091ef47da048fab3c4feb002f5287b2ff295744))
+* update isUIResource to use EmbeddedResource type ([#122](https://github.com/idosal/mcp-ui/issues/122)) ([5a65a0b](https://github.com/idosal/mcp-ui/commit/5a65a0b1ba63e6cfda26b8da41239a532f00d60a)), closes [#117](https://github.com/idosal/mcp-ui/issues/117)
+* use targetOrigin in the proxy message relay ([#40](https://github.com/idosal/mcp-ui/issues/40)) ([b3fb54e](https://github.com/idosal/mcp-ui/commit/b3fb54e28ca7b8eeda896b5bcf478b6343dbba47))
+* validate URL ([b7c994d](https://github.com/idosal/mcp-ui/commit/b7c994dfdd947b3dfbb903fc8cb896d61004c8d8))
+* wc dist overwrite ([#63](https://github.com/idosal/mcp-ui/issues/63)) ([9e46c56](https://github.com/idosal/mcp-ui/commit/9e46c56c7a8908410fad6d08a5d845139e93f80f))
+
+
+### Documentation
+
+* bump ([#4](https://github.com/idosal/mcp-ui/issues/4)) ([ad4d163](https://github.com/idosal/mcp-ui/commit/ad4d1632cc1f9c99072349a8f0cdaac343236132))
+
+
+### Features
+
+* add adapters infra (appssdk) ([#125](https://github.com/idosal/mcp-ui/issues/125)) ([2e016cd](https://github.com/idosal/mcp-ui/commit/2e016cdc05d08c2f7c2e4a40efbec2b0704e7ef6))
+* add convenience function isUIResource to client SDK ([#86](https://github.com/idosal/mcp-ui/issues/86)) ([607c6ad](https://github.com/idosal/mcp-ui/commit/607c6add3567bb60c45accf3e1b25a38ed284a6f))
+* add embeddedResourceProps for annotations ([#99](https://github.com/idosal/mcp-ui/issues/99)) ([b96ec44](https://github.com/idosal/mcp-ui/commit/b96ec442ec319a1944393ada0bdcccb93b7ffc62))
+* add proxy option to externalUrl ([#37](https://github.com/idosal/mcp-ui/issues/37)) ([7b95cd0](https://github.com/idosal/mcp-ui/commit/7b95cd0b3873fc1cde28748ec463e81c6ff1c494))
+* add remote-dom content type ([#18](https://github.com/idosal/mcp-ui/issues/18)) ([5dacf37](https://github.com/idosal/mcp-ui/commit/5dacf37c22b5ee6ae795049a8d573fc073b8a1f5))
+* add Ruby server SDK ([#31](https://github.com/idosal/mcp-ui/issues/31)) ([5ffcde4](https://github.com/idosal/mcp-ui/commit/5ffcde4a373accdd063fa6c3b1b3d4df13c91b53))
+* add sandbox permissions instead of an override ([#83](https://github.com/idosal/mcp-ui/issues/83)) ([b1068e9](https://github.com/idosal/mcp-ui/commit/b1068e9e87caa2b4302bf145a33efdfd1af05c1d))
+* add ui-request-render-data message type ([#111](https://github.com/idosal/mcp-ui/issues/111)) ([26135ce](https://github.com/idosal/mcp-ui/commit/26135ce2c7f7d586b0b81a03623cd77dc1bc7f90))
+* add UIResourceRenderer Web Component ([#58](https://github.com/idosal/mcp-ui/issues/58)) ([ec8f299](https://github.com/idosal/mcp-ui/commit/ec8f2994ecf36774e6ad5191654ba22946d0ee49))
+* auto resize with the autoResizeIframe prop ([#56](https://github.com/idosal/mcp-ui/issues/56)) ([76c867a](https://github.com/idosal/mcp-ui/commit/76c867a569b72aed892290aa84e1194ab8eb79ce))
+* change onGenericMcpAction to optional onUiAction ([1913b59](https://github.com/idosal/mcp-ui/commit/1913b5977c30811f9e67659949e2d961f2eda983))
+* **client:** allow setting supportedContentTypes for HtmlResource ([#17](https://github.com/idosal/mcp-ui/issues/17)) ([e009ef1](https://github.com/idosal/mcp-ui/commit/e009ef10010134ba3d9893314cc4d8e1274f1f07))
+* consolidate ui:// and ui-app:// ([#8](https://github.com/idosal/mcp-ui/issues/8)) ([2e08035](https://github.com/idosal/mcp-ui/commit/2e08035676bb6a46ef3c94dba916bc895f1fa3cc))
+* pass iframe props down ([#14](https://github.com/idosal/mcp-ui/issues/14)) ([112539d](https://github.com/idosal/mcp-ui/commit/112539d28640a96e8375a6b416f2ba559370b312))
+* refactor UTFtoB64 (bump server version) ([#95](https://github.com/idosal/mcp-ui/issues/95)) ([2d5e16b](https://github.com/idosal/mcp-ui/commit/2d5e16bf39073ee890586f458412f0c3b474c2b8))
+* send render data to the iframe ([#51](https://github.com/idosal/mcp-ui/issues/51)) ([d38cfc7](https://github.com/idosal/mcp-ui/commit/d38cfc7925061c1ae1911bdee408033c8e9f283d))
+* separate html and remote-dom props ([#24](https://github.com/idosal/mcp-ui/issues/24)) ([a7f0529](https://github.com/idosal/mcp-ui/commit/a7f05299dc9cc40184f9ab25c5b648ee7077be64))
+* support generic messages response ([#35](https://github.com/idosal/mcp-ui/issues/35)) ([10b407b](https://github.com/idosal/mcp-ui/commit/10b407b279b3ee9608ef077445f4d714f88343c5))
+* support passing resource metadata ([#87](https://github.com/idosal/mcp-ui/issues/87)) ([f1c1c9b](https://github.com/idosal/mcp-ui/commit/f1c1c9b62dd74c63045b295eb388181843ac772a))
+* support ui action result types ([#6](https://github.com/idosal/mcp-ui/issues/6)) ([899d152](https://github.com/idosal/mcp-ui/commit/899d1527286a281a23fbb8f3a207d435dfc3fe96))
+* switch to ResourceRenderer ([#21](https://github.com/idosal/mcp-ui/issues/21)) ([6fe3166](https://github.com/idosal/mcp-ui/commit/6fe316682675e27db914d60696754677e3783448))
+
+
+### BREAKING CHANGES
+
+* The existing naming is ambiguous. Renaming delivery to encoding and flavor to framework should clarify the intent.
+* exported names have changed
+* removed deprecated client API
+* (previous one didn't take due to semantic-release misalignment)
+
+# [5.13.0-alpha.2](https://github.com/idosal/mcp-ui/compare/v5.13.0-alpha.1...v5.13.0-alpha.2) (2025-10-10)
+
+
+### Bug Fixes
+
+* adapter version ([259c842](https://github.com/idosal/mcp-ui/commit/259c84247a00933575e1fff08674cce52be59973))
+
+# [5.13.0-alpha.1](https://github.com/idosal/mcp-ui/compare/v5.12.1...v5.13.0-alpha.1) (2025-10-10)
+
+
+### Features
+
+* add adapters infra (appssdk) ([#125](https://github.com/idosal/mcp-ui/issues/125)) ([2e016cd](https://github.com/idosal/mcp-ui/commit/2e016cdc05d08c2f7c2e4a40efbec2b0704e7ef6))
+
## [5.12.1](https://github.com/idosal/mcp-ui/compare/v5.12.0...v5.12.1) (2025-10-08)
diff --git a/sdks/typescript/client/README.md b/sdks/typescript/client/README.md
index b8ae03bc..e162dab2 100644
--- a/sdks/typescript/client/README.md
+++ b/sdks/typescript/client/README.md
@@ -39,7 +39,7 @@
## π‘ What's `mcp-ui`?
-`mcp-ui` is a collection of SDKs comprising:
+`mcp-ui` is a playground for the open spec of UI over MCP. It offers a collection of community SDKs comprising:
* **`@mcp-ui/server` (TypeScript)**: Utilities to generate UI resources (`UIResource`) on your MCP server.
* **`@mcp-ui/client` (TypeScript)**: UI components (e.g., ` `) to render the UI resources and handle their events.
@@ -143,6 +143,82 @@ Rendered using the internal ` ` component, which uti
UI snippets must be able to interact with the agent. In `mcp-ui`, this is done by hooking into events sent from the UI snippet and reacting to them in the host (see `onUIAction` prop). For example, an HTML may trigger a tool call when a button is clicked by sending an event which will be caught handled by the client.
+
+### Platform Adapters
+
+MCP-UI SDKs includes adapter support for host-specific implementations, enabling your open MCP-UI widgets to work seamlessly regardless of host. Adapters automatically translate between MCP-UI's `postMessage` protocol and host-specific APIs. Over time, as hosts become compatible with the open spec, these adapters wouldn't be needed.
+
+#### Available Adapters
+
+##### Apps SDK Adapter
+
+For Apps SDK environments (e.g., ChatGPT), this adapter translates MCP-UI protocol to Apps SDK API calls (e.g., `window.openai`).
+
+**How it Works:**
+- Intercepts MCP-UI `postMessage` calls from your widgets
+- Translates them to appropriate Apps SDK API calls
+- Handles bidirectional communication (tools, prompts, state management)
+- Works transparently - your existing MCP-UI code continues to work without changes
+
+**Usage:**
+
+```ts
+import { createUIResource } from '@mcp-ui/server';
+
+const htmlResource = createUIResource({
+ uri: 'ui://greeting/1',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+ Call Tool
+
+ `
+ },
+ encoding: 'text',
+ // Enable adapters
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: ...
+ }
+ // Future adapters can be enabled here
+ }
+});
+```
+
+The adapter scripts are automatically injected into your HTML content and handle all protocol translation.
+
+**Supported Actions:**
+- β
**Tool calls** - `{ type: 'tool', payload: { toolName, params } }`
+- β
**Prompts** - `{ type: 'prompt', payload: { prompt } }`
+- β
**Intents** - `{ type: 'intent', payload: { intent, params } }` (converted to prompts)
+- β
**Notifications** - `{ type: 'notify', payload: { message } }`
+- β
**Render data** - Access to `toolInput`, `toolOutput`, `widgetState`, `theme`, `locale`
+- β οΈ **Links** - `{ type: 'link', payload: { url } }` (may not be supported, returns error in some environments)
+
+#### Advanced Usage
+
+You can manually wrap HTML with adapters or access adapter scripts directly:
+
+```ts
+import { wrapHtmlWithAdapters, getAppsSdkAdapterScript } from '@mcp-ui/server';
+
+// Manually wrap HTML with adapters
+const wrappedHtml = wrapHtmlWithAdapters(
+ 'Click me ',
+ {
+ appsSdk: {
+ enabled: true,
+ config: { intentHandling: 'ignore' }
+ }
+ }
+);
+
+// Get a specific adapter script
+const appsSdkScript = getAppsSdkAdapterScript({ timeout: 60000 });
+```
+
## ποΈ Installation
### TypeScript
diff --git a/sdks/typescript/client/package.json b/sdks/typescript/client/package.json
index b0688934..4545b7eb 100644
--- a/sdks/typescript/client/package.json
+++ b/sdks/typescript/client/package.json
@@ -1,17 +1,17 @@
{
"name": "@mcp-ui/client",
- "version": "5.12.1",
+ "version": "5.13.0-alpha.4",
"description": "mcp-ui Client SDK",
"private": false,
"type": "module",
- "main": "./dist/index.js",
+ "main": "./dist/index.cjs",
"module": "./dist/index.mjs",
- "types": "./dist/index.d.ts",
+ "types": "./dist/src/index.d.ts",
"exports": {
".": {
- "types": "./dist/index.d.ts",
+ "types": "./dist/src/index.d.ts",
"import": "./dist/index.mjs",
- "require": "./dist/index.js"
+ "require": "./dist/index.cjs"
},
"./ui-resource-renderer.wc.js": "./dist/ui-resource-renderer.wc.js"
},
@@ -60,8 +60,13 @@
},
"release": {
"branches": [
- "main"
+ "main",
+ {
+ "name": "alpha",
+ "prerelease": true
+ }
],
+ "tagFormat": "client/v${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
diff --git a/sdks/typescript/client/vite.config.ts b/sdks/typescript/client/vite.config.ts
index 1067c2fa..a872beaf 100644
--- a/sdks/typescript/client/vite.config.ts
+++ b/sdks/typescript/client/vite.config.ts
@@ -7,7 +7,7 @@ export default defineConfig({
plugins: [
react(),
dts({
- insertTypesEntry: true,
+ insertTypesEntry: false,
exclude: ['**/__tests__/**', '**/*.test.ts', '**/*.spec.ts', '**/UIResourceRendererWC.tsx'],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
diff --git a/sdks/typescript/server/CHANGELOG.md b/sdks/typescript/server/CHANGELOG.md
index 8f39f0db..bd4268dd 100644
--- a/sdks/typescript/server/CHANGELOG.md
+++ b/sdks/typescript/server/CHANGELOG.md
@@ -1,3 +1,134 @@
+# [5.12.0-alpha.6](https://github.com/idosal/mcp-ui/compare/server/v5.12.0-alpha.5...server/v5.12.0-alpha.6) (2025-10-13)
+
+
+### Bug Fixes
+
+* separate adapter wrappers for flexibility ([#128](https://github.com/idosal/mcp-ui/issues/128)) ([a636844](https://github.com/idosal/mcp-ui/commit/a6368448c44b15da87c883cb3a65ebfe6119e85d))
+
+# [5.12.0-alpha.5](https://github.com/idosal/mcp-ui/compare/server/v5.12.0-alpha.4...server/v5.12.0-alpha.5) (2025-10-12)
+
+
+### Bug Fixes
+
+* exports vite ([4de2b0c](https://github.com/idosal/mcp-ui/commit/4de2b0cfae91813ad68fb1ce68b1cf7c2a161baf))
+
+# [5.12.0-alpha.4](https://github.com/idosal/mcp-ui/compare/server/v5.12.0-alpha.3...server/v5.12.0-alpha.4) (2025-10-11)
+
+
+### Bug Fixes
+
+* exports ([0018c17](https://github.com/idosal/mcp-ui/commit/0018c17dd8b184ee549327f1742d9da71edfd576))
+
+# [5.12.0-alpha.3](https://github.com/idosal/mcp-ui/compare/server/v5.12.0-alpha.2...server/v5.12.0-alpha.3) (2025-10-11)
+
+
+### Bug Fixes
+
+* version ([767a245](https://github.com/idosal/mcp-ui/commit/767a245d2374f05e27ece090dc5af8613a9a6b96))
+
+# [5.12.0-alpha.2](https://github.com/idosal/mcp-ui/compare/server/v5.12.0-alpha.1...server/v5.12.0-alpha.2) (2025-10-10)
+
+
+### Bug Fixes
+
+* set the mime type as text/html+skybridge for apps SDK ([bc47423](https://github.com/idosal/mcp-ui/commit/bc474232a249e5cc40f348e3a26f93c806fcc602))
+
+# [5.12.0-alpha.1](https://github.com/idosal/mcp-ui/compare/server/v5.11.0...server/v5.12.0-alpha.1) (2025-10-10)
+
+
+### Bug Fixes
+
+* adapter version ([259c842](https://github.com/idosal/mcp-ui/commit/259c84247a00933575e1fff08674cce52be59973))
+* release ([420efc0](https://github.com/idosal/mcp-ui/commit/420efc0a82bf8de2731514648268cad1209320e2))
+* server alpha versioning ([7f35d3b](https://github.com/idosal/mcp-ui/commit/7f35d3be2cfa6a535d3fbd5f86fbec1b20432dca))
+* server versioning ([2324371](https://github.com/idosal/mcp-ui/commit/2324371ed636381bb44a1feae1b59a87c84c6666))
+* update isUIResource to use EmbeddedResource type ([#122](https://github.com/idosal/mcp-ui/issues/122)) ([5a65a0b](https://github.com/idosal/mcp-ui/commit/5a65a0b1ba63e6cfda26b8da41239a532f00d60a)), closes [#117](https://github.com/idosal/mcp-ui/issues/117)
+
+
+### Features
+
+* add adapters infra (appssdk) ([#125](https://github.com/idosal/mcp-ui/issues/125)) ([2e016cd](https://github.com/idosal/mcp-ui/commit/2e016cdc05d08c2f7c2e4a40efbec2b0704e7ef6))
+* add ui-request-render-data message type ([#111](https://github.com/idosal/mcp-ui/issues/111)) ([26135ce](https://github.com/idosal/mcp-ui/commit/26135ce2c7f7d586b0b81a03623cd77dc1bc7f90))
+
+# 1.0.0-alpha.1 (2025-10-10)
+
+
+### Bug Fixes
+
+* adapter version ([259c842](https://github.com/idosal/mcp-ui/commit/259c84247a00933575e1fff08674cce52be59973))
+* add a bridge to pass messages in and out of the proxy ([#38](https://github.com/idosal/mcp-ui/issues/38)) ([30ccac0](https://github.com/idosal/mcp-ui/commit/30ccac0706ad8e02ebcd8960924ed1d58ddedf85))
+* bump client version ([75c9236](https://github.com/idosal/mcp-ui/commit/75c923689654b4443ad1093fafc0bad16902e4cc))
+* **client:** specify iframe ([fd0b70a](https://github.com/idosal/mcp-ui/commit/fd0b70a84948d3aa5d7a79269ff7c3bcd0946689))
+* **client:** styling ([6ff9b68](https://github.com/idosal/mcp-ui/commit/6ff9b685fd1be770fd103943e45275e9ec86905c))
+* dependencies ([887f61f](https://github.com/idosal/mcp-ui/commit/887f61f827b4585c17493d4fa2dfb251ea598587))
+* export RemoteDomResource ([2b86f2d](https://github.com/idosal/mcp-ui/commit/2b86f2dd4506de49c69908e23d84a2a323170446))
+* export ResourceRenderer and HtmlResource ([2b841a5](https://github.com/idosal/mcp-ui/commit/2b841a556c1111ed70ccb3d3987afd21fe7df897))
+* exports ([3a93a16](https://github.com/idosal/mcp-ui/commit/3a93a16e1b7438ba7b2ef49ca854479f755abcc6))
+* iframe handle ([#15](https://github.com/idosal/mcp-ui/issues/15)) ([66bd4fd](https://github.com/idosal/mcp-ui/commit/66bd4fd3d04f82e3e4557f064e701b68e1d8af11))
+* lint ([4487820](https://github.com/idosal/mcp-ui/commit/44878203a71c3c9173d463b809be36769e996ba9))
+* lint ([d0a91f9](https://github.com/idosal/mcp-ui/commit/d0a91f9a07ec0042690240c3d8d0bad620f8c765))
+* minor typo ([a0bee9c](https://github.com/idosal/mcp-ui/commit/a0bee9c85e5ee02e021ba687940ced38220445fe))
+* move react dependencies to be peer dependencies ([#91](https://github.com/idosal/mcp-ui/issues/91)) ([f672f3e](https://github.com/idosal/mcp-ui/commit/f672f3efc1c2ba2fbae16f9dcdc2142c2b4bd920)), closes [#90](https://github.com/idosal/mcp-ui/issues/90)
+* package config ([8dc1e53](https://github.com/idosal/mcp-ui/commit/8dc1e5358c3c8e641206a5e6851427d360cc1955))
+* packaging ([9e6babd](https://github.com/idosal/mcp-ui/commit/9e6babd3a587213452ea7aec4cc9ae3a50fa1965))
+* pass ref explicitly using iframeProps ([#33](https://github.com/idosal/mcp-ui/issues/33)) ([d01b5d1](https://github.com/idosal/mcp-ui/commit/d01b5d1e4cdaedc436ba2fa8984d866d93d59087))
+* publish ([0943e7a](https://github.com/idosal/mcp-ui/commit/0943e7acaf17f32aae085c2313bfbec47bc59f1f))
+* ref passing to UIResourceRenderer ([#32](https://github.com/idosal/mcp-ui/issues/32)) ([d28c23f](https://github.com/idosal/mcp-ui/commit/d28c23f9b8ee320f4e361200ae02a23f0d2a1c0c))
+* release ([420efc0](https://github.com/idosal/mcp-ui/commit/420efc0a82bf8de2731514648268cad1209320e2))
+* remove shared dependency ([e66e8f4](https://github.com/idosal/mcp-ui/commit/e66e8f49b1ba46090db6e4682060488566f4fe41))
+* rename components and methods to fit new scope ([#22](https://github.com/idosal/mcp-ui/issues/22)) ([6bab1fe](https://github.com/idosal/mcp-ui/commit/6bab1fe3a168a18e7ba4762e23478abf4e0cc84c))
+* rename delivery -> encoding and flavor -> framework ([#36](https://github.com/idosal/mcp-ui/issues/36)) ([9a509ed](https://github.com/idosal/mcp-ui/commit/9a509ed80d051b0a8042b36958b401a0a7c1e138))
+* Ruby comment ([b22dc2e](https://github.com/idosal/mcp-ui/commit/b22dc2e0a0db20d98ada884649ad408ebaf72d22))
+* server versioning ([2324371](https://github.com/idosal/mcp-ui/commit/2324371ed636381bb44a1feae1b59a87c84c6666))
+* support react-router ([21ffb95](https://github.com/idosal/mcp-ui/commit/21ffb95fe6d77a348b95b38dbf3741ba6442894e))
+* text and blob support in RemoteDOM resources ([ec68eb9](https://github.com/idosal/mcp-ui/commit/ec68eb90df984da8b492cc25eafdafdeda79f299))
+* trigger release ([aaca831](https://github.com/idosal/mcp-ui/commit/aaca83125c3f7825ccdebf0f04f8553e953c5249))
+* typescript ci publish ([e7c0ebf](https://github.com/idosal/mcp-ui/commit/e7c0ebfa7f7b552f9763743fda659d1441f21692))
+* typescript types to be compatible with MCP SDK ([#10](https://github.com/idosal/mcp-ui/issues/10)) ([74365d7](https://github.com/idosal/mcp-ui/commit/74365d7ed6422beef6cd9ee0f5a97c847bd9827b))
+* update deps ([4091ef4](https://github.com/idosal/mcp-ui/commit/4091ef47da048fab3c4feb002f5287b2ff295744))
+* update isUIResource to use EmbeddedResource type ([#122](https://github.com/idosal/mcp-ui/issues/122)) ([5a65a0b](https://github.com/idosal/mcp-ui/commit/5a65a0b1ba63e6cfda26b8da41239a532f00d60a)), closes [#117](https://github.com/idosal/mcp-ui/issues/117)
+* use targetOrigin in the proxy message relay ([#40](https://github.com/idosal/mcp-ui/issues/40)) ([b3fb54e](https://github.com/idosal/mcp-ui/commit/b3fb54e28ca7b8eeda896b5bcf478b6343dbba47))
+* validate URL ([b7c994d](https://github.com/idosal/mcp-ui/commit/b7c994dfdd947b3dfbb903fc8cb896d61004c8d8))
+* wc dist overwrite ([#63](https://github.com/idosal/mcp-ui/issues/63)) ([9e46c56](https://github.com/idosal/mcp-ui/commit/9e46c56c7a8908410fad6d08a5d845139e93f80f))
+
+
+### Documentation
+
+* bump ([#4](https://github.com/idosal/mcp-ui/issues/4)) ([ad4d163](https://github.com/idosal/mcp-ui/commit/ad4d1632cc1f9c99072349a8f0cdaac343236132))
+
+
+### Features
+
+* add adapters infra (appssdk) ([#125](https://github.com/idosal/mcp-ui/issues/125)) ([2e016cd](https://github.com/idosal/mcp-ui/commit/2e016cdc05d08c2f7c2e4a40efbec2b0704e7ef6))
+* add convenience function isUIResource to client SDK ([#86](https://github.com/idosal/mcp-ui/issues/86)) ([607c6ad](https://github.com/idosal/mcp-ui/commit/607c6add3567bb60c45accf3e1b25a38ed284a6f))
+* add embeddedResourceProps for annotations ([#99](https://github.com/idosal/mcp-ui/issues/99)) ([b96ec44](https://github.com/idosal/mcp-ui/commit/b96ec442ec319a1944393ada0bdcccb93b7ffc62))
+* add proxy option to externalUrl ([#37](https://github.com/idosal/mcp-ui/issues/37)) ([7b95cd0](https://github.com/idosal/mcp-ui/commit/7b95cd0b3873fc1cde28748ec463e81c6ff1c494))
+* add remote-dom content type ([#18](https://github.com/idosal/mcp-ui/issues/18)) ([5dacf37](https://github.com/idosal/mcp-ui/commit/5dacf37c22b5ee6ae795049a8d573fc073b8a1f5))
+* add Ruby server SDK ([#31](https://github.com/idosal/mcp-ui/issues/31)) ([5ffcde4](https://github.com/idosal/mcp-ui/commit/5ffcde4a373accdd063fa6c3b1b3d4df13c91b53))
+* add sandbox permissions instead of an override ([#83](https://github.com/idosal/mcp-ui/issues/83)) ([b1068e9](https://github.com/idosal/mcp-ui/commit/b1068e9e87caa2b4302bf145a33efdfd1af05c1d))
+* add ui-request-render-data message type ([#111](https://github.com/idosal/mcp-ui/issues/111)) ([26135ce](https://github.com/idosal/mcp-ui/commit/26135ce2c7f7d586b0b81a03623cd77dc1bc7f90))
+* add UIResourceRenderer Web Component ([#58](https://github.com/idosal/mcp-ui/issues/58)) ([ec8f299](https://github.com/idosal/mcp-ui/commit/ec8f2994ecf36774e6ad5191654ba22946d0ee49))
+* auto resize with the autoResizeIframe prop ([#56](https://github.com/idosal/mcp-ui/issues/56)) ([76c867a](https://github.com/idosal/mcp-ui/commit/76c867a569b72aed892290aa84e1194ab8eb79ce))
+* change onGenericMcpAction to optional onUiAction ([1913b59](https://github.com/idosal/mcp-ui/commit/1913b5977c30811f9e67659949e2d961f2eda983))
+* **client:** allow setting supportedContentTypes for HtmlResource ([#17](https://github.com/idosal/mcp-ui/issues/17)) ([e009ef1](https://github.com/idosal/mcp-ui/commit/e009ef10010134ba3d9893314cc4d8e1274f1f07))
+* consolidate ui:// and ui-app:// ([#8](https://github.com/idosal/mcp-ui/issues/8)) ([2e08035](https://github.com/idosal/mcp-ui/commit/2e08035676bb6a46ef3c94dba916bc895f1fa3cc))
+* pass iframe props down ([#14](https://github.com/idosal/mcp-ui/issues/14)) ([112539d](https://github.com/idosal/mcp-ui/commit/112539d28640a96e8375a6b416f2ba559370b312))
+* refactor UTFtoB64 (bump server version) ([#95](https://github.com/idosal/mcp-ui/issues/95)) ([2d5e16b](https://github.com/idosal/mcp-ui/commit/2d5e16bf39073ee890586f458412f0c3b474c2b8))
+* send render data to the iframe ([#51](https://github.com/idosal/mcp-ui/issues/51)) ([d38cfc7](https://github.com/idosal/mcp-ui/commit/d38cfc7925061c1ae1911bdee408033c8e9f283d))
+* separate html and remote-dom props ([#24](https://github.com/idosal/mcp-ui/issues/24)) ([a7f0529](https://github.com/idosal/mcp-ui/commit/a7f05299dc9cc40184f9ab25c5b648ee7077be64))
+* support generic messages response ([#35](https://github.com/idosal/mcp-ui/issues/35)) ([10b407b](https://github.com/idosal/mcp-ui/commit/10b407b279b3ee9608ef077445f4d714f88343c5))
+* support passing resource metadata ([#87](https://github.com/idosal/mcp-ui/issues/87)) ([f1c1c9b](https://github.com/idosal/mcp-ui/commit/f1c1c9b62dd74c63045b295eb388181843ac772a))
+* support ui action result types ([#6](https://github.com/idosal/mcp-ui/issues/6)) ([899d152](https://github.com/idosal/mcp-ui/commit/899d1527286a281a23fbb8f3a207d435dfc3fe96))
+* switch to ResourceRenderer ([#21](https://github.com/idosal/mcp-ui/issues/21)) ([6fe3166](https://github.com/idosal/mcp-ui/commit/6fe316682675e27db914d60696754677e3783448))
+
+
+### BREAKING CHANGES
+
+* The existing naming is ambiguous. Renaming delivery to encoding and flavor to framework should clarify the intent.
+* exported names have changed
+* removed deprecated client API
+* (previous one didn't take due to semantic-release misalignment)
+
# [5.11.0](https://github.com/idosal/mcp-ui/compare/v5.10.0...v5.11.0) (2025-09-16)
diff --git a/sdks/typescript/server/README.md b/sdks/typescript/server/README.md
index b8ae03bc..bdaba089 100644
--- a/sdks/typescript/server/README.md
+++ b/sdks/typescript/server/README.md
@@ -39,7 +39,7 @@
## π‘ What's `mcp-ui`?
-`mcp-ui` is a collection of SDKs comprising:
+`mcp-ui` is a playground for the open spec of UI over MCP. It offers a collection of community SDKs comprising:
* **`@mcp-ui/server` (TypeScript)**: Utilities to generate UI resources (`UIResource`) on your MCP server.
* **`@mcp-ui/client` (TypeScript)**: UI components (e.g., ` `) to render the UI resources and handle their events.
@@ -143,6 +143,88 @@ Rendered using the internal ` ` component, which uti
UI snippets must be able to interact with the agent. In `mcp-ui`, this is done by hooking into events sent from the UI snippet and reacting to them in the host (see `onUIAction` prop). For example, an HTML may trigger a tool call when a button is clicked by sending an event which will be caught handled by the client.
+
+### Platform Adapters
+
+MCP-UI SDKs includes adapter support for host-specific implementations, enabling your open MCP-UI widgets to work seamlessly regardless of host. Adapters automatically translate between MCP-UI's `postMessage` protocol and host-specific APIs. Over time, as hosts become compatible with the open spec, these adapters wouldn't be needed.
+
+#### Available Adapters
+
+##### Apps SDK Adapter
+
+For Apps SDK environments (e.g., ChatGPT), this adapter translates MCP-UI protocol to Apps SDK API calls (e.g., `window.openai`).
+
+**How it Works:**
+- Intercepts MCP-UI `postMessage` calls from your widgets
+- Translates them to appropriate Apps SDK API calls
+- Handles bidirectional communication (tools, prompts, state management)
+- Works transparently - your existing MCP-UI code continues to work without changes
+
+**Usage:**
+
+```ts
+import { createUIResource } from '@mcp-ui/server';
+
+const htmlResource = createUIResource({
+ uri: 'ui://greeting/1',
+ content: {
+ type: 'rawHtml',
+ htmlString: `
+
+ Call Tool
+
+ `
+ },
+ encoding: 'text',
+ // Enable adapters
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: ...
+ }
+ // Future adapters can be enabled here
+ }
+});
+```
+
+The adapter scripts are automatically injected into your HTML content and handle all protocol translation.
+
+**Supported Actions:**
+- β
**Tool calls** - `{ type: 'tool', payload: { toolName, params } }`
+- β
**Prompts** - `{ type: 'prompt', payload: { prompt } }`
+- β
**Intents** - `{ type: 'intent', payload: { intent, params } }` (converted to prompts)
+- β
**Notifications** - `{ type: 'notify', payload: { message } }`
+- β
**Render data** - Access to `toolInput`, `toolOutput`, `widgetState`, `theme`, `locale`
+- β οΈ **Links** - `{ type: 'link', payload: { url } }` (may not be supported, returns error in some environments)
+
+#### Advanced Usage
+
+You can manually wrap HTML with adapters, get MIME types, or access adapter scripts directly:
+
+```ts
+import { wrapHtmlWithAdapters, getAdapterMimeType, getAppsSdkAdapterScript } from '@mcp-ui/server';
+
+const adaptersConfig = {
+ appsSdk: {
+ enabled: true,
+ config: { intentHandling: 'ignore' }
+ }
+};
+
+// Manually wrap HTML with adapters (returns string)
+const wrappedHtml = wrapHtmlWithAdapters(
+ 'Click me ',
+ adaptersConfig
+);
+
+// Get the MIME type for the enabled adapters
+const mimeType = getAdapterMimeType(adaptersConfig);
+// Returns: 'text/html+skybridge'
+
+// Get a specific adapter script directly
+const appsSdkScript = getAppsSdkAdapterScript({ timeout: 60000 });
+```
+
## ποΈ Installation
### TypeScript
diff --git a/sdks/typescript/server/package.json b/sdks/typescript/server/package.json
index d4f948fe..d5ee5051 100644
--- a/sdks/typescript/server/package.json
+++ b/sdks/typescript/server/package.json
@@ -1,17 +1,17 @@
{
"name": "@mcp-ui/server",
- "version": "5.11.0",
+ "version": "5.12.0-alpha.6",
"private": false,
"description": "mcp-ui Server SDK",
"type": "module",
- "main": "./dist/index.js",
+ "main": "./dist/index.cjs",
"module": "./dist/index.mjs",
- "types": "./dist/index.d.ts",
+ "types": "./dist/src/index.d.ts",
"exports": {
".": {
- "types": "./dist/index.d.ts",
+ "types": "./dist/src/index.d.ts",
"import": "./dist/index.mjs",
- "require": "./dist/index.js"
+ "require": "./dist/index.cjs"
}
},
"files": [
@@ -20,6 +20,7 @@
"devDependencies": {
"@types/node": "^18.19.100",
"@vitest/coverage-v8": "^1.0.0",
+ "esbuild": "^0.19.0",
"typescript": "^5.0.0",
"vite": "^5.0.0",
"vite-plugin-dts": "^3.6.0",
@@ -27,6 +28,8 @@
},
"scripts": {
"prepublishOnly": "pnpm run build",
+ "prebuild": "pnpm run bundle:adapter",
+ "bundle:adapter": "node scripts/bundle-adapter.js",
"dev": "vite",
"build": "vite build",
"test": "vitest run",
@@ -38,8 +41,13 @@
},
"release": {
"branches": [
- "main"
+ "main",
+ {
+ "name": "alpha",
+ "prerelease": true
+ }
],
+ "tagFormat": "server/v${version}",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
diff --git a/sdks/typescript/server/scripts/bundle-adapter.js b/sdks/typescript/server/scripts/bundle-adapter.js
new file mode 100644
index 00000000..3d86b01b
--- /dev/null
+++ b/sdks/typescript/server/scripts/bundle-adapter.js
@@ -0,0 +1,38 @@
+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);
+
+// Bundle the adapter runtime directly from the adapter-runtime.ts file
+try {
+ const result = await build({
+ entryPoints: [join(__dirname, '../src/adapters/appssdk/adapter-runtime.ts')],
+ bundle: true,
+ write: false,
+ format: 'iife',
+ platform: 'browser',
+ target: 'es2020',
+ minify: false, // Keep readable for debugging
+ });
+
+ const bundledCode = result.outputFiles[0].text;
+
+ // Write the bundled code to a TypeScript file using JSON serialization for safe escaping
+ const serializedCode = JSON.stringify(bundledCode);
+
+ const outputContent = `// This file is auto-generated by scripts/bundle-adapter.js
+// Do not edit directly - modify adapter-runtime.ts instead
+
+export const ADAPTER_RUNTIME_SCRIPT = ${serializedCode};
+`;
+
+ const outputTsPath = join(__dirname, '../src/adapters/appssdk/adapter-runtime.bundled.ts');
+ writeFileSync(outputTsPath, outputContent);
+ console.log('β
Successfully bundled Apps SDK adapter runtime');
+} catch (error) {
+ console.error('β Failed to bundle adapter runtime:', error);
+ process.exit(1);
+}
diff --git a/sdks/typescript/server/src/__tests__/adapters/adapter-integration.test.ts b/sdks/typescript/server/src/__tests__/adapters/adapter-integration.test.ts
new file mode 100644
index 00000000..d3f5cffb
--- /dev/null
+++ b/sdks/typescript/server/src/__tests__/adapters/adapter-integration.test.ts
@@ -0,0 +1,349 @@
+import { describe, it, expect } from 'vitest';
+import { createUIResource } from '../../index';
+import { wrapHtmlWithAdapters, getAdapterMimeType } from '../../utils';
+
+describe('Apps SDK Adapter Integration', () => {
+ describe('createUIResource with adapters', () => {
+ it('should create UI resource without adapter by default', () => {
+ const resource = createUIResource({
+ uri: 'ui://test',
+ content: {
+ type: 'rawHtml',
+ htmlString: 'Test
',
+ },
+ encoding: 'text',
+ });
+
+ expect(resource.resource.text).toBe('Test
');
+ expect(resource.resource.text).not.toContain('MCPUIAppsSdkAdapter');
+ });
+
+ it('should wrap HTML with Apps SDK adapter when enabled', () => {
+ const resource = createUIResource({
+ uri: 'ui://test',
+ content: {
+ type: 'rawHtml',
+ htmlString: 'Test
',
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ },
+ },
+ });
+
+ expect(resource.resource.text).toContain('');
+ expect(resource.resource.text).toContain('Test
');
+ });
+
+ it('should pass adapter config to the wrapper', () => {
+ const resource = createUIResource({
+ uri: 'ui://test',
+ content: {
+ type: 'rawHtml',
+ htmlString: 'Test
',
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ config: {
+ timeout: 5000,
+ intentHandling: 'ignore',
+ hostOrigin: 'https://custom.com',
+ },
+ },
+ },
+ });
+
+ const html = resource.resource.text as string;
+ expect(html).toContain('5000');
+ expect(html).toContain('ignore');
+ expect(html).toContain('https://custom.com');
+ });
+
+ it('should not wrap when adapter is disabled', () => {
+ const resource = createUIResource({
+ uri: 'ui://test',
+ content: {
+ type: 'rawHtml',
+ htmlString: 'Test
',
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: false,
+ },
+ },
+ });
+
+ expect(resource.resource.text).toBe('Test
');
+ });
+
+ it('should work with HTML containing head tag', () => {
+ const resource = createUIResource({
+ uri: 'ui://test',
+ content: {
+ type: 'rawHtml',
+ htmlString: 'Test Content',
+ },
+ encoding: 'text',
+ adapters: {
+ appsSdk: {
+ enabled: true,
+ },
+ },
+ });
+
+ const html = resource.resource.text as string;
+ expect(html).toContain('');
+ expect(html).toContain('');
+ expect(result).toContain(html);
+ });
+
+ it('should inject script in head tag if present', () => {
+ const html = 'Test
';
+ const result = wrapHtmlWithAdapters(html, {
+ appsSdk: {
+ enabled: true,
+ },
+ });
+
+ const headIndex = result.indexOf('');
+ const scriptIndex = result.indexOf('');
+ expect(script.trim().startsWith('')).toBe(true);
+ });
+
+ it('should include the bundled adapter code', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Check for key adapter components
+ expect(script).toContain('MCPUIAppsSdkAdapter');
+ expect(script).toContain('initAdapter');
+ expect(script).toContain('uninstallAdapter');
+ });
+
+ it('should inject default config when no config provided', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Should call initAdapter with empty config
+ expect(script).toContain('initAdapter({})');
+ });
+
+ it('should inject custom timeout config', () => {
+ const config: AppsSdkAdapterConfig = {
+ timeout: 5000,
+ };
+
+ const script = getAppsSdkAdapterScript(config);
+
+ expect(script).toContain('5000');
+ expect(script).toContain('"timeout":5000');
+ });
+
+ it('should inject custom intentHandling config', () => {
+ const config: AppsSdkAdapterConfig = {
+ intentHandling: 'ignore',
+ };
+
+ const script = getAppsSdkAdapterScript(config);
+
+ expect(script).toContain('ignore');
+ expect(script).toContain('"intentHandling":"ignore"');
+ });
+
+ it('should inject custom hostOrigin config', () => {
+ const config: AppsSdkAdapterConfig = {
+ hostOrigin: 'https://custom.com',
+ };
+
+ const script = getAppsSdkAdapterScript(config);
+
+ expect(script).toContain('https://custom.com');
+ expect(script).toContain('"hostOrigin":"https://custom.com"');
+ });
+
+ it('should inject multiple config options', () => {
+ const config: AppsSdkAdapterConfig = {
+ timeout: 10000,
+ intentHandling: 'prompt',
+ hostOrigin: 'https://test.example.com',
+ };
+
+ const script = getAppsSdkAdapterScript(config);
+
+ expect(script).toContain('10000');
+ expect(script).toContain('prompt');
+ expect(script).toContain('https://test.example.com');
+ });
+
+ it('should set MCP_APPSSDK_ADAPTER_NO_AUTO_INSTALL flag', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Should prevent the bundled code from auto-initializing
+ expect(script).toContain('MCP_APPSSDK_ADAPTER_NO_AUTO_INSTALL');
+ expect(script).toContain('window.MCP_APPSSDK_ADAPTER_NO_AUTO_INSTALL = true');
+ });
+
+ it('should expose global MCPUIAppsSdkAdapter API', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('window.MCPUIAppsSdkAdapter');
+ expect(script).toContain('init: initAdapter');
+ expect(script).toContain('uninstall: uninstallAdapter');
+ });
+
+ it('should check for window before initialization', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Should have window checks
+ expect(script).toContain("typeof window !== 'undefined'");
+ });
+
+ it('should be wrapped in IIFE', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Should be wrapped in a function to avoid global pollution
+ expect(script).toContain('(function()');
+ expect(script).toContain('})()');
+ });
+
+ it('should include use strict directive', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain("'use strict'");
+ });
+
+ it('should contain core adapter functionality keywords', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Check for essential adapter components
+ expect(script).toContain('postMessage');
+ expect(script).toContain('window.openai');
+ expect(script).toContain('handleMCPUIMessage');
+ });
+
+ it('should support tool calling', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('callTool');
+ expect(script).toContain('tool');
+ });
+
+ it('should support prompt sending', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('sendFollowUpMessage');
+ expect(script).toContain('prompt');
+ });
+
+ it('should handle widget state', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('widgetState');
+ // widgetState is read from Apps SDK
+ });
+
+ it('should handle render data', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('renderData');
+ expect(script).toContain('toolInput');
+ expect(script).toContain('toolOutput');
+ });
+
+ it('should handle lifecycle messages', () => {
+ const script = getAppsSdkAdapterScript();
+
+ expect(script).toContain('ui-lifecycle');
+ expect(script).toContain('ui-request');
+ });
+
+ it('should properly escape JSON in config', () => {
+ const config: AppsSdkAdapterConfig = {
+ hostOrigin: 'https://example.com/"test"',
+ };
+
+ // Should not throw and should properly escape quotes
+ expect(() => getAppsSdkAdapterScript(config)).not.toThrow();
+
+ const script = getAppsSdkAdapterScript(config);
+ // The JSON.stringify should handle escaping
+ expect(script).toContain('\\"test\\"');
+ });
+ });
+
+ describe('Type Definitions', () => {
+ it('should accept valid config types', () => {
+ const validConfigs: AppsSdkAdapterConfig[] = [
+ {},
+ { timeout: 5000 },
+ { intentHandling: 'prompt' },
+ { intentHandling: 'ignore' },
+ { hostOrigin: 'https://example.com' },
+ {
+ timeout: 10000,
+ intentHandling: 'ignore',
+ hostOrigin: 'https://test.com',
+ },
+ ];
+
+ for (const config of validConfigs) {
+ expect(() => getAppsSdkAdapterScript(config)).not.toThrow();
+ }
+ });
+ });
+
+ describe('Script Size', () => {
+ it('should generate a reasonably sized script', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Script should be present but not excessively large
+ expect(script.length).toBeGreaterThan(100);
+ expect(script.length).toBeLessThan(50000); // ~50KB max
+ });
+
+ it('should not significantly grow with config', () => {
+ const baseScript = getAppsSdkAdapterScript();
+ const configuredScript = getAppsSdkAdapterScript({
+ timeout: 10000,
+ intentHandling: 'ignore',
+ hostOrigin: 'https://example.com',
+ });
+
+ // Config should only add a small amount to script size
+ const sizeDiff = configuredScript.length - baseScript.length;
+ expect(sizeDiff).toBeLessThan(200);
+ });
+ });
+
+ describe('Script Validity', () => {
+ it('should generate syntactically valid JavaScript', () => {
+ const script = getAppsSdkAdapterScript();
+
+ // Extract just the JavaScript code (remove
+`.trim();
+}
diff --git a/sdks/typescript/server/src/adapters/appssdk/index.ts b/sdks/typescript/server/src/adapters/appssdk/index.ts
new file mode 100644
index 00000000..0eba3d29
--- /dev/null
+++ b/sdks/typescript/server/src/adapters/appssdk/index.ts
@@ -0,0 +1,14 @@
+/**
+ * Apps SDK Adapter for MCP-UI
+ *
+ * Enables MCP-UI widgets to work in Apps SDK environments (e.g., ChatGPT)
+ */
+
+export { getAppsSdkAdapterScript } from './adapter.js';
+export type {
+ AppsSdkAdapterConfig,
+ AppsSdkBridge,
+ RenderData,
+ MCPUIMessage,
+} from './types.js';
+
diff --git a/sdks/typescript/server/src/adapters/appssdk/types.ts b/sdks/typescript/server/src/adapters/appssdk/types.ts
new file mode 100644
index 00000000..5a8244fd
--- /dev/null
+++ b/sdks/typescript/server/src/adapters/appssdk/types.ts
@@ -0,0 +1,171 @@
+/**
+ * Type definitions for the Apps SDK adapter
+ */
+
+import type { UIActionResult } from '../../types.js';
+
+/**
+ * Additional MCP-UI Protocol Messages (Lifecycle & Control)
+ */
+
+export interface MCPUILifecycleReadyMessage {
+ type: 'ui-lifecycle-iframe-ready';
+ messageId?: string;
+ payload?: Record;
+}
+
+export interface MCPUISizeChangeMessage {
+ type: 'ui-size-change';
+ messageId?: string;
+ payload: {
+ width?: number;
+ height?: number;
+ };
+}
+
+export interface MCPUIRequestDataMessage {
+ type: 'ui-request-data';
+ messageId: string;
+ payload: {
+ requestType: string;
+ params?: Record;
+ };
+}
+
+export interface MCPUIRequestRenderDataMessage {
+ type: 'ui-request-render-data';
+ messageId?: string;
+ payload?: Record;
+}
+
+export interface MCPUIRenderDataMessage {
+ type: 'ui-lifecycle-iframe-render-data';
+ messageId?: string;
+ payload: {
+ renderData: RenderData;
+ };
+}
+
+export interface MCPUIMessageReceivedMessage {
+ type: 'ui-message-received';
+ messageId?: string;
+ payload: {
+ messageId: string;
+ };
+}
+
+export interface MCPUIMessageResponseMessage {
+ type: 'ui-message-response';
+ messageId?: string;
+ payload: {
+ messageId: string;
+ response?: unknown;
+ error?: unknown;
+ };
+}
+
+export interface RenderData {
+ toolInput?: Record;
+ toolOutput?: unknown;
+ widgetState?: unknown;
+ locale?: string;
+ theme?: string;
+ displayMode?: 'inline' | 'pip' | 'fullscreen';
+ maxHeight?: number;
+ [key: string]: unknown;
+}
+
+export type MCPUIMessage =
+ | UIActionResult
+ | MCPUILifecycleReadyMessage
+ | MCPUISizeChangeMessage
+ | MCPUIRequestDataMessage
+ | MCPUIRequestRenderDataMessage
+ | MCPUIRenderDataMessage
+ | MCPUIMessageReceivedMessage
+ | MCPUIMessageResponseMessage;
+
+/**
+ * Apps SDK Protocol Types (e.g., ChatGPT window.openai interface)
+ */
+
+export interface AppsSdkBridge {
+ toolInput: Record;
+ toolOutput: unknown;
+ widgetState: unknown;
+ setWidgetState(state: unknown): Promise;
+ callTool(name: string, args: Record): Promise;
+ sendFollowUpMessage(params: { prompt: string }): Promise;
+ requestDisplayMode(params: { mode: 'inline' | 'pip' | 'fullscreen' }): Promise;
+ maxHeight?: number;
+ displayMode?: 'inline' | 'pip' | 'fullscreen';
+ locale?: string;
+ theme?: string;
+}
+
+export interface AppsSdkSetGlobalsEventDetail {
+ displayMode?: 'inline' | 'pip' | 'fullscreen';
+ maxHeight?: number;
+ toolOutput?: unknown;
+ widgetState?: unknown;
+ locale?: string;
+ theme?: string;
+}
+
+export interface AppsSdkToolResponseEventDetail {
+ name: string;
+ args: Record;
+ result: unknown;
+}
+
+/**
+ * Apps SDK Adapter Configuration
+ */
+
+export interface AppsSdkAdapterConfig {
+ /**
+ * Custom logger (defaults to console)
+ */
+ logger?: Pick;
+
+ /**
+ * Origin to use when dispatching MessageEvents to the iframe (defaults to window.location.origin)
+ * This simulates the origin of the host/parent window
+ */
+ hostOrigin?: string;
+
+ /**
+ * Timeout in milliseconds for async operations (defaults to 30000)
+ */
+ timeout?: number;
+
+ /**
+ * How to handle 'intent' messages (defaults to 'prompt')
+ * - 'prompt': Convert to sendFollowupTurn with intent description
+ * - 'ignore': Log and acknowledge but take no action
+ */
+ intentHandling?: 'prompt' | 'ignore';
+}
+
+/**
+ * Internal adapter state
+ */
+
+export interface PendingRequest {
+ messageId: string;
+ type: string;
+ resolve: (value: T | PromiseLike) => void;
+ reject: (error: unknown) => void;
+ timeoutId: ReturnType;
+}
+
+/**
+ * Window extension for Apps SDK environment (e.g., window.openai in ChatGPT)
+ */
+
+declare global {
+ interface Window {
+ openai?: AppsSdkBridge;
+ }
+}
+
diff --git a/sdks/typescript/server/src/adapters/index.ts b/sdks/typescript/server/src/adapters/index.ts
new file mode 100644
index 00000000..647aa7f3
--- /dev/null
+++ b/sdks/typescript/server/src/adapters/index.ts
@@ -0,0 +1,14 @@
+/**
+ * MCP-UI Adapters
+ *
+ * Adapters enable MCP-UI widgets to work in host-specific environments by translating
+ * the open MCP-UI protocol to platform-specific APIs.
+ *
+ * Available adapters:
+ * - appsSdk: For Apps SDK environments (e.g., ChatGPT)
+ *
+ * Future adapters could include other platforms as needed.
+ */
+
+export * from './appssdk/index.js';
+
diff --git a/sdks/typescript/server/src/index.ts b/sdks/typescript/server/src/index.ts
index b567279d..ab3b215e 100644
--- a/sdks/typescript/server/src/index.ts
+++ b/sdks/typescript/server/src/index.ts
@@ -10,7 +10,7 @@ import {
UIActionResultIntent,
UIActionResultToolCall,
} from './types.js';
-import { getAdditionalResourceProps, utf8ToBase64 } from './utils.js';
+import { getAdditionalResourceProps, utf8ToBase64, wrapHtmlWithAdapters, getAdapterMimeType } from './utils.js';
export type UIResource = {
type: 'resource';
@@ -39,7 +39,15 @@ export function createUIResource(options: CreateUIResourceOptions): UIResource {
"MCP-UI SDK: content.htmlString must be provided as a string when content.type is 'rawHtml'.",
);
}
- mimeType = 'text/html';
+
+ // Wrap with adapters if any are enabled
+ if (options.adapters) {
+ actualContentString = wrapHtmlWithAdapters(actualContentString, options.adapters);
+ // Use adapter's mime type if provided, otherwise fall back to 'text/html'
+ mimeType = (getAdapterMimeType(options.adapters) as MimeType) ?? 'text/html';
+ } else {
+ mimeType = 'text/html';
+ }
} else if (options.content.type === 'externalUrl') {
if (!options.uri.startsWith('ui://')) {
throw new Error(
@@ -102,7 +110,17 @@ export function createUIResource(options: CreateUIResourceOptions): UIResource {
};
}
-export type { CreateUIResourceOptions, ResourceContentPayload, UIActionResult } from './types.js';
+export type {
+ CreateUIResourceOptions,
+ ResourceContentPayload,
+ UIActionResult,
+ AdaptersConfig,
+ AppsSdkAdapterOptions,
+} from './types.js';
+
+// Export adapters
+export { wrapHtmlWithAdapters, getAdapterMimeType } from './utils.js';
+export * from './adapters/index.js';
export function postUIActionResult(result: UIActionResult): void {
if (window.parent) {
diff --git a/sdks/typescript/server/src/types.ts b/sdks/typescript/server/src/types.ts
index db875328..1bf70ea4 100644
--- a/sdks/typescript/server/src/types.ts
+++ b/sdks/typescript/server/src/types.ts
@@ -6,6 +6,7 @@ export type URI = `ui://${string}`;
// text/html for rawHtml content, text/uri-list for externalUrl content
export type MimeType =
| 'text/html'
+ | 'text/html+skybridge'
| 'text/uri-list'
| 'application/vnd.mcp-ui.remote-dom+javascript; framework=react'
| 'application/vnd.mcp-ui.remote-dom+javascript; framework=webcomponents';
@@ -47,6 +48,64 @@ export interface CreateUIResourceOptions {
resourceProps?: UIResourceProps;
// additional resource props to be passed on the top-level embedded resource (i.e. annotations)
embeddedResourceProps?: EmbeddedUIResourceProps;
+ // Adapters for different environments (e.g., Apps SDK)
+ adapters?: AdaptersConfig;
+}
+
+/**
+ * Configuration for all available adapters
+ * Adapters enable MCP-UI widgets to work in different environments
+ */
+export interface AdaptersConfig {
+ /**
+ * Apps SDK adapter (e.g., ChatGPT)
+ * Translates MCP-UI protocol to Apps SDK API calls (window.openai)
+ */
+ appsSdk?: AppsSdkAdapterOptions;
+
+ // Future adapters can be added here
+ // e.g., anotherPlatform?: AnotherPlatformAdapterOptions;
+}
+
+/**
+ * Configuration options for Apps SDK adapter
+ */
+export interface AppsSdkAdapterOptions {
+ /**
+ * Whether to enable the Apps SDK adapter.
+ * When enabled, the adapter script will be automatically injected into HTML content,
+ * allowing MCP-UI widgets to work in Apps SDK environments (e.g., ChatGPT).
+ * @default false
+ */
+ enabled: boolean;
+
+ /**
+ * Custom configuration for the adapter
+ */
+ config?: {
+ /**
+ * How to handle 'intent' messages (defaults to 'prompt')
+ * - 'prompt': Convert to sendFollowupTurn with intent description
+ * - 'ignore': Log and acknowledge but take no action
+ */
+ intentHandling?: 'prompt' | 'ignore';
+
+ /**
+ * Timeout in milliseconds for async operations (defaults to 30000)
+ */
+ timeout?: number;
+
+ /**
+ * Origin to use when dispatching MessageEvents to the iframe (defaults to window.location.origin)
+ */
+ hostOrigin?: string;
+ };
+
+ /**
+ * MIME type to use when this adapter is enabled.
+ * @default 'text/html+skybridge'
+ */
+ mimeType?: string;
}
export type UIResourceProps = Omit, 'uri' | 'mimeType'>;
diff --git a/sdks/typescript/server/src/utils.ts b/sdks/typescript/server/src/utils.ts
index ee80237a..4c96f06c 100644
--- a/sdks/typescript/server/src/utils.ts
+++ b/sdks/typescript/server/src/utils.ts
@@ -1,5 +1,6 @@
-import type { CreateUIResourceOptions, UIResourceProps } from './types.js';
+import type { CreateUIResourceOptions, UIResourceProps, AdaptersConfig } from './types.js';
import { UI_METADATA_PREFIX } from './types.js';
+import { getAppsSdkAdapterScript } from './adapters/appssdk/adapter.js';
export function getAdditionalResourceProps(
resourceOptions: Partial,
@@ -60,3 +61,76 @@ export function utf8ToBase64(str: string): string {
}
}
}
+
+/**
+ * Determines the MIME type based on enabled adapters.
+ *
+ * @param adaptersConfig - Configuration for all adapters
+ * @returns The MIME type to use, or undefined if no adapters are enabled
+ */
+export function getAdapterMimeType(adaptersConfig?: AdaptersConfig): string | undefined {
+ if (!adaptersConfig) {
+ return undefined;
+ }
+
+ // Apps SDK adapter
+ if (adaptersConfig.appsSdk?.enabled) {
+ return adaptersConfig.appsSdk.mimeType ?? 'text/html+skybridge';
+ }
+
+ // Future adapters can be added here by checking for their config and returning their mime type.
+
+ return undefined;
+}
+
+/**
+ * Wraps HTML content with enabled adapter scripts.
+ * This allows the HTML to communicate with different platform environments.
+ *
+ * @param htmlContent - The HTML content to wrap
+ * @param adaptersConfig - Configuration for all adapters
+ * @returns The wrapped HTML content with adapter scripts injected
+ */
+export function wrapHtmlWithAdapters(
+ htmlContent: string,
+ adaptersConfig?: AdaptersConfig,
+): string {
+ if (!adaptersConfig) {
+ return htmlContent;
+ }
+
+ const adapterScripts: string[] = [];
+
+ // Apps SDK adapter
+ if (adaptersConfig.appsSdk?.enabled) {
+ const script = getAppsSdkAdapterScript(adaptersConfig.appsSdk.config);
+ adapterScripts.push(script);
+ }
+
+ // Future adapters can be added here by checking for their config and pushing their scripts to adapterScripts.
+
+ // If no adapters are enabled, return original HTML
+ if (adapterScripts.length === 0) {
+ return htmlContent;
+ }
+
+ // Combine all adapter scripts
+ const combinedScripts = adapterScripts.join('\n');
+
+ let finalHtmlContent: string;
+
+ // If the HTML already has a tag, inject the adapter scripts into it
+ if (htmlContent.includes('')) {
+ finalHtmlContent = htmlContent.replace('', `\n${combinedScripts}`);
+ }
+ // If the HTML has an tag but no , add a with the adapter scripts
+ else if (htmlContent.includes('')) {
+ finalHtmlContent = htmlContent.replace('', `\n\n${combinedScripts}\n`);
+ }
+ // Otherwise, prepend the adapter scripts before the content
+ else {
+ finalHtmlContent = `${combinedScripts}\n${htmlContent}`;
+ }
+
+ return finalHtmlContent;
+}
diff --git a/sdks/typescript/server/vite.config.ts b/sdks/typescript/server/vite.config.ts
index 6d0d5e5b..2b8b7ebe 100644
--- a/sdks/typescript/server/vite.config.ts
+++ b/sdks/typescript/server/vite.config.ts
@@ -7,7 +7,7 @@ export default defineConfig({
plugins: [
react(),
dts({
- insertTypesEntry: true,
+ insertTypesEntry: false,
tsconfigPath: path.resolve(__dirname, 'tsconfig.json'),
exclude: ['**/__tests__/**', '**/*.test.ts', '**/*.spec.ts'],
}),
diff --git a/sdks/typescript/server/vitest.config.ts b/sdks/typescript/server/vitest.config.ts
index 8e730d50..0d2c502f 100644
--- a/sdks/typescript/server/vitest.config.ts
+++ b/sdks/typescript/server/vitest.config.ts
@@ -1,8 +1,14 @@
import { defineConfig } from 'vitest/config';
+import { fileURLToPath } from 'url';
+import { dirname, join } from 'path';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
export default defineConfig({
test: {
globals: true,
environment: 'node',
+ globalSetup: join(__dirname, '../../../vitest.global-setup.ts'),
},
});
diff --git a/vitest.config.ts b/vitest.config.ts
index 13b8c1c0..7b1ea708 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -5,6 +5,7 @@ export default defineConfig({
globals: true, // Use global APIs (describe, it, expect)
environment: 'jsdom', // Default environment, can be overridden per package/file
setupFiles: './vitest.setup.ts',
+ globalSetup: './vitest.global-setup.ts',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
diff --git a/vitest.global-setup.ts b/vitest.global-setup.ts
new file mode 100644
index 00000000..d749f8d7
--- /dev/null
+++ b/vitest.global-setup.ts
@@ -0,0 +1,28 @@
+import { existsSync } from 'node:fs';
+import { spawnSync } from 'node:child_process';
+import { dirname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+export default async function globalSetup(): Promise {
+ const rootDir = dirname(fileURLToPath(import.meta.url));
+ const serverSdkDir = join(rootDir, 'sdks', 'typescript', 'server');
+ const bundlePath = join(serverSdkDir, 'src', 'adapters', 'appssdk', 'adapter-runtime.bundled.ts');
+
+ if (existsSync(bundlePath)) {
+ return;
+ }
+
+ const result = spawnSync(process.execPath, ['scripts/bundle-adapter.js'], {
+ cwd: serverSdkDir,
+ stdio: 'inherit',
+ });
+
+ if (result.error) {
+ throw result.error;
+ }
+
+ if (result.status !== 0) {
+ throw new Error(`Bundling Apps SDK adapter runtime failed with exit code ${result.status ?? 'unknown'}.`);
+ }
+}
+