View the source code for this module on GitHub: https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/mcp-use/src/server/widgets/mcp-ui-adapter.ts
server.uiResource(...) (see UIResource), which calls these helpers internally. The functions and types here are the building blocks for that pipeline and are also exported for advanced use.
A widget is shipped as a ui:// resource plus tool metadata. mcp-use supports two protocols from a single definition:
- MCP Apps Extension (SEP-1865): mime type
text/html;profile=mcp-app, metadata under_meta.ui.*, camelCase CSP keys. Used by Claude, Goose, and other MCP Apps clients. - ChatGPT Apps SDK: mime type
text/html+skybridge, metadata underopenai/*keys, snake_case CSP keys.
Resource builders
These functions produceUIResourceContent objects ({ type: "resource", resource }) that you can return from a tool or resource handler. They are the lower-level primitives behind createUIResourceFromDefinition.
createUIResourceFromDefinition
Create aUIResourceContent from a high-level UIResourceDefinition. This is the main router: it inspects the discriminated type field and delegates to the appropriate builder.
type ("externalUrl", "rawHtml", "remoteDom", "appsSdk", or "mcpApps").
The resource URI is derived from definition.name. For appsSdk and mcpApps types it is ui://widget/<name>.html; for the others it is ui://widget/<name>. When config.buildId is set, it is appended to the name (ui://widget/<name>-<buildId>...) for cache busting. The encoding defaults to "text" when definition.encoding is not set. For the externalUrl type, params are passed through buildWidgetUrl to build the iframe URL. Throws Error("Unknown UI resource type: ...") if the definition type is not one of the supported values (enforced by an exhaustiveness check).
Parameters
ReturnsUIResourceDefinitionrequiredUIResource definition (discriminated union ontype)Record<string, any>requiredRuntime parameters for the widget (used for theexternalUrltype)UrlConfigrequiredURL configuration used when building widget URLs
SignaturePromise<UIResourceContent>
createMcpAppsResource
Create aUIResourceContent for the MCP Apps Extension (SEP-1865) using the text/html;profile=mcp-app mime type.
resource._meta.ui per SEP-1865. Only the fields you set are emitted: csp is included when it has at least one key, prefersBorder when it is not undefined, and domain when truthy. If no metadata fields apply, _meta is omitted entirely.
Parameters
ReturnsstringrequiredResource URI (must start withui://)stringrequiredHTML template with embedded component code{ description?: string; csp?: { connectDomains?: string[]; resourceDomains?: string[]; frameDomains?: string[]; baseUriDomains?: string[] }; prefersBorder?: boolean; domain?: string }MCP Apps metadata (CSP, border preference, domain)
SignatureUIResourceContent
createExternalUrlResource
Create aUIResourceContent that loads an external URL in an iframe.
@mcp-ui/server’s createUIResource with content: { type: "externalUrl", iframeUrl }. Use this for widgets served from a separate origin (for example a Vite dev server or a deployed static site).
Parameters
ReturnsstringrequiredResource URI (must start withui://)stringrequiredURL to load in the iframeUIEncodingdefault:"\"text\""Encoding type ("text"or"blob")AdaptersConfigAdapter configuration (for example Apps SDK) passed through to@mcp-ui/serverAppsSdkMetadataAdditional metadata for the resource
SignaturePromise<UIResourceContent>
createRawHtmlResource
Create aUIResourceContent that renders raw HTML inline.
@mcp-ui/server’s createUIResource with content: { type: "rawHtml", htmlString }. The HTML is delivered inline rather than loaded from a URL.
Parameters
ReturnsstringrequiredResource URI (must start withui://)stringrequiredHTML content to renderUIEncodingdefault:"\"text\""Encoding type ("text"or"blob")AdaptersConfigAdapter configuration (for example Apps SDK)AppsSdkMetadataAdditional metadata for the resource
SignaturePromise<UIResourceContent>
createRemoteDomResource
Create aUIResourceContent for Remote DOM scripting.
application/vnd.mcp-ui.remote-dom+<framework>. Because remoteDom was removed from createUIResource in @mcp-ui/server v6, this constructs the resource object manually. When encoding is "blob", the script is base64-encoded into resource.blob; otherwise it is placed in resource.text.
The
adapters and metadata parameters are accepted for signature parity but are not applied (they are prefixed with an underscore in the implementation). The MIME type is still rendered by @mcp-ui/client.ReturnsstringrequiredResource URI (must start withui://)stringrequiredJavaScript code for remote DOM manipulation"react" | "webcomponents"default:"\"react\""Framework for remote DOMUIEncodingdefault:"\"text\""Encoding type ("text"or"blob")AdaptersConfigAccepted for parity; not appliedAppsSdkMetadataAccepted for parity; not applied
SignaturePromise<UIResourceContent>
buildWidgetUrl
Build the full URL for a locally served widget, including encoded props.<baseUrl>:<port>/mcp-use/widgets/<slug>. The widget name is slugified for URL safety. When props is provided and non-empty, all props are serialized into a single props query parameter as JSON. When props is undefined or an empty object, no query parameter is added.
Parameters
ReturnsstringrequiredWidget identifier (slugified for the URL path)Record<string, any> | undefinedrequiredParameters passed as a single JSON-encodedpropsquery paramUrlConfigrequiredURL configuration (baseUrl,port, optionalbuildId)
Signaturestring
UrlConfig
Configuration for building widget URLs, consumed by buildWidgetUrl and createUIResourceFromDefinition.SignaturestringrequiredBase URL of the server (for examplehttp://localhost)number | stringrequiredServer port appended to the base URLstringOptional build ID appended to widget URIs for cache busting
Protocol adapters
Adapters transform a single UnifiedWidgetMetadata definition into protocol-specific tool and resource metadata. Both implement ProtocolAdapter.AppsSdkAdapter
Protocol adapter that emits ChatGPT Apps SDK metadata.text/html+skybridge, flat _meta keys prefixed with openai/, and snake_case CSP fields (connect_domains, resource_domains, and so on).
buildToolMetadata always sets openai/outputTemplate to the resource URI and copies openai/toolInvocation/invoking, openai/toolInvocation/invoked, openai/widgetAccessible, and openai/resultCanProduceWidget from appsSdkMetadata when present. It falls back to metadata.invoking and metadata.invoked for the invocation status keys. buildResourceMetadata extends the base implementation by copying additional openai/* fields from appsSdkMetadata when they are not already set.
Members
SignaturestringReadonly. Always"text/html+skybridge"."apps-sdk"Readonly protocol identifier.Record<string, unknown>Builds Apps SDK tool metadata for a definition and resource URI.{ mimeType: string; _meta?: Record<string, unknown> }Builds Apps SDK resource metadata (mime type plus_meta).
McpAppsAdapter
Protocol adapter that emits MCP Apps Extension (SEP-1865) metadata.text/html;profile=mcp-app (the value of RESOURCE_MIME_TYPE), metadata under the _meta.ui.* namespace, and camelCase CSP fields kept as-is.
buildToolMetadata returns the new nested form { ui: { resourceUri } } and also includes the legacy flat key RESOURCE_URI_META_KEY pointing at the same URI for backward compatibility with older clients. Resource metadata is wrapped under _meta.ui.
Members
SignaturestringReadonly. EqualsRESOURCE_MIME_TYPE("text/html;profile=mcp-app")."mcp-apps"Readonly protocol identifier.Record<string, unknown>Builds MCP Apps tool metadata (ui.resourceUriplus the legacy flat key).{ mimeType: string; _meta?: Record<string, unknown> }Builds MCP Apps resource metadata wrapped under_meta.ui.
ProtocolAdapter
The interface implemented by every protocol adapter (AppsSdkAdapter and McpAppsAdapter).MethodsstringrequiredReadonly mime type for this protocol (text/html;profile=mcp-appfor MCP Apps,text/html+skybridgefor Apps SDK)"mcp-apps" | "apps-sdk"requiredReadonly protocol identifier
SignatureRecord<string, unknown>requiredBuild protocol-specific tool metadata from a definition and resource URI{ mimeType: string; _meta?: Record<string, unknown> }requiredBuild protocol-specific resource metadata (includesmimeTypeand optional_meta)
CSPConfig
Unified Content Security Policy configuration. Adapters map these camelCase fields to MCP Apps (camelCase) or Apps SDK (snake_case) format.Signaturestring[]Domains allowed for fetch, XHR, and WebSocket connectionsstring[]Domains allowed for images, scripts, stylesheets, and fontsstring[]Allowed iframe originsstring[]Allowed base URIs for the document (SEP-1865)string[]Domains foropenExternalwithout a confirmation modal (ChatGPT only, not in SEP-1865)string[]CSP directive literals to include inscript-src(for example'unsafe-eval'). Use with caution, these weaken security.string[]CSP directive literals to include instyle-src(for example'unsafe-inline')
UnifiedWidgetMetadata
Protocol-agnostic widget metadata. Write it once, and adapters transform it into both MCP Apps and Apps SDK formats.SignaturestringDescription of the widgetCSPConfigContent Security PolicybooleanRequest a visible border around the widgetstringDedicated domain for widget isolationstringHuman-readable summary for the AI model (ChatGPT only){ camera?; microphone?; geolocation?; clipboardWrite?; [key: string]: any }Sandbox permissions requested by the UI (SEP-1865). Hosts MAY honor these via iframeallowattributes.booleanEnable automatic size change notifications (legacy MCP-UI, still supported)stringStatus text shown while the tool is running. Maps toopenai/toolInvocation/invoking. Defaults to"Loading {name}...".stringStatus text shown after the tool completes. Maps toopenai/toolInvocation/invoked. Defaults to"{name} ready".
RESOURCE_MIME_TYPE
The MCP Apps Extension mime type, re-exported from@modelcontextprotocol/ext-apps.
"text/html;profile=mcp-app". It is the value returned by McpAppsAdapter’s mimeType property. Re-exported from @modelcontextprotocol/ext-apps/server for convenience.
Signature
RESOURCE_URI_META_KEY
The legacy flat_meta key for an MCP Apps resource URI, re-exported from @modelcontextprotocol/ext-apps.
_meta key under which the resource URI is duplicated for backward compatibility with older MCP Apps clients (McpAppsAdapter also emits the newer nested ui.resourceUri form). Re-exported from @modelcontextprotocol/ext-apps/server.
Signature
Widget definition types
These types describe widgets at the discovery and manifest level.WidgetManifest
Manifest describing a built widget on disk.name must match the widget directory or file name.
Properties
SignaturestringrequiredUnique widget identifier (must match directory or file name), for example"weather-display"stringHuman-readable titlestringDescription of what the widget displaysstringSemantic version of the widgetWidgetPropsWidget props schema (type, required, default per prop)[string, string]Preferred frame size[width, height], for example["800px", "600px"]{ main?: string; scripts?: string[]; styles?: string[] }Asset paths for the main entry, scripts, and styles
WidgetMetadata
Metadata exported from a React widget module (aresources/*.tsx file) for auto-discovery and auto-registration.
widgetMetadata. The auto-discovery pipeline reads it to register the widget and (when exposeAsTool is not false) an MCP tool.
This type is exported from
mcp-use/react, not mcp-use/server. It is documented here because it configures the same dual-protocol widget pipeline.SignaturestringHuman-readable title for the widgetstringDescription shown to the model and used for auto-registered tool descriptionsz.ZodTypeAny | InputDefinition[]Zod schema (preferred) orInputDefinitionarray for widget props validationz.ZodTypeAny | InputDefinition[]Deprecated. Usepropsinstead.z.ZodTypeAny | InputDefinition[]Deprecated. Usepropsinstead.((params: Record<string, any>) => CallToolResult | TypedCallToolResult<any>) | CallToolResult | TypedCallToolResult<any>Function or static value producing the tool output (what the model sees). Defaults to a summary message.booleandefault:"true"Whether to auto-register this widget as an MCP tool. Set tofalsewhen paired with a customserver.tool().ResourceAnnotations & Partial<ToolAnnotations>Annotations applied to both the resource and the toolRecord<string, unknown>Optional raw metadata for the widgetAppsSdkMetadataDeprecated. Legacy ChatGPT-only metadata. Prefermetadatafor dual-protocol support.{ description?; csp?: CSPConfig; prefersBorder?; domain?; widgetDescription?; autoResize?; invoking?; invoked? }Unified dual-protocol metadata. Write once; the server generates both Apps SDK and MCP Apps formats.
DiscoverWidgetsOptions
Options for discovering and registering widgets from a directory.SignaturestringPath to the widgets directory. Defaults todist/resources/mcp-use/widgets.booleandefault:"false"Automatically register widgets that do not have manifestsstring | RegExpFilter widgets by name pattern, for example"weather-*"
Landing page
MCPServer renders the v1 landing frontend at its exact basePath for GET and HEAD requests that explicitly accept text/html. It includes the animated mesh-gradient hero, endpoint copy control, hosted Manufact Inspector link, client installation tabs, and optional tools, prompts, and static resources registered before the server starts.
Without OAuth, the page is public. With OAuth, it requires a bearer token by default. Set publicLandingPage: true to expose only the HTML page without a token; JSON, event-stream, wildcard probes, DELETE, and POST remain protected.
generateLandingPage
Generate the same v1-compatible HTML document outsideMCPServer. The page includes SEO and JSON-LD metadata, connection instructions for common MCP clients, the hosted Manufact Inspector link, and optional icon and primitive lists. Its CSS and behavior are inline; the Outfit stylesheet and GitHub stars badge load from their original external URLs. Caller-provided values are escaped before entering HTML, including the JSON-LD script payload.
ReturnsLandingPageOptionsrequiredServer identity, endpoint URL, optional icon URL, and primitive lists.
Signaturestring
LandingPageOptions requires name, version, and the absolute public MCP endpoint url. It also accepts title, description, iconUrl, tools, prompts, and resources.
LandingPageTool
A tool entry rendered in the landing page Primitives section.SignaturestringrequiredTool namestringOptional human-readable titlestringOptional tool description
LandingPagePrompt
A prompt entry rendered in the landing page Primitives section.SignaturestringrequiredPrompt namestringOptional human-readable titlestringOptional prompt description
LandingPageResource
A resource entry rendered in the landing page Primitives section.SignaturestringrequiredResource URIstringOptional resource namestringOptional human-readable titlestringOptional resource description
Type generation
generateToolRegistryTypes
Generate TypeScript type definitions for theToolRegistry from registered tools and write them to .mcp-use/tool-registry.d.ts.
declare module "mcp-use/react" augmentation of the ToolRegistry interface. This powers type-safe tool calls in the useCallTool React hook. It is invoked automatically during development (on startup and on tool or widget changes) and by the mcp-use generate-types CLI command.
Behavior and edge cases:
- Production-safe: returns
trueimmediately and writes nothing whenprocess.env.NODE_ENV === "production". - Deterministic: tools are sorted alphabetically by name before generation.
- Idempotent writes: the new content is compared against the existing file (ignoring the timestamp line); if unchanged, the file is not rewritten.
- Defaults: a tool with no input
schemais typed asnull; a tool with nooutputSchemais typed asRecord<string, unknown>.
ReturnsMap<string, { config: ToolDefinition; handler: ToolCallback }>requiredThe server’sregistrations.toolsmapstringdefault:"process.cwd()"Project root directory where.mcp-use/is written
SignaturePromise<boolean>