OpenClaw MCP: Server and Client Registry Commands

Learn how to expose OpenClaw channel conversations over MCP and manage outbound MCP server definitions. Covers serve, list, show, status, doctor, probe, add, set, configure, tools, login, logout, reload, and unset.

Read this when

  • Connecting Codex, Claude Code, or another MCP client to OpenClaw-backed channels
  • Running `openclaw mcp serve`
  • Managing OpenClaw-saved MCP server definitions

openclaw mcp serves two purposes:

  • operate OpenClaw as an MCP server through openclaw mcp serve
  • handle OpenClaw-managed outbound MCP server definitions via list, show, status, doctor, probe, add, set, configure, tools, login, logout, reload, and unset

When OpenClaw acts as an MCP server, that is serve. The remaining subcommands treat OpenClaw as a client-side registry, storing servers that its own runtimes might use later.

Note

Only OpenClaw-managed mcp.servers entries in OpenClaw config are touched by list, show, set, and unset. Servers from the mcporter registry in config/mcporter.json are excluded; turn to mcporter list for that one.

If OpenClaw itself should run a coding harness session and push that runtime through ACP, use openclaw acp.

Choose the right MCP path

GoalUseWhy
Allow an external MCP client to read/send OpenClaw channel conversationsopenclaw mcp serveOpenClaw serves as the MCP server, exposing Gateway-backed conversations through stdio.
Keep third-party MCP servers available for OpenClaw-managed agent runsopenclaw mcp add, set, configure, tools, loginOpenClaw acts as the client-side MCP registry and later projects those servers into eligible runtimes.
Inspect a saved server without triggering an agent turnopenclaw mcp status, doctor, probeConfig is examined by status and doctor; probe opens a live MCP connection and lists capabilities.
Modify MCP config through a browserControl UI /settings/mcp (/mcp alias)The page displays inventory, enablement, OAuth/filter summaries, command hints, and a scoped mcp editor.
Provide Codex app-server with a scoped native MCP servermcp.servers.<name>.codexThe codex block affects only Codex app-server thread projection and is removed before native config handoff.
Run ACP-hosted harness sessionsopenclaw acp and ACP AgentsACP bridge mode rejects per-session MCP server injection; configure gateway/plugin bridges instead.

Tip

When uncertain about the right path, begin with openclaw mcp status --verbose. It reveals what OpenClaw has stored without launching any MCP servers.

OpenClaw as an MCP server

This is the openclaw mcp serve route.

When to use serve

Choose openclaw mcp serve when:

  • Codex, Claude Code, or another MCP client needs to reach OpenClaw-backed channel conversations directly
  • a local or remote OpenClaw Gateway with routed sessions is already in place
  • a single MCP server covering OpenClaw's channel backends is preferred over separate per-channel bridges

Pick openclaw acp instead when OpenClaw should take on hosting the coding runtime and keep the agent session within OpenClaw.

How it works

A stdio MCP server is started by openclaw mcp serve. That process is owned by the MCP client. As long as the stdio session remains open, the bridge links to a local or remote OpenClaw Gateway via WebSocket, making routed channel conversations available over MCP.

Client spawns the bridge

openclaw mcp serve is launched by the MCP client.

Bridge connects to Gateway

Through WebSocket, the bridge reaches the OpenClaw Gateway.

Sessions become MCP conversations

Routed sessions turn into MCP conversations, with transcript and history tools.

Live events queue

Live events wait in memory as long as the bridge stays connected.

Optional Claude push

When Claude channel mode is turned on, that same session can additionally receive push notifications that are specific to Claude.

Important behavior

  • the live queue state begins at the moment the bridge establishes its connection
  • earlier transcript history gets pulled in through messages_read
  • Claude push notifications are available only while the MCP session remains active
  • once the client drops the connection, the bridge shuts down and the live queue disappears
  • cancelling an events_wait request frees its server-side wait and timeout right away
  • when the bridge or MCP transport closes with an error, openclaw mcp serve fails rather than reporting a clean shutdown
  • one-shot agent entry points like openclaw agent and openclaw infer model run dispose of any bundled MCP runtimes they start once the reply finishes, so repeated scripted runs do not leave behind accumulated stdio MCP child processes
  • stdio MCP servers that OpenClaw launches, whether bundled or user-configured, get torn down as a process tree during shutdown, which means child subprocesses started by the server do not persist after the parent stdio client exits
  • deleting or resetting a session cleans up that session's MCP clients through the shared runtime cleanup path, so no stdio connections linger for a removed session

Choose a client mode

Generic MCP clients

Only the standard MCP tools apply. Go with conversations_list, messages_read, events_poll, events_wait, messages_send, and the approval tools.

Claude Code

Standard MCP tools plus the channel adapter specific to Claude. Turn on --claude-channel-mode on or stick with the default auto.

Note

As of now, auto and on behave identically. Client capability detection has not been implemented yet.

What serve exposes

