[{"data":1,"prerenderedAt":4628},["ShallowReactive",2],{"navigation_fr":3,"posts_fr:/fr/blog/mcp-security":51,"posts_fr:/fr/blog/mcp-security:surround":1091},[4],{"title":5,"path":6,"stem":7,"children":8,"page":50},"Fr","/fr","fr",[9],{"title":10,"path":11,"stem":12,"children":13,"page":50},"Blog","/fr/blog","fr/blog",[14,18,22,26,30,34,38,42,46],{"title":15,"path":16,"stem":17},"Serveurs MCP comme Serveurs de Ressources OAuth : Une Approche Simplifiée","/fr/blog/mcp-aouth","fr/blog/1. mcp-aouth",{"title":19,"path":20,"stem":21},"Pratiques de Sécurité pour MCP Utilisant JSON-RPC","/fr/blog/mcp-security","fr/blog/1. mcp-security",{"title":23,"path":24,"stem":25},"Serveurs MCP : Connecter l'IA aux Données en Temps Réel","/fr/blog/mcp-create","fr/blog/2. mcp-create",{"title":27,"path":28,"stem":29},"Agents MCP Tiny On-Premises : S'affranchir des Dépendances Cloud","/fr/blog/mcp-tiny-agents-on-premises","fr/blog/5. mcp-tiny-agents-on-premises",{"title":31,"path":32,"stem":33},"De l'Idée à l'API en 2 Jours : Construction de Bankly avec les Flux de Travail Agentiques","/fr/blog/overvibing","fr/blog/6. overvibing",{"title":35,"path":36,"stem":37},"Chatbot IA, Serveur MCP construit avec le Protocole de Flux de Travail Agentique pour démo sur Checkatrade.com","/fr/blog/mcp-in-chat-demo","fr/blog/8. mcp-in-chat-demo",{"title":39,"path":40,"stem":41},"DDD et les Frameworks Full-Stack","/fr/blog/architecture","fr/blog/architecture",{"title":43,"path":44,"stem":45},"Qualité : Comment protéger les Frontends alimentés par l'IA ?","/fr/blog/qa-front","fr/blog/qa-front",{"title":47,"path":48,"stem":49},"Consultation et Stratégie IT","/fr/blog/strategy","fr/blog/strategy",false,{"id":52,"title":19,"authors":53,"badge":60,"body":64,"date":1083,"description":1084,"extension":1085,"image":1086,"meta":1088,"navigation":167,"path":20,"seo":1089,"stem":21,"__hash__":1090},"posts_fr/fr/blog/1. mcp-security.md",[54],{"name":55,"description":56,"to":57,"avatar":58},"Michael Wybraniec","Freelance, Serveurs MCP, Développement Full-Stack, Architecture","https://www.linkedin.com/in/one-front/",{"src":59},"https://media.licdn.com/dms/image/v2/D4D03AQEGvIVcrTTS2g/profile-displayphoto-shrink_800_800/B4DZbtSf7LIEAc-/0/1747737772225?e=1753315200&v=beta&t=EOviZQkM396PoGctVjDCdlG8U3vN5UKWiIeNQ8IFUgQ",{"label":61,"color":62,"variant":63},"Sécurité","primary","soft",{"type":65,"value":66,"toc":1070},"minimark",[67,75,100,121,127,132,210,214,271,275,315,330,538,553,656,671,716,761,776,821,836,1020,1035,1053,1066],[68,69,70],"p",{},[71,72,74],"a",{"href":73},"/blog/","Retour au Blog",[76,77,80],"div",{"className":78},[79],"text-justify",[68,81,82,83,87,88,91,92,95,96,99],{},"Le Protocole de Contexte de Modèle (MCP) est un framework pour la communication structurée entre clients et serveurs utilisant JSON-RPC 2.0. Il permet l'échange de messages à granularité fine dans des systèmes distribués ou modulaires, y compris ceux impliquant des modèles d'IA, des agents modulaires ou l'orchestration de services. Lors de l'utilisation de protocoles légers comme JSON-RPC 2.0 pour la communication MCP, les développeurs font face à plusieurs défis de sécurité. Cet article décrit les ",[84,85,86],"strong",{},"problèmes critiques",", les ",[84,89,90],{},"meilleures solutions"," et les ",[84,93,94],{},"outils pratiques pour développeurs"," pour assurer des ",[84,97,98],{},"systèmes MCP robustes et sécurisés",".",[76,101,106,113],{"className":102},[103,104,105],"flex","justify-between","items-center",[107,108,110],"h2",{"id":109},"guide-visuel-de-larchitecture-de-sécurité-mcp",[84,111,112],{},"Guide Visuel de l'Architecture de Sécurité MCP",[68,114,115],{},[71,116,118],{"href":117},"#top",[84,119,120],{},"⤴",[76,122,124],{"className":123},[79],[68,125,126],{},"Ce guide fournit un aperçu visuel et pratique de la sécurisation des systèmes MCP, incluant la signature de messages, la gestion de sessions et les modèles d'architecture du monde réel. Il s'adresse aux développeurs et architectes construisant des systèmes modulaires, basés sur des agents ou distribués d'IA.",[128,129,131],"h3",{"id":130},"flux-de-signature-et-vérification-de-messages","Flux de Signature et Vérification de Messages",[133,134,139],"pre",{"className":135,"code":136,"language":137,"meta":138,"style":138},"language-mermaid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sequenceDiagram\n  participant Client\n  participant Serveur\n\n  Client->>Client: Sérialiser méthode + paramètres\n  Client->>Client: Signer payload avec clé privée\n  Client->>Serveur: Envoyer JSON-RPC + signature + clé publique\n\n  Serveur->>Serveur: Canonicaliser méthode + paramètres\n  Serveur->>Serveur: Vérifier signature avec clé publique\n  Serveur-->>Client: Traiter ou rejeter\n","mermaid","",[140,141,142,150,156,162,169,175,181,187,192,198,204],"code",{"__ignoreMap":138},[143,144,147],"span",{"class":145,"line":146},"line",1,[143,148,149],{},"sequenceDiagram\n",[143,151,153],{"class":145,"line":152},2,[143,154,155],{},"  participant Client\n",[143,157,159],{"class":145,"line":158},3,[143,160,161],{},"  participant Serveur\n",[143,163,165],{"class":145,"line":164},4,[143,166,168],{"emptyLinePlaceholder":167},true,"\n",[143,170,172],{"class":145,"line":171},5,[143,173,174],{},"  Client->>Client: Sérialiser méthode + paramètres\n",[143,176,178],{"class":145,"line":177},6,[143,179,180],{},"  Client->>Client: Signer payload avec clé privée\n",[143,182,184],{"class":145,"line":183},7,[143,185,186],{},"  Client->>Serveur: Envoyer JSON-RPC + signature + clé publique\n",[143,188,190],{"class":145,"line":189},8,[143,191,168],{"emptyLinePlaceholder":167},[143,193,195],{"class":145,"line":194},9,[143,196,197],{},"  Serveur->>Serveur: Canonicaliser méthode + paramètres\n",[143,199,201],{"class":145,"line":200},10,[143,202,203],{},"  Serveur->>Serveur: Vérifier signature avec clé publique\n",[143,205,207],{"class":145,"line":206},11,[143,208,209],{},"  Serveur-->>Client: Traiter ou rejeter\n",[128,211,213],{"id":212},"initialisation-sécurisée-de-session","Initialisation Sécurisée de Session",[133,215,217],{"className":135,"code":216,"language":137,"meta":138,"style":138},"sequenceDiagram\n  participant Coordinateur\n  participant Agent A\n  participant Agent B\n\n  Agent A->>Coordinateur: Demander démarrage de session\n  Coordinateur->>Agent A: Envoyer UUID de session + token\n  Agent A->>Agent B: Partager contexte avec token\n  Agent B->>Coordinateur: Vérifier session + rejoindre\n\n  Note over Coordinateur: Le coordinateur suit les rôles, tours et état\n",[140,218,219,223,228,233,238,242,247,252,257,262,266],{"__ignoreMap":138},[143,220,221],{"class":145,"line":146},[143,222,149],{},[143,224,225],{"class":145,"line":152},[143,226,227],{},"  participant Coordinateur\n",[143,229,230],{"class":145,"line":158},[143,231,232],{},"  participant Agent A\n",[143,234,235],{"class":145,"line":164},[143,236,237],{},"  participant Agent B\n",[143,239,240],{"class":145,"line":171},[143,241,168],{"emptyLinePlaceholder":167},[143,243,244],{"class":145,"line":177},[143,245,246],{},"  Agent A->>Coordinateur: Demander démarrage de session\n",[143,248,249],{"class":145,"line":183},[143,250,251],{},"  Coordinateur->>Agent A: Envoyer UUID de session + token\n",[143,253,254],{"class":145,"line":189},[143,255,256],{},"  Agent A->>Agent B: Partager contexte avec token\n",[143,258,259],{"class":145,"line":194},[143,260,261],{},"  Agent B->>Coordinateur: Vérifier session + rejoindre\n",[143,263,264],{"class":145,"line":200},[143,265,168],{"emptyLinePlaceholder":167},[143,267,268],{"class":145,"line":206},[143,269,270],{},"  Note over Coordinateur: Le coordinateur suit les rôles, tours et état\n",[128,272,274],{"id":273},"routage-de-contexte-mcp","Routage de Contexte MCP",[133,276,278],{"className":135,"code":277,"language":137,"meta":138,"style":138},"graph TD\n  A[Client] -->|JSON-RPC| B[Coordinateur]\n  B -->|Routage de Session| C1[Agent A]\n  B -->|Routage de Session| C2[Agent B]\n  C1 -->|Message de Contexte| C2\n  C2 -->|Réponse| C1\n  B -->|Observabilité| D[Stockage de Logs Signés]\n",[140,279,280,285,290,295,300,305,310],{"__ignoreMap":138},[143,281,282],{"class":145,"line":146},[143,283,284],{},"graph TD\n",[143,286,287],{"class":145,"line":152},[143,288,289],{},"  A[Client] -->|JSON-RPC| B[Coordinateur]\n",[143,291,292],{"class":145,"line":158},[143,293,294],{},"  B -->|Routage de Session| C1[Agent A]\n",[143,296,297],{"class":145,"line":164},[143,298,299],{},"  B -->|Routage de Session| C2[Agent B]\n",[143,301,302],{"class":145,"line":171},[143,303,304],{},"  C1 -->|Message de Contexte| C2\n",[143,306,307],{"class":145,"line":177},[143,308,309],{},"  C2 -->|Réponse| C1\n",[143,311,312],{"class":145,"line":183},[143,313,314],{},"  B -->|Observabilité| D[Stockage de Logs Signés]\n",[76,316,318,324],{"className":317},[103,104,105],[107,319,321],{"id":320},"problèmes-critiques-de-sécurité-dans-mcp-basé-sur-json-rpc",[84,322,323],{},"Problèmes Critiques de Sécurité dans MCP Basé sur JSON-RPC",[68,325,326],{},[71,327,328],{"href":117},[84,329,120],{},[331,332,333,352],"table",{},[334,335,336],"thead",{},[337,338,339,343,346,349],"tr",{},[340,341,342],"th",{},"Zone",[340,344,345],{},"Problème Critique",[340,347,348],{},"Pourquoi C'est Important dans MCP",[340,350,351],{},"Solution",[353,354,355,370,384,398,412,426,440,454,468,482,496,510,524],"tbody",{},[337,356,357,361,364,367],{},[358,359,360],"td",{},"🗭 Coordination",[358,362,363],{},"Pas de routage natif multi-parties",[358,365,366],{},"MCP implique souvent l'orchestration de plusieurs services ou agents",[358,368,369],{},"Implémenter un service coordinateur pour gérer le routage, les rôles et les relais de messages",[337,371,372,375,378,381],{},[358,373,374],{},"🔐 Identité",[358,376,377],{},"Pas de couche d'identité/auth/session",[358,379,380],{},"Vous devez authentifier et vérifier l'origine du message",[358,382,383],{},"Utiliser DIDs, mTLS ou couches d'identité basées sur signature avec tokens de session",[337,385,386,389,392,395],{},[358,387,388],{},"⚠️ Erreurs",[358,390,391],{},"Mauvaise observabilité et sémantique d'erreurs",[358,393,394],{},"Difficile de tracer les échecs dans les flux de modèles contextuels",[358,396,397],{},"Ajouter logs signés, codes d'erreur structurés et tableaux de bord de trace",[337,399,400,403,406,409],{},[358,401,402],{},"📦 Types de Données",[358,404,405],{},"Pas de support pour données binaires/complexes",[358,407,408],{},"Les paramètres et réponses du modèle peuvent ne pas s'adapter facilement au JSON",[358,410,411],{},"Utiliser encodage base64, CBOR ou attacher payloads structurés en dehors des champs JSON-RPC centraux",[337,413,414,417,420,423],{},[358,415,416],{},"🧪 Tests",[358,418,419],{},"Pas de simulation ou d'outils étape par étape",[358,421,422],{},"Besoin de replay de protocole et de débogage",[358,424,425],{},"Construire des harnais de test déterministes avec replay de protocole et mocking d'agents",[337,427,428,431,434,437],{},[358,429,430],{},"🧱 Persistance",[358,432,433],{},"Pas de session/mémoire entre appels",[358,435,436],{},"La continuité du contexte entre appels de modèle nécessite état et rôles suivis",[358,438,439],{},"Utiliser Redis ou stockage de session en mémoire pour persister l'état de rôle, tour et message",[337,441,442,445,448,451],{},[358,443,444],{},"💨 Agents Malveillants",[358,446,447],{},"N'importe quel acteur peut injecter logique ou contexte nuisible",[358,449,450],{},"Les agents malveillants peuvent faire dérailler ou empoisonner l'exécution du modèle",[358,452,453],{},"Utiliser sandboxing (ex. VM2/WASM), validation de comportement et listes autorisées pour flux de contexte",[337,455,456,459,462,465],{},[358,457,458],{},"🦮 Dérive de Session",[358,460,461],{},"Les agents peuvent désynchroniser données de contexte/tour",[358,463,464],{},"Conduit à conditions de course, hallucinations ou écrasement de contexte",[358,466,467],{},"Utiliser snapshots de session signés, compteurs de tour et outils de replay du coordinateur",[337,469,470,473,476,479],{},[358,471,472],{},"🔄 Attaques de Replay",[358,474,475],{},"Réutilisation de messages valides entre contextes",[358,477,478],{},"Non détecté, peut manipuler le comportement ou la sortie de l'agent",[358,480,481],{},"Tokens horodatés, validation de nonce ou chaînes de hash pour assurer la fraîcheur",[337,483,484,487,490,493],{},[358,485,486],{},"🛨️ Atténuation d'Agents Malveillants",[358,488,489],{},"Agents compromis agissant dans une session valide",[358,491,492],{},"Menace l'intégrité du système",[358,494,495],{},"Appliquer règles de comportement, utiliser sandboxes sécurisés et valider modèles d'entrée/sortie",[337,497,498,501,504,507],{},[358,499,500],{},"🌐 Identité Décentralisée (DIDs)",[358,502,503],{},"Manque de résolution d'identité globale fiable",[358,505,506],{},"Nécessaire pour délégation de confiance sécurisée entre agents",[358,508,509],{},"Adopter DIDs W3C et résoudre clés via Documents DID ou registres de clés",[337,511,512,515,518,521],{},[358,513,514],{},"📡 Gestion Sécurisée de Sessions",[358,516,517],{},"Les sessions peuvent être piratées, perdues ou incohérentes",[358,519,520],{},"Critique pour état du modèle, contexte et protection replay",[358,522,523],{},"Suivre sessions via coordinateur, assigner IDs uniques, utiliser clés par session",[337,525,526,529,532,535],{},[358,527,528],{},"🔄 Protection Replay et Course",[358,530,531],{},"Requêtes dupliquées ou réordonnées peuvent causer erreurs",[358,533,534],{},"Les agents peuvent mal se comporter ou retraiter anciennes données",[358,536,537],{},"Utiliser nonces, timestamps et compteurs de tour dans chaque message",[76,539,541,547],{"className":540},[103,104,105],[107,542,544],{"id":543},"tableau-de-vue-densemble-des-capacités",[84,545,546],{},"Tableau de Vue d'Ensemble des Capacités",[68,548,549],{},[71,550,551],{"href":117},[84,552,120],{},[331,554,555,577],{},[334,556,557],{},[337,558,559,562,565,568,571,574],{},[340,560,561],{},"Capacité",[340,563,564],{},"Contrôlé Par",[340,566,567],{},"Direction",[340,569,570],{},"Effets Secondaires",[340,572,573],{},"Approbation Nécessaire",[340,575,576],{},"Cas d'Usage Typiques",[353,578,579,599,618,637],{},[337,580,581,584,587,590,593,596],{},[358,582,583],{},"Outils",[358,585,586],{},"Modèle (LLM)",[358,588,589],{},"Client → Serveur",[358,591,592],{},"Oui (potentiellement)",[358,594,595],{},"Oui",[358,597,598],{},"Actions, appels API, manipulation de données",[337,600,601,604,607,609,612,615],{},[358,602,603],{},"Ressources",[358,605,606],{},"Application",[358,608,589],{},[358,610,611],{},"Non (lecture seule)",[358,613,614],{},"Généralement non",[358,616,617],{},"Récupération de données, collecte de contexte",[337,619,620,623,626,629,632,634],{},[358,621,622],{},"Prompts",[358,624,625],{},"Utilisateur",[358,627,628],{},"Serveur → Client",[358,630,631],{},"Non",[358,633,631],{},[358,635,636],{},"Flux guidés, modèles spécialisés",[337,638,639,642,645,648,651,653],{},[358,640,641],{},"Échantillonnage",[358,643,644],{},"Serveur",[358,646,647],{},"Serveur → Client → Serveur",[358,649,650],{},"Indirectement",[358,652,595],{},[358,654,655],{},"Tâches multi-étapes, comportements agentiques",[76,657,659,665],{"className":658},[103,104,105],[107,660,662],{"id":661},"architecture-de-référence-du-monde-réel",[84,663,664],{},"Architecture de Référence du Monde Réel",[68,666,667],{},[71,668,669],{"href":117},[84,670,120],{},[672,673,674,681,687,693,699,705,710],"ul",{},[675,676,677,680],"li",{},[84,678,679],{},"Frontend",": Nuxt 3 (avec Nuxt Content & Tailwind)",[675,682,683,686],{},[84,684,685],{},"Backend",": Node.js / Fastify / Express",[675,688,689,692],{},[84,690,691],{},"Coordinateur MCP",": Routage personnalisé + logique de contexte (sans état + conscient de session)",[675,694,695,698],{},[84,696,697],{},"Agents",": Microservices indépendants ou modules basés sur WASM",[675,700,701,704],{},[84,702,703],{},"Transport",": JSON-RPC 2.0 sur HTTPS (ou mTLS)",[675,706,707,709],{},[84,708,61],{},": Validation de signature, DIDs et clés de chiffrement par session",[675,711,712,715],{},[84,713,714],{},"Logs",": Logs signés en ajout seul + tableau de bord d'observabilité (Grafana / OpenTelemetry)",[133,717,719],{"className":135,"code":718,"language":137,"meta":138,"style":138},"graph LR\n  FE[Client Nuxt3] -->|JSON-RPC| COORD[Coordinateur MCP]\n  COORD --> A1[Agent A]\n  COORD --> A2[Agent B]\n  COORD --> REDIS[(Stockage de Session)]\n  COORD --> LOG[Logs Signés]\n  A1 --> RES1[(API Externe)]\n  A2 --> RES2[(LLM ou Outil)]\n",[140,720,721,726,731,736,741,746,751,756],{"__ignoreMap":138},[143,722,723],{"class":145,"line":146},[143,724,725],{},"graph LR\n",[143,727,728],{"class":145,"line":152},[143,729,730],{},"  FE[Client Nuxt3] -->|JSON-RPC| COORD[Coordinateur MCP]\n",[143,732,733],{"class":145,"line":158},[143,734,735],{},"  COORD --> A1[Agent A]\n",[143,737,738],{"class":145,"line":164},[143,739,740],{},"  COORD --> A2[Agent B]\n",[143,742,743],{"class":145,"line":171},[143,744,745],{},"  COORD --> REDIS[(Stockage de Session)]\n",[143,747,748],{"class":145,"line":177},[143,749,750],{},"  COORD --> LOG[Logs Signés]\n",[143,752,753],{"class":145,"line":183},[143,754,755],{},"  A1 --> RES1[(API Externe)]\n",[143,757,758],{"class":145,"line":189},[143,759,760],{},"  A2 --> RES2[(LLM ou Outil)]\n",[76,762,764,770],{"className":763},[103,104,105],[107,765,767],{"id":766},"outils-et-solutions-pour-développeurs",[84,768,769],{},"Outils et Solutions pour Développeurs",[68,771,772],{},[71,773,774],{"href":117},[84,775,120],{},[672,777,778,785,791,797,803,809,815],{},[675,779,780,781,784],{},"✅ ",[84,782,783],{},"Messages JSON-RPC Signés",": Créer JSON canonique, signer en utilisant EdDSA/ECDSA, envoyer avec clé publique ou DID.",[675,786,780,787,790],{},[84,788,789],{},"Snapshots de Session",": Stocker snapshots JSON par tour avec signatures.",[675,792,780,793,796],{},[84,794,795],{},"Détection de Replay",": Utiliser nonce + timestamps + chaînage de hash.",[675,798,780,799,802],{},[84,800,801],{},"Harnais de Test",": Construire outils de replay MCP avec agents simulés.",[675,804,780,805,808],{},[84,806,807],{},"Observabilité",": Utiliser OpenTelemetry ou agrégateurs de logs avec événements structurés.",[675,810,780,811,814],{},[84,812,813],{},"Validation de Signature",": Les bibliothèques client + agent doivent appliquer validation avant traitement.",[675,816,780,817,820],{},[84,818,819],{},"Service Résolveur DID",": Résoudre clés publiques liées aux DIDs d'agent.",[76,822,824,830],{"className":823},[103,104,105],[107,825,827],{"id":826},"comment-signer-les-payloads-json-rpc",[84,828,829],{},"Comment Signer les Payloads JSON-RPC",[68,831,832],{},[71,833,834],{"href":117},[84,835,120],{},[133,837,841],{"className":838,"code":839,"language":840,"meta":138,"style":138},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { sign, verify } from 'crypto';\nconst method = 'agent.perform';\nconst params = { input: 'Exécuter test' };\nconst payload = JSON.stringify({ method, params });\nconst signature = sign('sha256', Buffer.from(payload), privateKey);\n\n// Envoyer: { method, params, signature, pubKey }\n","ts",[140,842,843,882,903,931,970,1010,1014],{"__ignoreMap":138},[143,844,845,849,853,857,860,863,866,869,872,876,879],{"class":145,"line":146},[143,846,848],{"class":847},"s7zQu","import",[143,850,852],{"class":851},"sMK4o"," {",[143,854,856],{"class":855},"sTEyZ"," sign",[143,858,859],{"class":851},",",[143,861,862],{"class":855}," verify",[143,864,865],{"class":851}," }",[143,867,868],{"class":847}," from",[143,870,871],{"class":851}," '",[143,873,875],{"class":874},"sfazB","crypto",[143,877,878],{"class":851},"'",[143,880,881],{"class":851},";\n",[143,883,884,888,891,894,896,899,901],{"class":145,"line":152},[143,885,887],{"class":886},"spNyl","const",[143,889,890],{"class":855}," method ",[143,892,893],{"class":851},"=",[143,895,871],{"class":851},[143,897,898],{"class":874},"agent.perform",[143,900,878],{"class":851},[143,902,881],{"class":851},[143,904,905,907,910,912,914,918,921,923,926,928],{"class":145,"line":158},[143,906,887],{"class":886},[143,908,909],{"class":855}," params ",[143,911,893],{"class":851},[143,913,852],{"class":851},[143,915,917],{"class":916},"swJcz"," input",[143,919,920],{"class":851},":",[143,922,871],{"class":851},[143,924,925],{"class":874},"Exécuter test",[143,927,878],{"class":851},[143,929,930],{"class":851}," };\n",[143,932,933,935,938,940,943,945,949,952,955,958,960,962,965,968],{"class":145,"line":164},[143,934,887],{"class":886},[143,936,937],{"class":855}," payload ",[143,939,893],{"class":851},[143,941,942],{"class":855}," JSON",[143,944,99],{"class":851},[143,946,948],{"class":947},"s2Zo4","stringify",[143,950,951],{"class":855},"(",[143,953,954],{"class":851},"{",[143,956,957],{"class":855}," method",[143,959,859],{"class":851},[143,961,909],{"class":855},[143,963,964],{"class":851},"}",[143,966,967],{"class":855},")",[143,969,881],{"class":851},[143,971,972,974,977,979,981,983,985,988,990,992,995,997,1000,1003,1005,1008],{"class":145,"line":171},[143,973,887],{"class":886},[143,975,976],{"class":855}," signature ",[143,978,893],{"class":851},[143,980,856],{"class":947},[143,982,951],{"class":855},[143,984,878],{"class":851},[143,986,987],{"class":874},"sha256",[143,989,878],{"class":851},[143,991,859],{"class":851},[143,993,994],{"class":855}," Buffer",[143,996,99],{"class":851},[143,998,999],{"class":947},"from",[143,1001,1002],{"class":855},"(payload)",[143,1004,859],{"class":851},[143,1006,1007],{"class":855}," privateKey)",[143,1009,881],{"class":851},[143,1011,1012],{"class":145,"line":177},[143,1013,168],{"emptyLinePlaceholder":167},[143,1015,1016],{"class":145,"line":183},[143,1017,1019],{"class":1018},"sHwdD","// Envoyer: { method, params, signature, pubKey }\n",[76,1021,1023,1029],{"className":1022},[103,104,105],[107,1024,1026],{"id":1025},"résumé",[84,1027,1028],{},"Résumé",[68,1030,1031],{},[71,1032,1033],{"href":117},[84,1034,120],{},[68,1036,1037,1038,1041,1042,1041,1045,1048,1049,1052],{},"Un système MCP sécurisé construit avec JSON-RPC nécessite des couches de protection : identité, intégrité des messages, sécurité du contexte et règles de protocole claires. Combiner ",[84,1039,1040],{},"DIDs",", ",[84,1043,1044],{},"signatures",[84,1046,1047],{},"contrôle de session"," et ",[84,1050,1051],{},"défenses contre agents malveillants"," assure que votre système modulaire reste sûr, observable et extensible.",[76,1054,1060],{"className":1055},[1056,1057,1058,1059],"text-md","text-center","mt-10","font-bold",[68,1061,1062],{},[71,1063,1064],{"href":117},[84,1065,120],{},[1067,1068,1069],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":138,"searchDepth":152,"depth":152,"links":1071},[1072,1077,1078,1079,1080,1081,1082],{"id":109,"depth":152,"text":112,"children":1073},[1074,1075,1076],{"id":130,"depth":158,"text":131},{"id":212,"depth":158,"text":213},{"id":273,"depth":158,"text":274},{"id":320,"depth":152,"text":323},{"id":543,"depth":152,"text":546},{"id":661,"depth":152,"text":664},{"id":766,"depth":152,"text":769},{"id":826,"depth":152,"text":829},{"id":1025,"depth":152,"text":1028},"2025-06-26","Problèmes critiques de sécurité, meilleures solutions et outils pratiques pour des systèmes MCP robustes et sécurisés utilisant JSON-RPC.","md",{"src":1087},"/blog/mcp/mcp-cover.png",{},{"title":19,"description":1084},"v8QZCrRACbPHafMNqzDSLJTS3GEhRu0WnjMdQjJugMo",[1092,3172],{"id":1093,"title":15,"authors":1094,"badge":1099,"body":1101,"date":3166,"description":3167,"extension":1085,"image":3168,"meta":3169,"navigation":167,"path":16,"seo":3170,"stem":17,"__hash__":3171},"posts_fr/fr/blog/1. mcp-aouth.md",[1095],{"name":55,"description":1096,"to":57,"avatar":1097},"Freelance, MCP Servers, Full-Stack Development, Architecture",{"src":1098},"https://media.licdn.com/dms/image/v2/D4D03AQF3mn-R1ERoNg/profile-displayphoto-crop_800_800/B4DZeoMSehHMAI-/0/1750873484401?e=1756339200&v=beta&t=D2AWIO__-FP4J-iWELIG6djNIvq0WOe8x9uBYpKvFZA",{"label":1100,"color":62,"variant":63},"Architecture, Security",{"type":65,"value":1102,"toc":3148},[1103,1124,1148,1163,1212,1227,1279,1290,1421,1436,1550,1565,1604,2157,2172,2178,2246,2261,2272,2405,2420,2529,2544,2701,2879,2911,2917,2926,2987,2996,3011,3136,3145],[68,1104,1105,1109,1110,1109,1114,1109,1118],{},[71,1106,1108],{"href":1107},"/blog","Retour aux articles"," | ",[71,1111,1113],{"href":1112},"/blog/architecture","Architecture MCP",[71,1115,1117],{"href":1116},"/blog/mcp-security","Sécurité MCP",[71,1119,1123],{"href":1120,"rel":1121},"https://datatracker.ietf.org/doc/html/rfc8693",[1122],"nofollow","RFC 8693 Token Exchange",[76,1125,1127],{"className":1126},[79],[68,1128,1129,1130,1133,1134,1137,1138,1143,1144,1147],{},"L'architecture d'autorisation du Model Context Protocol (MCP) peut être considérablement simplifiée en traitant les serveurs MCP comme des ",[84,1131,1132],{},"serveurs de ressources OAuth"," plutôt que comme des serveurs d'autorisation. Cette approche révolutionnaire, proposée par ",[84,1135,1136],{},"dasiths"," dans la ",[71,1139,1142],{"href":1140,"rel":1141},"https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/381",[1122],"discussion GitHub",", permet aux développeurs de tirer parti des solutions d'identité existantes comme ",[84,1145,1146],{},"Okta, Auth0, Microsoft Entra ID"," tout en réduisant la complexité d'implémentation et en améliorant l'adoption en entreprise.",[76,1149,1151,1157],{"className":1150},[103,104,105],[107,1152,1154],{"id":1153},"le-problème-avec-lapproche-actuelle",[84,1155,1156],{},"Le Problème avec l'Approche Actuelle",[68,1158,1159],{},[71,1160,1161],{"href":117},[84,1162,120],{},[76,1164,1166,1173],{"className":1165},[79],[68,1167,1168,1169,1172],{},"L'implémentation actuelle du brouillon d'autorisation MCP traite chaque serveur MCP comme un ",[84,1170,1171],{},"serveur d'autorisation OAuth",". Cela signifie que chaque développeur de serveur MCP doit implémenter conformément aux spécifications :",[672,1174,1175,1185,1195,1198],{},[675,1176,1177,1184],{},[84,1178,1179],{},[71,1180,1183],{"href":1181,"rel":1182},"https://datatracker.ietf.org/doc/html/rfc8414",[1122],"RFC 8414"," - OAuth 2.0 Authorization Server Metadata",[675,1186,1187,1194],{},[84,1188,1189],{},[71,1190,1193],{"href":1191,"rel":1192},"https://datatracker.ietf.org/doc/html/rfc7591",[1122],"RFC 7591"," - OAuth 2.0 Dynamic Client Registration Protocol",[675,1196,1197],{},"Les endpoints d'autorisation et de tokens",[675,1199,1200,1201,1204,1205,1208,1209,99],{},"La gestion des sessions utilisateurs\nCette approche crée une ",[84,1202,1203],{},"complexité inutile"," et constitue un obstacle majeur à l'adoption, comme l'a souligné ",[84,1206,1207],{},"gao-sun"," qui a testé cette implémentation avec ",[84,1210,1211],{},"Logto, Keycloak et Auth0",[76,1213,1215,1221],{"className":1214},[103,104,105],[107,1216,1218],{"id":1217},"la-solution-serveur-de-ressources-oauth",[84,1219,1220],{},"La Solution : Serveur de Ressources OAuth",[68,1222,1223],{},[71,1224,1225],{"href":117},[84,1226,120],{},[76,1228,1230,1256],{"className":1229},[79],[68,1231,1232,1233,1236,1237,1245,1246,1249,1250,1255],{},"En traitant le serveur MCP comme un ",[84,1234,1235],{},"serveur de ressources OAuth"," conformément au ",[84,1238,1239,1244],{},[71,1240,1243],{"href":1241,"rel":1242},"https://datatracker.ietf.org/doc/html/rfc9728",[1122],"RFC 9728"," - OAuth 2.0 Protected Resource Metadata",", nous déléguons l'authentification et l'autorisation à des fournisseurs d'identité existants. Cette approche transforme le serveur MCP en un service ",[84,1247,1248],{},"sans état"," en ce qui concerne les préoccupations d'authentification, utilisant le ",[84,1251,1252],{},[71,1253,1123],{"href":1120,"rel":1254},[1122]," pour les scénarios de délégation.",[68,1257,1258,1259,1266,1267,1270,1271,1274,1275,99],{},"Selon la ",[84,1260,1261],{},[71,1262,1265],{"href":1263,"rel":1264},"https://github.com/modelcontextprotocol/modelcontextprotocol/blob/63ccd1a416de4ffe7c24d8257f8f3c849e4ea0f8/docs/specification/draft/basic/authorization.mdx",[1122],"spécification officielle MCP",", les serveurs MCP ",[84,1268,1269],{},"DOIVENT"," implémenter OAuth 2.0 Protected Resource Metadata pour indiquer l'emplacement des serveurs d'autorisation via l'en-tête ",[140,1272,1273],{},"WWW-Authenticate"," lors du retour d'un ",[1276,1277,1278],"em",{},"401 Unauthorized",[76,1280,1282,1287],{"className":1281},[79],[68,1283,1284],{},[84,1285,1286],{},"Diagramme 1 : Flux de découverte et d'autorisation MCP avec serveur de ressources OAuth",[68,1288,1289],{},"Ce diagramme illustre le processus complet de découverte des métadonnées et d'autorisation entre un client MCP, un serveur MCP agissant comme serveur de ressources OAuth, et un serveur d'autorisation externe. Le flux commence par une requête non autorisée et se termine par une communication MCP sécurisée avec un token d'accès valide.",[133,1291,1293],{"className":135,"code":1292,"language":137,"meta":138,"style":138},"sequenceDiagram\n    participant C as Client MCP\n    participant M as Serveur MCP (Serveur de Ressources)\n    participant A as Serveur d'Autorisation\n\n    C->>M: Requête MCP sans token\n    M-->>C: HTTP 401 Unauthorized avec en-tête WWW-Authenticate\n    Note over C: Extraire resource_metadata\u003Cbr />du WWW-Authenticate\n\n    C->>M: GET /.well-known/oauth-protected-resource\n    M-->>C: Métadonnées de ressource avec URL serveur d'autorisation\n    Note over C: Valider métadonnées RS,\u003Cbr />construire URL métadonnées AS\n\n    C->>A: GET /.well-known/oauth-authorization-server\n    A-->>C: Métadonnées serveur d'autorisation\n\n    Note over C,A: Flux d'autorisation OAuth 2.1 se déroule ici\n\n    C->>A: Requête de token\n    A-->>C: Token d'accès\n\n    C->>M: Requête MCP avec token d'accès\n    M-->>C: Réponse MCP\n    Note over C,M: Communication MCP continue avec token valide\n",[140,1294,1295,1299,1304,1309,1314,1318,1323,1328,1333,1337,1342,1347,1353,1358,1364,1370,1375,1381,1386,1392,1398,1403,1409,1415],{"__ignoreMap":138},[143,1296,1297],{"class":145,"line":146},[143,1298,149],{},[143,1300,1301],{"class":145,"line":152},[143,1302,1303],{},"    participant C as Client MCP\n",[143,1305,1306],{"class":145,"line":158},[143,1307,1308],{},"    participant M as Serveur MCP (Serveur de Ressources)\n",[143,1310,1311],{"class":145,"line":164},[143,1312,1313],{},"    participant A as Serveur d'Autorisation\n",[143,1315,1316],{"class":145,"line":171},[143,1317,168],{"emptyLinePlaceholder":167},[143,1319,1320],{"class":145,"line":177},[143,1321,1322],{},"    C->>M: Requête MCP sans token\n",[143,1324,1325],{"class":145,"line":183},[143,1326,1327],{},"    M-->>C: HTTP 401 Unauthorized avec en-tête WWW-Authenticate\n",[143,1329,1330],{"class":145,"line":189},[143,1331,1332],{},"    Note over C: Extraire resource_metadata\u003Cbr />du WWW-Authenticate\n",[143,1334,1335],{"class":145,"line":194},[143,1336,168],{"emptyLinePlaceholder":167},[143,1338,1339],{"class":145,"line":200},[143,1340,1341],{},"    C->>M: GET /.well-known/oauth-protected-resource\n",[143,1343,1344],{"class":145,"line":206},[143,1345,1346],{},"    M-->>C: Métadonnées de ressource avec URL serveur d'autorisation\n",[143,1348,1350],{"class":145,"line":1349},12,[143,1351,1352],{},"    Note over C: Valider métadonnées RS,\u003Cbr />construire URL métadonnées AS\n",[143,1354,1356],{"class":145,"line":1355},13,[143,1357,168],{"emptyLinePlaceholder":167},[143,1359,1361],{"class":145,"line":1360},14,[143,1362,1363],{},"    C->>A: GET /.well-known/oauth-authorization-server\n",[143,1365,1367],{"class":145,"line":1366},15,[143,1368,1369],{},"    A-->>C: Métadonnées serveur d'autorisation\n",[143,1371,1373],{"class":145,"line":1372},16,[143,1374,168],{"emptyLinePlaceholder":167},[143,1376,1378],{"class":145,"line":1377},17,[143,1379,1380],{},"    Note over C,A: Flux d'autorisation OAuth 2.1 se déroule ici\n",[143,1382,1384],{"class":145,"line":1383},18,[143,1385,168],{"emptyLinePlaceholder":167},[143,1387,1389],{"class":145,"line":1388},19,[143,1390,1391],{},"    C->>A: Requête de token\n",[143,1393,1395],{"class":145,"line":1394},20,[143,1396,1397],{},"    A-->>C: Token d'accès\n",[143,1399,1401],{"class":145,"line":1400},21,[143,1402,168],{"emptyLinePlaceholder":167},[143,1404,1406],{"class":145,"line":1405},22,[143,1407,1408],{},"    C->>M: Requête MCP avec token d'accès\n",[143,1410,1412],{"class":145,"line":1411},23,[143,1413,1414],{},"    M-->>C: Réponse MCP\n",[143,1416,1418],{"class":145,"line":1417},24,[143,1419,1420],{},"    Note over C,M: Communication MCP continue avec token valide\n",[76,1422,1424,1430],{"className":1423},[103,104,105],[107,1425,1427],{"id":1426},"avantages-de-cette-approche",[84,1428,1429],{},"Avantages de Cette Approche",[68,1431,1432],{},[71,1433,1434],{"href":117},[84,1435,120],{},[76,1437,1445,1493],{"className":1438},[1439,1440,1441,1442,1443,1444],"grid","grid-cols-1","md:grid-cols-2","items-start","w-full","gap-x-8",[76,1446,1448,1455,1462,1473,1479,1482],{"className":1447},[79],[1449,1450,1452],"h4",{"id":1451},"adoption-entreprise",[84,1453,1454],{},"🏢 Adoption Entreprise",[68,1456,1457,1458,1461],{},"Cette approche augmente considérablement l'",[84,1459,1460],{},"adoptabilité de MCP dans les scénarios d'entreprise"," où des serveurs d'autorisation OAuth sont déjà déployés. Les organisations peuvent :",[672,1463,1464,1467,1470],{},[675,1465,1466],{},"Utiliser leurs solutions d'identité existantes",[675,1468,1469],{},"Appliquer leurs politiques de sécurité établies",[675,1471,1472],{},"Intégrer MCP dans leur architecture de sécurité actuelle",[1449,1474,1476],{"id":1475},"réduction-de-complexité",[84,1477,1478],{},"⚡ Réduction de Complexité",[68,1480,1481],{},"Les développeurs de serveurs MCP n'ont plus besoin de :",[672,1483,1484,1487,1490],{},[675,1485,1486],{},"Implémenter des flux d'autorisation complexes",[675,1488,1489],{},"Gérer les sessions et tokens liés",[675,1491,1492],{},"Maintenir des bases de données d'utilisateurs",[76,1494,1496,1502,1523,1529,1536],{"className":1495},[79],[1449,1497,1499],{"id":1498},"sécurité-renforcée",[84,1500,1501],{},"🔒 Sécurité Renforcée",[672,1503,1504,1510,1516],{},[675,1505,1506,1509],{},[84,1507,1508],{},"Réduction de la surface d'attaque"," en cas de vulnérabilité",[675,1511,1512,1515],{},[84,1513,1514],{},"Architecture sans état"," pour les préoccupations d'auth",[675,1517,1518,1519,1522],{},"Possibilité d'utiliser des ",[84,1520,1521],{},"flux d'échange de tokens"," pour agir au nom de l'utilisateur",[1449,1524,1526],{"id":1525},"flexibilité-client",[84,1527,1528],{},"🔄 Flexibilité Client",[68,1530,1531,1532,1535],{},"Les clients MCP peuvent tirer parti de ",[84,1533,1534],{},"n'importe quel flux OAuth supporté"," pour récupérer un token :",[672,1537,1538,1541,1544,1547],{},[675,1539,1540],{},"Client credentials",[675,1542,1543],{},"Authorization code",[675,1545,1546],{},"Device code",[675,1548,1549],{},"Token exchange",[76,1551,1553,1559],{"className":1552},[103,104,105],[107,1554,1556],{"id":1555},"scénario-dexemple-échange-de-tokens",[84,1557,1558],{},"Scénario d'Exemple : Échange de Tokens",[68,1560,1561],{},[71,1562,1563],{"href":117},[84,1564,120],{},[76,1566,1568,1593],{"className":1567},[79],[68,1569,1570,1571,1574,1575,1577,1578,1236,1581,1588,1589,1592],{},"Considérons une organisation avec une ",[84,1572,1573],{},"multitude d'APIs REST"," développées au fil des années, comme mentionné par ",[84,1576,1136],{}," dans sa proposition. Ces APIs sont protégées par l'authentification ",[84,1579,1580],{},"JWT bearer",[84,1582,1583],{},[71,1584,1587],{"href":1585,"rel":1586},"https://datatracker.ietf.org/doc/html/rfc6750",[1122],"RFC 6750"," et disposent de serveurs d'autorisation OAuth existants (",[84,1590,1591],{},"Okta, Auth0, Microsoft Entra ID, Keycloak",").",[68,1594,1595,1596,1599,1600,1603],{},"Le ",[84,1597,1598],{},"chemin le plus simple pour adopter MCP"," serait de tirer parti de leur solution d'auth existante et de traiter le serveur MCP comme un simple service de niveau intermédiaire qui doit consommer leurs APIs existantes en utilisant le ",[84,1601,1602],{},"Token Exchange Flow"," du RFC 8693.",[133,1605,1609],{"className":1606,"code":1607,"language":1608,"meta":138,"style":138},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// Exemple d'implémentation côté serveur MCP inspirée de MCP Auth par gao-sun\nclass MCPResourceServer {\n  async handleRequest(request: MCPRequest, accessToken: string) {\n    // 1. Valider le token avec le serveur d'autorisation (RFC 7662 Token Introspection)\n    const validation = await this.validateToken(accessToken);\n    \n    if (!validation.valid) {\n      throw new UnauthorizedError();\n    }\n    \n    // 2. Échange de token pour accéder aux APIs internes (RFC 8693)\n    const exchangedToken = await this.exchangeToken(\n      accessToken, \n      'urn:ietf:params:oauth:token-type:access_token',\n      'https://api.internal.company.com'\n    );\n    \n    // 3. Appel à l'API avec le token échangé\n    return await this.callInternalAPI(exchangedToken);\n  }\n  \n  // Métadonnées de ressource protégée (RFC 9728) - Endpoint /.well-known/oauth-protected-resource\n  async getResourceMetadata() {\n    return {\n      \"authorization_servers\": [\"https://auth.company.com\"],\n      \"scopes_supported\": [\"mcp:read\", \"mcp:write\", \"mcp:admin\"],\n      \"bearer_methods_supported\": [\"header\"],\n      \"resource_documentation\": \"https://docs.company.com/mcp-api\"\n    };\n  }\n  \n  // Gestion de l'en-tête WWW-Authenticate selon la spécification MCP\n  async handleUnauthorized(response: Response) {\n    response.status = 401;\n    response.headers.set('WWW-Authenticate', \n      'Bearer realm=\"MCP Server\", resource_metadata=\"https://mcp.company.com/.well-known/oauth-protected-resource\"'\n    );\n    response.headers.set('MCP-Protocol-Version', '2024-11-05');\n    return response;\n  }\n}\n","typescript",[140,1610,1611,1616,1628,1661,1666,1695,1700,1725,1741,1746,1750,1755,1774,1784,1797,1807,1814,1818,1823,1844,1849,1854,1859,1870,1876,1905,1949,1974,1994,2000,2005,2010,2016,2038,2057,2084,2094,2101,2136,2146,2151],{"__ignoreMap":138},[143,1612,1613],{"class":145,"line":146},[143,1614,1615],{"class":1018},"// Exemple d'implémentation côté serveur MCP inspirée de MCP Auth par gao-sun\n",[143,1617,1618,1621,1625],{"class":145,"line":152},[143,1619,1620],{"class":886},"class",[143,1622,1624],{"class":1623},"sBMFI"," MCPResourceServer",[143,1626,1627],{"class":851}," {\n",[143,1629,1630,1633,1636,1638,1642,1644,1647,1649,1652,1654,1657,1659],{"class":145,"line":158},[143,1631,1632],{"class":886},"  async",[143,1634,1635],{"class":916}," handleRequest",[143,1637,951],{"class":851},[143,1639,1641],{"class":1640},"sHdIc","request",[143,1643,920],{"class":851},[143,1645,1646],{"class":1623}," MCPRequest",[143,1648,859],{"class":851},[143,1650,1651],{"class":1640}," accessToken",[143,1653,920],{"class":851},[143,1655,1656],{"class":1623}," string",[143,1658,967],{"class":851},[143,1660,1627],{"class":851},[143,1662,1663],{"class":145,"line":164},[143,1664,1665],{"class":1018},"    // 1. Valider le token avec le serveur d'autorisation (RFC 7662 Token Introspection)\n",[143,1667,1668,1671,1674,1677,1680,1683,1686,1688,1691,1693],{"class":145,"line":171},[143,1669,1670],{"class":886},"    const",[143,1672,1673],{"class":855}," validation",[143,1675,1676],{"class":851}," =",[143,1678,1679],{"class":847}," await",[143,1681,1682],{"class":851}," this.",[143,1684,1685],{"class":947},"validateToken",[143,1687,951],{"class":916},[143,1689,1690],{"class":855},"accessToken",[143,1692,967],{"class":916},[143,1694,881],{"class":851},[143,1696,1697],{"class":145,"line":177},[143,1698,1699],{"class":916},"    \n",[143,1701,1702,1705,1708,1711,1714,1716,1719,1722],{"class":145,"line":183},[143,1703,1704],{"class":847},"    if",[143,1706,1707],{"class":916}," (",[143,1709,1710],{"class":851},"!",[143,1712,1713],{"class":855},"validation",[143,1715,99],{"class":851},[143,1717,1718],{"class":855},"valid",[143,1720,1721],{"class":916},") ",[143,1723,1724],{"class":851},"{\n",[143,1726,1727,1730,1733,1736,1739],{"class":145,"line":189},[143,1728,1729],{"class":847},"      throw",[143,1731,1732],{"class":851}," new",[143,1734,1735],{"class":947}," UnauthorizedError",[143,1737,1738],{"class":916},"()",[143,1740,881],{"class":851},[143,1742,1743],{"class":145,"line":194},[143,1744,1745],{"class":851},"    }\n",[143,1747,1748],{"class":145,"line":200},[143,1749,1699],{"class":916},[143,1751,1752],{"class":145,"line":206},[143,1753,1754],{"class":1018},"    // 2. Échange de token pour accéder aux APIs internes (RFC 8693)\n",[143,1756,1757,1759,1762,1764,1766,1768,1771],{"class":145,"line":1349},[143,1758,1670],{"class":886},[143,1760,1761],{"class":855}," exchangedToken",[143,1763,1676],{"class":851},[143,1765,1679],{"class":847},[143,1767,1682],{"class":851},[143,1769,1770],{"class":947},"exchangeToken",[143,1772,1773],{"class":916},"(\n",[143,1775,1776,1779,1781],{"class":145,"line":1355},[143,1777,1778],{"class":855},"      accessToken",[143,1780,859],{"class":851},[143,1782,1783],{"class":916}," \n",[143,1785,1786,1789,1792,1794],{"class":145,"line":1360},[143,1787,1788],{"class":851},"      '",[143,1790,1791],{"class":874},"urn:ietf:params:oauth:token-type:access_token",[143,1793,878],{"class":851},[143,1795,1796],{"class":851},",\n",[143,1798,1799,1801,1804],{"class":145,"line":1366},[143,1800,1788],{"class":851},[143,1802,1803],{"class":874},"https://api.internal.company.com",[143,1805,1806],{"class":851},"'\n",[143,1808,1809,1812],{"class":145,"line":1372},[143,1810,1811],{"class":916},"    )",[143,1813,881],{"class":851},[143,1815,1816],{"class":145,"line":1377},[143,1817,1699],{"class":916},[143,1819,1820],{"class":145,"line":1383},[143,1821,1822],{"class":1018},"    // 3. Appel à l'API avec le token échangé\n",[143,1824,1825,1828,1830,1832,1835,1837,1840,1842],{"class":145,"line":1388},[143,1826,1827],{"class":847},"    return",[143,1829,1679],{"class":847},[143,1831,1682],{"class":851},[143,1833,1834],{"class":947},"callInternalAPI",[143,1836,951],{"class":916},[143,1838,1839],{"class":855},"exchangedToken",[143,1841,967],{"class":916},[143,1843,881],{"class":851},[143,1845,1846],{"class":145,"line":1394},[143,1847,1848],{"class":851},"  }\n",[143,1850,1851],{"class":145,"line":1400},[143,1852,1853],{"class":855},"  \n",[143,1855,1856],{"class":145,"line":1405},[143,1857,1858],{"class":1018},"  // Métadonnées de ressource protégée (RFC 9728) - Endpoint /.well-known/oauth-protected-resource\n",[143,1860,1861,1863,1866,1868],{"class":145,"line":1411},[143,1862,1632],{"class":886},[143,1864,1865],{"class":916}," getResourceMetadata",[143,1867,1738],{"class":851},[143,1869,1627],{"class":851},[143,1871,1872,1874],{"class":145,"line":1417},[143,1873,1827],{"class":847},[143,1875,1627],{"class":851},[143,1877,1879,1882,1885,1888,1890,1893,1895,1898,1900,1903],{"class":145,"line":1878},25,[143,1880,1881],{"class":851},"      \"",[143,1883,1884],{"class":916},"authorization_servers",[143,1886,1887],{"class":851},"\"",[143,1889,920],{"class":851},[143,1891,1892],{"class":916}," [",[143,1894,1887],{"class":851},[143,1896,1897],{"class":874},"https://auth.company.com",[143,1899,1887],{"class":851},[143,1901,1902],{"class":916},"]",[143,1904,1796],{"class":851},[143,1906,1908,1910,1913,1915,1917,1919,1921,1924,1926,1928,1931,1934,1936,1938,1940,1943,1945,1947],{"class":145,"line":1907},26,[143,1909,1881],{"class":851},[143,1911,1912],{"class":916},"scopes_supported",[143,1914,1887],{"class":851},[143,1916,920],{"class":851},[143,1918,1892],{"class":916},[143,1920,1887],{"class":851},[143,1922,1923],{"class":874},"mcp:read",[143,1925,1887],{"class":851},[143,1927,859],{"class":851},[143,1929,1930],{"class":851}," \"",[143,1932,1933],{"class":874},"mcp:write",[143,1935,1887],{"class":851},[143,1937,859],{"class":851},[143,1939,1930],{"class":851},[143,1941,1942],{"class":874},"mcp:admin",[143,1944,1887],{"class":851},[143,1946,1902],{"class":916},[143,1948,1796],{"class":851},[143,1950,1952,1954,1957,1959,1961,1963,1965,1968,1970,1972],{"class":145,"line":1951},27,[143,1953,1881],{"class":851},[143,1955,1956],{"class":916},"bearer_methods_supported",[143,1958,1887],{"class":851},[143,1960,920],{"class":851},[143,1962,1892],{"class":916},[143,1964,1887],{"class":851},[143,1966,1967],{"class":874},"header",[143,1969,1887],{"class":851},[143,1971,1902],{"class":916},[143,1973,1796],{"class":851},[143,1975,1977,1979,1982,1984,1986,1988,1991],{"class":145,"line":1976},28,[143,1978,1881],{"class":851},[143,1980,1981],{"class":916},"resource_documentation",[143,1983,1887],{"class":851},[143,1985,920],{"class":851},[143,1987,1930],{"class":851},[143,1989,1990],{"class":874},"https://docs.company.com/mcp-api",[143,1992,1993],{"class":851},"\"\n",[143,1995,1997],{"class":145,"line":1996},29,[143,1998,1999],{"class":851},"    };\n",[143,2001,2003],{"class":145,"line":2002},30,[143,2004,1848],{"class":851},[143,2006,2008],{"class":145,"line":2007},31,[143,2009,1853],{"class":855},[143,2011,2013],{"class":145,"line":2012},32,[143,2014,2015],{"class":1018},"  // Gestion de l'en-tête WWW-Authenticate selon la spécification MCP\n",[143,2017,2019,2021,2024,2026,2029,2031,2034,2036],{"class":145,"line":2018},33,[143,2020,1632],{"class":886},[143,2022,2023],{"class":916}," handleUnauthorized",[143,2025,951],{"class":851},[143,2027,2028],{"class":1640},"response",[143,2030,920],{"class":851},[143,2032,2033],{"class":1623}," Response",[143,2035,967],{"class":851},[143,2037,1627],{"class":851},[143,2039,2041,2044,2046,2049,2051,2055],{"class":145,"line":2040},34,[143,2042,2043],{"class":855},"    response",[143,2045,99],{"class":851},[143,2047,2048],{"class":855},"status",[143,2050,1676],{"class":851},[143,2052,2054],{"class":2053},"sbssI"," 401",[143,2056,881],{"class":851},[143,2058,2060,2062,2064,2067,2069,2072,2074,2076,2078,2080,2082],{"class":145,"line":2059},35,[143,2061,2043],{"class":855},[143,2063,99],{"class":851},[143,2065,2066],{"class":855},"headers",[143,2068,99],{"class":851},[143,2070,2071],{"class":947},"set",[143,2073,951],{"class":916},[143,2075,878],{"class":851},[143,2077,1273],{"class":874},[143,2079,878],{"class":851},[143,2081,859],{"class":851},[143,2083,1783],{"class":916},[143,2085,2087,2089,2092],{"class":145,"line":2086},36,[143,2088,1788],{"class":851},[143,2090,2091],{"class":874},"Bearer realm=\"MCP Server\", resource_metadata=\"https://mcp.company.com/.well-known/oauth-protected-resource\"",[143,2093,1806],{"class":851},[143,2095,2097,2099],{"class":145,"line":2096},37,[143,2098,1811],{"class":916},[143,2100,881],{"class":851},[143,2102,2104,2106,2108,2110,2112,2114,2116,2118,2121,2123,2125,2127,2130,2132,2134],{"class":145,"line":2103},38,[143,2105,2043],{"class":855},[143,2107,99],{"class":851},[143,2109,2066],{"class":855},[143,2111,99],{"class":851},[143,2113,2071],{"class":947},[143,2115,951],{"class":916},[143,2117,878],{"class":851},[143,2119,2120],{"class":874},"MCP-Protocol-Version",[143,2122,878],{"class":851},[143,2124,859],{"class":851},[143,2126,871],{"class":851},[143,2128,2129],{"class":874},"2024-11-05",[143,2131,878],{"class":851},[143,2133,967],{"class":916},[143,2135,881],{"class":851},[143,2137,2139,2141,2144],{"class":145,"line":2138},39,[143,2140,1827],{"class":847},[143,2142,2143],{"class":855}," response",[143,2145,881],{"class":851},[143,2147,2149],{"class":145,"line":2148},40,[143,2150,1848],{"class":851},[143,2152,2154],{"class":145,"line":2153},41,[143,2155,2156],{"class":851},"}\n",[76,2158,2160,2166],{"className":2159},[103,104,105],[107,2161,2163],{"id":2162},"types-de-grants-oauth-supportés",[84,2164,2165],{},"Types de Grants OAuth Supportés",[68,2167,2168],{},[71,2169,2170],{"href":117},[84,2171,120],{},[76,2173,2175],{"className":2174},[79],[68,2176,2177],{},"Selon le type de client et le cas d'usage, différents grants OAuth peuvent être utilisés avec cette approche :",[331,2179,2180,2194],{},[334,2181,2182],{},[337,2183,2184,2189],{},[340,2185,2186],{},[84,2187,2188],{},"Type de Grant",[340,2190,2191],{},[84,2192,2193],{},"Type de Client / Cas d'Usage",[353,2195,2196,2206,2216,2226,2236],{},[337,2197,2198,2203],{},[358,2199,2200],{},[84,2201,2202],{},"Authorization Code",[358,2204,2205],{},"Applications web traditionnelles avec backend et applications natives (mobile/desktop) pour SSO via navigateur système",[337,2207,2208,2213],{},[358,2209,2210],{},[84,2211,2212],{},"Client Credentials",[358,2214,2215],{},"Clients comme services web agissant en leur propre nom",[337,2217,2218,2223],{},[358,2219,2220],{},[84,2221,2222],{},"Device Code",[358,2224,2225],{},"Appareils sans navigateur ou avec saisie contrainte (Smart TV, console média, imprimante, etc.)",[337,2227,2228,2233],{},[358,2229,2230],{},[84,2231,2232],{},"Token Exchange",[358,2234,2235],{},"Applications et services obtenant un token d'accès dans des scénarios de délégation et d'impersonation",[337,2237,2238,2243],{},[358,2239,2240],{},[84,2241,2242],{},"JWT Bearer",[358,2244,2245],{},"Client possédant un JWT d'un domaine de sécurité l'échangeant contre un token OAuth 2.0 dans un autre domaine",[76,2247,2249,2255],{"className":2248},[103,104,105],[107,2250,2252],{"id":2251},"flux-dautorisation-complet",[84,2253,2254],{},"Flux d'Autorisation Complet",[68,2256,2257],{},[71,2258,2259],{"href":117},[84,2260,120],{},[76,2262,2264,2269],{"className":2263},[79],[68,2265,2266],{},[84,2267,2268],{},"Diagramme 2 : Flux d'autorisation OAuth 2.1 complet avec interaction utilisateur",[68,2270,2271],{},"Ce diagramme détaille le processus d'autorisation OAuth 2.1 incluant l'interaction avec l'agent utilisateur (navigateur). Il montre comment un client MCP obtient l'autorisation de l'utilisateur via le navigateur, utilise PKCE pour la sécurité, et échange le code d'autorisation contre un token d'accès pour établir une communication sécurisée avec le serveur MCP.",[133,2273,2275],{"className":135,"code":2274,"language":137,"meta":138,"style":138},"sequenceDiagram\n    participant B as Agent Utilisateur (Navigateur)\n    participant C as Client MCP\n    participant M as Serveur MCP (Serveur de Ressources)\n    participant A as Serveur d'Autorisation\n\n    C->>M: Requête MCP sans token\n    M->>C: HTTP 401 Unauthorized avec en-tête WWW-Authenticate\n    Note over C: Extraire l'URL resource_metadata du WWW-Authenticate\n\n    C->>A: GET /.well-known/oauth-authorization-server\n    A->>C: Réponse métadonnées serveur d'autorisation\n\n    alt Enregistrement client dynamique\n        C->>A: POST /register\n        A->>C: Identifiants Client\n    end\n\n    Note over C: Générer paramètres PKCE\n    C->>B: Ouvrir navigateur avec URL d'autorisation + code_challenge\n    B->>A: Requête d'autorisation\n    Note over A: L'utilisateur autorise\n    A->>B: Redirection vers callback avec code d'autorisation\n    B->>C: Callback code d'autorisation\n    C->>A: Requête token + code_verifier\n    A->>C: Token d'accès (+ token de rafraîchissement)\n    C->>M: Requête MCP avec token d'accès\n    M-->>C: Réponse MCP\n",[140,2276,2277,2281,2286,2290,2294,2298,2302,2306,2311,2316,2320,2324,2329,2333,2338,2343,2348,2353,2357,2362,2367,2372,2377,2382,2387,2392,2397,2401],{"__ignoreMap":138},[143,2278,2279],{"class":145,"line":146},[143,2280,149],{},[143,2282,2283],{"class":145,"line":152},[143,2284,2285],{},"    participant B as Agent Utilisateur (Navigateur)\n",[143,2287,2288],{"class":145,"line":158},[143,2289,1303],{},[143,2291,2292],{"class":145,"line":164},[143,2293,1308],{},[143,2295,2296],{"class":145,"line":171},[143,2297,1313],{},[143,2299,2300],{"class":145,"line":177},[143,2301,168],{"emptyLinePlaceholder":167},[143,2303,2304],{"class":145,"line":183},[143,2305,1322],{},[143,2307,2308],{"class":145,"line":189},[143,2309,2310],{},"    M->>C: HTTP 401 Unauthorized avec en-tête WWW-Authenticate\n",[143,2312,2313],{"class":145,"line":194},[143,2314,2315],{},"    Note over C: Extraire l'URL resource_metadata du WWW-Authenticate\n",[143,2317,2318],{"class":145,"line":200},[143,2319,168],{"emptyLinePlaceholder":167},[143,2321,2322],{"class":145,"line":206},[143,2323,1363],{},[143,2325,2326],{"class":145,"line":1349},[143,2327,2328],{},"    A->>C: Réponse métadonnées serveur d'autorisation\n",[143,2330,2331],{"class":145,"line":1355},[143,2332,168],{"emptyLinePlaceholder":167},[143,2334,2335],{"class":145,"line":1360},[143,2336,2337],{},"    alt Enregistrement client dynamique\n",[143,2339,2340],{"class":145,"line":1366},[143,2341,2342],{},"        C->>A: POST /register\n",[143,2344,2345],{"class":145,"line":1372},[143,2346,2347],{},"        A->>C: Identifiants Client\n",[143,2349,2350],{"class":145,"line":1377},[143,2351,2352],{},"    end\n",[143,2354,2355],{"class":145,"line":1383},[143,2356,168],{"emptyLinePlaceholder":167},[143,2358,2359],{"class":145,"line":1388},[143,2360,2361],{},"    Note over C: Générer paramètres PKCE\n",[143,2363,2364],{"class":145,"line":1394},[143,2365,2366],{},"    C->>B: Ouvrir navigateur avec URL d'autorisation + code_challenge\n",[143,2368,2369],{"class":145,"line":1400},[143,2370,2371],{},"    B->>A: Requête d'autorisation\n",[143,2373,2374],{"class":145,"line":1405},[143,2375,2376],{},"    Note over A: L'utilisateur autorise\n",[143,2378,2379],{"class":145,"line":1411},[143,2380,2381],{},"    A->>B: Redirection vers callback avec code d'autorisation\n",[143,2383,2384],{"class":145,"line":1417},[143,2385,2386],{},"    B->>C: Callback code d'autorisation\n",[143,2388,2389],{"class":145,"line":1878},[143,2390,2391],{},"    C->>A: Requête token + code_verifier\n",[143,2393,2394],{"class":145,"line":1907},[143,2395,2396],{},"    A->>C: Token d'accès (+ token de rafraîchissement)\n",[143,2398,2399],{"class":145,"line":1951},[143,2400,1408],{},[143,2402,2403],{"class":145,"line":1976},[143,2404,1414],{},[76,2406,2408,2414],{"className":2407},[103,104,105],[107,2409,2411],{"id":2410},"considérations-de-sécurité",[84,2412,2413],{},"Considérations de Sécurité",[68,2415,2416],{},[71,2417,2418],{"href":117},[84,2419,120],{},[76,2421,2423,2458],{"className":2422},[1439,1440,1441,1442,1443,1444],[76,2424,2426,2432],{"className":2425},[79],[1449,2427,2429],{"id":2428},"bonnes-pratiques",[84,2430,2431],{},"🔐 Bonnes Pratiques",[672,2433,2434,2440,2446,2452],{},[675,2435,2436,2439],{},[84,2437,2438],{},"PKCE requis"," pour tous les clients et serveurs d'autorisation MCP",[675,2441,2442,2445],{},[84,2443,2444],{},"Stockage sécurisé des tokens"," suivant les meilleures pratiques OAuth 2.0",[675,2447,2448,2451],{},[84,2449,2450],{},"Validation des URI de redirection"," pour prévenir les vulnérabilités de redirection ouverte",[675,2453,2454,2457],{},[84,2455,2456],{},"HTTPS obligatoire"," pour tous les endpoints d'autorisation",[76,2459,2461,2467],{"className":2460},[79],[1449,2462,2464],{"id":2463},"️-gestion-derreurs",[84,2465,2466],{},"⚠️ Gestion d'Erreurs",[331,2468,2469,2488],{},[334,2470,2471],{},[337,2472,2473,2478,2483],{},[340,2474,2475],{},[84,2476,2477],{},"Code de Statut",[340,2479,2480],{},[84,2481,2482],{},"Description",[340,2484,2485],{},[84,2486,2487],{},"Usage",[353,2489,2490,2503,2516],{},[337,2491,2492,2497,2500],{},[358,2493,2494],{},[84,2495,2496],{},"401",[358,2498,2499],{},"Non autorisé",[358,2501,2502],{},"Autorisation requise ou token invalide",[337,2504,2505,2510,2513],{},[358,2506,2507],{},[84,2508,2509],{},"403",[358,2511,2512],{},"Interdit",[358,2514,2515],{},"Scopes invalides ou permissions insuffisantes",[337,2517,2518,2523,2526],{},[358,2519,2520],{},[84,2521,2522],{},"400",[358,2524,2525],{},"Requête incorrecte",[358,2527,2528],{},"Requête d'autorisation malformée",[76,2530,2532,2538],{"className":2531},[103,104,105],[107,2533,2535],{"id":2534},"impact-sur-lécosystème-mcp",[84,2536,2537],{},"Impact sur l'Écosystème MCP",[68,2539,2540],{},[71,2541,2542],{"href":117},[84,2543,120],{},[76,2545,2547,2553,2558,2567,2580,2586,2592,2629,2634,2661,2667],{"className":2546},[79],[68,2548,2549,2550,2552],{},"Cette approche révolutionnaire simplifie considérablement l'intégration des serveurs d'autorisation, permettant de se connecter directement aux fournisseurs comme ",[84,2551,1591],{}," et autres sans avoir à développer un serveur d'autorisation from scratch.",[68,2554,2555],{},[84,2556,2557],{},"Moins de code boilerplate. Plus de développement. MCP devient plus adapté aux entreprises.",[68,2559,2560,2561,2563,2564],{},"Comme l'a annoncé ",[84,2562,1136],{}," : ",[1276,2565,2566],{},"\"Big thank you to everyone who spent their valuable time providing input, reviewing the PR and waiting patiently while this change was discussed over the past 4 weeks. It was a massive community effort.\"",[68,2568,2569,2570,2576,2577,99],{},"Cette nouvelle spécification est maintenant disponible dans le ",[84,2571,2572],{},[71,2573,2575],{"href":1263,"rel":2574},[1122],"draft officiel MCP - Section Authorization"," et incluse dans la spécification du ",[84,2578,2579],{},"18 juin 2025",[128,2581,2583],{"id":2582},"exigences-de-la-spécification-mcp",[84,2584,2585],{},"Exigences de la Spécification MCP",[68,2587,2588,2589,2591],{},"Selon la spécification officielle, les serveurs MCP agissant comme serveurs de ressources ",[84,2590,1269],{}," :",[2593,2594,2595,2604,2613,2621],"ol",{},[675,2596,2597,1707,2600,967],{},[84,2598,2599],{},"Implémenter OAuth 2.0 Protected Resource Metadata",[71,2601,2603],{"href":1241,"rel":2602},[1122],"RFC9728",[675,2605,2606,1274,2611],{},[84,2607,2608,2609],{},"Utiliser l'en-tête ",[140,2610,1273],{},[1276,2612,1278],{},[675,2614,2615],{},[84,2616,2617,2618],{},"Supporter l'endpoint ",[140,2619,2620],{},"/.well-known/oauth-protected-resource",[675,2622,2623,2628],{},[84,2624,2625,2626],{},"Inclure le champ ",[140,2627,1884],{}," avec au moins un serveur d'autorisation",[68,2630,2631,2632,2591],{},"Les clients MCP ",[84,2633,1269],{},[2593,2635,2636,2644,2653],{},[675,2637,2638,2643],{},[84,2639,2640,2641],{},"Parser les en-têtes ",[140,2642,1273],{}," et répondre aux réponses HTTP 401",[675,2645,2646,1707,2649,967],{},[84,2647,2648],{},"Suivre le protocole OAuth 2.0 Authorization Server Metadata",[71,2650,2652],{"href":1181,"rel":2651},[1122],"RFC8414",[675,2654,2655,2660],{},[84,2656,2657,2658],{},"Inclure l'en-tête ",[140,2659,2120],{}," dans les requêtes",[128,2662,2664],{"id":2663},"mises-à-jour-des-sdks-en-cours",[84,2665,2666],{},"Mises à jour des SDKs en cours :",[672,2668,2669,2679,2689],{},[675,2670,2671,2678],{},[84,2672,2673],{},[71,2674,2677],{"href":2675,"rel":2676},"https://github.com/modelcontextprotocol/python-sdk/pull/686",[1122],"Python SDK"," - Support pour la nouvelle spécification d'autorisation",[675,2680,2681,2688],{},[84,2682,2683],{},[71,2684,2687],{"href":2685,"rel":2686},"https://github.com/modelcontextprotocol/csharp-sdk/pull/377",[1122],"C# SDK"," - Intégration ASP.NET Core native AuthN/AuthZ",[675,2690,2691,2698,2699],{},[84,2692,2693],{},[71,2694,2697],{"href":2695,"rel":2696},"https://github.com/gao-sun/mcp-auth",[1122],"MCP Auth"," - Implémentation de référence par ",[84,2700,1207],{},[133,2702,2706],{"className":2703,"code":2704,"language":2705,"meta":138,"style":138},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// Exemple de métadonnées de ressource protégée (RFC 9728)\n{\n  \"authorization_servers\": [\n    \"https://auth.company.com\"\n  ],\n  \"resource_metadata\": {\n    \"resource\": \"https://mcp.company.com\",\n    \"authorization_servers\": [\"https://auth.company.com\"],\n    \"scopes_supported\": [\"mcp:read\", \"mcp:write\", \"mcp:admin\"],\n    \"bearer_methods_supported\": [\"header\"],\n    \"resource_documentation\": \"https://docs.company.com/mcp-api\"\n  }\n}\n","json",[140,2707,2708,2713,2717,2731,2740,2745,2758,2778,2799,2835,2855,2871,2875],{"__ignoreMap":138},[143,2709,2710],{"class":145,"line":146},[143,2711,2712],{"class":1018},"// Exemple de métadonnées de ressource protégée (RFC 9728)\n",[143,2714,2715],{"class":145,"line":152},[143,2716,1724],{"class":851},[143,2718,2719,2722,2724,2726,2728],{"class":145,"line":158},[143,2720,2721],{"class":851},"  \"",[143,2723,1884],{"class":886},[143,2725,1887],{"class":851},[143,2727,920],{"class":851},[143,2729,2730],{"class":851}," [\n",[143,2732,2733,2736,2738],{"class":145,"line":164},[143,2734,2735],{"class":851},"    \"",[143,2737,1897],{"class":874},[143,2739,1993],{"class":851},[143,2741,2742],{"class":145,"line":171},[143,2743,2744],{"class":851},"  ],\n",[143,2746,2747,2749,2752,2754,2756],{"class":145,"line":177},[143,2748,2721],{"class":851},[143,2750,2751],{"class":886},"resource_metadata",[143,2753,1887],{"class":851},[143,2755,920],{"class":851},[143,2757,1627],{"class":851},[143,2759,2760,2762,2765,2767,2769,2771,2774,2776],{"class":145,"line":183},[143,2761,2735],{"class":851},[143,2763,2764],{"class":1623},"resource",[143,2766,1887],{"class":851},[143,2768,920],{"class":851},[143,2770,1930],{"class":851},[143,2772,2773],{"class":874},"https://mcp.company.com",[143,2775,1887],{"class":851},[143,2777,1796],{"class":851},[143,2779,2780,2782,2784,2786,2788,2790,2792,2794,2796],{"class":145,"line":189},[143,2781,2735],{"class":851},[143,2783,1884],{"class":1623},[143,2785,1887],{"class":851},[143,2787,920],{"class":851},[143,2789,1892],{"class":851},[143,2791,1887],{"class":851},[143,2793,1897],{"class":874},[143,2795,1887],{"class":851},[143,2797,2798],{"class":851},"],\n",[143,2800,2801,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2831,2833],{"class":145,"line":194},[143,2802,2735],{"class":851},[143,2804,1912],{"class":1623},[143,2806,1887],{"class":851},[143,2808,920],{"class":851},[143,2810,1892],{"class":851},[143,2812,1887],{"class":851},[143,2814,1923],{"class":874},[143,2816,1887],{"class":851},[143,2818,859],{"class":851},[143,2820,1930],{"class":851},[143,2822,1933],{"class":874},[143,2824,1887],{"class":851},[143,2826,859],{"class":851},[143,2828,1930],{"class":851},[143,2830,1942],{"class":874},[143,2832,1887],{"class":851},[143,2834,2798],{"class":851},[143,2836,2837,2839,2841,2843,2845,2847,2849,2851,2853],{"class":145,"line":200},[143,2838,2735],{"class":851},[143,2840,1956],{"class":1623},[143,2842,1887],{"class":851},[143,2844,920],{"class":851},[143,2846,1892],{"class":851},[143,2848,1887],{"class":851},[143,2850,1967],{"class":874},[143,2852,1887],{"class":851},[143,2854,2798],{"class":851},[143,2856,2857,2859,2861,2863,2865,2867,2869],{"class":145,"line":206},[143,2858,2735],{"class":851},[143,2860,1981],{"class":1623},[143,2862,1887],{"class":851},[143,2864,920],{"class":851},[143,2866,1930],{"class":851},[143,2868,1990],{"class":874},[143,2870,1993],{"class":851},[143,2872,2873],{"class":145,"line":1349},[143,2874,1848],{"class":851},[143,2876,2877],{"class":145,"line":1355},[143,2878,2156],{"class":851},[133,2880,2884],{"className":2881,"code":2882,"language":2883,"meta":138,"style":138},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// En-tête WWW-Authenticate pour découverte (RFC 9728)\nHTTP/1.1 401 Unauthorized\nWWW-Authenticate: Bearer realm=\"MCP Server\",\n                  resource_metadata=\"https://mcp.company.com/.well-known/oauth-protected-resource\"\nMCP-Protocol-Version: 2024-11-05\n","http",[140,2885,2886,2891,2896,2901,2906],{"__ignoreMap":138},[143,2887,2888],{"class":145,"line":146},[143,2889,2890],{},"// En-tête WWW-Authenticate pour découverte (RFC 9728)\n",[143,2892,2893],{"class":145,"line":152},[143,2894,2895],{},"HTTP/1.1 401 Unauthorized\n",[143,2897,2898],{"class":145,"line":158},[143,2899,2900],{},"WWW-Authenticate: Bearer realm=\"MCP Server\",\n",[143,2902,2903],{"class":145,"line":164},[143,2904,2905],{},"                  resource_metadata=\"https://mcp.company.com/.well-known/oauth-protected-resource\"\n",[143,2907,2908],{"class":145,"line":171},[143,2909,2910],{},"MCP-Protocol-Version: 2024-11-05\n",[128,2912,2914],{"id":2913},"flux-de-découverte-officiel-mcp",[84,2915,2916],{},"Flux de Découverte Officiel MCP",[68,2918,1258,2919,2925],{},[84,2920,2921],{},[71,2922,2924],{"href":1263,"rel":2923},[1122],"spécification MCP 2.3.4",", le processus de découverte suit ce flux précis :",[2593,2927,2928,2934,2946,2955,2963,2968,2975,2981],{},[675,2929,2930,2933],{},[84,2931,2932],{},"Client MCP"," fait une requête sans token",[675,2935,2936,2939,2940,2943,2944],{},[84,2937,2938],{},"Serveur MCP"," répond avec ",[140,2941,2942],{},"HTTP 401"," et en-tête ",[140,2945,1273],{},[675,2947,2948,2951,2952,2954],{},[84,2949,2950],{},"Client"," extrait l'URL ",[140,2953,2751],{}," de l'en-tête",[675,2956,2957,2959,2960,2962],{},[84,2958,2950],{}," récupère ",[140,2961,2620],{}," du serveur MCP",[675,2964,2965,2967],{},[84,2966,2950],{}," utilise ces métadonnées pour construire l'URL du serveur d'autorisation",[675,2969,2970,2959,2972],{},[84,2971,2950],{},[140,2973,2974],{},"/.well-known/oauth-authorization-server",[675,2976,2977,2980],{},[84,2978,2979],{},"Flux OAuth 2.1"," standard se déroule",[675,2982,2983,2986],{},[84,2984,2985],{},"Communication MCP"," reprend avec le token valide",[68,2988,2989,2990,2992,2993,2995],{},"Cette approche, validée par ",[84,2991,1207],{}," avec des tests sur ",[84,2994,1211],{},", est maintenant la méthode recommandée dans l'écosystème MCP.",[76,2997,2999,3005],{"className":2998},[103,104,105],[107,3000,3002],{"id":3001},"conclusion",[84,3003,3004],{},"Conclusion",[68,3006,3007],{},[71,3008,3009],{"href":117},[84,3010,120],{},[76,3012,3014,3026,3031,3057,3063,3101,3107,3114,3128],{"className":3013},[79],[68,3015,3016,3017,3019,3020,3022,3023,3025],{},"L'adoption de l'approche ",[84,3018,1235],{}," pour les serveurs MCP marque un tournant décisif dans l'évolution de l'écosystème MCP vers une architecture plus mature et adaptée aux entreprises. Cette nouvelle spécification, fruit d'un effort communautaire de 4 semaines dirigé par ",[84,3021,1136],{}," et validé par ",[84,3024,1207],{},", transforme radicalement la façon dont nous concevons l'authentification et l'autorisation dans MCP.",[68,3027,3028],{},[84,3029,3030],{},"Pourquoi agir maintenant ?",[672,3032,3033,3039,3045,3051],{},[675,3034,780,3035,3038],{},[84,3036,3037],{},"Spécification officialisée"," dans MCP 2.3.4 (18 juin 2025)",[675,3040,780,3041,3044],{},[84,3042,3043],{},"SDKs en cours de mise à jour"," (Python, C#, JavaScript)",[675,3046,780,3047,3050],{},[84,3048,3049],{},"Implémentations de référence disponibles"," (MCP Auth par gao-sun)",[675,3052,780,3053,3056],{},[84,3054,3055],{},"Support confirmé"," pour Okta, Auth0, Microsoft Entra ID, Keycloak",[128,3058,3060],{"id":3059},"prochaines-étapes-recommandées",[84,3061,3062],{},"🚀 Prochaines Étapes Recommandées",[2593,3064,3065,3076,3086,3092],{},[675,3066,3067,2563,3070,3073,3074],{},[84,3068,3069],{},"Explorez l'implémentation de référence",[71,3071,2697],{"href":2695,"rel":3072},[1122]," par ",[84,3075,1207],{},[675,3077,3078,2563,3081],{},[84,3079,3080],{},"Consultez la spécification officielle",[71,3082,3085],{"href":3083,"rel":3084},"https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/draft/basic/authorization.mdx",[1122],"MCP Authorization Draft",[675,3087,3088,3091],{},[84,3089,3090],{},"Testez avec votre fournisseur d'identité"," existant (Okta, Auth0, etc.)",[675,3093,3094,2563,3097],{},[84,3095,3096],{},"Rejoignez la discussion communautaire",[71,3098,3100],{"href":1140,"rel":3099},[1122],"GitHub Discussions",[128,3102,3104],{"id":3103},"besoin-daide-pour-implémenter-mcp-dans-votre-organisation",[84,3105,3106],{},"💡 Besoin d'Aide pour Implémenter MCP dans Votre Organisation ?",[68,3108,3109,3110,3113],{},"En tant qu'",[84,3111,3112],{},"architecte spécialisé en MCP et OAuth",", je peux vous accompagner dans :",[672,3115,3116,3119,3122,3125],{},[675,3117,3118],{},"Migration vers l'architecture serveur de ressources OAuth",[675,3120,3121],{},"Intégration avec vos systèmes d'identité existants",[675,3123,3124],{},"Formation de vos équipes sur les meilleures pratiques MCP",[675,3126,3127],{},"Audit de sécurité et architecture review",[68,3129,3130],{},[84,3131,3132],{},[71,3133,3135],{"href":3134},"/contact","Contactez-moi pour discuter de votre projet MCP →",[76,3137,3139],{"className":3138},[1056,1057,1058,1059],[68,3140,3141],{},[71,3142,3143],{"href":117},[84,3144,120],{},[1067,3146,3147],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":138,"searchDepth":152,"depth":152,"links":3149},[3150,3151,3152,3153,3154,3155,3156,3157,3162],{"id":1153,"depth":152,"text":1156},{"id":1217,"depth":152,"text":1220},{"id":1426,"depth":152,"text":1429},{"id":1555,"depth":152,"text":1558},{"id":2162,"depth":152,"text":2165},{"id":2251,"depth":152,"text":2254},{"id":2410,"depth":152,"text":2413},{"id":2534,"depth":152,"text":2537,"children":3158},[3159,3160,3161],{"id":2582,"depth":158,"text":2585},{"id":2663,"depth":158,"text":2666},{"id":2913,"depth":158,"text":2916},{"id":3001,"depth":152,"text":3004,"children":3163},[3164,3165],{"id":3059,"depth":158,"text":3062},{"id":3103,"depth":158,"text":3106},"2025-06-27","Traiter le serveur MCP comme un serveur de ressources OAuth plutôt qu'un serveur d'autorisation permet une architecture plus simple, sans état et adaptée aux entreprises.",{"src":1087},{},{"title":15,"description":3167},"Fw37KPtU629WGmkjjPlU_Be2Pl4UELIht35YqKmB8iM",{"id":3173,"title":23,"authors":3174,"badge":3177,"body":3180,"date":4622,"description":4623,"extension":1085,"image":4624,"meta":4625,"navigation":167,"path":24,"seo":4626,"stem":25,"__hash__":4627},"posts_fr/fr/blog/2. mcp-create.md",[3175],{"name":55,"description":56,"to":57,"avatar":3176},{"src":59},{"label":3178,"color":3179,"variant":63},"MCP, Temps Réel","error",{"type":65,"value":3181,"toc":4610},[3182,3188,3203,3250,3265,3288,3303,3313,3406,3421,3828,3970,3985,3991,4158,4173,4191,4241,4256,4284,4299,4329,4415,4430,4436,4443,4566,4579,4588,4598,4607],[76,3183,3185],{"className":3184},[79],[68,3186,3187],{},"Les serveurs MCP révolutionnent la façon dont les modèles de langage interagissent avec les sources de données externes. Considérez-les comme des plugins sophistiqués qui étendent les capacités de l'IA au-delà de leurs données d'entraînement. Dans ce tutoriel complet, nous construirons un serveur MCP météorologique qui connecte Claude, GPT-4, ou tout autre LLM aux informations météorologiques en temps réel en utilisant Python et l'API Open-Meteo.",[76,3189,3191,3197],{"className":3190},[103,104,105],[107,3192,3194],{"id":3193},"quest-ce-quun-serveur-mcp",[84,3195,3196],{},"Qu'est-ce qu'un Serveur MCP ?",[68,3198,3199],{},[71,3200,3201],{"href":117},[84,3202,120],{},[76,3204,3206,3224],{"className":3205},[1439,1440,1441,1442,1443,1444],[76,3207,3208],{},[68,3209,3210,3219],{},[3211,3212],"img",{"alt":3213,"className":3214,"height":3216,"src":3217,"style":3218},"Diagramme d'Architecture MCP",[3215],"rounded-md",400,"/blog/mcp/llm-has-tools.png","padding: 20px; background-color: white",[71,3220,3223],{"href":3221,"rel":3222},"http://one-front/blog/mcp",[1122],"Serveur MCP : Connecter l'IA aux Données en Temps Réel",[76,3225,3227,3230,3233],{"className":3226},[79],[68,3228,3229],{},"Les serveurs MCP étendent les capacités des modèles de langage en les connectant aux sources de données et services. Ce sont des applications agnostiques qui facilitent l'intégration avec n'importe quelle donnée ou service que vous pouvez imaginer. Pensez aux appels de fonction, mais les fonctions sont des plugins qui peuvent virtuellement tout faire.",[68,3231,3232],{},"Les serveurs MCP exposent trois primitives principales :",[672,3234,3235,3240,3245],{},[675,3236,3237,3239],{},[84,3238,603],{}," (contrôlées par le client) : Exposition passive de données pour le contexte",[675,3241,3242,3244],{},[84,3243,583],{}," (contrôlés par le modèle) : Fonctionnalité exécutable pour les actions",[675,3246,3247,3249],{},[84,3248,622],{}," (contrôlés par l'utilisateur) : Workflows réutilisables et modèles",[76,3251,3253,3259],{"className":3252},[103,104,105],[107,3254,3256],{"id":3255},"pourquoi-les-données-météorologiques",[84,3257,3258],{},"Pourquoi les Données Météorologiques ?",[68,3260,3261],{},[71,3262,3263],{"href":117},[84,3264,120],{},[76,3266,3268,3271,3274],{"className":3267},[79],[68,3269,3270],{},"Les données météorologiques fournissent un excellent exemple pour le développement de serveurs MCP car elles démontrent l'intégration d'API du monde réel avec des applications pratiques. Les modèles de langage excellent à transformer les données météorologiques brutes (température, vitesse du vent, humidité) en descriptions en langage naturel et recommandations actionnables.",[68,3272,3273],{},"Nous utiliserons l'API Open-Meteo car elle est :",[672,3275,3276,3279,3282,3285],{},[675,3277,3278],{},"Gratuite pour un usage non commercial",[675,3280,3281],{},"Aucune clé API requise",[675,3283,3284],{},"Facilement configurable via les paramètres de requête",[675,3286,3287],{},"Parfaite pour l'intégration LLM",[76,3289,3291,3297],{"className":3290},[103,104,105],[107,3292,3294],{"id":3293},"configuration-du-projet",[84,3295,3296],{},"Configuration du Projet",[68,3298,3299],{},[71,3300,3301],{"href":117},[84,3302,120],{},[76,3304,3306],{"className":3305},[79],[68,3307,3308,3309,3312],{},"Avant de plonger dans le code, assurez-vous d'avoir les outils nécessaires installés. Nous utiliserons ",[140,3310,3311],{},"uv",", un gestionnaire de paquets Python basé sur Rust qui rend la gestion des dépendances transparente.",[133,3314,3318],{"className":3315,"code":3316,"language":3317,"meta":138,"style":138},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Créer le répertoire du projet\nmkdir mcp-server-weather\ncd mcp-server-weather\n\n# Initialiser le projet uv\nuv init\n\n# Créer et activer l'environnement virtuel\nuv venv\nsource .venv/bin/activate\n\n# Installer les dépendances\nuv add \"mcp[cli]\" httpx\n","bash",[140,3319,3320,3325,3333,3340,3344,3349,3356,3360,3365,3372,3380,3384,3389],{"__ignoreMap":138},[143,3321,3322],{"class":145,"line":146},[143,3323,3324],{"class":1018},"# Créer le répertoire du projet\n",[143,3326,3327,3330],{"class":145,"line":152},[143,3328,3329],{"class":1623},"mkdir",[143,3331,3332],{"class":874}," mcp-server-weather\n",[143,3334,3335,3338],{"class":145,"line":158},[143,3336,3337],{"class":947},"cd",[143,3339,3332],{"class":874},[143,3341,3342],{"class":145,"line":164},[143,3343,168],{"emptyLinePlaceholder":167},[143,3345,3346],{"class":145,"line":171},[143,3347,3348],{"class":1018},"# Initialiser le projet uv\n",[143,3350,3351,3353],{"class":145,"line":177},[143,3352,3311],{"class":1623},[143,3354,3355],{"class":874}," init\n",[143,3357,3358],{"class":145,"line":183},[143,3359,168],{"emptyLinePlaceholder":167},[143,3361,3362],{"class":145,"line":189},[143,3363,3364],{"class":1018},"# Créer et activer l'environnement virtuel\n",[143,3366,3367,3369],{"class":145,"line":194},[143,3368,3311],{"class":1623},[143,3370,3371],{"class":874}," venv\n",[143,3373,3374,3377],{"class":145,"line":200},[143,3375,3376],{"class":947},"source",[143,3378,3379],{"class":874}," .venv/bin/activate\n",[143,3381,3382],{"class":145,"line":206},[143,3383,168],{"emptyLinePlaceholder":167},[143,3385,3386],{"class":145,"line":1349},[143,3387,3388],{"class":1018},"# Installer les dépendances\n",[143,3390,3391,3393,3396,3398,3401,3403],{"class":145,"line":1355},[143,3392,3311],{"class":1623},[143,3394,3395],{"class":874}," add",[143,3397,1930],{"class":851},[143,3399,3400],{"class":874},"mcp[cli]",[143,3402,1887],{"class":851},[143,3404,3405],{"class":874}," httpx\n",[76,3407,3409,3415],{"className":3408},[103,104,105],[107,3410,3412],{"id":3411},"construction-du-serveur-mcp",[84,3413,3414],{},"Construction du Serveur MCP",[68,3416,3417],{},[71,3418,3419],{"href":117},[84,3420,120],{},[76,3422,3424,3816],{"className":3423},[1439,1440,1441,1442,1443,1444],[76,3425,3426],{},[133,3427,3429],{"className":2703,"code":3428,"language":2705,"meta":138,"style":138},"  [{\"type\": \"text\", \"text\": \"Prévisions pour 40.7128, -74.006 :\\n\\nAujourd'hui :\\nTempérature : 66°F\\nVent : 13 à 16 mph O\\nPrincipalement Ensoleillé\\n---\\nCe soir :\\nTempérature : 55°F\\nVent : 5 à 13 mph O\\nPartiellement Nuageux\\n---\\nLundi :\\nTempérature : 71°F\\nVent : 8 mph O\\nEnsoleillé\\n---\\nLundi Soir :\\nTempérature : 59°F\\nVent : 3 à 8 mph O\\nPrincipalement Dégagé\\n---\\nMardi :\\nTempérature : 77°F\\nVent : 3 à 7 mph SO\\nEnsoleillé\\n---\\nMardi Soir :\\nTempérature : 65°F\\nVent : 5 à 8 mph S\\nPrincipalement Dégagé\\n---\\nMercredi :\\nTempérature : 82°F\\nVent : 5 à 12 mph SO\\nEnsoleillé\\n---\\nMercredi Soir :\\nTempérature : 69°F\\nVent : 8 à 12 mph SO\\nPrincipalement Dégagé\\n---\\nJeudi :\\nTempérature : 85°F\\nVent : 7 à 12 mph SO\\nPrincipalement Ensoleillé\\n---\\nJeudi Soir :\\nTempérature : 72°F\\nVent : 7 à 12 mph SO\\nPartiellement Nuageux\\n---\\nVendredi :\\nTempérature : 82°F\\nVent : 7 à 12 mph SO\\nPossibilité d'Averses\\n---\\nVendredi Soir :\\nTempérature : 70°F\\nVent : 7 à 12 mph SO\\nPossibilité d'Averses\\n---\\nSamedi :\\nTempérature : 76°F\\nVent : 9 mph O\\nPossibilité d'Averses\\n---\\nSamedi Soir :\\nTempérature : 67°F\\nVent : 6 à 9 mph NO\\nPossibilité d'Averses\\n---\", \"uuid\": \"fb196843-938b-4a75-b1a5-b660892f9817\"}]\n",[140,3430,3431],{"__ignoreMap":138},[143,3432,3433,3436,3438,3441,3443,3445,3447,3450,3452,3454,3456,3458,3460,3462,3464,3467,3470,3473,3476,3479,3481,3484,3486,3489,3491,3494,3496,3499,3501,3504,3506,3509,3511,3514,3516,3518,3520,3523,3525,3528,3530,3533,3535,3538,3540,3542,3544,3547,3549,3552,3554,3557,3559,3562,3564,3566,3568,3571,3573,3576,3578,3581,3583,3585,3587,3589,3591,3594,3596,3599,3601,3604,3606,3608,3610,3612,3614,3617,3619,3622,3624,3627,3629,3631,3633,3635,3637,3640,3642,3645,3647,3650,3652,3654,3656,3658,3660,3663,3665,3668,3670,3673,3675,3677,3679,3681,3683,3686,3688,3691,3693,3695,3697,3699,3701,3703,3705,3708,3710,3712,3714,3716,3718,3721,3723,3725,3727,3730,3732,3735,3737,3739,3741,3743,3745,3747,3749,3752,3754,3757,3759,3762,3764,3766,3768,3770,3772,3775,3777,3780,3782,3785,3787,3789,3791,3793,3795,3797,3799,3802,3804,3806,3808,3811,3813],{"class":145,"line":146},[143,3434,3435],{"class":851},"  [{",[143,3437,1887],{"class":851},[143,3439,3440],{"class":886},"type",[143,3442,1887],{"class":851},[143,3444,920],{"class":851},[143,3446,1930],{"class":851},[143,3448,3449],{"class":874},"text",[143,3451,1887],{"class":851},[143,3453,859],{"class":851},[143,3455,1930],{"class":851},[143,3457,3449],{"class":886},[143,3459,1887],{"class":851},[143,3461,920],{"class":851},[143,3463,1930],{"class":851},[143,3465,3466],{"class":874},"Prévisions pour 40.7128, -74.006 :",[143,3468,3469],{"class":855},"\\n\\n",[143,3471,3472],{"class":874},"Aujourd'hui :",[143,3474,3475],{"class":855},"\\n",[143,3477,3478],{"class":874},"Température : 66°F",[143,3480,3475],{"class":855},[143,3482,3483],{"class":874},"Vent : 13 à 16 mph O",[143,3485,3475],{"class":855},[143,3487,3488],{"class":874},"Principalement Ensoleillé",[143,3490,3475],{"class":855},[143,3492,3493],{"class":874},"---",[143,3495,3475],{"class":855},[143,3497,3498],{"class":874},"Ce soir :",[143,3500,3475],{"class":855},[143,3502,3503],{"class":874},"Température : 55°F",[143,3505,3475],{"class":855},[143,3507,3508],{"class":874},"Vent : 5 à 13 mph O",[143,3510,3475],{"class":855},[143,3512,3513],{"class":874},"Partiellement Nuageux",[143,3515,3475],{"class":855},[143,3517,3493],{"class":874},[143,3519,3475],{"class":855},[143,3521,3522],{"class":874},"Lundi :",[143,3524,3475],{"class":855},[143,3526,3527],{"class":874},"Température : 71°F",[143,3529,3475],{"class":855},[143,3531,3532],{"class":874},"Vent : 8 mph O",[143,3534,3475],{"class":855},[143,3536,3537],{"class":874},"Ensoleillé",[143,3539,3475],{"class":855},[143,3541,3493],{"class":874},[143,3543,3475],{"class":855},[143,3545,3546],{"class":874},"Lundi Soir :",[143,3548,3475],{"class":855},[143,3550,3551],{"class":874},"Température : 59°F",[143,3553,3475],{"class":855},[143,3555,3556],{"class":874},"Vent : 3 à 8 mph O",[143,3558,3475],{"class":855},[143,3560,3561],{"class":874},"Principalement Dégagé",[143,3563,3475],{"class":855},[143,3565,3493],{"class":874},[143,3567,3475],{"class":855},[143,3569,3570],{"class":874},"Mardi :",[143,3572,3475],{"class":855},[143,3574,3575],{"class":874},"Température : 77°F",[143,3577,3475],{"class":855},[143,3579,3580],{"class":874},"Vent : 3 à 7 mph SO",[143,3582,3475],{"class":855},[143,3584,3537],{"class":874},[143,3586,3475],{"class":855},[143,3588,3493],{"class":874},[143,3590,3475],{"class":855},[143,3592,3593],{"class":874},"Mardi Soir :",[143,3595,3475],{"class":855},[143,3597,3598],{"class":874},"Température : 65°F",[143,3600,3475],{"class":855},[143,3602,3603],{"class":874},"Vent : 5 à 8 mph S",[143,3605,3475],{"class":855},[143,3607,3561],{"class":874},[143,3609,3475],{"class":855},[143,3611,3493],{"class":874},[143,3613,3475],{"class":855},[143,3615,3616],{"class":874},"Mercredi :",[143,3618,3475],{"class":855},[143,3620,3621],{"class":874},"Température : 82°F",[143,3623,3475],{"class":855},[143,3625,3626],{"class":874},"Vent : 5 à 12 mph SO",[143,3628,3475],{"class":855},[143,3630,3537],{"class":874},[143,3632,3475],{"class":855},[143,3634,3493],{"class":874},[143,3636,3475],{"class":855},[143,3638,3639],{"class":874},"Mercredi Soir :",[143,3641,3475],{"class":855},[143,3643,3644],{"class":874},"Température : 69°F",[143,3646,3475],{"class":855},[143,3648,3649],{"class":874},"Vent : 8 à 12 mph SO",[143,3651,3475],{"class":855},[143,3653,3561],{"class":874},[143,3655,3475],{"class":855},[143,3657,3493],{"class":874},[143,3659,3475],{"class":855},[143,3661,3662],{"class":874},"Jeudi :",[143,3664,3475],{"class":855},[143,3666,3667],{"class":874},"Température : 85°F",[143,3669,3475],{"class":855},[143,3671,3672],{"class":874},"Vent : 7 à 12 mph SO",[143,3674,3475],{"class":855},[143,3676,3488],{"class":874},[143,3678,3475],{"class":855},[143,3680,3493],{"class":874},[143,3682,3475],{"class":855},[143,3684,3685],{"class":874},"Jeudi Soir :",[143,3687,3475],{"class":855},[143,3689,3690],{"class":874},"Température : 72°F",[143,3692,3475],{"class":855},[143,3694,3672],{"class":874},[143,3696,3475],{"class":855},[143,3698,3513],{"class":874},[143,3700,3475],{"class":855},[143,3702,3493],{"class":874},[143,3704,3475],{"class":855},[143,3706,3707],{"class":874},"Vendredi :",[143,3709,3475],{"class":855},[143,3711,3621],{"class":874},[143,3713,3475],{"class":855},[143,3715,3672],{"class":874},[143,3717,3475],{"class":855},[143,3719,3720],{"class":874},"Possibilité d'Averses",[143,3722,3475],{"class":855},[143,3724,3493],{"class":874},[143,3726,3475],{"class":855},[143,3728,3729],{"class":874},"Vendredi Soir :",[143,3731,3475],{"class":855},[143,3733,3734],{"class":874},"Température : 70°F",[143,3736,3475],{"class":855},[143,3738,3672],{"class":874},[143,3740,3475],{"class":855},[143,3742,3720],{"class":874},[143,3744,3475],{"class":855},[143,3746,3493],{"class":874},[143,3748,3475],{"class":855},[143,3750,3751],{"class":874},"Samedi :",[143,3753,3475],{"class":855},[143,3755,3756],{"class":874},"Température : 76°F",[143,3758,3475],{"class":855},[143,3760,3761],{"class":874},"Vent : 9 mph O",[143,3763,3475],{"class":855},[143,3765,3720],{"class":874},[143,3767,3475],{"class":855},[143,3769,3493],{"class":874},[143,3771,3475],{"class":855},[143,3773,3774],{"class":874},"Samedi Soir :",[143,3776,3475],{"class":855},[143,3778,3779],{"class":874},"Température : 67°F",[143,3781,3475],{"class":855},[143,3783,3784],{"class":874},"Vent : 6 à 9 mph NO",[143,3786,3475],{"class":855},[143,3788,3720],{"class":874},[143,3790,3475],{"class":855},[143,3792,3493],{"class":874},[143,3794,1887],{"class":851},[143,3796,859],{"class":851},[143,3798,1930],{"class":851},[143,3800,3801],{"class":886},"uuid",[143,3803,1887],{"class":851},[143,3805,920],{"class":851},[143,3807,1930],{"class":851},[143,3809,3810],{"class":874},"fb196843-938b-4a75-b1a5-b660892f9817",[143,3812,1887],{"class":851},[143,3814,3815],{"class":851},"}]\n",[76,3817,3819,3822,3825],{"className":3818},[79],[68,3820,3821],{},"Ici vous pouvez voir une réponse de l'API get-weather d'un serveur MCP !",[68,3823,3824],{},"Commencez par créer l'échafaudage du serveur. Cela établit la fondation pour notre serveur MCP en utilisant FastMCP, qui simplifie la création et la gestion de serveurs.",[68,3826,3827],{},"FastMCP fournit une interface simplifiée pour définir les outils, ressources et prompts. En tirant parti de ses fonctionnalités intégrées, vous pouvez vous concentrer sur l'implémentation de la fonctionnalité sans vous soucier des détails de serveur de bas niveau.",[133,3829,3833],{"className":3830,"code":3831,"language":3832,"meta":138,"style":138},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from typing import Any\nimport httpx\nfrom mcp.server.fastmcp import FastMCP\n\n# Initialiser le serveur FastMCP\nmcp = FastMCP(\"weather\")\n\n# Constantes\nOPENMETEO_API_BASE = \"https://api.open-meteo.com/v1\"\nUSER_AGENT = \"weather-app/1.0\"\n\n# Fonction d'aide pour les requêtes API\nasync def make_openmeteo_request(url: str) -> dict[str, Any] | None:\n    \"\"\"Effectuer une requête vers l'API Open-Meteo avec gestion d'erreur appropriée.\"\"\"\n    headers = {\n        \"User-Agent\": USER_AGENT,\n        \"Accept\": \"application/json\"\n    }\n    async with httpx.AsyncClient() as client:\n        try:\n            response = await client.get(url, headers=headers, timeout=30.0)\n            response.raise_for_status()\n            return response.json()\n        except Exception:\n            return None\n\nif __name__ == \"__main__\":\n    mcp.run(transport='stdio')\n","python",[140,3834,3835,3840,3845,3850,3854,3859,3864,3868,3873,3878,3883,3887,3892,3897,3902,3907,3912,3917,3921,3926,3931,3936,3941,3946,3951,3956,3960,3965],{"__ignoreMap":138},[143,3836,3837],{"class":145,"line":146},[143,3838,3839],{},"from typing import Any\n",[143,3841,3842],{"class":145,"line":152},[143,3843,3844],{},"import httpx\n",[143,3846,3847],{"class":145,"line":158},[143,3848,3849],{},"from mcp.server.fastmcp import FastMCP\n",[143,3851,3852],{"class":145,"line":164},[143,3853,168],{"emptyLinePlaceholder":167},[143,3855,3856],{"class":145,"line":171},[143,3857,3858],{},"# Initialiser le serveur FastMCP\n",[143,3860,3861],{"class":145,"line":177},[143,3862,3863],{},"mcp = FastMCP(\"weather\")\n",[143,3865,3866],{"class":145,"line":183},[143,3867,168],{"emptyLinePlaceholder":167},[143,3869,3870],{"class":145,"line":189},[143,3871,3872],{},"# Constantes\n",[143,3874,3875],{"class":145,"line":194},[143,3876,3877],{},"OPENMETEO_API_BASE = \"https://api.open-meteo.com/v1\"\n",[143,3879,3880],{"class":145,"line":200},[143,3881,3882],{},"USER_AGENT = \"weather-app/1.0\"\n",[143,3884,3885],{"class":145,"line":206},[143,3886,168],{"emptyLinePlaceholder":167},[143,3888,3889],{"class":145,"line":1349},[143,3890,3891],{},"# Fonction d'aide pour les requêtes API\n",[143,3893,3894],{"class":145,"line":1355},[143,3895,3896],{},"async def make_openmeteo_request(url: str) -> dict[str, Any] | None:\n",[143,3898,3899],{"class":145,"line":1360},[143,3900,3901],{},"    \"\"\"Effectuer une requête vers l'API Open-Meteo avec gestion d'erreur appropriée.\"\"\"\n",[143,3903,3904],{"class":145,"line":1366},[143,3905,3906],{},"    headers = {\n",[143,3908,3909],{"class":145,"line":1372},[143,3910,3911],{},"        \"User-Agent\": USER_AGENT,\n",[143,3913,3914],{"class":145,"line":1377},[143,3915,3916],{},"        \"Accept\": \"application/json\"\n",[143,3918,3919],{"class":145,"line":1383},[143,3920,1745],{},[143,3922,3923],{"class":145,"line":1388},[143,3924,3925],{},"    async with httpx.AsyncClient() as client:\n",[143,3927,3928],{"class":145,"line":1394},[143,3929,3930],{},"        try:\n",[143,3932,3933],{"class":145,"line":1400},[143,3934,3935],{},"            response = await client.get(url, headers=headers, timeout=30.0)\n",[143,3937,3938],{"class":145,"line":1405},[143,3939,3940],{},"            response.raise_for_status()\n",[143,3942,3943],{"class":145,"line":1411},[143,3944,3945],{},"            return response.json()\n",[143,3947,3948],{"class":145,"line":1417},[143,3949,3950],{},"        except Exception:\n",[143,3952,3953],{"class":145,"line":1878},[143,3954,3955],{},"            return None\n",[143,3957,3958],{"class":145,"line":1907},[143,3959,168],{"emptyLinePlaceholder":167},[143,3961,3962],{"class":145,"line":1951},[143,3963,3964],{},"if __name__ == \"__main__\":\n",[143,3966,3967],{"class":145,"line":1976},[143,3968,3969],{},"    mcp.run(transport='stdio')\n",[76,3971,3973,3979],{"className":3972},[103,104,105],[107,3974,3976],{"id":3975},"création-des-outils-météorologiques",[84,3977,3978],{},"Création des Outils Météorologiques",[68,3980,3981],{},[71,3982,3983],{"href":117},[84,3984,120],{},[76,3986,3988],{"className":3987},[79],[68,3989,3990],{},"Les outils sont le cœur des serveurs MCP. Ils exposent des fonctionnalités exécutables que les modèles de langage peuvent invoquer. Notre outil météorologique récupérera les conditions actuelles et les prévisions basées sur les coordonnées géographiques.",[133,3992,3994],{"className":3830,"code":3993,"language":3832,"meta":138,"style":138},"@mcp.tool()\nasync def get_current_weather(latitude: float, longitude: float) -> str:\n    \"\"\"Obtenir la météo actuelle pour un emplacement.\n\n    Args:\n        latitude: Latitude de l'emplacement\n        longitude: Longitude de l'emplacement\n    \"\"\"\n    \n    url = f\"{OPENMETEO_API_BASE}/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m,is_day,showers,cloud_cover,wind_speed_10m,wind_direction_10m,pressure_msl,snowfall,precipitation,relative_humidity_2m,apparent_temperature,rain,weather_code,surface_pressure,wind_gusts_10m\"\n    \n    data = await make_openmeteo_request(url)\n\n    if not data:\n        return \"Impossible de récupérer les données météorologiques actuelles pour cet emplacement.\"\n\n    return data\n\n@mcp.tool()\nasync def get_forecast(latitude: float, longitude: float, days: int = 7) -> str:\n    \"\"\"Obtenir les prévisions météorologiques pour un emplacement.\n\n    Args:\n        latitude: Latitude de l'emplacement\n        longitude: Longitude de l'emplacement  \n        days: Nombre de jours à prévoir (1-16)\n    \"\"\"\n    \n    url = f\"{OPENMETEO_API_BASE}/forecast?latitude={latitude}&longitude={longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,weather_code&forecast_days={days}\"\n    \n    data = await make_openmeteo_request(url)\n    \n    if not data:\n        return \"Impossible de récupérer les données de prévision pour cet emplacement.\"\n    \n    return data\n",[140,3995,3996,4001,4006,4011,4015,4020,4025,4030,4035,4039,4044,4048,4053,4057,4062,4067,4071,4076,4080,4084,4089,4094,4098,4102,4106,4111,4116,4120,4124,4129,4133,4137,4141,4145,4150,4154],{"__ignoreMap":138},[143,3997,3998],{"class":145,"line":146},[143,3999,4000],{},"@mcp.tool()\n",[143,4002,4003],{"class":145,"line":152},[143,4004,4005],{},"async def get_current_weather(latitude: float, longitude: float) -> str:\n",[143,4007,4008],{"class":145,"line":158},[143,4009,4010],{},"    \"\"\"Obtenir la météo actuelle pour un emplacement.\n",[143,4012,4013],{"class":145,"line":164},[143,4014,168],{"emptyLinePlaceholder":167},[143,4016,4017],{"class":145,"line":171},[143,4018,4019],{},"    Args:\n",[143,4021,4022],{"class":145,"line":177},[143,4023,4024],{},"        latitude: Latitude de l'emplacement\n",[143,4026,4027],{"class":145,"line":183},[143,4028,4029],{},"        longitude: Longitude de l'emplacement\n",[143,4031,4032],{"class":145,"line":189},[143,4033,4034],{},"    \"\"\"\n",[143,4036,4037],{"class":145,"line":194},[143,4038,1699],{},[143,4040,4041],{"class":145,"line":200},[143,4042,4043],{},"    url = f\"{OPENMETEO_API_BASE}/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m,is_day,showers,cloud_cover,wind_speed_10m,wind_direction_10m,pressure_msl,snowfall,precipitation,relative_humidity_2m,apparent_temperature,rain,weather_code,surface_pressure,wind_gusts_10m\"\n",[143,4045,4046],{"class":145,"line":206},[143,4047,1699],{},[143,4049,4050],{"class":145,"line":1349},[143,4051,4052],{},"    data = await make_openmeteo_request(url)\n",[143,4054,4055],{"class":145,"line":1355},[143,4056,168],{"emptyLinePlaceholder":167},[143,4058,4059],{"class":145,"line":1360},[143,4060,4061],{},"    if not data:\n",[143,4063,4064],{"class":145,"line":1366},[143,4065,4066],{},"        return \"Impossible de récupérer les données météorologiques actuelles pour cet emplacement.\"\n",[143,4068,4069],{"class":145,"line":1372},[143,4070,168],{"emptyLinePlaceholder":167},[143,4072,4073],{"class":145,"line":1377},[143,4074,4075],{},"    return data\n",[143,4077,4078],{"class":145,"line":1383},[143,4079,168],{"emptyLinePlaceholder":167},[143,4081,4082],{"class":145,"line":1388},[143,4083,4000],{},[143,4085,4086],{"class":145,"line":1394},[143,4087,4088],{},"async def get_forecast(latitude: float, longitude: float, days: int = 7) -> str:\n",[143,4090,4091],{"class":145,"line":1400},[143,4092,4093],{},"    \"\"\"Obtenir les prévisions météorologiques pour un emplacement.\n",[143,4095,4096],{"class":145,"line":1405},[143,4097,168],{"emptyLinePlaceholder":167},[143,4099,4100],{"class":145,"line":1411},[143,4101,4019],{},[143,4103,4104],{"class":145,"line":1417},[143,4105,4024],{},[143,4107,4108],{"class":145,"line":1878},[143,4109,4110],{},"        longitude: Longitude de l'emplacement  \n",[143,4112,4113],{"class":145,"line":1907},[143,4114,4115],{},"        days: Nombre de jours à prévoir (1-16)\n",[143,4117,4118],{"class":145,"line":1951},[143,4119,4034],{},[143,4121,4122],{"class":145,"line":1976},[143,4123,1699],{},[143,4125,4126],{"class":145,"line":1996},[143,4127,4128],{},"    url = f\"{OPENMETEO_API_BASE}/forecast?latitude={latitude}&longitude={longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,weather_code&forecast_days={days}\"\n",[143,4130,4131],{"class":145,"line":2002},[143,4132,1699],{},[143,4134,4135],{"class":145,"line":2007},[143,4136,4052],{},[143,4138,4139],{"class":145,"line":2012},[143,4140,1699],{},[143,4142,4143],{"class":145,"line":2018},[143,4144,4061],{},[143,4146,4147],{"class":145,"line":2040},[143,4148,4149],{},"        return \"Impossible de récupérer les données de prévision pour cet emplacement.\"\n",[143,4151,4152],{"class":145,"line":2059},[143,4153,1699],{},[143,4155,4156],{"class":145,"line":2086},[143,4157,4075],{},[76,4159,4161,4167],{"className":4160},[103,104,105],[107,4162,4164],{"id":4163},"test-de-votre-serveur-mcp",[84,4165,4166],{},"Test de Votre Serveur MCP",[68,4168,4169],{},[71,4170,4171],{"href":117},[84,4172,120],{},[76,4174,4176,4185],{"className":4175},[1439,1440,1441,1442,1443,1444],[76,4177,4178],{},[68,4179,4180],{},[3211,4181],{"alt":4182,"className":4183,"height":3216,"src":4184,"style":3218},"Interface MCP Inspector",[3215],"/blog/mcp/mcp-inspector.png",[76,4186,4188],{"className":4187},[79],[68,4189,4190],{},"Le MCP Inspector fournit une interface web pour tester votre serveur avant de l'intégrer avec les modèles de langage. Cet outil est inestimable pour le débogage et la validation.",[133,4192,4194],{"className":3315,"code":4193,"language":3317,"meta":138,"style":138},"# Démarrer le serveur MCP en mode développement\nmcp dev server.py\n\n# Ouvrir le navigateur sur http://localhost:5173\n# Se connecter au serveur\n# Naviguer vers l'onglet Outils\n# Tester get_current_weather avec des coordonnées\n# Exemple : latitude=63.4463991, longitude=10.8127596\n",[140,4195,4196,4201,4212,4216,4221,4226,4231,4236],{"__ignoreMap":138},[143,4197,4198],{"class":145,"line":146},[143,4199,4200],{"class":1018},"# Démarrer le serveur MCP en mode développement\n",[143,4202,4203,4206,4209],{"class":145,"line":152},[143,4204,4205],{"class":1623},"mcp",[143,4207,4208],{"class":874}," dev",[143,4210,4211],{"class":874}," server.py\n",[143,4213,4214],{"class":145,"line":158},[143,4215,168],{"emptyLinePlaceholder":167},[143,4217,4218],{"class":145,"line":164},[143,4219,4220],{"class":1018},"# Ouvrir le navigateur sur http://localhost:5173\n",[143,4222,4223],{"class":145,"line":171},[143,4224,4225],{"class":1018},"# Se connecter au serveur\n",[143,4227,4228],{"class":145,"line":177},[143,4229,4230],{"class":1018},"# Naviguer vers l'onglet Outils\n",[143,4232,4233],{"class":145,"line":183},[143,4234,4235],{"class":1018},"# Tester get_current_weather avec des coordonnées\n",[143,4237,4238],{"class":145,"line":189},[143,4239,4240],{"class":1018},"# Exemple : latitude=63.4463991, longitude=10.8127596\n",[76,4242,4244,4250],{"className":4243},[103,104,105],[107,4245,4247],{"id":4246},"principes-de-conception-clés",[84,4248,4249],{},"Principes de Conception Clés",[68,4251,4252],{},[71,4253,4254],{"href":117},[84,4255,120],{},[76,4257,4259,4262,4267],{"className":4258},[79],[68,4260,4261],{},"Lors de la construction de serveurs MCP, résistez à la tentation de formater les données retournées dans vos outils. Au lieu de cela, retournez les données brutes et laissez le modèle de langage les traiter et les formater de manière appropriée. Cette approche tire parti des capacités de langage naturel du LLM tout en maintenant l'intégrité des données.",[68,4263,4264],{},[84,4265,4266],{},"Meilleures Pratiques :",[672,4268,4269,4272,4275,4278,4281],{},[675,4270,4271],{},"Retourner des jeux de données complets plutôt que des résumés filtrés",[675,4273,4274],{},"Utiliser des noms d'outils descriptifs et de la documentation",[675,4276,4277],{},"Implémenter une gestion d'erreur appropriée pour les échecs d'API",[675,4279,4280],{},"Garder les outils focalisés sur des responsabilités uniques",[675,4282,4283],{},"Tirer parti d'async/await pour de meilleures performances",[76,4285,4287,4293],{"className":4286},[103,104,105],[107,4288,4290],{"id":4289},"extension-de-votre-serveur",[84,4291,4292],{},"Extension de Votre Serveur",[68,4294,4295],{},[71,4296,4297],{"href":117},[84,4298,120],{},[76,4300,4302,4305,4311,4317,4323],{"className":4301},[79],[68,4303,4304],{},"Une fois que vous avez un serveur météorologique de base fonctionnel, considérez l'ajout de ces améliorations :",[68,4306,4307,4310],{},[84,4308,4309],{},"Services de Localisation :"," Intégrer l'API de Géocodage Open-Meteo pour convertir les noms de villes en coordonnées, réduisant la dépendance au LLM pour la génération de coordonnées.",[68,4312,4313,4316],{},[84,4314,4315],{},"Données Historiques :"," Ajouter des outils pour accéder aux modèles météorologiques historiques et aux données climatiques.",[68,4318,4319,4322],{},[84,4320,4321],{},"Alertes et Avertissements :"," Implémenter la surveillance d'alertes météorologiques pour les conditions météorologiques sévères.",[68,4324,4325,4328],{},[84,4326,4327],{},"Emplacements Multiples :"," Supporter les requêtes par lot pour comparer la météo à travers plusieurs emplacements.",[133,4330,4332],{"className":3830,"code":4331,"language":3832,"meta":138,"style":138},"@mcp.tool()\nasync def get_location(city: str, country: str = \"\") -> str:\n    \"\"\"Obtenir les coordonnées d'une ville en utilisant le géocodage.\n    \n    Args:\n        city: Nom de la ville\n        country: Nom du pays optionnel pour désambiguïsation\n    \"\"\"\n    \n    query = f\"{city},{country}\" if country else city\n    url = f\"https://geocoding-api.open-meteo.com/v1/search?name={query}&count=1&language=fr&format=json\"\n    \n    data = await make_openmeteo_request(url)\n    \n    if not data or not data.get('results'):\n        return \"Emplacement non trouvé.\"\n    \n    return data['results'][0]\n",[140,4333,4334,4338,4343,4348,4352,4356,4361,4366,4370,4374,4379,4384,4388,4392,4396,4401,4406,4410],{"__ignoreMap":138},[143,4335,4336],{"class":145,"line":146},[143,4337,4000],{},[143,4339,4340],{"class":145,"line":152},[143,4341,4342],{},"async def get_location(city: str, country: str = \"\") -> str:\n",[143,4344,4345],{"class":145,"line":158},[143,4346,4347],{},"    \"\"\"Obtenir les coordonnées d'une ville en utilisant le géocodage.\n",[143,4349,4350],{"class":145,"line":164},[143,4351,1699],{},[143,4353,4354],{"class":145,"line":171},[143,4355,4019],{},[143,4357,4358],{"class":145,"line":177},[143,4359,4360],{},"        city: Nom de la ville\n",[143,4362,4363],{"class":145,"line":183},[143,4364,4365],{},"        country: Nom du pays optionnel pour désambiguïsation\n",[143,4367,4368],{"class":145,"line":189},[143,4369,4034],{},[143,4371,4372],{"class":145,"line":194},[143,4373,1699],{},[143,4375,4376],{"class":145,"line":200},[143,4377,4378],{},"    query = f\"{city},{country}\" if country else city\n",[143,4380,4381],{"class":145,"line":206},[143,4382,4383],{},"    url = f\"https://geocoding-api.open-meteo.com/v1/search?name={query}&count=1&language=fr&format=json\"\n",[143,4385,4386],{"class":145,"line":1349},[143,4387,1699],{},[143,4389,4390],{"class":145,"line":1355},[143,4391,4052],{},[143,4393,4394],{"class":145,"line":1360},[143,4395,1699],{},[143,4397,4398],{"class":145,"line":1366},[143,4399,4400],{},"    if not data or not data.get('results'):\n",[143,4402,4403],{"class":145,"line":1372},[143,4404,4405],{},"        return \"Emplacement non trouvé.\"\n",[143,4407,4408],{"class":145,"line":1377},[143,4409,1699],{},[143,4411,4412],{"class":145,"line":1383},[143,4413,4414],{},"    return data['results'][0]\n",[76,4416,4418,4424],{"className":4417},[103,104,105],[107,4419,4421],{"id":4420},"intégration-avec-les-modèles-de-langage",[84,4422,4423],{},"Intégration avec les Modèles de Langage",[68,4425,4426],{},[71,4427,4428],{"href":117},[84,4429,120],{},[76,4431,4433],{"className":4432},[79],[68,4434,4435],{},"Votre serveur MCP peut s'intégrer avec divers modèles de langage incluant Claude Desktop, GPT-4 à travers des clients compatibles, et d'autres applications compatibles MCP. Le serveur communique à travers l'entrée/sortie standard (stdio), le rendant universellement compatible.",[68,4437,4438,4439,4442],{},"Pour utiliser avec Claude Desktop, ajoutez votre configuration de serveur au fichier de paramètres MCP, typiquement situé à ",[140,4440,4441],{},"~/Library/Application Support/Claude/claude_desktop_config.json"," sur macOS.",[133,4444,4446],{"className":2703,"code":4445,"language":2705,"meta":138,"style":138},"{\n  \"mcpServers\": {\n    \"weather\": {\n      \"command\": \"uv\",\n      \"args\": [\"run\", \"python\", \"server.py\"],\n      \"cwd\": \"/chemin/vers/votre/mcp-server-weather\"\n    }\n  }\n}\n",[140,4447,4448,4452,4465,4478,4497,4536,4554,4558,4562],{"__ignoreMap":138},[143,4449,4450],{"class":145,"line":146},[143,4451,1724],{"class":851},[143,4453,4454,4456,4459,4461,4463],{"class":145,"line":152},[143,4455,2721],{"class":851},[143,4457,4458],{"class":886},"mcpServers",[143,4460,1887],{"class":851},[143,4462,920],{"class":851},[143,4464,1627],{"class":851},[143,4466,4467,4469,4472,4474,4476],{"class":145,"line":158},[143,4468,2735],{"class":851},[143,4470,4471],{"class":1623},"weather",[143,4473,1887],{"class":851},[143,4475,920],{"class":851},[143,4477,1627],{"class":851},[143,4479,4480,4482,4485,4487,4489,4491,4493,4495],{"class":145,"line":164},[143,4481,1881],{"class":851},[143,4483,4484],{"class":2053},"command",[143,4486,1887],{"class":851},[143,4488,920],{"class":851},[143,4490,1930],{"class":851},[143,4492,3311],{"class":874},[143,4494,1887],{"class":851},[143,4496,1796],{"class":851},[143,4498,4499,4501,4504,4506,4508,4510,4512,4515,4517,4519,4521,4523,4525,4527,4529,4532,4534],{"class":145,"line":171},[143,4500,1881],{"class":851},[143,4502,4503],{"class":2053},"args",[143,4505,1887],{"class":851},[143,4507,920],{"class":851},[143,4509,1892],{"class":851},[143,4511,1887],{"class":851},[143,4513,4514],{"class":874},"run",[143,4516,1887],{"class":851},[143,4518,859],{"class":851},[143,4520,1930],{"class":851},[143,4522,3832],{"class":874},[143,4524,1887],{"class":851},[143,4526,859],{"class":851},[143,4528,1930],{"class":851},[143,4530,4531],{"class":874},"server.py",[143,4533,1887],{"class":851},[143,4535,2798],{"class":851},[143,4537,4538,4540,4543,4545,4547,4549,4552],{"class":145,"line":177},[143,4539,1881],{"class":851},[143,4541,4542],{"class":2053},"cwd",[143,4544,1887],{"class":851},[143,4546,920],{"class":851},[143,4548,1930],{"class":851},[143,4550,4551],{"class":874},"/chemin/vers/votre/mcp-server-weather",[143,4553,1993],{"class":851},[143,4555,4556],{"class":145,"line":183},[143,4557,1745],{"class":851},[143,4559,4560],{"class":145,"line":189},[143,4561,1848],{"class":851},[143,4563,4564],{"class":145,"line":194},[143,4565,2156],{"class":851},[76,4567,4569,4573],{"className":4568},[103,104,105],[107,4570,4571],{"id":3001},[84,4572,3004],{},[68,4574,4575],{},[71,4576,4577],{"href":117},[84,4578,120],{},[76,4580,4582,4585],{"className":4581},[79],[68,4583,4584],{},"La construction de serveurs MCP ouvre de nouvelles possibilités pour l'intégration de l'IA avec les sources de données du monde réel. Ce serveur météorologique démontre les concepts fondamentaux qui s'appliquent à toute intégration d'API externe ou de service. Le Model Context Protocol représente un pas significatif vers des systèmes d'IA plus capables et connectés.",[68,4586,4587],{},"Le code source complet pour ce tutoriel est disponible dans le dépôt des fichiers d'exercice. Expérimentez avec différentes APIs, ajoutez de nouveaux outils, et explorez les possibilités infinies du développement de serveurs MCP.",[76,4589,4592],{"className":4590},[103,4591,105],"justify-end",[68,4593,4594],{},[71,4595,4597],{"href":57,"rel":4596},[1122],"#OuverteAuxCollaborationsFreelance",[76,4599,4601],{"className":4600},[1056,1057,1058,1059],[68,4602,4603],{},[71,4604,4605],{"href":117},[84,4606,120],{},[1067,4608,4609],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":138,"searchDepth":152,"depth":152,"links":4611},[4612,4613,4614,4615,4616,4617,4618,4619,4620,4621],{"id":3193,"depth":152,"text":3196},{"id":3255,"depth":152,"text":3258},{"id":3293,"depth":152,"text":3296},{"id":3411,"depth":152,"text":3414},{"id":3975,"depth":152,"text":3978},{"id":4163,"depth":152,"text":4166},{"id":4246,"depth":152,"text":4249},{"id":4289,"depth":152,"text":4292},{"id":4420,"depth":152,"text":4423},{"id":3001,"depth":152,"text":3004},"2025-06-01","Apprenez à créer un serveur Model Context Protocol (MCP) en utilisant Python et l'API Open-Meteo pour fournir des données météorologiques aux modèles de langage comme GPT-4 et Claude.",{"src":1087},{},{"title":23,"description":4623},"F458zeQnEhe_o8Ydhx3dx9iGkSe4WoRy7kzhh_eDBGE",1779118049817]