Architecture
Overview
Section titled “Overview”The bridge uses a 3-layer architecture that keeps your MCP App and MCP Server completely unmodified:
[MCP App (iframe)] --postMessage--> [bridge.js] --WebSocket--> [Resource Server] --stdio/HTTP--> [MCP Server]Layer 1: Bridge Client (browser-side)
Section titled “Layer 1: Bridge Client (browser-side)”The Bridge Client is an IIFE script (bridge.js) automatically injected into the HTML served by the Resource Server.
Key responsibilities:
- Monkey-patches
window.parent.postMessageto intercept JSON-RPC messages - Establishes WebSocket connection to the Resource Server
- Translates platform events (theme changes, viewport resize) into MCP notifications
- Handles the
ui/initializehandshake
Layer 2: Resource Server (HTTP + WebSocket)
Section titled “Layer 2: Resource Server (HTTP + WebSocket)”The Resource Server is the central orchestrator:
- HTTP: Serves
ui://resources as regular web pages, injectingbridge.jsinto HTML responses - WebSocket: Maintains bidirectional communication with Bridge Clients
- Sessions: Crypto-secure session management with platform-specific auth validation
- CSP: Auto-generates Content-Security-Policy headers from resource metadata
- Forwarding: Routes
tools/callandresources/readrequests to the MCP Server
Layer 3: MCP Server (unmodified)
Section titled “Layer 3: MCP Server (unmodified)”Your existing MCP Server remains completely unchanged. The Resource Server connects to it as a standard MCP client, using either stdio or HTTP transport.
Message Flow
Section titled “Message Flow”A typical tool call flows through:
- User interacts with UI in Telegram WebView
- MCP App calls
postMessage({ jsonrpc: "2.0", method: "tools/call", ... }) bridge.jsintercepts, sends via WebSocket- Resource Server validates session, forwards to MCP Server
- MCP Server executes tool, returns result
- Resource Server sends result via WebSocket
bridge.jsdispatchesMessageEventto the MCP App- UI updates
Total added latency: ~1 WebSocket round-trip (negligible when co-located).