Connect an AI Agent with MCP
MCP, the Model Context Protocol, lets an AI agent discover and call the tools of a server. A tool is a function with a name and named parameters.
odctl mcp starts an MCP server that offers odctl's commands as tools. An MCP client, such as an AI assistant, starts odctl mcp as a process. It exchanges messages with the process over its standard input and output, which MCP calls stdio. The agent calls a tool and odctl runs the command.
The server offers five tools that only read, each running the command of the same name:
listreturns every profile with its services and ports.explaintakesprofileand returns that profile's services, images, ports, volumes and usage.pstakesprofilesand returns their containers and the active profiles, or every container odctl manages whenprofilesis left out.inforeturns the odctl version, the image tag, the workspace, whether Docker is reachable and odctl's own images.logstakesprofiles,service,tail,timestamps,sinceanduntil, and returns the logs of the containers of those profiles.
tail defaults to 100 lines, so one call cannot fill the agent's context with a long log. odctl logs prints all lines, and a call can pass another number.
Results and errors:
list,explain,psandinforeturn the documents on the JSON Output page, andlist's array arrives under the keyresultbecause a tool's structured result is an object.inforeports Docker as not reachable withreachable: false, not as an error.logsreturns the lines thatodctl logsprints.- A tool that fails returns the error message of the command.
- Tools run one at a time.
The server offers the tools up and down only when you start it with --allow-changes, as Allow Up and Down explains. The tool names and their parameter names stay the same in every 1.x release, as What Stays Stable in 1.x says.
This guide builds on Getting Started and JSON Output.
Install
The server needs the mcp extra of odctl. This installs odctl with it:
| docs/snippets/mcp-server/commands.sh:install | |
|---|---|
Without the extra, odctl mcp exits with an error that names this command. uv tool install keeps odctl in an environment of its own, so the client scripts below need the mcp package in an environment of their own. This makes one in the current folder: python -m venv .venv, then source .venv/bin/activate and pip install "mcp>=2.3.0,<3". Keep it out of an environment that holds the client of the Feast guide, which needs mcp below 2.
Add It to an MCP Client
Claude Code is Anthropic's command-line coding agent, and it is an MCP client. The scripts in the next sections start the server themselves and need no client set up, so skip this section if you use only them. Run this in the folder of your project to add odctl to the project:
| docs/snippets/mcp-server/commands.sh:claude-code | |
|---|---|
The command writes this entry to .mcp.json:
| docs/snippets/mcp-server/mcp.json | |
|---|---|
Any MCP client that starts a server over stdio needs the same two things, the command odctl and the argument mcp. odctl reads the .odctl workspace of the folder where the client starts it. When your client starts servers in another folder, put "--workspace", "<absolute path to .odctl>" before "mcp" in the highlighted args. The --workspace option sets the workspace for every tool, because it is read once, when the server starts.
List the Tools
This script starts the server command from its arguments and prints the name and description of each tool. Save it as mcp_client.py and run it in the environment that has mcp:
This lists the five tools that only read:
| docs/snippets/mcp-server/commands.sh:list-tools | |
|---|---|
Allow Up and Down
The tools up and down start and stop profiles, so an agent that can call them changes what runs on your machine. They exist only when the server starts with the option --allow-changes. An option shows in the client's configuration, where an environment variable left set in a shell could allow changes without anyone seeing it. This lists the seven tools:
| docs/snippets/mcp-server/commands.sh:list-tools-changes | |
|---|---|
up takes profiles and pull, and down takes profiles and volumes. Each returns what the command prints. The server marks both as destructive, so a client can ask before it runs them. up replaces a container whose definition changed, and the data inside it goes with it. down takes named profiles only. odctl down --all --volumes asks before it removes the data of every profile, and a server cannot ask. So down with volumes refuses names that cover every profile odctl down --all --volumes would stop, and no tool removes everything in one call.
Runnable Example
Save this file as example.py and run it with python example.py in the folder that holds your .odctl workspace, made by odctl init as Getting Started shows, in the environment that has mcp. It starts the server with --allow-changes, starts kafka-lite, reads info, the containers of kafka-lite and the last five lines of the connect service, then stops kafka-lite. A tool that fails returns its error as the result, so the script checks each result, stops at the first error and still stops kafka-lite:
It prints the result of each tool under a line with the tool's name. The output below shortens the path of the .odctl folder to /home/you/project/.odctl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |