Official repo for spec & SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers
by modelcontextprotocolLast 12 weeks ยท 413 commits
5 of 6 standards met
Summary Adds full interactivity and rich annotation support to the CesiumJS map server: Unified annotation system โ discriminated union ( in JSON Schema) supporting marker, route (polyline), area (polygon), and circle (ellipse) annotation types Interact tool โ , , , actions via command queue with 200ms batching Streaming support โ progressively renders annotations as the model streams them (skipping last potentially-truncated item) Geocode tool โ multi-query OpenStreetMap Nominatim search with rate limiting show-map โ accepts initial annotations, supports bounding box or center+radius viewport modes Persistence โ annotations and camera state saved to localStorage, restored on revisit Copy/export โ toolbar button copies all annotations as Markdown table + GeoJSON (multi-mime clipboard) Canvas label billboards โ DPR-aware rendered labels with rounded-rect backgrounds, anchored per annotation type Fullscreen โ keyboard shortcuts (Escape, Ctrl/Cmd+Enter) and toolbar button Model context updates โ debounced camera position + screenshot sent to model on navigation Annotation types JSON Schema Uses which produces proper with discriminator values. Separate full schemas (for ) and update schemas (partial fields, for ). Test plan [ ] with no annotations โ globe loads at default/bbox location [ ] with mixed annotations โ markers, routes, areas, circles render correctly [ ] add/update/remove โ annotations appear/change/disappear [ ] Navigate action โ camera flies to new bounding box [ ] Geocode with multiple queries โ results returned with coordinates and bounding boxes [ ] Annotations persist across page reloads (localStorage) [ ] Copy button โ clipboard contains Markdown + GeoJSON [ ] Streaming () โ annotations render progressively [ ] Fullscreen toggle works via button and keyboard shortcuts ๐ค Generated with Claude Code
Describe the bug An MCP App (ext-apps OpenSeadragon deep-zoom viewer) loads and renders its UI inside the sandbox iframe โ header, metadata bar, zoom controls all appear โ but network requests to declared / origins are blocked. The tile canvas remains blank. No image content renders. This worked correctly until ~Feb 26, 2026 and broke without any server-side code changes, suggesting a change in how the host client (claude.ai) applies CSP or network restrictions to the sandbox iframe. CSP configuration The MCP server declares both (maps to , , ) and (maps to ) on the viewer resource: This configuration has not changed since the viewer was first deployed (~two weeks ago). The viewer uses OpenSeadragon (loaded from CDN) to fetch IIIF Image API tiles from . To Reproduce 1. Connect to the rijksmuseum-mcp-plus MCP server (public, npm: ) 2. Call with (Rembrandt, The Night Watch) 3. The ext-apps viewer iframe loads โ OpenSeadragon initialises, controls are visible, navigator panel is present 4. The tile canvas is empty โ no image content renders Reproducible on any . The failure is structural, not artwork-specific. Expected behaviour OpenSeadragon should fetch via XHR () and load tiles via `img-srciiif.micr.iohttps://iiif.micr.io/PJEZO/info.jsonaccess-control-allow-origin: get_artwork_imaged935609acdn.jsdelivr.netiiif.micr.ioaccess-control-allow-origin: @modelcontextprotocol/ext-appsiiif.micr.ioavailableDisplayModes: ['inline', 'fullscreen']prefersBorder: falseresources/read` โ not loaded from an external URL. Related issues in this repo: #374 (map server CSP), #387 (frameDomains CSP mapping).
Repository: modelcontextprotocol/ext-apps. Description: Official repo for spec & SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers Stars: 1725, Forks: 194. Primary language: TypeScript. Languages: TypeScript (70.3%), MDX (25.5%), JavaScript (4.2%). Homepage: https://apps.extensions.modelcontextprotocol.io/ Topics: ai, apps, mcp, mcp-apps, modelcontextprotocol, ui. Latest release: v1.1.2 (3d ago). Open PRs: 60, open issues: 56. Last activity: 23h ago. Community health: 87%. Top contributors: ochafik, jonathanhefner, antonpk1, martinalong, localden, idosal, liady, jerome3o-anthropic, Avcharov, dependabot[bot] and others.
TypeScript
Summary Adds full annotation, interaction, and page extraction capabilities to the PDF server: Interact tool with command queue pattern (server enqueues โ client polls โ processes): Navigation: , , , , Annotations: (7 types: highlight, underline, strikethrough, note, rectangle, freetext, stamp), , Text highlighting: โ auto-find and highlight text by query Page extraction: โ batch text and/or screenshot extraction from page ranges without visual navigation (offscreen rendering) Form filling: โ fill PDF form fields Annotated PDF download via (client-side) + SDK support Annotation persistence in localStorage keyed by viewUUID validation โ interact returns clear error if UUID doesn't match an active viewer Prompt engineering** โ display_pdf result enumerates all interact actions; interact description leads with annotation capabilities; schema simplified from 7,802 โ 2,239 chars (dropped 14-variant anyOf union) New dependency (^1.17.1) โ client-side PDF modification for annotated download Files changed Test plan [x] โ 6 tests pass (annotation CRUD, highlight_text) [x] โ existing screenshot tests pass [x] โ 3/3 pass (model discovers annotations) [x] โ compiles cleanly [ ] Manual: display PDF in Claude, use interact to annotate, click download ๐ค Generated with Claude Code
Is your feature request related to a problem? Please describe. When building interactive workflows with MCP Apps, there is currently no protocol-level way to pause an agent until a user completes a UI interaction. A tool call that includes renders a rich UI, but the tool returns immediately โ the agent continues without waiting for the user. The only workaround is instructing the agent via tool description text to "wait for the user", which is fragile and LLM-dependent. Elicitation () does block the server while waiting for user input, but the client renders only a flat form derived from the JSON schema. This makes elicitation unsuitable for interactions that require rich UI โ multi-step flows, visual pickers, data tables, custom confirmation dialogs, and so on. The result is a gap: there is no way to say "show the user this rich UI, collect their input, and only then let the server continue." Describe the solution you'd like Allow a server to include a hint on an request. When present, a host that supports both MCP Apps and elicitation renders the referenced UI resource instead of the default flat form. The UI collects the user interaction and resolves the elicitation with a response conforming to , unblocking the server. The flow would be: 1. Server issues with both and . 2. Host fetches and renders the UI resource in a sandboxed iframe (standard MCP Apps flow). 3. Host passes the elicitation context to the UI (e.g. via or a new event). 4. User completes the interaction; the UI calls back with data satisfying (e.g. via or a new method). 5. Host sends the response to the server, which unblocks and completes the tool call. Hosts that do not support MCP Apps fall back gracefully to the flat form from โ fully backwards compatible. Describe alternatives you've considered Tool description instructions โ telling the LLM agent to "wait for the user to interact with the UI before proceeding." This works in practice but is fragile, model-dependent, and not a protocol guarantee. Having the UI call a dedicated follow-up tool โ the UI triggers a second tool call via after the user completes the interaction, effectively signalling completion. This bypasses the agent entirely and works today, but means the original tool call has already returned, so the server cannot use the user's input to complete the original operation and return a result to the agent. SEP-1686 Tasks ( state) โ the Tasks proposal models a server pausing to wait for elicitation during a long-running operation. This is complementary but a heavier primitive; attaching a UI resource to a standard elicitation request is a simpler, more targeted solution for the interactive UI use case. Additional context** A concrete real-world scenario: an MCP server exposes a tool that retrieves a customer portfolio and asks the user to assign an account manager. The ideal UX is a rich dashboard (cards, health indicators, a dropdown to select the manager) rendered inline in the agent chat. Today this requires either accepting that the agent won't wait for the user, or working around it with tool description hacks. Rich UI elicitation would make this a first-class, reliable pattern. This proposal composes two existing MCP primitives rather than introducing new ones โ the elicitation blocking mechanism stays unchanged, and the pattern follows what MCP Apps already does for tool calls. The main open design question is whether the UI resolves the elicitation via an existing call to a server-side endpoint, or via a new host-level API like . Related: MCP Elicitation spec: [specification/2025-06-18/client/elicitation.mdx](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/client/elicitation.mdx) SEP-1036 URL Mode Elicitation: [modelcontextprotocol#1036](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1036) SEP-1686 Tasks: [modelcontextprotocol#1686](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686) MCP Apps spec (SEP-1865): [specification/draft/apps.mdx](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx)
Summary Ignore MCP client roots by default* when the pdf-server starts via . Clients may advertise roots that point to directories on the client's* filesystem, but the server resolves them locally โ giving the client unintended access to the server's machine. Add CLI flag to explicitly opt in to honoring client roots (for trusted/local clients). Add interface with boolean (defaults to ) so programmatic callers have the same control. Test plan [x] Existing unit tests continue to pass (119/119) [x] New tests verify does not set up roots handlers by default [x] New tests verify sets up roots handlers [ ] Manual: start server with and confirm roots are ignored (log message printed) [ ] Manual: start server with and confirm roots are honored https://claude.ai/code/session_014ohk5NMEPe8TBKpqp4ZRSw