MCP server bridging Claude.ai/Desktop with self-hosted OpenClaw via OAuth 2.1.
io.github.freema/openclaw-mcp MCP Server
This MCP server bridges Claude.ai/Desktop with a self-hosted OpenClaw service using OAuth 2.1. It is delivered as the io.github.freema/openclaw-mcp package and is associated with container distribution at ghcr.io/freema/openclaw--mcp.
π¦ Model Context Protocol (MCP) server for OpenClaw AI assistant integration.
Demo
Why I Built This
Hey! I created this MCP server because I didn't want to rely solely on messaging channels to communicate with OpenClaw. What really excites me is the ability to connect OpenClaw to the Claude web UI. Essentially, my chat can delegate tasks to my Claw bot, which then handles everything else β like spinning up Claude Code to fix issues for me.
Think of it as an AI assistant orchestrating another AI assistant. Pretty cool, right?
Quick Start
Docker (Recommended)
Pre-built images are published to GitHub Container Registry on every release.
Then in Claude.ai add a custom MCP connector pointing to https://your-domain.com/mcp with MCP_CLIENT_ID=openclaw and your MCP_CLIENT_SECRET.
Important: The connector URL must end with /mcp β that's the Streamable HTTP endpoint. A bare domain (https://your-domain.com) hits the server root and returns 404 after OAuth completes.
Tip: Pin a specific version instead of latest for production: ghcr.io/freema/openclaw-mcp:1.1.0
Important: When running behind a reverse proxy (Caddy, nginx, Traefik, Cloudflare Tunnel, etc.) you must set:
MCP_ISSUER_URL (or --issuer-url) to your public HTTPS URL β otherwise OAuth metadata advertises http://localhost:3000 and clients fail to authenticate.
TRUST_PROXY=1 (or --trust-proxy 1) β otherwise express-rate-limit rejects the proxy's X-Forwarded-For header and /token crashes with ERR_ERL_UNEXPECTED_X_FORWARDED_FOR.
Recommended: Set MCP_REDIRECT_URIS=https://claude.ai/api/mcp/auth_callback,https://claude.com/api/mcp/auth_callback so authorization codes can only be delivered to Claude's callbacks. Note the exact /api/mcp/auth_callback path β matching is exact, and getting it wrong fails OAuth with Unregistered redirect_uri (see Troubleshooting).
Tasks are scoped to the MCP connection that created them. In HTTP mode, where
one process serves many clients, a client can only see and cancel its own
tasks β another client's task_id reads as "not found" even if it is known.
Reconnecting starts a fresh scope, so poll a task on the connection that
queued it.
Multi-Instance Mode
Orchestrate multiple OpenClaw gateways from a single MCP server. One bridge, many claws β route requests to prod, staging, dev, or whatever you name them (lobster-supreme and the-claw-abides are perfectly valid names).
Two defaults changed for security. Both only affect HTTP mode; stdio is
unchanged.
CORS is now off by default. Previously an unset CORS_ORIGINS sent
Access-Control-Allow-Origin: *. If a browser client depends on that, set
the origins explicitly (CORS_ORIGINS=https://your-app.com), or
CORS_ORIGINS=* to restore the old behaviour.
Async tasks are scoped to the connection that created them. A client
that used to poll a task_id queued by a different connection will now get
"not found".
Migrating from SSE to HTTP transport
Starting with v1.5.0, the primary transport is Streamable HTTP (--transport http). The legacy SSE transport (--transport sse) is deprecated but still works for backward compatibility.
What changed
Before
After
--transport sse
--transport http (recommended)
Primary endpoint: GET /sse
Primary endpoint: POST/GET/DELETE /mcp
Health: "transport": "sse"
Health: "transport": "streamable-http"
Migration steps
CLI / Docker: Replace --transport sse with --transport http
bash
# Before
openclaw-mcp --transport sse --port 3000
# After
openclaw-mcp --transport http --port 3000