To surface channel-backed conversations, the bridge relies on route metadata already present in Gateway session state. A conversation shows up whenever OpenClaw already holds session state with a known route, for instance:

  • channel
  • recipient or destination metadata
  • accountId when present
  • threadId when present

That setup gives MCP clients a single place to:

  • list routed conversations from recent activity
  • pull up recent transcript history
  • wait for new inbound events
  • send a reply back along the same route
  • see approval requests that show up while the bridge is connected

Usage

Local Gateway

openclaw mcp serve

Remote Gateway (token)

openclaw mcp serve --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token

Remote Gateway (password)

openclaw mcp serve --url wss://gateway-host:18789 --password-file ~/.openclaw/gateway.password

Verbose / Claude off

openclaw mcp serve --verbose
openclaw mcp serve --claude-channel-mode off

Bridge tools

conversations_list

Lists recent session-backed conversations that already carry route metadata in Gateway session state.

Filters: limit (max 500), search, channel, includeDerivedTitles, includeLastMessage.

conversation_get

Returns a single conversation matched by session_key through a direct Gateway session lookup.

messages_read

Reads recent transcript messages for one session-backed conversation. limit starts at 20 by default, with 200 as the ceiling.

attachments_fetch

Pulls out non-text message content blocks and canonical persisted media metadata from a single transcript message. Persisted entries rely on { "type": "openclaw_media", "media": { ... } }, where media may hold url, contentType, kind, fileName, dimensions, duration, or size. This view only exposes metadata, it does not act as a separate durable attachment blob store.

events_poll

Reads queued live events starting from a numeric cursor. limit caps at 200. If the cursor you request goes back further than the retained queue history, the response also carries gap.requested_after_cursor and gap.oldest_available_cursor.

events_wait

Long-polls until the next matching queued event arrives or the timeout runs out (30s by default, 300s max).

Reach for this when a generic MCP client needs near-real-time delivery but has no Claude-specific push protocol available. A known cursor gap returns right away with the same additive gap metadata, even if no matching event is currently held in the queue.

messages_send

Sends text back through the route already recorded on the session.

What happens right now:

  • an existing conversation route is required
  • the session's channel, recipient, account id, and thread id are used
  • only text gets sent

permissions_list_open

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

permissions_respond

Resolves one pending exec/plugin approval request using:

  • allow-once
  • allow-always
  • deny

Event model

An in-memory event queue is kept by the bridge while it remains connected.

Event types available now:

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

Warning

  • the queue operates only during a live session; it becomes active the moment the MCP bridge launches
  • neither events_poll nor events_wait will, on their own, replay earlier Gateway history
  • the queue has a fixed size; when gap is set, pull durable history through messages_read, then pick up again with after_cursor assigned a value one below gap.oldest_available_cursor
  • access the durable backlog via messages_read

Claude channel notifications

Claude-specific channel notifications can also be exposed by the bridge. Think of this as the OpenClaw counterpart to a Claude Code channel adapter: the usual MCP tools stay in place, but live inbound messages may additionally arrive as MCP notifications tailored to Claude.

off

--claude-channel-mode off: only the standard MCP tools are offered.

on

--claude-channel-mode on: turns on Claude channel notifications.

auto (default)

--claude-channel-mode auto: the current default; bridge behavior matches on.

Once Claude channel mode is active, the server advertises Claude experimental capabilities and can send out:

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

How the bridge behaves right now:

  • incoming user transcript messages get forwarded as notifications/claude/channel
  • Claude permission requests arriving over MCP are kept in memory
  • if the command owner in the associated conversation later issues yes <id> or no <id> (where <id> is the 5-character request id, leaving out l), the bridge turns that into notifications/claude/channel/permission
  • these notifications exist only for the live session; with the MCP client disconnected, no push destination remains

This design is deliberately client-specific. Generic MCP clients should stick with the standard polling tools.

MCP client config

Sample stdio client configuration:

{
  "mcpServers": {
    "openclaw": {
      "command": "openclaw",
      "args": [
        "mcp",
        "serve",
        "--url",
        "wss://gateway-host:18789",
        "--token-file",
        "/path/to/gateway.token"
      ]
    }
  }
}

For most generic MCP clients, begin with the standard tool surface and leave Claude mode alone. Enable Claude mode only for clients that genuinely understand the Claude-specific notification methods.

Options

Supported by openclaw mcp serve:

  • --url (string), Gateway WebSocket URL. Falls back to gateway.remote.url when set.

  • --token (string), Gateway token.

  • --token-file (string), Load the token from a file.

  • --password (string), Gateway password.

  • --password-file (string), Load the password from a file.

  • --claude-channel-mode (auto" | "on" | "off), Claude notification mode. Defaults to auto.

  • -v, --verbose (boolean), Verbose logging to stderr.

Tip

Whenever possible, go with --token-file or --password-file instead of putting secrets directly inline.

Security and trust boundary

Routing is never invented by the bridge. Only conversations that Gateway already knows how to route get exposed.

