woodpecker-mcp
An MCP server for Woodpecker CI, generated from the Woodpecker OpenAPI spec with fastmcp and served over streamable HTTP.
The tool surface is a curated allowlist, not the full API: all the reads an agent needs to answer "why is my build red / stuck", plus exactly five write operations (trigger, restart, cancel, approve, decline pipeline). Everything else, repo/secret/cron/agent CRUD, forge and system administration, is not exposed.
Tools
| Area | Tools |
|---|---|
| Repos | list_repos, lookup_repo, get_repo, get_repo_permissions, list_branches, list_pull_requests |
| Pipelines | list_pipelines, get_pipeline, get_pipeline_config, get_pipeline_metadata |
| Pipeline ops (write) | trigger_pipeline, restart_pipeline, cancel_pipeline, approve_pipeline, decline_pipeline |
| Logs | get_step_logs, plain-text step logs, base64-decoded, tailed (default 200 lines) |
| Orgs | lookup_org, get_org, get_org_permissions |
| Queue & agents | get_queue_info, list_agents, get_agent, list_agent_tasks |
| Secrets & registries (metadata only) | list_repo_secrets, list_org_secrets, list_repo_registries, list_org_registries |
Configuration
| Variable | Required | Description |
|---|---|---|
WOODPECKER_SERVER |
yes | Base URL of the Woodpecker server, e.g. https://ci.example.com (/api is appended) |
WOODPECKER_TOKEN |
see below | Personal access token used as a shared fallback for upstream API calls |
WOODPECKER_MCP_READ_ONLY |
no | true/1/yes/on removes the five write tools entirely |
WOODPECKER_MCP_TRANSPORT |
no | http (default) or stdio |
HOST |
no | Bind address (http only), default 0.0.0.0 |
PORT |
no | Bind port (http only), default 8000 |
Multi-client authentication (http)
Each client authenticates as its own Woodpecker user by sending its personal access token as a standard bearer header with every request:
Authorization: Bearer <woodpecker-token>
The token is forwarded upstream for that request only; a shared
httpx2.AsyncClient reads the header per request, so clients never see each
other's credentials. WOODPECKER_TOKEN is optional under http, if set, it is
used as a fallback for requests that carry no bearer token of their own. A
request with neither its own token nor a configured fallback is rejected.
Under the stdio transport there are no per-request headers, so
WOODPECKER_TOKEN is required and always used.
The server performs no authentication of its own beyond forwarding the token,
deploy it on a trusted network (e.g. behind TLS). token fields in upstream
responses (e.g. agent registration tokens, which Woodpecker returns in
cleartext to admin PATs) are redacted before reaching the client.
Running
Docker (streamable HTTP)
Run the server once; each client authenticates per request with its own token,
so no shared WOODPECKER_TOKEN is required:
docker run -p 8000:8000 \
-e WOODPECKER_SERVER=https://ci.example.com \
ghcr.io/rtuszik/woodpecker-mcp:latest
Add -e WOODPECKER_TOKEN=... only if you want a shared fallback token for
clients that connect without one of their own.
The MCP endpoint is http://<host>:8000/mcp (streamable HTTP).
The server keeps no session state, so any number of replicas can run behind
an ordinary load balancer without session affinity. Clients on the
2026-07-28 protocol are sessionless by design; older clients are served in
stateless mode, without an Mcp-Session-Id or a standalone SSE stream.
Connecting a client (remote HTTP)
Point the client at wherever the server is deployed and send your own Woodpecker personal access token as a bearer header. Replace the URL below with your server's endpoint. In Claude Code:
claude mcp add --transport http woodpecker https://your-mcp-host/mcp \
--header "Authorization: Bearer <your-woodpecker-token>"
or in a generic MCP client config:
{
"mcpServers": {
"woodpecker": {
"type": "http",
"url": "https://your-mcp-host/mcp",
"headers": {
"Authorization": "Bearer <your-woodpecker-token>"
}
}
}
}
Every request carries the header, so the server acts as your Woodpecker user for that request only. Different clients can hit the same server with different tokens.
A plain http:// URL works too (e.g. on a trusted LAN without TLS), though
some clients refuse to send an Authorization header over non-HTTPS; prefer
terminating TLS at a reverse proxy for anything exposed beyond localhost.
uvx (stdio)
The package is published to PyPI as
woodpecker-ci-mcp. With
WOODPECKER_MCP_TRANSPORT=stdio the server speaks MCP over stdin/stdout, so a
client can spawn it directly. Register it with e.g. Claude Code:
claude mcp add woodpecker \
--env WOODPECKER_SERVER=https://ci.example.com \
--env WOODPECKER_TOKEN=... \
--env WOODPECKER_MCP_TRANSPORT=stdio \
-- uvx woodpecker-ci-mcp
or in a generic MCP client config:
{
"mcpServers": {
"woodpecker": {
"command": "uvx",
"args": ["woodpecker-ci-mcp"],
"env": {
"WOODPECKER_SERVER": "https://ci.example.com",
"WOODPECKER_TOKEN": "...",
"WOODPECKER_MCP_TRANSPORT": "stdio"
}
}
}
}
In stdio mode there are no per-request headers, so the configured
WOODPECKER_TOKEN is always used.
Development
uv sync # install
uv run pytest # tests
mise run check # format, lint, typecheck, tests
The bundled spec lives at src/woodpecker_mcp/openapi.yaml; the allowlist that
defines the tool surface is src/woodpecker_mcp/spec.py.
Metadata
Release files for woodpecker-ci-mcp 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| woodpecker_ci_mcp-0.5.0.tar.gz | 20.4 kB | Without provenance | Details for woodpecker_ci_mcp-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| woodpecker_ci_mcp-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for woodpecker_ci_mcp-0.5.0-py3-none-any.whl |
Total release size: 43.3 kB
Release files / woodpecker_ci_mcp-0.5.0.tar.gz
| Download URL | woodpecker_ci_mcp-0.5.0.tar.gz |
|---|---|
| Size | 20.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c19330f8a0744fe7128a58b9efb09683a9f3813858e45ba7e356a9dabd229cd4
|
|
BLAKE2b-256 checksum How to use checksums |
948b9f4b6f57cc4c32727981606b3b67fec001a71d151384a47023a65828e5ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / woodpecker_ci_mcp-0.5.0-py3-none-any.whl
| Download URL | woodpecker_ci_mcp-0.5.0-py3-none-any.whl |
|---|---|
| Size | 22.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1bc2c07771f5d578387ca20b6a12a537f405fc9d511a89243544361101b0c69
|
|
BLAKE2b-256 checksum How to use checksums |
427e63a4df1a3173b14dc0e48bac6dbd91d898d34bccb7aaf2e95e0410c977ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for woodpecker-ci-mcp 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.