// Generated by ts-to-zod // Post-processed for Zod v3/v4 compatibility and MCP SDK integration // Run: npm run generate:schemas import { z } from "zod"; import { ContentBlockSchema, CallToolResultSchema, ImplementationSchema, RequestIdSchema, ToolSchema, } from "@modelcontextprotocol/sdk/types.js"; /** * @description Color theme preference for the host environment. */ export const McpUiThemeSchema = z .union([z.literal("light"), z.literal("dark")]) .describe("Color theme preference for the host environment."); /** * @description Display mode for UI presentation. */ export const McpUiDisplayModeSchema = z .union([z.literal("inline"), z.literal("fullscreen"), z.literal("pip")]) .describe("Display mode for UI presentation."); /** * @description CSS variable keys available to MCP apps for theming. */ 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."); /** * @description Style variables for theming MCP apps. * * Individual style keys are optional - hosts may provide any subset of these values. * Values are strings containing CSS values (colors, sizes, font stacks, etc.). * * Note: This type uses `Record` rather than `Partial>` * for compatibility with Zod schema generation. Both are functionally equivalent for validation. */ 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` rather than `Partial>`\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` rather than `Partial>`\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` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", ); /** * @description Request to open an external URL in the host's default browser. * @see {@link app!App.openLink} for the method that sends this request */ export const McpUiOpenLinkRequestSchema = z.object({ method: z.literal("ui/open-link"), params: z.object({ /** @description URL to open in the host's browser */ url: z.string().describe("URL to open in the host's browser"), }), }); /** * @description Result from opening a URL. * @see {@link McpUiOpenLinkRequest} */ export const McpUiOpenLinkResultSchema = z .object({ /** @description True if the host failed to open the URL (e.g., due to security policy). */ isError: z .boolean() .optional() .describe( "True if the host failed to open the URL (e.g., due to security policy).", ), }) .passthrough(); /** * @description Result from sending a message. * @see {@link McpUiMessageRequest} */ export const McpUiMessageResultSchema = z .object({ /** @description True if the host rejected or failed to deliver the message. */ isError: z .boolean() .optional() .describe("True if the host rejected or failed to deliver the message."), }) .passthrough(); /** * @description Notification that the sandbox proxy iframe is ready to receive content. * @internal * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy */ export const McpUiSandboxProxyReadyNotificationSchema = z.object({ method: z.literal("ui/notifications/sandbox-proxy-ready"), params: z.object({}), }); /** * @description Content Security Policy configuration for UI resources. */ export const McpUiResourceCspSchema = z.object({ /** @description Origins for network requests (fetch/XHR/WebSocket). */ connectDomains: z .array(z.string()) .optional() .describe("Origins for network requests (fetch/XHR/WebSocket)."), /** @description Origins for static resources (scripts, images, styles, fonts). */ resourceDomains: z .array(z.string()) .optional() .describe("Origins for static resources (scripts, images, styles, fonts)."), /** @description Origins for nested iframes (frame-src directive). */ frameDomains: z .array(z.string()) .optional() .describe("Origins for nested iframes (frame-src directive)."), /** @description Allowed base URIs for the document (base-uri directive). */ baseUriDomains: z .array(z.string()) .optional() .describe("Allowed base URIs for the document (base-uri directive)."), }); /** * @description Sandbox permissions requested by the UI resource. * Hosts MAY honor these by setting appropriate iframe `allow` attributes. * Apps SHOULD NOT assume permissions are granted; use JS feature detection as fallback. */ export const McpUiResourcePermissionsSchema = z.object({ /** @description Request camera access (Permission Policy `camera` feature). */ camera: z .object({}) .optional() .describe("Request camera access (Permission Policy `camera` feature)."), /** @description Request microphone access (Permission Policy `microphone` feature). */ microphone: z .object({}) .optional() .describe( "Request microphone access (Permission Policy `microphone` feature).", ), /** @description Request geolocation access (Permission Policy `geolocation` feature). */ geolocation: z .object({}) .optional() .describe( "Request geolocation access (Permission Policy `geolocation` feature).", ), /** @description Request clipboard write access (Permission Policy `clipboard-write` feature). */ clipboardWrite: z .object({}) .optional() .describe( "Request clipboard write access (Permission Policy `clipboard-write` feature).", ), }); /** * @description Notification of UI size changes (Guest UI -> Host). * @see {@link app!App.sendSizeChanged} for the method to send this from Guest UI */ export const McpUiSizeChangedNotificationSchema = z.object({ method: z.literal("ui/notifications/size-changed"), params: z.object({ /** @description New width in pixels. */ width: z.number().optional().describe("New width in pixels."), /** @description New height in pixels. */ height: z.number().optional().describe("New height in pixels."), }), }); /** * @description Notification containing complete tool arguments (Host -> Guest UI). */ export const McpUiToolInputNotificationSchema = z.object({ method: z.literal("ui/notifications/tool-input"), params: z.object({ /** @description Complete tool call arguments as key-value pairs. */ 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."), }), }); /** * @description Notification containing partial/streaming tool arguments (Host -> Guest UI). */ export const McpUiToolInputPartialNotificationSchema = z.object({ method: z.literal("ui/notifications/tool-input-partial"), params: z.object({ /** @description Partial tool call arguments (incomplete, may change). */ arguments: z .record( z.string(), z .unknown() .describe("Partial tool call arguments (incomplete, may change)."), ) .optional() .describe("Partial tool call arguments (incomplete, may change)."), }), }); /** * @description Notification that tool execution was cancelled (Host -> Guest UI). * Host MUST send this if tool execution was cancelled for any reason (user action, * sampling error, classifier intervention, etc.). */ export const McpUiToolCancelledNotificationSchema = z.object({ method: z.literal("ui/notifications/tool-cancelled"), params: z.object({ /** @description Optional reason for the cancellation (e.g., "user action", "timeout"). */ reason: z .string() .optional() .describe( 'Optional reason for the cancellation (e.g., "user action", "timeout").', ), }), }); /** * @description CSS blocks that can be injected by apps. */ export const McpUiHostCssSchema = z.object({ /** @description CSS for font loading (`@font-face` rules or `@import` statements). Apps must apply using {@link applyHostFonts}. */ fonts: z.string().optional(), }); /** * @description Style configuration for theming MCP apps. */ export const McpUiHostStylesSchema = z.object({ /** @description CSS variables for theming the app. */ variables: McpUiStylesSchema.optional().describe( "CSS variables for theming the app.", ), /** @description CSS blocks that apps can inject. */ css: McpUiHostCssSchema.optional().describe( "CSS blocks that apps can inject.", ), }); /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge!AppBridge.teardownResource} for the host method that sends this */ export const McpUiResourceTeardownRequestSchema = z.object({ method: z.literal("ui/resource-teardown"), params: z.object({}), }); /** * @description Result from graceful shutdown request. * @see {@link McpUiResourceTeardownRequest} */ export const McpUiResourceTeardownResultSchema = z.record( z.string(), z.unknown(), ); export const McpUiSupportedContentBlockModalitiesSchema = z.object({ /** @description Host supports text content blocks. */ text: z.object({}).optional().describe("Host supports text content blocks."), /** @description Host supports image content blocks. */ image: z .object({}) .optional() .describe("Host supports image content blocks."), /** @description Host supports audio content blocks. */ audio: z .object({}) .optional() .describe("Host supports audio content blocks."), /** @description Host supports resource content blocks. */ resource: z .object({}) .optional() .describe("Host supports resource content blocks."), /** @description Host supports resource link content blocks. */ resourceLink: z .object({}) .optional() .describe("Host supports resource link content blocks."), /** @description Host supports structured content. */ structuredContent: z .object({}) .optional() .describe("Host supports structured content."), }); /** * @description Capabilities supported by the host application. * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities */ export const McpUiHostCapabilitiesSchema = z.object({ /** @description Experimental features (structure TBD). */ experimental: z .object({}) .optional() .describe("Experimental features (structure TBD)."), /** @description Host supports opening external URLs. */ openLinks: z .object({}) .optional() .describe("Host supports opening external URLs."), /** @description Host can proxy tool calls to the MCP server. */ serverTools: z .object({ /** @description Host supports tools/list_changed notifications. */ listChanged: z .boolean() .optional() .describe("Host supports tools/list_changed notifications."), }) .optional() .describe("Host can proxy tool calls to the MCP server."), /** @description Host can proxy resource reads to the MCP server. */ serverResources: z .object({ /** @description Host supports resources/list_changed notifications. */ listChanged: z .boolean() .optional() .describe("Host supports resources/list_changed notifications."), }) .optional() .describe("Host can proxy resource reads to the MCP server."), /** @description Host accepts log messages. */ logging: z.object({}).optional().describe("Host accepts log messages."), /** @description Sandbox configuration applied by the host. */ sandbox: z .object({ /** @description Permissions granted by the host (camera, microphone, geolocation). */ permissions: McpUiResourcePermissionsSchema.optional().describe( "Permissions granted by the host (camera, microphone, geolocation).", ), /** @description CSP domains approved by the host. */ csp: McpUiResourceCspSchema.optional().describe( "CSP domains approved by the host.", ), }) .optional() .describe("Sandbox configuration applied by the host."), /** @description Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns. */ updateModelContext: McpUiSupportedContentBlockModalitiesSchema.optional().describe( "Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.", ), /** @description Host supports receiving content messages (ui/message) from the Guest UI. */ message: McpUiSupportedContentBlockModalitiesSchema.optional().describe( "Host supports receiving content messages (ui/message) from the Guest UI.", ), }); /** * @description Capabilities provided by the Guest UI ({@link app!App}). * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities */ export const McpUiAppCapabilitiesSchema = z.object({ /** @description Experimental features (structure TBD). */ experimental: z .object({}) .optional() .describe("Experimental features (structure TBD)."), /** @description App exposes MCP-style tools that the host can call. */ tools: z .object({ /** @description App supports tools/list_changed notifications. */ listChanged: z .boolean() .optional() .describe("App supports tools/list_changed notifications."), }) .optional() .describe("App exposes MCP-style tools that the host can call."), }); /** * @description Notification that Guest UI has completed initialization (Guest UI -> Host). * @see {@link app!App.connect} for the method that sends this notification */ export const McpUiInitializedNotificationSchema = z.object({ method: z.literal("ui/notifications/initialized"), params: z.object({}).optional(), }); /** * @description UI Resource metadata for security and rendering configuration. */ export const McpUiResourceMetaSchema = z.object({ /** @description Content Security Policy configuration. */ csp: McpUiResourceCspSchema.optional().describe( "Content Security Policy configuration.", ), /** @description Sandbox permissions requested by the UI. */ permissions: McpUiResourcePermissionsSchema.optional().describe( "Sandbox permissions requested by the UI.", ), /** @description Dedicated origin for widget sandbox. */ domain: z .string() .optional() .describe("Dedicated origin for widget sandbox."), /** @description Visual boundary preference - true if UI prefers a visible border. */ prefersBorder: z .boolean() .optional() .describe( "Visual boundary preference - true if UI prefers a visible border.", ), }); /** * @description Request to change the display mode of the UI. * The host will respond with the actual display mode that was set, * which may differ from the requested mode if not supported. * @see {@link app!App.requestDisplayMode} for the method that sends this request */ export const McpUiRequestDisplayModeRequestSchema = z.object({ method: z.literal("ui/request-display-mode"), params: z.object({ /** @description The display mode being requested. */ mode: McpUiDisplayModeSchema.describe("The display mode being requested."), }), }); /** * @description Result from requesting a display mode change. * @see {@link McpUiRequestDisplayModeRequest} */ export const McpUiRequestDisplayModeResultSchema = z .object({ /** @description The display mode that was actually set. May differ from requested if not supported. */ mode: McpUiDisplayModeSchema.describe( "The display mode that was actually set. May differ from requested if not supported.", ), }) .passthrough(); /** * @description Tool visibility scope - who can access the tool. */ export const McpUiToolVisibilitySchema = z .union([z.literal("model"), z.literal("app")]) .describe("Tool visibility scope - who can access the tool."); /** * @description UI-related metadata for tools. */ export const McpUiToolMetaSchema = z.object({ /** * URI of the UI resource to display for this tool, if any. * This is converted to `_meta["ui/resourceUri"]`. * * @example "ui://weather/widget.html" */ resourceUri: z.string().optional(), /** * @description Who can access this tool. Default: ["model", "app"] * - "model": Tool visible to and callable by the agent * - "app": Tool callable by the app from this server only */ 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', ), }); /** * @description Request to send a message to the host's chat interface. * @see {@link app!App.sendMessage} for the method that sends this request */ export const McpUiMessageRequestSchema = z.object({ method: z.literal("ui/message"), params: z.object({ /** @description Message role, currently only "user" is supported. */ role: z .literal("user") .describe('Message role, currently only "user" is supported.'), /** @description Message content blocks (text, image, etc.). */ content: z .array(ContentBlockSchema) .describe("Message content blocks (text, image, etc.)."), }), }); /** * @description Notification containing HTML resource for the sandbox proxy to load. * @internal * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy */ export const McpUiSandboxResourceReadyNotificationSchema = z.object({ method: z.literal("ui/notifications/sandbox-resource-ready"), params: z.object({ /** @description HTML content to load into the inner iframe. */ html: z.string().describe("HTML content to load into the inner iframe."), /** @description Optional override for the inner iframe's sandbox attribute. */ sandbox: z .string() .optional() .describe("Optional override for the inner iframe's sandbox attribute."), /** @description CSP configuration from resource metadata. */ csp: McpUiResourceCspSchema.optional().describe( "CSP configuration from resource metadata.", ), /** @description Sandbox permissions from resource metadata. */ permissions: McpUiResourcePermissionsSchema.optional().describe( "Sandbox permissions from resource metadata.", ), }), }); /** * @description Notification containing tool execution result (Host -> Guest UI). */ export const McpUiToolResultNotificationSchema = z.object({ method: z.literal("ui/notifications/tool-result"), /** @description Standard MCP tool execution result. */ params: CallToolResultSchema.describe("Standard MCP tool execution result."), }); /** * @description Rich context about the host environment provided to Guest UIs. */ export const McpUiHostContextSchema = z .object({ /** @description Metadata of the tool call that instantiated this App. */ toolInfo: z .object({ /** @description JSON-RPC id of the tools/call request. */ id: RequestIdSchema.optional().describe( "JSON-RPC id of the tools/call request.", ), /** @description Tool definition including name, inputSchema, etc. */ tool: ToolSchema.describe( "Tool definition including name, inputSchema, etc.", ), }) .optional() .describe("Metadata of the tool call that instantiated this App."), /** @description Current color theme preference. */ theme: McpUiThemeSchema.optional().describe( "Current color theme preference.", ), /** @description Style configuration for theming the app. */ styles: McpUiHostStylesSchema.optional().describe( "Style configuration for theming the app.", ), /** @description How the UI is currently displayed. */ displayMode: McpUiDisplayModeSchema.optional().describe( "How the UI is currently displayed.", ), /** @description Display modes the host supports. */ availableDisplayModes: z .array(z.string()) .optional() .describe("Display modes the host supports."), /** * @description Container dimensions. Represents the dimensions of the iframe or other * container holding the app. Specify either width or maxWidth, and either height or maxHeight. */ containerDimensions: z .union([ z.object({ /** @description Fixed container height in pixels. */ height: z.number().describe("Fixed container height in pixels."), }), z.object({ /** @description Maximum container height in pixels. */ maxHeight: z .union([z.number(), z.undefined()]) .optional() .describe("Maximum container height in pixels."), }), ]) .and( z.union([ z.object({ /** @description Fixed container width in pixels. */ width: z.number().describe("Fixed container width in pixels."), }), z.object({ /** @description Maximum container width in pixels. */ 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.", ), /** @description User's language and region preference in BCP 47 format. */ locale: z .string() .optional() .describe("User's language and region preference in BCP 47 format."), /** @description User's timezone in IANA format. */ timeZone: z.string().optional().describe("User's timezone in IANA format."), /** @description Host application identifier. */ userAgent: z.string().optional().describe("Host application identifier."), /** @description Platform type for responsive design decisions. */ platform: z .union([z.literal("web"), z.literal("desktop"), z.literal("mobile")]) .optional() .describe("Platform type for responsive design decisions."), /** @description Device input capabilities. */ deviceCapabilities: z .object({ /** @description Whether the device supports touch input. */ touch: z .boolean() .optional() .describe("Whether the device supports touch input."), /** @description Whether the device supports hover interactions. */ hover: z .boolean() .optional() .describe("Whether the device supports hover interactions."), }) .optional() .describe("Device input capabilities."), /** @description Mobile safe area boundaries in pixels. */ safeAreaInsets: z .object({ /** @description Top safe area inset in pixels. */ top: z.number().describe("Top safe area inset in pixels."), /** @description Right safe area inset in pixels. */ right: z.number().describe("Right safe area inset in pixels."), /** @description Bottom safe area inset in pixels. */ bottom: z.number().describe("Bottom safe area inset in pixels."), /** @description Left safe area inset in pixels. */ left: z.number().describe("Left safe area inset in pixels."), }) .optional() .describe("Mobile safe area boundaries in pixels."), }) .passthrough(); /** * @description Notification that host context has changed (Host -> Guest UI). * @see {@link McpUiHostContext} for the full context structure */ export const McpUiHostContextChangedNotificationSchema = z.object({ method: z.literal("ui/notifications/host-context-changed"), /** @description Partial context update containing only changed fields. */ params: McpUiHostContextSchema.describe( "Partial context update containing only changed fields.", ), }); /** * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). * * Unlike `notifications/message` which is for debugging/logging, this request is intended * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. * Unlike messages, context updates do not trigger follow-ups. * * The host will typically defer sending the context to the model until the next user message * (including `ui/message`), and will only send the last update received. * * @see {@link app.App.updateModelContext} for the method that sends this request */ export const McpUiUpdateModelContextRequestSchema = z.object({ method: z.literal("ui/update-model-context"), params: z.object({ /** @description Context content blocks (text, image, etc.). */ content: z .array(ContentBlockSchema) .optional() .describe("Context content blocks (text, image, etc.)."), /** @description Structured content for machine-readable context data. */ structuredContent: z .record( z.string(), z .unknown() .describe("Structured content for machine-readable context data."), ) .optional() .describe("Structured content for machine-readable context data."), }), }); /** * @description Initialization request sent from Guest UI to Host. * @see {@link app!App.connect} for the method that sends this request */ export const McpUiInitializeRequestSchema = z.object({ method: z.literal("ui/initialize"), params: z.object({ /** @description App identification (name and version). */ appInfo: ImplementationSchema.describe( "App identification (name and version).", ), /** @description Features and capabilities this app provides. */ appCapabilities: McpUiAppCapabilitiesSchema.describe( "Features and capabilities this app provides.", ), /** @description Protocol version this app supports. */ protocolVersion: z.string().describe("Protocol version this app supports."), }), }); /** * @description Initialization result returned from Host to Guest UI. * @see {@link McpUiInitializeRequest} */ export const McpUiInitializeResultSchema = z .object({ /** @description Negotiated protocol version string (e.g., "2025-11-21"). */ protocolVersion: z .string() .describe('Negotiated protocol version string (e.g., "2025-11-21").'), /** @description Host application identification and version. */ hostInfo: ImplementationSchema.describe( "Host application identification and version.", ), /** @description Features and capabilities provided by the host. */ hostCapabilities: McpUiHostCapabilitiesSchema.describe( "Features and capabilities provided by the host.", ), /** @description Rich context about the host environment. */ hostContext: McpUiHostContextSchema.describe( "Rich context about the host environment.", ), }) .passthrough();