The term "external" is misleading for MCP Apps because developers
typically interpret it as "third-party." However, MCP App HTML runs in
a sandboxed iframe with no same-origin server, so *all* origins must be
declared—including where your own bundled JS/CSS is served from. Using
"network" instead avoids this confusion and aligns with the detailed
explanations in `patterns.md` and `spec.types.ts`.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Single quotes in `concurrently` commands work on Unix shells but not on
Windows Command Shell (`cmd.exe`), causing the `INPUT` environment
variable to not be set and npm scripts to fail with errors like:
'cross-env' is not recognized as an internal or external command
Error: INPUT environment variable is not set
Replace single quotes with escaped double quotes (`\"`) in npm scripts
in all example `package.json` files.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new section to the patterns guide explaining how to configure
Content Security Policy and CORS for MCP Apps that make network requests:
- CSP via `_meta.ui.csp` controls browser-side permissions (`connectDomains`,
`resourceDomains`)
- CORS via `_meta.ui.domain` provides a stable origin for API servers to
allowlist
Includes a type-checked example showing `computeAppDomainForClaude()` helper
that hashes an MCP server URL to create a stable `*.claudemcpcontent.com`
subdomain. Also adds `@see` links to `McpUiResourceMeta` and `McpUiResourceCsp`
in `registerAppResource` JSDoc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: fix basic-host setup instructions in quickstart
Add missing root-level npm install and build steps before running
the basic-host example. Without these steps, the example fails because
it imports from dist/src/ which doesn't exist until the root package
is built.
Fixes setup failure when following quickstart tutorial.
* Update quickstart.md
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
---------
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
Clarifies when to use `localStorage` vs server-side storage for view state:
- Scope section intro to "recoverable" view state (easy to recreate)
- Add guidance for state representing user effort (bookmarks, annotations,
custom configurations) to use app-only tools instead
- Note that `viewUUID` should also be passed to app-only tools for scoping
- Clarify that example links are specifically for `localStorage` approach
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document how to serve binary content (e.g., video) via MCP resources
as base64-encoded blobs. Includes server-side registration using the
`blob` field and client-side fetching with conversion to data URIs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Documents the recommended approach for real-time dashboards that need to
poll server tools at regular intervals. Includes both Vanilla JS and
React examples with proper cleanup handling via `app.onteardown` and
`useEffect` cleanup functions respectively.
Also updates the "Tools that are private to Apps" section to mention
polling as a use case for app-only visibility.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert italic `_See example..._` text to `> [!NOTE]` callouts for better
visual prominence, and expand cross-references to include additional
relevant examples for each pattern.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename "host styling" section to "host context" and add safe area
insets handling
- Replace abstract `renderLoadingUI`/`renderFinalUI` example with
concrete code preview pattern for `ontoolinputpartial`
- Rename callback parameter `params` → `ctx` for clarity across all
`onhostcontextchanged` handlers
- Add CSS snippet for fullscreen border-radius handling
- Expand display mode example to show `availableDisplayModes` check
- Fix minor typos and wording consistency
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The `extractRegion()` function in `sync-snippets.ts` used `indexOf()` to
find region markers like `//#region persistData`. This caused incorrect
matching when one region name was a prefix of another—searching for
`persistData` would match `//#region persistDataServer` first if it
appeared earlier in the file.
The fix detects the file's line ending style and appends it to region
markers, ensuring exact matches:
- `//#region persistData\n` no longer matches `//#region persistDataServer\n`
This corrects `docs/patterns.md` where the `persistData` code fence was
incorrectly showing server-side code instead of client-side localStorage
helpers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: add stable spec release 2026-01-26
- Use git mv to copy specification from draft to specification/2026-01-26/apps.mdx (preserves history)
- Update status from 'Draft' to 'Stable (2026-01-26)'
- Add specification version table to README
- Update Resources section with links to both stable and draft specs
* chore: bump version to 1.0.0
- Update main package version from 0.4.2 to 1.0.0
- Update all example package versions to 1.0.0
- Regenerate package-lock.json
* prettier
* chore: align protocol version with spec release 2026-01-26
- Add 'Protocol Version: 2026-01-26' to spec header
- Update LATEST_PROTOCOL_VERSION from '2025-11-21' to '2026-01-26'
- Update spec examples to use '2026-01-26' protocol version
- Add '2025-11-21' to SUPPORTED_PROTOCOL_VERSIONS for backwards compatibility
* chore: update spec references to stable 2026-01-26
- Update typedoc.config.mjs navigation link
- Update docs/overview.md spec links (10 occurrences)
- Update plugins/mcp-apps/skills/create-mcp-app/SKILL.md spec link
- Update src/spec.types.ts @see links
- Update AGENTS.md spec path
- Regenerate src/generated/schema.ts with updated links
* chore: simplify versioning - first stable release
- Remove backwards compatibility version (2025-11-21) - this is the first stable release
- Remove redundant 'Protocol Version' header - spec version IS the protocol version
* chore: add history reference comment to stable spec
Update links from `claude.ai/docs/` to `claude.com/docs/` for the
remote and local MCP server configuration documentation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Codex to the list of agents supporting skills in `agent-skills.md`.
Add Goose to the list of supported clients in `testing-mcp-apps.md` and
rename "VS Code Copilot" to "VS Code (Insiders)" for accuracy.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add intro explaining what Agent Skills are and link to the two skill
files (`create-mcp-app`, `migrate-oai-app`). Reorganize headings and add
"Invoke a Skill" and "Test Your App" sections. Update `README.md` link
text and add tip to quickstart suggesting agent skills as an alternative.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document how to test MCP Apps using `basic-host` and MCP Apps-compatible
hosts like Claude.ai and VS Code Copilot. Cover debugging features for
`basic-host`, and using `cloudflared` to expose local servers for remote
hosts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add framing prose to the migration guide to improve navigation:
- Expanded intro describing document purpose and how to use it
- Added note about features marked "Not yet implemented"
- Added brief transition sentences before Server-Side and Client-Side sections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `docs/agent-skills.md` with installation instructions for multiple AI
coding agents including Claude Code, VS Code/Copilot, Gemini CLI, Cline,
and Goose. The guide provides three installation methods: Claude Code
plugin, Vercel Skills CLI (`npx skills add`), and manual installation.
Update `README.md` to link to the new guide and reframe the plugin
section around the broader "Agent Skills" concept.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds `docs/overview.md` covering the core concepts: architecture,
lifecycle, UI resources, bidirectional communication, theming, display
modes, and security. Includes mermaid flowchart and sequence diagrams.
Also adds the `@boneskull/typedoc-plugin-mermaid` TypeDoc plugin for
mermaid diagram support. However, the plugin handles HTML entities from
TypeDoc incorrectly, so `scripts/typedoc-plugin-fix-mermaid-entities.mjs`
decodes HTML entities before the plugin processes them.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrites the Quickstart tutorial to provide a more focused, step-by-step
introduction to building MCP Apps. The guide now uses synced code fences
that pull from `examples/quickstart/`, ensuring all code shown in the
documentation is type-checked and tested.
Key improvements:
- Clearer project setup instructions with explicit commands
- Streamlined explanations of the tool + resource registration pattern
- Added screenshot showing the completed app
- E2E test coverage validates the example works end-to-end
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Migrate JSDoc and markdown documentation from `{@includeCode ./file#region}`
tags to inline code fences with `source="./file#region"` attributes.
Code examples are now visible directly in source files while remaining
type-checked via their `.examples.ts` source files.
Add `scripts/sync-snippets.ts` to extract code from `//#region` blocks
and sync it into labeled fences. Run with `npm run sync:snippets`.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: standardize UI terminology to use "view" consistently
Replaces "widget" and "Guest UI" terminology with "view" across
the codebase as decided in the community survey.
This change updates:
- Specification document
- SDK source code and JSDoc comments
- Example servers and documentation
- Plugin documentation and skills
Closes#71
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit backtick-wrapped display text to all `{@link}` tags for
monospace rendering in TypeDoc output. This improves readability by:
- Using monospace font for code references (types, methods, functions)
- Stripping module prefixes from display text (e.g., `app!App.connect`
displays as `App.connect`)
Updated files across the SDK including `App`, `AppBridge`,
`PostMessageTransport`, React hooks, server helpers, types, and
documentation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Each pattern section now includes a "See examples/..." link pointing
to a working implementation in the repository. This helps readers
quickly find real code demonstrating each pattern.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add new pattern showing how to combine `updateModelContext()` with
`sendMessage()` when data exceeds message size limits. The example
demonstrates offloading a large transcript to model context first,
then sending a brief trigger message.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Documents `updateModelContext` for keeping the model informed about user
interactions. The example shows a shopping cart use case with YAML frontmatter
for structured, parseable context.
Also refines the `updateModelContext` JSDoc to clarify the difference from
`sendMessage` and removes the `structuredContent` example.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `IntersectionObserver` pattern for pausing expensive operations
(animations, WebGL, polling) when widgets scroll out of view.
- Add `visibilityBasedPause` example to `patterns.tsx` with play/pause
callbacks and `onteardown` cleanup
- Document pattern in `patterns.md` with link to MDN docs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces the TODO stub with complete server-side and client-side examples
based on the `pdf-server` implementation pattern:
- Server: shows returning `widgetUUID` via `CallToolResult._meta`
- Client: shows receiving UUID via `ontoolresult`, using it as localStorage
key with generic `saveState<T>()` / `loadState<T>()` helpers
Also clarifies the distinction between widget state persistence (UI state
surviving page reloads) and `updateModelContext()` (model-visible state).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds JSDoc example `App_updateModelContext_reportError` showing how to
report runtime errors (e.g., microphone permission denied) back to the
model using `updateModelContext`.
Updates patterns.md with clearer framing:
- Server-side (tool handler): return `{ isError: true, ... }`
- Client-side (app): use `updateModelContext` for runtime errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Expand `App_ontoolinputpartial_progressiveRendering` example in
`app.examples.ts` to show full state management pattern with
`toolInputs` and `toolInputsPartial` variables
- Add healed JSON caveat to `ontoolinputpartial` JSDoc in `app.ts`
- Update `patterns.md` to reference the expanded example and document
the streaming preview pattern
- Remove empty `lowerPerceivedLatency` placeholder from `patterns.tsx`
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `App_onhostcontextchanged_respondToDisplayMode` example showing how to
listen for display mode changes and update UI with `classList.toggle()`.
Update `App_requestDisplayMode_fullscreen` to `App_requestDisplayMode_toggle`
to show the common toggle pattern checking `availableDisplayModes` first.
Refactor full examples (pdf-server, shadertoy-server) to use
`classList.toggle(class, condition)` instead of add/remove branches.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge the separate "Support native host styling using CSS variables" and
"Reacting to light/dark theme changes" sections into a single "Matching
host styling (CSS variables, theme, and fonts)" pattern. This provides
clearer guidance by covering all three concerns together.
- Rename `docs/patterns.ts` to `docs/patterns.tsx` for JSX support
- Add `hostStylingVanillaJs` and `hostStylingReact` consolidated examples
- Enhance `applyHostFonts_fromHostContext` to apply initial fonts after
`connect()`, not just on context change
- Add CSS usage examples to `applyHostStyleVariables()` JSDoc
- Update font example to use `var(--font-sans, system-ui, sans-serif)`
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reference existing JSDoc examples instead of maintaining a separate one in
`docs/patterns.ts`:
- Vanilla JS: `applyDocumentTheme_fromHostContext` from `styles.examples.ts`
- React: `useDocumentTheme_conditionalRender` for reactive theme reading
Expand `applyDocumentTheme_fromHostContext` example to show both the
`onhostcontextchanged` handler and initial theme application after `connect()`.
Note in the docs that `useHostStyles()` applies theme automatically, so React
apps don't need additional setup unless they want to read the theme reactively
for conditional rendering.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
References existing type-checked examples instead of a stub:
- Vanilla JS: `applyHostStyleVariables_fromHostContext` from `src/styles.examples.ts`
- React: `useHostStyles_basicUsage` from `src/react/useHostStyles.examples.tsx`
Expanded `applyHostStyleVariables_fromHostContext` to show the full pattern:
using CSS variables in styles, applying on `onhostcontextchanged`, and
applying initial styles after `connect()`.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the `_meta.ui.visibility: ["app"]` feature in `docs/patterns.md`
by referencing the existing type-checked example from
`src/server/index.examples.ts#registerAppTool_toolVisibility`.
- Fix typo: `["apps"]` → `["app"]` (singular)
- Remove placeholder function from `docs/patterns.ts`
- Expand description to explain use cases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduces a patterns documentation page for common MCP Apps recipes.
The skeleton includes TODO sections for: perceived latency, iframe/MCP Apps
coexistence, authenticated calls, private tools, theme changes, fullscreen,
host styling, data persistence, OpenAI migration, and error handling.
- Add `docs/patterns.md` to `projectDocuments` in `typedoc.config.mjs`
- Add `docs/patterns.ts` companion file with region-delimited code stubs
- Include `docs/**/*.ts` in `tsconfig.json` for type-checking
- Document the standalone docs pattern in `CLAUDE.md`
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new skill (`plugins/mcp-apps/skills/migrate-oai-app/SKILL.md`)
that guides developers through migrating OpenAI Apps SDK applications
to the MCP Apps SDK. Includes API mapping tables, CSP configuration
guidance, and a "Before Finishing" checklist.
Also fixes the `registerAppResource()` JSDoc example in `src/server/index.ts`
to show CSP configuration in the correct location (on the content item,
not the resource config).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reorganize prerequisites to emphasize MCP concepts first
- Add tip linking to official MCP quickstart for newcomers
- Update install command to use published npm package
- Remove zod dependency and `structuredContent` usage
- Use `RESOURCE_MIME_TYPE` constant for consistency
- Add clearer comments explaining tool/resource registration
- Simplify UI to extract time from text content
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove 'server.ts' argument from 'npx tsc --noEmit' command.
When a file is specified directly, TypeScript ignores tsconfig.json,
causing skipLibCheck and other options to not apply. This results in
errors from node_modules (especially zod v4 locale files).
The correct command lets tsc use the project's tsconfig.json settings.
* docs: add tool visibility and restructure _meta.ui
- Restructure tool metadata: `_meta["ui/resourceUri"]` → `_meta.ui.resourceUri`
- Add `visibility` array field: ["model"], ["apps"], or ["model", "apps"]
- Default ["model"] preserves standard MCP behavior
- ["apps"] enables widget-only tools hidden from agent
- Add McpUiToolMeta interface for type safety
- Add Design Decision #4 explaining approach vs OpenAI's two-field model
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* address PR review comments
- Change default visibility to ["model", "apps"]
- Add deprecation notice for flat ui/resourceUri format
- Add McpUiToolMeta and McpUiToolVisibility to spec.types.ts
- Improve tools/list and tools/call behavior wording
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate schemas for McpUiToolMeta types
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: tool visibility and nested _meta.ui format
- Rename visibility "apps" → "app" in McpUiToolVisibility type
- Add _meta.ui.resourceUri nested format (deprecate flat format)
- Add getToolUiResourceUri() utility with backward compatibility
- Add visibility demo to system-monitor-server:
- get-system-stats: visibility ["model"] with resourceUri
- refresh-stats: visibility ["app"] (app-only polling)
- Update all example servers to use new _meta.ui format
- Add 11 unit tests for getToolUiResourceUri()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate schemas with updated dependencies
* feat: export McpUiToolMeta type and add type annotations
- Export McpUiToolMeta and McpUiToolVisibility types from types.ts
- Export corresponding Zod schemas (McpUiToolMetaSchema, McpUiToolVisibilitySchema)
- Add `as McpUiToolMeta` type annotations to all example servers
- Update docs/quickstart.md with proper typing
Ensures type safety for `_meta.ui` tool metadata across the codebase.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add server helpers and optional connect() transport
Add `src/server/` with convenience functions for registering MCP App tools
and resources:
- `registerAppTool(server, name, config, handler)`
- `registerAppResource(server, name, uri, config, callback)`
The `transport` parameter in `App.connect()` is now optional, defaulting to
`PostMessageTransport(window.parent)`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update src/server/index.ts
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
* feat: update McpUiAppToolConfig to support both _meta.ui and flat formats
* refactor: simplify server helper imports
* docs: add deprecation notice and improve resourceUri documentation
* feat: add backward compat normalization in registerAppTool
- If _meta.ui.resourceUri is set, also set legacy flat key
- If legacy flat key is set, also set _meta.ui.resourceUri
- Preserves existing visibility when merging
- Does not overwrite if both formats already set
* refactor: avoid mutating config arg in registerAppTool
* style: format with prettier
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
According to spec, mimeType should be present in both the resource
declaration and the resource content. This adds the missing mimeType
to the registerResource() declaration (third parameter) in all example
servers and the quickstart documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ochafik <olivier.chafik@gmail.com>