Skip to main content

MCP server that exposes Podman container management as tools for AI assistants

Project description

podman-mcp

PyPI version Python License: MIT Podman Claude GitHub Copilot ChatGPT Cursor Windsurf

A Model Context Protocol (MCP) server that exposes Podman container management as tools for AI assistants such as Claude, GitHub Copilot, ChatGPT, Cursor and Windsurf.

With podman-mcp you can manage containers and images through natural language — no need to remember CLI flags.

"Show me all running containers"
"Pull the nginx image and run it on port 8080"
"Show me the last 100 log lines from myapp"


Table of Contents


Requirements


Installation

Using pip (recommended)

pip install podman-mcp

From source

git clone https://github.com/edtroleis/podman-mcp.git
cd podman-mcp

python3 -m venv .venv
source .venv/bin/activate

pip install -r requirements.txt

Client Configuration

Claude Code

Via pip:

claude mcp add --scope user podman-mcp -- podman-mcp

From source:

claude mcp add --scope user podman-mcp -- /absolute/path/to/podman-mcp/.venv/bin/podman-mcp

The --scope user flag makes the server available across all projects.

Verify:

claude mcp list

Skip confirmation prompts

By default, Claude asks for confirmation before calling each tool. To allow all podman-mcp tools to run without prompts, add the following to ~/.claude/settings.json:

{
  "permissions": {
    "allow": [
      "mcp__podman-mcp__*"
    ]
  }
}

GitHub Copilot (VS Code)

Create or edit .vscode/mcp.json in your workspace.

Via pip:

{
  "servers": {
    "podman-mcp": {
      "type": "stdio",
      "command": "podman-mcp"
    }
  }
}

From source:

{
  "servers": {
    "podman-mcp": {
      "type": "stdio",
      "command": "/absolute/path/to/podman-mcp/.venv/bin/podman-mcp"
    }
  }
}

Requires VS Code 1.99+ with GitHub Copilot agent mode enabled.

Note: VS Code does not auto-start MCP servers. After opening Copilot Chat, click the Start button next to podman-mcp in the Tools section once per VS Code session. This is a VS Code security design decision and cannot be configured away.


Cursor

Create or edit ~/.cursor/mcp.json.

Via pip:

{
  "mcpServers": {
    "podman-mcp": {
      "command": "podman-mcp"
    }
  }
}

From source:

{
  "mcpServers": {
    "podman-mcp": {
      "command": "/absolute/path/to/podman-mcp/.venv/bin/podman-mcp"
    }
  }
}

Windsurf

Create or edit ~/.codeium/windsurf/mcp_config.json.

Via pip:

{
  "mcpServers": {
    "podman-mcp": {
      "command": "podman-mcp"
    }
  }
}

From source:

{
  "mcpServers": {
    "podman-mcp": {
      "command": "/absolute/path/to/podman-mcp/.venv/bin/podman-mcp"
    }
  }
}

ChatGPT and other HTTP clients

Start the server in SSE mode:

Via pip:

podman-mcp --transport sse --host 127.0.0.1 --port 8000

From source:

/absolute/path/to/podman-mcp/.venv/bin/podman-mcp --transport sse --host 127.0.0.1 --port 8000

The MCP endpoint will be available at:

http://127.0.0.1:8000/sse

Configure your client to connect to that URL as a remote MCP server.


Using from the Terminal

You can interact with podman-mcp directly from the terminal using the Claude Code CLI — no IDE required.

Claude Code CLI

Once podman-mcp is registered with --scope user, start an interactive session:

claude

Then ask naturally:

How many images do I have locally?
Pull nginx:latest
Show logs from my api container
List all running containers
Remove the alpine image

Other AI CLIs (HTTP mode)

For AI tools that support remote MCP over HTTP, start the server in SSE mode first:

podman-mcp --transport sse --host 127.0.0.1 --port 8000

Then point your AI CLI client to http://127.0.0.1:8000/sse.


