Aperçu

Sécurité du serveur MCP

Cette page s’adresse à la personne qui doit approuver la connexion d’un agent IA à Docsbook. Elle décrit ce que fait réellement le serveur MCP aujourd’hui — comment un client s’authentifie, ce que chaque portée peut atteindre, ce qui est consigné, ce qui quitte le réseau — puis indique, dans deux sections distinctes, les points sur lesquels Docsbook ne respecte pas la spécification du Model Context Protocol et les artefacts de conformité qui n’existent pas encore.

Rien de ce qui est présenté ici n’est prospectif. Lorsqu’un contrôle est absent, il est indiqué comme tel.

Ce que vous obtenez#

Un client connecté détient un jeton Bearer opaque, lié à un compte Docsbook, et portant l’une de deux portées. La portée est choisie par une personne sur un écran de consentement — elle n’est pas demandée par le client. Chaque outil qui agit sur un projet détermine ce projet par son propriétaire ; ainsi, un jeton qui désigne l’identifiant d’un espace de travail appartenant à quelqu’un d’autre ne renvoie rien, et non cet espace : c’est la limite entre les locataires, et elle s’applique à tous les outils.

La limite entre la lecture et l’écriture est plus étroite que ne le suggèrent les deux noms de portée, et la section ci-dessous indique précisément quels outils l’appliquent et lesquels ne l’appliquent pas. Lisez-la avant de considérer un jeton en lecture seule comme une mesure de confinement.

Chaque appel comptabilisé ajoute une ligne au journal d’appels de votre propre projet : quel outil a été utilisé, ce qui a été envoyé, ce qui a été renvoyé, le temps pris et ce qu’il a consommé. Les arguments et les résultats sont expurgés par clé avant leur stockage, de sorte qu’une clé API transmise à un outil n’est jamais enregistrée.

Ce que vous n’obtenez pas : l’expiration des jetons, des jetons d’actualisation, la limitation du débit, des rôles au sein d’un compte ou un rapport d’audit.

Fonctionnement de l’authentification#

Le flux d’autorisation#

Docsbook est son propre serveur d’autorisation et son propre serveur de ressources. Il émet des jetons opaques pour lui-même ; il n’accepte, ne transmet et ne réutilise jamais un jeton émis par un tiers.

Étape Ce qui se passe
Découverte Une requête non authentifiée vers le point de terminaison du serveur renvoie 401 avec WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource". Ce document désigne la ressource et son serveur d’autorisation ; /.well-known/oauth-authorization-server contient les points de terminaison au format RFC 8414.
Enregistrement du client Un POST vers le point de terminaison d’enregistrement renvoie un nouveau client_id au format RFC 7591. Les clients ne sont pas persistés — l’identifiant est généré sans état, et le point de terminaison d’autorisation accepte tout client_id.
Autorisation Le client envoie response_type=code, un redirect_uri, un state d’au moins 8 caractères et, normalement, un code_challenge PKCE. Les paramètres sont associés à state et le navigateur est redirigé vers une page de consentement. La ligne expire après 10 minutes.
Consentement La page de consentement exige un compte Docsbook connecté et un clic explicite. Elle comporte une case à cocher — Autoriser la modification de la documentation — qui détermine la portée. Il n’existe ni cookie « mémoriser ce client » ni possibilité de réapprobation silencieuse : chaque autorisation affiche l’écran.
Échange du jeton Le code est échangé contre un jeton Bearer au point de terminaison des jetons. Lorsque le client a fourni un défi PKCE avec la méthode S256, le vérificateur est contrôlé et toute discordance est refusée. Le code n’est utilisable qu’une seule fois : il est effacé lors du premier échange réussi.

Les métadonnées publiées déclarent un modèle de client public — code_challenge_methods_supported: ["S256"], token_endpoint_auth_methods_supported: ["none"], grant_types_supported: ["authorization_code"]. Il n’existe ni secret client ni octroi d’identifiants client.

Ce qu’est le jeton#

