Table of Contents

🇬🇧 English version

Intégration MCP (Model Context Protocol)

Statut : expérimental ([Experimental("ORKEXP004")] sur chaque type MCP — voir APIs expérimentales). Bi-génération depuis PUB-07. Code : src/core/Orkeon.Infrastructure/MCP/.

L'intégration MCP fonctionne dans les deux sens :

  • Client — McpClient parle JSON-RPC Ă  un serveur MCP externe ; McpToolProvider se connecte Ă  un nombre quelconque de serveurs, liste leurs outils et enregistre chacun dans l'IToolRegistry d'Orkeon sous forme d'McpToolAdapter (IBaseTool) : les agents utilisent les outils MCP externes comme des outils natifs. DisconnectServerAsync les dĂ©senregistre.
  • Serveur — McpServer expose les outils de l'IToolRegistry d'Orkeon aux clients MCP externes (tools/list / tools/call, avec conversion ToolSchema → JSON Schema), sur stdio (RunStdioAsync) ou par traitement de requĂŞtes individuelles (ProcessRequestAsync).

Négociation de version : deux lignées de protocole

McpProtocol déclare ce que les deux côtés parlent :

  • LignĂ©e moderne, sans Ă©tat — ModernVersion = "2026-07-28". Pas de handshake : chaque requĂŞte porte _meta (io.modelcontextprotocol/protocolVersion, clientInfo, clientCapabilities) ; la dĂ©couverte des capacitĂ©s est la mĂ©thode server/discover.
  • LignĂ©e legacy Ă  initialize — SupportedLegacyVersions = ["2025-11-25", "2025-06-18", "2024-11-05"] : handshake initialize classique suivi du notifications/initialized obligatoire. 2025-03-26 est dĂ©libĂ©rĂ©ment exclue : c'est la seule rĂ©vision qui impose le batching JSON-RPC, que cette implĂ©mentation ne parle pas.

Client (McpClient.ConnectAsync)

  1. Sonde avec server/discover (en déclarant 2026-07-28 dans _meta).
  2. Succès avec supportedVersions → serveur moderne ; adoption de la révision la plus récente supportée des deux côtés. Un succès sans supportedVersions est un serveur legacy répondant avec indulgence à une méthode inconnue → repli sur initialize.
  3. Erreur -32022 UnsupportedProtocolVersionError → serveur moderne quand même ; lecture de sa liste supportée dans les données de l'erreur, renégociation, nouvelle tentative de server/discover.
  4. Toute autre erreur → serveur legacy ; handshake initialize, qui négocie réellement (la révision choisie par le serveur est acceptée si le client la supporte) et se termine par notifications/initialized.

Sur une connexion moderne établie, chaque requête porte son _meta ; un -32022 en cours de route déclenche une renégociation + une nouvelle tentative avec une révision supportée des deux côtés (McpClient.SendAsync).

