docs: section vue générale et workflow des interactions MCP
FlowDeck CI / test (push) Failing after 17s
FlowDeck CI / docker (push) Skipped

This commit is contained in:
2026-09-08 08:53:04 -04:00
parent bb12763a41
commit f84ff201ea
+106
View File
@@ -13,6 +13,9 @@
1. [Verdict : est-ce une bonne idée ?](#1-verdict)
2. [Ce que FlowDeck a déjà (l'essentiel est fait)](#2-ce-que-flowdeck-a-déjà)
3. [Positionnement : deux rôles complémentaires](#3-positionnement)
- [3.1 Vue générale des interactions](#31-vue-générale-des-interactions)
- [3.2 Workflow d'un échange avec un agent externe](#32-workflow-dun-échange-avec-un-agent-externe)
- [3.3 Les agents internes passent-ils par le MCP ?](#33-les-agents-internes-passent-ils-par-le-mcp-)
4. [Architecture cible](#4-architecture-cible)
5. [Services offerts par le serveur MCP](#5-services-offerts)
6. [Plan d'implémentation pas à pas](#6-plan-dimplémentation)
@@ -116,6 +119,109 @@ Deux surfaces agentiques, complémentaires — **ne pas confondre** :
Le serveur MCP **ne contient pas de LLM** : il exécute les outils demandés par le client. C'est le client
(claude, cursor, openclaw…) qui décide quoi appeler. Le code de raisonnement n'est pas dupliqué.
### 3.1 Vue générale des interactions {#31-vue-générale-des-interactions}
Deux portes d'entrée distinctes, **un seul socle commun** :
```
CHEMIN A — AGENTS EXTERNES CHEMIN B — AGENT INTERNE
(serveur MCP, NOUVEAU) (UI existante, INCHANGÉE)
Claude Desktop ─┐ Utilisateur (navigateur)
Cursor ├─ MCP stdio ───┐ │
OpenClaw/Hermes ├─ MCP HTTP ────┼──┐ │ chat 🤖 + @mentions
npx mcp-remote ─┘ │ │ ▼
┌───────────▼──▼──────────────┐ ┌─────────────────────────┐
│ Serveur MCP │ │ AgentEngine (ReAct) │
│ app/mcp_server.py │ │ boucle raisonnement↔act │
│ auth token `fd_*` │ │ streaming SSE vers l'UI │
└───────────┬─────────────────┘ └────────────┬────────────┘
│ calls d'outils │ function calls
┌───────────▼──────────────────────────────────▼─────────────┐
│ ToolRegistry — 22 outils │
│ search · read · create · update · delete · gitea · … │
└───────────┬────────────────────────────────────────────────┘
│
┌───────────▼───────────────┐
│ PermissionManager │ ← mêmes ACL pour les deux chemins
│ agent_actions (audit+undo)│
└───────────┬───────────────┘
│
┌───────────▼───────────────┐
│ SQLite · API Gitea/GitHub │
└───────────────────────────┘
```
**À retenir :** les agents externes (chemin A) et l'agent interne (chemin B) ne se rencontrent
jamais « en vol » — ils **convergent** sur le même `ToolRegistry`, passent par les mêmes
`PermissionManager` et le même journal `agent_actions`. Une action faite par Claude Desktop arrive
au même endroit et avec les mêmes règles qu'une action faite par l'agent intégré au navigateur.
### 3.2 Workflow d'un échange avec un agent externe {#32-workflow-dun-échange-avec-un-agent-externe}
Exemple réel : un utilisateur demande à Claude Desktop *« crée une collection Sprint 27 avec les
issues ouvertes du dépôt bruno/flowdeck »*.
```
Claude Desktop Serveur MCP ToolRegistry / Perms / SQLite
│ │ │
│ 1. initialize (handshake) │ │
│─────────────────────────────▶│ │
│ 2. tools/list │ │
│─────────────────────────────▶│ │
│ ◀── 22 outils + schémas │ │
│ (JSON Schema exacts) │ │
│ │ │
│ 3. tools/call │ │
│ "sync_gitea" │ │
│ {owner:"bruno", │ │
│ repo:"flowdeck"} │ │
│─────────────────────────────▶│ 4. résolution user_id │
│ │ (Bearer fd_* → users.id) │
│ │ 5. PermissionManager │
│ │ assert_can(...) │
│ │ 6. execute() → GET issues │
│ │ Gitea + INSERT collection│
│ │ 7. journal agent_actions │
│ │ (payload + undo snapshot)│
│ ◀── résultat JSON │ │
│ {status:"success", │ │
│ data:{collection_id, │ │
│ issues:N}} │ │
│ │ │
│ 8. tools/call "create_page" │ (même séquence 4→7 : │
│ … contenu du CR… │ perms → execute → audit) │
```
Le client MCP orchestre : il décide seul d'enchaîner `sync_gitea` puis `create_page` (ou
`create_document`, `create_gitea_issue`…). Le serveur ne fait que **vérifier, exécuter, auditer** —
l'équivalent de ce que fait `AgentEngine` côté interne, mais sans LLM et sans streaming UI.
### 3.3 Les agents internes passent-ils par le MCP ? {#33-les-agents-internes-passent-ils-par-le-mcp-}
**Non. L'agent interne continue d'appeler directement le `ToolRegistry`** — et c'est une décision
d'architecture, pas un oubli. Le serveur MCP est la porte d'entrée des agents **externes uniquement**.
| Critère | Agent interne → ToolRegistry (direct) | Agent interne → serveur MCP (contournement) |
|---|---|---|
| Streaming SSE (raisonnement + actions live) | événements natifs | **perdu** — le MCP est atomique requête/réponse |
| Contexte (user, workspace, @mentions, page ouverte) | déjà en mémoire dans `AgentEngine` | à re-transmettre à chaque appel |
| Mode approval interactif (`confirm`) | fonctionne (dialogue dans l'UI) | impossible — pas d'humain pour confirmer |
| Surcharge | aucune | sérialisation JSON-RPC + re-auth à chaque outil |
| Bénéfice | — | **aucun** : mêmes outils, mêmes permissions, même base |
Un mauvais aiguillage (agent interne → MCP → ToolRegistry) créerait une boucle hermétique :
l'agent interne n'est pas un « agent externe », il vit **dans** FlowDeck et possède déjà tout ce
dont le MCP aurait besoin d'être re-sécurisé. Réutiliser le serveur MCP en interne reviendrait à
faire transiter des appels locaux par un protocole réseau sans protection supplémentaire.
**Ce que ça ne change pas :** les deux chemins respectent exactement les mêmes règles
(permissions, audit, rollback), donc un agent externe ne peut ni voir ni modifier plus de choses
que l'agent interne ou l'utilisateur lui-même. Et si un jour l'agent interne doit *consommer*
des serveurs MCP externes (rôle client, façon « External Agents » de Notion), c'est une
fonctionnalité séparée — documentée dans `Guide_Complet_Notion_AI.md` — qui n'entre pas en conflit
avec le serveur décrit ici.
---
## 4. Architecture cible {#4-architecture-cible}