Le jeton est constitué de 48 octets générés par le CSPRNG de la plateforme, représentés par 96 caractères hexadécimaux. Il ne contient aucune revendication : c’est une clé de recherche vers une ligne contenant le compte, la portée et un horodatage de révocation.

  • Il n’expire pas. Aucun expires_in n’est renvoyé et aucun jeton d’actualisation n’est émis. Un jeton est valide jusqu’à sa révocation.
  • La révocation est immédiate. La révocation depuis le panneau horodate la ligne, et chaque appel ultérieur échoue lors de la recherche — aucun cache ne se trouve devant celle-ci.
  • Il est stocké tel qu’il a été émis, et non haché. Traitez un jeton MCP Docsbook comme vous traiteriez un mot de passe : si la machine qui le détient est compromise, révoquez-le plutôt que de supposer qu’il a expiré avec le temps. (Ce qui est chiffré au repos est indiqué dans la section ce qui quitte votre espace de travail.)
  • La dernière utilisation est enregistrée à chaque appel, de sorte qu’un jeton inutilisé reste visible dans la liste des jetons du panneau.

Ce que chaque portée permet de faire#

La portée est une chaîne unique comparée à l’identique. Toute valeur qui n’est pas la portée d’écriture est traitée comme étant en lecture seule — une valeur non reconnue est refusée par défaut.

Appelant Ce qui est renvoyé
Aucun jeton, endpoint sans portée Rien. 401 avec l’en-tête de découverte.
Aucun jeton, endpoint limité au dépôt (/{owner}/{repo}/api/mcp/server) Cinq outils : get_info, find_skill, find_widget, list_content_widgets et search sur ce seul site publié. Jamais soumis à un quota, jamais facturés à qui que ce soit.
Jeton en lecture seule Tous les outils de rapports, de recherche, de plan, d’analyse et d’historique des appels, plus list_memoryet, aujourd’hui, les outils d’écriture des paramètres répertoriés ci-dessous
Jeton en lecture-écriture Tout ce que le compte peut faire

La vérification de la portée ne couvre pas encore tous les outils d’écriture, et vous devez en tenir compte dans votre planification. Elle est appliquée exactement à quatre outils : write_docs, create_issue, connect_source et configure_source. Ceux-ci refusent un jeton en lecture seule avant toute action.

Tout autre outil qui modifie l’état — les outils d’écriture des paramètres update_* et set_*, update_access, l’enregistrement et la suppression de webhooks, la création d’objectifs et d’entonnoirs, l’importation, l’approbation et la suppression de traductions, create_workspace — est limité uniquement par la propriété du projet, et non par la portée. Un jeton en lecture seule peut donc modifier les paramètres d’un projet, activer un webhook ou supprimer une traduction sur un projet dont le compte est propriétaire. Il ne peut toutefois pas valider une page, créer un ticket, connecter une source ou activer un agent.

Considérez la portée en lecture seule comme signifiant « ne peut pas publier ni mettre en place de nouvelles fonctionnalités », et non comme « ne peut rien modifier ». Si le cloisonnement est plus important, utilisez un compte Docsbook distinct qui n’est propriétaire que du projet que vous acceptez d’exposer. Il s’agit d’un défaut, répertorié à nouveau sous limites, et non d’un choix de conception.

Un outil qui applique effectivement cette vérification répond à un jeton en lecture seule par une erreur structurée READ_ONLY_TOKEN indiquant le nom de l’outil et la manière de s’authentifier à nouveau — et non par un simple 403, ni par une absence de réponse silencieuse. La même structure s’applique lorsque le solde d’un projet est épuisé (INSUFFICIENT_BALANCE, avec le nom du projet, le prix et le solde restant) et lorsqu’un forfait n’inclut pas la fonctionnalité (PLAN_RESTRICTION, avec le nom du niveau).

Le search anonyme est le seul outil sans jeton qui lit un projet, et il est refusé de trois façons : sur un endpoint associé à aucun projet, pour un projet dont la visibilité est privée (ce qui couvre également un forfait arrivé à expiration), et lorsque le projet n’a plus de solde pour payer l’intégration de la requête. Il n’accepte aucun argument de projet, et ne peut donc jamais lire que le site auquel il est associé.

Ce qu’un jeton ne peut pas atteindre#