Available Tools

Images

Tool Description Parameters
list_images List all local images
pull_image Pull an image from a registry image: str
remove_image Remove an image image: str, force: bool
build_image Build an image from a Dockerfile tag: str, dockerfile: str, context: str
tag_image Tag an image with a new name source: str, target: str
push_image Push an image to a registry image: str
image_history Show layer history of an image image: str
search_image Search for images in registries term: str
save_image Save an image to a tar archive image: str, output: str
load_image Load an image from a tar archive path: str
prune_images Remove unused images all: bool

Containers

Tool Description Parameters
list_containers List containers all: bool (include stopped)
run_container Run a container image: str, args: str
start_container Start a stopped container name: str
stop_container Stop a running container name: str
restart_container Restart a container name: str
pause_container Pause all processes in a container name: str
unpause_container Resume a paused container name: str
rename_container Rename a container name: str, new_name: str
remove_container Remove a container name: str, force: bool
container_logs Fetch container logs name: str, tail: int
exec_in_container Run a command inside a container name: str, command: str
inspect_container Inspect container configuration name: str
container_stats Show resource usage for running containers name: str (empty for all)
container_top Show running processes inside a container name: str
container_port List port mappings of a container name: str
container_diff Show filesystem changes in a container name: str
copy_to_container Copy files between host and container src: str, dest: str

Networks

Tool Description Parameters
network_list List all networks
network_create Create a new network name: str
network_remove Remove a network name: str
network_inspect Inspect a network name: str
network_connect Connect a container to a network network: str, container: str
network_disconnect Disconnect a container from a network network: str, container: str
network_prune Remove all unused networks

Volumes

Tool Description Parameters
volume_list List all volumes
volume_create Create a new volume name: str
volume_remove Remove a volume name: str
volume_inspect Inspect a volume name: str
volume_prune Remove all unused volumes

Pods

Tool Description Parameters
pod_list List pods all: bool (include stopped)
pod_create Create a new pod name: str
pod_remove Remove a pod name: str, force: bool
pod_start Start a pod and all its containers name: str
pod_stop Stop a pod and all its containers name: str
pod_restart Restart a pod and all its containers name: str
pod_inspect Inspect a pod name: str
pod_stats Show resource usage stats for pods name: str (empty for all)

Secrets

Tool Description Parameters
secret_list List all secrets
secret_create Create a secret from a literal value name: str, value: str
secret_remove Remove a secret name: str
secret_inspect Inspect a secret (value is never revealed) name: str

Generate

Tool Description Parameters
generate_kube Generate Kubernetes YAML from a pod or container name: str
generate_systemd Generate a systemd unit file for a container or pod name: str

System

Tool Description Parameters
system_info Podman disk usage and system stats
system_prune Remove all unused resources all: bool
system_events Show recent Podman events since: str, until: str, filter: str
podman_version Show Podman version information
podman_info Show detailed host and runtime information
login_registry Login to a container registry registry: str, username: str, password: str

Usage Examples

Once registered, interact with Podman using natural language. Examples by category:

Images

How many images do I have locally?
Pull the python:3.12-slim image from Docker Hub
Build an image tagged myapp:latest from the Dockerfile in the current directory
Show the layer history of the debian:latest image
Tag myapp:latest as localhost:8082/myapp:1.0
Push localhost:8082/myapp:1.0 to the registry
Search for postgres images in Docker Hub
Save the myapp:latest image to /tmp/myapp.tar
Remove the alpine image

Containers

List all running containers
Show me all containers, including stopped ones
Run nginx in detached mode, exposing port 8080 on the host
Start the stopped api container
Restart the db container
Show the last 200 log lines from the api container
What is the IP address of the db container?
Show CPU and memory usage for all running containers
Execute the command "df -h" inside the api container
Show all port mappings of the web container
Remove all stopped containers

Networks

List all networks
Create a network called backend-net
Connect the api container to the backend-net network
Remove unused networks

