OpenClaw MCP Proxy

OpenClaw MCP Proxy

Exposes app-registered tools as an MCP server for OpenClaw, forwarding actual tool execution back to the app over a WebSocket bridge.

Category
Visit Server

README

OpenClaw MCP Proxy

OpenClaw MCP Proxy is a small FastAPI + FastMCP service that exposes app-registered tools as an MCP server for OpenClaw, while forwarding actual tool execution back to the app over a WebSocket bridge.

It has two responsibilities:

  • Manage chat-scoped proxy sessions over HTTP and WebSocket.
  • Expose the registered tool set as MCP over either stateless HTTP or stdio.

Architecture

sequenceDiagram
    participant AppClient
    participant ProxyServer
    participant OpenClawClient

    AppClient->>ProxyServer: POST /v1/chat/sessions
    ProxyServer-->>AppClient: mcpSessionId, bridge_url, mcp_url
    AppClient->>ProxyServer: WS /v1/chat/sessions/{session_id}/bridge
    OpenClawClient->>ProxyServer: POST /v1/mcp/{session_id}
    ProxyServer->>AppClient: invoke_tool
    AppClient-->>ProxyServer: invoke_result
    ProxyServer-->>OpenClawClient: MCP tool result
    AppClient->>ProxyServer: DELETE /v1/chat/sessions/{session_id}

Endpoints

POST /v1/chat/sessions

Creates a session and returns the bridge and MCP endpoints for that session.

Request body:

{
  "device_id": "device-1",
  "device_name": "desktop",
  "app_version": "1.0.0",
  "chat_id": "chat-1",
  "tools": [
    {
      "name": "echo_text",
      "path": "/tools/echo_text",
      "description": "Echo text.",
      "input_schema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          }
        }
      }
    }
  ]
}

Response body:

{
  "mcpSessionId": "session-id",
  "bridge_url": "ws://127.0.0.1:8000/v1/chat/sessions/session-id/bridge",
  "mcp_url": "http://127.0.0.1:8000/v1/mcp/session-id"
}

DELETE /v1/chat/sessions/{session_id}

Deletes a session.

Response body:

{
  "ok": true
}

WS /v1/chat/sessions/{session_id}/bridge

Connects the app-side execution bridge for a registered session.

Bridge messages:

  • Proxy -> app: invoke_tool
  • App -> proxy: invoke_result
  • Proxy -> app: ping
  • App -> proxy: pong

Proxy -> app:

{
  "type": "invoke_tool",
  "mcpSessionId": "session-id",
  "request_id": "session-id:1",
  "tool_name": "echo_text",
  "arguments": {
    "text": "hello"
  }
}

App -> proxy:

{
  "type": "invoke_result",
  "mcpSessionId": "session-id",
  "request_id": "session-id:1",
  "ok": true,
  "content": {
    "echoed_text": "hello"
  }
}

POST /v1/mcp/{session_id}

Exposes the registered tools for a specific session as a stateless HTTP MCP endpoint.

This is the simplest way to connect OpenClaw to a specific registered session.

POST /v1/mcp/ with MCP-Session-Id

The MCP endpoint also supports header-based session routing:

  • Header: MCP-Session-Id: <session_id>

This is useful when the MCP client configuration prefers a stable URL and injects the session ID through headers.

MCP Transports

The proxy now supports two MCP-facing transports:

  • HTTP: multi-session, routed by path or MCP-Session-Id
  • stdio: single-session, bound during MCP initialize via mcpSessionId

The stdio transport is implemented as a local proxy process in front of the HTTP MCP endpoint. The actual tool execution path is unchanged:

  1. The app registers a session over HTTP.
  2. The app connects the WebSocket bridge.
  3. The stdio process stores initialize.params.mcpSessionId and proxies MCP traffic to POST /v1/mcp with header MCP-Session-Id.
  4. The HTTP proxy forwards tool execution to the app over the existing bridge.

GET /health

Returns plain text ok.

Authentication

The proxy uses two independent bearer tokens:

  • OPENCLAW_PROXY_APP_TOKEN Used by:

    • POST /v1/chat/sessions
    • DELETE /v1/chat/sessions/{session_id}
    • WS /v1/chat/sessions/{session_id}/bridge
  • OPENCLAW_PROXY_OPENCLAW_TOKEN Used by:

    • /v1/mcp/...

Important:

  • If OPENCLAW_PROXY_APP_TOKEN is empty, app-facing endpoints accept requests without authentication.
  • If OPENCLAW_PROXY_OPENCLAW_TOKEN is empty, MCP-facing endpoints accept requests without authentication.

Do not leave either token empty outside local development.

