build-mcp-app
This skill should be used when the user wants to build an "MCP app", add "interactive UI" or "widgets" to an MCP server, "render components in chat", build "MCP UI resources", make a tool that shows a "form", "picker", "dashboard" or "confirmation dialog" inline in the conversation, or mentions "apps SDK" in the context of MCP. Use AFTER the build-mcp-server skill has settled the deployment model, or when the user already knows they want UI widgets.
npx skills add anthropics/claude-plugins-official --skill build-mcp-app --agent claude-code
Same command for any agent — swap --agent for codex, cursor, copilot.
Weekly change comes from our own snapshots, not the repository page — it measures attention, not adoption.
What it does
Instructs building an MCP app that serves UI resources to render interactive components inline in chat, atop a standard MCP server. It covers when to attach widgets to tools, and provides a scaffold for a minimal picker widget, including server setup, UI resource registration, and widget runtime integration.
How it works
The skill guides the developer to:
- Build an MCP app that serves UI resources and renders widgets in the chat surface, via a two-part registration: a tool that returns data and a separate UI resource that serves an HTML widget.
- Use a resourceUri via the _meta.ui.resourceUri to link tools to their UI, and implement the HTML in a registered resource (with mime type RESOURCE_MIME_TYPE).
- Implement an App-based widget inside an iframe, communicating with the host through methods such as app.ontoolresult, app.ontoolinput, app.sendMessage, app.updateModelContext, app.callServerTool, app.openLink, app.getHostContext, app.requestDisplayMode, app.downloadFile, and lifecycle via new App(info, caps, {autoResize: true}).
- Provide a minimal picker scaffold including server.ts logic to register a tool (e.g., pick_contact) and a corresponding HTML widget (widgets/picker.html) that consumes tool results and posts back user selections.
- Bundle the ext-apps UI bundle into the widget HTML to satisfy CSP restrictions, and configure the transport for the MCP server (StreamableHTTPServerTransport by default, with an option for StdioServerTransport for local MCPB packaging).
When to use it
Use after the build-mcp-server skill has settled the deployment model, or when the user explicitly asks for UI widgets in MCP. The skill also notes scenarios where a widget is appropriate (structured input, picker, confirm dialog, display of visuals, or live progress) and when to skip a widget in favor of plain text.
What it can touch
The skill references the following tools and resources:
- Tool: "pick_contact" with _meta.ui.resourceUri: "ui://widgets/picker.html"
- Resource: "Contact Picker" registered at "ui://widgets/picker.html" with MIME type RESOURCE_MIME_TYPE
- Widget runtime requires the App class from "@modelcontextprotocol/ext-apps" and uses the bundle from the ext-apps package to expose globalExtApps
- Server scaffolding imports include packages such as @modelcontextprotocol/sdk, @modelcontextprotocol/ext-apps/server, express, and zod
Caveats
- Widgets live inside an iframe and cannot access host DOM, cookies, or arbitrary network calls; communications are channeled via the App API and server tool calls.
- The UI bundle must be inlined into the widget HTML; external script fetching is blocked by CSP, hence bundling is mandatory.
- The host applies CSP and frame-domain restrictions; resources must declare external origins via CSP settings.
- Local MCPB packaging requires an alternative transport (StdioServerTransport) as noted in the scaffold.
# Build an MCP App (Interactive UI Widgets) An MCP app is a standard MCP server that **also serves UI resources** — interactive components rendered inline in the chat surface. Build once, runs in Claude *and* ChatGPT and any other host that implements the apps surface. The UI layer is **additive**. Under the hood it's still tools, resources, and the same wire protocol. If you haven't built a plain MCP server before, the `build-mcp-server` skill covers the base layer. This skill adds widgets on top. > **Testing in Claude:** Add the server as a custom connector in claude.ai (via a Cloudflare tunnel for local dev) — this exercises the real iframe sandbox and `hostContext`. See https://claude.com/docs/connectors/building/testing. ## Claude host specifics | `_meta.ui.*` key | Where | Effect | |---|---|---| | `resourceUri` | tool | Which `ui://` resource the host renders for this tool's results. | | `visibility: ["app"]` | tool | Hide a widget-only helper tool (e.g. geometry/image fetcher called via `callServerTool`) from Claude's tool list. | | `prefersBorder: false` | resource | Drop the host's outer card border (mobile). | | `csp.{connectDomains, resourceDomains, baseUriDomains}` | re
- Claude host specifics
- When a widget beats plain text
- Widgets vs Elicitation — route correctly
- Architecture: two deployment shapes
- Remote MCP app (most common)
- MCPB-packaged MCP app (local + UI)
- How widgets attach to tools
- Widget runtime — the App class
- Scaffold: minimal picker widget
- Design notes that save you a rewrite
- Testing
- Reference files
npm install @modelcontextprotocol/sdk @modelcontextprotocol/ext-apps zod express test.jsonl — one JSON-RPC message per line
What does the build-mcp-app skill do?
This skill should be used when the user wants to build an "MCP app", add "interactive UI" or "widgets" to an MCP server, "render components in chat", build "MCP UI resources", make a tool that shows a "form", "picker", "dashboard" or "confirmation dialog" inline in the conversation, or mentions "apps SDK" in the context of MCP. Use AFTER the build-mcp-server skill has settled the deployment model, or when the user already knows they want UI widgets.
How do I install it?
Run `npx skills add anthropics/claude-plugins-official --skill build-mcp-app --agent claude-code` — it drops the skill into your project so the agent can pick it up. Swap the --agent value for codex, cursor or copilot if you use one of those.
Where does this skill come from?
From anthropics/claude-plugins-official, a repository with 33,027 stars. We read it straight from the repository tree rather than a submitted listing, so what you see here is what is actually published.
Is a popular skill a good skill?
Not necessarily. Stars measure attention, not adoption — a repository can trend for a week and be abandoned. That is why we show the weekly change from our own snapshots next to the total, instead of a single flattering number.