Server-Sent Events (SSE) is a standard HTTP transport for MCP servers—unidirectional streams from server to client. This guide builds an MCP server with legacy SSE in .NET and connects it to Claude Desktop.
Note: Legacy SSE (protocol 2024-11-05) is maintained for compatibility. New remote deployments should prefer Streamable HTTP—see Build MCP Server with Streamable HTTP and the MCP protocol overview. This article focuses on legacy SSE because some clients and bridges (including mcp-remote) still target /sse.
Prerequisites
- Basic understanding of .NET and C# programming
- Familiarity with HTTP protocols and web APIs
- Knowledge of asynchronous programming concepts
- Understanding of the MCP protocol overview
- Recommended: Server-Sent Events (SSE) and EventSource for SSE wire format, headers, and reconnection behavior
Understanding Server-Sent Events (SSE)
Server-Sent Events (SSE) is a web standard that allows a server to push data to a client over a single HTTP connection. Unlike WebSockets, SSE provides unidirectional communication from server to client, making it well suited for streaming updates over HTTP.
For a full treatment of event framing, EventSource clients, C# and Node.js server examples, and production tuning, see Server-Sent Events (SSE) and EventSource.
Key benefits of SSE for MCP
- Simplicity: Built on standard HTTP, no special protocols needed
- Automatic reconnection: Clients can reconnect on connection loss
- Event-driven: Fits MCP's message-based architecture
- Firewall friendly: Works through most corporate firewalls
- Low overhead: Minimal protocol overhead compared to WebSockets
How MCP uses SSE
Legacy MCP over HTTP splits traffic across two endpoints:
| Endpoint | Role |
|---|---|
GET /sse |
Long-lived SSE stream (server → client) |
POST /message |
JSON-RPC requests (client → server) |
MCP JSON-RPC responses travel as standard SSE frames on Content-Type: text/event-stream:
data: {"jsonrpc":"2.0","id":1,"result":{...}}
For the full field reference (data, event, id, retry, comment heartbeats), see Server-Sent Events (SSE) and EventSource.
Complete example: Echo MCP server
Create the project
dotnet new web -n SseMcpServer
cd SseMcpServer
dotnet package add ModelContextProtocol.AspNetCore
Pin the port so Claude config stays predictable. In Properties/launchSettings.json:
"applicationUrl": "http://localhost:5130"
Define tools
Create Tools/EchoTools.cs:
using System.ComponentModel;
using ModelContextProtocol.Server;
[McpServerToolType]
public sealed class EchoTools
{
[McpServerTool, Description("Echoes the input back to the client.")]
public static string Echo(string message) => message;
}
Configure Program.cs
Legacy SSE is disabled by default in the MCP C# SDK. Enable it explicitly:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddMcpServer()
.WithHttpTransport(options =>
{
options.Stateless = false;
options.EnableLegacySse = true;
})
.WithTools<Tools>();
var app = builder.Build();
app.MapMcp();
app.Run();
Run and smoke test
Start the server:
dotnet run
Test with Claude Desktop
Claude Desktop connects to legacy SSE MCP servers through mcp-remote: a stdio bridge that forwards to your HTTP URL (GET /sse and POST /message).
Prerequisites
- Claude Desktop installed
- Node.js 18+ (for
npx mcp-remote) - The .NET MCP server running locally on port 5130
Configure Claude Desktop
Edit claude_desktop_config.json:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sse-echo": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:5130/sse"
]
}
}
}
Step-by-step
- Start the server:
dotnet run(leave the terminal open) - Add the config above to
claude_desktop_config.json - Fully quit Claude Desktop and relaunch (config is read at startup)
- Open Claude and check the MCP/tools indicator (hammer icon)—
sse-echoshould show as connected - Send a test prompt, for example: "Use the echo tool to repeat the phrase hello mcp"
- Confirm Claude calls
Echoand returns the echoed text
Verify and troubleshoot
- Claude logs: Help → View Logs (or Developer settings)—look for connection errors
- Server terminal: should log incoming HTTP requests when Claude connects
- Wrong port: align
launchSettings.jsonwith the URL inclaude_desktop_config.json - Server not running: start the server before restarting Claude
- Stale config: quit Claude completely (not just close the window), then relaunch
- Firewall: ensure localhost traffic on port 5130 is allowed
- SSE disconnects behind a proxy: disable response buffering and send periodic comment heartbeats—see Server-Sent Events (SSE) and EventSource
For local development without HTTP, stdio transport is simpler—see Building MCP Server Using .NET.
Conclusion
An MCP server over legacy SSE fits existing clients and bridges that target /sse. The .NET MCP SDK handles concurrent connections well; for new remote deployments, use Build MCP Server with Streamable HTTP when your clients support it.
Next steps
- Implement custom tools for your use case
- Add authentication and authorization
- Set up monitoring and logging
- Deploy to your preferred cloud platform
Related reading
- Build MCP Server with Streamable HTTP — recommended remote HTTP transport
- Server-Sent Events (SSE) and EventSource — SSE protocol deep dive
- What is the MCP Protocol? — transports overview
- Building MCP Server Using .NET — stdio and HTTP basics
- Run MCP Server in Docker — container deployment