* fix: Move CSP to HTTP headers + add worker-src, frameDomains, baseUriDomains, permissions
Security improvements:
- CSP is now set via HTTP headers in serve.ts instead of meta tags
(meta tag CSP can be tampered with by same-origin content)
- CSP passed as query param to sandbox.html for header-based enforcement
New CSP/permissions features (borrowed from PR #158):
- frameDomains: control frame-src directive for nested iframes
- baseUriDomains: control base-uri directive
- permissions: camera, microphone, geolocation via iframe allow attribute
WebGL fix:
- Use document.write() instead of srcdoc for inner iframe content
(srcdoc creates opaque origin that breaks WebGL canvas updates)
- Add worker-src directive with blob: support (critical for WebGL apps
like CesiumJS/Three.js that use workers for tile decoding, terrain
processing, image processing)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: Remove permissions support (defer to PR #158)
Keep this PR focused on CSP security fixes only.
Permissions (camera, microphone, geolocation) will be
handled in #158.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* cleanup McpUiResourceCsp type usage / duplicate defs
* fix: guard against CSP injection in domain parameters
Validate CSP domain entries to reject characters that could:
- Break out of CSP directives (semicolons, newlines)
- Inject CSP keywords like 'unsafe-eval' (quotes)
- Inject multiple sources in one entry (spaces)
This prevents injection attacks where malicious domains could
override the security policy.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* 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>
The spec used `ui/notifications/sandbox-ready` but the implementation
uses `ui/notifications/sandbox-proxy-ready`. Updated the spec to match.
Also fixed a typo: `ui/sandbox-resource-ready` → `ui/notifications/sandbox-resource-ready`
Fixes#156🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
This adds the media-src directive to the Content Security Policy to enable
MCP Apps to play video and audio content.
Changes:
- Add media-src to the restrictive default CSP in the spec
- Add media-src to the CSP construction from metadata in the spec
- Update resourceDomains documentation in spec to include media
- Update resourceDomains JSDoc in src/types.ts to include media-src
Fixesmodelcontextprotocol/ext-apps#106
Update `ui/host-context-change` to `ui/notifications/host-context-changed`
to match the SDK implementation and follow the notifications naming convention.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Change MIME type from `text/html+mcp` to `text/html;profile=mcp-app`
to follow RFC 6838 recommendations for custom media types.
The `+suffix` format (like `text/html+mcp`) is intended for structured
syntax suffixes (e.g., `+json`, `+xml`) that describe the underlying
format. Since MCP Apps doesn't define a new syntax but rather a profile
of HTML, using a profile parameter is more semantically correct.
Fixes#59🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Safe area insets apply on web as well, not just mobile devices.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The host should resolve "system" to either "light" or "dark" before
passing the theme to the app. Apps only need to know the actual
resolved theme value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
Change connect_domains and resource_domains to connectDomains and
resourceDomains for consistency with the rest of the specification
which uses camelCase naming convention.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The UIResource interface incorrectly specified `_meta?: UIResourceMeta`
when it should be `_meta?: { ui?: UIResourceMeta }` to match the
resources/read response format and all usage examples throughout the
document.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace inline comments with comprehensive TypeDoc comments that explain
the purpose and usage of each property. Add examples and clarify
constraints (MUST/SHOULD) for better developer understanding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Move metadata field documentation from separate prose section into
TypeDoc comments on the UiResourceMeta interface properties. This
consolidates the documentation and eliminates duplication while making
it more maintainable and IDE-friendly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Change CSP code block from yaml to typescript fence, add context showing
where csp variable originates (resource.\_meta?.ui?.csp), rename
cspHeader to cspValue for accuracy, and remove Content-Security-Policy:
prefix since the variable holds just the policy value, not a complete
HTTP header.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The tool input and tool result examples now show fully formed JSON-RPC
messages with all required fields (jsonrpc, id/method, result/params) to
better demonstrate the protocol format. Also fixes MDX parsing error in
Client\<>Server heading by escaping angle brackets.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Corrects the indentation of nested block structures (alt, opt, par,
loop) in all four Mermaid sequence diagrams. Content inside nested
blocks is now properly indented relative to the block keywords, making
the hierarchical structure clearer and more readable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Unquote ui, csp, domain, and prefersBorder properties in the
resources/read response TypeScript example to follow standard TypeScript
syntax conventions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes code blocks for notification examples to use `typescript` fence
instead of `json`. This properly represents TypeScript types (like
Record<string, unknown>, CallToolResult, Partial<HostContext>) without
quotes, matching the format used elsewhere in the specification.
Affected notifications:
- ui/notifications/tool-input
- ui/notifications/tool-input-partial
- ui/notifications/tool-result
- ui/tool-cancelled
- ui/resource-teardown
- ui/size-change
- ui/host-context-change
- ui/notifications/sandbox-ready
- ui/notifications/sandbox-resource-ready
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>