Files
Docker-Container/Gitea MCP Connector/README.md
T

106 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gitea MCP Connector
Stellt die [Forgejo/Gitea](https://git.vogt.de.com)-API als MCP-Server (Model Context Protocol) per HTTP bereit, damit Claude (claude.ai / Claude Desktop) lesend und schreibend auf Repositories, Issues, Pull Requests, Wiki-Seiten etc. zugreifen kann.
Basiert auf dem Open-Source-Projekt [ronmi/forgejo-mcp](https://github.com/ronmi/forgejo-mcp).
## Architektur
```
Claude Desktop (mcp-remote Bridge, --header X-Api-Key)
│ HTTPS
Pangolin Reverse Proxy (gitea-mcp.vogt.de.com)
- terminiert TLS
- prüft HTTP-Header X-Api-Key
│ HTTP intern
gitea-mcp Container (Docker, Port 8080, HTTP-Transport)
Gitea/Forgejo-Instanz (git.vogt.de.com) via REST-API + FORGEJOMCP_TOKEN
```
## Docker Compose
```yaml
services:
gitea-mcp:
image: ronmi/forgejo-mcp:latest
container_name: gitea-mcp
restart: always
command: http --address :8080 --server https://git.vogt.de.com
environment:
FORGEJOMCP_TOKEN: '${FORGEJOMCP_TOKEN}'
ports:
- '8081:8080'
```
`.env`:
```
FORGEJOMCP_TOKEN=<Gitea/Forgejo API-Token, idealerweise von einem dedizierten Service-User>
```
## Reverse Proxy (Pangolin)
- **Target:** `http://<docker-host-ip>:8081`
- **Domain:** `gitea-mcp.vogt.de.com`
- **Pfad:** `/` (kein Pfad-Rewrite die volle URL für Claude lautet `https://gitea-mcp.vogt.de.com/mcp`)
- **Absicherung:** HTTP-Header-Regel, identisch zum Muster bei `mealie-mcp`:
- Header-Name: `X-Api-Key`
- Value: zufälliger Secret-String (`openssl rand -hex 32`)
- Ohne korrekten Header blockt Pangolin den Request bereits auf Proxy-Ebene, bevor er den Container erreicht.
**Wichtig:** `FORGEJOMCP_TOKEN` (App-Token gegenüber der Gitea-API) und `X-Api-Key` (Pangolin-Proxy-Secret) sind zwei unabhängige Werte und dürfen nicht verwechselt werden genau wie bei `MEALIE_API_TOKEN` vs. `X-Api-Key` beim Mealie-Connector.
## Verbindung mit Claude
Wie beim Mealie-Connector läuft die Verbindung über die **lokale `mcp-remote`-Bridge in Claude Desktop**, da claude.ai-Custom-Connectors keine zuverlässige Möglichkeit bieten, eigene HTTP-Header mitzugeben.
In der Claude-Desktop-Config (`claude_desktop_config.json`, Menü *Konnektoren → Lokale MCP-Server → Config bearbeiten*):
```json
{
"mcpServers": {
"gitea": {
"command": "npx",
"args": [
"mcp-remote",
"https://gitea-mcp.vogt.de.com/mcp",
"--header",
"X-Api-Key:${GITEA_MCP_KEY}"
],
"env": {
"GITEA_MCP_KEY": "<gleicher Secret-Wert wie im Pangolin-Header>"
}
}
}
}
```
Danach Claude Desktop neu starten. Die Gitea-Tools (Repos, Issues, Pull Requests, Wiki, Releases, …) stehen dann in jedem Chat zur Verfügung.
## Testen
Handshake ohne Header (sollte von Pangolin blockiert werden, sobald der Header aktiv ist):
```bash
curl -i https://gitea-mcp.vogt.de.com/mcp
```
Vollständiger MCP-Handshake mit korrekten Headern:
```bash
curl -X POST https://gitea-mcp.vogt.de.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "X-Api-Key: <secret>" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
```
Eine erfolgreiche Antwort enthält `serverInfo` mit `"name":"gitea"` (bzw. dem vom Server gemeldeten Namen).
## Sicherheitshinweise
- Der `gitea-mcp`-Server selbst hat **keine eigene Authentifizierung** wer die URL ohne den `X-Api-Key`-Schutz erreicht, hat vollen Zugriff auf alle Repos, die für `FORGEJOMCP_TOKEN` sichtbar sind (inkl. Schreibrechte, je nach Token-Scope).
- Empfohlen: dedizierter Gitea-Service-User mit möglichst eng gefasstem Token-Scope statt eines Admin-Tokens für `FORGEJOMCP_TOKEN`.
- Der Secret-Wert für `X-Api-Key` muss identisch in Pangolin und in der Claude-Desktop-Config gepflegt werden.
- Da im Compose-File aktuell ein Klartext-Token vorkam: Token in Gitea rotieren/neu ausstellen, sobald der bisherige Wert irgendwo (z. B. Chat-Verlauf) sichtbar war, und stattdessen über `.env` einbinden (siehe oben).