MCP Registry : comment publier un serveur de gouvernance IA
Publier un serveur MCP prend vingt minutes. Publier un serveur de gouvernance sans mentir sur ce qu'il fait demande une étape de plus — celle que ce guide met en premier.
Le registre officiel Model Context Protocol est l'annuaire que consultent les clients MCP pour découvrir des serveurs. Y figurer, c'est être trouvable par quelqu'un qui cherche « compliance » ou « policy » sans connaître votre nom. Ne pas y figurer, c'est exister uniquement pour ceux à qui vous avez envoyé une URL.
Ce guide est la procédure telle qu'elle s'est réellement déroulée pour un serveur de gouvernance — y compris les deux endroits où elle s'est arrêtée net.
Étape 0 — Ne publiez pas avant que la promesse soit vraie
Avant de toucher au registre, quatre vérifications contre la production, pas contre votre machine. Elles prennent une minute et évitent le seul échec irréparable de cette procédure : un serveur listé qui ne tient pas sa description.
# 1. le site répond
curl -s -o /dev/null -w "%{http_code}\n" https://votre-domaine.tld/
# 2. la signature est ACTIVE — bloquant si le manifeste dit "signed evidence"
curl -s https://votre-domaine.tld/.well-known/votre-authority.json | grep -o '"status":"[a-z]*"'
# 3. l'endpoint MCP répond et liste l'outil annoncé
curl -s https://votre-domaine.tld/api/mcp-http \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# 4. le manifeste est servi en JSON (et pas une redirection)
curl -sL -o /dev/null -w "%{http_code} %{size_download}\n" \
https://votre-domaine.tld/.well-known/mcp-server.jsonÉtape 1 — Choisir l'espace de noms (décision quasi irréversible)
L'espace de noms détermine la méthode d'authentification et la lecture que le marché fait de vous. Changer après publication crée un doublon, et le nom fait partie de l'identité que les clients mémorisent.
| Espace de noms | Nom du serveur | Authentification | Lecture par le marché |
|---|---|---|---|
| Domaine | ca.exemple/mcp | DNS TXT (Ed25519) ou fichier HTTP | produit d'entreprise |
| GitHub | io.github.pseudo/serveur | mcp-publisher login github | projet personnel |
Pour un serveur de gouvernance, le domaine n'est pas un choix esthétique : la preuve de propriété du domaine est l'affirmation d'identité sur laquelle repose la confiance dans vos décisions. Un serveur qui prétend arbitrer des questions de conformité depuis un pseudonyme GitHub demande beaucoup à ses appelants.
Étape 2 — Écrire server.json
Le manifeste minimal viable pour un serveur distant. Deux contraintes attrapent presque tout le monde : le nom doit être en DNS inversé, et la description est limitée à 100 caractères.
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "ca.structureclerk/mcp",
"title": "StructureClerk",
"description": "AI agent policy decisions: ALLOW, DENY, APPROVE, ESCALATE. Signed evidence.",
"version": "2.0.0",
"websiteUrl": "https://structureclerk.ca/authority",
"remotes": [
{ "type": "streamable-http", "url": "https://structureclerk.ca/api/mcp-http" }
]
}Conseil de maintenance : gardez ce fichier dans le dépôt (par exemple sous public/.well-known/mcp-server.json), servi publiquement, et copiez-le en server.json au moment de publier. Un manifeste qui n'existe que sur le poste de celui qui a publié devient faux au premier changement d'outil, et personne ne s'en aperçoit.
Étape 3 — La partie qui bloque : la clé Ed25519
La documentation dit « prouvez la propriété du domaine par DNS ». On imagine un jeton affiché par l'outil, à coller dans la zone DNS. Ce n'est pas ça. C'est vous qui générez une paire de clés Ed25519 : la clé publique va dans l'enregistrement TXT, la clé privée est passée à l'outil en hexadécimal.
Lancer mcp-publisher login dns --domain exemple.tld sans clé donne exactement ceci, et rien d'autre :
Error: ed25519 private key (hex) is requiredLes trois commandes qui débloquent :
# 1. an Ed25519 keypair (the private key never leaves your machine)
openssl genpkey -algorithm Ed25519 -out key.pem
# 2. the PUBLIC key, base64, for the DNS record
PUBLIC_KEY="$(openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64)"
echo "v=MCPv1; k=ed25519; p=${PUBLIC_KEY}"
# 3. the PRIVATE key, hex — this is what the CLI asks for
PRIVATE_KEY="$(openssl pkey -in key.pem -noout -text | grep -A3 "priv:" | tail -n +2 | tr -d ' :\n')"- L'enregistrement TXT va sur l'apex du domaine (
exemple.tld, pas_mcp.exemple.tld), avec pour valeur exactementv=MCPv1; k=ed25519; p=<clé publique base64>. - Sur macOS,
opensslest LibreSSL par défaut et n'implémente pas Ed25519 : installez OpenSSL 3 (Homebrew) et appelez ce binaire-là. - Sur Windows,
cmd.exen'interprète ni$HOMEni$(...). Utilisez le terminal Git Bash livré avec Git for Windows — ces commandes y fonctionnent telles quelles. - La clé privée ne se met nulle part d'autre : ni dans le dépôt, ni dans le manifeste, ni dans un CI. C'est elle qui prouve que vous êtes le domaine.
Attendez la propagation DNS avant de continuer. dig TXT exemple.tld doit renvoyer votre enregistrement ; comptez 5 à 30 minutes selon le registrar. Et gardez l'enregistrement en place après coup : le registre peut revérifier.
Étape 4 — Publier
- 1
Installer l'outil
mcp-publisherest distribué en binaire de release. Sous Windows, le binaire téléchargé n'est pas dans lePATH: appelez-le par son chemin complet, ou ajoutez son dossier auPATH.brew install mcp-publisher # macOS # Linux / Windows : binaire de release du dépôt modelcontextprotocol/registry - 2
S'authentifier auprès du registre
Avec la clé privée hexadécimale produite à l'étape 3, et le domaine dont l'enregistrement TXT est propagé.
mcp-publisher login dns --domain exemple.tld --private-key "${PRIVATE_KEY}" - 3
Publier depuis le dossier qui contient server.json
L'outil valide localement avant d'envoyer. S'il refuse, le message cite le champ fautif : corrigez-le dans le fichier source du dépôt, pas seulement dans la copie jetable.
cp public/.well-known/mcp-server.json ./server.json mcp-publisher publish - 4
Vérifier le référencement
Puis le seul test qui compte vraiment : le parcours d'un utilisateur réel, dans un client MCP, qui cherche votre serveur par mot-clé, l'ajoute, et lui pose une question de son métier.
curl -s "https://registry.modelcontextprotocol.io/v0/servers?search=exemple"
Ce que la publication d'un serveur de gouvernance impose en plus
Un serveur qui convertit des devises peut se contenter d'être correct. Un serveur qui répond « cet agent a-t-il le droit ? » engage l'appelant devant un tiers : régulateur, client, auditeur. Cinq exigences en découlent, aucune imposée par le registre — elles sont imposées par la nature de la réponse.
- Déterminisme. La même question doit donner la même réponse. Un moteur de gouvernance qui échantillonne ne peut pas être audité ; le nôtre est une table de règles pure, sans LLM dans le chemin de décision.
- Citations au bon niveau. Citer un cadre est vérifiable ; citer un article précis comme s'il s'agissait d'un avis juridique est une promesse qu'un moteur ne peut pas tenir.
- Fraîcheur publiée. Chaque citation porte sa date de dernière vérification, et la réponse porte celle de sa source la plus ancienne. Un produit de conformité qui cache l'âge de ses données demande à être cru plutôt que vérifié.
- Preuve vérifiable sans vous. Empreinte, signature, chaînage, horodatage tiers — et vérification gratuite, sans compte. Une preuve qu'il faut payer pour vérifier n'est pas une preuve.
- Statut consultatif affiché. Le manifeste, la réponse et la documentation doivent dire la même chose : le serveur décide, l'infrastructure de l'appelant applique.
Déclarez aussi lesquels de vos outils sont facturés. Un agent qui découvre votre serveur dans le registre n'a aucun moyen de deviner qu'un appel coûte quelque chose, et un outil facturé non déclaré est la meilleure façon de perdre la confiance d'un intégrateur en une seule facture.
Dépannage — les erreurs réellement rencontrées
| Symptôme | Cause | Correction |
|---|---|---|
Error: ed25519 private key (hex) is required | La commande login dns attend une clé que vous générez vous-même | Étape 3, puis --private-key <hex> |
mcp-publisher : commande non reconnue | Binaire téléchargé mais absent du PATH | Appeler par chemin complet, ou ajouter le dossier au PATH |
| Le manifeste téléchargé fait 15 octets | curl sans -L a enregistré le corps d'une redirection | curl -L, puis vérifier que le fichier contient bien du JSON |
openssl genpkey -algorithm Ed25519 échoue (macOS) | LibreSSL, livré par défaut, n'implémente pas Ed25519 | Installer OpenSSL 3 et appeler ce binaire explicitement |
login dns échoue en boucle | TXT pas encore propagé | dig TXT exemple.tld, attendre, réessayer |
| Description rejetée | Plus de 100 caractères | Raccourcir dans le fichier source, republier |
| Le serveur apparaît, les outils échouent | Production pas à jour | Le registre référence, il ne proxifie pas : redéployez |
Après la publication
- Garder l'enregistrement DNS TXT en permanence.
- Incrémenter
versiondans le manifeste à chaque changement, puis republier avec la même commande. - Traiter la description du registre comme une affirmation publique : si elle cesse d'être vraie, elle se corrige le jour même.
- Noter la date de publication quelque part dans le dépôt — c'est le genre de fait qu'on croit retenir et qu'on ne retient pas.
+Faut-il un domaine pour publier au registre MCP ?
Non : l'authentification GitHub permet de publier sous io.github.<pseudo>/<serveur>. Mais pour un serveur de gouvernance, la preuve de propriété du domaine fait partie de l'argument de confiance, et l'espace de noms est très difficile à changer après coup.
+Où doit être placé l'enregistrement TXT ?
Sur l'apex du domaine, avec la valeur v=MCPv1; k=ed25519; p=<clé publique base64>. Pas sur un sous-domaine, pas sur un sélecteur. Il doit rester en place après la publication, le registre pouvant revérifier la propriété.
+La clé privée doit-elle être conservée ?
Oui, dans votre gestionnaire de secrets : elle sera nécessaire à chaque republication. Elle ne va ni dans le dépôt, ni dans le manifeste, ni dans une variable de CI partagée.
+Le registre exécute-t-il mon serveur ?
Non. Il référence son nom, sa description et son URL. Si votre production tombe ou régresse, le référencement reste intact et pointe vers un serveur cassé — d'où l'étape 0.
+Comment mettre à jour un serveur déjà publié ?
Incrémentez version dans le manifeste et relancez mcp-publisher publish avec la même authentification. Le nom, lui, ne change pas : c'est l'identité que les clients ont mémorisée.
Le serveur décrit ici est réel : ca.structureclerk/mcp expose un outil de décision d'autorité pour agents IA. Sa spécification et son format de preuve sont publics sur la page Autorité.