What that implies:

  • sender allowlists, pairing, and channel-level trust remain the responsibility of the underlying OpenClaw channel configuration
  • messages_send can respond only through a route that was previously stored
  • approval state lives only in memory for the current bridge session
  • bridge authentication should rely on the same Gateway token or password controls you would trust for any other remote Gateway client

If a conversation does not show up in conversations_list, the usual culprit is not MCP configuration. More often it is route metadata that is incomplete or absent in the underlying Gateway session.

Testing

A deterministic Docker smoke test ships with OpenClaw for this bridge:

pnpm test:docker:mcp-channels

That smoke test runs a single container: conversation state is seeded, the Gateway is started, then openclaw mcp serve is launched as a stdio child process and driven as an MCP client. It checks conversation discovery, transcript reads, attachment metadata reads, live event queue behavior, and Claude-style channel and permission notifications across the real stdio MCP bridge. Outbound send routing (messages_send reusing the stored conversation route) gets its own coverage from unit tests in src/mcp/channel-server.test.ts.

This is the quickest way to confirm the bridge works without connecting a real Telegram, Discord, or iMessage account to the test run.

For more testing context, see Testing.

Troubleshooting

No conversations returned

Typically the Gateway session is not routable yet. Verify that the underlying session has stored channel/provider, recipient, and optional account/thread route metadata.

events_poll or events_wait misses older messages

The live queue starts when the bridge connects and keeps only a bounded window. If a result contains gap, read durable transcript history with messages_read, then resume with after_cursor set to one less than gap.oldest_available_cursor.

Claude notifications do not show up

Check every one of these:

  • the stdio MCP session remained open on the client side
  • --claude-channel-mode equals on or auto
  • the client recognizes the Claude-specific notification methods
  • the inbound message arrived after the bridge had established its connection

Approvals are missing

permissions_list_open displays only those approval requests that were observed during the bridge's active connection period. It does not function as a persistent record of approval history.

OpenClaw as an MCP client registry

This is the openclaw mcp list, show, status, doctor, probe, add, set, configure, tools, login, logout, reload, and unset path.

These commands do not expose OpenClaw through MCP. They handle MCP server definitions that OpenClaw manages, located under mcp.servers in the OpenClaw configuration. They do not access mcporter servers from config/mcporter.json.

Those stored definitions serve runtimes that OpenClaw starts or sets up at a later point, including embedded OpenClaw and other runtime adapters. OpenClaw keeps these definitions in one central place so those runtimes do not have to maintain their own separate MCP server lists.

Important behavior

  • these commands only interact with OpenClaw configuration
  • status, list, show, doctor without --probe, set, configure, tools, logout, reload, and unset do not establish a connection to the target MCP server
  • login runs the MCP OAuth network flow for the specified HTTP server and stores the resulting local credentials
  • status --verbose outputs resolved transport, auth, timeout, filter, and parallel-tool-call hints without making a connection
  • doctor inspects saved definitions for local configuration issues, such as missing stdio commands, invalid working directories, absent TLS files, disabled servers, literal sensitive header/env values, and incomplete OAuth authorization
  • doctor --probe adds the same live connection verification as probe once static checks succeed
  • probe connects to the chosen server or all configured servers, enumerates tools, and reports capabilities/diagnostics
  • add constructs a definition from flags and probes before saving, unless --no-probe is set or OAuth authorization must happen first
  • runtime adapters determine which transport shapes they support at execution time
  • enabled: false retains a server in the saved state but removes it from embedded runtime discovery
  • requestTimeoutMs and connectionTimeoutMs specify per-server request and connection timeouts in milliseconds
  • supportsParallelToolCalls: true designates servers that adapters can invoke in parallel
  • HTTP servers can use static headers, OAuth login, TLS verification control, and mTLS certificate/key paths
  • embedded OpenClaw exposes configured MCP tools in standard coding and messaging tool profiles; minimal still conceals them, and tools.deny: ["bundle-mcp"] turns them off explicitly
  • per-server toolFilter.include and toolFilter.exclude filter discovered MCP tools before they become OpenClaw tools
  • servers that advertise resources or prompts also provide utility tools for listing/reading resources and listing/fetching prompts; those generated utility names (resources_list, resources_read, prompts_list, prompts_get) follow the same include/exclude filter
  • dynamic MCP tool-list changes invalidate the cached catalog for that session; the next discovery/use refreshes from the server
  • repeated MCP tool request/protocol failures pause that server briefly so one broken server does not consume the whole turn
  • session-scoped bundled MCP runtimes are reaped after 10 minutes of idle time and one-shot embedded runs clean them up at run end

Runtime adapters may transform this shared registry into the format their downstream client expects. For instance, embedded OpenClaw consumes OpenClaw transport values directly, while Claude Code and Gemini receive CLI-native type values such as http, sse, or stdio.

Codex tool approvals

