ExMCP.Transport.HTTP (ex_mcp v0.9.0)

View Source

This module implements the standard MCP specification.

Streamable HTTP transport for MCP with enhanced SSE support.

This transport uses HTTP POST and GET requests with optional Server-Sent Events (SSE) for streaming server-to-client messages. This is one of the two official MCP transports defined in the specification.

Features

  • Auto-reconnection: Automatic reconnection with exponential backoff
  • Keep-alive: Built-in heartbeat mechanism for connection health
  • Event resumption: Supports Last-Event-ID for event replay
  • Session management: Automatic session ID generation and tracking
  • Configurable endpoint: Customize the MCP endpoint path
  • Single response mode: Option to use HTTP responses instead of SSE
  • Protocol Versioning: Sends mcp-protocol-version header.

Security Features

The Streamable HTTP transport supports comprehensive security features:

  • Authentication: Bearer tokens, API keys, basic auth
  • Origin Validation: Prevent DNS rebinding attacks (recommended to enable)
  • CORS Headers: Cross-origin resource sharing
  • Security Headers: XSS protection, frame options, etc.
  • TLS/SSL: Secure connections with certificate validation

Example with Security

{:ok, client} = ExMCP.Client.start_link(
  transport: :http,
  url: "https://api.example.com",
  endpoint: "/mcp/v1",  # Configurable endpoint
  protocol_version: "2025-06-18", # Specify protocol version
  use_sse: true,         # Use SSE for responses (default: true)
  session_id: "existing-session",  # Resume existing session
  security: %{
    auth: {:bearer, "your-token"},
    validate_origin: true,
    allowed_origins: ["https://app.example.com"],
    cors: %{
      allowed_methods: ["GET", "POST"],
      allow_credentials: true
    }
  }
)

Session Management

The HTTP transport automatically manages sessions using the Mcp-Session-Id header. Sessions enable:

  • Request/response correlation
  • Resumability after connection loss
  • Server-side state management

Non-SSE Mode

For simpler deployments, the HTTP transport can operate without SSE:

{:ok, client} = ExMCP.Client.start_link(
  transport: :http,
  url: "https://api.example.com",
  use_sse: false  # Responses come in HTTP response body
)

Security Best Practices

  1. Always use HTTPS in production
  2. Enable origin validation to prevent DNS rebinding attacks
  3. Bind to localhost when possible for local servers
  4. Implement proper authentication (bearer tokens, API keys, etc.)
  5. Set restrictive CORS policies for cross-origin requests

Summary

Functions

Builds SSL options from TLS configuration.

Types

t()

@type t() :: %ExMCP.Transport.HTTP{
  access_token: term(),
  auth_completed: term(),
  auth_config: term(),
  base_url: String.t(),
  endpoint: String.t(),
  headers: [{String.t(), String.t()}],
  http_client: module(),
  last_event_id: String.t() | nil,
  last_response: map() | nil,
  origin: String.t() | nil,
  protocol_version: String.t(),
  retry_delay: term(),
  security: ExMCP.Security.Validation.security_config() | nil,
  session_id: String.t() | nil,
  sse_deferred_attempted: boolean(),
  sse_pid: pid() | nil,
  timeouts: map(),
  use_sse: boolean()
}

Functions

build_ssl_options(tls_config)

Builds SSL options from TLS configuration.

Examples

tls_config = %{
  verify: :verify_peer,
  versions: [:"tlsv1.2", :"tlsv1.3"],
  cert: "client.pem",
  key: "client.key"
}

ssl_opts = ExMCP.Transport.HTTP.build_ssl_options(tls_config)