Abstract
The Model Context Protocol (MCP) is designed to be transport-agnostic. While most implementations support stdio and SSE by default, real-world enterprise systems often require custom transports such as:
HTTP (JSON-RPC over POST)
WebSocket (bidirectional streaming)
Message queues (Kafka, RabbitMQ)
This article explains how MCP works internally and how to implement a custom transport layer (HTTP and WebSocket) in Python.
Understanding MCP Architecture
MCP separates two concerns:
| Layer | Responsibility |
|---|---|
| Protocol Layer | JSON-RPC message format |
| Transport Layer | How messages are delivered |
MCP defines:
Tool registration
JSON-RPC methods (
tools/list,tools/call)Structured request/response format
It does not mandate how messages are transported. That’s why you can plug in custom transports.
MCP Internal Flow
Client - Transport Layer - MCP Message Handler - Tool Execution - Transport ResponseThe key idea:
Your custom transport only needs to forward JSON messages to the MCP handler.
Implementing HTTP Transport (JSON-RPC over POST)
This is ideal when:
Integrating with API gateways
Deploying in microservices
Running behind load balancers
Install Dependencies
pip install fastapi uvicorn mcpExample HTTP MCP Server
# http_mcp_server.py
from fastapi import FastAPI, Request
from mcp.server.fastmcp import FastMCP
app = FastAPI()
mcp = FastMCP("HTTP MCP Server")
# Define tool
@mcp.tool()
def leave_balance(employee_name: str) -> int:
return {"Jayant": 15}.get(employee_name, 0)
@app.post("/mcp")
async def handle_mcp(request: Request):
body = await request.json()
# Pass raw JSON-RPC message to MCP
response = await mcp.handle_message(body)
return responseRun Server
uvicorn http_mcp_server:app --reloadEndpoint:
POST http://localhost:8000/mcpCharacteristics of HTTP Transport
Stateless
Simple to deploy
No streaming support (unless chunked)
Easy to secure via middleware

Join the conversation! Your thoughts help the community grow.