MCP Servers in OpenClaw: Plugging External Tools Into Your Agent
How to extend an OpenClaw agent with MCP servers — Telegram, Postgres, Slack, and custom tools. Practical setup with code, plus the gotchas nobody warns you about.
MCP Servers in OpenClaw: Plugging External Tools Into Your Agent
An OpenClaw agent out of the box can read files, run shell commands, and search the web. That covers maybe 30% of what you'll actually want it to do. The other 70% is things like "send me a Telegram message when the deploy finishes" or "query the production Postgres for yesterday's signups" or "post a draft to Slack for review."
That gap is what MCP — Model Context Protocol — exists to fill. It's the standard Anthropic shipped so agents can talk to external tools without you writing custom integrations every time.
I have eight MCP servers wired into my agent right now. Some I installed in five minutes from a registry. Two I wrote myself in an afternoon. Here's what I learned doing it.
What an MCP Server Actually Is
Strip away the jargon and an MCP server is just a process that exposes a list of tools to the agent over a JSON-RPC protocol. The server says "I can do these five things, here are the parameters each one takes." The agent decides when to call them.
The transport is usually stdio (server runs as a subprocess) or HTTP. For local stuff, stdio is fine and it's what most servers ship with.
A minimal config in ~/.claude/mcp.json looks like this:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/myapp"]
}
}
}
That's it. Restart your agent and mcp__postgres__query shows up as a callable tool. The agent can now ask the database questions in natural language and you didn't write a line of glue code.
Servers That Actually Earn Their Keep
After running a bunch in production, these are the ones I'd install on day one:
Postgres / SQLite — Lets the agent query and inspect databases without you writing a CLI wrapper. The official server is read-only by default, which is the right choice. If you want writes, run a second server with a write-enabled connection string.
Filesystem — Sandbox the agent to a specific directory tree. Yes, the agent can already read and write files via shell, but the MCP version is faster and the sandbox boundary is enforced at the server level, not just by hoping the agent obeys instructions.
Telegram (or Slack) — This is the one that turns a script into a coworker. Once your agent can ping you on Telegram when something interesting happens, you stop watching logs. It just tells you. The official Telegram MCP plugin handles the bot token, message routing, and even file attachments.
GitHub — Read PRs, post comments, create issues. Worth installing if you want the agent to participate in code review workflows.
Browser automation (Playwright) — Lets the agent open URLs, click around, fill forms. Slower than HTTP requests but necessary for sites that require JavaScript or have anti-bot protections.
Episodic memory — Search past conversations semantically. I use this constantly. The agent forgets everything between sessions otherwise, and rebuilding context every time is expensive.
The pattern across all of these: the MCP server handles the hard part (auth, parsing, retries) and exposes a clean tool interface. You don't have to reinvent any of it.
Writing Your Own Server
Eventually you'll want a tool that doesn't exist yet. The Anthropic SDK makes this short.
Here's a minimal server in TypeScript that exposes one tool:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({ name: "my-tools", version: "1.0.0" });
server.setRequestHandler("tools/list", async () => ({
tools: [{
name: "ping_uptime_check",
description: "Check if a URL is responding with HTTP 200",
inputSchema: {
type: "object",
properties: { url: { type: "string" } },
required: ["url"]
}
}]
}));
server.setRequestHandler("tools/call", async (req) => {
if (req.params.name === "ping_uptime_check") {
const r = await fetch(req.params.arguments.url);
return { content: [{ type: "text", text: `Status ${r.status}` }] };
}
});
await server.connect(new StdioServerTransport());
Add it to mcp.json:
{
"mcpServers": {
"my-tools": {
"command": "node",
"args": ["/abs/path/to/server.js"]
}
}
}
Done. Took maybe twenty minutes including reading the docs.
The Gotchas
A few things bit me that the docs don't lead with.
Tool name collisions. If two MCP servers expose a tool with the same name, the agent gets confused or one silently wins. Namespace your tool names if you write your own (mycompany_uptime_ping, not ping).
Stdio means buffering matters. If your custom server prints debug logs to stdout, you'll corrupt the JSON-RPC protocol and nothing will work. Send all logs to stderr. Always.
Restart on config change. The agent reads mcp.json at startup. Edit the file mid-session and nothing happens until you restart. This wasted twenty minutes of mine the first time.
Auth tokens in plain text. MCP configs sit in your home directory in plaintext JSON. If you're putting production credentials in there, encrypt the file at rest or use environment variable expansion ("env": {"DB_PASSWORD": "${MY_PASSWORD}"}) and source the variable from a vault.
Long-running tools time out. The default tool call timeout is 60 seconds. If your tool runs a 10-minute video render, the agent will think it failed and retry. Either set a longer timeout in your server config or have the tool return a job ID immediately and expose a separate check_status tool.
When MCP Isn't the Right Answer
MCP is great for tools the agent decides to call. It's the wrong choice for things the agent should do every turn — those belong in the system prompt or as autoloaded skills. It's also overkill for one-shot scripts. If you just need the agent to run a Python file once, Bash("python script.py") is faster than wrapping it in MCP.
Rule of thumb: if you'd want this capability available across multiple agent sessions and contexts, make it an MCP server. If it's specific to one task, a shell command or a skill is lighter weight.
What This Unlocks
Once your agent has five or six MCP servers wired up, the conversation changes. You stop saying "write me a script that does X" and start saying "do X." The agent figures out which tool to use, calls it, handles the error, retries if needed, and tells you the result.
That shift is what people mean when they talk about agents instead of chatbots. The model didn't get smarter — its hands just got bigger.