MCP App (Apps SDK / widgets) metadata
MCP Apps ship UI surfaces (widgets) through the same MCP protocol as tools: discovery via tools/list and resources/list, HTML (or other) payload via resources/read, and optional prompts/list if you expose prompts. _meta on tools, resources, and resource contents tells the host which URI to load and how to embed it safely (including CSP-style domain allowlists).
Typical host flow
tools/list— Model and host learn tool names, schemas, and tool-level_meta(often including which resource URI opens the widget).resources/list— Host learns which URIs exist for templates or static UI assets.- User invokes a tool →
tools/call— Handler returns text (and/or structured content) plus optional result_meta; some hosts read_metahere to confirm or refresh the UI resource URI. resources/readon that URI — Returns contents (e.g. HTML) and per-content_metaused for iframe template binding, base URL / domain, and network or resource allowlists so the embedded app can call your API and Agentsyx without being blocked by default embed policies.
prompts/list is optional for widget-first apps; omit it if you do not ship prompts.
Linking tools to UI resources
Use a stable resource URI (for example ui://your-app/widget.html) everywhere:
- On the tool definition (from
tools/list):_metashould point the host at that URI (common pattern: a nested object such asui.resourceUri—exact shape may follow your SDK or host conventions). - On
tools/callresults: repeat the same URI in result_metaif your host reads the call response to decide which resource to load or refresh (some stacks use bothuiand a flatui/resourceUri-style key).
Keep the URI stable across releases when possible; changing it is a breaking change for hosts and upstream mappings.
resources/read and content _meta (embedding and CSP)
The resources/read response includes contents (e.g. MIME type and HTML string) and, for each content item, extensible _meta.
Hosts use that _meta to:
- Bind the HTML to a template or output surface (vendor-specific key names are common—treat them as examples of host extensions, not part of the core MCP spec text).
- Declare a widget base domain or origin the iframe should trust for script or asset loads.
- Supply CSP-related allowlists—for example which origins the widget may connect to (
fetch, XHR) and which resource domains (images, scripts, frames) are allowed—so your UI can reach your API and Agentsyx without violating embed defaults.
Document intent (what each class of field is for) in your runbook; do not hard-code production URLs in public docs—list categories (API origin, Agentsyx, your static host) your CSP must include.
Optional tool arguments on the Apps-facing tool (for example anonymous short id, portal URL, login URL) may be filled by the host or platform; see Injected parameters & metadata.
Widget runtime: calling server tools from the UI
The embedded bundle (for example built with @modelcontextprotocol/ext-apps) should connect to the MCP session before running UI code that invokes tools—otherwise callServerTool (or equivalent) can fail with a not-connected error.
Use callServerTool with name and arguments that match tools the host actually exposes after upstream mapping (in Agentsyx, those are often the downstream tools wired to your connector—e.g. loadMyChats, widgetAdd in the Chat Vault reference).
Host–widget logging (Agentsyx)
The MCP App host can forward diagnostic events to the iframe via postMessage. Widgets should filter for:
type:"agentsyx-log"source:"mcp-host"
Optional fields such as level, message, and context can be shown in an in-widget debug panel—useful on mobile where browser devtools are limited.
Directory and review considerations
Storefronts and hosts expect a coherent product surface (web SaaS + optional chat). Keep names, descriptions, and privacy-related disclosures aligned across your portal, MCP servers, and embedded UI.
This page stays reference-level; submission checklists live with your release process.
Reference implementation
Chat Vault illustrates the split:
chat-vault-part-mcp-app— MCP App server + Vite widget:registerAppTool/registerAppResource, Streamable HTTPPOST /mcp, tool and resource_meta, widgetcallServerToolto backend tools.chat-vault-part2— Separate MCP tools server (API key,x-a6-*headers) for data operations.
Your layout does not have to match; the important part is standard MCP tools/* and resources/* plus consistent _meta and CSP for embedding.