mcp-transport-websocket-setup
Scannednpx machina-cli add skill a5c-ai/babysitter/mcp-transport-websocket-setup --openclawMCP Transport WebSocket Setup
Configure WebSocket transport for bidirectional MCP communication.
Capabilities
- Configure WebSocket transport for MCP
- Implement connection lifecycle management
- Set up reconnection with backoff
- Handle message framing
- Implement heartbeat/ping-pong
- Configure secure WebSocket (WSS)
Usage
Invoke this skill when you need to:
- Set up bidirectional MCP communication
- Implement WebSocket-based MCP transport
- Configure connection management
- Enable real-time bidirectional messaging
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
| language | string | Yes | Target language |
| server | boolean | No | Generate server code (default: true) |
| client | boolean | No | Generate client code (default: false) |
| secure | boolean | No | Use WSS (default: true) |
Generated Patterns
TypeScript WebSocket Server
import { WebSocketServer, WebSocket } from 'ws';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
interface Connection {
ws: WebSocket;
server: Server;
lastPing: number;
}
const connections = new Map<string, Connection>();
const wss = new WebSocketServer({
port: parseInt(process.env.WS_PORT || '8080'),
path: '/mcp',
});
// Heartbeat interval
const HEARTBEAT_INTERVAL = 30000;
wss.on('connection', (ws, req) => {
const connectionId = crypto.randomUUID();
console.log(`New connection: ${connectionId}`);
// Create MCP server for this connection
const server = new Server(
{ name: 'my-mcp-server', version: '1.0.0' },
{ capabilities: { tools: {}, resources: {} } }
);
// Register handlers
registerToolHandlers(server);
// Store connection
connections.set(connectionId, {
ws,
server,
lastPing: Date.now(),
});
// Handle messages
ws.on('message', async (data) => {
try {
const message = JSON.parse(data.toString());
await handleMessage(connectionId, message);
} catch (error) {
console.error('Failed to process message:', error);
ws.send(JSON.stringify({
jsonrpc: '2.0',
error: { code: -32700, message: 'Parse error' },
}));
}
});
// Handle close
ws.on('close', () => {
console.log(`Connection closed: ${connectionId}`);
connections.delete(connectionId);
});
// Handle errors
ws.on('error', (error) => {
console.error(`Connection error: ${connectionId}`, error);
});
// Respond to pings
ws.on('pong', () => {
const conn = connections.get(connectionId);
if (conn) conn.lastPing = Date.now();
});
});
// Heartbeat check
setInterval(() => {
const now = Date.now();
connections.forEach((conn, id) => {
if (now - conn.lastPing > HEARTBEAT_INTERVAL * 2) {
console.log(`Terminating stale connection: ${id}`);
conn.ws.terminate();
connections.delete(id);
} else {
conn.ws.ping();
}
});
}, HEARTBEAT_INTERVAL);
async function handleMessage(connectionId: string, message: any) {
const conn = connections.get(connectionId);
if (!conn) return;
// Process MCP message and send response
// Implementation depends on message type
}
console.log(`WebSocket MCP Server running on port ${process.env.WS_PORT || 8080}`);
TypeScript WebSocket Client
import WebSocket from 'ws';
interface MCPClientOptions {
url: string;
reconnect?: boolean;
maxRetries?: number;
}
class MCPWebSocketClient {
private ws: WebSocket | null = null;
private reconnectAttempts = 0;
private maxRetries: number;
private reconnectDelay = 1000;
constructor(private options: MCPClientOptions) {
this.maxRetries = options.maxRetries ?? 5;
}
async connect(): Promise<void> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.options.url);
this.ws.on('open', () => {
console.log('Connected to MCP server');
this.reconnectAttempts = 0;
this.reconnectDelay = 1000;
resolve();
});
this.ws.on('message', (data) => {
const message = JSON.parse(data.toString());
this.handleMessage(message);
});
this.ws.on('close', () => {
console.log('Disconnected from MCP server');
if (this.options.reconnect) {
this.attemptReconnect();
}
});
this.ws.on('error', (error) => {
console.error('WebSocket error:', error);
reject(error);
});
});
}
private attemptReconnect() {
if (this.reconnectAttempts >= this.maxRetries) {
console.error('Max reconnection attempts reached');
return;
}
this.reconnectAttempts++;
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
setTimeout(() => {
this.connect().catch(() => {
// Will trigger another reconnect attempt
});
}, delay);
}
async send(message: any): Promise<void> {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
throw new Error('Not connected');
}
this.ws.send(JSON.stringify(message));
}
private handleMessage(message: any) {
// Handle incoming MCP messages
console.log('Received:', message);
}
close() {
this.options.reconnect = false;
this.ws?.close();
}
}
Workflow
- Configure server - WebSocket server setup
- Add handlers - Message processing
- Implement heartbeat - Connection health
- Add reconnection - Client reconnection
- Configure security - WSS setup
- Add monitoring - Connection metrics
Target Processes
- mcp-transport-layer
- mcp-server-bootstrap
- mcp-client-implementation
Source
git clone https://github.com/a5c-ai/babysitter/blob/main/plugins/babysitter/skills/babysit/process/specializations/cli-mcp-development/skills/mcp-transport-websocket-setup/SKILL.mdView on GitHub Overview
Sets up bidirectional MCP communication over WebSocket, including lifecycle management, heartbeat, and optional WSS. The pattern includes a server that maintains per-connection MCP instances and a client with automatic reconnection. This enables real-time, secure MCP messaging between peers.
How This Skill Works
The server spins up a WebSocketServer on a given port and path, creates an MCP server instance per connection, and routes messages through a shared handler with JSON-RPC framing. The client can reconnect automatically with backoff, and both sides exchange heartbeats using ping/pong to detect stale connections. Secure WebSocket (WSS) can be enabled to encrypt traffic end-to-end.
When to Use It
- Need real-time bidirectional MCP messaging between peers over WebSocket.
- Require lifecycle and connection management for MCP transports.
- Need automatic reconnection with backoff after network interruptions.
- Need proper message framing, heartbeat, and liveness checks.
- Require secure WebSocket (WSS) to protect MCP traffic.
Quick Start
- Step 1: Decide on server/client flags and whether to enable secure WebSocket (secure = true).
- Step 2: Start the WebSocket server on the desired port and path (e.g., /mcp) and instantiate per-connection MCP servers.
- Step 3: Implement handleMessage for MCP message processing, enable heartbeat/ping-pong, and, for clients, configure reconnection/backoff as needed.
Best Practices
- Enable WSS in production and terminate TLS at the edge or proxy.
- Tune the heartbeat interval and backoff to balance latency and stability.
- Implement robust message handling and JSON-RPC framing in handleMessage.
- Cleanly close connections and release resources on WS errors or closures.
- Validate and sanitize all incoming messages to enforce protocol boundaries.
Example Use Cases
- A Node.js MCP server using ws to accept connections, create per-connection MCP servers, and manage heartbeat and message handling.
- An MCP WebSocket client with automatic reconnection and configurable maxRetries and backoff delays.
- Heartbeat/ping-pong logic to detect and terminate stale connections.
- Configuring a secure WebSocket (WSS) endpoint for production with TLS termination.
- Custom message routing that uses JSON-RPC framing to standardize MCP requests and responses.