From deedddc08e5559d7392e15f909851744a1701a5a Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 18:44:39 -0600 Subject: [PATCH 1/6] Update `package.json` --- package-lock.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/package-lock.json b/package-lock.json index 1014b6ef0..5431ecd05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -494,6 +494,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2099,6 +2100,7 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -2123,6 +2125,7 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2623,6 +2626,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3338,6 +3342,7 @@ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "dev": true, "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3785,6 +3790,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -5316,6 +5322,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5414,6 +5421,7 @@ "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -6184,6 +6192,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6933,6 +6942,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7026,6 +7036,7 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -7159,6 +7170,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7411,6 +7423,7 @@ "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, "license": "ISC", + "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -7455,6 +7468,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz", "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } From 3db823ab28d6eabbea77d1cdfaf21d0e58ca2606 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 19:07:03 -0600 Subject: [PATCH 2/6] Add TypeScript type checking to example build scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `tsc --noEmit &&` before `vite build` in all example `package.json` files to catch type errors during builds. Previously, type errors in `server.ts` files were not detected because Vite/Bun transpile without type checking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- examples/basic-host/package.json | 2 +- examples/basic-server-react/package.json | 2 +- examples/basic-server-vanillajs/package.json | 2 +- examples/budget-allocator-server/package.json | 2 +- examples/cohort-heatmap-server/package.json | 2 +- examples/customer-segmentation-server/package.json | 2 +- examples/scenario-modeler-server/package.json | 2 +- examples/system-monitor-server/package.json | 2 +- examples/threejs-server/package.json | 2 +- examples/wiki-explorer-server/package.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/basic-host/package.json b/examples/basic-host/package.json index c20444d89..78cf826f4 100644 --- a/examples/basic-host/package.json +++ b/examples/basic-host/package.json @@ -4,7 +4,7 @@ "version": "1.0.0", "type": "module", "scripts": { - "build": "concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"", + "build": "tsc --noEmit && concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"", "watch": "concurrently \"cross-env INPUT=index.html vite build --watch\" \"cross-env INPUT=sandbox.html vite build --watch\"", "serve": "bun serve.ts", "start": "cross-env NODE_ENV=development npm run build && npm run serve", diff --git a/examples/basic-server-react/package.json b/examples/basic-server-react/package.json index c3738d5c5..5927040cd 100644 --- a/examples/basic-server-react/package.json +++ b/examples/basic-server-react/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun server.ts", "start": "cross-env NODE_ENV=development npm run build && npm run serve", diff --git a/examples/basic-server-vanillajs/package.json b/examples/basic-server-vanillajs/package.json index a6fba880e..5bc5a71c0 100644 --- a/examples/basic-server-vanillajs/package.json +++ b/examples/basic-server-vanillajs/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve": "bun server.ts", "start": "cross-env NODE_ENV=development npm run build && npm run serve", diff --git a/examples/budget-allocator-server/package.json b/examples/budget-allocator-server/package.json index e716944f9..86a951004 100644 --- a/examples/budget-allocator-server/package.json +++ b/examples/budget-allocator-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/cohort-heatmap-server/package.json b/examples/cohort-heatmap-server/package.json index dad6b7ff9..aff800021 100644 --- a/examples/cohort-heatmap-server/package.json +++ b/examples/cohort-heatmap-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/customer-segmentation-server/package.json b/examples/customer-segmentation-server/package.json index 738e86db5..b8b7f197a 100644 --- a/examples/customer-segmentation-server/package.json +++ b/examples/customer-segmentation-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/scenario-modeler-server/package.json b/examples/scenario-modeler-server/package.json index 6bf2b7c5f..95c13fc15 100644 --- a/examples/scenario-modeler-server/package.json +++ b/examples/scenario-modeler-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/system-monitor-server/package.json b/examples/system-monitor-server/package.json index 8e84c9457..6adfbb913 100644 --- a/examples/system-monitor-server/package.json +++ b/examples/system-monitor-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/threejs-server/package.json b/examples/threejs-server/package.json index e59e58863..bdc00f554 100644 --- a/examples/threejs-server/package.json +++ b/examples/threejs-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", diff --git a/examples/wiki-explorer-server/package.json b/examples/wiki-explorer-server/package.json index 95edd6cdf..5c389c317 100644 --- a/examples/wiki-explorer-server/package.json +++ b/examples/wiki-explorer-server/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "cross-env INPUT=mcp-app.html vite build", + "build": "tsc --noEmit && cross-env INPUT=mcp-app.html vite build", "watch": "cross-env INPUT=mcp-app.html vite build --watch", "serve:http": "bun server.ts", "serve:stdio": "bun server.ts --stdio", From 876f62f38700129675ec6970f2c368d34d85a712 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 19:12:19 -0600 Subject: [PATCH 3/6] Make `_meta` optional in `McpUiAppResourceConfig` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `_meta` and `ui` properties were required, causing TypeScript errors when calling `registerAppResource()` without providing metadata. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/server/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/index.ts b/src/server/index.ts index 2191a72f9..ca29a94f4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -62,8 +62,8 @@ export interface McpUiAppToolConfig extends ToolConfig { * MCP App Resource configuration for `registerAppResource`. */ export interface McpUiAppResourceConfig extends ResourceMetadata { - _meta: { - ui: McpUiResourceMeta; + _meta?: { + ui?: McpUiResourceMeta; [key: string]: unknown; }; } From 98644e453335fc4ffc3c2369dcd18de15bcb6434 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 20:04:35 -0600 Subject: [PATCH 4/6] Fix Zod type compatibility in `registerAppTool()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use `ZodRawShapeCompat | AnySchema` from SDK's `zod-compat` module instead of raw `ZodRawShape` to resolve type errors when examples pass `ZodObject` schemas to `registerAppTool()`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/server/index.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/server/index.ts b/src/server/index.ts index ca29a94f4..720cf6584 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -16,8 +16,11 @@ import type { ToolCallback, ReadResourceCallback, } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { + AnySchema, + ZodRawShapeCompat, +} from "@modelcontextprotocol/sdk/server/zod-compat.js"; import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js"; -import type { ZodRawShape } from "zod"; // Re-exports for convenience export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE }; @@ -29,7 +32,7 @@ export type { ResourceMetadata, ToolCallback, ReadResourceCallback }; export interface ToolConfig { title?: string; description?: string; - inputSchema?: ZodRawShape; + inputSchema?: ZodRawShapeCompat | AnySchema; annotations?: ToolAnnotations; _meta?: Record; } @@ -96,11 +99,15 @@ export interface McpUiAppResourceConfig extends ResourceMetadata { * }); * ``` */ -export function registerAppTool( +export function registerAppTool< + TInputSchema extends ZodRawShapeCompat | AnySchema | undefined = undefined, +>( server: Pick, name: string, - config: McpUiAppToolConfig, - handler: ToolCallback, + config: Omit & { + inputSchema?: TInputSchema; + }, + handler: ToolCallback, ): void { // Normalize metadata for backward compatibility: // - If _meta.ui.resourceUri is set, also set the legacy flat key From 0b8ec0e0e1a55a90033531d4f96fb4f228b942d4 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 20:07:04 -0600 Subject: [PATCH 5/6] Remove unused imports in example apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `basic-server-react`: Remove unused `McpUiResourceTeardownResult` - `customer-segmentation-server`: Remove unused `PostMessageTransport` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- examples/basic-server-react/src/mcp-app.tsx | 2 +- examples/customer-segmentation-server/src/mcp-app.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/basic-server-react/src/mcp-app.tsx b/examples/basic-server-react/src/mcp-app.tsx index 80fd38171..c250b8fa0 100644 --- a/examples/basic-server-react/src/mcp-app.tsx +++ b/examples/basic-server-react/src/mcp-app.tsx @@ -1,7 +1,7 @@ /** * @file App that demonstrates a few features using MCP Apps SDK + React. */ -import type { App, McpUiResourceTeardownResult } from "@modelcontextprotocol/ext-apps"; +import type { App } from "@modelcontextprotocol/ext-apps"; import { useApp } from "@modelcontextprotocol/ext-apps/react"; import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { StrictMode, useCallback, useEffect, useState } from "react"; diff --git a/examples/customer-segmentation-server/src/mcp-app.ts b/examples/customer-segmentation-server/src/mcp-app.ts index 2b12eacd3..5feb91003 100644 --- a/examples/customer-segmentation-server/src/mcp-app.ts +++ b/examples/customer-segmentation-server/src/mcp-app.ts @@ -3,7 +3,6 @@ */ import { App, - PostMessageTransport, applyHostStyleVariables, applyHostFonts, applyDocumentTheme, From a9b6ac75c102ec3940e95108433aa399d492a008 Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 17 Dec 2025 20:23:16 -0600 Subject: [PATCH 6/6] Fix CI git install test for fork PRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use `github.event.pull_request.head.repo.full_name` to correctly reference the fork repository when testing git installs from PRs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be0db8ab2..70ee9333a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -144,7 +144,7 @@ jobs: mkdir test-project cd test-project npm init -y - # Install from the PR branch - npm install "git+https://github.com/${{ github.repository }}#${{ github.head_ref || github.ref_name }}" + # Install from the PR branch (use head repo for fork PRs) + npm install "git+https://github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}#${{ github.head_ref || github.ref_name }}" # Verify the package is usable (ESM import) node --input-type=module -e "import { App } from '@modelcontextprotocol/ext-apps'; console.log('Import successful:', typeof App)"