Repository navigation
Integrations Docker MCP Gateway
Experimental: this works and is tested, but may change and gets less hardening than the stable core.
Docker's MCP Gateway (docker mcp gateway run, what Docker Desktop's MCP
Toolkit runs) starts MCP servers in containers and serves their tools to one MCP client. Tracekit's
MCP gateway decides each tool call before it runs, holds risky ones for a person and signs a record
of each call and its result. Put Tracekit's in front, with Docker's as a stdio upstream. Neither side needs code.
agent --Streamable HTTP--> tracekit mcp-gateway --stdio--> docker mcp gateway run --> MCP servers in containers
|
+-- decide, approve, complete --> signer
| Docker's MCP Gateway | Tracekit's MCP gateway | |
|---|---|---|
| What it does | Runs each MCP server in a container with the secrets, mounts and network you grant it; refuses a call whose arguments or text result look like they carry a secret (--block-secrets, on by default) |
Decides each call before Docker sees it, holds risky ones for a person with the approval bound to the exact arguments, and signs the decision and the result |
| Where | A process its MCP client starts, speaking stdio | A service between the agent and Docker's gateway, outside the agent, reaching a signer |
| What a third party can check later | Its log and OpenTelemetry spans name the tool and the server, not the arguments or the result | A signed, hash-chained bundle, verified offline |
Run Tracekit's MCP gateway as its page describes: a v2 signer that lists it under gateways, its
http and signer sections, and agents that send their run in X-Tracekit-Run. Then add one upstream per Docker
server, each starting Docker's gateway on stdio with that one server:
upstreams:
- name: duckduckgo # tools listed as duckduckgo__<tool>, decided as mcp:duckduckgo/<tool>
command: [docker, mcp, gateway, run, --servers=duckduckgo]
- name: fetch
command: [docker, mcp, gateway, run, --servers=fetch]tracekit mcp-gateway serve --config mcp-gateway.yaml-
One server per upstream, named after it. A call is decided as
mcp:<upstream>/<tool>, so the upstream's name is the server name your rules see (mcp:fetch/*). Several servers behind onedocker mcp gateway runare all decided under that one name. -
--serverskeeps Docker's dynamic tools off. Without it, Docker's gateway adds tools such asmcp-find,mcp-add,mcp-execandcode-mode(itsdynamic-toolsfeature, on by default), which add servers and run other tools from inside one call. Tracekit decides that one call, not the calls it makes.docker mcp feature disable dynamic-toolsturns them off too. -
Docker settings go in
settings. A stdio upstream gets only a few variables of the gateway's environment (HOME,PATH,USERand the like); putDOCKER_HOST,DOCKER_CONTEXTorDOCKER_CONFIGin the upstream'ssettingsif thedockerCLI needs them (on Windows alsoProgramFilesandProgramData, which Docker's own client configs pass). -
Docker keeps its servers' secrets (
docker mcp secret set); the upstream needs noenv. -
The agent doesn't reach Docker. Run the agent as a user that can't use the Docker daemon or Docker Desktop (not
in the
dockergroup, no Docker socket mounted), and run Tracekit's gateway as one that can. An agent with Docker access can start its owndocker mcp gateway runand call the same servers around Tracekit. -
Point the agent at Tracekit's gateway, not at Docker's:
docker mcp client connectwrites anMCP_DOCKERentry into a client's config that starts Docker's gateway directly.
-
Sees: each tool call the agent sends through Tracekit's gateway, recorded as on the
MCP gateway's page: the decision for
mcp:<upstream>/<tool>and its arguments, any approval, and Docker's answer as the result (sourcegateway, tier T2). A call Docker refuses (its--block-secrets, its own policy, a container that fails) completes as an error. Each tool listing is recorded as untrusted input. - Doesn't see: what happens inside Docker's gateway: the image a call ran in, its mounts, network and secrets; the calls Docker's dynamic tools make (keep them off); anything the agent does with Docker itself.
- Doesn't tell agents apart on Docker's side: Docker's gateway sees one client, Tracekit's gateway, not the agents behind it. The Tracekit record names the agent.
-
Doesn't import Docker's spans: Docker's gateway exports an OpenTelemetry span per tool call (
mcp.tool.call, withmcp.tool.name,mcp.server.nameandmcp.server.type). Tracekit's OTLP import doesn't read those attributes as a tool call; it counts and skips the spans. They carry no arguments or results.
Docker's gateway takes --interceptor=<before|after>:<exec|docker|http>:<command, image or URL> for tool calls. A
before interceptor gets the call and may answer it instead: a non-empty answer is the result and the call doesn't run,
an empty one lets it run, and an interceptor that fails (a non-zero exit, an HTTP request that can't be made) fails the
call. An after interceptor gets only the result: not the tool, its arguments or which call it ends, and Docker's
gateway runs calls concurrently. An interceptor could decide and hold calls, but it couldn't tie a result to its
decision, and its request carries no run or caller identity for the signer to check: every allowed call would end as
a decided_not_completed gap. Tracekit's gateway in front records the decision, the approval and the result of each
call.
- Docker's dynamic tools run other tools from inside one call, which Tracekit decides as that call. Start each Docker
upstream with
--servers. - All servers behind one
docker mcp gateway runshare the upstream's name. Give each server its own upstream. - Tracekit's gateway cuts only the secrets in its own config from what it answers and records, not the ones Docker
gives its servers. Keep Docker's
--block-secretson. - Custody holds only while the agent can't reach Docker. Run the agent without Docker access.
- Docker's OpenTelemetry spans aren't imported as tool calls. Record the calls through Tracekit's gateway.
- Tested against a stand-in for
docker mcp gateway run(an MCP server on stdio), not Docker's gateway itself.
The MCP gateway's own limits apply too. Limits lists these with what to do.
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help