#Possibility to run MCPs with sandboxing?

1 messages · Page 1 of 1 (latest)

magic wagon
#

Hi,
I setup a local MCP today like this:

  "mcp": {
    "servers": {
      "basecamp": {
        "command": "/home/openclaw/basecamp-mcp/venv/bin/python",
        "args": [
          "/home/openclaw/basecamp-mcp/basecamp_fastmcp.py"
        ],
        "cwd": "/home/openclaw/basecamp-mcp"
      }
    }
  }

I registered it with openclaw mcp and with mcporter and setup the mcporter skill (please tell me if that's overkill). It works great without sandboxing but not with it (makes sense since there is no mcporter binary and no code nor possibility to connect to the internet inside the container). Unfortunately I do require sandboxing, especially since I am running a local model with a small number of weights.
My question is: Is there a way around that? Like hosting the MCP server as an HTTP/SSE service and somehow forwarding that to Docker? Am I overlooking something?
Cheers!

hidden shaleBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

patent idolBOT
# magic wagon Hi, I setup a local MCP today like this: ```json "mcp": { "servers": { ...

Short answer: yes, the HTTP/SSE route is the clean workaround.

A few verified bits from the current docs/source:

  • mcp.servers supports stdio, SSE/HTTP, and streamable-http. A URL-based server can be configured like:
{
  mcp: {
    servers: {
      basecamp: {
        url: "http://host.docker.internal:3100/mcp",
        transport: "streamable-http",
        headers: { Authorization: "Bearer <token>" }
      }
    }
  }
patent idolBOT
patent idolBOT
# magic wagon Hi, I setup a local MCP today like this: ```json "mcp": { "servers": { ...
    }
  }
}

Then recreate the sandbox with openclaw sandbox recreate --all.

  • Don’t use localhost in the MCP URL from inside the sandbox unless the MCP server is inside the same container. From the sandbox, localhost is the sandbox container. Either run the MCP server as another container on a custom bridge network, or expose it from the host and use host.docker.internal / a reachable LAN or bridge address.

  • network: "host" is intentionally blocked, and network: "container:<id>" is blocked by default. Custom bridge network is the safer shape.

On mcporter: if your Basecamp server already speaks MCP, registering it directly under mcp.servers is usually enough. mcporter is useful when you specifically need that runtime/daemon layer; otherwise it’s probably extra moving parts here.

Security caveat: Basecamp MCP is effectively a privileged bridge to your Basecamp data, so keep it bound narrowly, require an auth header, and avoid mounting its code/secrets into the agent sandbox unless you really need stdio.

Docs:
https://docs.openclaw.ai/cli/mcp

patent idolBOT
magic wagon
#

ok I set it up like you told me. It works great without sandboxing again. but not with it. the sandboxed agent says:
I’m not able to reach the MCP server from this sandbox—there’s no mcporter binary installed here, the mcporter skill directory is locked down (root‑only), and a direct curl to http://host.docker.internal:3100/mcp fails with a connection error.

To fetch your Basecamp todos I’d need either:

  1. The mcporter executable (or a Node module that provides it) installed in the sandbox, or2. A way to reach the MCP endpoint from here (e.g. an exposed HTTP address you can curl).

If you can install mcporter (e.g. npm i -g mcporter or add the binary to a path the sandbox can see) or give me a reachable URL/command, I’ll run it and return the todos. Let me know how you’d like to proceed.

patent idolBOT
# magic wagon ok I set it up like you told me. It works great without sandboxing again. but no...

JL, that error lines up with two sandbox defaults:

  1. Docker sandboxes default to no network, so http://host.docker.internal:3100/mcp will fail unless you opt into a Docker network.
  2. The default sandbox image does not include Node, so a stdio MCP command like mcporter will not exist inside the sandbox unless you install/bake it in.

First, can you share openclaw --version? Version matters a lot here.

If your MCP is exposed as HTTP on the host, I’d try this shape in openclaw.json:

