Woow Podman MCP Server
Provides tools for interacting with a Podman host via the libpod REST API, including managing containers, images, volumes, networks, and pods, with safety profiles gating available operations.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Woow Podman MCP Servershow me all running containers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Woow Podman MCP Server
A FastMCP server that exposes a Podman host through its libpod REST API as MCP tools, plus a web admin console that supervises it, gates it, and publishes it on an authenticated URL that Claude (or any MCP client) can connect to directly.
Three components, one container:
# | Component | What it is |
1 |
| The MCP server. 23 tools over the libpod API, gated by a safety profile. Binds to loopback only. |
2 |
| The admin console: React SPA + FastAPI, on |
3 |
| Product-agnostic plumbing shared with the other Woow MCP consoles: app factory, JWT auth, config store, process manager, reverse proxy. |
The connector URL is https://<host>/private_<mcp_auth_token>/mcp/. The path segment is the
credential — see Security.
Quick start
git clone https://github.com/WOOWTECH/Woow_podman__mcp_server.git
cd Woow_podman__mcp_server
# Podman's rootless socket must be running.
systemctl --user enable --now podman.socket
PODMAN_SOCK=/run/user/$(id -u)/podman/podman.sock \
PODMAN_UID=$(id -u) PODMAN_GID=$(id -g) \
JWT_SECRET=$(openssl rand -hex 32) \
docker compose up --buildThen:
Open http://localhost:8080. The admin password is printed once in the first-boot logs (
ADMIN_PASSWORD not set — generated one for first boot: …), or setADMIN_PASSWORDyourself.Tokens → Rotate to mint the MCP auth token. It is shown once.
Point your client at
http://localhost:8080/private_<that token>/mcp/.
To skip the GUI entirely, seed the config file directly:
python3 scripts/seed.py --config ./data/config.json --profile safeRelated MCP server: bazzite-mcp
Safety profiles
Tools are gated at registration time, not at list time. A tool outside the active profile does
not exist on the protocol — it cannot be called by name, cannot be reached by a client that cached
an older tools/list, and does not appear in the schema. This is deliberate: a gate that only
filters the listing is bypassed by any client that already knows the tool name.
Profile | Tools | Includes |
| 13 |
|
| 18 | + |
| 23 | + |
Set with PODMAN_MCP_PROFILE. In Kubernetes the profile lives in the Secret, so changing it
requires a rollout — the GUI deliberately cannot widen it.
Security
The Podman socket is the entire boundary. Anything that can reach it can start a privileged container and therefore own the host account. Three rules:
Mount the rootless socket (
/run/user/<uid>/podman/podman.sock), never the root service's.Run the container as that same uid/gid. A bind mount the process cannot connect to fails with
EACCES, which reads like a bug rather than a permission problem.Leave the profile at
safeunless you specifically need the destructive tools.
No OAuth. The server answers every /.well-known/* probe and /register with a JSON 404.
This is not an omission — it is the fix. The SPA catch-all used to answer those probes with
200 text/html, which a client reads as "yes, I have an authorization server"; it then attempted
Dynamic Client Registration, got HTML back, and failed with "Couldn't register with … 's sign-in
service" in a redirect loop. A clean 404 makes discovery fail fast so the client falls back to
anonymous access and just sends initialize.
The path token is the credential. It is compared with secrets.compare_digest, never echoed
back unmasked, and rotating it from the Tokens page restarts the child. Put the console behind a
tunnel with TLS; do not expose :8080 directly.
Configuration
Everything lives in /data/config.json (MCP_ADMIN_CONFIG), written atomically and chmod 600.
The connection section is upper-cased into the child's environment, so podman_uri arrives as
PODMAN_URI.
See .env.example for the full list. The ones that matter:
Variable | Default | Notes |
|
|
|
|
| A version newer than the daemon 404s every call |
|
|
|
|
| Per-call response ceiling; tools truncate by row and say how many they dropped |
| (random per process) | Set it, or every restart invalidates sessions |
| (generated, logged once) | First boot only |
Notes from the field
podman statswith an unknown name. libpod answersHTTP 200with{"Error": {}, "Stats": null}— and{}is falsy, so the obviousif payload.get("Error")check never fires and the tool silently returns nothing. It also returns no stats when any requested name is unknown, not just the bad one, so the error names the whole batch rather than accusing a container that is running fine.podman topwith plainpsflags. libpod returns fewer columns than titles for flag-style args likeaux, so the rows cannot be tabulated. The tool detects the mismatch and prints the raw output with a hint to use descriptor form (ps_args="-eo pid,user,comm") instead of producing a column-shifted table.Stream framing. libpod is always 8-byte multiplexed, even with a TTY; only the Docker-compat
/v1.xendpoints go raw. Thettyflag is passed down explicitly rather than guessed from the payload, because output that happens to start with\x01\x00\x00\x00is otherwise eaten.
Development
pip install -e ".[dev]"
pytest # 22 tests, no network, no Podman required
cd frontend && npm install && npm run devRun the console against a local Podman without Docker:
python3 scripts/seed.py --config /tmp/pm/config.json \
--podman-uri unix:///run/user/$(id -u)/podman/podman.sock
MCP_ADMIN_CONFIG=/tmp/pm/config.json JWT_SECRET=dev \
uvicorn podman_mcp_admin.main:app --port 8080Or run the MCP server on its own, with no console at all:
PODMAN_MCP_PROFILE=readonly python3 -m woow_podman_mcp_server.server # stdioRoadmap
Phase 1 (this release) is "the console comes up and the connector works". The MCP server is a
single self-contained server.py; the console supervises it, proxies it, streams its logs and
rotates its token.
Phase | Scope |
1 ✅ | Console boots, auth, process supervision, encrypted proxy, 18/23 tools live |
2 | Profile data model: |
3 | Connection & health: real Podman probe, Test Connection with distinct errors per failure mode, full dashboard |
4 | Kubernetes manifests, Cloudflare tunnel, socket-security docs |
5 | Podman operations pages (containers, images, volumes, networks, pods) |
Until Phase 2/3 land, the Connection and Tools pages get a JSON 404 from the API fallback
and render empty. That is intentional and easier to debug than a stub that pretends to work.
License
MIT — see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI tools to manage containerized applications through Podman, supporting container lifecycle operations, command execution, log viewing, image management, and resource monitoring. Features automatic network discovery for seamless integration with MCP Discovery Hub.Last updated12
- AlicenseBqualityDmaintenanceMCP server for managing Bazzite Linux hosts, enabling system administration, desktop control, and gaming tasks through natural language.Last updated242MIT
- Alicense-qualityBmaintenanceEnterprise-grade MCP server exposing Ansible Automation Platform 2.x as a complete AI interface for LLMs, enabling natural language management of automation resources.Last updated1Apache 2.0
- Alicense-qualityBmaintenanceEnables management of Podman containers, pods, images, and compose stacks via natural language, with support for container stats, logs, exec, health analysis, and a web dashboard.Last updated1MIT
Related MCP Connectors
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server for generating rough-draft project plans from natural-language prompts.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/WOOWTECH/Woow_podman__mcp_server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server