Skip to main content

MCP Servers

The Model Context Protocol (MCP) is how an agent borrows tools from another program. An MCP server exposes tools, resources and prompts; OpenClaw connects to it and makes those tools available to your agents. Server definitions live under mcp.servers in openclaw.json, and the tools they expose go through the same tool profile and tool policy as every other tool.

The official references are Connect MCP servers and the openclaw mcp CLI.

tip

Before building a custom plugin or skill, check whether the vendor already ships an MCP server.

Security advisory

Versions v2026.5.20 through v2026.6.5 had a High-severity flaw (GHSA-52xj-c9p8-78cv, CVSS 8.3) where the MCP loopback could expose owner-only tools to non-owner runs. Patched in v2026.6.6. See the June 2026 advisory batch.


What MCP Provides​

CapabilityWhat it doesExample
ToolsFunctions the agent can callread_file, run_query, send_email
ResourcesData the agent can readDatabase schemas, documentation
PromptsReusable prompt templatesA code review checklist

Most servers expose only tools. When a server also has resources or prompts, OpenClaw adds utility tools for them (resources_list, resources_read, prompts_list, prompts_get).

MCP uses JSON-RPC 2.0 over one of three transports: stdio (a local child process), Streamable HTTP, or the older SSE.


Adding a Server​

Three ways, all writing the same mcp.servers entry:

  1. Control UI: Settings → MCP → Add server, or in a chat + → Connectors → Add MCP server…
  2. CLI: openclaw mcp add with flags (it probes the server before saving)
  3. Config: edit openclaw.json directly

Whichever you use, check that the server actually answers:

openclaw mcp doctor <name> --probe

From the CLI​

# Local stdio server
openclaw mcp add filesystem \
--command npx \
--arg -y --arg @modelcontextprotocol/server-filesystem --arg /home/user/projects

# Remote Streamable HTTP server, exposing only some tools
openclaw mcp add docs \
--url https://mcp.example.com/mcp \
--transport streamable-http \
--include 'search,read_*'

# Remote server that uses MCP OAuth
openclaw mcp add tracker --url https://mcp.example.com/mcp --transport streamable-http --auth oauth
openclaw mcp login tracker

Other flags: --env KEY=value, --cwd, --header KEY=value, --timeout, --connect-timeout, --exclude, --disabled, --no-probe.

Local servers (stdio)​

OpenClaw spawns the process and talks to it over stdin/stdout.

~/.openclaw/openclaw.json
{
mcp: {
servers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"],
},
git: {
command: "uvx",
args: ["mcp-server-git", "--repository", "/home/user/projects/myapp"],
},
},
},
}
FieldDescription
commandExecutable to spawn (required for stdio)
argsCommand-line arguments
envExtra environment variables. ${VAR} substitution works here as in the rest of the config.
cwdWorking directory
enabledfalse keeps the definition but does not connect

OpenClaw silently drops interpreter and loader hooks from a stdio server's env (NODE_OPTIONS, PYTHONSTARTUP, LD_*, DYLD_*, BASH_FUNC_* and similar) and logs a warning. Ordinary credentials such as GITHUB_TOKEN, DATABASE_URL or *_API_KEY pass through.

Remote servers (HTTP)​

~/.openclaw/openclaw.json
{
mcp: {
servers: {
"cloud-service": {
url: "https://api.example.com/mcp",
transport: "streamable-http",
headers: { "X-API-Key": "${SERVICE_KEY}" },
connectionTimeoutMs: 5000,
requestTimeoutMs: 20000,
},
"legacy-tools": {
url: "https://mcp.internal.example.com/sse",
transport: "sse",
headers: { Authorization: "Bearer ${MCP_API_KEY}" },
},
},
},
}
FieldDescription
urlServer endpoint (required for HTTP)
transportstreamable-http or sse. When omitted, OpenClaw uses sse, so always set it for Streamable HTTP servers.
headersHTTP headers, for example auth tokens. Redacted in logs and status output.
auth"oauth" to use credentials saved by openclaw mcp login; static Authorization headers are then ignored
connectionTimeoutMs, requestTimeoutMsPer-server timeouts
sslVerify, clientCert, clientKeyTLS verification and mutual TLS
supportsParallelToolCallsHint that concurrent calls are safe

The name __proto__ is reserved. openclaw mcp doctor warns when a header or env value looks like a literal secret.

Transport types​

TransportWhen to use it
stdioLocal servers and CLI tools
Streamable HTTPRemote servers; preferred for anything new
SSEOlder remote servers only

CLI Commands​

