| | |
| | |
| | |
| | import { z } from "zod"; |
| | import { |
| | ContentBlockSchema, |
| | CallToolResultSchema, |
| | ImplementationSchema, |
| | RequestIdSchema, |
| | ToolSchema, |
| | } from "@modelcontextprotocol/sdk/types.js"; |
| |
|
| | |
| | |
| | |
| | export const McpUiThemeSchema = z |
| | .union([z.literal("light"), z.literal("dark")]) |
| | .describe("Color theme preference for the host environment."); |
| |
|
| | |
| | |
| | |
| | export const McpUiDisplayModeSchema = z |
| | .union([z.literal("inline"), z.literal("fullscreen"), z.literal("pip")]) |
| | .describe("Display mode for UI presentation."); |
| |
|
| | |
| | |
| | |
| | export const McpUiStyleVariableKeySchema = z |
| | .union([ |
| | z.literal("--color-background-primary"), |
| | z.literal("--color-background-secondary"), |
| | z.literal("--color-background-tertiary"), |
| | z.literal("--color-background-inverse"), |
| | z.literal("--color-background-ghost"), |
| | z.literal("--color-background-info"), |
| | z.literal("--color-background-danger"), |
| | z.literal("--color-background-success"), |
| | z.literal("--color-background-warning"), |
| | z.literal("--color-background-disabled"), |
| | z.literal("--color-text-primary"), |
| | z.literal("--color-text-secondary"), |
| | z.literal("--color-text-tertiary"), |
| | z.literal("--color-text-inverse"), |
| | z.literal("--color-text-ghost"), |
| | z.literal("--color-text-info"), |
| | z.literal("--color-text-danger"), |
| | z.literal("--color-text-success"), |
| | z.literal("--color-text-warning"), |
| | z.literal("--color-text-disabled"), |
| | z.literal("--color-text-ghost"), |
| | z.literal("--color-border-primary"), |
| | z.literal("--color-border-secondary"), |
| | z.literal("--color-border-tertiary"), |
| | z.literal("--color-border-inverse"), |
| | z.literal("--color-border-ghost"), |
| | z.literal("--color-border-info"), |
| | z.literal("--color-border-danger"), |
| | z.literal("--color-border-success"), |
| | z.literal("--color-border-warning"), |
| | z.literal("--color-border-disabled"), |
| | z.literal("--color-ring-primary"), |
| | z.literal("--color-ring-secondary"), |
| | z.literal("--color-ring-inverse"), |
| | z.literal("--color-ring-info"), |
| | z.literal("--color-ring-danger"), |
| | z.literal("--color-ring-success"), |
| | z.literal("--color-ring-warning"), |
| | z.literal("--font-sans"), |
| | z.literal("--font-mono"), |
| | z.literal("--font-weight-normal"), |
| | z.literal("--font-weight-medium"), |
| | z.literal("--font-weight-semibold"), |
| | z.literal("--font-weight-bold"), |
| | z.literal("--font-text-xs-size"), |
| | z.literal("--font-text-sm-size"), |
| | z.literal("--font-text-md-size"), |
| | z.literal("--font-text-lg-size"), |
| | z.literal("--font-heading-xs-size"), |
| | z.literal("--font-heading-sm-size"), |
| | z.literal("--font-heading-md-size"), |
| | z.literal("--font-heading-lg-size"), |
| | z.literal("--font-heading-xl-size"), |
| | z.literal("--font-heading-2xl-size"), |
| | z.literal("--font-heading-3xl-size"), |
| | z.literal("--font-text-xs-line-height"), |
| | z.literal("--font-text-sm-line-height"), |
| | z.literal("--font-text-md-line-height"), |
| | z.literal("--font-text-lg-line-height"), |
| | z.literal("--font-heading-xs-line-height"), |
| | z.literal("--font-heading-sm-line-height"), |
| | z.literal("--font-heading-md-line-height"), |
| | z.literal("--font-heading-lg-line-height"), |
| | z.literal("--font-heading-xl-line-height"), |
| | z.literal("--font-heading-2xl-line-height"), |
| | z.literal("--font-heading-3xl-line-height"), |
| | z.literal("--border-radius-xs"), |
| | z.literal("--border-radius-sm"), |
| | z.literal("--border-radius-md"), |
| | z.literal("--border-radius-lg"), |
| | z.literal("--border-radius-xl"), |
| | z.literal("--border-radius-full"), |
| | z.literal("--border-width-regular"), |
| | z.literal("--shadow-hairline"), |
| | z.literal("--shadow-sm"), |
| | z.literal("--shadow-md"), |
| | z.literal("--shadow-lg"), |
| | ]) |
| | .describe("CSS variable keys available to MCP apps for theming."); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | export const McpUiStylesSchema = z |
| | .record( |
| | McpUiStyleVariableKeySchema.describe( |
| | "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record<K, string | undefined>` rather than `Partial<Record<K, string>>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", |
| | ), |
| | z |
| | .union([z.string(), z.undefined()]) |
| | .describe( |
| | "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record<K, string | undefined>` rather than `Partial<Record<K, string>>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", |
| | ), |
| | ) |
| | .describe( |
| | "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record<K, string | undefined>` rather than `Partial<Record<K, string>>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", |
| | ); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiOpenLinkRequestSchema = z.object({ |
| | method: z.literal("ui/open-link"), |
| | params: z.object({ |
| | |
| | url: z.string().describe("URL to open in the host's browser"), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiOpenLinkResultSchema = z |
| | .object({ |
| | |
| | isError: z |
| | .boolean() |
| | .optional() |
| | .describe( |
| | "True if the host failed to open the URL (e.g., due to security policy).", |
| | ), |
| | }) |
| | .passthrough(); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiMessageResultSchema = z |
| | .object({ |
| | |
| | isError: z |
| | .boolean() |
| | .optional() |
| | .describe("True if the host rejected or failed to deliver the message."), |
| | }) |
| | .passthrough(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export const McpUiSandboxProxyReadyNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/sandbox-proxy-ready"), |
| | params: z.object({}), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiResourceCspSchema = z.object({ |
| | |
| | connectDomains: z |
| | .array(z.string()) |
| | .optional() |
| | .describe("Origins for network requests (fetch/XHR/WebSocket)."), |
| | |
| | resourceDomains: z |
| | .array(z.string()) |
| | .optional() |
| | .describe("Origins for static resources (scripts, images, styles, fonts)."), |
| | |
| | frameDomains: z |
| | .array(z.string()) |
| | .optional() |
| | .describe("Origins for nested iframes (frame-src directive)."), |
| | |
| | baseUriDomains: z |
| | .array(z.string()) |
| | .optional() |
| | .describe("Allowed base URIs for the document (base-uri directive)."), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export const McpUiResourcePermissionsSchema = z.object({ |
| | |
| | camera: z |
| | .object({}) |
| | .optional() |
| | .describe("Request camera access (Permission Policy `camera` feature)."), |
| | |
| | microphone: z |
| | .object({}) |
| | .optional() |
| | .describe( |
| | "Request microphone access (Permission Policy `microphone` feature).", |
| | ), |
| | |
| | geolocation: z |
| | .object({}) |
| | .optional() |
| | .describe( |
| | "Request geolocation access (Permission Policy `geolocation` feature).", |
| | ), |
| | |
| | clipboardWrite: z |
| | .object({}) |
| | .optional() |
| | .describe( |
| | "Request clipboard write access (Permission Policy `clipboard-write` feature).", |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiSizeChangedNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/size-changed"), |
| | params: z.object({ |
| | |
| | width: z.number().optional().describe("New width in pixels."), |
| | |
| | height: z.number().optional().describe("New height in pixels."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiToolInputNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/tool-input"), |
| | params: z.object({ |
| | |
| | arguments: z |
| | .record( |
| | z.string(), |
| | z |
| | .unknown() |
| | .describe("Complete tool call arguments as key-value pairs."), |
| | ) |
| | .optional() |
| | .describe("Complete tool call arguments as key-value pairs."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiToolInputPartialNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/tool-input-partial"), |
| | params: z.object({ |
| | |
| | arguments: z |
| | .record( |
| | z.string(), |
| | z |
| | .unknown() |
| | .describe("Partial tool call arguments (incomplete, may change)."), |
| | ) |
| | .optional() |
| | .describe("Partial tool call arguments (incomplete, may change)."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export const McpUiToolCancelledNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/tool-cancelled"), |
| | params: z.object({ |
| | |
| | reason: z |
| | .string() |
| | .optional() |
| | .describe( |
| | 'Optional reason for the cancellation (e.g., "user action", "timeout").', |
| | ), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiHostCssSchema = z.object({ |
| | |
| | fonts: z.string().optional(), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiHostStylesSchema = z.object({ |
| | |
| | variables: McpUiStylesSchema.optional().describe( |
| | "CSS variables for theming the app.", |
| | ), |
| | |
| | css: McpUiHostCssSchema.optional().describe( |
| | "CSS blocks that apps can inject.", |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiResourceTeardownRequestSchema = z.object({ |
| | method: z.literal("ui/resource-teardown"), |
| | params: z.object({}), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiResourceTeardownResultSchema = z.record( |
| | z.string(), |
| | z.unknown(), |
| | ); |
| |
|
| | export const McpUiSupportedContentBlockModalitiesSchema = z.object({ |
| | |
| | text: z.object({}).optional().describe("Host supports text content blocks."), |
| | |
| | image: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports image content blocks."), |
| | |
| | audio: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports audio content blocks."), |
| | |
| | resource: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports resource content blocks."), |
| | |
| | resourceLink: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports resource link content blocks."), |
| | |
| | structuredContent: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports structured content."), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiHostCapabilitiesSchema = z.object({ |
| | |
| | experimental: z |
| | .object({}) |
| | .optional() |
| | .describe("Experimental features (structure TBD)."), |
| | |
| | openLinks: z |
| | .object({}) |
| | .optional() |
| | .describe("Host supports opening external URLs."), |
| | |
| | serverTools: z |
| | .object({ |
| | |
| | listChanged: z |
| | .boolean() |
| | .optional() |
| | .describe("Host supports tools/list_changed notifications."), |
| | }) |
| | .optional() |
| | .describe("Host can proxy tool calls to the MCP server."), |
| | |
| | serverResources: z |
| | .object({ |
| | |
| | listChanged: z |
| | .boolean() |
| | .optional() |
| | .describe("Host supports resources/list_changed notifications."), |
| | }) |
| | .optional() |
| | .describe("Host can proxy resource reads to the MCP server."), |
| | |
| | logging: z.object({}).optional().describe("Host accepts log messages."), |
| | |
| | sandbox: z |
| | .object({ |
| | |
| | permissions: McpUiResourcePermissionsSchema.optional().describe( |
| | "Permissions granted by the host (camera, microphone, geolocation).", |
| | ), |
| | |
| | csp: McpUiResourceCspSchema.optional().describe( |
| | "CSP domains approved by the host.", |
| | ), |
| | }) |
| | .optional() |
| | .describe("Sandbox configuration applied by the host."), |
| | |
| | updateModelContext: |
| | McpUiSupportedContentBlockModalitiesSchema.optional().describe( |
| | "Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.", |
| | ), |
| | |
| | message: McpUiSupportedContentBlockModalitiesSchema.optional().describe( |
| | "Host supports receiving content messages (ui/message) from the Guest UI.", |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiAppCapabilitiesSchema = z.object({ |
| | |
| | experimental: z |
| | .object({}) |
| | .optional() |
| | .describe("Experimental features (structure TBD)."), |
| | |
| | tools: z |
| | .object({ |
| | |
| | listChanged: z |
| | .boolean() |
| | .optional() |
| | .describe("App supports tools/list_changed notifications."), |
| | }) |
| | .optional() |
| | .describe("App exposes MCP-style tools that the host can call."), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiInitializedNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/initialized"), |
| | params: z.object({}).optional(), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiResourceMetaSchema = z.object({ |
| | |
| | csp: McpUiResourceCspSchema.optional().describe( |
| | "Content Security Policy configuration.", |
| | ), |
| | |
| | permissions: McpUiResourcePermissionsSchema.optional().describe( |
| | "Sandbox permissions requested by the UI.", |
| | ), |
| | |
| | domain: z |
| | .string() |
| | .optional() |
| | .describe("Dedicated origin for widget sandbox."), |
| | |
| | prefersBorder: z |
| | .boolean() |
| | .optional() |
| | .describe( |
| | "Visual boundary preference - true if UI prefers a visible border.", |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | export const McpUiRequestDisplayModeRequestSchema = z.object({ |
| | method: z.literal("ui/request-display-mode"), |
| | params: z.object({ |
| | |
| | mode: McpUiDisplayModeSchema.describe("The display mode being requested."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiRequestDisplayModeResultSchema = z |
| | .object({ |
| | |
| | mode: McpUiDisplayModeSchema.describe( |
| | "The display mode that was actually set. May differ from requested if not supported.", |
| | ), |
| | }) |
| | .passthrough(); |
| |
|
| | |
| | |
| | |
| | export const McpUiToolVisibilitySchema = z |
| | .union([z.literal("model"), z.literal("app")]) |
| | .describe("Tool visibility scope - who can access the tool."); |
| |
|
| | |
| | |
| | |
| | export const McpUiToolMetaSchema = z.object({ |
| | |
| | |
| | |
| | |
| | |
| | |
| | resourceUri: z.string().optional(), |
| | |
| | |
| | |
| | |
| | |
| | visibility: z |
| | .array(McpUiToolVisibilitySchema) |
| | .optional() |
| | .describe( |
| | 'Who can access this tool. Default: ["model", "app"]\n- "model": Tool visible to and callable by the agent\n- "app": Tool callable by the app from this server only', |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiMessageRequestSchema = z.object({ |
| | method: z.literal("ui/message"), |
| | params: z.object({ |
| | |
| | role: z |
| | .literal("user") |
| | .describe('Message role, currently only "user" is supported.'), |
| | |
| | content: z |
| | .array(ContentBlockSchema) |
| | .describe("Message content blocks (text, image, etc.)."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export const McpUiSandboxResourceReadyNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/sandbox-resource-ready"), |
| | params: z.object({ |
| | |
| | html: z.string().describe("HTML content to load into the inner iframe."), |
| | |
| | sandbox: z |
| | .string() |
| | .optional() |
| | .describe("Optional override for the inner iframe's sandbox attribute."), |
| | |
| | csp: McpUiResourceCspSchema.optional().describe( |
| | "CSP configuration from resource metadata.", |
| | ), |
| | |
| | permissions: McpUiResourcePermissionsSchema.optional().describe( |
| | "Sandbox permissions from resource metadata.", |
| | ), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiToolResultNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/tool-result"), |
| | |
| | params: CallToolResultSchema.describe("Standard MCP tool execution result."), |
| | }); |
| |
|
| | |
| | |
| | |
| | export const McpUiHostContextSchema = z |
| | .object({ |
| | |
| | toolInfo: z |
| | .object({ |
| | |
| | id: RequestIdSchema.optional().describe( |
| | "JSON-RPC id of the tools/call request.", |
| | ), |
| | |
| | tool: ToolSchema.describe( |
| | "Tool definition including name, inputSchema, etc.", |
| | ), |
| | }) |
| | .optional() |
| | .describe("Metadata of the tool call that instantiated this App."), |
| | |
| | theme: McpUiThemeSchema.optional().describe( |
| | "Current color theme preference.", |
| | ), |
| | |
| | styles: McpUiHostStylesSchema.optional().describe( |
| | "Style configuration for theming the app.", |
| | ), |
| | |
| | displayMode: McpUiDisplayModeSchema.optional().describe( |
| | "How the UI is currently displayed.", |
| | ), |
| | |
| | availableDisplayModes: z |
| | .array(z.string()) |
| | .optional() |
| | .describe("Display modes the host supports."), |
| | |
| | |
| | |
| | |
| | containerDimensions: z |
| | .union([ |
| | z.object({ |
| | |
| | height: z.number().describe("Fixed container height in pixels."), |
| | }), |
| | z.object({ |
| | |
| | maxHeight: z |
| | .union([z.number(), z.undefined()]) |
| | .optional() |
| | .describe("Maximum container height in pixels."), |
| | }), |
| | ]) |
| | .and( |
| | z.union([ |
| | z.object({ |
| | |
| | width: z.number().describe("Fixed container width in pixels."), |
| | }), |
| | z.object({ |
| | |
| | maxWidth: z |
| | .union([z.number(), z.undefined()]) |
| | .optional() |
| | .describe("Maximum container width in pixels."), |
| | }), |
| | ]), |
| | ) |
| | .optional() |
| | .describe( |
| | "Container dimensions. Represents the dimensions of the iframe or other\ncontainer holding the app. Specify either width or maxWidth, and either height or maxHeight.", |
| | ), |
| | |
| | locale: z |
| | .string() |
| | .optional() |
| | .describe("User's language and region preference in BCP 47 format."), |
| | |
| | timeZone: z.string().optional().describe("User's timezone in IANA format."), |
| | |
| | userAgent: z.string().optional().describe("Host application identifier."), |
| | |
| | platform: z |
| | .union([z.literal("web"), z.literal("desktop"), z.literal("mobile")]) |
| | .optional() |
| | .describe("Platform type for responsive design decisions."), |
| | |
| | deviceCapabilities: z |
| | .object({ |
| | |
| | touch: z |
| | .boolean() |
| | .optional() |
| | .describe("Whether the device supports touch input."), |
| | |
| | hover: z |
| | .boolean() |
| | .optional() |
| | .describe("Whether the device supports hover interactions."), |
| | }) |
| | .optional() |
| | .describe("Device input capabilities."), |
| | |
| | safeAreaInsets: z |
| | .object({ |
| | |
| | top: z.number().describe("Top safe area inset in pixels."), |
| | |
| | right: z.number().describe("Right safe area inset in pixels."), |
| | |
| | bottom: z.number().describe("Bottom safe area inset in pixels."), |
| | |
| | left: z.number().describe("Left safe area inset in pixels."), |
| | }) |
| | .optional() |
| | .describe("Mobile safe area boundaries in pixels."), |
| | }) |
| | .passthrough(); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiHostContextChangedNotificationSchema = z.object({ |
| | method: z.literal("ui/notifications/host-context-changed"), |
| | |
| | params: McpUiHostContextSchema.describe( |
| | "Partial context update containing only changed fields.", |
| | ), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | export const McpUiUpdateModelContextRequestSchema = z.object({ |
| | method: z.literal("ui/update-model-context"), |
| | params: z.object({ |
| | |
| | content: z |
| | .array(ContentBlockSchema) |
| | .optional() |
| | .describe("Context content blocks (text, image, etc.)."), |
| | |
| | structuredContent: z |
| | .record( |
| | z.string(), |
| | z |
| | .unknown() |
| | .describe("Structured content for machine-readable context data."), |
| | ) |
| | .optional() |
| | .describe("Structured content for machine-readable context data."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiInitializeRequestSchema = z.object({ |
| | method: z.literal("ui/initialize"), |
| | params: z.object({ |
| | |
| | appInfo: ImplementationSchema.describe( |
| | "App identification (name and version).", |
| | ), |
| | |
| | appCapabilities: McpUiAppCapabilitiesSchema.describe( |
| | "Features and capabilities this app provides.", |
| | ), |
| | |
| | protocolVersion: z.string().describe("Protocol version this app supports."), |
| | }), |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | export const McpUiInitializeResultSchema = z |
| | .object({ |
| | |
| | protocolVersion: z |
| | .string() |
| | .describe('Negotiated protocol version string (e.g., "2025-11-21").'), |
| | |
| | hostInfo: ImplementationSchema.describe( |
| | "Host application identification and version.", |
| | ), |
| | |
| | hostCapabilities: McpUiHostCapabilitiesSchema.describe( |
| | "Features and capabilities provided by the host.", |
| | ), |
| | |
| | hostContext: McpUiHostContextSchema.describe( |
| | "Rich context about the host environment.", |
| | ), |
| | }) |
| | .passthrough(); |
| |
|