Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ HolmesGPT integrates with popular observability and cloud platforms. The followi
| [<img src="images/integration_logos/opensearchserverless-icon.png" alt="Elasticsearch" width="20" style="vertical-align: middle;"> **Elasticsearch / OpenSearch**](https://holmesgpt.dev/data-sources/builtin-toolsets/elasticsearch/) | Query logs, cluster health, shard and index diagnostics |
| [<img src="images/integration_logos/gcpmonitoring-icon.png" alt="GCP" width="20" style="vertical-align: middle;"> **GCP**](https://holmesgpt.dev/data-sources/builtin-toolsets/gcp/) | Google Cloud Platform resources (MCP) |
| [<img src="images/integration_logos/github_logo.png" alt="GitHub" width="20" style="vertical-align: middle;"> **GitHub**](https://holmesgpt.dev/data-sources/builtin-toolsets/github-mcp/) | Repositories, issues, and pull requests (MCP) |
| [<img src="images/integration_logos/jenkins-icon.png" alt="Jenkins" width="20" style="vertical-align: middle;"> **Jenkins (MCP)**](https://holmesgpt.dev/data-sources/builtin-toolsets/jenkins-mcp/) | Build status, pipeline logs, and job history (MCP) |
| [<img src="images/integration_logos/grafana-icon.png" alt="Grafana" width="20" style="vertical-align: middle;"> **Grafana**](https://holmesgpt.dev/data-sources/builtin-toolsets/grafanadashboards/) | Query and analyze dashboard configurations and panels |
| [<img src="images/integration_logos/helm_logo.png" alt="Helm" width="20" style="vertical-align: middle;"> **Helm**](https://holmesgpt.dev/data-sources/builtin-toolsets/helm/) | Release status, chart metadata, and values |
| [<img src="images/integration_logos/http-icon.png" alt="Internet" width="20" style="vertical-align: middle;"> **Internet**](https://holmesgpt.dev/data-sources/builtin-toolsets/internet/) | Public runbooks, community docs etc |
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/builtin-toolsets/.nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ nav:
- Helm: helm.md
- Inspektor Gadget: inspektor-gadget.md
- Internet: internet.md
- Jenkins (MCP): jenkins-mcp.md
- Kafka: kafka.md
- Kubectl Run: kubectl-run.md
- Kubernetes: kubernetes.md
Expand Down
8 changes: 8 additions & 0 deletions docs/data-sources/builtin-toolsets/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ HolmesGPT includes pre-built integrations for popular monitoring and observabili

</div>

### CI/CD

<div class="grid cards" markdown>

- [:simple-jenkins:{ .lg .middle } **Jenkins (MCP)**](jenkins-mcp.md)

</div>

### Workflow Orchestration

<div class="grid cards" markdown>
Expand Down
238 changes: 238 additions & 0 deletions docs/data-sources/builtin-toolsets/jenkins-mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
# Jenkins (MCP)
Comment thread
arikalon1 marked this conversation as resolved.

The Jenkins MCP Server Plugin enables Holmes to interact with your Jenkins CI/CD infrastructure.

## Prerequisites

- A running Jenkins instance with the [MCP Server Plugin](https://plugins.jenkins.io/mcp-server/) installed
- A Jenkins API token for authentication
- Network connectivity from Holmes to the Jenkins MCP endpoint

**Installing the Jenkins MCP Plugin:**

1. In Jenkins, go to **Manage Jenkins** → **Plugins** → **Available plugins**
2. Search for "MCP Server" and install it
3. Restart Jenkins if required

**Creating a Jenkins API Token:**

1. Sign in to Jenkins
2. Click your username in the upper-right corner → **Security**
3. Under **API Token**, click **Add new Token**
4. Enter a descriptive name and click **Generate**
5. Copy the token immediately (it won't be shown again)
6. Click **Save**

**Encoding credentials for Basic authentication:**

The Jenkins MCP server uses HTTP Basic authentication. Encode your credentials:

=== "Linux / macOS"

```bash
echo -n "username:api_token" | base64
```

=== "Windows (PowerShell)"

```powershell
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("username:api_token"))
```

Store the encoded credential securely for use in the configuration below.

## Configuration

=== "Holmes CLI"

Add the following to **~/.holmes/config.yaml**. Create the file if it doesn't exist:

```yaml
mcp_servers:
jenkins:
description: "Jenkins CI/CD server"
config:
url: "https://your-jenkins-instance/mcp-server/mcp"
mode: streamable-http
headers:
Authorization: "Basic <base64_encoded_credentials>"
verify_ssl: false # Set to true if using valid SSL certificates
icon_url: "https://cdn.simpleicons.org/jenkins/D24939"
llm_instructions: |
When investigating build failures, start with recent build status and then examine console output.
Use pagination for large result sets to avoid token overflow.
```

Replace `<base64_encoded_credentials>` with your encoded `username:api_token`.

--8<-- "snippets/toolset_refresh_warning.md"

=== "Holmes Helm Chart"

**Create Kubernetes Secret:**

```bash
# Encode your credentials
JENKINS_AUTH=$(echo -n "username:api_token" | base64)

# Create the secret
kubectl create secret generic jenkins-credentials \
--from-literal=token="$JENKINS_AUTH" \
-n <namespace>
```

**Configure Helm Values:**

```yaml
# values.yaml
additionalEnvVars:
- name: JENKINS_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: jenkins-credentials
key: token

mcp_servers:
jenkins:
description: "Jenkins CI/CD server"
config:
url: "https://your-jenkins-instance/mcp-server/mcp"
mode: streamable-http
headers:
Authorization: "Basic {{ env.JENKINS_AUTH_TOKEN }}"
verify_ssl: false
icon_url: "https://cdn.simpleicons.org/jenkins/D24939"
llm_instructions: |
When investigating build failures, start with recent build status and then examine console output.
Use pagination for large result sets to avoid token overflow.
```

Then deploy or upgrade your Holmes installation:

```bash
helm upgrade --install holmes robusta/holmes -f values.yaml
```

=== "Robusta Helm Chart"

**Create Kubernetes Secret:**

```bash
# Encode your credentials
JENKINS_AUTH=$(echo -n "username:api_token" | base64)

# Create the secret
kubectl create secret generic jenkins-credentials \
--from-literal=token="$JENKINS_AUTH" \
-n <namespace>
```

**Configure Helm Values:**

```yaml
# generated_values.yaml
holmes:
additionalEnvVars:
- name: JENKINS_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: jenkins-credentials
key: token

mcp_servers:
jenkins:
description: "Jenkins CI/CD server"
config:
url: "https://your-jenkins-instance/mcp-server/mcp"
mode: streamable-http
headers:
Authorization: "Basic {{ env.JENKINS_AUTH_TOKEN }}"
verify_ssl: false
icon_url: "https://cdn.simpleicons.org/jenkins/D24939"
llm_instructions: |
When investigating build failures, start with recent build status and then examine console output.
Use pagination for large result sets to avoid token overflow.
```

Then deploy or upgrade your Robusta installation:

```bash
helm upgrade --install robusta robusta/robusta -f generated_values.yaml --set clusterName=YOUR_CLUSTER_NAME
```

!!! warning "MCP endpoint path"
The Jenkins MCP server serves on `/mcp-server/mcp` for Streamable HTTP transport. Other available endpoints:

- **Streamable HTTP**: `/mcp-server/mcp` (recommended)
- **SSE**: `/mcp-server/sse`
- **Stateless**: `/mcp-server/stateless`

## Testing the Connection

```bash
holmes ask "List all Jenkins jobs"
```

## Common Use Cases

**Investigate a failed build:**
```bash
holmes ask "Why did the last build of my-app-pipeline fail?"
```

**Check build status:**
```bash
holmes ask "What is the status of the most recent builds for the deploy-production job?"
```

**View build logs:**
```bash
holmes ask "Show me the console output from the last failed build of backend-service"
```

**Monitor pipeline stages:**
```bash
holmes ask "What stages failed in the latest run of the CI pipeline?"
```

**Check queue status:**
```bash
holmes ask "Are there any builds waiting in the Jenkins queue?"
```

**Analyze build trends:**
```bash
holmes ask "Show me the build history and success rate for the integration-tests job"
```

## Troubleshooting

**Authentication Errors**

If you receive 401 or 403 errors:

1. Verify your API token is valid and not expired
2. Ensure the credentials are properly base64 encoded (username:token format)
3. Check that the Jenkins user has appropriate permissions

**Connection Issues**

If Holmes cannot connect to Jenkins:

1. Verify the Jenkins URL is accessible from the Holmes pod/container
2. Check if SSL certificate verification is causing issues (`verify_ssl: false` for self-signed certs)
3. Ensure the MCP Server plugin is installed and enabled in Jenkins

**Plugin Not Found**

If the `/mcp-server/mcp` endpoint returns 404:

1. Verify the MCP Server plugin is installed in Jenkins
2. Restart Jenkins after plugin installation
3. Check Jenkins system logs for plugin errors

## Additional Resources

- [Jenkins MCP Server Plugin](https://plugins.jenkins.io/mcp-server/)
- [Jenkins API Token Documentation](https://www.jenkins.io/doc/book/system-administration/authenticating-scripted-clients/)
- [Model Context Protocol Specification](https://modelcontextprotocol.io/)
1 change: 1 addition & 0 deletions docs/why-holmesgpt.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ HolmesGPT ships with read-only integrations for every major observability vendor
- **Traces**: Tempo, Datadog, NewRelic
- **Dashboards**: Grafana
- **Infrastructure**: Kubernetes, Docker, Helm, ArgoCD, OpenShift, Cilium, KubeVela
- **CI/CD**: Jenkins
- **Cloud**: AWS RDS, Azure SQL, Azure AKS, GCP
- **Databases**: PostgreSQL, MySQL, ClickHouse, MariaDB, SQL Server, MongoDB Atlas
- **ITSM**: ServiceNow
Expand Down
Binary file added images/integration_logos/jenkins-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions images/integration_logos/jenkins-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions tests/test_mcp_toolset.py
Original file line number Diff line number Diff line change
Expand Up @@ -2287,3 +2287,76 @@ def test_extra_headers_templates_not_resolved(self):

# regular headers SHOULD be resolved by replace_env_vars_values
assert config["config"]["headers"]["X-Static"] == "resolved_value"


class TestJenkinsMCPConfig:
"""Validate that the Jenkins MCP integration config documented in
docs/data-sources/builtin-toolsets/jenkins-mcp.md is accepted by
RemoteMCPToolset and that its fields are preserved correctly.
"""

_JENKINS_URL = "https://jenkins.example.com/mcp-server/mcp"
_JENKINS_AUTH = "dXNlcjp0b2tlbg==" # base64("user:token")

def _make_toolset(self) -> RemoteMCPToolset:
"""Return a RemoteMCPToolset configured exactly as shown in the Jenkins docs."""
return RemoteMCPToolset(
name="jenkins",
description="Jenkins CI/CD server",
config={
"url": self._JENKINS_URL,
"mode": "streamable-http",
"headers": {"Authorization": f"Basic {self._JENKINS_AUTH}"},
"verify_ssl": False,
},
)

def _stub_get_server_tools(self, monkeypatch, toolset: RemoteMCPToolset) -> None:
"""Patch _get_server_tools so prerequisites_callable makes no network calls."""

async def _no_op():
return ListToolsResult(tools=[])

monkeypatch.setattr(toolset, "_get_server_tools", _no_op)

def test_jenkins_config_url_and_mode_parsed(
self, monkeypatch, suppress_migration_warnings
):
"""Documented Jenkins URL and streamable-http mode must be stored verbatim."""
toolset = self._make_toolset()
self._stub_get_server_tools(monkeypatch, toolset)
toolset.prerequisites_callable(config=toolset.config)

assert str(toolset._mcp_config.url) == self._JENKINS_URL
assert toolset._mcp_config.mode == MCPMode.STREAMABLE_HTTP

def test_jenkins_config_auth_header_preserved(
self, monkeypatch, suppress_migration_warnings
):
"""Basic auth header must survive config parsing unchanged."""
toolset = self._make_toolset()
self._stub_get_server_tools(monkeypatch, toolset)
toolset.prerequisites_callable(config=toolset.config)

assert toolset._mcp_config.headers is not None
assert toolset._mcp_config.headers.get("Authorization") == (
f"Basic {self._JENKINS_AUTH}"
)

def test_jenkins_config_ssl_verification_disabled(
self, monkeypatch, suppress_migration_warnings
):
"""verify_ssl=False must be reflected in the parsed config."""
toolset = self._make_toolset()
self._stub_get_server_tools(monkeypatch, toolset)
toolset.prerequisites_callable(config=toolset.config)

assert toolset._mcp_config.verify_ssl is False

def test_jenkins_config_missing_url_fails_prerequisites(self):
"""A Jenkins toolset with no URL must fail prerequisites with a clear error."""
toolset = RemoteMCPToolset(name="jenkins", description="Jenkins CI/CD server")
ok, msg = toolset.prerequisites_callable(config=toolset.config)

assert ok is False
assert msg # error message must be non-empty
Loading