Portainer 堆栈管理 MCP 服务器

Portainer Stacks 是一个面向 Portainer 实例上 Docker Compose 堆栈管理的 MCP 服务器,提供堆栈与容器操作、环境查看及完整 Portainer API 回退能力,适用于通过 AI 助手进行 DevOps 和容器化应用管理。

  • by Guthman
  • Rust
  • 本地部署
  • 更新于
在 GitHub 查看 Guthman/portainer-mcp

使用说明

portainer-stacks

An MCP server for managing Docker Compose stacks on a Portainer instance. Built against the Portainer 2.39.0 API spec. Exposes 12 typed tools for common stack and container operations plus a generic fallback for full API access.

For broader Portainer coverage beyond stack management, see the official portainer/portainer-mcp.

Why this server?

  • Minimal and focused — purpose-built for stack management
  • Windows, Linux & macOS (arm64 and x86_64)
  • Single static binary — no runtime, no node_modules, trivial to install from pre-built releases
  • Low memory footprint — a few MB vs Node's ~30-50MB baseline; ideal for a process that sits idle between tool calls
  • Instant startup — no module loading delay; relevant since MCP hosts may spawn/kill the process per session
  • MCP-native — includes tool annotations, prompts, and resources

Features

  • List, inspect, create, update, and delete compose stacks
  • Start, stop, and git-redeploy stacks
  • Restart or recreate individual Docker containers (with optional image re-pull)
  • List environments/endpoints
  • Generic request tool for any Portainer API endpoint — if a dedicated tool doesn't cover your use case, the fallback portainer_request tool gives full access to the entire Portainer API
  • API key authentication (no login flow needed)
  • Optional self-signed certificate support

Installation

Docker (easiest)

A multi-arch image (linux/amd64, linux/arm64) is published to GHCR. No local install step — just reference it from your MCP client config (see Usage).

docker pull ghcr.io/guthman/portainer-mcp:latest

Pin to a specific version for reproducibility, e.g. ghcr.io/guthman/portainer-mcp:0.4.1.

Pre-built binaries

Check Releases for pre-built binaries (Windows, Linux musl, macOS — both x86_64 and arm64).

From source

git clone https://github.com/Guthman/portainer-mcp.git
cd portainer-mcp
cargo build --release

The binary will be at target/release/portainer-stacks (or portainer-stacks.exe on Windows).

Verifying what you run

When you configure any MCP server, you're telling your AI assistant to run a binary on your machine with whatever permissions you give it. If that binary gets swapped out — a bad download, a compromised update, or something modifying it on disk — the assistant will run the replacement without question. Most MCP configurations don't have a built-in way to pin to a specific binary hash, so it's worth verifying the file yourself.

This applies to all MCP servers, not just this one.

Release binaries for this project include GitHub Artifact Attestations — signed provenance records that confirm a binary was built by this repo's CI from a specific commit. To verify a downloaded artifact:

gh attestation verify portainer-stacks-v*.tar.gz --owner Guthman

If verification passes, the binary is untampered and matches what the source code produced. It doesn't guarantee the code itself is safe — you should still review what you run — but it closes the gap between "code in the repo" and "binary on your machine."

Configuration

Set these environment variables:

Variable Required Default Description
PORTAINER_API_KEY Yes — Portainer API key (how to create one)
PORTAINER_URL No http://localhost:9000 Portainer instance URL
PORTAINER_INSECURE No false Set to true to accept self-signed TLS certificates
PORTAINER_ENV_DISPLAY No masked How env var values appear in responses: masked (all hidden), filtered (sensitive redacted), full (all visible)
PORTAINER_SENSITIVE_NAMES No — Comma-separated env var names to add as sensitive in filtered mode
PORTAINER_VISIBLE_NAMES No — Comma-separated env var names to force visible in filtered mode

Environment variable display modes

Stack objects and Docker container inspect output include environment variables that often contain secrets (passwords, API keys, tokens, connection strings). By default, all values are masked before they reach the LLM. The same mode applies to env var lists in portainer_request responses (Docker Config.Env, Swarm service specs, stack and edge stack env, Kubernetes container env); other fields in those responses are returned as-is.

Mode Behavior
masked All env var values → [MASKED]
filtered Names matching sensitive patterns → [REDACTED], others shown
full All values in cleartext (use with caution)

In filtered mode, names matching built-in patterns (PASSWORD, SECRET, TOKEN, etc.) and any names listed in PORTAINER_SENSITIVE_NAMES are redacted. Names in PORTAINER_VISIBLE_NAMES override both, so you can exempt specific variables. Priority: explicit visible > explicit sensitive > built-in pattern.

Use the configure-env-display prompt to scan your stacks and get personalized guidance.

Usage

Via Docker

The same config works for any MCP host (Claude Desktop, Claude Code, Cursor, VS Code, etc.). Docker must be installed and running on the machine where the MCP client launches the server.

{
  "mcpServers": {
    "portainer": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "PORTAINER_URL",
        "-e", "PORTAINER_API_KEY",
        "-e", "PORTAINER_INSECURE",
        "-e", "PORTAINER_ENV_DISPLAY",
        "ghcr.io/guthman/portainer-mcp:latest"
      ],
      "env": {
        "PORTAINER_URL": "https://your-portainer:9443",
        "PORTAINER_API_KEY": "your-api-key",
        "PORTAINER_INSECURE": "true",
        "PORTAINER_ENV_DISPLAY": "masked"
      }
    }
  }
}

The -i flag is required (MCP speaks over stdio). --rm cleans up the container when the client disconnects. Forwarding env vars via -e NAME (without =value) pulls them from the env block above — keeping secrets out of args, where some hosts may log them.

With Claude Desktop

Add to your Claude Desktop MCP config (claude_desktop_config.json):

{
  "mcpServers": {
    "portainer": {
      "command": "path/to/portainer-stacks",
      "env": {
        "PORTAINER_URL": "https://your-portainer:9443",
        "PORTAINER_API_KEY": "your-api-key",
        "PORTAINER_INSECURE": "true",
        "PORTAINER_ENV_DISPLAY": "masked"
      }
    }
  }
}

With Claude Code

Add to your .mcp.json:

{
  "mcpServers": {
    "portainer": {
      "command": "path/to/portainer-stacks",
      "env": {
        "PORTAINER_URL": "https://your-portainer:9443",
        "PORTAINER_API_KEY": "your-api-key",
        "PORTAINER_INSECURE": "true",
        "PORTAINER_ENV_DISPLAY": "masked"
      }
    }
  }
}

Tools

Tool Description
list_endpoints List environments/endpoints — call this first to get endpoint IDs
list_stacks List all stacks, optionally filtered
get_stack Get a single stack by ID
get_stack_file Get the compose file content of a stack
create_stack Create a new compose stack from file content
update_stack Update a stack's compose file, env vars, or settings
delete_stack Delete a stack
start_stack Start a stopped stack
stop_stack Stop a running stack
redeploy_git_stack Redeploy a git-based stack (pull latest and redeploy)
restart_container Restart a running Docker container
recreate_container Recreate a container (destroy + create), optionally re-pulling its image
portainer_request Generic API request for any Portainer endpoint

Typical workflow

  1. list_endpoints — get the endpoint_id for your environment
  2. list_stacks — see your stacks
  3. get_stack_file — inspect a stack's compose file
  4. update_stack / redeploy_git_stack — make changes

Roadmap

  • Support for multiple Portainer API versions
  • Automatic tool updates when new Portainer API versions are released
  • Support for more auth methods or credential handling? Better prompts? Let me know!

License

MIT