openclaw-mcp-client
v0.1.2
Published
OpenClaw plugin that bridges MCP (Model Context Protocol) servers as native agent tools over StreamableHTTP
Maintainers
Readme
openclaw-mcp-client
An OpenClaw plugin that bridges Model Context Protocol (MCP) servers as native agent tools. It connects to remote MCP servers over StreamableHTTP transport, discovers their tools at startup, and registers them into the OpenClaw agent runtime — making every MCP tool available to the agent without any extra code.
Table of Contents
- Overview
- Architecture
- Requirements
- Installation
- Configuration
- OAuth Authentication
- Tool Naming
- Contributing
- Notes & Limitations
Overview
OpenClaw agents execute tools. MCP servers expose tools. This plugin is the bridge between the two.
On agent startup, it connects to each configured MCP server in parallel, fetches the list of available tools, and registers them with the OpenClaw runtime. From that point on, the agent can call any MCP tool just like a native OpenClaw tool. When the agent shuts down, all connections are cleanly closed.
OpenClaw Agent
│
▼
openclaw-mcp-client (this plugin)
│
├──▶ MCP Server A (StreamableHTTP)
├──▶ MCP Server B (StreamableHTTP + OAuth)
└──▶ MCP Server C (StreamableHTTP + custom headers)Architecture
The plugin is written in TypeScript and compiled to ESM (Node 22+) via tsup.
Module Breakdown
| File | Responsibility |
|---|---|
| src/index.ts | Plugin entry point. Implements OpenClawPlugin.register(), wiring up the service lifecycle and CLI commands. |
| src/client.ts | MCP client logic. connectServer() establishes one connection; connectAll() runs them all in parallel; disconnectAll() cleanly closes them on shutdown. |
| src/oauth.ts | FileOAuthProvider — implements the MCP SDK's OAuthClientProvider interface. Persists tokens, client info, and PKCE code verifiers to JSON files on disk. |
| src/auth-cli.ts | The mcp-auth <server-name> CLI command. Guides the user through an interactive OAuth authorization flow. |
| src/types.ts | All TypeScript interfaces: OpenClawPlugin, PluginApi, PluginTool, PluginService, McpServerConfig, ConnectedServer, PluginConfig, etc. |
| openclaw.plugin.json | OpenClaw plugin manifest. Declares the plugin id, name, and JSON Schema for the configuration. |
Data Flow
OpenClaw loads plugin
│
▼
plugin.register(api)
├── api.registerService("mcp-connections")
│ ├── start()
│ │ ├── connectAll(servers) ← connects in parallel
│ │ │ └── per server:
│ │ │ ├── new MCP Client
│ │ │ ├── StreamableHTTPClientTransport
│ │ │ │ ├── (optional) OAuth via FileOAuthProvider
│ │ │ │ └── (optional) custom HTTP headers
│ │ │ ├── client.connect()
│ │ │ └── client.listTools()
│ │ └── api.registerTool() for each discovered tool
│ └── stop()
│ └── disconnectAll(servers) ← close all connections
└── api.registerCli(mcp-auth command)When a registered tool is called by the agent:
agent calls tool "myserver_toolname"
│
▼
execute(toolCallId, params)
│
▼
server.client.callTool({ name: "toolname", arguments: params })
│
▼
result content (text parts joined) returned to agentRequirements
- Node.js 22+
- OpenClaw installed:
# via install script
curl -fsSL https://openclaw.ai/install.sh | bash
# or via npm
npm install -g openclaw@latestInstallation
1. Install the plugin
openclaw plugins install openclaw-mcp-clientIf that fails with npm pack produced no archive (known OpenClaw bug), use the workaround:
npm pack openclaw-mcp-client
openclaw plugins install ./openclaw-mcp-client-*.tgz2. Configure (see next section)
3. Restart the gateway
openclaw gateway restartConfiguration
The plugin is configured inside ~/.openclaw/openclaw.json under the plugins.entries key.
Minimal example (one unauthenticated server):
{
"plugins": {
"entries": {
"openclaw-mcp-client": {
"enabled": true,
"config": {
"servers": [
{
"name": "my-server",
"url": "http://localhost:3000/mcp"
}
]
}
}
}
}
}Configuration Reference
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| servers | array | Yes | — | List of MCP servers to connect to. |
| servers[].name | string | Yes | — | Unique identifier for the server. Used in tool name prefixes and OAuth token storage. |
| servers[].url | string | Yes | — | StreamableHTTP endpoint of the MCP server (e.g. https://api.example.com/mcp). |
| servers[].headers | object | No | — | Extra HTTP headers to include in every request (e.g. { "X-Api-Key": "..." }). |
| servers[].auth | "oauth" | No | — | Authentication method. Set to "oauth" to enable the OAuth 2.0 PKCE flow. |
| servers[].callbackUrl | string | No | http://localhost:3000/callback | OAuth redirect URI. If the MCP server exposes its own /callback endpoint, set it here. Otherwise leave unset and use the localhost copy-paste flow. |
| clientName | string | No | "OpenClaw" | OAuth client_name sent during dynamic client registration. |
| authDir | string | No | ~/.openclaw-mcp-auth/ | Directory where OAuth tokens and client info are persisted. |
| toolPrefix | boolean | No | true | Prefix registered tool names with the server name (e.g. myserver_toolname). Set to false to use bare tool names. |
Full Configuration Example
{
"plugins": {
"entries": {
"openclaw-mcp-client": {
"enabled": true,
"config": {
"clientName": "MyApp",
"authDir": "/home/user/.my-mcp-tokens",
"toolPrefix": true,
"servers": [
{
"name": "local-tools",
"url": "http://localhost:4000/mcp"
},
{
"name": "secure-api",
"url": "https://api.example.com/mcp",
"headers": {
"X-Api-Key": "my-secret-key"
}
},
{
"name": "oauth-service",
"url": "https://oauth.example.com/mcp",
"auth": "oauth"
}
]
}
}
}
}
}OAuth Authentication
For MCP servers that require OAuth 2.0, the plugin ships with a FileOAuthProvider that implements the PKCE authorization code flow. Tokens are stored as JSON files in ~/.openclaw-mcp-auth/ (one file per server, named <server-name>.json).
Setting up OAuth for a server
Make sure the server has
"auth": "oauth"in its config entry.Run the interactive auth command:
openclaw mcp-auth <server-name>The command will:
- Attempt to connect to the server.
- If not yet authorized, print an authorization URL.
- Ask you to open the URL in a browser, grant access, and paste the resulting callback URL back into the terminal.
- Exchange the authorization code for tokens and save them to disk.
If tokens are already present and valid, the command will report
Already authenticated!.
After authentication, restart the gateway so the plugin picks up the stored tokens:
openclaw gateway restartNote: No local server is needed. The redirect to
http://localhost:3000/callbackwill fail in the browser — that's expected. Just copy the full URL from the browser's address bar and paste it into the terminal. This also works over SSH: the browser runs locally while the command runs on the remote machine. The MCP server must accepthttp://localhost:3000/callbackas an allowed redirect URI.
Tool Naming
By default (toolPrefix: true), each tool name is prefixed with the server name and an underscore:
<server-name>_<tool-name>For example, a tool called search on a server named brave becomes brave_search.
Set toolPrefix: false in the config to use bare tool names. This is useful when connecting to a single server or when tool names are guaranteed to be unique.
Contributing
git clone https://github.com/harlley/openclaw-mcp-client.git
cd openclaw-mcp-client
pnpm install
pnpm build
# Install local dev symlink into OpenClaw
openclaw plugins install -l /path/to/openclaw-mcp-clientUseful commands:
pnpm build # Build (ESM, outputs to dist/)
pnpm typecheck # TypeScript type checking
pnpm lint # Lint with oxlint
pnpm check # typecheck + lint togetherThis project has no automated test suite. End-to-end verification requires running the plugin within OpenClaw against a real MCP server. Issues and PRs are welcome at github.com/harlley/openclaw-mcp-client.
Notes & Limitations
- Transport: Only StreamableHTTP transport is supported.
stdioor SSE-based MCP servers are not supported. - Failed connections are non-fatal: If a server fails to connect at startup, the error is logged and the plugin continues with the remaining servers. The failing server's tools are simply not registered.
- OAuth prerequisite: If a server has
auth: "oauth"but tokens are not yet present, it is skipped at startup with a warning. Runopenclaw mcp-auth <server-name>first. - Text content only: The tool executor joins all
text-typed content parts from MCP responses. Binary or image content is currently ignored. - No reconnection:
maxRetriesis set to0. If an MCP server goes down after initial connection, tool calls will fail until the gateway is restarted.
