Skip to main content
Glama
manjunath031984

Jenkins MCP Server

README.md
# Jenkins MCP Server

A production-ready [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the Jenkins REST API as a rich set of structured tools, with first-class support for the `jenkins-terraform-gcp:1.1` Docker image (Terraform + GCP aware log inspection).

Built with **Python 3.13**, **FastMCP**, **requests** and **python-dotenv**.

## Features

- 64 MCP tools covering jobs, builds, pipelines, nodes, plugins, credentials, users, queue, views, search, system administration, Terraform and GCP.
- Folder, nested-folder, multibranch pipeline and organization-folder support.
- Automatic CSRF crumb handling (Crumb Issuer), with transparent retry on stale crumbs.
- Connection pooling + retry/backoff via a single shared `requests.Session`.
- Structured JSON responses: `{"status": "success", "data": {...}, "message": "..."}` / `{"status": "error", "message": "..."}`.
- Rotating file + console logging.
- Pagination support on list-style tools.
- Docker & docker-compose deployment.
- Optional Jenkins CLI fallback.

## Project Structure

```
jenkins-mcp-gcp/
├── server.py            # FastMCP entry point - registers all tools
├── jenkins_client.py     # Jenkins REST API client (pooling, retries, crumb)
├── config.py             # .env-driven configuration
├── requirements.txt
├── .env.example
├── Dockerfile
├── docker-compose.yml
├── mcp.json              # Example MCP client configuration
├── tools/
│   ├── jobs.py           # Job management
│   ├── builds.py         # Builds, pipeline stages, queue, health report
│   ├── nodes.py          # Build agents / nodes
│   ├── plugins.py        # Plugin management
│   ├── credentials.py    # Credential metadata (no secrets)
│   ├── system.py         # Ping, system info, users, views, CLI
│   ├── terraform.py      # Terraform-aware tools
│   └── gcp.py            # GCP-aware tools
└── utils/
    ├── logger.py          # Logging configuration
    ├── helpers.py         # Response envelope, pagination, decorators
    └── terraform_parser.py  # Terraform/GCP log-parsing heuristics
```

## Requirements

- Python 3.13+
- A running Jenkins instance (the `jenkins-terraform-gcp:1.1` image at `http://localhost:8090` by default)
- A Jenkins API token (Jenkins → your user → **Configure** → **API Token** → **Add new Token**)

## Installation

### 1. Clone / open the project

```powershell
cd jenkins-mcp
```

### 2. Create a virtual environment

```powershell
python -m venv .venv
.venv\Scripts\Activate.ps1
```

macOS/Linux:

```bash
python3 -m venv .venv
source .venv/bin/activate
```

### 3. Install dependencies

```powershell
pip install -r requirements.txt
```

### 4. Configure environment variables

Copy the example file and fill in your real values - `.env` is git-ignored and never committed:

```powershell
Copy-Item .env.example .env
```

Edit `.env`:

```env
JENKINS_URL=http://localhost:8090
JENKINS_USER=admin
JENKINS_TOKEN=xxxxxxxx
MCP_TRANSPORT=stdio
```

`server.py` (via `config.py`) calls `load_dotenv()` on startup and reads every setting with `os.getenv()`, so the token is picked up automatically from `.env` - you don't need to (and shouldn't) pass `JENKINS_TOKEN` through `mcp.json`, `claude_desktop_config.json`, or any other client configuration file.

## Run the Server

Stdio transport (default - used by Claude Desktop, VS Code, Cursor):

```powershell
python server.py
```

Network transport (used for the Docker deployment or remote clients):

```powershell
$env:MCP_TRANSPORT="streamable-http"; python server.py
```

## Testing

Quick connectivity check once the server is configured:

```powershell
python -c "from jenkins_client import JenkinsClient; import json; print(json.dumps(JenkinsClient().ping(), indent=2))"
```

You can also use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to interactively call every tool:

```powershell
npx @modelcontextprotocol/inspector python server.py
```

Then call the `ping_jenkins` tool first to validate connectivity/authentication before exercising job/build tools.

## Claude Desktop Configuration

Edit `claude_desktop_config.json` (Claude Desktop → Settings → Developer → Edit Config) and merge in:

```json
{
  "mcpServers": {
    "jenkins-mcp": {
      "command": "C:\\path\\to\\jenkins-mcp\\.venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\jenkins-mcp\\server.py"],
      "env": {
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}
```

> **Security note:** `JENKINS_URL`, `JENKINS_USER` and `JENKINS_TOKEN` are intentionally **not** set here. `server.py` loads them from the `.env` file in the project directory at startup (via `python-dotenv`), so the token never needs to appear in `claude_desktop_config.json`, `mcp.json`, or any other client configuration file that might get committed to source control.

## VS Code MCP Configuration

Create `.vscode/mcp.json` in your workspace (or use the provided `mcp.json` as a template):

```json
{
  "servers": {
    "jenkins-mcp": {
      "type": "stdio",
      "command": "${workspaceFolder}/.venv/Scripts/python.exe",
      "args": ["${workspaceFolder}/server.py"],
      "env": {
        "MCP_TRANSPORT": "stdio"
      }
    }
  }
}
```

`JENKINS_URL`, `JENKINS_USER` and `JENKINS_TOKEN` are deliberately omitted from `mcp.json` - they are loaded from your local `.env` file when `server.py` starts, so no credentials ever need to be written to this file (which is safe to commit).

Then run **MCP: List Servers** from the VS Code command palette and start `jenkins-mcp`.

## Cursor MCP Configuration

Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "jenkins-mcp": {
      "command": "python",
      "args": ["server.py"],
      "cwd": "/absolute/path/to/jenkins-mcp"
    }
  }
}
```

As long as a `.env` file exists in `cwd`, `server.py` picks up `JENKINS_URL` / `JENKINS_USER` / `JENKINS_TOKEN` automatically - there's no need (and no reason) to duplicate them here.

## Docker Deployment

Build and run with docker-compose (recommended - it also sets up `host.docker.internal` so the container can reach Jenkins running on your Docker Desktop host):

```powershell
docker compose up --build -d
```

The server listens on `http://localhost:8000` using the `streamable-http` transport. Point your MCP client at that URL, or override `JENKINS_URL` in a local `.env` file (docker-compose reads it automatically) if Jenkins is reachable via a different hostname/network.

Build the image manually:

```powershell
docker build -t jenkins-mcp:latest .
docker run --rm -p 8000:8000 --env-file .env --add-host host.docker.internal:host-gateway jenkins-mcp:latest
```

## Configuration Reference (`.env`)

| Variable | Default | Description |
|---|---|---|
| `JENKINS_URL` | `http://localhost:8090` | Base Jenkins URL |
| `JENKINS_USER` | _(empty)_ | Jenkins username |
| `JENKINS_TOKEN` | _(empty)_ | Jenkins API token |
| `JENKINS_VERIFY_SSL` | `true` | Verify TLS certs for `https://` Jenkins |
| `JENKINS_TIMEOUT` | `30` | Request timeout (seconds) |
| `JENKINS_MAX_RETRIES` | `3` | HTTP retry attempts |
| `JENKINS_BACKOFF_FACTOR` | `0.5` | Retry backoff factor |
| `JENKINS_POOL_CONNECTIONS` / `JENKINS_POOL_MAXSIZE` | `10` / `20` | Connection pool sizing |
| `LOG_LEVEL` | `INFO` | Logging level |
| `LOG_FILE` | `logs/jenkins_mcp.log` | Rotating log file path |
| `DEFAULT_PAGE_SIZE` | `50` | Default page size for paginated tools |
| `JENKINS_CLI_JAR` | _(empty)_ | Optional path to `jenkins-cli.jar` |
| `TERRAFORM_STATE_BUCKET` / `GCP_PROJECT` | _(empty)_ | Optional fallback hints for Terraform/GCP tools |
| `MCP_TRANSPORT` | `stdio` | `stdio` \| `streamable-http` \| `sse` |

