Run OpenClaw as an MCP Server: Complete Guide
OpenClaw as an MCP server
Section titled “OpenClaw as an MCP server”You can think of openclaw mcp as having two primary roles:
- run OpenClaw as an MCP server with
openclaw mcp serve - manage OpenClaw-owned outbound MCP server definitions with
list,show,set, andunset
To put it simply:
serveis OpenClaw acting as an MCP serverlist/show/set/unsetis OpenClaw acting as an MCP client-side registry for other MCP servers its runtimes may consume later
Use openclaw acp when OpenClaw should host a coding harness session itself and route that runtime through ACP.
This is the openclaw mcp serve path.
When to use serve
Section titled “When to use serve”You should use openclaw mcp serve when:
- Codex, Claude Code, or another MCP client should talk directly to OpenClaw-backed channel conversations.
- You already have a local or remote OpenClaw Gateway with routed sessions.
- You want one MCP server that works across OpenClaw’s channel backends.
- You want to avoid running separate per-channel bridges.
Use openclaw acp instead when OpenClaw should host the coding runtime itself and keep the agent session inside OpenClaw.
How it works
Section titled “How it works”openclaw mcp serve starts a stdio MCP server. The MCP client owns that process. While the client keeps the stdio session open, the bridge connects to a local or remote OpenClaw Gateway over WebSocket and exposes routed channel conversations over MCP.
Lifecycle:
- the MCP client spawns
openclaw mcp serve - the bridge connects to Gateway
- routed sessions become MCP conversations and transcript/history tools
- live events are queued in memory while the bridge is connected
- if Claude channel mode is enabled, the same session can also receive Claude-specific push notifications
Important behavior:
- live queue state starts when the bridge connects
- older transcript history is read with
messages_read - Claude push notifications only exist while the MCP session is alive
- when the client disconnects, the bridge exits and the live queue is gone
Choose a client mode
Section titled “Choose a client mode”You can use the same bridge in two different ways:
- Generic MCP clients: standard MCP tools only. Use
conversations_list,messages_read,events_poll,events_wait,messages_send, and the approval tools. - Claude Code: standard MCP tools plus the Claude-specific channel adapter. Enable
--claude-channel-mode onor leave the defaultauto.
Today, auto behaves the same as on. There is no client capability detection yet.
What serve exposes
Section titled “What serve exposes”The bridge uses existing Gateway session route metadata to show you channel-backed conversations. You will see a conversation appear whenever OpenClaw already has session state with a known route, such as:
channel- recipient or destination metadata
- optional
accountId - optional
threadId
This gives your MCP clients a single place to handle several tasks:
- list recent routed conversations
- read recent transcript history
- wait for new inbound events
- send a reply back through the same route
- see approval requests that arrive while the bridge is connected
Getting the bridge running is simple. Here are the commands you can use depending on your setup:
# Local Gatewayopenclaw mcp serve
# Remote Gatewayopenclaw mcp serve --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
# Remote Gateway with password authopenclaw mcp serve --url wss://gateway-host:18789 --password-file ~/.openclaw/gateway.password
# Enable verbose bridge logsopenclaw mcp serve --verbose
# Disable Claude-specific push notificationsopenclaw mcp serve --claude-channel-mode offBridge tools
Section titled “Bridge tools”The current bridge provides these MCP tools for you to work with:
conversations_listconversation_getmessages_readattachments_fetchevents_pollevents_waitmessages_sendpermissions_list_openpermissions_respond
conversations_list
Section titled “conversations_list”This tool lists recent session-backed conversations that already have route metadata in the Gateway session state.
You can use these filters:
limitsearchchannelincludeDerivedTitlesincludeLastMessage
conversation_get
Section titled “conversation_get”Use this to return a single conversation by its session_key.
messages_read
Section titled “messages_read”This allows you to read recent transcript messages for a specific session-backed conversation.
attachments_fetch
Section titled “attachments_fetch”This tool extracts non-text message content blocks from a transcript message. It is important to note that this is a metadata view over transcript content, rather than a standalone durable attachment store.
events_poll
Section titled “events_poll”You can use this to read queued live events starting from a numeric cursor.
events_wait
Section titled “events_wait”This tool long-polls until the next matching queued event arrives or a timeout expires. Use this when your MCP client needs near-real-time delivery without using a Claude-specific push protocol.
messages_send
Section titled “messages_send”This sends text back through the same route already recorded on the session.
Current behavior:
- requires an existing conversation route
- uses the session’s channel, recipient, account id, and thread id
- sends text only
permissions_list_open
Section titled “permissions_list_open”This lists pending exec/plugin approval requests that the bridge has seen since it connected to the Gateway.
permissions_respond
Section titled “permissions_respond”You can resolve a pending exec/plugin approval request with one of these options:
allow-onceallow-alwaysdeny
Event model
Section titled “Event model”The bridge maintains an in-memory event queue while it is connected.
Current event types include:
messageexec_approval_requestedexec_approval_resolvedplugin_approval_requestedplugin_approval_resolvedclaude_permission_request
Keep these limits in mind:
- the queue is live-only; it starts when the MCP bridge starts
events_pollandevents_waitdo not replay older Gateway history on their own- you should read the durable backlog using
messages_read
Claude channel notifications
Section titled “Claude channel notifications”You can use the bridge to access Claude-specific channel notifications. Think of this as the OpenClaw version of a Claude Code channel adapter. Your standard MCP tools stay available. Live inbound messages can also arrive as Claude-specific MCP notifications.
You can control this behavior using these flags:
--claude-channel-mode off: standard MCP tools only--claude-channel-mode on: enable Claude channel notifications--claude-channel-mode auto: current default; same bridge behavior ason
When you enable Claude channel mode, the server advertises Claude experimental capabilities. It can then emit these specific notifications:
notifications/claude/channelnotifications/claude/channel/permission
Here is how the bridge handles things right now:
- It forwards inbound
usertranscript messages asnotifications/claude/channel. - It tracks Claude permission requests received over MCP in-memory.
- If the linked conversation later sends
yes abcdeorno abcde, the bridge converts that tonotifications/claude/channel/permission. - These notifications are live-session only. If the MCP client disconnects, there is no push target.
This setup is intentionally client-specific. If you are using a generic MCP client, you should rely on the standard polling tools instead.
MCP client config
Section titled “MCP client config”Here is an example of a stdio client config you can use. It shows how to point the bridge to your gateway host:
{ "mcpServers": { "openclaw": { "command": "openclaw", "args": [ "mcp", "serve", "--url", "wss://gateway-host:18789", "--token-file", "/path/to/gateway.token" ] } }}For most generic MCP clients, I recommend starting with the standard tool surface and ignoring Claude mode. You should turn Claude mode on only for clients that actually understand the Claude-specific notification methods.
Options
Section titled “Options”When you run openclaw mcp serve, you have several flags to configure how it connects and behaves:
--url <url>: Gateway WebSocket URL--token <token>: Gateway token--token-file <path>: read token from file--password <password>: Gateway password--password-file <path>: read password from file--claude-channel-mode <auto|on|off>: Claude notification mode-v,--verbose: verbose logs on stderr
You should use --token-file or --password-file instead of putting secrets directly in your command line whenever you can. It keeps your credentials out of your shell history.
Security and trust boundary
Section titled “Security and trust boundary”The bridge doesn’t invent its own routing logic. It just shows the conversations that Gateway already knows how to handle.
Here is what that looks like in practice:
- Sender allowlists, pairing, and channel-level trust are still handled by your underlying OpenClaw channel configuration.
messages_sendcan only send replies through a route that is already stored.- Approval states stay in-memory and only last for the current bridge session.
- Bridge authentication uses the same Gateway token or password controls you trust for any other remote Gateway client.
If you notice a conversation is missing from conversations_list, it usually isn’t an issue with your MCP configuration. Most of the time, it means there is missing or incomplete route metadata in the underlying Gateway session.
Testing
Section titled “Testing”OpenClaw includes a deterministic Docker smoke test for this bridge. You can run it with this command:
pnpm test:docker:mcp-channelsThat smoke test handles several tasks:
- It starts a seeded Gateway container.
- It starts a second container that spawns
openclaw mcp serve. - It verifies conversation discovery, transcript reads, attachment metadata reads, live event queue behavior, and outbound send routing.
- It validates Claude-style channel and permission notifications over the real stdio MCP bridge.
This is the fastest way to prove the bridge works without needing to wire a real Telegram, Discord, or iMessage account into your test run.
For more details on the testing environment, check out Testing.
Troubleshooting
Section titled “Troubleshooting”No conversations returned
Section titled “No conversations returned”This usually means the Gateway session is not already routable. You should confirm that the underlying session has stored the necessary channel/provider, recipient, and optional account/thread route metadata.
events_poll or events_wait misses older messages
Section titled “events_poll or events_wait misses older messages”This is expected. The live queue starts exactly when the bridge connects. If you need to read older transcript history, use messages_read.
Claude notifications do not show up
Section titled “Claude notifications do not show up”If these aren’t appearing, check these four points:
- The client kept the stdio MCP session open.
--claude-channel-modeis set toonorauto.- The client actually understands the Claude-specific notification methods.
- The inbound message happened after the bridge connected.
Approvals are missing
Section titled “Approvals are missing”Remember that permissions_list_open only shows approval requests observed while the bridge was connected. It is not designed to be a durable approval history API.
OpenClaw as an MCP client registry
Section titled “OpenClaw as an MCP client registry”You can use OpenClaw as a central place to keep your MCP server definitions. When you run commands like openclaw mcp list, show, set, or unset, you are interacting with the mcp.servers section of your OpenClaw config. OpenClaw stores these definitions so that different runtimes—like embedded Pi or other adapters—can find them later. This way, you don’t have to manage multiple lists of the same servers across different tools.
There are a few important things to remember about how this works. These commands only read or write to your config file. They don’t actually connect to the MCP server or check if your URLs and commands are valid at that moment. The runtime adapters are the ones that decide which transports they support when they actually run.
Saved MCP server definitions
Section titled “Saved MCP server definitions”OpenClaw includes a lightweight registry for any part of the system that needs managed MCP definitions. You can use these commands to manage your list:
openclaw mcp listopenclaw mcp show [name]openclaw mcp set <name> <json>openclaw mcp unset <name>
Here are some examples of how that looks in practice:
openclaw mcp listopenclaw mcp show context7 --jsonopenclaw mcp set context7 '{"command":"uvx","args":["context7-mcp"]}'openclaw mcp set docs '{"url":"https://mcp.example.com"}'openclaw mcp unset context7Your config file will end up looking something like this:
{ "mcp": { "servers": { "context7": { "command": "uvx", "args": ["context7-mcp"] }, "docs": { "url": "https://mcp.example.com" } } }}Stdio transport
Section titled “Stdio transport”This transport launches a local child process and talks to it using stdin and stdout.
| Field | Description |
|---|---|
command | Executable to spawn (required) |
args | Array of command-line arguments |
env | Extra environment variables |
cwd / workingDirectory | Working directory for the process |
SSE / HTTP transport
Section titled “SSE / HTTP transport”This option connects to a remote MCP server using HTTP Server-Sent Events.
| Field | Description |
|---|---|
url | HTTP or HTTPS URL of the remote server (required) |
headers | Optional key-value map of HTTP headers (for example auth tokens) |
connectionTimeout | Per-server connection timeout in ms (optional) |
Example:
{ "mcp": { "servers": { "remote-tools": { "url": "https://mcp.example.com", "headers": { "Authorization": "Bearer <token>" } } } }}If you have sensitive data in your url or headers, OpenClaw redacts those values in logs and status reports.
Streamable HTTP transport
Section titled “Streamable HTTP transport”Besides sse and stdio, you can use streamable-http. This uses HTTP streaming for two-way communication with remote servers.
| Field | Description |
|---|---|
url | HTTP or HTTPS URL of the remote server (required) |
transport | Set to "streamable-http" to select this transport |
headers | Optional key-value map of HTTP headers (for example auth tokens) |
connectionTimeout | Per-server connection timeout in ms (optional) |
Example:
{ "mcp": { "servers": { "streaming-tools": { "url": "https://mcp.example.com/stream", "transport": "streamable-http", "connectionTimeout": 10000, "headers": { "Authorization": "Bearer <token>" } } } }}Just a reminder: these commands only handle your saved config. They don’t start a channel bridge or verify that the target server is actually online.
Current limits
Section titled “Current limits”This is how the bridge works right now.
Current limits:
- Conversation discovery relies on existing Gateway session route metadata
- There is no generic push protocol yet, only the Claude-specific adapter
- You cannot use message edit or react tools at this time
- HTTP, SSE, and streamable-http transports connect to one remote server; there is no multiplexing
- The
permissions_list_openfield only shows approvals that happened while the bridge was connected
OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.