Skip to content

feat: Introduce MCP Apps#1295

Merged
rafaeelaudibert merged 1 commit intomainfrom
mcp-apps
Mar 21, 2026
Merged

feat: Introduce MCP Apps#1295
rafaeelaudibert merged 1 commit intomainfrom
mcp-apps

Conversation

@rafaeelaudibert
Copy link
Member

This pull request adds comprehensive support for MCP Apps, which allows MCP servers to ship interactive HTML UIs alongside their tools. When a tool has an associated ui:// resource, the app renders the HTML inside a sandboxed iframe instead of showing raw tool input/output.

Key Features

  • Double-iframe sandbox architecture for security isolation using a custom mcp-sandbox: protocol
  • Lazy connection management - MCP server connections are created on-demand when UI resources are first requested
  • Tool-to-UI discovery via _meta.ui.resourceUri fields in MCP tool definitions
  • Real-time communication between apps and the host using the official @modelcontextprotocol/ext-apps AppBridge
  • Theme integration that maps Radix UI theme tokens to MCP Apps CSS variables
  • Fullscreen and inline display modes with smooth transitions
  • Content Security Policy generation from server-declared domains
  • Permission Policy support for camera, microphone, geolocation, and clipboard access

Architecture

The implementation spans both main and renderer processes:

Main Process:

  • McpAppsService manages server connections and acts as a proxy between renderer and MCP servers
  • Tool input/result/cancellation events are forwarded from AgentService to apps via tRPC subscriptions
  • Custom protocol handler serves the sandbox proxy HTML on mcp-sandbox://proxy

Renderer Process:

  • McpAppHost component manages iframe lifecycle and AppBridge communication
  • useAppBridge hook handles the complete bridge setup, context synchronization, and message routing
  • Apps can send messages to pre-fill the chat input and request display mode changes

Security Model

Apps run in a double-iframe sandbox where the outer iframe has an isolated origin (mcp-sandbox://proxy) preventing access to the host's DOM, storage, or cookies. The inner iframe uses document.write() instead of srcdoc to preserve origin for WebGL operations while maintaining security boundaries.

Developer Experience

  • Per-server disable toggle in settings
  • Debug menu option to refresh MCP Apps discovery and clear caches
  • Comprehensive error handling and logging throughout the pipeline
  • Standard MCP tool view always remains visible alongside the app UI

Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@rafaeelaudibert rafaeelaudibert requested a review from a team March 18, 2026 19:56
Copy link
Contributor

@jonathanlab jonathanlab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Tested that this works for me locally, great stuff 🚢

Copy link
Member Author

Merge activity

  • Mar 19, 3:54 PM UTC: Graphite couldn't merge this PR because it failed for an unknown reason (GitHub is reporting that this PR is not mergeable, despite passing required status checks defined by your branch protection rules. Please check your rulesets for additional blocking criteria. Graphite Merge Queue does not currently support rulesets. Please contact Graphite support for further assistance.).

Let's support MCP Apps inside PostHog Code. This is done via a new service that's triggered when we start a new Code session.

The best way to understand how this works is in the Archtiecture file. We use `AppBridge` provided by Anthropic to handle this.

Integrating with ACP is not trivial because we don't have the raw tool call with us and we have to go through the ACP protocol, but this looks good!
@rafaeelaudibert rafaeelaudibert merged commit eb89c54 into main Mar 21, 2026
15 checks passed
@rafaeelaudibert rafaeelaudibert deleted the mcp-apps branch March 21, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants