add common/baserow-mcp-oauth-fix.md (fix connecteur Claude.ai Baserow MCP)
This commit is contained in:
@@ -0,0 +1,87 @@
|
|||||||
|
# baserow-mcp-oauth-fix — sidecar OAuth devant Baserow (28/07/2026)
|
||||||
|
|
||||||
|
**Statut** : deploye, teste bout-en-bout. Reste 1 action manuelle (voir "Action restante").
|
||||||
|
|
||||||
|
## Probleme
|
||||||
|
|
||||||
|
Connecteur Claude.ai vers Baserow MCP (`https://baserow.bolbol.tn/mcp/<token>/sse`) :
|
||||||
|
« Impossible de s'inscrire aupres du service de connexion de Baserow ».
|
||||||
|
|
||||||
|
**Cause** : meme piege que `mcp-vps.md`/`mcp-nas` — Claude.ai sonde systematiquement
|
||||||
|
`/.well-known/oauth-authorization-server`, `/.well-known/oauth-protected-resource` et
|
||||||
|
`POST /register` a l'ajout d'un connecteur MCP personnalise, meme quand le serveur
|
||||||
|
cible n'a besoin d'aucune auth (la vraie protection Baserow = le token secret deja
|
||||||
|
dans l'URL `/mcp/<token>/sse`). Baserow (Caddy + Nuxt) renvoie 404 (page Nuxt
|
||||||
|
generique, pas une 404 backend) sur ces 3 routes → echec du handshake connecteur.
|
||||||
|
|
||||||
|
**Difference avec mcp-vps/mcp-nas** : ceux-la sont du code Python maison, patchable
|
||||||
|
directement. Baserow est l'image officielle (watchtower la met a jour) — impossible
|
||||||
|
de patcher son code source sans que ca saute au prochain rebuild/update.
|
||||||
|
|
||||||
|
## Fix
|
||||||
|
|
||||||
|
Sidecar devant Baserow, **sans toucher a l'image Baserow** :
|
||||||
|
`/volume1/docker/baserow-oauth-stub` (2 containers, reseau `n8n` uniquement) :
|
||||||
|
|
||||||
|
- **baserow-oauth-app** (Starlette/uvicorn, build local, pas de port publie) :
|
||||||
|
`/register`, `/authorize`, `/token` — meme pattern PKCE que `linux_mcp_server.py`
|
||||||
|
(mcp-vps), `CLIENT_ID = claude-baserow-mcp`, tokens jamais verifies ailleurs
|
||||||
|
(la seule vraie protection reste le token dans l'URL Baserow).
|
||||||
|
- **baserow-oauth-proxy** (nginx:alpine, port **3887**→80, reseau `n8n`) :
|
||||||
|
- `/.well-known/oauth-authorization-server` et `/.well-known/oauth-protected-resource(/*)`
|
||||||
|
→ JSON statique (fichiers montes en volume, pas de logique dynamique necessaire)
|
||||||
|
- `/register`, `/authorize`, `/token` → proxy vers `baserow-oauth-app:8080`
|
||||||
|
- `location /` (tout le reste : app web, API, `/ws/*`, `/mcp/*/sse`) → proxy
|
||||||
|
transparent vers `baserow:80` (alias Docker du container Baserow sur le reseau
|
||||||
|
`n8n`), avec support WebSocket (`map $http_upgrade $connection_upgrade`) et SSE
|
||||||
|
(`proxy_buffering off`, `proxy_read_timeout 3600s`, `chunked_transfer_encoding on`).
|
||||||
|
|
||||||
|
## Gotcha reseau (couteux a redecouvrir)
|
||||||
|
|
||||||
|
Premiere tentative : 2 services sur un reseau `default` cree par le compose (nouveau
|
||||||
|
bridge custom) + le service nginx en plus sur `n8n`. Resultat : **ping fonctionne
|
||||||
|
entre les 2 containers, mais toute connexion TCP (nc, wget, proxy_pass) time out**
|
||||||
|
en silence (502/504 selon le point de test) — alors que Baserow lui-meme (deja sur
|
||||||
|
`n8n`) passait sans probleme. Hypothese : regle firewall (crowdsec-firewall-bouncer
|
||||||
|
ou iptables DOCKER-USER) qui n'autorise le trafic TCP inter-conteneurs que sur les
|
||||||
|
reseaux Docker deja connus/etablis (`n8n`), pas sur un reseau tout juste cree.
|
||||||
|
**Fix : mettre les 2 services UNIQUEMENT sur le reseau externe `n8n` (pas de reseau
|
||||||
|
`default` supplementaire)** — resout immediatement le probleme, ping ET TCP passent.
|
||||||
|
A retenir pour tout futur sidecar : privilegier un reseau externe deja peuple plutot
|
||||||
|
qu'un nouveau bridge, si un blocage TCP-mais-pas-ICMP apparait entre 2 conteneurs.
|
||||||
|
|
||||||
|
## Tests de validation (28/07/2026)
|
||||||
|
|
||||||
|
Tous compares en baseline (direct port 3888, bypass total du sidecar) vs via le
|
||||||
|
proxy (port 3887) :
|
||||||
|
|
||||||
|
| Test | Baseline 3888 | Via proxy 3887 |
|
||||||
|
|---|---|---|
|
||||||
|
| `/.well-known/oauth-authorization-server` | 404 (Baserow) | 200 JSON statique |
|
||||||
|
| `/.well-known/oauth-protected-resource` | 404 (Baserow) | 200 JSON statique |
|
||||||
|
| `POST /register` | 404 (Baserow) | 201, `client_id: claude-baserow-mcp` |
|
||||||
|
| `GET /authorize` + PKCE S256 → `POST /token` | n/a | 200, `access_token` + `refresh_token` |
|
||||||
|
| `GET /mcp/<token>/sse` (bon Host header) | 200, event `endpoint` | 200, event `endpoint` identique |
|
||||||
|
| `GET /` (app web) | 302 (redirect login) | 302 identique |
|
||||||
|
| `GET /api/_health/` | 200 | 200 identique |
|
||||||
|
| Upgrade WebSocket `/ws/core/` | 101 Switching Protocols | 101 identique |
|
||||||
|
|
||||||
|
**Piege methodologique note en passant** : tester `/mcp/<token>/sse` en `curl` direct
|
||||||
|
sur le port 3888 SANS forcer `Host: baserow.bolbol.tn` renvoie un faux-negatif (404
|
||||||
|
JSON generique Nuxt) — le Caddyfile de Baserow route `/api/* /ws/* /mcp/* /assistant/*`
|
||||||
|
vers le backend uniquement si l'expression `@is_baserow_tool` matche `BASEROW_PUBLIC_URL`
|
||||||
|
sur le Host recu ; sinon fallback silencieux vers le frontend Nuxt qui 404 proprement.
|
||||||
|
Toujours forcer le bon Host en test local.
|
||||||
|
|
||||||
|
## Action restante (manuelle, root DSM — meme pattern que cin.bolbol.tn/formation.bolbol.tn)
|
||||||
|
|
||||||
|
Reverse-proxy DSM `baserow.bolbol.tn` : changer la destination **3888 → 3887**.
|
||||||
|
Seul geste necessaire ; reversible en 10 secondes (remettre 3888) si probleme.
|
||||||
|
Apres bascule : reconnecter le connecteur Baserow dans claude.ai (Parametres →
|
||||||
|
Connecteurs) pour relancer le handshake OAuth avec les nouveaux endpoints.
|
||||||
|
|
||||||
|
## Fichiers
|
||||||
|
|
||||||
|
`/volume1/docker/baserow-oauth-stub/` : `oauth_app.py`, `Dockerfile`, `nginx.conf`,
|
||||||
|
`oauth-authorization-server.json`, `oauth-protected-resource.json`, `docker-compose.yml`
|
||||||
|
(miroir complet pousse dans ce commit, sous `common/baserow-oauth-stub/`).
|
||||||
Reference in New Issue
Block a user