## Security

- **Never commit secrets.** `JENKINS_TOKEN` (and `JENKINS_USER`) live only in your local `.env` file. `.gitignore` excludes `.env` and `*.env`, and `mcp.json` in this repo intentionally has no credential fields.
- **Use `.env.example` as the template.** It only contains placeholder values and is safe to commit; copy it to `.env` and fill in real values locally (or inject real env vars via your secrets manager / CI in production).
- **Rotate tokens, don't reuse passwords.** Generate a dedicated Jenkins API token (Jenkins → your user → Configure → API Token) instead of using your account password.
- **Nothing sensitive is logged.** `jenkins_client.py` only logs the Jenkins URL and username (never the token), and error messages (e.g. on HTTP 401) reference the *names* of the misconfigured variables, not their values, so credentials never end up in `logs/jenkins_mcp.log` or in tool error responses.
- **Credential tools return metadata only.** `list_credentials_ids` / `get_credential_information` never surface secret values, matching Jenkins' own credential API behavior.
- If a token does leak (e.g. committed by mistake), revoke/regenerate it immediately in Jenkins and scrub it from git history.

## Tool Reference

All tools return `{"status": "success", "data": {...}, "message": "..."}` on success or `{"status": "error", "message": "..."}` on failure.

### General
- `ping_jenkins` - version, URL, authentication status

### Jobs
- `list_jobs`, `get_job`, `create_pipeline_job`, `delete_job`, `enable_job`, `disable_job`, `copy_job`, `search_job`

### Builds
- `trigger_build`, `trigger_build_with_parameters`, `stop_build`, `last_build_status`, `build_console_output`, `build_duration`, `build_artifacts`, `build_changes`, `queue_status`, `search_build`

### Pipeline
- `get_pipeline_stages`, `get_stage_logs`, `replay_pipeline`, `blue_ocean_info`, `pipeline_health_report`

### Nodes
- `list_nodes`, `node_status`, `node_executors`, `online_nodes`, `offline_nodes`

### Plugins
- `installed_plugins`, `plugin_version`, `plugin_updates_available`

### System
- `jenkins_version`, `installed_tools`, `system_information`, `quiet_down_mode`, `cancel_quiet_down`, `run_jenkins_cli_command` (optional)

### Credentials
- `list_credentials_ids`, `get_credential_information` (secret values are never returned)

### Users
- `current_user`, `who_am_i`

### Queue
- `queue_information`, `cancel_queue_item`

### Views
- `list_views`, `view_jobs`

### Terraform Support
- `validate_terraform_pipeline`, `validate_jenkinsfile`, `detect_terraform_version`, `detect_workspace`, `show_tfvars`, `show_backend_configuration`, `show_terraform_plan_log`, `show_apply_log`, `show_destroy_log`, `detect_terraform_errors` (classified into Authentication, Provider, Backend, Syntax, State Lock, Permission, Quota, Networking), `terraform_plan_summary`, `workspace_cleanup`

### GCP Support
- `detect_gcloud_version`, `current_gcp_project`, `service_account`, `enabled_apis`, `terraform_state_bucket`, `gcp_resource_inspector`

> Terraform/GCP tools work by parsing Jenkins console logs and workspace files (Jenkins has no native Terraform/GCP awareness), so they are most accurate immediately after a build has run.

## Security Notes

- Credential tools never return secret values (passwords, private keys, secret text/bytes are stripped from responses).
- CSRF crumbs are obtained automatically and refreshed transparently on rejection.
- Configure `JENKINS_VERIFY_SSL=true` in production and use a scoped Jenkins API token rather than a personal password.