Skip to content

feat(toolhive): re-enable the GitHub MCP over streamable-http - #4212

Merged
Tanguille merged 2 commits into
mainfrom
feat/github-mcp-http
Jul 27, 2026
Merged

feat(toolhive): re-enable the GitHub MCP over streamable-http#4212
Tanguille merged 2 commits into
mainfrom
feat/github-mcp-http

Conversation

@Tanguille

Copy link
Copy Markdown
Owner

Re-enables the GitHub MCP server, disabled since ToolHive v0.40.1 health monitoring re-ran initialize against its stdio backend and degraded the resources and unified gateways (upstream #5890).

Why a transport change, not a different server

Question Answer
Is there a newer toolhive that fixes it? No. v0.40.1 is latest (released 2026-07-20) and is what we pin. Issue #5890 is open, untriaged, zero linked PRs
Does the same server support HTTP? Yes, since PR #1849. Read-only enforcement in HTTP mode was broken at first and fixed by #2208, in every release from v1.0.0
Better alternative? No. octocode-mcp is stdio-only with no container image; Docker Hub mcp/github wraps the archived implementation, stdio-only, latest tag only

The part the transport change forces

http takes no server-side token. Unlike the stdio path, its ServerConfig has no Token field and it authenticates per request, so the PAT cannot stay an env var:

// cmd/github-mcp-server/main.go - stdio
stdioServerConfig := ghmcp.StdioServerConfig{ ... Token: token, ... }
// http - no Token field anywhere in httpConfig

So the PAT moves to an MCPExternalAuthConfig of type bearerToken, which makes the proxy attach it as an Authorization header. This is the first MCPExternalAuthConfig in the cluster.

Scoping

--read-only plus --toolsets context,repos,issues,pull_requests. The full server exposes ~79 tools and every one lands in the unified gateway's semantic tool index. No MCPToolConfig: toolsFilter: [] is a proven no-op (see #4211), so scoping is done on the server itself.

Verified

  • ghcr.io/github/github-mcp-server:v1.7.0 manifest exists on ghcr (amd64+arm64), released 2026-07-23
  • all three objects pass kubectl apply --dry-run=server
  • toolhive-secrets still carries GITHUB_PERSONAL_ACCESS_TOKEN

Not runtime-verified — no pods have been started. Draft until someone watches the first rollout: confirm the pod goes Ready, github_* tools appear on vmcp-resources, and the unified gateway does not report a degraded backend.

The server was disabled because ToolHive's virtual-MCP health monitoring
repeatedly sends `initialize` to stdio backends, which github-mcp-server
answers with `duplicate "initialize" received`, degrading the resources and
unified gateways (upstream #5890).

The server has supported streamable-http since PR #1849, so the fix is a
transport change rather than a different vendor: `args: [http]` instead of
`[stdio]`, on v1.7.0. Read-only enforcement in http mode was broken when it
first shipped and was fixed in #2208, which is in every release from v1.0.0.

http mode does not take a server-side token - unlike the stdio path, its
ServerConfig has no Token field and it authenticates per request. So the PAT
moves from a `secrets:` env mount to an MCPExternalAuthConfig of type
bearerToken, which makes the proxy attach it as an Authorization header. This
is the first MCPExternalAuthConfig in the cluster.

Scoped to four toolsets, since the full server exposes ~79 tools and every one
of them lands in the unified gateway's semantic tool index.

Verified: the v1.7.0 image manifest exists on ghcr.io, all four objects pass
`kubectl apply --dry-run=server`, and the referenced secret key is present.
Not yet verified at runtime - the pods have not been started.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Tanguille, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 28 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 40320871-661f-421a-aa71-713fd5bde448

📥 Commits

Reviewing files that changed from the base of the PR and between 7f352ce and 73cca9b.

📒 Files selected for processing (1)
  • kubernetes/apps/ai/toolhive/config/github.yaml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/github-mcp-http

Comment @coderabbitai help to get the list of available commands.

@tanguille-cluster

Copy link
Copy Markdown
@@ (root level) @@
# toolhive.stacklok.dev/v1beta1/MCPToolConfig/ai/github
! - one document removed:
- apiVersion: toolhive.stacklok.dev/v1beta1
- kind: MCPToolConfig
- metadata:
-   name: github
-   namespace: ai
-   labels:
-     app.kubernetes.io/name: toolhive
-     kustomize.toolkit.fluxcd.io/name: toolhive
-     kustomize.toolkit.fluxcd.io/namespace: ai
- spec:
-   toolsFilter: []

@@ (root level) @@
# toolhive.stacklok.dev/v1beta1/MCPExternalAuthConfig/ai/github
! + one document added:
+ apiVersion: toolhive.stacklok.dev/v1beta1
+ kind: MCPExternalAuthConfig
+ metadata:
+   name: github
+   namespace: ai
+   labels:
+     app.kubernetes.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/namespace: ai
+ spec:
+   type: bearerToken
+   bearerToken:
+     tokenSecretRef:
+       name: toolhive-secrets
+       key: GITHUB_PERSONAL_ACCESS_TOKEN

@@ (root level) @@
# toolhive.stacklok.dev/v1beta1/MCPServer/ai/github
! + one document added:
+ apiVersion: toolhive.stacklok.dev/v1beta1
+ kind: MCPServer
+ metadata:
+   name: github
+   namespace: ai
+   labels:
+     app.kubernetes.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/namespace: ai
+ spec:
+   resources:
+     limits:
+       cpu: 200m
+       memory: 200Mi
+     requests:
+       cpu: 10m
+       memory: 64Mi
+   image: "ghcr.io/github/github-mcp-server:v1.7.0"
+   mcpPort: 8082
+   proxyPort: 8080
+   transport: streamable-http
+   args:
+   - http
+   - "--read-only"
+   - "--toolsets"
+   - "context,repos,issues,pull_requests"
+   externalAuthConfigRef:
+     name: github
+   groupRef:
+     name: resources
+   permissionProfile:
+     name: network
+     type: builtin
+   podTemplateSpec:
+     spec:
+       containers:
+       - name: mcp
+         resources:
+           limits:
+             cpu: 500m
+             memory: 256Mi
+           requests:
+             cpu: 10m
+             memory: 64Mi

@@ (root level) @@
# toolhive.stacklok.dev/v1beta1/MCPServer/ai/github-opt
! + one document added:
+ apiVersion: toolhive.stacklok.dev/v1beta1
+ kind: MCPServer
+ metadata:
+   name: github-opt
+   namespace: ai
+   labels:
+     app.kubernetes.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/name: toolhive
+     kustomize.toolkit.fluxcd.io/namespace: ai
+ spec:
+   resources:
+     limits:
+       cpu: 200m
+       memory: 200Mi
+     requests:
+       cpu: 10m
+       memory: 64Mi
+   image: "ghcr.io/github/github-mcp-server:v1.7.0"
+   mcpPort: 8082
+   proxyPort: 8080
+   transport: streamable-http
+   args:
+   - http
+   - "--read-only"
+   - "--toolsets"
+   - "context,repos,issues,pull_requests"
+   externalAuthConfigRef:
+     name: github
+   groupRef:
+     name: all
+   permissionProfile:
+     name: network
+     type: builtin
+   podTemplateSpec:
+     spec:
+       containers:
+       - name: mcp
+         resources:
+           limits:
+             cpu: 500m
+             memory: 256Mi
+           requests:
+             cpu: 10m
+             memory: 64Mi

@Tanguille
Tanguille marked this pull request as ready for review July 27, 2026 17:55
@github-actions

Copy link
Copy Markdown

AI Automated Review

Analysis engine: qwen-3.6-fast@http://litellm.ai.svc.cluster.local/v1 (openai)

Recommendation: Approve

This PR cleanly re-enables the GitHub MCP server by switching from stdio to streamable-http transport, addressing the upstream health-check initialization bug (PR 5890). The implementation correctly handles the authentication model change (moving PAT to MCPExternalAuthConfig) and updates the image version.

Change-by-Change Findings

  1. Transport & Auth Refactor:

    • Switched transport from stdio to streamable-http for both github and github-opt servers.
    • Introduced MCPExternalAuthConfig named github with type: bearerToken. This is required because the HTTP mode does not accept a token via env vars like stdio did; instead, it relies on the proxy injecting an Authorization header.
    • Verified that externalAuthConfigRef is set on both MCPServer objects.
    • Confirmed toolhive-secrets contains GITHUB_PERSONAL_ACCESS_TOKEN (per PR body).
  2. Image Version Bump:

    • Updated ghcr.io/github/github-mcp-server from v1.6.0 to v1.7.0.
    • v1.7.0 includes MCP spec updates (go-sdk 1.7.0-pre.3) and lockdown improvements. No breaking changes identified in release notes that affect this configuration.
  3. Scoping & Args:

    • Added --read-only and --toolsets context,repos,issues,pull_requests args. This aligns with the PR description's intent to limit tool exposure (~79 tools total) and keep the optimizer index small.
    • Removed MCPToolConfig reference as noted in PR body (toolsFilter: [] is a no-op).
  4. Resources & Ports:

    • Set mcpPort: 8082 and proxyPort: 8080, matching default HTTP bindings.
    • Resource requests/limits remain unchanged from the commented-out stdio config, which is appropriate.

Standards Compliance

  • YAML Structure: Follows repository conventions for ToolHive manifests. Uses schema annotations.
  • Secrets Handling: Does not commit secrets; references existing SOPS-managed secret toolhive-secrets. Complies with AGENTS.md safety rules.
  • Commit Title: feat(toolhive): ... follows Conventional Commits.

Release Notes (github-mcp-server v1.7.0)

  • Server-to-server auth support for GitHub apps (stdio).
  • Projects tools pagination improved.
  • MCP 2026-07-28 spec compliance via go-sdk 1.7.0-pre.3.
  • Lockdown mode improvements.
  • Various dependency bumps (go-chi, docker actions, golang, distroless).

Unknowns / Needs Verification

  • Runtime Validation: As noted in the PR body, this has not been runtime-verified. Ensure pods become Ready and tools appear in the unified gateway after merge.
  • Schema Availability: The $schema URLs (k8s-schemas.home-operations.com) were not fetchable during review but are standard for this repo. Assume valid per repo history.

@Tanguille
Tanguille merged commit 0bf728f into main Jul 27, 2026
15 of 16 checks passed
@Tanguille
Tanguille deleted the feat/github-mcp-http branch July 27, 2026 18:44
Tanguille added a commit that referenced this pull request Jul 27, 2026
…4220)

The operator turns MCPExternalAuthConfig tokenSecretRef into a thv CLI store
reference and never projects the Secret, so both backends have crashlooped on
"secrets provider not configured" since #4212.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant