Releases: ni-c/woodpecker-ci-mcp
Releases · ni-c/woodpecker-ci-mcp
Release list
v0.1.0
First public release.
Added
- MCP server for the Woodpecker CI API, verified
against Woodpecker 3.18.0. - 71 tools covering the whole API: repositories, pipelines, build logs, secrets,
registries, cron jobs, organizations, users, agents, forges, and the server
queue and log level. get_step_logsdecodes what the API actually returns — an array of
base64-encoded chunks — reassembles it in line order, reports the step's exit
code, and returns the end of the log by default, because that is where a
failing step explains itself.- Secrets and registries exist at repository, organization and instance level in
Woodpecker; here that is ascopeparameter on five tools each rather than
fifteen tool names. WOODPECKER_ALLOW_TOOLS/WOODPECKER_DENY_TOOLSnarrow the tool list by name
orlist_*prefix, andessentialselects the eight tools that cover finding
a repository, reading its pipelines and logs, and running one again.WOODPECKER_READ_ONLY=trueregisters only the 34 read tools; the 37 write
tools never reach the client's tool list.- Fifteen operations that cannot be undone — every
delete_*, plus
move_repository, the whole-instancerepair_repository,update_forgeand
pause_queue— are two-step: the first call returns a short-lived
confirmation token bound to those exact arguments.
Security
- Agent tokens are redacted on read. The Woodpecker API returns each agent's
token in clear text fromGET /agents, including the list call, and that token
is enough to attach a machine to the server and receive pipeline workloads with
their secrets.list_agents,get_agentandupdate_agentreplace it;
create_agentstill returns it, because that is the only way to get it, and
says what it is. - Build logs, commit messages and pipeline metadata are marked as untrusted
content — all of it is written by whoever can push to the repository. - The access token is deleted from the environment after start-up, never sent to
a redirect target, and never echoed into an error message. - Results are budgeted: list results drop whole entries rather than overflowing
the model's context, and logs are capped separately and far lower. Single
objects are budgeted too, by shortening the longest text anywhere in the tree
and then dropping entries from the longest list, so an oversized answer comes
back smaller rather than not at all. - Twenty operations are two-step, not fifteen.
approve_pipelinejoined them
outright — a blocked pipeline is usually one from a fork, approving it runs
that fork's code with the repository's secrets, and the model deciding whether
to approve is typically holding a build log written by whoever opened the pull
request. Four more are two-step only in the direction that escalates:
update_usergrantingadmin,update_repositorygranting atrusted_*
flag,update_secretoverwriting a value that cannot be recovered, and
set_log_levelsilencing the server. The reverse of each, and every other
field, still applies on the first call. - Credential-shaped fields are scrubbed from every pass-through result, not
just the agent token that is known to leak today. Which fields Woodpecker's Go
models serialize is not this server's decision, and a forge addon or a reverse
proxy can reshape a body; a field namedpassword,client_secret,
private_keyortokenis now redacted wherever it appears.create_agentis
the one deliberate exception. - Build output is stripped of terminal control sequences. A step's stdout is
whatever its container wrote — ANSI colour, cursor movement, progress bars that
rewrite their own line, and sometimes raw binary. None of it survives as
meaning in a JSON result, all of it costs budget, and the escape sequences are
a rendering vector in whatever terminal displays the answer. - The invariant that no attacker-controlled prose reaches a confirmation prompt
is now enforced where the interpolation happens, rather than resting on three
input-schema regexes two files away. - Repository-controlled text carries the untrusted-content marker in every result
that returns it, including the pipeline echoed back bytrigger_pipeline,
restart_pipeline,approve_pipeline,decline_pipelineandrun_cron, the
instance-wide pipeline queue, and forge branch names. - The fatal-error handler prints the message and stack rather than the error
object, whosecausechain can carry the failed request's headers.