Fix build errors in examples (#180)

* Update `package.json`

* Add TypeScript type checking to example build scripts

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 <noreply@anthropic.com>

* Make `_meta` optional in `McpUiAppResourceConfig`

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 <noreply@anthropic.com>

* Fix Zod type compatibility in `registerAppTool()`

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 <noreply@anthropic.com>

* Remove unused imports in example apps

- `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 <noreply@anthropic.com>

* Fix CI git install test for fork PRs

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 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2025-12-18 05:17:23 -06:00 • committed by GitHub
commit 4ff22d0097
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 41 additions and 21 deletions

View file

@ -144,7 +144,7 @@ jobs:
mkdir test-project mkdir test-project
cd test-project cd test-project
npm init -y npm init -y
# Install from the PR branch # Install from the PR branch (use head repo for fork PRs)
npm install "git+https://github.com/${{ github.repository }}#${{ github.head_ref || github.ref_name }}" 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) # Verify the package is usable (ESM import)
node --input-type=module -e "import { App } from '@modelcontextprotocol/ext-apps'; console.log('Import successful:', typeof App)" node --input-type=module -e "import { App } from '@modelcontextprotocol/ext-apps'; console.log('Import successful:', typeof App)"

View file

@ -4,7 +4,7 @@
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
"scripts": { "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\"", "watch": "concurrently \"cross-env INPUT=index.html vite build --watch\" \"cross-env INPUT=sandbox.html vite build --watch\"",
"serve": "bun serve.ts", "serve": "bun serve.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts", "serve": "bun server.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",

View file

@ -1,7 +1,7 @@
/** /**
* @file App that demonstrates a few features using MCP Apps SDK + React. * @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 { useApp } from "@modelcontextprotocol/ext-apps/react";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { StrictMode, useCallback, useEffect, useState } from "react"; import { StrictMode, useCallback, useEffect, useState } from "react";

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts", "serve": "bun server.ts",
"start": "cross-env NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -3,7 +3,6 @@
*/ */
import { import {
App, App,
PostMessageTransport,
applyHostStyleVariables, applyHostStyleVariables,
applyHostFonts, applyHostFonts,
applyDocumentTheme, applyDocumentTheme,

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

View file

@ -4,7 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "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", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",

14
package-lock.json generated
View file

@ -494,6 +494,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5", "@babel/generator": "^7.28.5",
@ -2099,6 +2100,7 @@
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
@ -2123,6 +2125,7 @@
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.2.2" "csstype": "^3.2.2"
} }
@ -2623,6 +2626,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.9.0", "baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759", "caniuse-lite": "^1.0.30001759",
@ -3338,6 +3342,7 @@
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
} }
@ -3785,6 +3790,7 @@
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"accepts": "^2.0.0", "accepts": "^2.0.0",
"body-parser": "^2.2.1", "body-parser": "^2.2.1",
@ -5316,6 +5322,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz",
"integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -5414,6 +5421,7 @@
"integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@types/estree": "1.0.8" "@types/estree": "1.0.8"
}, },
@ -6184,6 +6192,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -6933,6 +6942,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -7026,6 +7036,7 @@
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4", "fdir": "^6.4.4",
@ -7159,6 +7170,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -7411,6 +7423,7 @@
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"peer": true,
"bin": { "bin": {
"yaml": "bin.mjs" "yaml": "bin.mjs"
}, },
@ -7455,6 +7468,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==", "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
"license": "MIT", "license": "MIT",
"peer": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }

View file

@ -16,8 +16,11 @@ import type {
ToolCallback, ToolCallback,
ReadResourceCallback, ReadResourceCallback,
} from "@modelcontextprotocol/sdk/server/mcp.js"; } 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 { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
import type { ZodRawShape } from "zod";
// Re-exports for convenience // Re-exports for convenience
export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE }; export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE };
@ -29,7 +32,7 @@ export type { ResourceMetadata, ToolCallback, ReadResourceCallback };
export interface ToolConfig { export interface ToolConfig {
title?: string; title?: string;
description?: string; description?: string;
inputSchema?: ZodRawShape; inputSchema?: ZodRawShapeCompat | AnySchema;
annotations?: ToolAnnotations; annotations?: ToolAnnotations;
_meta?: Record<string, unknown>; _meta?: Record<string, unknown>;
} }
@ -62,8 +65,8 @@ export interface McpUiAppToolConfig extends ToolConfig {
* MCP App Resource configuration for `registerAppResource`. * MCP App Resource configuration for `registerAppResource`.
*/ */
export interface McpUiAppResourceConfig extends ResourceMetadata { export interface McpUiAppResourceConfig extends ResourceMetadata {
_meta: { _meta?: {
ui: McpUiResourceMeta; ui?: McpUiResourceMeta;
[key: string]: unknown; [key: string]: unknown;
}; };
} }
@ -96,11 +99,15 @@ export interface McpUiAppResourceConfig extends ResourceMetadata {
* }); * });
* ``` * ```
*/ */
export function registerAppTool( export function registerAppTool<
TInputSchema extends ZodRawShapeCompat | AnySchema | undefined = undefined,
>(
server: Pick<McpServer, "registerTool">, server: Pick<McpServer, "registerTool">,
name: string, name: string,
config: McpUiAppToolConfig, config: Omit<McpUiAppToolConfig, "inputSchema"> & {
handler: ToolCallback<ZodRawShape>, inputSchema?: TInputSchema;
},
handler: ToolCallback<TInputSchema>,
): void { ): void {
// Normalize metadata for backward compatibility: // Normalize metadata for backward compatibility:
// - If _meta.ui.resourceUri is set, also set the legacy flat key // - If _meta.ui.resourceUri is set, also set the legacy flat key