Aller au contenu

AI Stack : Qdrant + CLI Ollama

L’AI Stack rassemble cinq services qui collaborent pour servir tous les besoins IA de l’infrastructure : base vectorielle pour le RAG, passerelle multi-modèles compatible Ollama, mémoire de session, et deux briques MCP (Model Context Protocol) qui exposent les outils N8N aux modèles avec un contrôle d’accès strict.

ServicePortRôle
Qdrant6333Base de données vectorielle (embeddings, recherche sémantique)
CLI Ollama11434Passerelle compatible Ollama vers Codex et Gemini
Claude Redis6379Mémoire de sessions de conversation (LRU 256 MB)
MCP Gateway3001Reverse proxy MCP : whitelist d’outils + négociation SSE/JSON
N8N MCP3000Bridge MCP exposant l’API N8N aux modèles

mcp-backend (isolé)

ai-internal

MCP JSON-RPC

20 outils whitelisted

REST API key

N8N Workflows

IA Router · intent detection

Service Handler General · chat libre

Conversation Agent · sessions multi-tour

RAG · futur

Qdrant · :6333

CLI Ollama · :11434

Claude Redis · sessions

Subprocess CLI · codex / gemini

MCP Gateway · :3001 · whitelist + Bearer

N8N MCP bridge · :3000


ObjectifSolution
Pas de vendor lock-inAPI Ollama-compatible, fournisseurs interchangeables (Codex / Gemini)
Sessions cross-providerSessionRecord partage l’historique entre modèles, fallback par injection
Contrôle des outils MCPGateway whitelist + confirmation Telegram sur les actions destructrices
Profiles scopésUn même service expose des permissions différentes selon le profil (error-analyst vs n8n-admin)
RAG localQdrant self-hosted, pas de fuite de documents privés vers le cloud
Nom virtuelProviderID réelNotes
codex-maxOpenAI Codexgpt-5.1-codex-maxFrontier, agentique, tâches complexes
codexOpenAI Codexgpt-5.1-codexStandard agentique
codex-miniOpenAI Codexgpt-5.1-codex-miniPlus petit, plus économique
gemini-flashGoogle Geminigemini-2.5-flashRapide, low-cost
gemini-proGoogle Geminigemini-2.5-proLe plus capable côté Gemini
<model>-yoloTousSkip approval/confirmation flow
CritèreCodex (gpt-5.1)ClaudeGemini
Mode agentique natifOuiOui (via tool use)Limité
Sessions persistantesthread_id natifLimitésession_id natif
Coût pour les workflowsMoyenÉlevéBas
Modèles -yolo (full-auto)Oui (--full-auto)Non équivalentOui (--yolo)

Codex couvre les besoins agentiques (analyse, refactoring, génération de code). Gemini sert de fallback rapide / économique. Claude n’est plus servi par CLI Ollama : il reste utilisé directement via Claude Code côté poste développeur.


Fenêtre de terminal
# Lister les collections
curl http://localhost:6333/collections | jq '.result.collections'
# Créer une collection
curl -X PUT http://localhost:6333/collections/documents \
-H "Content-Type: application/json" \
-d '{
"vectors": { "size": 1536, "distance": "Cosine" }
}'
# Recherche vectorielle
curl http://localhost:6333/collections/documents/points/search \
-H "Content-Type: application/json" \
-d '{ "vector": [0.1, 0.2, ...], "limit": 5 }'

CLI Ollama maintient un SessionRecord par session_id qui suit l’utilisateur à travers les fournisseurs. Si on commence une conversation sur codex-max puis on bascule vers gemini-pro, l’historique précédent est ré-injecté en prefix de prompt.

oui

non, ou pas d'ID

Requête · session_id, model

get_session_record() · charge SessionRecord

Modèle inchangé ?

Native resume · Codex thread_id ou Gemini session_id

Injection d'historique · _inject_history()

Exécution CLI

record_turn() · met à jour SessionRecord + current_model

Champs de SessionRecord : session_id, current_provider, current_model, codex_thread_id, gemini_session_id, turn_count, total_tokens. Stocké en mémoire (pas de persistence Redis pour les SessionRecords eux-mêmes — l’historique des messages, lui, vit dans Claude Redis).

CLI Ollama expose plusieurs profiles YAML qui scopent les outils MCP utilisables et les modèles autorisés. Un même service rend donc des permissions différentes selon le profil envoyé dans la requête.

ProfileOutils autorisésOutils avec approbationKnowledge base
error-analyst5 read-only (n8n_get_workflow, n8n_executions, …)aucunDLQ format, workflow architecture
n8n-admin5 read + 2 writen8n_update_partial_workflow, n8n_update_full_workflowAdmin guide

Les fichiers .md listés dans knowledge_base sont injectés dans le system prompt à chaque requête, donnant au modèle un contexte stable sans le réenvoyer à chaque tour.

MCP Gateway (whitelist + négociation de transport)

Section intitulée « MCP Gateway (whitelist + négociation de transport) »

mcp-gateway est un reverse proxy MCP qui s’interpose entre cli-ollama et n8n-mcp. Il assure trois rôles :

  1. Whitelist d’outils côté serveur — bloque tout outil hors de la liste avant que la requête atteigne n8n-mcp.
  2. Négociation de transport — demande toujours du SSE en upstream, puis re-formate selon le Accept du client (Claude CLI préfère JSON, Codex CLI préfère SSE/rmcp).
  3. Bearer auth + isolation réseaumcp-backend n’est pas joignable depuis ai-internal autrement que via la gateway.