CommandWhat it does
openclaw mcp listList configured servers
openclaw mcp show [name]Print one server's definition, or all of them
openclaw mcp status [--verbose]Transport, auth, timeouts and filters, without connecting
openclaw mcp doctor [name] [--probe]Static checks; --probe also connects
openclaw mcp probe [name]Connect and list tools, resources and prompts
openclaw mcp add <name> [flags]Add a server from flags, probing first
openclaw mcp set <name> <json>Write one server from a JSON object
openclaw mcp configure <name>Change operator controls such as the Codex approval mode
openclaw mcp tools <name> --include/--exclude/--clearSet the server's tool filter
openclaw mcp login <name> / logout <name>OAuth sign-in and sign-out
openclaw mcp reloadDrop cached MCP runtimes in this process
openclaw mcp unset <name>Remove a server
openclaw mcp serveRun OpenClaw as a stdio MCP server (see below)
openclaw mcp probe filesystem
openclaw mcp status --verbose
openclaw mcp doctor --probe

With Gateway hot reload, changed servers are picked up on the next turn. openclaw mcp reload only affects the CLI process it runs in; a Gateway elsewhere needs its own reload or restart. A server that fails to start is retried with exponential backoff (30 seconds, doubling up to 10 minutes).


Filtering Tools​

The real mechanism is toolFilter on each server, with include and exclude lists of tool names or * globs:

~/.openclaw/openclaw.json
{
mcp: {
servers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/safe-dir"],
toolFilter: {
include: ["read_*", "list_*", "search_files"],
exclude: ["write_file", "move_file"],
},
},
},
},
}

Or from the CLI:

openclaw mcp tools filesystem --include 'read_*,list_*,search_files' --exclude 'write_file,move_file'
openclaw mcp tools filesystem --clear
allowed_tools and blocked_tools do nothing

Server entries accept unknown keys without an error. Keys such as allowed_tools, blocked_tools or allowedTools pass openclaw config validate and are silently ignored, so every tool stays exposed. Use toolFilter, then confirm with openclaw mcp status --verbose or openclaw mcp probe <name>.

Other layers:

  • Tool policy. MCP tools are named <server>__<tool>. tools.deny: ["filesystem__*"] removes a whole server before it connects; tools.deny: ["bundle-mcp"] disables all MCP tools. The minimal tool profile hides MCP tools; coding and messaging include them.
  • Per session. In a Control UI chat, + → Connectors → Tool access lets you deny individual tools for that session.

Vetted Servers​

An MCP server is code with your credentials. Prefer the MCP reference servers or the vendor's own official server, and check the npm or PyPI publisher before you run anything (npm view <pkg> maintainers repository.url).

MCP reference servers​

Maintained by the MCP project. They are reference implementations, written to demonstrate the protocol, not hardened products:

ServerPackageRun with
Filesystem@modelcontextprotocol/server-filesystemnpx
Memory@modelcontextprotocol/server-memorynpx
Sequential Thinking@modelcontextprotocol/server-sequential-thinkingnpx
Everything (test server)@modelcontextprotocol/server-everythingnpx
Fetchmcp-server-fetchuvx (Python)
Gitmcp-server-gituvx (Python)
Timemcp-server-timeuvx (Python)

The former GitHub, PostgreSQL, SQLite, Google Drive, Brave Search and Puppeteer reference servers are archived. Their npm packages (@modelcontextprotocol/server-github, server-postgres, server-brave-search, server-gdrive, server-puppeteer) are deprecated and no longer maintained. There is no @modelcontextprotocol/server-sentry or server-google-drive, and nothing under @anthropic/mcp-*.

Vendor servers​

ServiceOfficial server
GitHubgithub/github-mcp-server: remote at https://api.githubcopilot.com/mcp/, or the ghcr.io/github/github-mcp-server Docker image
Brave Search@brave/brave-search-mcp-server (brave/brave-search-mcp-server)
Browser automation@playwright/mcp (microsoft/playwright-mcp)
Sentry@sentry/mcp-server (getsentry/sentry-mcp)
Notion@notionhq/notion-mcp-server (makenotion/notion-mcp-server)
Home AssistantThe built-in Model Context Protocol Server integration

For web search, OpenClaw also has a built-in web_search tool with a Brave provider, so you may not need an MCP server at all.

Finding more​


Recipes​

GitHub (remote, official)​

~/.openclaw/openclaw.json
{
mcp: {
servers: {
github: {
url: "https://api.githubcopilot.com/mcp/",
transport: "streamable-http",
headers: { Authorization: "Bearer ${GITHUB_MCP_PAT}" },
toolFilter: { exclude: ["delete_*", "merge_pull_request"] },
},
},
},
}

Use a fine-grained personal access token limited to the repositories the agent needs.

Research: search plus fetch​

~/.openclaw/openclaw.json
{
mcp: {
servers: {
"brave-search": {
command: "npx",
args: ["-y", "@brave/brave-search-mcp-server"],
env: { BRAVE_API_KEY: "${BRAVE_API_KEY}" },
},
fetch: {
command: "uvx",
args: ["mcp-server-fetch"],
},
},
},
}

Databases​

Give the agent a read-only database user, and use a server from the database vendor or one whose source you have read. Several popular names on PyPI and npm, such as mcp-server-postgres on PyPI, are unrelated packages from unknown authors. Do not hand them production credentials.

