Skip to main content
Glama
TelmanH

Jenkins MCP Server

by TelmanH

Jenkins MCP Server

Read-only, multi-instance Jenkins access for AI assistants: VS Code GitHub Copilot (Agent mode) at work, Claude Code for local testing, or any other MCP client. Large build logs are analysed on the server; the model only receives small, relevant excerpts. A team knowledge base remembers solved problems, so the next analysis starts from what the team already knows.

Two ways to run it

Company use

Local testing / development

Who

everyone who analyses builds at work

developers of this server

Platform

Windows

macOS or Windows

AI client

VS Code GitHub Copilot (Agent mode)

Claude Code (macOS) or VS Code Copilot (Windows)

Jenkins

your company Jenkins

a test Jenkins in Docker (or any reachable one)

Setup

setup\windows\setup.ps1

tests/macos/setup.sh or setup\windows\setup.ps1 -Dev

Step-by-step guide

setup/windows/README.md

tests/README.md

Client config

.vscode/mcp.json, generated by setup.ps1 (token prompts, VS Code secure storage)

macOS: registered by the script (claude mcp add); Windows: .vscode/mcp.json

The server code is the same in both cases. Day-to-day usage: docs/USER_GUIDE.md.

Related MCP server: Debugging MCP Server

Read-only guarantee

The server cannot change anything in Jenkins:

  • Its HTTP session (ReadOnlySession in src/jenkins_mcp/client.py) refuses every method except GET and HEAD before a request leaves the process. A tool that tried to trigger, stop, delete or configure something would fail with "this MCP server is read-only".

  • Credentials are only sent to the configured Jenkins URLs; URLs of other hosts are refused.

  • Every tool that talks to Jenkins is marked readOnlyHint for the AI client. Only draft_kb_entry and propose_kb_update write: one new local file in knowledge/drafts/ each time (never overwrites, never Jenkins), so they are honestly marked as local writes.

  • The only other local writes are the log cache (~/.cache/jenkins-mcp, owner-only permissions).

  • Tested: offline (no non-GET request is ever sent, POST/PUT/PATCH/DELETE blocked) and live against a real Jenkins (all build numbers unchanged after running every tool).

Project layout

jenkins-mcp/
├── src/jenkins_mcp/        SERVER CODE (same on Windows and macOS, installed with pip)
├── config/                 YOUR SETTINGS: *.example templates committed; your yaml/.env are git-ignored
├── knowledge/              TEAM DATA: known issues (Markdown); may also live in its own repo
├── docs/USER_GUIDE.md      how to use it day to day
│
├── setup/windows/          COMPANY: Windows + VS Code Copilot
│   ├── setup.ps1           install script (-Dev: + test tools, for developers)
│   └── README.md           step-by-step guide
├── .vscode/                VS Code: mcp.json = Copilot server (generated, git-ignored; template mcp.example.json),
│                           settings.json = pytest
│
└── tests/                  LOCAL TESTING / DEVELOPMENT (never installed)
    ├── README.md           step-by-step guide: macOS + Claude Code, Windows + VS Code
    ├── macos/setup.sh      macOS: install + Claude Code registration + offline tests
    ├── test_*.py           offline tests (pytest, fake Jenkins)
    ├── fixtures/           sample log + example knowledge base for the tests
    └── live/               real Jenkins in Docker + live check of every tool (run_live.sh / run_live.ps1)

Source package:

src/jenkins_mcp/
├── app.py          FastMCP object, server instructions, shared parameter types
├── main.py         imports tools + prompts, run()  (command: jenkins-mcp)
├── vscode_config.py  writes .vscode/mcp.json (token prompts per instance), called by setup.ps1
├── xmlutil.py      Jenkins XML 1.1 parsing
├── settings.py     paths (JENKINS_MCP_HOME), env tunables
├── config.py       config/jenkins_instances.yaml + config/.env -> Settings, validation, instance lookup
├── client.py       ReadOnlySession (GET/HEAD only), Instance
├── targets.py      job/build/URL resolution
├── text.py         secret masking, output budget, formatting
├── rules/          built-in error/ignore/noise rules (YAML)
├── logs/           download + cache, cleaning, stage detection, error grouping
├── kb/             knowledge base: load entries, match against logs
├── tools/          MCP tools: instances, jobs, builds, logs, artifacts, infra, knowledge
└── prompts.py      analyse_build, document_session