WebSocket close codes:

  • 4401: invalid app token
  • 4404: unknown session_id

Configuration

Environment variables:

Variable Default Description
OPENCLAW_PROXY_APP_TOKEN "" Bearer token for app registration and bridge endpoints.
OPENCLAW_PROXY_OPENCLAW_TOKEN "" Bearer token for MCP requests from OpenClaw.
OPENCLAW_PROXY_SERVER_URL http://127.0.0.1:8000 Base URL used by the stdio proxy process to reach the HTTP proxy.
OPENCLAW_PROXY_SESSION_TTL_SECONDS 300 Session time-to-live in seconds.
OPENCLAW_PROXY_TOOL_TIMEOUT_SECONDS 120 Tool call timeout in seconds.

Example .env:

OPENCLAW_PROXY_APP_TOKEN=replace-me
OPENCLAW_PROXY_OPENCLAW_TOKEN=replace-me
OPENCLAW_PROXY_SERVER_URL=http://127.0.0.1:8000
OPENCLAW_PROXY_SESSION_TTL_SECONDS=300
OPENCLAW_PROXY_TOOL_TIMEOUT_SECONDS=120

Run Locally

Requirements

  • Python 3.11+ recommended
  • pip

Install dependencies

pip install -r requirements.txt

Start the server

uvicorn app.main:app --host 0.0.0.0 --port 8000

Start the stdio MCP proxy

After creating a session and connecting the app bridge, you can expose that session over stdio:

python -m app.stdio_main

Optional flags:

python -m app.stdio_main \
  --proxy-base-url http://127.0.0.1:8000

The stdio client must send mcpSessionId in initialize.params, for example:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": {
      "name": "your-client",
      "version": "1.0.0"
    },
    "mcpSessionId": "<session_id>"
  }
}

Check health

curl http://127.0.0.1:8000/health

Expected output:

ok

OpenClaw MCP Configuration

Header-routed example:

{
  "mcpServers": {
    "otakuroom-chat-mcp": {
      "transport": "http",
      "url": "https://your-proxy-host.example.com/v1/mcp",
      "headers": {
        "Authorization": "Bearer ${OPENCLAW_PROXY_OPENCLAW_TOKEN}",
        "MCP-Session-Id": "${SESSION_ID}"
      }
    }
  }
}

You can also connect directly to the session-specific URL returned by session creation, for example:

https://your-proxy-host.example.com/v1/mcp/<session_id>

Stdio example:

{
  "mcpServers": {
    "otakuroom-chat-mcp": {
      "transport": "stdio",
      "command": "python",
      "args": [
        "-m",
        "app.stdio_main"
      ],
      "env": {
        "OPENCLAW_PROXY_SERVER_URL": "http://127.0.0.1:8000",
        "OPENCLAW_PROXY_OPENCLAW_TOKEN": "${OPENCLAW_PROXY_OPENCLAW_TOKEN}"
      }
    }
  }
}

How Tool Forwarding Works

  1. The app creates a session and sends its available tool definitions.
  2. The proxy stores the session in memory.
  3. OpenClaw calls the session MCP endpoint.
  4. The proxy dynamically builds a FastMCP server for that session and tool set.
  5. When OpenClaw invokes a tool, the proxy sends invoke_tool over the WebSocket bridge.
  6. The app executes the tool locally and sends invoke_result.
  7. The proxy returns the tool result to the MCP caller.

Testing

Run the proxy integration tests:

python -m unittest tests.test_proxy_integration

Current coverage includes:

  • session-specific MCP routing via mcp_url
  • header-based MCP routing via MCP-Session-Id
  • normal WebSocket bridge disconnect without error-level logging
  • shared MCP server construction and stdio proxy bootstrap behavior

Operational Notes

  • Sessions are stored in memory only. The proxy is not currently designed for stateless multi-instance deployment without sticky routing or shared session state.

  • Tool calls require an active bridge connection. If the session exists but the bridge is disconnected, tool calls fail with Bridge is not connected.

  • Sessions expire automatically. A background cleanup loop runs every 15 seconds and removes expired sessions.

  • Registered tool names must be unique within a session.

  • Reverse proxies must support WebSocket upgrade and must forward:

    • Authorization
    • MCP-Session-Id
  • HTTP MCP is served directly from the in-process session registry.

  • stdio MCP runs as a separate proxy process and forwards to the HTTP MCP endpoint.

  • Tool schemas are registered dynamically from the provided input_schema. Only trusted app clients should be allowed to register tool definitions.

Limitations

  • No persistent session storage.
  • No built-in rate limiting.
  • No container or deployment manifests are included in this directory.
  • Audit logging is plain application logging, not a full security audit pipeline.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured