Transports

Two ways for agents to talk to your MCP server. Both share the same handle_rpc dispatch underneath โ€” only the wire is different.

HTTP โ€” for production and browser-launched agents

Setup

# urls.py โ€” the one-liner
urlpatterns = get_routes(endpoints, mcp=True)
# โ†’ POST /mcp

Or with custom behaviour:

from zeromcp import MCPResource

class MyMCP(MCPResource):
    endpoints = my_endpoints
    summary = 'agent-tools'

urlpatterns = [path('mcp/', MyMCP.as_view())]

Wire format

Single endpoint, JSON-RPC 2.0 over HTTP POST. Each request body is one message:

POST /mcp HTTP/1.1
Content-Type: application/json

{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{"jsonrpc": "2.0", "id": 1, "result": {"tools": [...]}}

Use it for

stdio โ€” for desktop agents

Setup

MCP_API_KEY="<your-token>" python manage.py mcp_serve myapp.urls.endpoints

The first argument is the dotted path to your endpoints registry. The command reads newline-delimited JSON-RPC from stdin, dispatches via handle_rpc, writes responses to stdout.

Use it for

Example agent config

{
  "mcpServers": {
    "myapp": {
      "command": "python",
      "args": ["manage.py", "mcp_serve", "myapp.urls.endpoints"],
      "cwd": "/path/to/your/django/project",
      "env": {
        "MCP_API_KEY": "your-token-here",
        "DJANGO_SETTINGS_MODULE": "myapp.settings"
      }
    }
  }
}

Authentication

Both transports use 0-mcp's existing auth โ€” no new code path. The MCP bridge attaches credentials to a synthetic HttpRequest that goes through the same _authenticate you use for REST.

API key

The agent attaches a X-Api-Key header (HTTP) or sets MCP_API_KEY (stdio). 0-mcp's _authenticate resolves the key and switches to the matching tenant DB.

How keys are issued is up to your project โ€” 0-mcp does not enforce a particular format. See Authentication for the resolution flow 0-mcp uses, and Sessions for issuing keys.

Session cookie

HTTP transport accepts the session cookie like any other request. Useful when the agent runs inside a web app that already has a session.

Anonymous access

Set authenticated = False on your MCPResource subclass for unauthenticated tool calls. Use carefully โ€” the agent will run with no user, so anything that depends on self.user will need explicit handling.

Comparison

TransportAuthProcess modelBest for
HTTPX-Api-Key header or session cookieInside your ASGI serverProduction, browsers, services
stdioMCP_API_KEY env varSubprocess launched by the agentClaude Desktop, Cursor, local agents

Direct dispatch โ€” no HTTP loopback

Even the HTTP transport does not make a real network call to itself when running a tool. The bridge builds a synthetic HttpRequest, wraps view_cls.as_view() with the project's settings.MIDDLEWARE (async-capable only), and calls it directly:

๐Ÿ”Œ

HTTP and stdio share the same handle_rpc and bridge.call_tool. Adding a third transport is mostly an IO-loop change โ€” the protocol layer stays untouched.

0-mcp by Stamatios Stamou Jr โ€” github.com/ssjunior/0-mcp