A mini code agent with Docker Agent - Part 5: the `mcp` toolset
So far, all our tools were built into docker-agent (shell, filesystem, todo, think, memory, rag). The Model Context Protocol (MCP) opens another door: plugging in external tool servers, written by other people, to give the agent capabilities that docker-agent does not provide natively.
Three ways to plug an MCP server into Docker Agent
docker-agent knows three transports, all under type: mcp:
| Form | Config | What for |
|---|---|---|
| Local (stdio) | command: + args: | run a server as a subprocess, talk over stdin/stdout |
| Remote (HTTP/SSE) | remote: (URL) | an MCP server reachable over the network |
| Docker MCP | ref: docker:<server> | servers from the Docker MCP Toolkit |
This new lesson puts two of them into practice: local stdio and streamable HTTP
agents:
root:
toolsets:
- type: mcp # local server, launched as a subprocess
command: npx
args: ["-y", "@modelcontextprotocol/server-everything"]
tools: ["get-sum"]
- type: mcp # remote server, reached over HTTP
remote:
url: https://mcp-docs.docker.com/mcp
transport_type: streamable
tools: ["fetch_docker_docs"]
The local server, over stdio
toolsets:
- type: mcp
command: npx
args: ["-y", "@modelcontextprotocol/server-everything"]
docker-agent launches the process npx ...server-everything and speaks MCP to it over stdin/stdout. The server announces its tools (get-sum, echo, ...), which docker-agent then exposes to the model exactly like built-in tools. The model sees no difference: it gets a catalogue of tools and decides which one to call.
server-everythingreally exists ā it is the official demonstration server of the MCP project. Nothing to invent, nothing to write: the @modelcontextprotocol/server-everything package is published on npm by the project itself, andnpx -yfetches it and runs it. As of today it exposes 13 tools āget-sum,echo,get-env,get-tiny-image,trigger-long-running-operation,get-structured-content..., none of which does any "real" work. We are going to use it purely to see the MCP mechanism end to end, with no network, no API key, no third-party service.
The remote server, over streamable HTTP
This transport launches no process and pulls no image: docker-agent speaks HTTP to a server somebody else operates.
toolsets:
- type: mcp
remote:
url: https://mcp-docs.docker.com/mcp
transport_type: streamable
tools: ["fetch_docker_docs"]
That server is the Docker documentation itself: public, anonymous, nothing to install. It exposes a single tool, fetch_docker_docs().
Three config points worth knowing:
transport_typeonly accepts three values:streamable(or its aliasstreamable-http) for the current transport, andssefor servers still on the old mode ("legacy").headers:carries the authentication when the server asks for it, with environment interpolation:Authorization: "Bearer ${env.MY_TOKEN}".tools:filters the tools exposed by the server.
Shrinking the surface: tools:
An MCP server can expose dozens of tools. You can keep only a few of them:
- type: mcp
ref: docker:github-official
tools:
- get_file_contents
- search_repositories
Useful for a small model: an MCP server can expose dozens of tools, but you only need a handful of them. The model only sees those listed in tools:, which is handy for a small model because with fewer tools the prompt is shorter, the choice simpler, and therefore there are fewer mistakes. And it is better for security: you only expose what is necessary.
shell or MCP? (a reminder from lesson 01)
shell | MCP | |
|---|---|---|
| Surface | the whole system, untyped | what the server exposes, typed |
| Target with no CLI (API, DB, SaaS) | no | yes |
| Framing / safety | weak | strong (explicit tools, tools:) |
| Effort | none | plug in/host a server |
Rule of thumb: shell to explore and run local CLIs; MCP as soon as you need a capability that is without a local binary, typed, or framed.
Now we are going to test the agent with these two MCP servers, over stdio and over streamable HTTP.
The complete agent.yaml for this lesson
agents:
root:
model: mellum
description: An agent whose tools come from two MCP servers, one local and one remote.
instruction: |
Your tools come from external MCP servers.
Use `get-sum` to add two numbers.
Use `fetch_docker_docs` for any question about the Docker documentation,
and answer only from what it returns.
toolsets:
# --- Local server, over stdio (the simplest transport) ---------------
- type: mcp
# docker-agent launches this process and speaks MCP over stdin/stdout.
command: npx
args: ["-y", "@modelcontextprotocol/server-everything"]
tools: ["get-sum"]
# --- Remote server, over streamable HTTP -----------------------------
- type: mcp
remote:
url: https://mcp-docs.docker.com/mcp
transport_type: streamable
tools: ["fetch_docker_docs"]
models:
mellum:
provider: dmr
model: huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M
base_url: http://localhost:12434/engines/v1
# base_url: http://host.docker.internal:12434/engines/v1
š You'll find all the configuration files over here: 05-mcp-toolsets
Running Docker Agent with these two MCP servers
cd 05-mcp-toolsets
# TUI
docker-agent run localhost.agent.yaml
# Or TUI with sbx (sandbox):
sbx run docker-agent --kit . -- run agent.yaml
Prompts to try
Try these prompts in the TUI:
"Use the get-sum tool to add 21 and 21"

"What topics does the Docker documentation cover? Two sentences."


"What tools do you have available? List them for me."

Key takeaways
- MCP plugs in external tool servers; the model sees them as built-in tools.
- Three transports:
ref: docker:<server>(the idiomatic one),command/args(local stdio),remote(streamable HTTP or SSE). - A remote server needs no process, no image, no plugin ā just a URL and the right
transport_type. tools:shrinks the exposed surface, which is good for a small model and good for security.
In the next blog post, we'll talk about skills, which let you compose tools to create more complex capabilities, and expose them to the model as a single tool.
Written by

No comments yet. Be the first to comment!