Skip to content

Run OpenClaw as an MCP Server: Complete Guide

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, and unset

To put it simply:

  • serve is OpenClaw acting as an MCP server
  • list / show / set / unset is 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.

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.

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:

  1. the MCP client spawns openclaw mcp serve
  2. the bridge connects to Gateway
  3. routed sessions become MCP conversations and transcript/history tools
  4. live events are queued in memory while the bridge is connected
  5. 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

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 on or leave the default auto.

Today, auto behaves the same as on. There is no client capability detection yet.

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:

Terminal window
# Local Gateway
openclaw mcp serve
# Remote Gateway
openclaw mcp serve --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token
# Remote Gateway with password auth
openclaw mcp serve --url wss://gateway-host:18789 --password-file ~/.openclaw/gateway.password
# Enable verbose bridge logs
openclaw mcp serve --verbose
# Disable Claude-specific push notifications
openclaw mcp serve --claude-channel-mode off

The current bridge provides these MCP tools for you to work with:

  • conversations_list
  • conversation_get
  • messages_read
  • attachments_fetch
  • events_poll
  • events_wait
  • messages_send
  • permissions_list_open
  • permissions_respond

This tool lists recent session-backed conversations that already have route metadata in the Gateway session state.

You can use these filters:

  • limit
  • search
  • channel
  • includeDerivedTitles
  • includeLastMessage

Use this to return a single conversation by its session_key.

This allows you to read recent transcript messages for a specific session-backed conversation.

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.

You can use this to read queued live events starting from a numeric cursor.

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.

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

This lists pending exec/plugin approval requests that the bridge has seen since it connected to the Gateway.

You can resolve a pending exec/plugin approval request with one of these options:

  • allow-once
  • allow-always
  • deny

The bridge maintains an in-memory event queue while it is connected.

Current event types include:

  • message
  • exec_approval_requested
  • exec_approval_resolved
  • plugin_approval_requested
  • plugin_approval_resolved
  • claude_permission_request

Keep these limits in mind:

  • the queue is live-only; it starts when the MCP bridge starts
  • events_poll and events_wait do not replay older Gateway history on their own
  • you should read the durable backlog using messages_read

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 as on

When you enable Claude channel mode, the server advertises Claude experimental capabilities. It can then emit these specific notifications:

  • notifications/claude/channel
  • notifications/claude/channel/permission

Here is how the bridge handles things right now:

  • It forwards inbound user transcript messages as notifications/claude/channel.
  • It tracks Claude permission requests received over MCP in-memory.
  • If the linked conversation later sends yes abcde or no abcde, the bridge converts that to notifications/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.

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.

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 &lt;auto|on|off&gt;: 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.

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_send can 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.

OpenClaw includes a deterministic Docker smoke test for this bridge. You can run it with this command:

Terminal window
pnpm test:docker:mcp-channels

That 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.

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.

If these aren’t appearing, check these four points:

  • The client kept the stdio MCP session open.
  • --claude-channel-mode is set to on or auto.
  • The client actually understands the Claude-specific notification methods.
  • The inbound message happened after the bridge connected.

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.

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.

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 list
  • openclaw mcp show [name]
  • openclaw mcp set <name> <json>
  • openclaw mcp unset <name>

Here are some examples of how that looks in practice:

Terminal window
openclaw mcp list
openclaw mcp show context7 --json
openclaw mcp set context7 '{"command":"uvx","args":["context7-mcp"]}'
openclaw mcp set docs '{"url":"https://mcp.example.com"}'
openclaw mcp unset context7

Your config file will end up looking something like this:

{
"mcp": {
"servers": {
"context7": {
"command": "uvx",
"args": ["context7-mcp"]
},
"docs": {
"url": "https://mcp.example.com"
}
}
}
}

This transport launches a local child process and talks to it using stdin and stdout.

FieldDescription
commandExecutable to spawn (required)
argsArray of command-line arguments
envExtra environment variables
cwd / workingDirectoryWorking directory for the process

This option connects to a remote MCP server using HTTP Server-Sent Events.

FieldDescription
urlHTTP or HTTPS URL of the remote server (required)
headersOptional key-value map of HTTP headers (for example auth tokens)
connectionTimeoutPer-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.

Besides sse and stdio, you can use streamable-http. This uses HTTP streaming for two-way communication with remote servers.

FieldDescription
urlHTTP or HTTPS URL of the remote server (required)
transportSet to "streamable-http" to select this transport
headersOptional key-value map of HTTP headers (for example auth tokens)
connectionTimeoutPer-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.

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_open field only shows approvals that happened while the bridge was connected
OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.