🇬🇧 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 —
McpClientparle JSON-RPC à un serveur MCP externe ;McpToolProviderse connecte à un nombre quelconque de serveurs, liste leurs outils et enregistre chacun dans l'IToolRegistryd'Orkeon sous forme d'McpToolAdapter(IBaseTool) : les agents utilisent les outils MCP externes comme des outils natifs.DisconnectServerAsyncles désenregistre. - Serveur —
McpServerexpose les outils de l'IToolRegistryd'Orkeon aux clients MCP externes (tools/list/tools/call, avec conversionToolSchema→ 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Ă©thodeserver/discover. - LignĂ©e legacy Ă
initialize—SupportedLegacyVersions = ["2025-11-25", "2025-06-18", "2024-11-05"]: handshakeinitializeclassique suivi dunotifications/initializedobligatoire.2025-03-26est 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)
- Sonde avec
server/discover(en déclarant2026-07-28dans_meta). - 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 sanssupportedVersionsest un serveur legacy répondant avec indulgence à une méthode inconnue → repli surinitialize. - Erreur
-32022UnsupportedProtocolVersionError→ serveur moderne quand même ; lecture de sa liste supportée dans les données de l'erreur, renégociation, nouvelle tentative deserver/discover. - 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 parnotifications/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îcheurttlMs/cacheScope, identité du serveur dans le_metadu résultat). - Une requête déclarant une version
_metanon supportée est rejetée en-32022avec le payload{ supported, requested }, quelle que soit la méthode. - Le
initializelegacy renvoie la révision demandée quand elle est supportée, sinon la révision legacy la plus récente.pingreste servi pour les sessions legacy seulement (retiré de la lignée moderne). tools/listest renvoyé en ordre déterministe (tri ordinal par nom — un SHOULD de 2026-07-28, pour des caches clients stables) avec les champs modernesresultType/ttlMs/cacheScope; les clients legacy ignorent ces membres additifs.- Les notifications (sans
id, ounotifications/*) 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_requiredremonte 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-26exclue (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