Chaque outil détermine son espace de travail cible à partir de workspace_id explicite, de l’argument repo ou de l’ancrage propre au point de terminaison — et, dans les trois cas, la recherche est filtrée par le compte du jeton. Un espace de travail que le compte ne possède pas ne renvoie aucun résultat, et l’outil répond « espace de travail introuvable ». Le résolveur de facturation applique le même filtre : indiquer l’identifiant de projet d’un tiers ne permet donc pas non plus de débiter le solde d’un tiers.

Deux autres limites méritent d’être précisées, car elles surprennent les utilisateurs :

  • write_docs valide les modifications dans le dépôt hébergé par Docsbook avec les propres identifiants GitHub de Docsbook. Un site fourni depuis un dépôt de votre propre compte GitHub est refusé avec NO_GITHUB_ACCESS, au lieu d’y être validé. Un jeton MCP ne permet donc pas d’envoyer des modifications vers votre organisation GitHub.
  • Une compétence exécutée en mode audit ne peut pas effectuer de modification. Lorsqu’une compétence en mode audit est active, une liste explicite d’outils d’écriture ainsi que tout outil dont le nom commence par update_, set_, register_webhook_, enable_ ou disable_ sont refusés avant leur exécution. Le lanceur qui activait autrefois ce mode pour toute une exécution côté serveur a été supprimé le 12.09.2026 ; la protection s’applique donc désormais à un tour ayant préchargé une compétence audit et rien d’autre.

Qu’est-ce qui est enregistré#

Chaque appel MCP — facturé ou non, réussi ou non — écrit une ligne dans le registre des appels du projet, que le propriétaire du projet peut consulter dans le panneau Feeds.

Enregistré Non enregistré
Nom de l’outil, classe de facturation, prix, centimes effectivement débités, durée, indicateur de réussite, identifiant d’exécution en arrière-plan et auteur de la demande (agent, panneau, planification, événement) L’adresse IP de l’appelant
Les arguments de l’appel et son résultat, sérialisés, expurgés et tronqués La charge utile brute — seul le rendu expurgé et tronqué est stocké
Le compte qui a effectué l’appel et le projet concerné par l’appel Toute valeur associée à une clé contenant apikey, api_key, authorization, credential, password, passwd, secret, token, private_key, privatekey, session ou cookie

Deux détails de l’expurgation sont importants pour la vérification. Elle recherche la clé, sans tenir compte de la casse et comme une sous-chaîne, et non la forme de la valeur — deviner à quoi ressemble un secret est une approche qui lui échappe. Elle s’exécute également à la sortie comme à l’entrée, afin qu’un outil qui renvoie ses propres données d’entrée ne puisse pas divulguer une clé dans son résultat. Chaque côté est limité à 8 000 caractères, avec un marqueur indiquant le nombre de caractères supprimés.

Les analyses au niveau du lecteur ne transmettent jamais d’identité à un client MCP. Un visiteur est un pseudonyme : sha256(salt | repository | ip), tronqué à 16 caractères hexadécimaux, le sel étant conservé côté serveur. get_top_visitors, get_page_journeys et get_visitor_activity renvoient ce pseudonyme, un pays et des événements au niveau de la page ; aucun outil ne renvoie d’adresse IP, de nom ou d’adresse e-mail. Le pseudonyme est propre à un seul dépôt : le même lecteur sur deux de vos sites correspond donc à deux identifiants sans rapport.

Ce qui quitte votre espace de travail#

Données Destination Chiffré au repos
Texte, titres et en-têtes des pages Copiés dans le Postgres de Docsbook pour la recherche en texte intégral, et intégrés sous forme de vecteurs pour la recherche sémantique Non — stockés en tant que contenu
Texte des pages envoyé pour la vectorisation, le chat et le travail des agents OpenRouter, le fournisseur du modèle, avec la clé de Docsbook ou votre propre clé si vous en configurez une n/d — uniquement en transit
Événements des lecteurs Le système d’analyse de Docsbook, y compris les adresses IP brutes, qu’aucune API ne renvoie n/d
Votre secret client OIDC pour les documents privés Le Postgres de Docsbook Oui — AES-GCM, clé dérivée du secret de la plateforme
Un jeton GitHub que vous connectez pour une source de dépôt privée Le Postgres de Docsbook Oui — même procédé ; l’API indique uniquement si un jeton existe
Votre propre clé d’API de modèle (apportez votre propre clé) Le Postgres de Docsbook, et le fournisseur lors de chaque appel qu’elle finance Non — stockée telle quelle et supprimée de toutes les données d’espace de travail renvoyées par l’API
Jetons Bearer MCP Le Postgres de Docsbook Non — voir ci-dessus
Pages récupérées par fetch_url, read_source et le robot d’exploration Vers l’adresse que vous avez indiquée n/d

Deux affirmations que l’on trouve généralement sur la page de sécurité d’un fournisseur de documentation, corrigées :

  • « Votre contenu ne quitte jamais votre dépôt » n’est pas vrai ici. Docsbook stocke une copie consultable du texte de vos pages ainsi que ses représentations vectorielles, et envoie le texte des pages à un fournisseur de modèles pour créer ces représentations et répondre aux appels de chat et d’agents. Ce qui est vrai, c’est que GitHub reste la source de vérité : l’arrêt du paiement met fin au travail facturé à l’usage sans supprimer vos fichiers Markdown.
  • Les récupérations sortantes sont protégées, et pas simplement considérées comme fiables. Avant toute récupération, le schéma est vérifié, le nom d’hôte est résolu et toute adresse résolue appartenant à une plage privée ou réservée est refusée — la vérification est également réexécutée à chaque étape de redirection, de sorte qu’une URL publique ne puisse pas rediriger vers une URL interne. robots.txt est respecté et la réponse est plafonnée. Le récupérateur de compétences est encore plus limité : il ne récupère des données que depuis l’hôte et le préfixe de chemin propres au catalogue, et ne peut donc pas être transformé en proxy d’URL arbitraire.

Les webhooks et les hooks de chat ne sont pas la même chose#

Les livraisons de webhooks sortants sont signées. La signature est un HMAC-SHA256 calculé sur les octets exacts envoyés, dans X-Docsbook-Signature-256: sha256=<hex>, avec X-Docsbook-Event. Une URL de webhook entrant Discord ou Slack est adaptée à cette plateforme avant la signature, de sorte que la signature couvre toujours ce que votre endpoint reçoit effectivement. Le secret est défini lors de l'enregistrement, comporte au moins 16 caractères et n'est jamais renvoyé en clair par la suite. Les tentatives de livraison expirent au bout de 15 secondes et la réponse est enregistrée sous forme tronquée.

Les hooks de chat ne comportent aucune signature. Les hooks pré-, post- et de streaming de l'assistant de documentation sont de simples JSON POST avec un délai d'expiration de 5 secondes et sans en-tête HMAC. Ne réutilisez pas votre code de vérification des webhooks en supposant qu'il a vérifié quoi que ce soit. Le pré-hook peut également renvoyer inject_context, dont le texte est intégré au prompt de l'assistant — un endpoint vers lequel vous dirigez un hook de chat peut donc influencer ce que dit l'assistant ; traitez-le comme une infrastructure de confiance, authentifiez-le par un autre moyen et ne le dirigez pas vers une URL que vous ne contrôlez pas.

Pourquoi c’est la bonne méthode (preuves)#

Règle suivie par Docsbook Pourquoi elle est importante pour le système qui le consomme Source
Émettre nos propres jetons opaques ; ne jamais en accepter ni en transmettre un émis ailleurs « Les serveurs MCP NE DOIVENT PAS accepter de jetons qui n’ont pas été explicitement émis pour le serveur MCP » Bonnes pratiques de sécurité MCP, transmission de jetons
Répondre à un appel non authentifié avec WWW-Authenticate désignant les métadonnées de la ressource protégée « Les serveurs MCP DOIVENT implémenter les métadonnées de ressource protégée OAuth 2.0 (RFC9728) » Autorisation MCP
Vérifier le vérificateur S256 de PKCE au point de terminaison de jeton et publier code_challenge_methods_supported « Si code_challenge_methods_supported est absent, le serveur d’autorisation ne prend pas en charge PKCE et les clients MCP DOIVENT refuser de poursuivre » Considérations de sécurité relatives à l’autorisation
Afficher un écran de consentement lors de chaque autorisation au lieu de mémoriser un client L’attaque par confusion de mandataire fonctionne en accédant à un écran de consentement ignoré : « Cookie présent, consentement ignoré » Bonnes pratiques de sécurité MCP, confusion de mandataire
Limiter l’ensemble des portées à deux, choisies par une personne, plutôt qu’à un catalogue de portées demandées par un client Une mauvaise conception des portées entraîne une « augmentation de la surface d’impact : un jeton étendu volé permet un accès à des outils ou ressources sans rapport » Bonnes pratiques de sécurité MCP, minimisation des portées
Refuser une adresse IP privée ou réservée après résolution, et revérifier à chaque redirection Les clients et les serveurs DEVRAIENT bloquer « les adresses de liaison locale : 169.254.0.0/16 (y compris les points de terminaison de métadonnées cloud) » Bonnes pratiques de sécurité MCP, SSRF
Lier la cible de chaque outil à la propriété de l’appelant plutôt qu’à un identifiant qu’il a fourni Les serveurs « NE DOIVENT PAS considérer la possession d’un identifiant d’état comme une authentification » et devraient lier l’état au principal vérifié Bonnes pratiques de sécurité MCP, détournement d’identifiant d’état
Évaluer les compétences chargées par votre agent, y compris les nôtres « Les compétences qui récupèrent des données depuis des URL externes présentent un risque particulier, car le contenu récupéré peut contenir des instructions malveillantes » Anthropic, compétences d’agent

Un dernier point concerne votre client plutôt que nous : la spécification MCP demande aux clients de « considérer les annotations des outils comme non fiables, sauf si elles proviennent de serveurs de confiance », et de maintenir « un humain dans la boucle ayant la possibilité de refuser les invocations d’outils » (Outils MCP). Un jeton Docsbook en lecture-écriture est précisément le cas qui mérite cette intervention humaine.

Là où Docsbook ne respecte pas aujourd’hui la spécification MCP#

Ces éléments sont évalués par rapport à la révision 2026-07-28. Chacun constitue une lacune de Docsbook, et non un désaccord avec la spécification.

Exigence Ce que fait Docsbook Gravité pour un évaluateur
« Les serveurs d’autorisation DOIVENT valider les URI de redirection exactes par rapport aux valeurs préenregistrées » Valide le schéma du redirect_uri par rapport à une liste d’autorisation — HTTPS, loopback et une liste fixe de schémas de liens profonds d’éditeurs — et ne le compare pas à une valeur enregistrée au moment de l’échange, car les clients ne sont pas conservés Le point à soulever en premier. Associé à un écran de consentement qui n’affiche pas la cible de redirection, un utilisateur qui clique sur un lien conçu à cette fin peut approuver une autorisation qui aboutit ailleurs. L’écran exige néanmoins un clic délibéré à chaque fois ; il est impossible de l’ignorer.
« Les serveurs d’autorisation DEVRAIENT émettre des jetons d’accès à courte durée de vie » et renouveler les jetons d’actualisation pour les clients publics Émet un jeton sans expiration et sans jeton d’actualisation Un jeton divulgué reste valide jusqu’à ce que quelqu’un le révoque
Les serveurs DOIVENT « limiter le débit des invocations d’outils » N’effectue aucune limitation de débit. Le solde du projet est le seul mécanisme de limitation, et un appel de découverte non mesuré n’est soumis à aucune limitation Évaluez votre risque en argent, et non en nombre de requêtes
PKCE pour le code d’autorisation Vérifié lorsque le client fournit un défi avec la méthode S256 ; un client qui n’en fournit aucun termine néanmoins le flux Tous les clients MCP courants envoient du PKCE ; le serveur ne l’exige pas actuellement
Révision du protocole Le serveur utilise les révisions fondées sur l’initialisation prises en charge par le SDK actuel, la plus récente étant 2025-11-25, via un transport HTTP sans état Un client limité à 2026-07-28 ne se connectera pas
scope dans le défi WWW-Authenticate et scopes_supported dans les métadonnées Aucun des deux n’est publié ; la portée est sélectionnée sur l’écran de consentement Les clients ne peuvent pas découvrir les deux portées par programmation