Configuration

Files (templates in config/, your copies are git-ignored):

File

Content

config/jenkins_instances.yaml

Jenkins instances, TLS, log rules, knowledge base folder (template: jenkins_instances.example.yaml)

config/.env

Credentials, one pair per instance (template: .env.example)

Environment variables (set them in config/.env, in the MCP client config, or in the shell):

Variable

Default

Purpose

JENKINS_<NAME>_USER / JENKINS_<NAME>_TOKEN

-

Credentials of instance <name> (upper case, non-alphanumeric -> _). Other names: user_env / token_env in the yaml

JENKINS_MCP_HOME

nearest parent of the working dir with config/jenkins_instances(.example).yaml

Project folder with config/ and knowledge/

JENKINS_MCP_CONFIG

<home>/config/jenkins_instances.yaml

Instance file

JENKINS_MCP_KB_DIR

knowledge.dir in the yaml, else <home>/knowledge

Knowledge base folder (e.g. a private team repo)

JENKINS_MCP_CACHE_DIR

~/.cache/jenkins-mcp

Log cache (contains raw console logs)

JENKINS_MCP_CACHE_MAX_MB

1024

Cache size limit

JENKINS_MCP_MAX_LOG_MB

200

Larger logs keep the first 20 % and the end

JENKINS_MCP_MAX_CHARS

12000

Hard size limit of one tool answer

JENKINS_MCP_JOB_CACHE_S

60

Job lists (list_jobs, overviews) are reused for this long; 0 = off

JENKINS_MCP_LOG_LEVEL

WARNING

Server log level (stderr)

After editing the yaml or .env, call list_instances(reload_config=true); no restart is needed. Config problems are reported by list_instances under config_errors.

Use a dedicated Jenkins user with read permissions only (Overall/Read, Job/Read) for the API token. The server never writes to Jenkins, but a read-only account limits the damage if a token leaks.

Tools (34)

Tool

Purpose

list_instances

instances, token source, connection check (version, user/groups, admin rights, quiet-down), config errors, knowledge base state; reload_config

list_jobs

recursive job list with status/folder/name filter; failing jobs show the last green build

failures_overview

red/yellow jobs in the last N hours across all instances, with the last green build

recent_builds

every build in the last N hours across all instances: result, culprits, long-running builds

get_job

job details, permalinks, recent builds, parameters, children

find_jobs_by_scm

which jobs build a repository (or load a Shared Library), across instances; any URL spelling

get_build_summary

start here: result, params, agent, culprits, downstream builds, pending input, stages, failed stage, known issues, root-cause candidates, tail

get_stage_log

errors and tail of one stage (default: failed stage); exact = per-step log via wfapi (parallel branches)

get_pending_inputs

what a running build waits for (input step); approving stays in the UI

get_log_errors

de-duplicated error groups, annotated by the knowledge base

search_log / get_log_lines

regex search with context / line windows

get_test_failures

failed JUnit cases incl. how long they fail

get_pipeline_info

what actually ran: Jenkinsfile source, git checkouts, Shared Library versions (hint on LF-version mismatch), replay, slowest steps; show_script = executed Jenkinsfile

compare_builds

good vs bad: agent, params, stages, commits (Jenkinsfile/groovy changes flagged), new errors, errors also in good build, env.log diff; pick builds by node (good_on_node/bad_on_node) or take the good build from another instance (other_instance)

get_job_config

config.xml as a summary: SCM, Jenkinsfile path, parameters, triggers, retention, label, build steps, Config File Provider files, credential IDs; raw = masked XML

read_managed_file

content of a Config File Provider file (settings.xml...), secrets masked

get_job_config_history, diff_job_config

who changed the job config and when (Job Config History plugin); semantic + XML diff of two versions or against the live config

list_artifacts, read_artifact, get_env_log

artifact list (sizes, download URL), text artifacts (UTF-8, UTF-16, cp1252), secrets masked

compare_artifacts

artifacts of two builds: added/removed, changed (fingerprint, size, bytes); diff of one text artifact, checksum of a binary

list_workspace, read_workspace_file

files that were not archived, from the job / Pipeline node-block workspace (current state on the agent)

node_health, get_queue

agents (labels, disk, memory, offline reason, clock) and queue

get_node

one node: labels, which build runs on which executor, Java version, config.xml (remote root, launcher, node env vars masked, tool locations)

find_known_issues

