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, andunset
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.serversentries in OpenClaw config are touched bylist,show,set, andunset. Servers from the mcporter registry inconfig/mcporter.jsonare excluded; turn tomcporter listfor 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
| Goal | Use | Why |
|---|---|---|
| Allow an external MCP client to read/send OpenClaw channel conversations | openclaw mcp serve | OpenClaw serves as the MCP server, exposing Gateway-backed conversations through stdio. |
| Keep third-party MCP servers available for OpenClaw-managed agent runs | openclaw mcp add, set, configure, tools, login | OpenClaw acts as the client-side MCP registry and later projects those servers into eligible runtimes. |
| Inspect a saved server without triggering an agent turn | openclaw mcp status, doctor, probe | Config is examined by status and doctor; probe opens a live MCP connection and lists capabilities. |
| Modify MCP config through a browser | Control 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 server | mcp.servers.<name>.codex | The codex block affects only Codex app-server thread projection and is removed before native config handoff. |
| Run ACP-hosted harness sessions | openclaw acp and ACP Agents | ACP 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_waitrequest frees its server-side wait and timeout right away - when the bridge or MCP transport closes with an error,
openclaw mcp servefails rather than reporting a clean shutdown - one-shot agent entry points like
openclaw agentandopenclaw infer model rundispose 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,
autoandonbehave 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
accountIdwhen presentthreadIdwhen 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-onceallow-alwaysdeny
Event model
An in-memory event queue is kept by the bridge while it remains connected.
Event types available now:
messageexec_approval_requestedexec_approval_resolvedplugin_approval_requestedplugin_approval_resolvedclaude_permission_request
Warning
- the queue operates only during a live session; it becomes active the moment the MCP bridge launches
- neither
events_pollnorevents_waitwill, on their own, replay earlier Gateway history- the queue has a fixed size; when
gapis set, pull durable history throughmessages_read, then pick up again withafter_cursorassigned a value one belowgap.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/channelnotifications/claude/channel/permission
How the bridge behaves right now:
- incoming
usertranscript messages get forwarded asnotifications/claude/channel - Claude permission requests arriving over MCP are kept in memory
- if the command owner in the associated conversation later issues
yes <id>orno <id>(where<id>is the 5-character request id, leaving outl), the bridge turns that intonotifications/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 togateway.remote.urlwhen 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 toauto. -
-v, --verbose(boolean), Verbose logging to stderr.
Tip
Whenever possible, go with
--token-fileor--password-fileinstead 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_sendcan 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-modeequalsonorauto- 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,doctorwithout--probe,set,configure,tools,logout,reload, andunsetdo not establish a connection to the target MCP serverloginruns the MCP OAuth network flow for the specified HTTP server and stores the resulting local credentialsstatus --verboseoutputs resolved transport, auth, timeout, filter, and parallel-tool-call hints without making a connectiondoctorinspects 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 authorizationdoctor --probeadds the same live connection verification asprobeonce static checks succeedprobeconnects to the chosen server or all configured servers, enumerates tools, and reports capabilities/diagnosticsaddconstructs a definition from flags and probes before saving, unless--no-probeis set or OAuth authorization must happen first- runtime adapters determine which transport shapes they support at execution time
enabled: falseretains a server in the saved state but removes it from embedded runtime discoveryrequestTimeoutMsandconnectionTimeoutMsspecify per-server request and connection timeouts in millisecondssupportsParallelToolCalls: truedesignates 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
codingandmessagingtool profiles;minimalstill conceals them, andtools.deny: ["bundle-mcp"]turns them off explicitly - per-server
toolFilter.includeandtoolFilter.excludefilter 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 reloadopenclaw mcp unset <name>
Notes:
listorders server names alphabetically.- When invoked without a name,
showprints the complete configured MCP server object. statuscategorizes configured transports without establishing a connection.--verboseincludes 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.doctorruns static checks without connecting. Append--probeif the command should also confirm that enabled servers can connect.probeconnects and reports tool counts, support for resources and prompts, list-change capability, and diagnostics.addaccepts 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.setrequires a single JSON object value on the command line.configuremodifies enablement, tool filters, timeouts, OAuth, TLS, Codex approval mode, and parallel-tool-call hints without replacing the entire server definition. Add--probeto validate the updated server before saving.toolsadjusts per-server tool filters. Include and exclude entries are MCP tool names and simple*globs.- For HTTP servers configured with
auth: "oauth",loginruns the OAuth flow. With a loopback redirect, OpenClaw listens for the browser callback and finishes login automatically. The printed--codecommand stays as the fallback for remote, headless, or unreachable callbacks. logoutremoves stored OAuth credentials for the named server without deleting the saved server definition.reloaddiscards 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 setalso converts CLI-nativetype: "http"to the same canonical config shape for compatibility. unseterrors 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.
| Field | Description |
|---|---|
command | Executable to spawn (required) |
args | Array of command-line arguments |
env | Extra environment variables |
cwd / workingDirectory | Working 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
envblock. This applies the same host environment security policy used for other OpenClaw-spawned processes: it blocks known interpreter startup hooks (for exampleNODE_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.). OtherAWS_*keys such asAWS_CONFIG_FILEandAWS_SHARED_CREDENTIALS_FILEremain 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.
| Field | Description |
|---|---|
url | HTTP or HTTPS URL of the remote server (required) |
headers | Optional key-value map of HTTP headers (for example auth tokens) |
connectionTimeoutMs | Per-server connection timeout in ms (optional) |
requestTimeoutMs | Per-server MCP request timeout in milliseconds |
auth: "oauth" | Use MCP OAuth credentials saved by openclaw mcp login |
sslVerify | Set false only for explicitly trusted private HTTPS endpoints |
clientCert / clientKey | mTLS client certificate and key paths |
supportsParallelToolCalls | Hint 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:
- The sender calls a tool from the server before connecting an account.
- OpenClaw returns a sign-in link for that sender instead of exposing another sender's credentials.
- 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.
| Field | Description |
|---|---|
url | The remote server's HTTP or HTTPS address, which is mandatory |
transport | Assign "streamable-http" to pick this transport; if left out, OpenClaw falls back to sse |
headers | A non-required key-value collection of HTTP headers, such as authentication tokens |
connectionTimeoutMs | Connection timeout for the server, expressed in milliseconds and optional |
requestTimeoutMs | Per-server timeout for MCP requests, measured in milliseconds |
auth: "oauth" | Rely on MCP OAuth credentials that openclaw mcp login has stored |
sslVerify | Only set to false for private HTTPS endpoints you explicitly trust |
clientCert / clientKey | Paths to the mTLS client certificate and its key |
supportsParallelToolCalls | Indicates 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
probeanddoctor --probeestablish 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 (+ → Connectors → Add 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:
- Open the Control UI and select MCP.
- Inspect the summary cards showing total, enabled, OAuth, and filtered servers.
- Each server row offers transport, auth, filter, timeout, and command details.
- Disable a definition to keep it while excluding it from runtime discovery.
- For structural modifications like adding servers, headers, TLS, OAuth metadata, or tool filters, edit the scoped
mcpconfig section. - Click Save to persist config alone, or Save & Publish to push it through the Gateway config path.
- Execute
openclaw mcp doctor --probeto 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/uiextension only when Apps are turned on. - Only
ui://resources carrying the exacttext/html;profile=mcp-appMIME 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
requestTimeoutMsapplies 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 auditwarns while the bridge is enabled. Disable it withopenclaw config set mcp.apps.enabled false --strict-jsonwhen 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_opencaptures only approvals that occur while the bridge remains connected