Multi-Client Agent Orchestration: Implementing SSE-based Remote Connections
Transition your local stdio servers to network-connected remote servers using bi-directional Server-Sent Events (SSE). Support multi-client scaling.
Multi-Client Agent Orchestration: SSE-based Connections
While standard input/output (stdio) transports are ideal for local development and single-machine agent setups, they fundamentally cannot handle remote network environments or multi-client communication patterns. To deploy your MCP server to the cloud and connect multiple different LLM clients simultaneously, you must use Server-Sent Events (SSE).
SSE provides a bi-directional communication protocol over standard https:
- ▸The client listens to server events using a continuous
EventSourcestream (server-to-client). - ▸The client sends commands and tool payloads to the server via standard HTTP
POSTcalls (client-to-server).
Prerequisites
- ▸Familiarity with Node.js and the Express framework.
- ▸The
@modelcontextprotocol/sdkinstalled in your project. - ▸An understanding of HTTP request lifecycles.
Communication Architecture
[Client (e.g. Browser Agent)] --(HTTP POST: JSON-RPC)--> [SSE Server Endpoint]
[Client (e.g. Browser Agent)] <--(Server-Sent Events)--- [SSE Stream Endpoint]Express-based SSE Transport Implementation
Here is a functional blueprint for setting up an SSE-based MCP server using Express:
import express from 'express';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import cors from 'cors';
const app = express();
app.use(cors()); // Critical for browser clients
app.use(express.json());
const mcpServer = new Server({ name: 'sse-server', version: '1.0.0' }, { capabilities: {} });
// We must track transports per-session if we support multiple clients.
// For this simple example, we'll track a single global transport.
let sseTransport: SSEServerTransport | null = null;
app.get('/mcp/events', (req, res) => {
sseTransport = new SSEServerTransport('/mcp/messages', res);
mcpServer.connect(sseTransport);
// The client keeps this connection open indefinitely
});
app.post('/mcp/messages', (req, res) => {
if (sseTransport) {
sseTransport.handleMessage(req, res);
} else {
res.status(400).send("No active SSE session initialized.");
}
});
app.listen(3001, () => console.log('SSE MCP Server running on port 3001'));Best Practices
- ▸Session Management: The blueprint above uses a single global transport. In production, you must map
sessionIds to distinctSSEServerTransportinstances so multiple clients don't overwrite each other. - ▸CORS Configuration: If your AI client runs in a browser (like a React app), you MUST configure CORS headers on both your
/eventsand/messagesendpoints. - ▸Reverse Proxies: If you deploy behind Nginx or Cloudflare, ensure you configure them to not buffer SSE responses. (e.g.,
proxy_buffering off;in Nginx).
Troubleshooting
- ▸Connection Drops After 60 Seconds: Your load balancer or proxy is likely timing out the idle HTTP connection. Implement server-side keep-alive pings or configure your reverse proxy's timeout settings.
- ▸CORS Errors on POST: Ensure you are explicitly handling preflight
OPTIONSrequests if you are sending custom headers likeAuthorizationwith your JSON-RPC payloads.
Related Guides
How to Connect Slack to AI Agents with the Slack MCP Server
Integrate Slack with your AI agent using MCP. Read messages, post updates, manage channels, and automate Slack workflows seamlessly.
CommunicationEmail Automation Workflows: Orchestrating Gmail and Resend Safely with MCP
Create secure email flows. Whitelist recipient domains, compose email templates, and trigger Gmail drafts programmatically with MCP.