When a server operates under the default auto mode, Codex app-server approval-gates any tools that lack MCP safety annotations. Those calls can be approved during interactive turns through the Control UI. If you trust a particular server, you can set the mode at the time you add it:

openclaw mcp add memory \
  --command npx \
  --arg -y \
  --arg @modelcontextprotocol/server-memory \
  --approval approve

For a server that has already been saved, adjust only its approval mode:

openclaw mcp configure memory --approval approve

The flag writes codex.defaultToolsApprovalMode, which takes auto, prompt, or approve. With approve, per-call approval is skipped for every tool on that server, so reserve it for servers you trust. When a server stays in auto mode and none of its tools carry safety annotations, mcp probe and mcp doctor --probe issue warnings.

The optional codex block serves as OpenClaw projection metadata, applying exclusively to Codex app-server threads. It leaves ACP sessions, generic Codex harness configuration, and other runtime adapters untouched. To project a server only into particular OpenClaw agent ids, supply a non-empty codex.agents. Config validation rejects empty, blank, or invalid agent lists, and the runtime projection path omits them rather than treating them as global. Before handing the native mcp_servers config to Codex, OpenClaw removes the codex metadata.

Saved MCP server definitions

Commands:

  • openclaw mcp list [--json]
  • openclaw mcp show [name] [--json]
  • openclaw mcp status [--verbose] [--json]
  • openclaw mcp doctor [name] [--probe] [--json]
  • openclaw mcp probe [name] [--json]
  • openclaw mcp add <name> [flags]
  • openclaw mcp set <name> <json>
  • openclaw mcp configure <name> [flags]
  • openclaw mcp tools <name> [--include csv] [--exclude csv] [--clear]
  • openclaw mcp login <name> [--code code]
  • openclaw mcp logout <name>
  • openclaw mcp reload
  • openclaw mcp unset <name>

Notes:

  • list orders server names alphabetically.
  • When invoked without a name, show prints the complete configured MCP server object.
  • status categorizes configured transports without establishing a connection. --verbose includes resolved launch parameters, timeout values, OAuth settings, filters, and parallel-call details, along with cases where saved OAuth tokens demand reauthorization. Text and JSON output redact stdio arguments that carry credentials.
  • doctor runs static checks without connecting. Append --probe if the command should also confirm that enabled servers can connect.
  • probe connects and reports tool counts, support for resources and prompts, list-change capability, and diagnostics.
  • add accepts stdio flags like --command, --arg, --env, and --cwd, or HTTP flags such as --url, --transport, --header, --auth oauth, TLS, timeout, and tool-selection options. Set the Codex tool approval mode with --approval auto|prompt|approve.
  • set requires a single JSON object value on the command line.
  • configure modifies enablement, tool filters, timeouts, OAuth, TLS, Codex approval mode, and parallel-tool-call hints without replacing the entire server definition. Add --probe to validate the updated server before saving.
  • tools adjusts per-server tool filters. Include and exclude entries are MCP tool names and simple * globs.
  • For HTTP servers configured with auth: "oauth", login runs the OAuth flow. With a loopback redirect, OpenClaw listens for the browser callback and finishes login automatically. The printed --code command stays as the fallback for remote, headless, or unreachable callbacks.
  • logout removes stored OAuth credentials for the named server without deleting the saved server definition.
  • reload discards cached in-process MCP runtimes for the current CLI process only. Gateway or agent processes in a different process still require their own reload or restart procedure.
  • Use transport: "streamable-http" for Streamable HTTP MCP servers. openclaw mcp set also converts CLI-native type: "http" to the same canonical config shape for compatibility.
  • unset errors if the named server is absent.

Examples:

openclaw mcp list
openclaw mcp show context7 --json
openclaw mcp status --verbose
openclaw mcp doctor --probe
openclaw mcp probe context7 --json
openclaw mcp add memory --command npx --arg -y --arg @modelcontextprotocol/server-memory
openclaw mcp set context7 '{"command":"uvx","args":["context7-mcp"]}'
openclaw mcp tools context7 --include 'resolve-library-id,get-library-docs'
openclaw mcp set docs '{"url":"https://mcp.example.com","transport":"streamable-http"}'
openclaw mcp configure docs --timeout 20 --connect-timeout 5 --include 'search,read_*'
openclaw mcp configure docs --auth oauth --oauth-scope 'docs.read'
openclaw mcp login docs
openclaw mcp logout docs
openclaw mcp unset context7

Common server recipes

These examples only save server definitions. Run openclaw mcp doctor --probe afterward to verify that the server starts and exposes tools.

Filesystem

openclaw mcp add files \
  --command npx \
  --arg -y \
  --arg @modelcontextprotocol/server-filesystem \
  --arg "$HOME/Documents" \
  --include 'read_file,list_directory,search_files'
openclaw mcp doctor files --probe

Restrict filesystem servers to the smallest directory tree the agent should read or edit.

Memory

openclaw mcp add memory \
  --command npx \
  --arg -y \
  --arg @modelcontextprotocol/server-memory
