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
stdio Transport
Streamable HTTP
WebSocket
SSE Legacy
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 Pattern Transport Example ws:// or wss://WebSocket ws://localhost:8080/mcphttp(s)://... ending in /sseSSE (Legacy) http://localhost:8080/ssehttp:// or https://Streamable HTTP https://api.example.com/mcpCommand string stdio npx @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
Version Transport Status 2024-11-05 HTTP+SSE Legacy (supported) 2025-03-26 Streamable HTTP Supported 2025-06-18 Streamable HTTP Supported 2025-11-25 Streamable HTTP Current
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