mirror of
https://github.com/shadoll/redmine-mcp.git
synced 2026-08-28 11:33:28 +00:00
Add Helm chart and Kubernetes deployment configuration for Redmine MCP
This commit is contained in:
@@ -9,12 +9,18 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set image tag
|
||||
id: tag
|
||||
run: echo "value=sha-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -36,6 +42,28 @@ jobs:
|
||||
file: container/Containerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ghcr.io/${{ github.repository }}:latest
|
||||
tags: ghcr.io/${{ github.repository }}:${{ steps.tag.outputs.value }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Bump chart version and set appVersion
|
||||
id: chart
|
||||
run: |
|
||||
CURRENT=$(grep '^version:' helm/Chart.yaml | awk '{print $2}')
|
||||
MAJOR=$(echo $CURRENT | cut -d. -f1)
|
||||
MINOR=$(echo $CURRENT | cut -d. -f2)
|
||||
PATCH=$(echo $CURRENT | cut -d. -f3)
|
||||
NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
|
||||
|
||||
sed -i "s/^version: .*/version: $NEW_VERSION/" helm/Chart.yaml
|
||||
sed -i "s/^appVersion: .*/appVersion: \"${{ steps.tag.outputs.value }}\"/" helm/Chart.yaml
|
||||
|
||||
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit and push chart update
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add helm/Chart.yaml
|
||||
git commit -m "chore: chart ${{ steps.chart.outputs.version }}, appVersion ${{ steps.tag.outputs.value }} [skip ci]"
|
||||
git push
|
||||
|
||||
@@ -4,8 +4,6 @@ Exposes Redmine REST API as tools for Claude Code via MCP (Model Context Protoco
|
||||
|
||||
## Available tools
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
**Issues**
|
||||
|
||||
| Tool | Description |
|
||||
@@ -87,6 +85,74 @@ Verify it was added:
|
||||
claude mcp list
|
||||
```
|
||||
|
||||
## Kubernetes / k3s
|
||||
|
||||
### Quick start
|
||||
|
||||
**1. Install Helm** (if not already installed):
|
||||
```bash
|
||||
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
```
|
||||
|
||||
**2. Install the chart:**
|
||||
```bash
|
||||
helm install redmine-mcp ./helm \
|
||||
--set redmine.url=https://your.redmine.com \
|
||||
--set redmine.apiKey=your_api_key
|
||||
```
|
||||
|
||||
**3. Register with Claude Code** (using port-forward):
|
||||
```bash
|
||||
kubectl port-forward svc/redmine-mcp 8000:8000
|
||||
claude mcp add --scope user --transport http redmine http://localhost:8000/mcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Expose via NodePort (access without port-forward)
|
||||
|
||||
```bash
|
||||
helm install redmine-mcp ./helm \
|
||||
--set redmine.url=https://your.redmine.com \
|
||||
--set redmine.apiKey=your_api_key \
|
||||
--set service.type=NodePort
|
||||
```
|
||||
|
||||
Then find the assigned port:
|
||||
```bash
|
||||
kubectl get svc redmine-mcp
|
||||
```
|
||||
|
||||
Register:
|
||||
```bash
|
||||
claude mcp add --scope user --transport http redmine http://<node-ip>:<node-port>/mcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Use an existing Kubernetes Secret
|
||||
|
||||
```bash
|
||||
kubectl create secret generic redmine-credentials \
|
||||
--from-literal=REDMINE_URL=https://your.redmine.com \
|
||||
--from-literal=REDMINE_API_KEY=your_api_key
|
||||
|
||||
helm install redmine-mcp ./helm \
|
||||
--set redmine.existingSecret=redmine-credentials
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Upgrade / uninstall
|
||||
|
||||
```bash
|
||||
# Upgrade
|
||||
helm upgrade redmine-mcp ./helm --reuse-values
|
||||
|
||||
# Uninstall
|
||||
helm uninstall redmine-mcp
|
||||
```
|
||||
|
||||
## Usage examples
|
||||
|
||||
Once registered, just ask Claude naturally in any project:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: redmine-mcp
|
||||
description: Redmine MCP Server — exposes Redmine REST API as MCP tools for Claude Code
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "0.0.0" # updated automatically by CI
|
||||
@@ -0,0 +1,36 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "redmine-mcp.name" -}}
|
||||
{{- .Chart.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "redmine-mcp.labels" -}}
|
||||
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
app.kubernetes.io/name: {{ include "redmine-mcp.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "redmine-mcp.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "redmine-mcp.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Name of the secret containing Redmine credentials
|
||||
*/}}
|
||||
{{- define "redmine-mcp.secretName" -}}
|
||||
{{- if .Values.redmine.existingSecret -}}
|
||||
{{ .Values.redmine.existingSecret }}
|
||||
{{- else -}}
|
||||
{{ include "redmine-mcp.name" . }}-credentials
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,58 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "redmine-mcp.name" . }}
|
||||
labels:
|
||||
{{- include "redmine-mcp.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "redmine-mcp.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "redmine-mcp.labels" . | nindent 8 }}
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8000
|
||||
protocol: TCP
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "redmine-mcp.secretName" . }}
|
||||
env:
|
||||
- name: MCP_TRANSPORT
|
||||
value: http
|
||||
- name: MCP_HOST
|
||||
value: "0.0.0.0"
|
||||
- name: MCP_PORT
|
||||
value: "8000"
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- if not .Values.redmine.existingSecret }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "redmine-mcp.name" . }}-credentials
|
||||
labels:
|
||||
{{- include "redmine-mcp.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
REDMINE_URL: {{ .Values.redmine.url | required "redmine.url is required" | quote }}
|
||||
REDMINE_API_KEY: {{ .Values.redmine.apiKey | required "redmine.apiKey is required" | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "redmine-mcp.name" . }}
|
||||
labels:
|
||||
{{- include "redmine-mcp.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
selector:
|
||||
{{- include "redmine-mcp.selectorLabels" . | nindent 4 }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,29 @@
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: ghcr.io/shadoll/redmine-mcp
|
||||
tag: "" # defaults to Chart.appVersion when empty
|
||||
pullPolicy: Always
|
||||
|
||||
redmine:
|
||||
# Inline credentials (will be stored in a Secret)
|
||||
url: ""
|
||||
apiKey: ""
|
||||
# -- Or reference an existing Secret with keys REDMINE_URL and REDMINE_API_KEY
|
||||
existingSecret: ""
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
|
||||
resources: {}
|
||||
# limits:
|
||||
# cpu: 200m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 64Mi
|
||||
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
affinity: {}
|
||||
Reference in New Issue
Block a user