openclaw mcp probe memory --json

Apply a tool filter when the server exposes write tools that should stay unavailable to normal agents.

Local script

openclaw mcp add local-tools \
  --command node \
  --arg ./dist/mcp-server.js \
  --cwd /srv/openclaw-tools \
  --env API_BASE=https://internal.example
openclaw mcp status --verbose

doctor verifies that cwd exists and that the command resolves from the configured environment.

Remote HTTP

openclaw mcp add docs \
  --url https://mcp.example.com/mcp \
  --transport streamable-http \
  --auth oauth \
  --oauth-scope docs.read \
  --timeout 20 \
  --connect-timeout 5 \
  --include 'search,read_*'
openclaw mcp doctor docs --probe

Use OAuth when the remote server supports it. If the server requires static headers, avoid committing literal bearer tokens.

Desktop/CUA

openclaw mcp set cua-driver '{"command":"cua-driver","args":["mcp"]}'
openclaw mcp tools cua-driver --include 'list_apps,get_window_state,click,type_text'
openclaw mcp doctor cua-driver --probe

Direct desktop-control servers inherit the permissions of the process they launch. Use narrow tool filters and OS-level permission prompts.

JSON output shapes

Use --json for scripts and dashboards. Field sets can grow over time, so consumers should ignore unknown keys.

status --json

{
  "path": "/home/user/.openclaw/openclaw.json",
  "servers": [
    {
      "name": "docs",
      "configured": true,
      "enabled": true,
      "ok": true,
      "transport": "streamable-http",
      "launch": "streamable-http https://mcp.example.com/mcp",
      "auth": "oauth",
      "authStatus": {
        "hasTokens": true,
        "requiresAuthorization": false,
        "hasClientInformation": true,
        "hasCodeVerifier": false,
        "hasDiscoveryState": true,
        "hasLastAuthorizationUrl": false,
        "state": "authorized"
      },
      "requestTimeoutMs": 20000,
      "connectionTimeoutMs": 5000,
      "toolFilter": {
        "include": ["search", "read_*"],
        "exclude": []
      },
      "supportsParallelToolCalls": true
    }
  ]
}

doctor --json

{
  "ok": true,
  "path": "/home/user/.openclaw/openclaw.json",
  "servers": [
    {
      "name": "docs",
      "ok": true,
      "issues": [
        {
          "level": "warning",
          "message": "OAuth credentials are not authorized; run openclaw mcp login docs"
        }
      ]
    }
  ]
}

doctor --json exits nonzero when any enabled checked server has an error-level issue. warning and info issues are reported but do not make the command fail by themselves.

probe --json

{
  "generatedAt": "2026-05-31T09:00:00.000Z",
  "servers": {
    "docs": {
      "launch": "streamable-http https://mcp.example.com/mcp",
      "tools": 2,
      "codexApprovalMode": "auto",
      "approvalHint": "tools have no safety annotations; calls will require interactive approval",
      "resources": true,
      "listChanged": {
        "tools": true,
        "resources": false,
        "prompts": false
      }
    }
  },
  "tools": ["docs__read_page", "docs__search"],
  "diagnostics": []
}

probe --json starts an interactive MCP client session and outputs the result right away; in contrast to status/doctor, there is no top-level path field in the output. The effective codexApprovalMode is included for each server; when that mode is auto and the discovered tools lack safety annotations, approvalHint shows up. The resources and prompts keys are included only if the server genuinely advertises the capability (a server without prompts leaves out the prompts key instead of reporting false). If diagnostics exist or a selected enabled server fails to connect, the command prints the full result and then exits with a nonzero status, letting automation review partial successes. For verifying reachability and capability, use probe; it is not meant for auditing static configuration.

Example config shape:

{
  "mcp": {
    "servers": {
      "context7": {
        "command": "uvx",
        "args": ["context7-mcp"]
      },
      "docs": {
        "url": "https://mcp.example.com",
        "transport": "streamable-http",
        "requestTimeoutMs": 20000,
        "connectionTimeoutMs": 5000,
        "supportsParallelToolCalls": true,
        "auth": "oauth",
        "oauth": {
          "scope": "docs.read"
        },
        "sslVerify": true,
        "clientCert": "/path/to/client.crt",
        "clientKey": "/path/to/client.key",
        "toolFilter": {
          "include": ["search_*"],
          "exclude": ["admin_*"]
        },
        "codex": {
          "defaultToolsApprovalMode": "approve"
        }
      }
    }
  }
}

Stdio transport

Spawns a local child process and exchanges data over stdin/stdout.

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

Warning

Stdio env safety filter

