Overview
The WebSocket relay is a lightweight Bun-powered server that acts as a message router between MCP servers and Figma plugins. It runs on port 3055 by default and provides channel-based message isolation.Why a Relay Server?
The relay solves several architectural challenges:Protocol Mismatch
Protocol Mismatch
MCP servers communicate via stdio with AI agents, but need WebSocket connectivity to reach Figma plugins. The relay bridges this gap.
Multi-User Support
Multi-User Support
Multiple users can run MCP servers simultaneously on the same machine. The relay uses channel isolation to prevent message conflicts.
Connection Management
Connection Management
The relay handles WebSocket lifecycle events (connect, disconnect, reconnect) and maintains client state across channels.
Message Broadcasting
Message Broadcasting
The relay efficiently broadcasts messages to all clients in a channel except the sender, preventing echo loops.
Server Architecture
Core Components
socket.ts
Data Structures
The relay uses a Map of Sets to organize clients by channel:This structure provides O(1) channel lookups and O(n) broadcast operations within a channel.
Connection Lifecycle
1. Client Connection
When a client connects, they receive a welcome message:socket.ts
2. Joining a Channel
Clients send a join message to enter a channel:socket.ts
3. Sending Messages
Once in a channel, clients can exchange messages:socket.ts
The relay excludes the sender from broadcasts to prevent echo loops and ensure clean request-response flow.
4. Client Disconnection
When a client disconnects, they’re removed from all channels:socket.ts
Message Format
Join Message
Regular Message
Broadcast Message (relayed)
System Message
Error Message
Configuration
Port Configuration
The relay port is configurable via environment variable:socket.ts
Host Configuration
For WSL or remote access, uncomment the hostname option:socket.ts
CORS Headers
The relay includes CORS headers for browser-based clients:socket.ts
Logging and Debugging
The relay provides detailed console logging:socket.ts
Example Log Output
Performance Characteristics
Benchmarks
- Channel lookup: O(1) using Map
- Client broadcast: O(n) where n = clients in channel
- Join/leave: O(1) for Set operations
- Memory: ~100 bytes per client per channel
Scalability
The relay is designed for local development, not high-scale production:- Supported: 1-10 clients per channel, 1-10 active channels
- Memory: Grows linearly with client count
- CPU: Minimal (less than 1% on modern hardware)
- Network: No compression or batching optimizations
For production deployments, consider using a battle-tested WebSocket server like Socket.IO or Centrifugo.
Starting the Relay
Development Mode
Production Mode
For production, use a process manager like PM2:Docker Deployment
Example Dockerfile for containerized deployment:Error Handling
The relay handles common error scenarios:Invalid JSON
Missing Channel Name
Not in Channel
Troubleshooting
”Connection refused” on port 3055
Cause: Relay server is not running. Solution:“No other clients in channel”
Cause: Only one client in the channel. Solution: Connect both MCP server and Figma plugin to the same channel:Messages not routing
Cause: Clients in different channels. Solution: Verify channel names match exactly (case-sensitive):Next Steps
System Architecture
Understand the full three-component pipeline
Channel Communication
Learn about channel-based isolation