Jenkins Mcp Go — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Jenkins Mcp Go (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<!-- markdownlint-disable MD033 MD041 --> <div align="center">
A focused, fast Model Context Protocol (MCP) server for Jenkins, written in Go.
Connect Jenkins to Claude Desktop, Claude Code, Cursor, or any MCP-compatible AI agent: fetch console logs, inspect pipeline stages, parse JUnit and Ginkgo test reports, diff two builds, rank flaky tests, trigger and abort builds, and manage the build queue — all over a single MCP stdio transport, from one static Go binary.
</div>
Most Jenkins integrations expect a human at a keyboard. LLM agents need something different: small, structured responses; a clear path from "build failed" to "here is the failing line"; and the ability to grep a multi-gigabyte console log without re-downloading it on every question.
jenkins-mcp-go is built for that workflow:
(trigger_build, stop_build, cancel_queue_item) are gated by JENKINS_MCP_READONLY: set the env var and the server registers only the read surface.
API token, configured by environment variables. No multi-tenant surface, no credential vault to misuse.
actually ask — "what changed between build A and B?" (compare_builds), "which tests in this job are flaky?" (get_flaky_candidates), "what commits and files touched this build?" (get_scm_context) — instead of mirroring Jenkins endpoints one-for-one.
a cap. get_console_log_path returns the on-disk path of a finished build's log so the agent can Read/Grep/Bash it natively instead of streaming gigabytes through MCP.
The cache is keyed by job path + build number, capped by total size, and evicted by LRU mtime.
parse /wfapi/describe, /testReport/api/json, and Ginkgo's Summarizing N Failure block so the agent gets pre-digested failure information.
| Tool | Purpose |
|---|---|
health_check | Validate the server's setup: Jenkins reachability and version, authenticated user, CSRF crumb issuer, Pipeline/JUnit plugin presence, online/offline node counts, clock skew, and the effective config the process is running with. |
get_plugin_versions | List installed Jenkins plugins with versions, pinned flag, and pending-update flag. Optional name_filter (RE2) and include_inactive. 403 degrades to a clear hint. |
whoami_can | Probe a job for the configured token's effective Read / Build / Cancel / Configure permissions via read-only GET requests. Useful up-front to avoid a 403 on a trigger or cancel. Stays read-only even when JENKINS_MCP_READONLY=false. |
list_jobs | Enumerate jobs and folders under a path (or root). Optional recursion and case-insensitive RE2 name filter; capped at 500 entries. |
list_branches | Enumerate the branches of a WorkflowMultiBranchProject with per-branch last-build number, result, duration, and timestamp. Optional name_filter (RE2) and healthy_only. |
get_console_log | Tail the build's /consoleText. Defaults to last 500 lines; pass tail_lines: -1 for the full log. |
get_console_log_path | Force-cache the full log for a completed build and return its on-disk path so the agent can Read/Grep/Bash it natively. |
search_console_log | RE2 regex search over the console log with line-number-aware context windows. |
tail_running_build | Capped, offset-tracked tail of an in-flight build's console via Jenkins' progressiveText. Echo Next since_byte back to paginate. Never writes to the on-disk cache. |
get_build_info | Pretty-printed build summary: result, duration, parameters, change set. |
get_build_environment | Three sections for a build: Cause (trigger reason verbatim), Parameters (masked secrets surfaced as (masked)), and Injected Env Vars via EnvInject. Optional RE2 name_filter narrows the env-var section. Degrades on EnvInject 404. |
get_scm_context | Per-commit history for one build: commit id, author, timestamp, message subject, and each commit's touched paths with A/M/D edit codes. Pipeline change sets are flattened with per-set headers. Optional RE2 path_filter. |
last_green_build | Report the most recent successful build of a job. Returns number, finish time (UTC), and URL — the start point for bisect-from-green. |
changes_since_last_green | Union the commits across every completed build since the job's last green. Walks previousCompletedBuild, dedupes by commitId, supports path_filter and max_commits. Surfaces 'all green' and wide-window footers. |
compare_builds | Diff two builds of the same job across result, duration, parameters, SCM commits, pipeline stages, and JUnit tests. The agent answers "what changed between A and B?" in one call. |
get_pipeline_stages | List Declarative/Scripted Pipeline stages via /wfapi/describe with status and duration. |
get_stage_log | Fetch a single pipeline stage's log via /execution/node/<id>/wfapi/log. |
get_pipeline_script | Return the Jenkinsfile a specific build actually ran. Tries the Replay plugin first (build-pinned), falls back to config.xml (job-level — provenance surfaced). Returns SCM coords as a hint for Pipeline-from-SCM jobs. |
get_test_report | Structured JUnit results from /testReport/api/json, with failed cases and head+tail of stack traces. |
get_flaky_candidates | Rank flaky tests across the latest N completed builds of one job by counting pass↔fail flips. Returns a sorted table of test name, flip count, pass/fail tallies, and last-seen build. |
get_test_history | Per-build trend of a single test across the last N completed builds — the follow-up to get_flaky_candidates once a suspect is known. Timeline (build #, result, status, duration, error head) plus a summary of counts and flips. |
find_test_by_name | Locate which job runs a test whose full name contains a substring. Walks list_jobs(recursive) under folder_path, fans out per-job probes against lastCompletedBuild/testReport with a 5s per-job timeout, renders a sorted table of hits. |
find_recent_failures | Survey failed builds across the jobs under folder_path within a lookback window. Per-job probe of the last 5 builds; filters by since (24h default; supports Nd) and result_filter (FAILURE/UNSTABLE/ABORTED/ANY_NON_SUCCESS). |
list_pr_builds | List all builds for a PR on a WorkflowMultiBranchProject. Probes the common PR branch naming conventions in parallel (PR-N, pull/N/head, change-N, pr/N) and renders the build history for the first match. |
get_ginkgo_failure_summary | Parse Ginkgo's Summarizing N Failure block and surface the first [ERROR] tagged with each spec name. |
list_nodes | List Jenkins agents/nodes with status, executor counts, labels, and monitor summaries. |
get_node | Per-node detail: status, per-executor idle state, labels, full monitor data. |
list_queue | List pending Jenkins queue items with the block reason for each. |
cancel_queue_item | Drop a pending queue item by id. Mutating; suppressed when JENKINS_MCP_READONLY is set. |
trigger_build | Queue a build, optionally with parameters; can block until the build is assigned a number. Mutating. |
stop_build | Abort a running build. Mutating. |
Build-targeted tools take a job_path (slash-separated, e.g. Builds/team/job-name) and an optional build_number (0 or omitted = lastBuild). A URL like https://jenkins.example.com/job/Builds/job/team/job/job-name/86/ becomes job_path="Builds/team/job-name", build_number=86. list_jobs takes a folder_path in the same slash-separated form (empty = root).
See docs/TOOLS.md for the full parameter reference.
Grab the archive for your OS and architecture from the Releases page and put the jenkins-mcp binary on your PATH.
go installgo install github.com/2001adarsh/jenkins-mcp-go@latestThe binary lands in $(go env GOBIN) (or $(go env GOPATH)/bin).
Pre-built multi-arch images are published to GitHub Container Registry:
docker pull ghcr.io/2001adarsh/jenkins-mcp-go:latestTags:
:latest — most recent release:vX.Y.Z — pinned to a specific release:vX.Y.Z-amd64 / :vX.Y.Z-arm64 — per-arch (the unsuffixed tags above are multi-arch manifests; docker pull resolves the right one automatically)The image is built on gcr.io/distroless/static:nonroot — runs as a non-root user, ships with CA roots so HTTPS to Jenkins works out of the box, and is under 20 MB compressed. See the Docker MCP client setup section for a docker run-based Claude Desktop config.
git clone https://github.com/2001adarsh/jenkins-mcp-go.git
cd jenkins-mcp-go
make build
./bin/jenkins-mcp -h 2>/dev/null || true # the server speaks MCP over stdio; -h prints nothingConfiguration is read from the environment at startup. There is no config file and no command-line flags — keep credentials out of process arguments.
| Variable | Required | Default | Description |
|---|---|---|---|
JENKINS_URL | yes | — | Base URL of the Jenkins instance, e.g. https://jenkins.example.com. |
JENKINS_USER | yes | — | Username for HTTP Basic auth. |
JENKINS_API_TOKEN | yes | — | API token (not the password). Generate one at /me/configure in your Jenkins UI. |
JENKINS_MCP_CACHE_DIR | no | $XDG_CACHE_HOME/jenkins-mcp (or ~/.cache/jenkins-mcp) | Where finished build logs are cached on disk. |
JENKINS_MCP_CACHE_MAX | no | 1073741824 (1 GiB) | Soft cap on cache size in bytes. Evicts oldest-mtime files first. |
JENKINS_MCP_TIMEOUT | no | 90s | HTTP timeout (Go duration: 30s, 2m, etc.). |
JENKINS_MCP_DEBUG | no | unset | When set to any non-empty value, emits one stderr line per outbound Jenkins request and cache event. See docs/DEBUGGING.md. |
JENKINS_MCP_READONLY | no | unset | When truthy (1/true/yes, case-insensitive), suppresses registration of any tool that mutates Jenkins state. Active mode is logged at startup. |
Note — JENKINS_API_TOKEN should be a Jenkins API token, not your account password. In Jenkins, navigate to your user menu → Configure → API Token → Add new Token.The server speaks MCP over stdio. Hook it up by adding an entry to your client's MCP server configuration.
<details open> <summary><strong>Claude Desktop</strong> — <code>~/Library/Application Support/Claude/claude_desktop_config.json</code> (macOS) or <code>%APPDATA%\Claude\claude_desktop_config.json</code> (Windows)</summary>
{
"mcpServers": {
"jenkins": {
"command": "/usr/local/bin/jenkins-mcp",
"env": {
"JENKINS_URL": "https://jenkins.example.com",
"JENKINS_USER": "your-username",
"JENKINS_API_TOKEN": "your-api-token"
}
}
}
}</details>
<details> <summary><strong>Claude Desktop via Docker</strong> — same config file, no binary on PATH required</summary>
{
"mcpServers": {
"jenkins": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "JENKINS_URL",
"-e", "JENKINS_USER",
"-e", "JENKINS_API_TOKEN",
"ghcr.io/2001adarsh/jenkins-mcp-go:latest"
],
"env": {
"JENKINS_URL": "https://jenkins.example.com",
"JENKINS_USER": "your-username",
"JENKINS_API_TOKEN": "your-api-token"
}
}
}
}-i keeps stdin open (MCP speaks stdio); --rm cleans up the container after Claude Desktop disconnects. The console-log cache lives inside the container by default, so it's lost on restart — add -v "$HOME/.cache/jenkins-mcp:/home/nonroot/.cache/jenkins-mcp" and -e XDG_CACHE_HOME=/home/nonroot/.cache to the args array if you want the cache to survive across sessions.
</details>
<details> <summary><strong>Claude Code</strong> (CLI)</summary>
claude mcp add jenkins /usr/local/bin/jenkins-mcp \
--env JENKINS_URL=https://jenkins.example.com \
--env JENKINS_USER=your-username \
--env JENKINS_API_TOKEN=your-api-token</details>
<details> <summary><strong>Cursor / Continue / any other MCP client</strong></summary>
Any client that supports stdio MCP servers will accept a configuration of the form:
{
"command": "jenkins-mcp",
"args": [],
"env": {
"JENKINS_URL": "https://jenkins.example.com",
"JENKINS_USER": "your-username",
"JENKINS_API_TOKEN": "your-api-token"
}
}</details>
Once the server is registered, ask your agent things like:
→ calls list_jobs with folder_path: "Builds/team", recursive: true, name_filter: "integration".
→ calls get_build_info.
→ calls get_console_log with tail_lines: 200.
→ calls search_console_log with pattern: "panic|fatal", context_lines: 5.
→ calls compare_builds with build_a: 91, build_b: 92.
→ calls get_flaky_candidates.
→ calls get_scm_context with path_filter: "^internal/auth/".
→ calls get_ginkgo_failure_summary.
→ calls get_console_log_path; the agent then uses its own Read/Grep/Bash tools on the returned path.
Only finished builds are cached (the writer requires Jenkins' Finished: marker), and the cache is evicted by LRU mtime once it exceeds JENKINS_MCP_CACHE_MAX. Files live in JENKINS_MCP_CACHE_DIR.
output, error messages, or cached files.
directory is the only path the server writes to.
If you find a security issue, please follow SECURITY.md rather than opening a public issue.
make build / test / lint / fmt. See CONTRIBUTING.md for the full contributor guide and docs/DEBUGGING.md for how to exercise the server locally with MCP Inspector.
/api/json,/consoleText, /wfapi/describe, /testReport/api/json endpoints. Pipeline-specific tools require the Pipeline plugin.
github.com/modelcontextprotocol/go-sdk v1.6+.How jenkins-mcp-go compares to other ways of exposing Jenkins to an LLM:
| Option | Runtime | Read-only mode | Console-log cache | Pipeline / JUnit / Ginkgo tools |
|---|---|---|---|---|
| `jenkins-mcp-go` (this repo) | Single static Go binary | Yes, gated by JENKINS_MCP_READONLY | LRU disk cache for finished builds | First-class, pre-digested responses |
| Python-based Jenkins MCP servers | Python interpreter + deps | Varies by project | Typically none — re-fetches each call | Usually raw /api/json pass-through |
| Generic HTTP-to-MCP gateways | Node / Python runtime | Whatever the gateway enforces | None | None — agent has to parse raw JSON |
Direct curl / shell tools from the agent | Shell | Manual | None | None — agent reasons over raw text |
If you want a small, predictable surface tailored to "the agent is debugging a Jenkins build", this project is for you. If you need a generic JSON proxy or multi-tenant credential routing, a generic HTTP-MCP gateway is a better fit.
Install the jenkins-mcp binary, then add it to your Claude Desktop or Claude Code MCP configuration with your JENKINS_URL, JENKINS_USER, and JENKINS_API_TOKEN. See MCP client setup above for the exact JSON / CLI snippets.
Yes. Any MCP client that supports stdio servers will accept the same command + env configuration shown in the MCP client setup section.
Reads are always on. Write tools (trigger_build, stop_build, cancel_queue_item) are registered by default but can be suppressed entirely by setting JENKINS_MCP_READONLY=1 — the server then never registers a mutating tool, so an agent literally cannot call one.
No extra plugin is required for the core read tools — they hit standard Jenkins endpoints. Pipeline-specific tools (get_pipeline_stages, get_stage_log) require the Pipeline plugin, which most Jenkins installations already have.
Yes. Use get_console_log_path to force-cache the full log for a finished build to disk; the tool returns a local path the agent can then Read, Grep, or Bash natively. The cache is LRU-evicted and capped by JENKINS_MCP_CACHE_MAX.
Yes. get_ginkgo_failure_summary parses Ginkgo's Summarizing N Failure block and surfaces the first [ERROR] line tagged with each spec name plus surrounding context — much faster than asking the agent to scan the whole log.
The server uses a single Jenkins user's API token (not a password), confined to one JENKINS_URL. Combine with JENKINS_MCP_READONLY=1 and a least-privilege Jenkins user for the safest default. See SECURITY.md for the full threat model.
MIT © Adarsh Singh
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.