match a build or a pasted error text against the knowledge base

get_known_issue, list_known_issues

read / list entries, with how often each matched since the server started

draft_kb_entry

write a new local draft in knowledge/drafts/ (local write, never Jenkins)

propose_kb_update

propose an update of an existing entry (new build, extra regexes) as a new draft next to it (local write)

recurring_errors

errors across the newest builds of a job: regression ("new since #N") vs. also in green builds

Prompts: analyse_build, document_session, morning_report (Copilot: type / and pick mcp.jenkins...; Claude Code: /mcp__jenkins__analyse_build).

All tools are read-only towards Jenkins; see Read-only guarantee.

Knowledge base workflow

  1. Analyse a build. get_build_summary shows known_issues if an entry matches.

  2. When the cause is found and confirmed, run the prompt document_session (or ask the agent). It checks for duplicates and calls draft_kb_entry, or propose_kb_update when an entry already exists. recurring_errors finds red-herring candidates (errors that also occur in green builds).

  3. Review the draft in knowledge/drafts/, move it to knowledge/, commit it to your team's private knowledge repo. The server picks up file changes automatically.

Company knowledge does not belong in this public repository: .gitignore excludes knowledge/KB-*.md and drafts. Keep entries in a private repo and point JENKINS_MCP_KB_DIR (or knowledge.dir) at its checkout.

Format and field reference: knowledge/README.md. Start new entries from knowledge/TEMPLATE.md.

Development

See tests/README.md. Adding a tool: write a function with @mcp.tool(annotations=READ_ONLY) in a module under src/jenkins_mcp/tools/ (for a new module also import it in tools/__init__.py), and add a test to tests/test_tools.py.

Notes and limits

  • Multibranch branch names containing / are addressed with %2F (as list_jobs shows them).

  • Stage line ranges come from console markers; output of parallel branches can interleave (get_stage_log exact=true reads the stage step by step from wfapi instead).

  • Builds still running are not cached on disk; their log is fetched incrementally (only the new part).

  • Downstream builds are recognised from the console line Starting building: <display name> #N. If a job has a custom display name, it cannot be resolved by that name, and the summary says so.

  • Logs larger than JENKINS_MCP_MAX_LOG_MB keep the first 20 % and the end.

  • Log content is untrusted: a log line can contain text that looks like an instruction. The server cannot change Jenkins, so such text cannot trigger actions through it.

Security

See SECURITY.md for the threat model and how to report a vulnerability.

License

MIT © 2026 Telman Huseynli

Roadmap

  • Release 1.1.0: the live Docker test (Jenkins 2.580.1) and a manual Windows / VS Code Copilot run against real instances passed. Set the package status back to 5 - Production/Stable, turn Unreleased in CHANGELOG.md into 1.1.0, tag v1.1.0 and publish a GitHub release.

  • Replace the module-level singletons (config, knowledge base cache, log LRU, job tree cache) with one application context object, and pass log rules into logs/ instead of reading the global config there.

  • CI pipeline on Windows: ruff, mypy, pytest.

  • Read-only plugin tools: installed plugins and versions, plugins with problems (missing dependencies), available updates. /pluginManager/api/json?depth=1 usually needs Overall/SystemRead or Administer: check it with a normal user's token first; without that permission the tools would only return 403.

  • More read tools: views, node env/PATH (system info, needs admin), Jenkinsfile and JCasC history from Git (Bitbucket).

  • Optional HTTP transport for one shared team server (needs authentication / a gateway).

  • Human-in-the-loop write actions (not implemented): plan_* tool -> one-time token -> human confirms -> execute_plan with a separate service account and an allow-list.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    Provides AI assistants with persistent memory of your project architecture, development history, and technical decisions, allowing them to give context-aware coding help without needing repeated explanations.
    16
    61 npm
    2
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables LLMs to automatically diagnose coding errors through codebase search, test execution, and live debugger integration (DAP/V8 CDP). Provides a secure, policy-gated environment for investigating failures while preventing destructive operations.
    9
    ISC
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to access full Datadog observability, including log search, APM trace filtering, smart sampling, and cross-correlation between logs, traces, and metrics.
    23
    1,326 npm
    6
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI coding agents to access evidence-backed repository memory, code graph, project DNA, and deterministic change validation so they understand design decisions, past bugs, and invariants while working.
    1,677 npm
    13
    Functional Source , Version 1.1, ALv2 Future