Before launching a stdio MCP server, OpenClaw rejects env keys related to interpreter startup, loader hijacking, and shell initialization, even when they are specified in a server's env block. This applies the same host environment security policy used for other OpenClaw-spawned processes: it blocks known interpreter startup hooks (for example NODE_OPTIONS, PYTHONSTARTUP, PERL5OPT, RUBYOPT, BASHOPTS, KSH_ENV), shared-library and function-injection prefixes (DYLD_*, LD_*, BASH_FUNC_*), and similar runtime-control variables. Startup silently discards these and logs a warning, so they cannot inject an implicit prelude, swap the interpreter, enable a debugger, or hijack the dynamic linker against the stdio process. An explicit allowlist keeps ordinary MCP credential env vars usable (GITHUB_TOKEN, GH_TOKEN, GITLAB_TOKEN, NPM_TOKEN, NODE_AUTH_TOKEN, DATABASE_URL, MONGODB_URI, REDIS_URL, AMQP_URL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET), along with ordinary proxy and server-specific env vars (HTTP_PROXY, custom *_API_KEY, etc.). Other AWS_* keys such as AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE remain blocked because they point at credential files rather than carry a credential value directly.

If your MCP server truly requires one of the blocked variables, configure it on the gateway host process rather than within the stdio server's env.

SSE / HTTP transport

Connects to a remote MCP server via 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)
connectionTimeoutMsPer-server connection timeout in ms (optional)
requestTimeoutMsPer-server MCP request timeout in milliseconds
auth: "oauth"Use MCP OAuth credentials saved by openclaw mcp login
sslVerifySet false only for explicitly trusted private HTTPS endpoints
clientCert / clientKeymTLS client certificate and key paths
supportsParallelToolCallsHint that concurrent calls are safe for this server

Example:

{
  "mcp": {
    "servers": {
      "remote-tools": {
        "url": "https://mcp.example.com",
        "auth": "oauth",
        "requestTimeoutMs": 20000,
        "headers": {
          "Authorization": "Bearer <token>"
        }
      }
    }
  }
}

Logs and status output hide sensitive values found in url (userinfo) and headers. When openclaw mcp doctor detects literal values inside headers or env entries that look sensitive, it raises a warning so operators can shift those values out of committed config.

OAuth workflow

OAuth applies to HTTP MCP servers that advertise the MCP OAuth flow. While auth: "oauth" is active, static Authorization headers are disregarded for that server. By default, OAuth credentials are shared and managed by operators. Credentials saved through openclaw mcp login function with embedded MCP, CLI runners, and the local Codex app-server.

Native MCP OAuth sessions reside in the owner-only shared SQLite database located at <state-dir>/state/openclaw.sqlite (mcp_oauth_stores). The row may hold access and refresh tokens, dynamic client registration secrets, discovery metadata, and the temporary PKCE verifier. Refresh, login, and logout all rely on the same SQLite lease, preventing parallel OpenClaw processes from using up a single refresh token or reviving a logged-out session.

