Registre MCP : GitHub, server.json et comment référencer votre serveur

Le registre MCP est l’endroit où les clients et les places de marché trouvent votre serveur, et l’inscription ne demande qu’un seul server.json, un espace de noms vérifié et une seule commande. Cet article suit la connexion GitHub, les contrôles de propriété des paquets, les serveurs distants et un flux de publication par étiquette.

Registre MCP : GitHub, server.json et comment référencer votre serveur
Cristian Da Conceicao
Fondateur de Picasso IA

Un bon serveur MCP que personne ne trouve pourrait aussi bien ne pas exister. Le registre MCP officiel règle ce problème avec un seul fichier JSON, un nom vérifié et une seule commande, et GitHub intervient à trois moments distincts : la connexion, l’espace de noms et l’automatisation des publications. Cet article suit les fichiers et les commandes exacts de la documentation du registre, afin que votre serveur y figure dès la première tentative plutôt qu’à la cinquième.

💡 Réponse rapide : rédigez un server.json, prouvez que vous possédez le paquet vers lequel il pointe, exécutez mcp-publisher login github, puis exécutez mcp-publisher publish. Tout ce qui suit explique pourquoi chaque étape existe et ce qui casse si vous la sautez.

Ce qu’est réellement le registre MCP

Le registre MCP est le dépôt officiel et centralisé des métadonnées des serveurs MCP accessibles publiquement, soutenu par Anthropic, GitHub, PulseMCP et Microsoft. Il a ouvert en préversion en septembre 2025, l’API est figée en v0.1 depuis fin octobre 2025, et la documentation affiche toujours une bannière de préversion, donc attendez-vous à de petites évolutions. Le service en production se trouve à registry.modelcontextprotocol.io.

Des métadonnées, pas du code

Vue aérienne d’un port à conteneurs où des conteneurs empilés forment des grilles bien ordonnées à l’heure dorée

Le registre ne stocke jamais votre code. Il stocke une fiche qui pointe vers un paquet sur npm, PyPI, NuGet, crates.io, un registre de conteneurs ou une version publiée sur GitHub. Pensez à un port à conteneurs : le manifeste indique ce qui se trouve dans chaque caisse et d’où elle vient, tandis que la cargaison se trouve ailleurs. C’est pourquoi l’ordre compte. Vous publiez d’abord le paquet, et seulement ensuite la fiche du registre.

Où intervient GitHub

GitHub intervient à trois endroits du processus :

  • Identité. Connectez-vous avec GitHub, et le nom de votre serveur doit commencer par io.github.username/, ou par le nom de votre organisation à la place du nom d’utilisateur.
  • Métadonnées. server.json contient un objet repository avec "source": "github" et l’URL du dépôt.
  • Automatisation. GitHub Actions peut s’authentifier auprès du registre via OIDC, sans secret stocké.

Il existe aussi une vitrine distincte. GitHub exploite son propre registre MCP à github.com/mcp, et GitHub a annoncé que les serveurs publiés d’eux-mêmes dans le registre open source de la communauté « apparaîtront automatiquement » là-bas. Considérez cela comme un bonus, pas comme une garantie : après la publication, vérifiez vous-même la fiche GitHub.

Qui peut référencer un serveur

Les serveurs open source comme les serveurs propriétaires sont acceptés, à une condition : le serveur doit être accessible publiquement. Cela signifie un paquet public (un paquet npm, une image Docker sur un registre public) ou un point d’accès distant qui n’est pas enfermé dans un réseau privé. Les serveurs installés sur un hôte interne comme mcp.acme-corp.internal, ou derrière un registre de paquets privé, sont hors du champ. Pour ceux-là, exploitez votre propre registre privé.

Bon à savoir également : les applications hôtes ne sont pas censées lire directement le registre officiel. Les places de marché et les agrégateurs le consultent à intervalle régulier, par exemple toutes les heures, et y ajoutent leur propre sélection et leurs propres notes. Votre fiche passe par eux.

