Skip to content

Commit 3d1a31c

Browse files
authored
Adding K8s installation with Helm chart (#3)
# Adding K8s installation with Helm chart ## Changes * Updated the CI/CD pipelines to improve the tests and versioning of the app * Updated the docs to include the installation with helm ## New Features * Adding a helm chart to install the Sysdig MCP server in a k8s cluster --------- Signed-off-by: S3B4SZ17 <sebastian.zumbado@sysdig.com>
1 parent ae08b12 commit 3d1a31c

20 files changed

+840
-16
lines changed

.github/workflows/helm_test.yaml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
name: Lint & Test helm chart
3+
4+
on:
5+
pull_request:
6+
branches:
7+
- main
8+
- develop
9+
- feature/**
10+
- release/**
11+
- hotfix/**
12+
paths:
13+
- 'charts/**'
14+
push:
15+
branches:
16+
- main
17+
- develop
18+
- feature/**
19+
- release/**
20+
- hotfix/**
21+
paths:
22+
- 'charts/**'
23+
24+
concurrency:
25+
group: '${{ github.workflow }}-${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
26+
cancel-in-progress: true
27+
28+
jobs:
29+
set-charts:
30+
# Required permissions
31+
permissions:
32+
contents: read
33+
pull-requests: read
34+
outputs:
35+
charts: ${{ steps.charts.outputs.changes }}
36+
name: "Set Charts"
37+
runs-on: [ubuntu-latest]
38+
steps:
39+
- uses: actions/checkout@v4
40+
- uses: dorny/paths-filter@v2
41+
id: charts
42+
with:
43+
base: ${{ github.ref_name }}
44+
filters: |
45+
sysdig-mcp:
46+
- 'charts/sysdig-mcp/**'
47+
lint-charts:
48+
needs: set-charts
49+
name: Lint new helm charts
50+
runs-on: [ubuntu-latest]
51+
strategy:
52+
matrix:
53+
chart: ${{ fromJSON(needs.set-charts.outputs.charts) }}
54+
# When set to true, GitHub cancels all in-progress jobs if any matrix job fails.
55+
fail-fast: false
56+
# The maximum number of jobs that can run simultaneously
57+
max-parallel: 3
58+
steps:
59+
60+
- uses: actions/checkout@v4
61+
with:
62+
fetch-depth: 0
63+
64+
- name: Set up Helm
65+
uses: azure/setup-helm@v4
66+
with:
67+
version: v3.5.0
68+
69+
- uses: actions/setup-python@v4
70+
with:
71+
python-version: '3.10'
72+
check-latest: true
73+
74+
- name: Set up chart-testing
75+
uses: helm/chart-testing-action@v2.6.1
76+
77+
- name: Run chart-testing (list-changed)
78+
id: list-changed
79+
run: |
80+
changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }} --chart-dirs charts)
81+
if [[ -n "$changed" ]]; then
82+
echo "changed=true" >> "$GITHUB_OUTPUT"
83+
fi
84+
85+
- name: Run chart-testing (lint)
86+
if: steps.list-changed.outputs.changed == 'true'
87+
run: ct lint --target-branch ${{ github.event.repository.default_branch }} --chart-dirs charts
88+
89+
- name: Create kind cluster
90+
if: steps.list-changed.outputs.changed == 'true'
91+
uses: helm/kind-action@v1.12.0
92+
93+
- name: Run chart-testing (install)
94+
if: steps.list-changed.outputs.changed == 'true'
95+
run: ct install --target-branch ${{ github.event.repository.default_branch }} --chart-dirs charts

.github/workflows/publish.yaml

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---
12
name: Publish Docker image
23

34
on:
@@ -6,22 +7,36 @@ on:
67
- main
78
paths:
89
- pyproject.toml
10+
- Dockerfile
11+
- '*.py'
12+
- tests/**
13+
- tools/**
14+
- utils/**
915
workflow_dispatch:
10-
inputs:
11-
version:
12-
description: "Version to publish"
13-
required: false
14-
default: "latest"
15-
type: string
16+
17+
concurrency:
18+
group: '${{ github.workflow }}-${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
19+
cancel-in-progress: true
1620

1721
jobs:
22+
tests:
23+
permissions:
24+
checks: write
25+
pull-requests: write
26+
contents: write
27+
uses: ./.github/workflows/test.yaml
28+
secrets: inherit
1829
push_to_registry:
1930
name: Push Docker image to GitHub Packages
2031
runs-on: ubuntu-latest
32+
needs: tests
2133
permissions:
2234
contents: read # required for actions/checkout
2335
packages: write # required for pushing to ghcr.io
2436
id-token: write # required for signing with cosign
37+
outputs:
38+
version: ${{ steps.extract_version.outputs.VERSION }}
39+
tag: ${{ steps.extract_version.outputs.TAG }}
2540
steps:
2641
- name: Check out the repo
2742
uses: actions/checkout@v4
@@ -31,6 +46,8 @@ jobs:
3146
run: |
3247
VERSION=$(grep 'version =' pyproject.toml | sed -e 's/version = "\(.*\)"/\1/')-$(echo $GITHUB_SHA | cut -c1-7)
3348
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
49+
TAG=v$(grep 'version =' pyproject.toml | sed -e 's/version = "\(.*\)"/\1/')
50+
echo "TAG=$TAG" >> "$GITHUB_OUTPUT"
3451
3552
- name: Log in to GitHub Container Registry
3653
uses: docker/login-action@v3
@@ -61,3 +78,29 @@ jobs:
6178
ghcr.io/sysdiglabs/sysdig-mcp-server:v${{ steps.extract_version.outputs.VERSION }}
6279
DIGEST: ${{ steps.build-and-push.outputs.digest }}
6380
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
81+
82+
tag_release:
83+
name: Tag Release
84+
runs-on: ubuntu-latest
85+
needs: push_to_registry
86+
steps:
87+
- name: Check out the repo
88+
uses: actions/checkout@v4
89+
90+
- name: Get tag version
91+
id: semantic_release
92+
uses: anothrNick/github-tag-action@1.73.0
93+
env:
94+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
95+
DEFAULT_BUMP: "patch"
96+
TAG_CONTEXT: ${{ (github.base_ref != 'main') && 'branch' || 'repo' }}
97+
PRERELEASE_SUFFIX: "beta"
98+
PRERELEASE: ${{ (github.base_ref != 'main') && 'true' || 'false' }}
99+
DRY_RUN: false
100+
INITIAL_VERSION: ${{ needs.push_to_registry.outputs.tag }}
101+
102+
- name: Summary
103+
run: |
104+
echo "## Release Summary
105+
- Tag: ${{ steps.semantic_release.outputs.tag }}
106+
- Docker Image: ghcr.io/sysdiglabs/sysdig-mcp-server:v${{ needs.push_to_registry.outputs.version }}" >> $GITHUB_STEP_SUMMARY

.github/workflows/test.yaml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
1+
---
12
name: Test
23

34
on:
45
push:
56
branches:
67
- main
8+
- develop
9+
- feature/**
10+
- release/**
11+
- hotfix/**
12+
paths:
13+
- pyproject.toml
14+
- Dockerfile
15+
- '*.py'
16+
- tests/**
17+
- tools/**
18+
- utils/**
719
pull_request:
20+
paths:
21+
- pyproject.toml
22+
- Dockerfile
23+
- '*.py'
24+
- tests/**
25+
- tools/**
26+
- utils/**
27+
workflow_call:
28+
29+
concurrency:
30+
group: '${{ github.workflow }}-${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
31+
cancel-in-progress: true
832

933
jobs:
1034
test:
@@ -34,3 +58,52 @@ jobs:
3458

3559
- name: Run Unit Tests
3660
run: make test
61+
62+
pre_release:
63+
name: Tag Release
64+
runs-on: ubuntu-latest
65+
needs: test
66+
permissions:
67+
contents: write # required for creating a tag
68+
steps:
69+
- name: Check out the repo
70+
uses: actions/checkout@v4
71+
with:
72+
ref: ${{ github.head_ref }} # checkout the correct branch name
73+
fetch-depth: 0
74+
75+
- name: Extract current version
76+
id: pyproject_version
77+
run: |
78+
TAG=v$(grep 'version =' pyproject.toml | sed -e 's/version = "\(.*\)"/\1/')
79+
echo "TAG=$TAG" >> "$GITHUB_OUTPUT"
80+
81+
- name: Get tag version
82+
id: semantic_release
83+
uses: anothrNick/github-tag-action@1.73.0
84+
env:
85+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86+
DEFAULT_BUMP: "patch"
87+
TAG_CONTEXT: ${{ (github.base_ref != 'main') && 'branch' || 'repo' }}
88+
PRERELEASE_SUFFIX: "beta"
89+
PRERELEASE: ${{ (github.base_ref != 'main') && 'true' || 'false' }}
90+
DRY_RUN: true
91+
INITIAL_VERSION: ${{ steps.pyproject_version.outputs.TAG }}
92+
93+
- name: Compare versions
94+
run: |
95+
echo "Current version: ${{ steps.pyproject_version.outputs.TAG }}"
96+
echo "New version: ${{ steps.semantic_release.outputs.tag }}"
97+
if [ "${{ steps.pyproject_version.outputs.TAG }}" != "${{ steps.semantic_release.outputs.tag }}" ]; then
98+
echo "### Version mismatch detected! :warning:
99+
Current pyproject version: ${{ steps.pyproject_version.outputs.TAG }}
100+
New Tag version: **${{ steps.semantic_release.outputs.tag }}**
101+
Current Tag: ${{ steps.semantic_release.outputs.old_tag }}
102+
Please update the version in pyproject.toml." >> $GITHUB_STEP_SUMMARY
103+
exit 1
104+
else
105+
echo "### Version match confirmed! :rocket:
106+
Current pyproject version: ${{ steps.pyproject_version.outputs.TAG }}
107+
New Tag version: **${{ steps.semantic_release.outputs.tag }}**
108+
The version is up-to-date." >> $GITHUB_STEP_SUMMARY
109+
fi

README.md

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# MCP Server
22

3+
## Table of contents
4+
5+
- [MCP Server](#mcp-server)
6+
- [Table of contents](#table-of-contents)
7+
- [Description](#description)
8+
- [Available Tools](#available-tools)
9+
- [Requirements](#requirements)
10+
- [UV Setup](#uv-setup)
11+
- [Configuration](#configuration)
12+
- [`app_config.yaml`](#app_configyaml)
13+
- [Environment Variables](#environment-variables)
14+
- [Running the Server](#running-the-server)
15+
- [Docker](#docker)
16+
- [K8s Deployment](#k8s-deployment)
17+
- [UV](#uv)
18+
- [Client Configuration](#client-configuration)
19+
- [Authentication](#authentication)
20+
- [URL](#url)
21+
- [Claude Desktop App](#claude-desktop-app)
22+
- [MCP Inspector](#mcp-inspector)
23+
324
## Description
425

526
This is an implementation of an [MCP (Model Context Protocol) Server](https://modelcontextprotocol.io/quickstart/server) to allow different LLMs to query information from Sysdig Secure platform. **It is still in early development and not yet ready for production use.** New endpoints and functionalities will be added over time. The goal is to provide a simple and easy-to-use interface for querying information from Sysdig Secure platform using LLMs.
@@ -73,10 +94,6 @@ source .venv/bin/activate
7394

7495
This will create a virtual environment using `uv` and install the required dependencies.
7596

76-
### Sysdig SDK
77-
78-
You will need the Sysdig-SDK. You can find it in the `build` directory as a `.tar.gz` file that will be used by UV to install the package.
79-
8097
## Configuration
8198

8299
The application can be configured via the `app_config.yaml` file and environment variables.
@@ -93,7 +110,7 @@ This file contains the main configuration for the application, including:
93110

94111
The following environment variables are required for configuring the Sysdig SDK:
95112

96-
- `SYSDIG_HOST`: The URL of your Sysdig Secure instance (e.g., `https://secure.sysdig.com`).
113+
- `SYSDIG_HOST`: The URL of your Sysdig Secure instance (e.g., `https://us2.app.sysdig.com`).
97114
- `SYSDIG_SECURE_TOKEN`: Your Sysdig Secure API token.
98115

99116
You can find your API token in the Sysdig Secure UI under **Settings > Sysdig Secure API**. Make sure to copy the token as it will not be shown again.
@@ -105,9 +122,11 @@ You can set these variables in your shell or in a `.env` file.
105122

106123
You can also use `MCP_TRANSPORT` to override the transport protocol set in `app_config.yaml`.
107124

125+
> All of this env variables have precedence over the fields configured in the app_config.yaml.
126+
108127
## Running the Server
109128

110-
You can run the MCP server using either Docker or `uv`.
129+
You can run the MCP server using either Docker, `uv` or install it in your K8s cluster with helm.
111130

112131
### Docker
113132

@@ -129,6 +148,51 @@ By default, the server will run using the `stdio` transport. To use the `streama
129148
docker run -e MCP_TRANSPORT=streamable-http -e SYSDIG_HOST=<your_sysdig_host> -e SYSDIG_SECURE_TOKEN=<your_sysdig_secure_api_token> -p 8080:8080 sysdig-mcp-server
130149
```
131150

151+
### K8s Deployment
152+
153+
If you want to run the Sysdig MCP server in a K8s cluster you can use the helm chart provided in the `charts/sysdig-mcp` path
154+
155+
Modify the `values.yaml`
156+
157+
```yaml
158+
# Example values.yaml
159+
---
160+
sysdig:
161+
secrets:
162+
create: true
163+
# If enabled, the secrets will be mounted as environment variables
164+
secureAPIToken: "<your_sysdig_secure_api_token>"
165+
mcp:
166+
transport: "streamable-http"
167+
# You can set the Sysdig Tenant URL at this level or below in the app_config configmap
168+
host: "https://us2.app.sysdig.com" # <your_sysdig_host> "https://eu1.app.sysdig.com"
169+
170+
configMap:
171+
enabled: true
172+
app_config: |
173+
# Sysdig MCP Server Configuration
174+
# This file is used to configure the Sysdig MCP server.
175+
# You can add your custom configuration here.
176+
app:
177+
host: "0.0.0.0"
178+
port: 8080
179+
log_level: "error"
180+
181+
sysdig:
182+
host: "https://us2.app.sysdig.com" # <your_sysdig_host> "https://eu1.app.sysdig.com"
183+
184+
mcp:
185+
transport: streamable-http
186+
host: "0.0.0.0"
187+
port: 8080
188+
```
189+
190+
Install the chart
191+
192+
```bash,copy
193+
helm upgrade --install sysdig-mcp ./charts/sysdig-mcp/ -n sysdig-mcp -f charts/sysdig-mcp/values.yaml
194+
```
195+
132196
### UV
133197

134198
To run the server using `uv`, first set up the environment as described in the [UV Setup](#uv-setup) section. Then, run the `main.py` script:
@@ -233,3 +297,11 @@ For the Claude Desktop app, you can manually configure the MCP server by editing
233297
- Replace `<path_to_your_sysdig_mcp_server_directory>` with the absolute path to the `sysdig-mcp-server` directory.
234298

235299
4. **Save the file** and restart the Claude Desktop app for the changes to take effect.
300+
301+
### MCP Inspector
302+
303+
1. Run the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) locally
304+
2. Select the transport type and have the Sysdig MCP server running accordingly.
305+
3. Pass the Authorization header if using "streamable-http" or the SYSDIG_SECURE_API_TOKEN env var if using "stdio"
306+
307+
![mcp-inspector](./docs/assets/mcp-inspector.png)

0 commit comments

Comments
 (0)