@mcp-web/bridge
v0.1.3
Published
A bridge server that enables web frontend applications to be controlled by AI agents through the Model Context Protocol (MCP). The bridge mediates between web applications (via WebSocket) and AI agents (via HTTP/JSON-RPC).
Readme
MCP Web Bridge
A bridge server that enables web frontend applications to be controlled by AI agents through the Model Context Protocol (MCP). The bridge mediates between web applications (via WebSocket) and AI agents (via HTTP/JSON-RPC).
Overview
The bridge server:
- Runs a single-port server for both WebSocket and HTTP connections
- Manages session authentication and tool registration
- Routes tool calls between AI agents and the appropriate frontend session
- Supports multiple JavaScript runtimes (Node.js, Deno, Bun, PartyKit/Cloudflare)
Quick Start
Node.js
import { MCPWebBridgeNode } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeNode({
name: 'My App',
description: 'My awesome application',
port: 3001,
});
// Graceful shutdown
process.on('SIGINT', async () => {
await bridge.close();
process.exit(0);
});Deno
import { MCPWebBridgeDeno } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeDeno({
name: 'My App',
description: 'My awesome application',
port: 3001,
});
// Bridge is now listening on ws://localhost:3001 and http://localhost:3001Bun
import { MCPWebBridgeBun } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeBun({
name: 'My App',
description: 'My awesome application',
port: 3001,
});PartyKit / Cloudflare
// server.ts
import { createPartyKitBridge } from '@mcp-web/bridge';
export default createPartyKitBridge({
name: 'My App',
description: 'My awesome application on the edge',
});Runtime Adapters
The bridge supports multiple JavaScript runtimes through adapters. Each adapter wraps the runtime-agnostic core and provides I/O specific to that runtime.
MCPWebBridgeNode (Node.js)
Status: Production Ready ✅
The Node.js adapter uses http.createServer() with the ws library for WebSocket support.
import { MCPWebBridgeNode } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeNode({
name: 'My App',
description: 'My application',
port: 3001, // Single port for HTTP + WebSocket
host: '0.0.0.0', // Optional: bind address
});
// Access the core for advanced usage
const handlers = bridge.getHandlers();
// Graceful shutdown
await bridge.close();Features:
- Single port for both HTTP and WebSocket (uses HTTP upgrade)
- Full session and query limit support
- Timer-based scheduler for session timeouts
MCPWebBridgeDeno (Deno / Deno Deploy)
Status: Experimental 🧪
The Deno adapter uses Deno.serve() with native WebSocket upgrade support.
import { MCPWebBridgeDeno } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeDeno({
name: 'My App',
description: 'My application',
port: 3001,
hostname: '0.0.0.0', // Optional
});Deno Deploy:
// main.ts - Entry point for Deno Deploy
import { MCPWebBridgeDeno } from '@mcp-web/bridge';
new MCPWebBridgeDeno({
name: 'Production Bridge',
description: 'MCP Web bridge on Deno Deploy',
port: Number(Deno.env.get('PORT')) || 8000,
});Features:
- Native Deno.serve() with WebSocket upgrade
- Works with Deno Deploy
- Timer-based scheduler
Limitations:
- Deno Deploy doesn't support monorepo subdirectories for entry points
- Consider using a separate repo or root-level entry point for deployment
MCPWebBridgeBun (Bun)
Status: Experimental 🧪
The Bun adapter uses Bun.serve() with native WebSocket support.
import { MCPWebBridgeBun } from '@mcp-web/bridge';
const bridge = new MCPWebBridgeBun({
name: 'My App',
description: 'My application',
port: 3001,
hostname: '0.0.0.0', // Optional
});Features:
- Native Bun.serve() with built-in WebSocket
- Excellent performance
- Timer-based scheduler
MCPWebBridgeParty (PartyKit / Cloudflare)
Status: Experimental 🧪
The PartyKit adapter enables deployment to Cloudflare's edge network with Durable Objects for state management.
// server.ts
import { createPartyKitBridge } from '@mcp-web/bridge';
export default createPartyKitBridge({
name: 'My App',
description: 'My application on the edge',
sessionCheckIntervalMs: 60000, // Optional: alarm interval
});partykit.json:
{
"name": "my-mcp-bridge",
"main": "server.ts",
"compatibility_date": "2024-01-01"
}Deploy:
npx partykit deployFeatures:
- Global edge deployment via Cloudflare
- Durable Objects for stateful WebSocket handling
- Hibernation support for cost efficiency
- Uses PartyKit Alarms instead of setInterval for session timeouts
Key Differences:
- No explicit port configuration (managed by PartyKit/Cloudflare)
- Uses
AlarmSchedulerinstead ofTimerScheduler - State persists across hibernation cycles via
Party.storage
Custom Adapters
You can create custom adapters for other runtimes by using the core MCPWebBridge class directly:
import { MCPWebBridge, TimerScheduler } from '@mcp-web/bridge';
import type { BridgeHandlers, WebSocketConnection, HttpRequest, HttpResponse } from '@mcp-web/bridge';
// Create the core with a scheduler
const scheduler = new TimerScheduler();
const core = new MCPWebBridge(config, scheduler);
// Get handlers to wire up to your runtime
const handlers: BridgeHandlers = core.getHandlers();
// Implement these in your adapter:
// - handlers.onWebSocketConnect(sessionId, ws, url)
// - handlers.onWebSocketMessage(sessionId, ws, data)
// - handlers.onWebSocketClose(sessionId)
// - handlers.onHttpRequest(req) -> Promise<HttpResponse>Configuration Options
All adapters accept these common options from MCPWebConfig:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| name | string | required | Server name displayed to clients |
| description | string | required | Server description |
| icon | string | undefined | Optional icon URL or data URI |
| agentUrl | string | undefined | URL of the AI agent for query forwarding |
| authToken | string | undefined | Auth token for agent communication |
| maxSessionsPerToken | number | undefined | Max sessions per auth token |
| onSessionLimitExceeded | 'reject' \| 'close_oldest' | 'reject' | Behavior when limit exceeded |
| maxInFlightQueriesPerToken | number | undefined | Max concurrent queries per token |
| sessionMaxDurationMs | number | undefined | Max session duration (ms) |
Adapter-Specific Options
Node.js / Deno / Bun:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| port | number | 3001 | Port to listen on |
| host / hostname | string | '0.0.0.0' | Hostname to bind to |
PartyKit:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| sessionCheckIntervalMs | number | 60000 | Alarm interval for session checks |
Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ AI Agent │────▶│ Bridge Server │◀────│ Web Frontend │
│ (HTTP/JSON-RPC)│ │ (Single Port) │ │ (WebSocket) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
┌──────────┴──────────┐
│ MCPWebBridge │
│ (Runtime-Agnostic │
│ Core Logic) │
└─────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ Node.js │ │ Deno │ │ PartyKit │
│ Adapter │ │ Adapter │ │ Adapter │
└─────────────┘ └─────────────┘ └─────────────┘The bridge server acts as the central hub:
- Frontend connections: Web apps connect via WebSocket to register tools and receive tool calls
- Agent connections: AI agents connect via HTTP/JSON-RPC to discover and execute tools
- Session management: Each frontend gets a unique session with authentication
- Tool routing: Tool calls from agents are routed to the appropriate frontend session
Development
Build the package:
pnpm buildRun tests:
pnpm testNext Steps
Once your bridge server is running:
- Configure your web app to connect using @mcp-web/core
- Set up your AI agent to connect using @mcp-web/client
- Register tools in your web app that the AI agent can call