Choisissez d’abord votre espace de noms

Le champ name de server.json est l’identité permanente de votre serveur, et votre méthode de connexion détermine les noms que vous avez le droit d’utiliser.

Méthode de connexionFormat du nomExemple
GitHubio.github.username/* ou io.github.orgname/*io.github.alice/weather-server
Domaine (DNS ou HTTP)Forme inversée de votre domainecom.example/acme-analytics

Les noms GitHub, des gains rapides

Gros plan de vieilles boîtes aux lettres en laiton avec de petites étiquettes de papier dans le hall d’un immeuble ancien

Choisissez la voie GitHub si vous êtes développeur indépendant ou projet open source. La CLI lance un flux d’autorisation OAuth par code d’appareil, vous l’approuvez dans le navigateur, et c’est terminé en quelques minutes. Pas de panneau DNS, pas de fichiers à héberger. Le compromis porte sur le nom : io.github.alice/weather-server convient bien à un projet personnel, mais une marque d’entreprise veut généralement son propre domaine.

Noms de domaine avec DNS ou HTTP

Les noms basés sur un domaine utilisent la forme inversée d’un domaine que vous contrôlez, par exemple com.example/acme-analytics. Vous prouvez ce contrôle de deux façons :

  1. DNS. Générez une paire Ed25519 (ou ECDSA P-384) avec openssl, puis publiez la moitié publique sous forme d’enregistrement TXT au format example.com. IN TXT "v=MCPv1; k=ed25519; p=<base64>". Prévoyez plusieurs minutes pour la propagation.
  2. HTTP. Hébergez la même ligne v=MCPv1; ... dans un fichier accessible à https://example.com/.well-known/mcp-registry-auth.

Connectez-vous ensuite avec mcp-publisher login dns --domain example.com ou mcp-publisher login http --domain example.com, en ajoutant la moitié privée de votre paire comme indiqué dans la documentation sur l’authentification. Les équipes qui préfèrent ne pas garder un fichier privé sur un ordinateur portable peuvent signer via les services de signature cloud de Google ou d’Azure.

Rédigez server.json étape par étape

Générer le squelette

Installez l’outil de publication avec Homebrew (brew install mcp-publisher) ou téléchargez un binaire depuis les versions GitHub du registre. Ensuite, dans le dossier de votre projet de serveur :

mcp-publisher --help
mcp-publisher init

La commande init écrit un modèle server.json et remplit automatiquement ce qu’elle peut à partir de votre projet.

Un fichier minimal fonctionnel

Développeur en sweat-shirt gris tapant sur un bureau debout, à côté d’un carnet de notes et d’une petite plante grasse

Voici la structure qu’utilise la documentation pour un serveur npm local :

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.my-username/weather",
  "description": "An MCP server for weather information.",
  "repository": {
    "url": "https://github.com/my-username/mcp-weather-server",
    "source": "github"
  },
  "version": "1.0.1",
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@my-username/mcp-weather-server",
      "version": "1.0.1",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

Conservez la ligne $schema générée par init, car la date du schéma évolue avec le temps. Trois champs posent l’essentiel des problèmes. Le name doit correspondre à la preuve de propriété contenue dans votre paquet (plus de détails ci-dessous). Le packages[].identifier doit pointer vers quelque chose déjà publié. Et transport.type indique aux clients comment communiquer avec le serveur, stdio désignant un processus local.

Besoin de variables d’environnement ? Ajoutez-les à l’entrée du paquet avec les indicateurs isRequired et isSecret, afin que les clients les demandent et masquent la saisie.

Les règles de version qui piègent

Chaque publication exige une version unique, et une fois publiée, cette version et ses métadonnées ne peuvent plus changer. Le versionnement sémantique est recommandé, même si toute chaîne est acceptée. Les plages de versions sont rejetées volontairement.

Chaîne de versionStatut
1.0.0, 1.0.0-beta.1, 3.0.0-rc.2Recommandé
2025-06-18, v1.0Autorisé
^1.2.3, ~1.2.3, >=1.2.3, 1.xInterdit

Deux habitudes vous évitent des ennuis. D’abord, alignez la version du serveur sur la version du paquet, de sorte que 1.2.3 dans server.json corresponde à 1.2.3 sur npm. Ensuite, si vous devez seulement corriger les métadonnées du registre sans toucher au paquet, publiez une préversion telle que 1.2.3-1. Attention au piège : le versionnement sémantique classe une préversion avant sa version finale, donc publier 1.2.3-1 après 1.2.3 ne sera pas marqué comme la dernière version.

Serveurs distants avec remotes

Vue en contre-plongée d’un couloir silencieux de centre de données bordé de hautes baies de serveurs noires

Les serveurs hébergés utilisent un tableau remotes à la place de packages, ou en complément :

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "com.example/acme-analytics",
  "description": "Real-time business intelligence and reporting platform",
  "version": "2.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://analytics.example.com/mcp",
      "headers": [
        {
          "name": "Authorization",
          "description": "Bearer token for your account",
          "isRequired": true,
          "isSecret": true
        }
      ]
    }
  ]
}

Un serveur distant doit être accessible publiquement à son URL. Privilégiez Streamable HTTP ; le transport SSE est déprécié, donc ajoutez un point d’accès "sse" uniquement pour les clients existants. Les configurations multi-locataires peuvent utiliser des variables d’URL telles que https://{tenant_id}.analytics.example.com/mcp, chacune décrite avec isRequired, default ou choices. Et si vous livrez à la fois un paquet et un serveur distant, listez les deux : l’application hôte choisit la méthode d’installation qu’elle préfère.

Prouvez que vous possédez le paquet

Le registre vérifie que le paquet appartient réellement au nom que vous revendiquez. Si vous sautez cette étape, la publication échoue avec « Registry validation failed for package ». Chaque type de paquet a sa propre preuve.

Une vérification par type de paquet

Gros plan d’un tampon de notaire en laiton imprimant une empreinte d’encre fraîche sur un épais papier crème

Type de paquetregistryTypePreuve de propriété
npmnpmmcpName dans package.json égal au nom du serveur
PyPIpypimcp-name: <server name> dans le README, commentaire masqué autorisé
NuGetnugetmcp-name: <server name> dans le README, commentaire masqué autorisé
Cargo (crates.io)cargomcp-name: <server name> sous forme de texte visible dans le README
Image Docker ou OCIociLABEL io.modelcontextprotocol.server.name="<server name>"
Fichier MCPBmcpbL’URL contient « mcp », plus un hash fileSha256 dans server.json

Pour npm, cela ressemble à ceci dans package.json :

{
  "name": "@my-username/mcp-weather-server",
  "version": "1.0.1",
  "mcpName": "io.github.my-username/weather"
}

Quelques détails piègent souvent. La vérification npm utilise uniquement le registre npm public, et PyPI et NuGet sont également limités à leurs registres officiels. crates.io supprime les commentaires HTML, donc le jeton Cargo doit être du texte visible et non un commentaire masqué. Pour les images de conteneurs, identifier suit registry/namespace/repository:tag, et les hébergeurs pris en charge sont Docker Hub, GitHub Container Registry (ghcr.io), Google Artifact Registry, Azure Container Registry et Microsoft Container Registry. Pour les fichiers MCPB hébergés sur les versions GitHub ou GitLab, calculez le hash avec openssl dgst -sha256 your-file.mcpb. Le registre ne vérifie pas ce hash, mais les clients le font avant l’installation.

💡 Astuce : le nom du serveur dans server.json et la preuve contenue dans le paquet doivent correspondre caractère pour caractère. Une seule majuscule en trop suffit à faire échouer la validation.

Publiez depuis votre terminal

Connexion avec GitHub

Femme en veste en jean assise à une table près d’une vitre de café sous la pluie, tenant un téléphone à côté d’un ordinateur ouvert

Lancez la connexion depuis le dossier de votre projet :

mcp-publisher login github

La CLI affiche un code à usage unique et une URL :

To authenticate, please:
1. Go to: https://github.com/login/device
2. Enter code: ABCD-1234
3. Authorize this application
Waiting for authorization...

Ouvrez le lien, collez le code, approuvez, et le terminal confirme la connexion. Si vous voyez ensuite « Invalid or expired Registry JWT token », la session a expiré. Relancez la connexion.

Publier et vérifier

Vue au niveau des yeux d’une vitrine de librairie à l’heure dorée, avec un seul nouveau livre relié posé sur un présentoir en bois

Une fois le paquet disponible sur npm et server.json enregistré, publiez :

mcp-publisher publish

Une exécution réussie affiche l’URL du registre ainsi que le nom de votre serveur avec sa version. Confirmez-le via l’API publique :

curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.my-username/weather"

Les métadonnées de votre serveur doivent apparaître dans le JSON renvoyé. Les places de marché en aval se mettent à jour selon leur propre calendrier, donc laissez-leur un peu de temps avant de vous attendre à voir la fiche là-bas, et cherchez-la aussi sur github.com/mcp.

Les mises à jour suivent le même chemin. Incrémentez la version du paquet, publiez-la sur npm, mettez server.json à jour pour correspondre, puis relancez mcp-publisher publish. Chaque publication est une version immuable à part entière, et le registre marque la version sémantique la plus récente comme la dernière, afin que les clients qui demandent la version courante obtiennent la bonne.

Livrez les versions avec GitHub Actions

Un flux de publication par étiquette

Vue en plongée de colis en carton circulant sur un tapis roulant dans une halle de tri

Une fois la publication manuelle fonctionnelle, intégrez-la à votre CI pour que chaque étiquette de version publie ensemble le paquet et la fiche du registre. Ce flux utilise GitHub OIDC, la méthode recommandée par la documentation :

name: Publish to MCP Registry

on:
  push:
    tags: ["v*"]

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout code
        uses: actions/checkout@v5

      - name: Set up Node.js
        uses: actions/setup-node@v5
        with:
          node-version: "lts/*"

      - name: Install dependencies
        run: npm ci

      - name: Build package
        run: npm run build --if-present

      - name: Publish package to npm
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Install mcp-publisher
        run: |
          curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher

      - name: Authenticate to MCP Registry
        run: ./mcp-publisher login github-oidc

      - name: Publish server to MCP Registry
        run: ./mcp-publisher publish

La publication se fait avec deux commandes : git tag v1.0.0 et git push origin v1.0.0. Le modèle laisse une étape facultative : la mise à jour de la version. Si server.json contient une version codée en dur, le registre rejettera une nouvelle publication identique, donc définissez-la à partir de l’étiquette avant l’étape de publication. Pour un serveur à paquet unique, cette ligne jq met à jour les deux champs de version :

VERSION=${GITHUB_REF#refs/tags/v}
jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json > server.tmp && mv server.tmp server.json

Les secrets dont vous avez besoin

  • GitHub OIDC : aucun secret pour le registre. Vous avez seulement besoin de l’autorisation id-token: write.
  • Jeton d’accès personnel GitHub : stockez-le comme secret et exécutez mcp-publisher login github --token, avec les portées read:org et read:user.
  • Connexion DNS : stockez la moitié privée de votre paire Ed25519 comme secret et transmettez-la à mcp-publisher login dns.
  • Registre de paquets : le flux ci-dessus a aussi besoin d’un secret NPM_TOKEN pour npm publish.

Corrigez les erreurs avant que les utilisateurs ne les voient

Vue de dessus d’un bureau avec une page imprimée annotée au crayon rouge, une loupe et des notes adhésives

La plupart des publications échouées se ramènent à cinq messages :

Message d’erreurCorrection probable
« Registry validation failed for package »Le paquet n’a pas sa preuve de propriété, comme mcpName dans package.json.
« Invalid or expired Registry JWT token »Reconnectez-vous avec mcp-publisher login github.
« You do not have permission to publish this server »Votre méthode de connexion ne correspond pas au préfixe du nom. La connexion GitHub exige io.github.your-username/.
« Authentication failed »Dans Actions, vérifiez que id-token: write est défini, ou contrôlez vos secrets.
« Package validation failed »Le paquet n’est pas encore sur son registre, ou il n’a pas la preuve de propriété.

Avant chaque publication, parcourez cette courte liste :

  • Le name dans server.json est égal au mcpName (ou au jeton du README, ou à l’étiquette de l’image).
  • La version du paquet dans server.json existe déjà sur npm, PyPI ou votre hébergeur de conteneurs.
  • Le version du serveur n’a jamais été publié auparavant, et ce n’est pas une plage.
  • Toute URL distante répond depuis l’internet public, et pas seulement depuis le réseau de votre bureau.
  • Le serveur est destiné au public. Les serveurs privés relèvent d’un registre privé.

Rédigez et illustrez avec PicassoIA

Un LLM est une machine rapide pour produire un premier jet de server.json, à condition que ce soit le registre qui juge. PicassoIA héberge de grands modèles de langage utilisables directement depuis le navigateur, dont Claude Sonnet 5, GPT 5.6 Sol et Gemini 3.5 Flash.

Comment utiliser Sonnet 5 sur PicassoIA

  1. Ouvrez la page Claude Sonnet 5 sur PicassoIA et lancez une nouvelle conversation.
  2. Collez vos champs package.json (nom, version, description, dépôt) ainsi que la ligne $schema produite par mcp-publisher init.
  3. Demandez uniquement du JSON, indiquez au modèle de laisser $schema intact, et interdisez les champs inventés.
  4. Copiez le résultat dans server.json, puis vérifiez à l’œil que name est égal à votre mcpName.
  5. Lancez mcp-publisher publish. Si la validation signale une erreur, recollez le message d’erreur exact dans la conversation.

Des prompts courts accompagnés du code collé font mieux que de longs prompts descriptifs, car les modèles inventent des champs plausibles lorsqu’ils ne voient pas le vrai fichier. Vous voulez aussi l’ébauche du flux Actions ? GPT 5.6 Sol fait un bon second avis pour cela.

PicassoIA exploite aussi une API pour développeurs, et elle constitue un exemple pratique de l’usage des environmentVariables. L’API se trouve à https://api.picassoia.com/v1 et fonctionne comme d’autres API de prédiction : vous créez une prédiction, vous l’interrogez, puis vous récupérez le résultat, avec jusqu’à 5 prédictions simultanées par compte (au début d’octobre 2026). Un serveur d’encapsulation hypothétique demanderait à chaque utilisateur son propre identifiant une seule fois, via une entrée de ce type dans son paquet :

"environmentVariables": [
  {
    "name": "PICASSOIA_TOKEN",
    "description": "Bearer credential for api.picassoia.com/v1",
    "isRequired": true,
    "isSecret": true,
    "format": "string"
  }
]

Une entrée de registre n’est que du texte, mais le README, la carte de partage et l’article de lancement ont tous besoin d’images. Ouvrez PicassoIA, choisissez un modèle d’image ou de vidéo, et générez une image principale ou un court extrait de démonstration pour votre serveur. Le catalogue complet des modèles se trouve sur picassoia.com/en/all-models. Essayez trois prompts, gardez le meilleur et livrez-le avec votre premier mcp-publisher publish.

Partager cet article

Choisissez votre langue