Outils whitelistés (20) : tous les outils nécessaires (n8n_list_workflows, n8n_get_workflow, n8n_validate_workflow, tools_documentation, search_nodes, get_node, validate_node, search_templates, get_template, validate_workflow, n8n_executions, n8n_health_check, n8n_create_workflow, n8n_update_full_workflow, n8n_update_partial_workflow, n8n_delete_workflow, n8n_deploy_template, n8n_autofix_workflow, n8n_test_workflow, n8n_workflow_versions).

Outils critiques (7) — passent la whitelist mais nécessitent confirmation Telegram avant exécution : n8n_create_workflow, n8n_update_full_workflow, n8n_update_partial_workflow, n8n_delete_workflow, n8n_deploy_template, n8n_autofix_workflow, n8n_test_workflow. La confirmation est gérée par mcp_confirmation.py côté cli-ollama qui poste un webhook au workflow MCP Confirmation Handler.

n8n-mcp est le serveur MCP qui expose réellement les outils N8N. Il s’authentifie auprès de l’API REST N8N via une API key (N8N_MCP_API_KEY), et exige un Bearer token (N8N_MCP_AUTH_TOKEN) côté client MCP.

Fenêtre de terminal
# Tester la chaîne complète depuis le host (via gateway)
curl -X POST http://127.0.0.1:3001/mcp \
-H "Authorization: Bearer ${N8N_MCP_AUTH_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Approved

Rejected/Expired

N8N Telegram Orchestrator

Affiche le plan ou la question

Boutons inline keyboard

CLI Ollama

Détecte tool_use ou question

Webhook N8N + état Pending

Attend approbation · timeout 5 min

Requête · non-YOLO

Décision

Exécution réelle

Réponse 'Rejected'

Retour résultat

Hooks pluggables (pre_tool_use, post_tool_use, on_response, on_error) permettent d’ajouter des règles transverses sans toucher aux providers.

// Intent detection (mode non-streaming, sans approbation)
{
"url": "http://cli-ollama:11434/api/generate",
"method": "POST",
"body": {
"model": "codex-yolo",
"prompt": "Analyse ce message Telegram et retourne un JSON …",
"stream": false
}
}
// Avec profile et MCP outils restreints
{
"model": "codex-yolo",
"prompt": "Inspecte le workflow X et propose un fix",
"profile": "error-analyst",
"mcp_config": "{\"allowed_tools\": [\"n8n_get_workflow\", \"n8n_executions\"]}"
}
ServiceMemory limitCPU
Qdrant4 GB2 vCPU
CLI Ollama4 GB2 vCPU
Claude Redis512 MB
MCP Gateway128 MB
N8N MCP256 MB

LimiteImpactMitigation
Qdrant peu peupléPas de RAG production aujourd’huiImport progressif depuis l’Obsidian vault
Embeddings via API externeDépendance OpenAI pour la vectorisationModèle local d’embeddings envisageable
Pas de streaming SessionRecordLes conversations en streaming ne capitalisent pas l’historiqueRoadmap : recorder les chunks streaming en mémoire
SessionRecord en mémoirePerte au restart containerPersistence Redis prévue post-MVP
Codex / Gemini cloudCoût + dépendance externeCaching Redis pour intent detection, modèles -yolo pour les hot paths

Si le RAG entre en production :

  • Worker N8N qui ingère l’Obsidian vault dans une collection Qdrant dédiée.
  • Profile obsidian-rag côté CLI Ollama avec un knowledge base + outils de recherche.
  • Pattern : embeddings via OpenAI, recherche Qdrant, prompt enrichi côté CLI Ollama.

Si je veux ajouter un autre provider :

  • Implémenter ProviderProtocol dans services/providers/<name>.py.
  • Ajouter le mapping virtual-name → real-model dans config.py.
  • Le SessionRecord et les hooks fonctionnent automatiquement (interface unifiée ExecutionMessage).

Si les coûts API montent :

  • Étendre le caching Claude Redis aux réponses fréquentes (intent detection notamment).
  • Router les requêtes simples vers gemini-flash (le moins cher) via l’IA Router.
  • Activer un rate-limit côté cli-ollama par session_id.

Si la sécurité MCP doit être plus stricte :

  • Réduire la whitelist gateway aux 5 outils read-only seulement.
  • Ajouter des profiles spécifiques par cas d’usage (au lieu d’un n8n-admin permissif).
  • Étendre la confirmation Telegram à plus d’outils (actuellement 7 critiques sur 20).
Fenêtre de terminal
# Health checks
curl http://localhost:6333/healthz # Qdrant
curl http://localhost:11434/api/tags # CLI Ollama
docker logs cli-ollama --tail 100
# Approbations en attente
curl http://cli-ollama:11434/api/approvals
curl http://cli-ollama:11434/api/questions
# Tester la chaîne MCP gateway → n8n-mcp
curl -X POST http://127.0.0.1:3001/mcp \
-H "Authorization: Bearer $N8N_MCP_AUTH_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq .result.tools[].name
# Vérifier l'isolation réseau
docker network inspect mcp-backend | jq '.[0].Containers'

  • Glossaire — RAG, Embeddings, Vector Database, MCP, LLM