Back to Browse

Woodpecker Ci MCP Server

by Ni C
Developer ToolsLow Risk10.0MCP RegistryLocal
Free

Server data from the Official MCP Registry

Read Woodpecker CI repositories, pipelines and logs, and drive builds, secrets and crons

About

Read Woodpecker CI repositories, pipelines and logs, and drive builds, secrets and crons

Security Report

10.0
Low Risk10.0Low Risk

Valid MCP server (1 strong, 1 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry. Trust signals: trusted author (11/11 approved).

5 files analyzed · 1 issue found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

file_system

Check that this permission is expected for this type of plugin.

What You'll Need

Set these up before or after installing:

Root URL of the Woodpecker server, e.g. https://woodpecker.example.comOptional

Environment variable: WOODPECKER_URL

Personal access token from the Woodpecker user settingsRequired

Environment variable: WOODPECKER_TOKEN

Set to true to register only the read tools (default: false)Optional

Environment variable: WOODPECKER_READ_ONLY

Comma-separated tool names or list_* prefixes to register; 'essential' selects a curated preset (default: all tools)Optional

Environment variable: WOODPECKER_ALLOW_TOOLS

Comma-separated tool names or list_* prefixes to remove from whatever the allow list leftOptional

Environment variable: WOODPECKER_DENY_TOOLS

Set to true to accept a self-signed certificate from the Woodpecker server (default: false)Optional

Environment variable: WOODPECKER_INSECURE_TLS

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-ni-c-woodpecker-ci-mcp": {
      "env": {
        "WOODPECKER_URL": "your-woodpecker-url-here",
        "WOODPECKER_TOKEN": "your-woodpecker-token-here",
        "WOODPECKER_READ_ONLY": "your-woodpecker-read-only-here",
        "WOODPECKER_DENY_TOOLS": "your-woodpecker-deny-tools-here",
        "WOODPECKER_ALLOW_TOOLS": "your-woodpecker-allow-tools-here",
        "WOODPECKER_INSECURE_TLS": "your-woodpecker-insecure-tls-here"
      },
      "args": [
        "-y",
        "@ni-c/woodpecker-ci-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

woodpecker-ci-mcp

CI npm version npm downloads node license container docs sponsor

A Model Context Protocol (MCP) server for Woodpecker CI, the lightweight container-native CI engine — it runs your pipelines, and this reads and drives them.

Lets MCP clients like Claude Code, Claude Desktop or Codex see which pipelines failed, read the build log of the step that broke, and act on it — restart it, cancel a runaway, approve a blocked one, rotate a secret, fix a cron — with the irreversible operations behind a confirmation token and the write tools switchable off entirely.

71 tools is the ceiling, not the floor: WOODPECKER_ALLOW_TOOLS=essential registers a curated eight instead, and a model picks the right tool far more reliably from eight than from 71 — see choosing which tools load.

Finding a failed pipeline, reading the failing step's log, and restarting it

What makes it different

It covers the whole API, not the read half. Repositories, pipelines, logs, secrets, registries, crons, organizations, users, agents, forges, the queue and the log level — 71 tools against Woodpecker 3.18.0. The point of an MCP server for a CI system is doing something about what it tells you.

Logs arrive as text. Woodpecker returns a step's output as an array of base64-encoded chunks with line numbers. get_step_logs decodes them, puts them back in order, reports the step's exit code, and returns the end of the log by default — a failing step explains itself in its last lines, and the first 4000 lines of npm ci answer nothing.

Agent tokens do not reach the model. GET /agents returns every agent's token in clear text, and that token is enough to attach a machine to the server and receive pipeline workloads with their secrets. Listing agents through this server redacts it. create_agent still returns one — that is the only way to get it — and says what it is.

It knows where this API is sharp. /version and /healthz sit outside the /api prefix that the Swagger document claims for them, so GET /api/version returns the web UI with HTTP 200 rather than a 404; a repository that exists in the forge is a 404 here until it is activated; perPage above 50 is clamped without a word; a cron schedule is five fields, not six; and a secret with no event list is refused, because the defaults people expect live in the web UI, not in the API.

Requirements

  • Node.js ≥ 22
  • A Woodpecker personal access token — your user settings, "CLI and API". There are no scopes: the token carries the full authority of your account.

Configuration

VariableRequiredDescription
WOODPECKER_URLyesRoot URL of the server, e.g. https://woodpecker.example.com
WOODPECKER_TOKENyesPersonal access token from your user settings
WOODPECKER_READ_ONLYnotrue registers only the 34 read tools
WOODPECKER_ALLOW_TOOLSnoComma-separated tool names, list_* prefixes, or essential for a curated preset
WOODPECKER_DENY_TOOLSnoSame syntax; removed from whatever WOODPECKER_ALLOW_TOOLS left
WOODPECKER_INSECURE_TLSnotrue accepts self-signed certificates (scoped to this connection)

WOODPECKER_URL is the server root, not the API root: https://woodpecker.example.com, not https://woodpecker.example.com/api. Both are accepted — the suffix is trimmed — because the Swagger page spells every example the long way.

Use https://. Over plain http the token travels unencrypted; the server prints a warning unless the host is local. For self-signed certificates prefer a proper internal CA over WOODPECKER_INSECURE_TLS.

Without configuration the server still starts and lists its tools (so registries and inspectors can introspect it); every call then fails with setup instructions instead of reaching the API. get_server_info works without a token, which makes it the first thing to call when nothing else does: if it answers, WOODPECKER_URL is right and the problem is the token.

Admin-only tools. Woodpecker inherits repository and organization permissions from the forge, and reserves users, agents, forges, the queue and the log level for instance administrators. Those tools are registered for everyone and answer 403 for accounts that may not use them; get_current_user reports which kind of account the token belongs to, and WOODPECKER_DENY_TOOLS is the tidy way to stop offering them at all.

Choosing which tools load

WOODPECKER_ALLOW_TOOLS and WOODPECKER_DENY_TOOLS take comma-separated tool names; a trailing * matches a whole family. essential is a curated preset — list_repositories, get_repository, list_pipelines, get_pipeline, get_step_logs, trigger_pipeline, restart_pipeline and cancel_pipeline — marked as such in the tool reference.

WOODPECKER_ALLOW_TOOLS=essential
WOODPECKER_ALLOW_TOOLS=list_*,get_pipeline,get_step_logs
WOODPECKER_DENY_TOOLS=delete_*,pause_queue,create_user,update_user

With 71 tools this is not a nicety. Every visible tool costs context on every request, and a server that offers delete_forge next to get_step_logs is a server nobody should point at their production CI without narrowing it first.

An entry that matches no tool aborts startup and names it, so a typo cannot silently hide a tool — an absent tool is not something anyone traces back to an environment variable. A filtered tool is never registered, so it is absent from tools/list and unknown to tools/call alike, exactly like a write tool under WOODPECKER_READ_ONLY.

If you run several of these servers at once, mcp-hub is the other answer — its /hub endpoint replaces every server's tools with six meta-tools.

Installation

Claude Code

claude mcp add woodpecker-ci -- npx -y @ni-c/woodpecker-ci-mcp

Claude Desktop

{
  "mcpServers": {
    "woodpecker-ci": {
      "command": "npx",
      "args": ["-y", "@ni-c/woodpecker-ci-mcp"],
      "env": {
        "WOODPECKER_URL": "https://woodpecker.example.com",
        "WOODPECKER_TOKEN": "…"
      }
    }
  }
}

Codex

[mcp_servers.woodpecker-ci]
command = "npx"
args = ["-y", "@ni-c/woodpecker-ci-mcp"]
env = { WOODPECKER_URL = "https://woodpecker.example.com", WOODPECKER_TOKEN = "…" }

Docker

docker run --rm -i \
  -e WOODPECKER_URL=https://woodpecker.example.com \
  -e WOODPECKER_TOKEN=… \
  ghcr.io/ni-c/woodpecker-ci-mcp

If your Woodpecker is only resolvable through your host's split DNS, add --dns <resolver>: a container does not inherit the host's resolver configuration, and the public answer for an internal name is usually an address that does not respond.

Tools

Read tools are always registered. 🛡 marks the ones that need an instance administrator; 👤 marks the ones that ask for a confirmation token before acting. The tool reference has the parameters.

Repositories

ToolDescription
list_repositoriesRepositories, optionally including ones not yet activated
get_repositoryOne repository with all its Woodpecker settings
lookup_repositoryTurns owner/name into the id every other tool takes
get_repository_permissionsWhat this account may do here — answers "why that 403"
list_repository_branchesBranches, as Woodpecker sees them in the forge
list_pull_requestsOpen pull requests and their index
activate_repositoryTurns Woodpecker on for a forge repository
update_repository 👤Config file, timeout, visibility, approval mode; 👤 to grant trust
repair_repository 👤Re-installs the webhook; 👤 only for the whole-instance variant
move_repository 👤Follows a repository that moved in the forge
chown_repositoryTakes ownership, so the token Woodpecker uses is yours
delete_repository 👤Removes it from Woodpecker with all its history

Pipelines and logs

ToolDescription
list_pipelinesPipelines with branch, event, status and time filters
get_pipelineOne pipeline with its workflows, steps and step ids
get_pipeline_configThe YAML this run was built from
get_pipeline_metadataThe CI_* environment a step saw, and the previous run
list_queued_pipelinesWhat is waiting, across all repositories
get_step_logsA step's output as text, tail first, with its exit code
trigger_pipelineStarts a pipeline on a branch
restart_pipelineRuns an existing one again, at the same commit
cancel_pipelineStops a pending or running pipeline
approve_pipeline 👤Releases a blocked one — it runs fork code with your secrets
decline_pipelineRefuses a blocked one
delete_pipeline 👤Deletes a pipeline and its logs
delete_step_logs 👤Deletes one step's output — for when a step printed a secret
delete_pipeline_logs👤 The same for every step of a pipeline

Secrets, registries and crons

scope selects the level: repository, organization or global.

ToolDescription
list_secretsSecrets at one level. Values are never returned by Woodpecker
get_secretOne secret's events, images and note
create_secretCreates one. At least one event is required
update_secret 👤Rotates the value (👤), or replaces the event and image lists
delete_secret 👤Deletes one; pipelines using it run without it
list_registriesContainer registry credentials at one level
get_registryOne entry. The password is stripped by Woodpecker
create_registryStores credentials for pulling private images
update_registryChanges username or password
delete_registry 👤Removes them
list_cronsScheduled runs and when each fires next
get_cronOne cron job
create_cronSchedules a run — five-field cron or @daily
update_cronChanges it, including enabled to pause without deleting
run_cronRuns it now, without touching the schedule
delete_cron 👤Removes the schedule

Accounts, organizations and instance administration

ToolDescription
get_current_userWhich account the token belongs to, and whether it is admin
get_pipeline_feedThe latest pipeline of every visible repository, in one call
list_organizations 🛡Organizations known to the instance
get_organizationOne organization
lookup_organizationTurns a name into the id org-level tools need
get_organization_permissionsMember and admin flags for this account
delete_organization 🛡👤Removes it with its org-level secrets, registries and agents
list_users 🛡Accounts that have ever logged in
get_user 🛡One account — forge_id is required
create_user 🛡Pre-creates a record, e.g. to grant admin before first login
update_user 🛡👤Changes email; 👤 to grant admin
delete_user 🛡👤Removes an account — transfer its repositories first
list_agents 🛡Build agents, with tokens redacted
get_agent 🛡One agent, token redacted
list_agent_tasks 🛡What an agent is running right now
create_agent 🛡Registers one and returns its token — a credential
update_agent 🛡Rename, relabel, or drain with no_schedule
delete_agent 🛡👤Removes it and invalidates its token
list_forges 🛡Forges this instance authenticates against
get_forge 🛡One forge; the OAuth secret is never returned
create_forge 🛡Adds a forge
update_forge 🛡👤Changes one — a wrong value locks everyone out
delete_forge 🛡👤Removes one
get_server_infoVersion and health. Works without a token
get_queue_info 🛡The server-side queue and agent statistics
get_log_level 🛡Current server log level
pause_queue 🛡👤Stops scheduling for the whole instance
resume_queue 🛡Starts it again
set_log_level 🛡👤Changes it; 👤 to silence the server

Not exposed, on purpose

  • POST/DELETE /user/token. They return and rotate the personal access token of the account this server authenticates as. A tool that hands the model its own credential is not a feature, and one that invalidates the server's own configuration mid-session is worse. The web UI does both, in front of a person.
  • POST /hook. The forge webhook endpoint. Calling it means forging a push event, which is a way to run a pipeline while making it look like someone committed something. trigger_pipeline is the honest version.
  • /debug/pprof/*. Nine endpoints of Go profiling data. A heap dump is not something to put in a model's context.
  • /stream/events and /stream/logs. Server-sent event streams do not fit a request/response tool. Poll get_pipeline instead.
  • Badge endpoints. They return SVG and XML for embedding, not information.

Safety

  • Twenty operations are two-step. Every delete_*, plus move_repository, the whole-instance repair_repository, update_forge, pause_queue and approve_pipeline — and four more only in the direction that escalates: update_user granting admin, update_repository granting a trusted_* flag, update_secret overwriting a value, and set_log_level silencing the server. The first call returns a short-lived confirmation token bound to those exact arguments; only a second call carrying it acts. A token for one repository is not a token for another, and a token for one tool is not a token for another.
  • Agent tokens are redacted on read — see above. create_agent is the exception, by necessity.
  • Secret values and registry passwords are never returned, and not because this server hides them: Woodpecker strips them from every response, including the one immediately after creating them. Store the value somewhere else too.
  • Build logs, commit messages and pipeline metadata are marked as untrusted data, because they are written by whoever can push to the repository. Confirmation prompts never quote anything that came from the API.
  • Error bodies are truncated, HTML error pages are dropped, and every response has a byte ceiling enforced while it streams. Log output has a much smaller budget of its own, and says when it was cut.
  • WOODPECKER_READ_ONLY=true does not register the write tools at all, and WOODPECKER_DENY_TOOLS cuts finer along the same line — a filtered tool is never built, not refused at call time.
  • The token is deleted from process.env once it has been read, is never sent to a redirect target, and is never echoed into an error message.

Development

npm install
npm run lint && npm run build && npm run test:coverage

Releasing

  1. Add the CHANGELOG entry and bump package.json.
  2. npm run lint && npm run build && npm run test:coverage
  3. Commit, then push a signed tag: git tag -s vX.Y.Z -m "vX.Y.Z" && git push origin main vX.Y.Z

The release workflow publishes to npm (Trusted Publishing, with provenance), creates the GitHub release from the CHANGELOG section and updates the MCP Registry entry.

Reviews

No reviews yet

Be the first to review this server!