Serveur (McpServer) — bi-génération sur un même endpoint

  • ImplĂ©mente server/discover (versions supportĂ©es, capacitĂ©s, indices de fraĂ®cheur ttlMs/cacheScope, identitĂ© du serveur dans le _meta du rĂ©sultat).
  • Une requĂŞte dĂ©clarant une version _meta non supportĂ©e est rejetĂ©e en -32022 avec le payload { supported, requested }, quelle que soit la mĂ©thode.
  • Le initialize legacy renvoie la rĂ©vision demandĂ©e quand elle est supportĂ©e, sinon la rĂ©vision legacy la plus rĂ©cente. ping reste servi pour les sessions legacy seulement (retirĂ© de la lignĂ©e moderne).
  • tools/list est renvoyĂ© en ordre dĂ©terministe (tri ordinal par nom — un SHOULD de 2026-07-28, pour des caches clients stables) avec les champs modernes resultType/ttlMs/cacheScope ; les clients legacy ignorent ces membres additifs.
  • Les notifications (sans id, ou notifications/*) ne reçoivent jamais de rĂ©ponse.

Transports

Transport Classe Notes
stdio StdioMcpTransport Lance le processus serveur (McpServerConfig.Command/Args) ; un message JSON-RPC par ligne ; la corrélation des réponses est agnostique de l'id (les ids nombre ou chaîne font l'aller-retour).
HTTP SseMcpTransport Forme Streamable HTTP, mode réponse JSON : un POST par message. Les requêtes modernes portent les en-têtes MCP-Protocol-Version, Mcp-Method et Mcp-Name (dérivés du message lui-même) ; un corps de réponse encadré SSE (text/event-stream) est déballé jusqu'à son payload data: final. Les flux initiés par le serveur ne sont pas consommés.

Activation

services.AddOrkeonMcp(configuration);   // lit la section "MCP"

AddOrkeonMcp lie McpOptions (Enabled, EnableServer, Servers — un dictionnaire de McpServerConfig : Transport stdio/sse, Command/Args ou Url) et enregistre McpToolProvider en singleton ; McpServer (+ McpServerOptions depuis MCP:Server : Name, Version) n'est enregistré que si MCP:EnableServer = true. La surcharge AddOrkeonInfrastructure(IConfiguration) appelle elle-même AddOrkeonMcp.

L'hôte partagé des runners honore la section de lui-même (STUDIO-21). orkeon run — et tout runner bâti sur RunnerHost — appelle AddOrkeonMcp dès que MCP:Servers déclare au moins un serveur et que MCP:Enabled n'est pas false, puis connecte chaque serveur dans un pas de démarrage explicite (McpStartup) avant le chargement de la crew — et avant que --validate juge la crew et que --list-tools imprime le manifeste, pour que les trois voient la même surface d'outils. Un serveur qui ne peut pas être connecté (commande inexistante, point de terminaison muet, poignée de main toujours en attente après 30 s) coûte une ligne d'erreur qui le nomme, dans le journal et sur stderr, et le run continue : une crew qui nomme un outil de ce serveur échoue alors au chargement, sous StrictTools, avec la ligne ordinaire « unknown tool ». Les outils sont enregistrés sous leur propre nom, sans préfixe de serveur ; un nom déjà tenu par le registre est ignoré. Orkeon Studio écrit la section depuis son onglet « Réglages › MCP ». Les autres racines livrées (orkeon-host, le REPL) appellent toujours la surcharge sans paramètre : là, et dans tout hôte qui embarque, MCP reste une surface bibliothèque — l'hôte appelle lui-même AddOrkeonMcp(configuration) (ou la surcharge config).

Il n'y a pas de hosted service : un hôte qui embarque résout McpToolProvider et appelle explicitement ConnectServerAsync(serverId, config) pour chaque serveur configuré (et McpServer.RunStdioAsync() pour servir) — exactement ce que fait le pas de démarrage de l'hôte des runners.

Limites honnĂŞtes

Alignées sur Limitations connues et l'entrée PUB-07 du changelog :

  • Pas de subscriptions/listen — les notifications de changement poussĂ©es par le serveur ne sont pas consommĂ©es.
  • Pas de requĂŞtes multi-aller-retour (MRTR) — un rĂ©sultat intermĂ©diaire moderne input_required remonte comme une erreur d'outil explicite, jamais comme des donnĂ©es partielles.
  • Pas d'autorisation MCP (OAuth).
  • HTTP = mode rĂ©ponse JSON uniquement — en-tĂŞtes modernes envoyĂ©s, corps SSE dĂ©ballĂ©s, mais pas de streaming initiĂ© par le serveur.
  • 2025-03-26 exclue (batching JSON-RPC obligatoire).
  • L'interop contre les serveurs de rĂ©fĂ©rence (MCP Inspector) n'a pas encore tournĂ© — suivie dans la note de clĂ´ture de PUB-07.

Statut expérimental

Chaque type MCP porte [Experimental("ORKEXP004")] : y faire référence depuis votre code est une erreur de compilation tant que le diagnostic n'est pas supprimé — cette suppression vaut opt-in et reconnaissance que la surface (notamment les types wire) peut encore bouger. Voir APIs expérimentales.


Voir aussi : Sous-systèmes opt-in · APIs expérimentales · Limitations connues · Retour à l'index