Skip to main content

MCP Transports

Protocol Revision: 2025-11-25
PraisonAI Agents supports all MCP transport mechanisms for connecting to MCP servers, providing flexibility for different deployment scenarios.

Transport Types

stdio

Local subprocess communication
  • Best for local development
  • NPX packages, Python scripts
  • Newline-delimited JSON-RPC

Streamable HTTP

HTTP POST/GET with SSE streaming
  • Production deployments
  • Session management
  • Resumable connections

WebSocket

Bidirectional real-time
  • Long-lived connections
  • Cloud-native (hibernatable)
  • Lower protocol overhead

SSE (Legacy)

Server-Sent Events
  • Backward compatibility
  • Protocol version 2024-11-05
  • URLs ending in /sse

Quick Start

from praisonaiagents import Agent, MCP

# Local NPX server
agent = Agent(
    name="Assistant",
    tools=MCP("npx @modelcontextprotocol/server-memory")
)

# Python script
agent = Agent(
    tools=MCP("python3 mcp_server.py")
)

Transport Auto-Detection

The MCP class automatically selects the appropriate transport based on the URL:
URL PatternTransportExample
ws:// or wss://WebSocketws://localhost:8080/mcp
http(s)://... ending in /sseSSE (Legacy)http://localhost:8080/sse
http:// or https://Streamable HTTPhttps://api.example.com/mcp
Command stringstdionpx @mcp/server-memory

stdio Transport

The stdio transport runs MCP servers as subprocesses, communicating via standard input/output.

Features

  • ✅ JSON-RPC messages over stdin/stdout
  • ✅ Newline-delimited messages
  • ✅ UTF-8 encoding enforced
  • ✅ Environment variable support

Usage

from praisonaiagents import Agent, MCP

# Simple command string
agent = Agent(
    tools=MCP("npx @modelcontextprotocol/server-filesystem")
)

# With separate command and args
agent = Agent(
    tools=MCP(
        command="python3",
        args=["server.py", "--config", "prod.json"]
    )
)

# With environment variables
agent = Agent(
    tools=MCP(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
        env={"GITHUB_TOKEN": "ghp_xxx"}
    )
)

# With timeout and debug
agent = Agent(
    tools=MCP(
        "npx @modelcontextprotocol/server-memory",
        timeout=120,
        debug=True
    )
)

Streamable HTTP Transport

This is the current standard transport (Protocol Revision 2025-11-25)
The Streamable HTTP transport uses HTTP POST for sending messages and supports SSE streaming for responses.

Features

  • ✅ Single MCP endpoint for all communication
  • ✅ Session management via Mcp-Session-Id header
  • ✅ Protocol versioning via Mcp-Protocol-Version header
  • ✅ SSE streaming with resumability
  • Last-Event-ID for connection recovery
  • ✅ Session termination via HTTP DELETE

Usage

from praisonaiagents import Agent, MCP

# Basic HTTP endpoint
agent = Agent(
    tools=MCP("https://api.example.com/mcp")
)

# With all options
agent = Agent(
    tools=MCP(
        "https://api.example.com/mcp",
        timeout=60,
        debug=True,
        headers={"Authorization": "Bearer token"},
        session=True,           # Enable session management
        resumability=True       # Enable SSE resumability
    )
)

Session Management

Sessions allow stateful interactions with MCP servers:
from praisonaiagents import MCP, SessionManager

# Session is automatically managed
mcp = MCP("https://api.example.com/mcp")

# Access session info
print(f"Session ID: {mcp.http_stream_client.transport.session_id}")

# Session is terminated on cleanup or explicitly
# mcp.http_stream_client.transport.terminate_session()

Protocol Version

The client automatically includes Mcp-Protocol-Version header:
# Default version: 2025-03-26 (for backward compatibility)
mcp = MCP("https://api.example.com/mcp")

# Specify version explicitly
mcp = MCP(
    "https://api.example.com/mcp",
    protocol_version="2025-11-25"
)

WebSocket Transport

Based on SEP-1288 (in review)
WebSocket transport provides bidirectional, long-lived connections ideal for cloud deployments.

Features

  • ws:// and wss:// URL detection
  • ✅ JSON-RPC message framing
  • ✅ Session ID handling
  • ✅ Reconnection with exponential backoff
  • ✅ Authentication token support
  • ✅ Ping/pong keepalive

Usage

from praisonaiagents import Agent, MCP

# Basic WebSocket
agent = Agent(
    tools=MCP("ws://localhost:8080/mcp")
)