Upgrades from the retired <state-dir>/mcp-oauth/*.json store are handled exclusively by openclaw doctor --fix. Runtime code never reads, writes, or falls back to those files.

Until shared credentials are available, OpenClaw excludes only that MCP server from the agent runtime rather than failing the agent turn. The operator, or an agent with shell access, can then execute openclaw mcp login <name> and use the server on a subsequent turn.

If a server rejects a token with insufficient_scope, OpenClaw keeps the requested scope and asks for openclaw mcp login <name> instead of repeating a refresh that cannot grant new scope. That login initiates a new authorization request while preserving the previous token until replacement credentials are stored.

When a remote MCP service is already supported by a separate OpenClaw refresh-capable auth profile, you may optionally set oauth.authProfileId. OpenClaw refreshes either credential source before runtime projection and passes only the current access token to the downstream MCP client.

Set oauth.identity: "per-requester" when every authenticated sender should connect a distinct account. Per-requester OAuth requires an HTTP server URL and cannot use oauth.authProfileId. Configure gateway.publicOrigin as the externally reachable HTTPS origin of the Gateway; HTTP is accepted only for literal loopback hosts (localhost, 127.0.0.1, or [::1]) during local development. The provider redirects to <gateway.publicOrigin>/oauth/mcp/callback after authorization.

{
  gateway: {
    publicOrigin: "https://gateway.example.com",
  },
  mcp: {
    servers: {
      docs: {
        url: "https://mcp.example.com/mcp",
        transport: "streamable-http",
        auth: "oauth",
        oauth: {
          identity: "per-requester",
          scope: "docs.read",
        },
      },
    },
  },
}

The per-requester flow is sender-driven:

  1. The sender calls a tool from the server before connecting an account.
  2. OpenClaw returns a sign-in link for that sender instead of exposing another sender's credentials.
  3. The provider redirects through the Gateway callback. After the callback succeeds, the sender retries the tool call with their connected account.

If gateway.publicOrigin is missing, the sign-in result names that setting and openclaw doctor reports the same operator fix. openclaw mcp login and openclaw mcp logout remain operator-only commands for shared credentials; they do not manage per-requester accounts.

Sign-in links are single-use bearer links: any chat participant who opens one connects their own account to the sender the link was issued for. Use per-requester OAuth in channels where every trusted sender is mutually trusted; a requester-private sign-in handoff is tracked as follow-up work.

The shared operator flow uses the following commands:

Save the server

Add or update the server with auth: "oauth" and any optional OAuth metadata.

openclaw mcp set docs '{"url":"https://mcp.example.com/mcp","transport":"streamable-http","auth":"oauth","oauth":{"scope":"docs.read"}}'

For an auth-profile-backed bearer, save the profile binding:

openclaw mcp set docs '{"url":"https://mcp.example.com/mcp","transport":"streamable-http","auth":"oauth","oauth":{"authProfileId":"docs:mcp"}}'

Start login

Run login to create the authorization request.

openclaw mcp login docs

OpenClaw starts the registered loopback callback, prints the authorization URL, and stores temporary OAuth verifier state in shared SQLite. Approve the request in the browser and return to the terminal; token exchange completes automatically after the callback arrives.

Use the manual fallback when needed

If the browser runs on another machine or cannot reach the printed loopback address, copy the returned code and pass it back to OpenClaw.

openclaw mcp login docs --code abc123

Check authorization

Use status or doctor to confirm that tokens are present and do not require additional authorization. If status reports authorization-required or doctor asks for additional authorization, run openclaw mcp login <name> again.

openclaw mcp status --verbose
openclaw mcp doctor docs --probe

Clear credentials

Logout removes stored OAuth credentials but keeps the saved server definition.

openclaw mcp logout docs

If the provider rotates tokens or the authorization state gets stuck, run openclaw mcp logout <name>, then repeat login. logout can clear credentials for a saved HTTP server even after auth: "oauth" has been removed from config, as long as the server name and URL still identify the credential store entry.

Streamable HTTP transport

streamable-http is an additional transport option alongside sse and stdio. It uses HTTP streaming for bidirectional communication with remote MCP servers.

FieldDescription
urlThe remote server's HTTP or HTTPS address, which is mandatory
transportAssign "streamable-http" to pick this transport; if left out, OpenClaw falls back to sse
headersA non-required key-value collection of HTTP headers, such as authentication tokens
connectionTimeoutMsConnection timeout for the server, expressed in milliseconds and optional
requestTimeoutMsPer-server timeout for MCP requests, measured in milliseconds
auth: "oauth"Rely on MCP OAuth credentials that openclaw mcp login has stored
sslVerifyOnly set to false for private HTTPS endpoints you explicitly trust
clientCert / clientKeyPaths to the mTLS client certificate and its key
supportsParallelToolCallsIndicates this server tolerates concurrent calls safely

Within OpenClaw configuration, transport: "streamable-http" serves as the standard spelling. When saved via openclaw mcp set, CLI-native MCP type: "http" values are accepted and openclaw doctor --fix fixes them in existing config; however, embedded OpenClaw consumes transport directly.

Example:

{
  "mcp": {
    "servers": {
      "streaming-tools": {
        "url": "https://mcp.example.com/stream",
        "transport": "streamable-http",
        "connectionTimeoutMs": 10000,
        "requestTimeoutMs": 30000,
        "headers": {
          "Authorization": "Bearer <token>"
        }
      }
    }
  }
}

Note

Registry commands leave the channel bridge inactive. Only probe and doctor --probe establish a live MCP client session to verify the target server is reachable.

Control UI

A dedicated MCP settings page lives in the browser Control UI at /settings/mcp; the older /mcp path still works as an alias. This page presents counts of configured servers, summaries of enabled/OAuth/filter states, transport rows for each server, controls to enable or disable, common CLI commands, and an editor scoped to the mcp configuration section.

For a condensed setup guide that covers Settings, the composer route (+ConnectorsAdd MCP server…) with its This session / Everywhere scopes, CLI, and direct config, consult Connect MCP servers.

Operators can rely on this page for edits and quick inventory. When live server verification is needed, turn to openclaw mcp doctor --probe or openclaw mcp probe.

Operator workflow:

  1. Open the Control UI and select MCP.
  2. Inspect the summary cards showing total, enabled, OAuth, and filtered servers.
  3. Each server row offers transport, auth, filter, timeout, and command details.
  4. Disable a definition to keep it while excluding it from runtime discovery.
  5. For structural modifications like adding servers, headers, TLS, OAuth metadata, or tool filters, edit the scoped mcp config section.
  6. Click Save to persist config alone, or Save & Publish to push it through the Gateway config path.
  7. Execute openclaw mcp doctor --probe to get live confirmation that the edited server launches and enumerates tools.

Notes:

  • command snippets quote server names so even unusual names stay copyable in a shell
  • URL-like values shown are redacted before rendering if they contain embedded credentials
  • the page never starts MCP transports on its own
  • depending on which process owns the MCP clients, active runtimes may require openclaw mcp reload, Gateway config publish, or a process restart

MCP Apps

OpenClaw can display tools that implement the stable MCP Apps extension. Apps are opt-in since their HTML originates from the configured MCP server. A view holding current App-interaction authority can request app-visible tools and resources from that same server.

Enable the host bridge:

openclaw config set mcp.apps.enabled true --strict-json

Restart the Gateway after this setting changes. When active, OpenClaw launches a sandbox-only HTTP(S) listener on the Gateway port plus one (for the default Gateway, 18790). The Control UI fetches Apps from that distinct origin; the listener never serves Control UI, authenticated Gateway routes, or user data.

Direct Gateway connections must reach both ports. If a reverse proxy or TLS terminator exposes the Control UI, assign Apps a dedicated public origin and proxy only that origin to the sandbox listener:

{
  mcp: {
    apps: {
      enabled: true,
      sandboxOrigin: "https://mcp-apps.example.com",
      sandboxPort: 18790,
    },
  },
}

The sandbox origin must be different from the Control UI origin. Keep other authenticated or sensitive content off it.

As an example, the official basic React demo can be set up like this:

{
  mcp: {
    apps: { enabled: true },
    servers: {
      "basic-react": {
        command: "npx",
        args: ["-y", "@modelcontextprotocol/server-basic-react", "--stdio"],
      },
    },
  },
}

Behavior and security boundaries:

  • OpenClaw announces the io.modelcontextprotocol/ui extension only when Apps are turned on.
  • Only ui:// resources carrying the exact text/html;profile=mcp-app MIME type are rendered.
  • UI resources stay under 2 MiB, sit behind a double-iframe proxy on a dedicated outer origin, load into an opaque inner App origin, and follow CSP derived from the resource metadata.
  • App-only tools (_meta.ui.visibility: ["app"]) never appear in model tool lists. Apps can invoke only app-visible tools on their owning server that also pass the effective OpenClaw tool policy for the run that created the view.
  • Listing and reading same-server resources also demand that same current App-interaction authority. OpenClaw rechecks after upstream resource work, so a grant revoked mid-flight cannot return resource data to the App.
  • Origin-bound App permissions like camera, microphone, and geolocation are withheld while inner App documents use opaque origins for cross-App isolation.
  • App HTML, full tool arguments, and raw results live in a bounded ten-minute in-memory view lease and are never written to disk or copied into transcript preview metadata. The transcript keeps only a bounded server/tool/resource descriptor tied to the original tool-call ID. After a Gateway restart, the Control UI can check that descriptor against the authenticated session transcript and refetch the ui:// document for display; reconstructed views cannot call tools or use the resource bridge until a fresh run establishes current App-interaction authority.
  • In channel conversations, the latest successful App view in a turn adds one Open App-style action to the final assistant reply. Telegram DMs use a native Mini App button; Slack and Discord render the same portable action as a link. Other channels keep the original reply text and append an understandable HTTPS link.
  • Channel launch links appear only when Gateway Tailscale exposure has prepared a published HTTPS origin. gateway.tailscale.mode: "serve" is reachable only from the tailnet; password-authenticated "funnel" is reachable from the public internet. Externally managed Funnel routes targeting the ordinary Gateway listener must migrate to managed "funnel" mode before OpenClaw can publish an internet-reachable origin. See Tailscale.
  • Launch tickets are opaque, minted only while materializing the final channel reply, and expire after at most two minutes or when the underlying view lease expires, whichever comes first. The URL does not contain Gateway bearer credentials, session keys, view metadata, App HTML, tool input, or tool results.
  • Standalone App windows allow 30 seconds to load the view. Each server's requestTimeoutMs applies to individual MCP requests, not to a complete App operation that may refresh the catalog before calling a tool. App request cancellation or closing the window aborts its browser request and propagates to the managed MCP runtime; other callers can still finish a shared catalog refresh. Cancellation cannot undo side effects already performed by the server.
  • When an App requests teardown, existing calls and authorized cleanup calls can finish until the App acknowledges shutdown or the one-second grace period expires. Closing or navigating away from the window cancels immediately.
  • Returning to a standalone App restored from the browser's back/forward cache reloads and revalidates the view instead of reviving its torn-down connection. This resets transient App state and does not automatically retry interrupted operations. If the launch ticket has expired, open a fresh App link.
  • If no published origin or ticket capacity is available, the view or ticket has expired, or the transport cannot render native controls, the original assistant text remains available. The Control UI keeps its existing inline App canvas and does not receive a duplicate launch action.
  • openclaw security audit warns while the bridge is enabled. Disable it with openclaw config set mcp.apps.enabled false --strict-json when it is not needed.

Current limits

The bridge, as it currently exists, is described on this page.

Present constraints:

  • Finding conversations relies on route metadata already present in the Gateway session
  • Only the Claude-specific adapter supports push; there is no general-purpose push protocol
  • Tools for editing messages or adding reactions are not yet available
  • The HTTP, SSE, and streamable-http transports each target one remote server, with no support for multiplexing across multiple upstreams
  • permissions_list_open captures only approvals that occur while the bridge remains connected
6,542 words · updated Aug 28, 2026