Files
bikoret/deploy/k8s/gitea-mcp-deployment.yaml
Scott KarpandClaude Fable 5.1 53778f372e Gitea MCP connector: MCP OAuth mode on bikoret.ch
The claude.ai connector ran the OAuth flow against a server in
static-token mode, which has no OAuth endpoints: the login ended on a
404. The proper form is gitea-mcp's -oauth mode, where each user
authorizes with their own Gitea account; it needs both origins public
over HTTPS and Gitea's ROOT_URL to be that origin.

- gitea-ingress.yaml: git.bikoret.ch → temple-council/gitea, TLS
- gitea-public-patch.yaml: ROOT_URL/DOMAIN/SSH_DOMAIN = git.bikoret.ch
  (were a name that never resolved and a released NLB IP)
- gitea-mcp-deployment.yaml: -oauth -oauth-public-url
  https://mcp.bikoret.ch -H https://git.bikoret.ch, no static token,
  probes on /healthz
- gitea-mcp-ingress.yaml: host mcp.bikoret.ch (mcp.shorashim.ch retired)
- gitea-public-apply.sh / gitea-public-verify.sh: the operator's
  DNS-gated apply and read-only verification (also in ~/.local/bin)
- KOHEN.md, deploy/ARCHITECTURE.md: the new doors and the Gitea OAuth2
  app ("Claude", PKCE, claude.ai + Claude Code redirect URIs)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-19 21:55:05 +00:00

97 lines
3.0 KiB
YAML

# Gitea MCP Server — public connector for claude.ai and Claude Code
#
# Deploys the official Gitea MCP server (gitea.com/gitea/gitea-mcp)
# in HTTP mode with MCP OAuth (-oauth): every client authorizes against
# Gitea with its OWN account (PKCE, no client secret), and the server
# forwards that bearer token to Gitea per request. No shared static
# token is used any more (gitea-mcp-secrets is kept only for a rollback
# to the pre-2026-10-19 static-token mode).
#
# The server serves /.well-known/oauth-protected-resource naming Gitea
# as the authorization server, so BOTH origins must be public HTTPS:
# -oauth-public-url https://mcp.bikoret.ch (gitea-mcp-ingress.yaml)
# -H https://git.bikoret.ch (gitea-ingress.yaml;
# Gitea ROOT_URL must be the same, gitea-public-patch.yaml)
# /mcp accepts only the Host from -oauth-public-url, and reverse proxies
# must pass Mcp-Protocol-Version, Mcp-Method and Mcp-Name through
# (ingress-nginx does).
#
# One-time in Gitea (Settings → Applications → Manage OAuth2 Applications):
# name Claude
# redirect URIs https://claude.ai/api/mcp/auth_callback
# http://127.0.0.1/callback (Claude Code; any port)
# confidential UNCHECKED (PKCE)
# The client ID goes into the claude.ai connector's Advanced settings,
# with the connector URL https://mcp.bikoret.ch/mcp.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea-mcp
namespace: shorashim
labels:
app.kubernetes.io/name: gitea-mcp
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: gitea-mcp
template:
metadata:
labels:
app.kubernetes.io/name: gitea-mcp
spec:
containers:
- name: gitea-mcp
image: docker.io/gitea/gitea-mcp-server@sha256:5fad9c4a1148071fd58ed617f779115f65a13c517c20427a3b39f80cac43e600 # pinned 2026-10-06: a floating tag upgrades on any restart
command: ["/app/gitea-mcp"]
args:
- "-t"
- "http"
- "-oauth"
- "-oauth-public-url"
- "https://mcp.bikoret.ch"
- "--host"
- "https://git.bikoret.ch"
- "--port"
- "8080"
ports:
- containerPort: 8080
name: http
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: gitea-mcp
namespace: shorashim
labels:
app.kubernetes.io/name: gitea-mcp
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: gitea-mcp
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: http