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.mcp 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