# Secure WebSocket with authentication
agent = Agent(
    tools=MCP(
        "wss://api.example.com/mcp",
        auth_token="Bearer your-secret-token",
        timeout=60
    )
)

Advanced WebSocket Options

from praisonaiagents.mcp.mcp_websocket import WebSocketMCPClient

# Direct client usage with all options
client = WebSocketMCPClient(
    server_url="wss://api.example.com/mcp",
    auth_token="your-token",
    timeout=60,
    options={
        "ping_interval": 30,
        "ping_timeout": 10,
        "max_retries": 5
    }
)

# Use with agent
agent = Agent(tools=list(client.tools))

Reconnection

WebSocket transport automatically reconnects with exponential backoff:
from praisonaiagents.mcp.mcp_websocket import calculate_backoff

# Backoff calculation: base_delay * 2^attempt, capped at max_delay
# Attempt 0: 1s, Attempt 1: 2s, Attempt 2: 4s, ... max 60s

SSE Transport (Legacy)

This transport is deprecated. Use Streamable HTTP for new implementations.
The SSE transport is maintained for backward compatibility with servers using protocol version 2024-11-05.

Usage

from praisonaiagents import Agent, MCP

# URLs ending in /sse use legacy SSE transport
agent = Agent(
    tools=MCP("http://localhost:8080/sse")
)

Security

Origin Validation (DNS Rebinding Prevention)

from praisonaiagents.mcp.mcp_security import SecurityConfig, is_valid_origin

# Configure allowed origins
config = SecurityConfig(
    allowed_origins=["localhost", "127.0.0.1", "example.com"],
    validate_origin=True
)

# Validate origin header
is_valid = is_valid_origin(
    origin="https://example.com",
    allowed_origins=config.allowed_origins
)

Authentication

from praisonaiagents.mcp.mcp_security import create_auth_header

# Bearer token
headers = create_auth_header("your-token", auth_type="bearer")
# {"Authorization": "Bearer your-token"}

# Basic auth
headers = create_auth_header("user:pass", auth_type="basic")
# {"Authorization": "Basic dXNlcjpwYXNz"}

# Custom header
headers = create_auth_header("api-key", auth_type="custom", header_name="X-API-Key")
# {"X-API-Key": "api-key"}

Secure Session IDs

from praisonaiagents.mcp.mcp_security import generate_secure_session_id

# Generate cryptographically secure session ID
session_id = generate_secure_session_id(length=32)
# Returns URL-safe base64 string with visible ASCII only

Backward Compatibility

Supporting Older Servers

The MCP class automatically handles backward compatibility:
from praisonaiagents import MCP
from praisonaiagents.mcp.mcp_compat import detect_transport_support

# Auto-detection handles:
# 1. Try Streamable HTTP first (POST to endpoint)
# 2. On 400/404/405, fall back to legacy SSE
# 3. URLs ending in /sse use legacy transport directly

mcp = MCP("https://api.example.com/mcp")  # Auto-negotiates

Protocol Versions Supported

VersionTransportStatus
2024-11-05HTTP+SSELegacy (supported)
2025-03-26Streamable HTTPSupported
2025-06-18Streamable HTTPSupported
2025-11-25Streamable HTTPCurrent

Custom Transports

You can implement custom transports by extending the BaseTransport class:
from praisonaiagents.mcp.mcp_transport import BaseTransport, TransportRegistry

class MyCustomTransport(BaseTransport):
    async def connect(self):
        """Establish connection"""
        pass
    
    async def send(self, message: dict):
        """Send JSON-RPC message"""
        pass
    
    async def receive(self) -> dict:
        """Receive JSON-RPC message"""
        pass
    
    async def close(self):
        """Close connection"""
        pass
    
    @property
    def is_connected(self) -> bool:
        return self._connected

# Register custom transport
registry = TransportRegistry()
registry.register("my_transport", MyCustomTransport)

Best Practices

Transport Selection

  • stdio: Local development, NPX packages
  • Streamable HTTP: Production web services
  • WebSocket: Real-time, cloud-native apps
  • SSE: Legacy server compatibility

Session Management

  • Enable sessions for stateful operations
  • Handle HTTP 404 (session expired)
  • Terminate sessions explicitly when done

Resumability

  • Enable for long-running operations
  • Track Last-Event-ID for recovery
  • Respect server retry delays

Security

  • Validate Origin headers
  • Use HTTPS/WSS in production
  • Implement proper authentication
  • Bind to localhost for local servers

Next Steps

MCP Tools

Learn about MCP tool integration

MCP Servers

Explore available MCP servers

SSE Transport Details

Deep dive into SSE transport

Custom MCP Servers

Build your own MCP servers