Pinning​

npx -y and uvx fetch the latest published version every time. For anything with credentials, pin a version (@brave/brave-search-mcp-server@2.1.4, mcp-server-git==2026.10.10) or install it once and point command at the installed binary.


Building Custom Servers​

When no server fits, write your own with an official SDK.

TypeScript​

npm init -y
npm install @modelcontextprotocol/sdk zod
src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "my-tools", version: "1.0.0" });

server.registerTool(
"get_weather",
{
description: "Get current weather for a city",
inputSchema: { city: z.string().describe("City name") },
},
async ({ city }) => {
const res = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=j1`);
const data = await res.json();
return {
content: [{ type: "text", text: JSON.stringify(data.current_condition[0], null, 2) }],
};
},
);

await server.connect(new StdioServerTransport());

Resources and prompts use server.registerResource(...) and server.registerPrompt(...) in the same way.

Register it with OpenClaw:

npm install -D typescript && npx -p typescript tsc --init && npx -p typescript tsc
openclaw mcp add my-tools --command node --arg ./dist/server.js --cwd /path/to/project

Python (FastMCP)​

pip install mcp
server.py
from mcp.server.fastmcp import FastMCP
import httpx

mcp = FastMCP("my-tools")

@mcp.tool()
async def get_weather(city: str) -> str:
"""Get current weather for a city."""
async with httpx.AsyncClient() as client:
resp = await client.get(f"https://wttr.in/{city}?format=j1")
return str(resp.json()["current_condition"][0])

if __name__ == "__main__":
mcp.run()
openclaw mcp add my-py-tools --command python --arg server.py --cwd /path/to/project

Testing your server​

openclaw mcp doctor my-tools --probe
npx @modelcontextprotocol/inspector

The MCP Inspector is a browser UI that connects to a stdio or HTTP server and lets you call its tools by hand.


OpenClaw as an MCP Server​

openclaw mcp serve runs the other way round: it is a stdio MCP server that an MCP client (Claude Code, Codex, Cursor and others) spawns. It connects to your Gateway over WebSocket and exposes channel conversations: listing conversations, reading messages, sending messages, waiting for events and handling approvals. It does not expose your agent's skills or memory, and it does not listen on an HTTP port.

Example client entry (for an MCP client's own config file, not openclaw.json):

MCP client config
{
"mcpServers": {
"openclaw": { "command": "openclaw", "args": ["mcp", "serve"] }
}
}

See Run OpenClaw as an MCP server.


Security​

MCP servers can read files, query databases, call APIs and run code. Treat them like shell scripts you are about to run.

Trust model​

SourceWhat to check
MCP reference serversMaintained, but examples rather than hardened products
Vendor's official serverPublisher on npm/PyPI matches the vendor; linked from the vendor's docs
Community serverRead the source, check activity and issues, pin the version

Credentials​

  • Use ${ENV_VAR} substitution or SecretRefs for secrets; never commit tokens in config
  • Scope API keys narrowly (read-only where possible)
  • Prefer auth: "oauth" with openclaw mcp login where the server supports it
  • Read what environment variables a server asks for

Containment​

  • stdio servers run as child processes with the Gateway user's permissions
  • Filesystem servers: pass only the directories they need
  • Database servers: use read-only users
  • Internal HTTP servers: keep them behind a firewall or VPN

Common risks​

RiskMitigation
Server reads sensitive filesRestrict filesystem paths in server args
Server exfiltrates dataPrefer local servers; watch outbound traffic
Malicious or typosquatted packageCheck the publisher, pin versions, read the source
Credential leak via config${VAR} substitution or SecretRefs; openclaw mcp doctor warns on literals
Agent misuses a tooltoolFilter.exclude, tools.deny, approvals
warning

An MCP server that can run commands, send email or messages, drive a browser or move money gives that power to every agent with access to it. Combine tool filters with approvals and sandboxing; see Security hardening.


Troubleshooting​

Server won't connect:

openclaw mcp doctor <name> --probe
openclaw mcp status --verbose

For stdio servers, check that command resolves in the Gateway's environment and that cwd exists. Debug logs prefix server stderr with bundle-mcp:<name>:.

Connects but no tools: run openclaw mcp probe <name> and check toolFilter.include and exclude. A Streamable HTTP server without transport: "streamable-http" is treated as SSE and may fail.

Server crashes on startup: run the command directly to see its error, for example npx -y @modelcontextprotocol/server-filesystem /tmp.

Authentication failures: check that the env var is set in the Gateway's environment, not just your shell. For OAuth servers, run openclaw mcp login <name> again.

Changes not visible: the Gateway reloads changed servers on the next turn. A CLI openclaw mcp reload does not reset a separate Gateway process.

Too many tools confusing the agent: narrow each server with toolFilter.include, or remove servers the agent does not need.


See Also​