Ce que Docsbook n’a pas encore#

Liste établie afin qu’un examen puisse écarter Docsbook en une heure plutôt qu’à la troisième semaine.

Fonctionnalité Statut
SOC 2 Type II Non proposé — aucun rapport à partager
Accord de traitement des données Non proposé — aucun DPA contresigné à ce jour
SLA contractuel Non proposé
SSO SAML pour se connecter à Docsbook Non proposé — la connexion au compte se fait via OAuth GitHub
Comptes d’équipe, rôles, RBAC Non proposé — l’accès se fait par compte, et toute personne pouvant se connecter à un compte peut effectuer toutes les actions permises par ce compte
Journal d’audit des événements du compte Non proposé — les connexions, l’émission de jetons et les changements de forfait ne sont pas exposés sous forme de journal d’événements. Les appels d’outils MCP sont journalisés intégralement, par projet ; les commits de contenu sont consultables dans l’historique des modifications
Rapport de test d’intrusion Non proposé

Une fonctionnalité est régulièrement confondue avec les deuxième et quatrième lignes : un espace de travail privé peut être protégé par un mot de passe ou par votre propre fournisseur OIDC via update_access, avec tous les forfaits. Il s’agit de l’authentification unique pour les lecteurs de votre site de documentation. Il ne s’agit pas de l’authentification unique pour les membres de votre compte Docsbook, et cela n’accorde aucun accès MCP.

Si votre organisation a besoin d’un document spécifique — un DPA conforme au RGPD, un BAA, un questionnaire rempli — écrivez à support@docsbook.io pour demander ce qui existe. La réponse aujourd’hui pourrait très bien être que cela n’existe pas.

Limites et questions en suspens#

  • Question en suspens : régions d’hébergement. Cette page ne nomme délibérément aucune région pour la base de données ou le magasin analytique. Il s’agit dans les deux cas de services gérés dont la région est un paramètre de déploiement plutôt qu’un élément qu’un lecteur peut vérifier à partir du comportement de Docsbook, et une version antérieure de cette page mentionnait des régions sans source. Demandez au support la réponse actuelle par écrit si la résidence des données fait partie de votre évaluation.
  • L’identifiant pseudonyme du visiteur est un pseudonyme, pas une anonymisation. Il s’agit d’un hachage salé d’une adresse IP tronquée à 64 bits. Toute personne détenant le sel et le magasin d’événements bruts pourrait le recalculer ; la garantie est que le sel ne se trouve pas dans les données et qu’aucune API ne renvoie d’adresse IP. La question de savoir si cela satisfait votre organisme de réglementation relève de ce dernier.
  • Un jeton en lecture-écriture est un identifiant d’administration complet. Il n’est pas possible d’autoriser « peut modifier les pages, mais ne peut pas changer les paramètres » ou « peut lire les analyses, mais pas les transcriptions de chat ». L’échelle des niveaux d’accès comporte deux échelons.
  • La portée en lecture seule est appliquée de manière incomplète. Huit outils la vérifient ; les outils d’écriture des paramètres, des webhooks, des objectifs et des traductions ne le font pas, et les descriptions de certains de ces outils affirment eux-mêmes qu’ils nécessitent un jeton en lecture-écriture alors qu’aucun contrôle ne l’effectue. Tant que ce problème n’est pas résolu, la limite fiable est la propriété du compte, et non la portée — isolez donc les usages par compte et consultez la liste effectivement contrôlée ci-dessus plutôt que la description d’un outil.
  • Rien de ce qui est présenté ici n’a fait l’objet d’une attestation indépendante. Chaque affirmation ci-dessus peut être vérifiée dans le comportement de Docsbook — émettez un jeton en lecture seule et observez un outil d’écriture le refuser ; connectez un projet dont vous n’êtes pas propriétaire et observez qu’il ne se résout pas — mais aucun tiers ne l’a audité. Considérez cette page comme une spécification que vous pouvez tester, et non comme une certification.
  • La disponibilité et le prix sont indiqués sur la page des tarifs. Aucun chiffre n’est indiqué ici, car un prix copié dans la documentation devient obsolète sans que personne ne s’en aperçoive.

Updated

Cette page vous a-t-elle été utile ?