runbook: addendum endpoint /mcp casse (SDK mismatch) + verification end-to-end

This commit is contained in:
2026-07-30 08:22:06 +00:00
parent 56ac1eeba3
commit 5f5de0e119
@@ -31,3 +31,30 @@ Fonctions ajoutees dans `models.py` : `add_memory_entry`, `list_memory_entries`,
## Push Gitea sans git ## Push Gitea sans git
`git` absent de mcp-nas et de la session SSH nas-host. Push via API Contents Gitea (`PUT .../contents/{path}` avec `sha` courant recupere par un `GET` prealable, `POST` si creation) plutot que `git push` — pattern deja documente dans `common/git-push-depuis-mcp-nas.md`, confirme fonctionnel ici aussi pour des fichiers Python (pas seulement Markdown). `git` absent de mcp-nas et de la session SSH nas-host. Push via API Contents Gitea (`PUT .../contents/{path}` avec `sha` courant recupere par un `GET` prealable, `POST` si creation) plutot que `git push` — pattern deja documente dans `common/git-push-depuis-mcp-nas.md`, confirme fonctionnel ici aussi pour des fichiers Python (pas seulement Markdown).
## Addendum (30/07/2026, meme session) : endpoint /mcp casse depuis toujours
Test end-to-end du correctif (demande explicite de Nabil, "teste-le toi-meme") a revele que `/mcp` n'avait
**jamais fonctionne** avec le SDK `mcp` 1.28.0 installe : `SseServerTransport` n'expose plus
`handle_sse()`/`read_stream()`/`write_stream()` (API d'une version anterieure). Trois bugs caches
par cette rupture d'API, corriges dans le meme passage :
1. **Transport casse** : reecrit selon le pattern officiel du SDK (`connect_sse()` comme context manager
async, un seul `SseServerTransport` partage au lieu d'un par connexion).
2. **Double envoi ASGI** : `connect_sse()` et `handle_post_message()` envoient chacun leur reponse HTTP
completement par eux-memes. Les faire passer par des routes FastAPI classiques (`Depends` + `return`)
fait que FastAPI tente un second envoi -> `RuntimeError: Unexpected ASGI message 'http.response.start'
sent, after response already completed`. Fix : montage ASGI brut (`router.mount`), auth X-API-Key geree
a la main (plus de `Depends(get_current_agent)` sur ce endpoint precis).
3. **Chemin double** : `SseServerTransport("/mcp/messages")` + montage a `/mcp` -> le SDK calcule
`root_path + endpoint` = `/mcp` + `/mcp/messages` = `/mcp/mcp/messages` (invalide). Fix : configurer
le transport avec `/messages` seul.
**Verification finale** : test end-to-end via vrai client MCP SDK (pas curl -- protocole SSE bidirectionnel
non testable simplement), commite dans `app/test_security_mcp_context.py`. 5 scenarios : GEMINI refuse sur
scope `tt` (lecture), GEMINI refuse meme en usurpant `agent=CLAUDE` dans les arguments (ancien vecteur),
GEMINI autorise sur son propre scope `llm` (non-regression), CLAUDE autorise sur `tt` (acces legitime
toujours fonctionnel), verification directe DB qu'aucune ecriture usurpee n'a atterri dans `tt`. Les 5
passent. Le endpoint MCP de context-hub est maintenant reellement fonctionnel et securise -- pas juste
"corrige sur le papier".