Skip to content

Commit f0aa88c

Browse files
authored
[ROB-3039] GitHub App credentials mcp config (#1717)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added GitHub App authentication as an alternative to Personal Access Token for GitHub MCP integration, supporting GitHub.com and Enterprise. * **Documentation** * Reworked GitHub MCP docs with clearer prerequisites, unified in-cluster deployment guidance, and simplified Helm/config examples using in-cluster MCP endpoints. * **Chores** * Moved token management to the in-cluster MCP component and removed the legacy local token refresh mechanism. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: avi@robusta.dev <avi@robusta.dev>
1 parent 75ee141 commit f0aa88c

File tree

8 files changed

+181
-539
lines changed

8 files changed

+181
-539
lines changed

docs/data-sources/builtin-toolsets/github-mcp.md

Lines changed: 98 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ The GitHub MCP server provides access to GitHub repositories, pull requests, iss
44

55
## Overview
66

7-
The GitHub MCP server is deployed as a separate pod in your cluster when using the Holmes or Robusta Helm charts. For CLI users, you'll need to deploy the MCP server manually and configure Holmes to connect to it.
7+
Holmes supports two authentication methods for GitHub. Both deploy a self-hosted MCP server pod in your cluster that wraps the [official GitHub MCP server](https://github.com/github/github-mcp-server):
88

9-
The server supports both GitHub.com and GitHub Enterprise Server, making it suitable for both cloud and on-premises deployments.
9+
- **Personal Access Token (PAT)**: Uses the standard `github-mcp` image. The PAT is passed directly to the MCP server.
10+
- **GitHub App**: Uses the `github-app-mcp` image which automatically generates and refreshes short-lived installation tokens from GitHub App credentials.
11+
12+
Both methods support GitHub.com and GitHub Enterprise Server.
1013

1114
## Prerequisites
1215

@@ -259,7 +262,7 @@ Before deploying the GitHub MCP server, you need a GitHub Personal Access Token
259262

260263
### Using a GitHub App
261264

262-
Instead of a Personal Access Token, you can authenticate using a [GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps). This method uses GitHub's remote MCP endpoint (`api.githubcopilot.com/mcp`) with automatically refreshed installation tokens.
265+
Instead of a Personal Access Token, you can authenticate using a [GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps). This deploys the `github-app-mcp` image which wraps the official GitHub MCP server with automatic installation token generation and refresh.
263266

264267
**Step 1: Create a GitHub App**
265268

@@ -296,52 +299,82 @@ Note the **Installation ID** from the URL after installation: `https://github.co
296299

297300
Find the **App ID** on the App's settings page (under "About").
298301

299-
**Step 5: Configure the GitHub MCP Server**
302+
**Step 5: Configure Holmes**
300303

301-
Choose one of:
304+
=== "Holmes CLI"
302305

303-
- **Self-hosted in cluster** — Deploy the MCP server using [Steps 1–2 from the PAT section above](#using-a-personal-access-token), then use its in-cluster URL.
304-
- **GitHub's remote endpoint** — Use `https://api.githubcopilot.com/mcp` (no deployment needed).
306+
For CLI usage, deploy the `github-app-mcp` server in your cluster and connect Holmes to it.
305307

306-
**Step 6: Configure Holmes**
308+
**Create the Kubernetes secret:**
307309

308-
=== "Holmes CLI"
310+
```bash
311+
kubectl create namespace holmes-mcp # if not already created
309312

310-
Set the following environment variables and add the MCP server to **~/.holmes/config.yaml**:
313+
kubectl create secret generic holmes-github-app \
314+
--from-literal=GITHUB_APP_ID=<YOUR_APP_ID> \
315+
--from-literal=GITHUB_APP_INSTALLATION_ID=<YOUR_INSTALLATION_ID> \
316+
--from-file=GITHUB_APP_PRIVATE_KEY=/path/to/private-key.pem \
317+
-n holmes-mcp
318+
```
311319

312-
```bash
313-
export GITHUB_APP_ID="<YOUR_APP_ID>"
314-
export GITHUB_APP_INSTALLATION_ID="<YOUR_INSTALLATION_ID>"
315-
export GITHUB_APP_PRIVATE_KEY="$(cat /path/to/private-key.pem)"
320+
**Deploy the GitHub App MCP server:**
321+
322+
```yaml
323+
apiVersion: apps/v1
324+
kind: Deployment
325+
metadata:
326+
name: github-mcp-server
327+
namespace: holmes-mcp
328+
spec:
329+
replicas: 1
330+
selector:
331+
matchLabels:
332+
app: github-mcp-server
333+
template:
334+
metadata:
335+
labels:
336+
app: github-mcp-server
337+
spec:
338+
containers:
339+
- name: github-mcp
340+
image: us-central1-docker.pkg.dev/genuine-flight-317411/mcp/github-app-mcp:1.0.0
341+
ports:
342+
- containerPort: 8000
343+
args:
344+
- "--stdio"
345+
- "python3 /app/wrapper.py"
346+
- "--port"
347+
- "8000"
348+
- "--outputTransport"
349+
- "streamableHttp"
350+
env:
351+
- name: GITHUB_APP_ID
352+
valueFrom:
353+
secretKeyRef:
354+
name: holmes-github-app
355+
key: GITHUB_APP_ID
356+
- name: GITHUB_APP_INSTALLATION_ID
357+
valueFrom:
358+
secretKeyRef:
359+
name: holmes-github-app
360+
key: GITHUB_APP_INSTALLATION_ID
361+
- name: GITHUB_APP_PRIVATE_KEY
362+
valueFrom:
363+
secretKeyRef:
364+
name: holmes-github-app
365+
key: GITHUB_APP_PRIVATE_KEY
316366
```
317367

318-
=== "Self-hosted MCP Server"
319-
320-
```yaml
321-
mcp_servers:
322-
github:
323-
description: "GitHub MCP Server"
324-
config:
325-
url: "http://github-mcp-server.holmes-mcp.svc.cluster.local:8000/sse"
326-
mode: "sse"
327-
extra_headers:
328-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
329-
```
330-
331-
=== "GitHub's Remote MCP"
332-
333-
```yaml
334-
mcp_servers:
335-
github:
336-
description: "GitHub MCP Server"
337-
config:
338-
url: "https://api.githubcopilot.com/mcp"
339-
mode: "streamable-http"
340-
extra_headers:
341-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
342-
```
343-
344-
Holmes will automatically generate an installation token at startup and refresh it in the background.
368+
Then add the MCP server to **~/.holmes/config.yaml**:
369+
370+
```yaml
371+
mcp_servers:
372+
github:
373+
description: "GitHub MCP Server"
374+
config:
375+
url: "http://github-mcp-server.holmes-mcp.svc.cluster.local:8000/mcp"
376+
mode: "streamable-http"
377+
```
345378

346379
=== "Holmes Helm Chart"
347380

@@ -357,65 +390,16 @@ Choose one of:
357390

358391
**Add to your `values.yaml`:**
359392

360-
=== "Self-hosted MCP Server"
393+
```yaml
394+
mcpAddons:
395+
github:
396+
enabled: true
397+
auth:
398+
githubApp:
399+
secretName: "holmes-github-app"
400+
```
361401

362-
```yaml
363-
additionalEnvVars:
364-
- name: GITHUB_APP_ID
365-
valueFrom:
366-
secretKeyRef:
367-
name: holmes-github-app
368-
key: GITHUB_APP_ID
369-
- name: GITHUB_APP_INSTALLATION_ID
370-
valueFrom:
371-
secretKeyRef:
372-
name: holmes-github-app
373-
key: GITHUB_APP_INSTALLATION_ID
374-
- name: GITHUB_APP_PRIVATE_KEY
375-
valueFrom:
376-
secretKeyRef:
377-
name: holmes-github-app
378-
key: GITHUB_APP_PRIVATE_KEY
379-
380-
mcp_servers:
381-
github:
382-
description: "GitHub MCP Server"
383-
config:
384-
url: "http://github-mcp-server.holmes-mcp.svc.cluster.local:8000/sse"
385-
mode: "sse"
386-
extra_headers:
387-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
388-
```
389-
390-
=== "GitHub's Remote MCP"
391-
392-
```yaml
393-
additionalEnvVars:
394-
- name: GITHUB_APP_ID
395-
valueFrom:
396-
secretKeyRef:
397-
name: holmes-github-app
398-
key: GITHUB_APP_ID
399-
- name: GITHUB_APP_INSTALLATION_ID
400-
valueFrom:
401-
secretKeyRef:
402-
name: holmes-github-app
403-
key: GITHUB_APP_INSTALLATION_ID
404-
- name: GITHUB_APP_PRIVATE_KEY
405-
valueFrom:
406-
secretKeyRef:
407-
name: holmes-github-app
408-
key: GITHUB_APP_PRIVATE_KEY
409-
410-
mcp_servers:
411-
github:
412-
description: "GitHub MCP Server"
413-
config:
414-
url: "https://api.githubcopilot.com/mcp"
415-
mode: "streamable-http"
416-
extra_headers:
417-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
418-
```
402+
A self-hosted MCP server pod is deployed using the `github-app-mcp` image, which generates and auto-refreshes installation tokens internally. The token refresh interval defaults to 30 minutes.
419403

420404
```bash
421405
helm upgrade --install holmes robusta/holmes -f values.yaml
@@ -435,81 +419,29 @@ Choose one of:
435419

436420
**Add to your `generated_values.yaml`:**
437421

438-
=== "Self-hosted MCP Server"
439-
440-
```yaml
441-
holmes:
442-
additionalEnvVars:
443-
- name: GITHUB_APP_ID
444-
valueFrom:
445-
secretKeyRef:
446-
name: holmes-github-app
447-
key: GITHUB_APP_ID
448-
- name: GITHUB_APP_INSTALLATION_ID
449-
valueFrom:
450-
secretKeyRef:
451-
name: holmes-github-app
452-
key: GITHUB_APP_INSTALLATION_ID
453-
- name: GITHUB_APP_PRIVATE_KEY
454-
valueFrom:
455-
secretKeyRef:
456-
name: holmes-github-app
457-
key: GITHUB_APP_PRIVATE_KEY
458-
459-
mcp_servers:
460-
github:
461-
description: "GitHub MCP Server"
462-
config:
463-
url: "http://github-mcp-server.holmes-mcp.svc.cluster.local:8000/sse"
464-
mode: "sse"
465-
extra_headers:
466-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
467-
```
468-
469-
=== "GitHub's Remote MCP"
470-
471-
```yaml
472-
holmes:
473-
additionalEnvVars:
474-
- name: GITHUB_APP_ID
475-
valueFrom:
476-
secretKeyRef:
477-
name: holmes-github-app
478-
key: GITHUB_APP_ID
479-
- name: GITHUB_APP_INSTALLATION_ID
480-
valueFrom:
481-
secretKeyRef:
482-
name: holmes-github-app
483-
key: GITHUB_APP_INSTALLATION_ID
484-
- name: GITHUB_APP_PRIVATE_KEY
485-
valueFrom:
486-
secretKeyRef:
487-
name: holmes-github-app
488-
key: GITHUB_APP_PRIVATE_KEY
489-
490-
mcp_servers:
491-
github:
492-
description: "GitHub MCP Server"
493-
config:
494-
url: "https://api.githubcopilot.com/mcp"
495-
mode: "streamable-http"
496-
extra_headers:
497-
Authorization: "Bearer {{ env.AUTO_GENERATED_GITHUB_TOKEN }}"
498-
```
422+
```yaml
423+
holmes:
424+
mcpAddons:
425+
github:
426+
enabled: true
427+
auth:
428+
githubApp:
429+
secretName: "holmes-github-app"
430+
```
431+
432+
A self-hosted MCP server pod is deployed using the `github-app-mcp` image, which generates and auto-refreshes installation tokens internally.
499433

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

504438
!!! info "How token refresh works"
505-
When `GITHUB_APP_ID`, `GITHUB_APP_INSTALLATION_ID`, and `GITHUB_APP_PRIVATE_KEY` are set, Holmes automatically:
439+
The `github-app-mcp` image handles token management internally:
506440

507-
1. Generates a JWT signed with the private key
441+
1. At startup, generates a JWT signed with the private key
508442
2. Exchanges it for a short-lived GitHub installation token
509-
3. Sets `AUTO_GENERATED_GITHUB_TOKEN` in the environment
510-
4. Runs a background thread that refreshes the token before it expires
511-
512-
The refresh interval defaults to 30 minutes. Override with `GITHUB_APP_TOKEN_REFRESH_INTERVAL_SECONDS`.
443+
3. Sets the token as `GITHUB_PERSONAL_ACCESS_TOKEN` for the underlying MCP server
444+
4. A background thread refreshes the token every 30 minutes
513445

514446
## Available Tools
515447

helm/holmes/templates/mcp-servers/github/deployment.yaml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,53 @@ spec:
6262
{{- end }}
6363
containers:
6464
- name: github-mcp
65+
{{- if .Values.mcpAddons.github.auth.githubApp.secretName }}
66+
image: "{{ .Values.mcpAddons.github.auth.githubApp.registry }}/{{ .Values.mcpAddons.github.auth.githubApp.image }}"
67+
{{- else }}
6568
image: "{{ .Values.mcpAddons.github.registry }}/{{ .Values.mcpAddons.github.image }}"
69+
{{- end }}
6670
imagePullPolicy: {{ .Values.mcpAddons.github.imagePullPolicy | default "IfNotPresent" }}
6771
ports:
6872
- containerPort: 8000
6973
name: http
7074
protocol: TCP
7175
args:
7276
- "--stdio"
77+
{{- if .Values.mcpAddons.github.auth.githubApp.secretName }}
78+
- "python3 /app/wrapper.py"
79+
{{- else }}
7380
- "github-mcp-server stdio"
81+
{{- end }}
7482
- "--port"
7583
- "8000"
84+
{{- if .Values.mcpAddons.github.auth.githubApp.secretName }}
85+
- "--outputTransport"
86+
- "streamableHttp"
87+
{{- end }}
7688
env:
89+
{{- if .Values.mcpAddons.github.auth.githubApp.secretName }}
90+
- name: GITHUB_APP_ID
91+
valueFrom:
92+
secretKeyRef:
93+
name: {{ .Values.mcpAddons.github.auth.githubApp.secretName }}
94+
key: GITHUB_APP_ID
95+
- name: GITHUB_APP_INSTALLATION_ID
96+
valueFrom:
97+
secretKeyRef:
98+
name: {{ .Values.mcpAddons.github.auth.githubApp.secretName }}
99+
key: GITHUB_APP_INSTALLATION_ID
100+
- name: GITHUB_APP_PRIVATE_KEY
101+
valueFrom:
102+
secretKeyRef:
103+
name: {{ .Values.mcpAddons.github.auth.githubApp.secretName }}
104+
key: GITHUB_APP_PRIVATE_KEY
105+
{{- else }}
77106
- name: GITHUB_PERSONAL_ACCESS_TOKEN
78107
valueFrom:
79108
secretKeyRef:
80-
name: {{ required "mcpAddons.github.auth.secretName is required" .Values.mcpAddons.github.auth.secretName }}
109+
name: {{ required "mcpAddons.github.auth.secretName is required for PAT auth" .Values.mcpAddons.github.auth.secretName }}
81110
key: {{ .Values.mcpAddons.github.auth.secretKey | default "token" }}
111+
{{- end }}
82112
{{- if .Values.mcpAddons.github.config.toolsets }}
83113
- name: GITHUB_TOOLSETS
84114
valueFrom:

0 commit comments

Comments
 (0)