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
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)"

View file

@ -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",

View file

@ -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",

View file

@ -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";

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

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

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

14
package-lock.json generated
View file

@ -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"
}

View file

@ -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<string, unknown>;
}
@ -62,8 +65,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;
};
}
@ -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">,
name: string,
config: McpUiAppToolConfig,
handler: ToolCallback<ZodRawShape>,
config: Omit<McpUiAppToolConfig, "inputSchema"> & {
inputSchema?: TInputSchema;
},
handler: ToolCallback<TInputSchema>,
): void {
// Normalize metadata for backward compatibility:
// - If _meta.ui.resourceUri is set, also set the legacy flat key