{
  agents: {
    defaults: {
      sandbox: {
        mode: "all", // or "non-main", whatever you intended
        docker: {
patent idolBOT
patent idolBOT
# magic wagon ok I set it up like you told me. It works great without sandboxing again. but no...

Also make sure the MCP server on port 3100 is listening on an address the Docker container can reach. If it is bound only to 127.0.0.1 on the host, host.docker.internal may still not reach it depending on how mcporter starts the server.

If your MCP config is stdio and launches mcporter inside the sandbox, then network alone won’t fix it. You need either a custom sandbox image with mcporter installed, or a one-time setup command. Docs say the setup command needs network egress + writable root + root user:

{
  agents: {
    defaults: {
      sandbox: {
        docker: {
          network: "bridge",
          readOnlyRoot: false,
          extraHosts: ["host.docker.internal:host-gateway"],
          setupCommand: "npm i -g mcporter"
        }
      }
patent idolBOT
magic wagon
#

openclaw --version
OpenClaw 2026.5.7 (eeef486)

I managed to get it working with sandboxing by running the mcp inside a docker container that is on the dame docker network as the openclaw container (when running rootless docker they MUST also run as the same user) like this:
openclaw.json:

{
"agents": {
    "defaults": {
      "workspace": "/home/openclaw/.openclaw/workspace",
      "models": {
        ...
      },
      "sandbox": {
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "none",
        "docker": {
          "image": "openclaw-sandbox-common:bookworm-slim",
          "network": "mcp-net"
        }
      }
      ...
    }
  }, 
  ...
  "mcp": {
    "servers": {
      "basecamp": {
        "url": "http://basecamp-mcp:3100/mcp",
        "transport": "streamable-http",
        "headers": {
          "Authorization": "Bearer <TOKEN>"
        }
      }
    }
  }
}

docker-compose.yaml

services:        
  basecamp-mcp:
    ...
    networks:
      - mcp-net

    ...

networks:
  mcp-net:
    name: mcp-net

...

Now while this works with sandboxing the agent is dumb. Ideally I should just ask plain text questions and the agent should automatically use the MCP. However I am just getting: "I’m not seeing the mcporter executable or its configuration files in this sandboxed environment" with the mcporter skill deactivated: "I don’t have direct visibility into your MCP configuration, so I’ll need the exact command". When I then give it the exact curl commands to set up a mcp-session-id id and then exactly what endpoints to call and with what parameters it works. But that shouldn't be how it works right?

patent idolBOT
# magic wagon `openclaw --version` OpenClaw 2026.5.7 (eeef486) I managed to get it working wi...

Right: you should not have to teach the agent raw MCP session/curl mechanics.

What you built proves network reachability, but the behavior you’re seeing means the model likely is not receiving the MCP server’s tools as OpenClaw tools. In the normal path, mcp.servers.basecamp is loaded by the embedded runtime, OpenClaw calls listTools, and each MCP tool is exposed to the agent as a normal tool with a generated name like basecamp__.... The sandbox container does not need to see a mcporter executable for an HTTP MCP server.

The main things I’d check:

  1. Is this session using a CLI backend? If yes, the backend only sees MCP tools when bundle MCP is enabled for that backend. Docs call this out: https://docs.openclaw.ai/gateway/cli-backends#bundle-mcp-overlays

  2. Check tool policy. If you have any non-empty tools.allow or tools.sandbox.tools.allow, everything not explicitly allowed is blocked. group:openclaw excludes provider/plugin-style tools, and bundled MCP tools are tagged as bundle-mcp, so they may need explicit allowlisting depending on your policy shape. Docs: https://docs.openclaw.ai/gateway/sandbox-vs-tool-policy-vs-elevated

  3. Check whether OpenClaw can actually catalog the MCP server:

openclaw mcp show basecamp --json
openclaw logs --follow | rg 'bundle-mcp|basecamp|MCP'

You’re looking for either “failed to start/list tools” or confirmation that it listed tools. If cataloging fails, the model never sees the tools.

patent idolBOT
# magic wagon `openclaw --version` OpenClaw 2026.5.7 (eeef486) I managed to get it working wi...
  1. Run:
openclaw sandbox explain --json

That should make it clear whether sandbox tool policy is filtering the MCP-derived tools in that session.

Also: your Docker-network workaround makes sense for the HTTP server case. The suspicious part is the agent asking for mcporter; that sounds like the mcporter/QMD skill path is active or the model is falling back to filesystem/process guessing because the MCP tools were not injected. If the MCP tools are visible, the agent should call them directly from plain English. 🦞

magic wagon
#
  1. agent:main:matrix.org

  2. and 4.
    openclaw@ubuntu:~$ openclaw sandbox explain --json --session agent:main:matrix.org
    {
    "docsUrl": "https://docs.openclaw.ai/sandbox",
    "agentId": "main",
    "sessionKey": "agent:main:matrix.org",
    "mainSessionKey": "agent:main:main",
    "sandbox": {
    "mode": "all",
    "scope": "session",
    "workspaceAccess": "none",
    "workspaceRoot": "/home/openclaw/.openclaw/sandboxes",
    "sessionIsSandboxed": true,
    "tools": {
    "allow": [
    "exec",
    "process",
    "read",
    "write",
    "edit",
    "apply_patch",
    "image",
    "sessions_list",
    "sessions_history",
    "sessions_send",
    "sessions_spawn",
    "sessions_yield",
    "subagents",
    "session_status"
    ],
    "deny": [
    "browser",
    "canvas",
    "nodes",
    "cron",
    "gateway",
    (all the channels)
    ],
    "sources": {
    "allow": {
    "source": "default",
    "key": "tools.sandbox.tools.allow"
    },
    "deny": {
    "source": "default",
    "key": "tools.sandbox.tools.deny"
    }
    }
    }
    },
    "elevated": {
    "enabled": false,
    "allowedByConfig": false,
    "alwaysAllowedByConfig": false,
    "allowFrom": {},
    "failures": [
    {
    "gate": "enabled",
    "key": "tools.elevated.enabled"
    }
    ]
    },
    "fixIt": [
    "agents.defaults.sandbox.mode=off",
    "agents.list[].sandbox.mode=off",
    "tools.sandbox.tools.allow",
    "tools.sandbox.tools.alsoAllow",
    "tools.sandbox.tools.deny",
    "agents.list[].tools.sandbox.tools.allow",
    "agents.list[].tools.sandbox.tools.alsoAllow",
    "agents.list[].tools.sandbox.tools.deny",
    "tools.elevated.enabled"
    ]
    }

openclaw@ubuntu:~$ openclaw mcp show basecamp --json
{
"url": "http://basecamp-mcp:3100/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer <TOKEN>"
}
}
logs show:
2026-05-18T07:33:02.791Z warn bundle-mcp {"subsystem":"bundle-mcp"} failed to start server "basecamp" (http://basecamp-mcp:3100/mcp): TypeError: fetch failed

patent idolBOT
# magic wagon 1. agent:main:matrix.org 2. and 4. openclaw@ubuntu:~$ openclaw sandbox explain ...

Yep, that explains it. You have two separate blockers.

First blocker is connectivity:

bundle-mcp ... failed to start server "basecamp" (http://basecamp-mcp:3100/mcp): TypeError: fetch failed

That MCP cataloging happens from the OpenClaw/Gateway runtime path, before the model gets tools. So don’t test only from the sandbox container; test from wherever the OpenClaw gateway process is actually running:

# if OpenClaw gateway is in Docker:
docker exec -it <openclaw-gateway-container> sh
getent hosts basecamp-mcp
curl -v http://basecamp-mcp:3100/mcp

If basecamp-mcp only resolves from the sandbox container, OpenClaw still can’t list MCP tools. The gateway container/process also needs network/DNS reachability to basecamp-mcp. agents.defaults.sandbox.docker.network = "mcp-net" controls the sandbox tool container network; it does not by itself prove the gateway-side bundle-MCP client can reach that hostname.

patent idolBOT
# magic wagon 1. agent:main:matrix.org 2. and 4. openclaw@ubuntu:~$ openclaw sandbox explain ...

Second blocker is tool policy. Your sandbox allowlist is explicit and only includes core tools:

exec, process, read, write, edit, apply_patch, image, sessions_...

Bundled MCP tools are tagged as bundle-mcp, so after connectivity is fixed they can still be filtered out. Add it to the sandbox tool policy, preferably without replacing the existing defaults:

{
  tools: {
    sandbox: {
      tools: {
        alsoAllow: ["bundle-mcp"]
      }
    }
patent idolBOT
# magic wagon 1. agent:main:matrix.org 2. and 4. openclaw@ubuntu:~$ openclaw sandbox explain ...
  }
}

If you also have a top-level tools.allow, add bundle-mcp there too, or use a profile that includes it. Docs: https://docs.openclaw.ai/gateway/sandbox-vs-tool-policy-vs-elevated

After both changes, restart the gateway and watch:

openclaw logs --follow | rg 'bundle-mcp|basecamp'

You want the fetch failed line gone. Once OpenClaw can list the Basecamp MCP tools and policy allows bundle-mcp, plain-English prompts should start using those tools instead of asking you for curl commands.