Volumes

List all volumes
Create a volume called postgres-data
Remove unused volumes

Pods

List all pods, including stopped ones
Create a pod called my-pod
Start the my-pod pod
Stop the my-pod pod
Remove the my-pod pod and all its containers
Show resource usage for all pods

Secrets

List all secrets
Create a secret called db-password with value s3cr3t
Show metadata for the db-password secret
Remove the db-password secret

Generate

Generate Kubernetes YAML for the my-pod pod
Generate a systemd unit file for the api container

System & Registry

Show Podman disk usage and system stats
Show detailed Podman host information
Show the Podman version
Show recent container start events from the last hour
Remove all unused containers, images, networks and volumes
Login to localhost:8082 with my credentials

Project Structure

podman-mcp/
├── .github/
│   └── workflows/
│       └── publish.yml    # GitHub Actions — publishes to PyPI on tag push
├── podman_mcp/
│   ├── __init__.py
│   └── server.py          # MCP server — all tools are defined here
├── tests/
│   └── test_server.py     # pytest test suite
├── pyproject.toml         # Project metadata and build config
├── requirements.txt       # Runtime dependencies
├── CONTRIBUTING.md        # How to contribute
├── LICENSE                # MIT License
└── README.md

Testing

Tests use pytest and mock subprocess.run so no Podman installation is required to run them.

Install dev dependencies and run the suite:

pip install -e ".[dev]"
pytest tests/

Run with verbose output:

pytest tests/ -v

Adding New Tools

Open podman_mcp/server.py and add a new function decorated with @mcp.tool():

@mcp.tool()
def your_tool_name(param: str) -> str:
    """Clear description — the AI assistant uses this to decide when to call the tool."""
    return run(f"<podman subcommand> {param}")

No re-registration is needed. Restart your AI client session to pick up the new tool.


Releasing a New Version

  1. Bump the version in pyproject.toml:
[project]
version = "1.2.3"
  1. Commit and push:
git add pyproject.toml
git commit -m "bump version to 1.2.3"
git push
  1. Create and push a tag — this triggers the publish pipeline:
git tag v1.2.3
git push origin v1.2.3

The GitHub Actions workflow will run tests, publish to PyPI and create a GitHub Release automatically.

Note: PyPI does not allow re-uploading the same version. Always bump the version before tagging.

Release Notes

Release notes are generated automatically from commits and PRs merged since the last tag, grouped by label:

Label Section
enhancement, feature New Features
bug, fix Bug Fixes
documentation, docs Documentation
anything else Other Changes

No conventional commit format required — just label your PRs on GitHub before merging.


Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

podman_mcp-0.3.0.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

podman_mcp-0.3.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file podman_mcp-0.3.0.tar.gz.

File metadata

  • Download URL: podman_mcp-0.3.0.tar.gz
  • Upload date:
  • Size: 15.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for podman_mcp-0.3.0.tar.gz
Algorithm Hash digest
SHA256 fb03c25a87d6844a0d27f8f54d6e74c199a8ed8a9b0be33cd3fdcff50ee578fc
MD5 0cbe63c773648fc041c88675abfb2f8e
BLAKE2b-256 032628dd379382272b19241eb04c7caacb3024f0bc35fcec2ce7cbfe0f3c701e

See more details on using hashes here.

Provenance

The following attestation bundles were made for podman_mcp-0.3.0.tar.gz:

Publisher: publish.yml on edtroleis/podman-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file podman_mcp-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: podman_mcp-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 10.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for podman_mcp-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9c7187c156609632c8d420cd9ed2230208051889fc344075e2b272f4a40ad4e2
MD5 a05d6c3e6c88605f6fb282f9e544688e
BLAKE2b-256 cba150769a53651ae748b56ec9e3744dd83d6d6fa09d594c8e40d1e0df1137d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for podman_mcp-0.3.0-py3-none-any.whl:

Publisher: publish.yml on edtroleis/podman-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page