Skip to content
GitHub

OpenClaw Setup

OpenClaw agents access MCP servers through the mcporter CLI skill. This guide covers connecting an OpenClaw agent to Gatelet in both unsandboxed (host) and sandboxed (Docker) modes.

OpenClaw agents don’t have native MCP support — they use mcporter (an OpenClaw skill, not a plugin) via the exec tool to call MCP servers.

  • OpenClaw installed (openclaw --version)
  • Gatelet running with a published port
  • Node.js installed

These steps apply to both unsandboxed and sandboxed agents.

Terminal window
npm install -g mcporter

Verify the skill is ready:

Terminal window
openclaw skills info mcporter
# Should show: ✓ Ready
Terminal window
openclaw config set skills.entries.mcporter.enabled true

Or manually add to ~/.openclaw/openclaw.json under skills.entries:

"mcporter": { "enabled": true }

mcporter looks for a project-level config at ./config/mcporter.json (relative to the working directory). Create it:

Terminal window
mkdir -p ./config

Create ./config/mcporter.json:

{
"mcpServers": {
"gatelet": {
"description": "Gatelet MCP proxy",
"baseUrl": "http://localhost:4000/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}

You can override the config path with mcporter --config /path/to/config.json.

Terminal window
mcporter config list
mcporter call gatelet.calendar_list_calendars

If your OpenClaw agent runs directly on the host (no Docker sandbox), the common setup above is all you need. mcporter is already on PATH and can reach Gatelet at localhost.


If your agent runs inside a Docker sandbox, additional steps are needed to make mcporter and its config available inside the container.

Telegram/etc --> OpenClaw Gateway (:18789)
|
v
Docker Sandbox (agent)
|
v
mcporter CLI (exec tool)
|
v
Gatelet MCP proxy (host.docker.internal:4000)
|
v
Google Calendar, Gmail, etc.
  • Docker running
  • Node.js available in the sandbox Docker image

The sandbox container mounts ~/.openclaw/workspace as /workspace. mcporter looks for a project-level config at /workspace/config/mcporter.json inside the container.

Terminal window
mkdir -p ~/.openclaw/workspace/config

Create ~/.openclaw/workspace/config/mcporter.json:

{
"mcpServers": {
"gatelet": {
"description": "Gatelet MCP proxy",
"baseUrl": "http://host.docker.internal:4000/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}

Sandbox security blocks bind mounts from outside ~/.openclaw/workspace. Copy the mcporter package into the workspace:

Terminal window
cp -r "$(npm root -g)/mcporter" ~/.openclaw/workspace/.mcporter-bin

Add the following to ~/.openclaw/openclaw.json under agents.defaults.sandbox.docker:

{
"binds": [
"<WORKSPACE>/.mcporter-bin:/opt/mcporter:ro"
],
"setupCommand": "mkdir -p /workspace/bin && ln -sf /opt/mcporter/dist/cli.js /workspace/bin/mcporter",
"env": {
"PATH": "/workspace/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
}
}

Replace <WORKSPACE> with your actual workspace path (e.g. /Users/you/.openclaw/workspace or /home/you/.openclaw/workspace).

Why each piece:

  • binds — mounts the mcporter package read-only into /opt/mcporter inside the container
  • setupCommand — creates a symlink so mcporter is on PATH (can’t use /usr/local/bin because root fs is read-only; can’t use /tmp because tmpfs wipes it)
  • env.PATH — prepends /workspace/bin so the agent can find mcporter

Existing containers don’t pick up new bind mounts. Recreate them:

Terminal window
openclaw sandbox recreate --all

New containers will be created automatically on next agent message.

Terminal window
# Find the container
docker ps --filter "name=openclaw-sbx" --format "{{.Names}}"
# Verify mcporter works
docker exec <CONTAINER_NAME> /workspace/bin/mcporter config list
# Test a tool call
docker exec <CONTAINER_NAME> /workspace/bin/mcporter call \
--http-url "http://host.docker.internal:4000/mcp" \
--allow-http --name gatelet \
calendar_list_calendars

Then message your bot and ask it to use mcporter to call gatelet tools.


IssueCauseFix
source is outside allowed rootsBind mount path not inside workspaceCopy files into ~/.openclaw/workspace/
Read-only file systemContainer root fs is read-onlyUse /workspace/bin for symlinks, not /usr/local/bin
No local servers matchmcporter can’t find configPut config at ./config/mcporter.json (host) or <workspace>/config/mcporter.json (sandbox)
getaddrinfo ENOTFOUND gateletHostname not resolvable from containerUse host.docker.internal:PORT (macOS/Windows) or 172.17.0.1:PORT (Linux)
Not Acceptable errorServer requires streamable-http Accept headermcporter handles this automatically with baseUrl config
Symlink wiped after container startSymlink was in /tmp (tmpfs)Use /workspace/bin instead
HOME=/ inside containerContainer user has no home dirUse project-level config at /workspace/config/mcporter.json
Agent doesn’t know about mcporterSkill not enabled or not installedRun npm install -g mcporter + enable skill in config

When mcporter gets a new version:

Terminal window
npm update -g mcporter

If using sandboxed agents, also update the workspace copy:

Terminal window
cp -r "$(npm root -g)/mcporter" ~/.openclaw/workspace/.mcporter-bin
openclaw sandbox recreate --all

Add entries to your mcporter.json:

{
"mcpServers": {
"gatelet": {
"description": "Gatelet MCP proxy",
"baseUrl": "http://localhost:4000/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
},
"another-server": {
"description": "Another MCP server",
"baseUrl": "https://mcp.example.com/mcp"
}
}
}

No restart needed — mcporter reads the config on each invocation.