MCP Framework
Transports

SSE Transport

Server-Sent Events transport for HTTP-based MCP communication (deprecated)

SSE Transport

DEPRECATED: The SSE Transport has been deprecated as of MCP specification version 2025-03-26. Please use the HTTP Stream Transport instead, which implements the new Streamable HTTP transport specification.

The Server-Sent Events (SSE) transport enables HTTP-based communication between the MCP server and clients. It uses SSE for server-to-client messages and HTTP POST for client-to-server messages.

Configuration

The SSE transport supports various configuration options to customize its behavior:

import { MCPServer } from "@modelcontextprotocol/mcp-framework";

const server = new MCPServer({
  transport: {
    type: "sse",
    options: {
      port: 8080,                // Port to listen on (default: 8080)
      host: "127.0.0.1",         // Host to bind to (default: "127.0.0.1")
      endpoint: "/sse",          // SSE endpoint path (default: "/sse")
      messageEndpoint: "/messages", // Message endpoint path (default: "/messages")
      maxMessageSize: "4mb",     // Maximum message size (default: "4mb")
      headers: {                 // Custom headers for SSE responses
        "X-Custom-Header": "value"
      },
      cors: {                    // CORS configuration
        allowOrigin: "*",
        allowMethods: "GET, POST, OPTIONS",
        allowHeaders: "Content-Type, Authorization, x-api-key",
        exposeHeaders: "Content-Type, Authorization, x-api-key",
        maxAge: "86400"
      },
      auth: {                    // Authentication configuration
        provider: authProvider,
        endpoints: {
          sse: true,            // Require auth for SSE connections
          messages: true        // Require auth for messages
        }
      }
    }
  }
});

Port and Host Configuration

The port option specifies which port the SSE server should listen on. Default is 8080.

The host option specifies the host address to bind to. Default is "127.0.0.1" (localhost only) for security. Set host: '0.0.0.0' to accept connections from other machines (required for Docker, cloud platforms).

transport: {
  type: "sse",
  options: {
    port: 8080,
    host: "0.0.0.0", // Accept connections from any network interface
  }
}

Endpoints

  • endpoint: The path for the SSE connection endpoint (default: "/sse")
  • messageEndpoint: The path for receiving messages via POST (default: "/messages")

Message Size Limit

The maxMessageSize option controls the maximum allowed size for incoming messages. Accepts string values like "4mb", "1kb", etc.

Custom Headers

You can specify custom headers to be included in SSE responses:

headers: {
  "X-Custom-Header": "value",
  "Cache-Control": "no-cache"
}

CORS Configuration

The SSE transport includes comprehensive CORS support with the following options:

cors: {
  allowOrigin: "*",                   // Access-Control-Allow-Origin
  allowMethods: "GET, POST, OPTIONS", // Access-Control-Allow-Methods
  allowHeaders: "Content-Type, Authorization, x-api-key", // Access-Control-Allow-Headers
  exposeHeaders: "Content-Type, Authorization, x-api-key", // Access-Control-Expose-Headers
  maxAge: "86400"                    // Access-Control-Max-Age
}

Origin Validation (DNS Rebinding Protection)

When allowedOrigins is configured within the cors block, the server validates the Origin header on every incoming request to protect against DNS rebinding attacks:

cors: {
  allowedOrigins: ["http://localhost:3000", "https://myapp.example.com"],
  allowOrigin: "*",
  allowMethods: "GET, POST, OPTIONS",
  allowHeaders: "Content-Type, Authorization, x-api-key",
  exposeHeaders: "Content-Type, Authorization, x-api-key",
  maxAge: "86400"
}

How origin validation works:

  • Requests with an Origin header that does not match any entry in allowedOrigins receive an HTTP 403 Forbidden response.
  • Requests without an Origin header (non-browser clients like curl, SDKs, and other server-side callers) are allowed through, since they are not subject to DNS rebinding.
  • Origin: null is always rejected when allowedOrigins is set. This is a security best practice, as null origins can be crafted by malicious pages.
  • When allowedOrigins is not configured, all origins are allowed. This preserves backwards compatibility with existing deployments.

For production deployments, always configure allowedOrigins to prevent DNS rebinding attacks.

Authentication

The SSE transport supports authentication through various providers. See the Authentication documentation for details.

auth: {
  provider: authProvider,    // Authentication provider instance
  endpoints: {
    sse: true,              // Require auth for SSE connections
    messages: true          // Require auth for messages
  }
}

Connection Management

Keep-Alive

The SSE transport automatically manages connection keep-alive:

  • Sends keep-alive messages every 15 seconds
  • Includes ping messages with timestamps
  • Optimizes socket settings for long-lived connections

Session Management

Each SSE connection is assigned a unique session ID that must be included in message requests:

  1. Client establishes SSE connection
  2. Server sends endpoint URL with session ID
  3. Client uses this URL for sending messages

Error Handling

The transport includes robust error handling:

  • Connection errors
  • Message parsing errors
  • Authentication failures
  • Size limit exceeded errors

Error responses include detailed information:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32000,
    "message": "Error message",
    "data": {
      "method": "method_name",
      "sessionId": "session_id",
      "connectionActive": true,
      "type": "message_handler_error"
    }
  }
}

Security Considerations

  1. HTTPS: Always use HTTPS in production environments
  2. Authentication: Enable authentication for both SSE and message endpoints
  3. CORS: Configure appropriate CORS settings for your environment
  4. Origin Validation: Configure allowedOrigins to prevent DNS rebinding attacks
  5. Host Binding: Keep the default 127.0.0.1 binding unless external access is required
  6. Message Size: Set appropriate message size limits
  7. Rate Limiting: Implement rate limiting for production use

Client Implementation

Here's an example of how to implement a client for the SSE transport:

// Establish SSE connection
const eventSource = new EventSource('http://localhost:8080/sse');

// Handle endpoint URL
eventSource.addEventListener('endpoint', (event) => {
  const messageEndpoint = event.data;
  // Store messageEndpoint for sending messages
});

// Handle messages
eventSource.addEventListener('message', (event) => {
  const message = JSON.parse(event.data);
  // Process message
});

// Send message
async function sendMessage(message) {
  const response = await fetch(messageEndpoint, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer your-token' // If using authentication
    },
    body: JSON.stringify(message)
  });
  
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
}