refactor: migrate shared SDK surfaces to v2

This commit is contained in:
Andrew Khadder 2026-07-14 15:46:56 -07:00
commit a76e3a7691
No known key found for this signature in database
8 changed files with 149 additions and 258 deletions

View file

@ -12,7 +12,7 @@
*
* ts-to-zod generates `import { z } from "zod"`. We rewrite this to
* `import { z } from "zod/v4"` because the generated schemas compose with
* schemas imported from `@modelcontextprotocol/sdk/types.js`, which the SDK
* schemas imported from `@modelcontextprotocol/core`, which the SDK
* constructs via `zod/v4`. Mixing schemas from the v3 and v4 APIs at runtime
* fails with errors like `keyValidator._parse is not a function` (v3 internals
* calling into v4 objects, or vice versa). The `zod/v4` subpath is exported by
@ -22,7 +22,7 @@
*
* **Problem**: ts-to-zod cannot resolve types imported from external packages.
* When it encounters types like `ContentBlock`, `CallToolResult`, `Implementation`,
* `RequestId`, and `Tool` from `@modelcontextprotocol/sdk`, it generates `z.any()`
* `RequestId`, and `Tool` from `@modelcontextprotocol/core`, it generates `z.any()`
* as a placeholder.
*
* **Solution**: Import the schemas from MCP SDK and remove the z.any() placeholders.
@ -193,7 +193,7 @@ function postProcess(content: string): string {
`import { z } from "zod/v4";
import {
${mcpImports},
} from "@modelcontextprotocol/sdk/types.js";`,
} from "@modelcontextprotocol/core";`,
);
// 2. Remove z.any() placeholders for external types (now imported from MCP SDK)

View file

@ -596,7 +596,9 @@
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
"required": {
"type": "array",
@ -611,25 +613,10 @@
"outputSchema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "object"
},
"properties": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"required": {
"type": "array",
"items": {
"type": "string"
}
"$schema": {
"type": "string"
}
},
"required": ["type"],
"additionalProperties": {}
},
"annotations": {
@ -1286,7 +1273,40 @@
}
},
"required": ["method", "params"],
"additionalProperties": false
"additionalProperties": false,
"$defs": {
"__schema0": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
{
"type": "array",
"items": {
"$ref": "#/$defs/__schema0"
}
}
]
}
}
},
"McpUiHostContext": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
@ -1359,7 +1379,9 @@
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
"required": {
"type": "array",
@ -1374,25 +1396,10 @@
"outputSchema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "object"
},
"properties": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"required": {
"type": "array",
"items": {
"type": "string"
}
"$schema": {
"type": "string"
}
},
"required": ["type"],
"additionalProperties": {}
},
"annotations": {
@ -2044,7 +2051,40 @@
"additionalProperties": false
}
},
"additionalProperties": {}
"additionalProperties": {},
"$defs": {
"__schema0": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
{
"type": "array",
"items": {
"$ref": "#/$defs/__schema0"
}
}
]
}
}
},
"McpUiHostCss": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
@ -2942,7 +2982,9 @@
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
"required": {
"type": "array",
@ -2957,25 +2999,10 @@
"outputSchema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "object"
},
"properties": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"required": {
"type": "array",
"items": {
"type": "string"
}
"$schema": {
"type": "string"
}
},
"required": ["type"],
"additionalProperties": {}
},
"annotations": {
@ -3637,7 +3664,40 @@
"hostCapabilities",
"hostContext"
],
"additionalProperties": {}
"additionalProperties": {},
"$defs": {
"__schema0": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"$ref": "#/$defs/__schema0"
}
},
{
"type": "array",
"items": {
"$ref": "#/$defs/__schema0"
}
}
]
}
}
},
"McpUiInitializedNotification": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
@ -5669,13 +5729,7 @@
]
}
},
"structuredContent": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"structuredContent": {},
"isError": {
"type": "boolean"
}

View file

@ -10,7 +10,7 @@ import {
RequestIdSchema,
ResourceLinkSchema,
ToolSchema,
} from "@modelcontextprotocol/sdk/types.js";
} from "@modelcontextprotocol/core";
/**
* @description Color theme preference for the host environment.

View file

@ -1,12 +1,10 @@
import {
import { JSONRPCMessageSchema } from "@modelcontextprotocol/core";
import type {
JSONRPCMessage,
JSONRPCMessageSchema,
MessageExtraInfo,
} from "@modelcontextprotocol/sdk/types.js";
import {
Transport,
TransportSendOptions,
} from "@modelcontextprotocol/sdk/shared/transport.js";
} from "@modelcontextprotocol/client";
import { TOOL_INPUT_PARTIAL_METHOD } from "./spec.types";
/**

View file

@ -1,6 +1,5 @@
import { useEffect, useState } from "react";
import { Implementation } from "@modelcontextprotocol/sdk/types.js";
import { Client } from "@modelcontextprotocol/sdk/client";
import type { Implementation } from "@modelcontextprotocol/client";
import {
App,
AppOptions,

View file

@ -40,24 +40,17 @@ import {
McpUiClientCapabilities,
} from "../app.js";
import type {
BaseToolCallback,
ClientCapabilities,
McpServer,
ReadResourceResult,
RegisteredTool,
ResourceMetadata,
StandardSchemaWithJSON,
ToolAnnotations,
ToolCallback,
ReadResourceCallback as _ReadResourceCallback,
RegisteredResource,
} from "@modelcontextprotocol/sdk/server/mcp.js";
import type {
AnySchema,
ZodRawShapeCompat,
} from "@modelcontextprotocol/sdk/server/zod-compat.js";
import type { StandardSchemaWithJSON } from "../standard-schema";
import type {
ClientCapabilities,
ReadResourceResult,
ToolAnnotations,
} from "@modelcontextprotocol/sdk/types.js";
} from "@modelcontextprotocol/server";
// Re-exports for convenience
export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE };
@ -70,8 +63,8 @@ export type { ResourceMetadata, ToolCallback };
export interface ToolConfig {
title?: string;
description?: string;
inputSchema?: ZodRawShapeCompat | StandardSchemaWithJSON;
outputSchema?: ZodRawShapeCompat | StandardSchemaWithJSON;
inputSchema?: StandardSchemaWithJSON;
outputSchema?: StandardSchemaWithJSON;
annotations?: ToolAnnotations;
_meta?: Record<string, unknown>;
}
@ -215,9 +208,8 @@ export interface McpUiAppResourceConfig extends ResourceMetadata {
* @see {@link registerAppResource `registerAppResource`} to register the HTML resource referenced by the tool
*/
export function registerAppTool<
OutputArgs extends ZodRawShapeCompat | StandardSchemaWithJSON,
InputArgs extends undefined | ZodRawShapeCompat | StandardSchemaWithJSON =
undefined,
OutputArgs extends StandardSchemaWithJSON,
InputArgs extends StandardSchemaWithJSON | undefined = undefined,
>(
server: Pick<McpServer, "registerTool">,
name: string,
@ -225,15 +217,7 @@ export function registerAppTool<
inputSchema?: InputArgs;
outputSchema?: OutputArgs;
},
// The widened constraint signals the v2 API shape, but NOTE: McpServer in
// sdk@1.x still calls zod internals at runtime, so non-zod schemas will fail
// here until we depend on sdk v2. Zod (which all current callers use) is
// unaffected. The cast below bridges the 1.x type signature.
cb: ToolCallback<
InputArgs extends undefined | ZodRawShapeCompat | AnySchema
? InputArgs
: AnySchema
>,
cb: ToolCallback<InputArgs>,
): RegisteredTool {
// Normalize metadata for backward compatibility:
// - If _meta.ui.resourceUri is set, also set the legacy flat key
@ -251,14 +235,7 @@ export function registerAppTool<
normalizedMeta = { ...meta, ui: { ...uiMeta, resourceUri: legacyUri } };
}
// Cast bridges the widened StandardSchemaWithJSON constraint to the
// sdk@1.x zod-typed signature. Drops once we depend on sdk v2.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return server.registerTool(
name,
{ ...config, _meta: normalizedMeta } as any,
cb as any,
);
return server.registerTool(name, { ...config, _meta: normalizedMeta }, cb);
}
export type McpUiReadResourceResult = ReadResourceResult & {
@ -418,10 +395,6 @@ export const EXTENSION_ID = "io.modelcontextprotocol/ui";
* This helper retrieves the capability object from the `extensions` field
* where MCP Apps advertises its support.
*
* Note: The `clientCapabilities` parameter extends the SDK's `ClientCapabilities`
* type with an `extensions` field (pending SEP-1724). Once `extensions` is added
* to the SDK, this can use `ClientCapabilities` directly.
*
* @param clientCapabilities - The client capabilities from the initialize response
* @returns The MCP Apps capability settings, or `undefined` if not supported
*
@ -456,10 +429,7 @@ export const EXTENSION_ID = "io.modelcontextprotocol/ui";
* ```
*/
export function getUiCapability(
clientCapabilities:
| (ClientCapabilities & { extensions?: Record<string, unknown> })
| null
| undefined,
clientCapabilities: ClientCapabilities | null | undefined,
): McpUiClientCapabilities | undefined {
if (!clientCapabilities) {
return undefined;

View file

@ -18,7 +18,7 @@ import type {
RequestId,
ResourceLink,
Tool,
} from "@modelcontextprotocol/sdk/types.js";
} from "@modelcontextprotocol/client";
/**
* Current protocol version supported by this SDK.
@ -163,8 +163,8 @@ export interface McpUiOpenLinkResult {
/** @description True if the host failed to open the URL (e.g., due to security policy). */
isError?: boolean;
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Note: The generated schema uses passthrough() to allow additional properties.
* Additional result properties are preserved for protocol extensibility.
* The generated schema uses passthrough() to allow them.
*/
[key: string]: unknown;
}
@ -195,8 +195,8 @@ export interface McpUiDownloadFileResult {
/** @description True if the download failed (e.g., user cancelled or host denied). */
isError?: boolean;
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Note: The generated schema uses passthrough() to allow additional properties.
* Additional result properties are preserved for protocol extensibility.
* The generated schema uses passthrough() to allow them.
*/
[key: string]: unknown;
}
@ -223,8 +223,8 @@ export interface McpUiMessageResult {
/** @description True if the host rejected or failed to deliver the message. */
isError?: boolean;
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Note: The generated schema uses passthrough() to allow additional properties.
* Additional result properties are preserved for protocol extensibility.
* The generated schema uses passthrough() to allow them.
*/
[key: string]: unknown;
}
@ -454,7 +454,7 @@ export interface McpUiResourceTeardownRequest {
*/
export interface McpUiResourceTeardownResult {
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Additional result properties are preserved for protocol extensibility.
*/
[key: string]: unknown;
}
@ -577,8 +577,8 @@ export interface McpUiInitializeResult {
/** @description Rich context about the host environment. */
hostContext: McpUiHostContext;
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Note: The generated schema uses passthrough() to allow additional properties.
* Additional result properties are preserved for protocol extensibility.
* The generated schema uses passthrough() to allow them.
*/
[key: string]: unknown;
}
@ -752,7 +752,7 @@ export interface McpUiRequestDisplayModeResult {
/** @description The display mode that was actually set. May differ from requested if not supported. */
mode: McpUiDisplayMode;
/**
* Index signature required for MCP SDK `Protocol` class compatibility.
* Additional result properties are preserved for protocol extensibility.
* Note: The generated schema uses passthrough() to allow additional properties.
*/
[key: string]: unknown;

View file

@ -69,33 +69,6 @@ export {
type McpUiClientCapabilities,
} from "./spec.types.js";
// Import types needed for protocol type unions (not re-exported, just used internally)
import type {
McpUiInitializeRequest,
McpUiOpenLinkRequest,
McpUiDownloadFileRequest,
McpUiMessageRequest,
McpUiUpdateModelContextRequest,
McpUiResourceTeardownRequest,
McpUiRequestDisplayModeRequest,
McpUiHostContextChangedNotification,
McpUiToolInputNotification,
McpUiToolInputPartialNotification,
McpUiToolResultNotification,
McpUiToolCancelledNotification,
McpUiSandboxResourceReadyNotification,
McpUiInitializedNotification,
McpUiSizeChangedNotification,
McpUiSandboxProxyReadyNotification,
McpUiRequestTeardownNotification,
McpUiInitializeResult,
McpUiOpenLinkResult,
McpUiDownloadFileResult,
McpUiMessageResult,
McpUiResourceTeardownResult,
McpUiRequestDisplayModeResult,
} from "./spec.types.js";
// Re-export all schemas from generated/schema.ts (already PascalCase)
export {
McpUiThemeSchema,
@ -135,106 +108,3 @@ export {
McpUiToolVisibilitySchema,
McpUiToolMetaSchema,
} from "./generated/schema.js";
// Re-export SDK types used in protocol type unions
import {
CallToolRequest,
CallToolResult,
CreateMessageRequest,
CreateMessageResult,
CreateMessageResultWithTools,
EmptyResult,
ListPromptsRequest,
ListPromptsResult,
ListResourcesRequest,
ListResourcesResult,
ListResourceTemplatesRequest,
ListResourceTemplatesResult,
ListToolsRequest,
ListToolsResult,
LoggingMessageNotification,
PingRequest,
PromptListChangedNotification,
ReadResourceRequest,
ReadResourceResult,
ResourceListChangedNotification,
ToolListChangedNotification,
} from "@modelcontextprotocol/sdk/types.js";
/**
* All request types in the MCP Apps protocol.
*
* Includes:
* - MCP UI requests (initialize, open-link, message, resource-teardown, request-display-mode)
* - MCP server requests forwarded from the app (tools/call, tools/list, resources/list,
* resources/templates/list, resources/read, prompts/list)
* - MCP client requests forwarded to the host (sampling/createMessage)
* - Protocol requests (ping)
*/
export type AppRequest =
| McpUiInitializeRequest
| McpUiOpenLinkRequest
| McpUiDownloadFileRequest
| McpUiMessageRequest
| McpUiUpdateModelContextRequest
| McpUiResourceTeardownRequest
| McpUiRequestDisplayModeRequest
| CallToolRequest
| ListToolsRequest
| ListResourcesRequest
| ListResourceTemplatesRequest
| ReadResourceRequest
| ListPromptsRequest
| CreateMessageRequest
| PingRequest;
/**
* All notification types in the MCP Apps protocol.
*
* Host to app:
* - Tool lifecycle (input, input-partial, result, cancelled)
* - Host context changes
* - MCP list changes (tools, resources, prompts)
* - Sandbox resource ready
*
* App to host:
* - Initialized, size-changed, sandbox-proxy-ready, request-teardown
* - Logging messages
*/
export type AppNotification =
// Sent to app
| McpUiHostContextChangedNotification
| McpUiToolInputNotification
| McpUiToolInputPartialNotification
| McpUiToolResultNotification
| McpUiToolCancelledNotification
| McpUiSandboxResourceReadyNotification
| ToolListChangedNotification
| ResourceListChangedNotification
| PromptListChangedNotification
// Received from app
| McpUiInitializedNotification
| McpUiSizeChangedNotification
| McpUiSandboxProxyReadyNotification
| McpUiRequestTeardownNotification
| LoggingMessageNotification;
/**
* All result types in the MCP Apps protocol.
*/
export type AppResult =
| McpUiInitializeResult
| McpUiOpenLinkResult
| McpUiDownloadFileResult
| McpUiMessageResult
| McpUiResourceTeardownResult
| McpUiRequestDisplayModeResult
| CallToolResult
| ListToolsResult
| ListResourcesResult
| ListResourceTemplatesResult
| ReadResourceResult
| ListPromptsResult
| CreateMessageResult
| CreateMessageResultWithTools
| EmptyResult;