Ajoutez un serveur MCP lorsqu’un cas d’usage de votre plugin nécessite des données en temps réel, une authentification, des actions contrôlées ou du code qui s’exécute sur une infrastructure que vous exploitez. Le serveur définit les outils dont disposent ChatGPT et Codex. Il peut fonctionner sans renvoyer d’interface utilisateur personnalisée.
Partez des objectifs que votre plugin prend en charge, recensés dans votre inventaire des cas d’usage. Chaque outil doit aider l’utilisateur à atteindre un objectif identifiable et ne donner accès qu’aux données et aux actions nécessaires pour l’atteindre.
Développez d’abord les outils. Une fois que le serveur fonctionne sans interface personnalisée, vous pouvez ajouter une interface utilisateur au serveur MCP pour les workflows qui nécessitent une interaction visuelle.
Choisissez un kit de développement logiciel pour MCP
Les kits de développement logiciel (SDK) officiels fournissent des utilitaires pour définir les schémas, une structure de base pour le serveur et un transport HTTP en streaming :
- SDK TypeScript, publié sous le nom
@modelcontextprotocol/sdk. - SDK Python, publié sous le nom
mcp.
Installez le SDK adapté à la pile technique de votre serveur :
# TypeScript
npm install @modelcontextprotocol/sdk zod
# Python
pip install mcp
Créez le serveur
Créez un serveur MCP avec un nom et un numéro de version stables :
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
const server = new McpServer({
name: "acme-projects",
version: "1.0.0",
});Les serveurs MCP peuvent aussi renvoyer un champ instructions lors de l’initialisation. ChatGPT et Codex utilisent ces instructions en complément des métadonnées des outils.
Réservez les instructions du serveur aux consignes communes à plusieurs outils, comme un ordre d’appel imposé ou des limites de débit partagées. Placez les informations les plus importantes dans les 512 premiers caractères. Ne répétez pas la description de chaque outil et ne cherchez pas à modifier la personnalité du modèle.
const server = new McpServer(
{ name: "acme-projects", version: "1.0.0" },
{
instructions:
"Before updating a project, call get_project to confirm its ID and current status.",
}
);Définissez les outils à partir des objectifs des utilisateurs
Créez un outil pour chaque action distincte que le plugin doit prendre en charge. Privilégiez des opérations ciblées comme list_projects, get_project et update_project plutôt qu’un seul outil doté de nombreux modes sans rapport entre eux.
Chaque outil doit comporter les éléments suivants :
- Un nom qui indique l’action effectuée et un titre compréhensible par l’utilisateur.
- Une description qui précise quand utiliser l’outil.
- Un schéma d’entrée explicite.
- Un schéma de sortie si l’outil renvoie des données structurées.
- Des annotations de sécurité qui reflètent le comportement réel de l’outil.
- Un gestionnaire qui vérifie que la requête est autorisée et exécute l’opération.
Le modèle s’appuie sur ces métadonnées pour décider s’il doit appeler l’outil et de quelle manière. Considérez les noms, les descriptions, les schémas et les annotations comme faisant partie intégrante du comportement du plugin tel que le perçoit l’utilisateur.
// Local example data; replace this with your application data.
const projects = [
{ id: "project-1", name: "Website", status: "active" },
{ id: "project-2", name: "Launch", status: "archived" },
];
async function listProjects({ status }: { status?: string }) {
return projects.filter((project) => !status || project.status === status);
}
import { z } from "zod";
server.registerTool(
"list_projects",
{
title: "List projects",
description:
"Use this when the user wants to find or review projects in their Acme workspace.",
inputSchema: {
status: z.enum(["active", "archived"]).optional(),
},
outputSchema: {
projects: z.array(
z.object({
id: z.string(),
name: z.string(),
status: z.string(),
})
),
},
annotations: {
readOnlyHint: true,
openWorldHint: false,
destructiveHint: false,
},
},
async ({ status }) => {
const projects = await listProjects({ status });
return {
structuredContent: { projects },
content: [
{
type: "text",
text: `Found ${projects.length} projects.`,
},
],
};
}
);Renvoyez des résultats utiles sans interface utilisateur
Le résultat d’un outil peut inclure les champs suivants :
structuredContent: des données concises que le modèle peut examiner et réutiliser lors d’appels ultérieurs.content: du texte ou d’autres contenus MCP qui aident le modèle à répondre à l’utilisateur._meta: des données propres au client, invisibles pour le modèle.
Renvoyez suffisamment d’informations pour que le modèle puisse mener le workflow à son terme sans composant d’interface. Utilisez des identifiants stables dans les résultats structurés pour que les outils appelés ensuite puissent faire référence aux mêmes enregistrements.
N’incluez aucun secret, jeton d’accès ou renseignement personnel superflu dans les résultats des outils. Le champ _meta est invisible pour le modèle, mais ne remplace ni les contrôles d’autorisation ni un stockage sécurisé.
Authentifiez et autorisez les requêtes
Ajoutez une authentification lorsqu’un outil lit des données privées ou agit pour le compte d’un utilisateur. Vérifiez les autorisations dans le serveur MCP à chaque requête. Ne laissez jamais le modèle décider si un utilisateur dispose des droits d’accès nécessaires.
Consultez la page Authentifier les utilisateurs pour en savoir plus sur la découverte OAuth, les schémas de sécurité et les demandes d’autorisation.
Pour faciliter l’utilisation de plusieurs comptes, exposez un outil de profil en lecture seule qui exige une authentification et ajoutez-lui la métadonnée _meta["openai/profile"]: true. OpenAI utilise les informations du profil pour identifier les comptes connectés de façon cohérente et aider les utilisateurs à les distinguer. Déterminez le profil à partir des informations d’authentification validées de la requête et limitez chaque appel d’outil aux droits associés à ces informations. Les utilisateurs peuvent connecter plusieurs comptes même sans outil de profil. Consultez la section Prendre en charge plusieurs comptes pour obtenir le schéma et un exemple d’implémentation.
Annotations des outils et élicitation
Définissez les annotations en fonction du comportement réel de l’outil :
readOnlyHint: utiliseztrueuniquement si l’outil ne peut pas modifier l’état du système.destructiveHint: utiliseztruesi l’outil peut produire des effets irréversibles ou difficiles à annuler.openWorldHint: utiliseztruesi l’outil accède à l’internet public ou à des ressources externes dont le périmètre n’est pas délimité, y compris pour des actions en lecture seule comme la recherche web. Si l’outil se limite au périmètre d’un compte privé ou d’un espace de travail privé, vous pouvez utiliserfalse, même si le service est hébergé à l’extérieur.
Ces annotations aident ChatGPT et Codex à choisir les confirmations à demander et les mesures de sécurité à appliquer. Elles ne remplacent pas les contrôles d’autorisation, de validation ou de confirmation sur votre serveur.
Utilisez l’élicitation MCP lorsque le serveur a besoin d’informations structurées que l’appel initial de l’outil ne contient pas. Demandez uniquement des informations que l’utilisateur peut raisonnablement fournir. N’utilisez pas l’élicitation pour recueillir des secrets ou contourner la procédure d’authentification habituelle.
Compatibilité avec les connaissances de l’entreprise
La fonctionnalité de connaissances de l’entreprise peut utiliser les outils en lecture seule de votre serveur MCP. Pour que votre plugin puisse servir de source de connaissances pour l’entreprise, implémentez les schémas d’entrée standard des outils search et fetch et ajoutez l’annotation readOnlyHint: true aux autres outils en lecture seule.
Pour les sources que le modèle doit citer, renvoyez des URL absolues que l’utilisateur peut ouvrir. Conservez les identifiants internes des documents dans le champ id du résultat. Pour connaître les schémas requis et la structure attendue des résultats, consultez le guide Créer des serveurs MCP pour les intégrations avec ChatGPT et l’API.
Exécutez et testez le serveur en local
Exposez un point de terminaison HTTP en streaming, généralement sur le chemin /mcp, puis examinez-le avec MCP Inspector :
npx @modelcontextprotocol/inspector
Dans l’interface de MCP Inspector, sélectionnez Streamable HTTP et saisissez http://localhost:3000/mcp.
Dans l’inspecteur, procédez aux vérifications suivantes :
- Vérifiez que l’initialisation réussit.
- Examinez les instructions du serveur et la liste des outils qu’il déclare.
- Appelez chaque outil avec des entrées représentatives, puis avec des entrées invalides.
- Vérifiez les schémas, les résultats, les erreurs et les annotations.
- Vérifiez que le serveur contrôle les autorisations pour l’accès aux données privées et les actions d’écriture.
Ensuite, connectez le serveur MCP personnalisé à ChatGPT et testez les demandes directes, les demandes indirectes, les cas limites et les demandes hors périmètre de votre inventaire des cas d’usage.
Déployez le point de terminaison
Pour soumettre votre plugin en vue de sa publication, déployez le serveur MCP sur un point de terminaison HTTPS stable et accessible publiquement. Secure MCP Tunnel permet de connecter un serveur MCP privé à ChatGPT, mais ne répond pas aux exigences de soumission pour publication.
Le point de terminaison de production doit :
- Prendre en charge le transport HTTP en streaming de MCP.
- Répondre à une URL stable qui se termine généralement par
/mcp. - Répondre aux besoins de latence et de disponibilité des workflows du plugin.
- Pouvoir accéder aux services et aux systèmes de stockage de données nécessaires.
- Respecter les limites d’accès imposées par l’authentification et les autorisations.
- Produire des journaux et des métriques en cas d’échec de l’initialisation ou d’un appel d’outil.
Si le serveur MCP doit rester privé, déployez un proxy HTTPS public qui transmet les requêtes MCP au serveur privé. Utilisez le mTLS géré par OpenAI pour authentifier ChatGPT en tant que client MCP, et OAuth 2.1 si votre plugin exige l’authentification des utilisateurs. Si votre réseau exige une liste d’adresses IP autorisées, utilisez les plages d’adresses IP publiées pour les connecteurs ChatGPT et mettez cette liste à jour automatiquement. Une liste d’adresses IP autorisées ne remplace ni l’authentification ni les contrôles d’autorisation.
Le point de terminaison public doit rester accessible pour l’examen du plugin et la vérification du domaine. Lorsque vous soumettez un plugin pour publication, n’utilisez ni Secure MCP Tunnel seul, ni un tunnel temporaire, ni un point de terminaison local.
Choisissez l’infrastructure
Vous pouvez déployer le serveur MCP sur une infrastructure sans serveur, conteneurisée, en périphérie de réseau ou sur une infrastructure applicative classique. Choisissez une plateforme selon les critères suivants :
- Prise en charge de l’environnement d’exécution et des dépendances.
- Gestion des réponses en streaming.
- Temps de démarrage à froid et latence des requêtes.
- Accès réseau aux services nécessaires.
- Exigences de résidence des données et de conformité.
- Gestion des secrets.
- Journalisation, traçage et alertes.
- Gestion des versions et possibilité de revenir à une version antérieure.
Si le serveur héberge aussi des ressources d’interface facultatives, déployez-les sur des origines stables autorisées par la politique de sécurité du contenu du composant.
Configurez le point de terminaison de production
Avant le déploiement :
- Configurez les informations d’authentification de production dans le système de gestion des secrets de l’hôte.
- Configurez le serveur d’autorisation et définissez les règles de redirection autorisées.
- Définissez des délais d’expiration et des limites de débit pour les outils coûteux en ressources ou dont les effets sont visibles à l’extérieur.
- Supprimez les réponses de débogage et les données personnelles superflues.
- Vérifiez que les journaux ne contiennent ni jetons d’accès ni résultats d’outils sensibles.
Après le déploiement, appelez le point de terminaison de production avec MCP Inspector. Vérifiez l’initialisation, les instructions du serveur, les outils, les schémas, les annotations, l’authentification, les résultats et les erreurs.
Préparez les mises à jour
Préservez la rétrocompatibilité des noms et des schémas des outils publiés. Ajoutez des champs ou des outils sans rompre les contrats existants. Si les métadonnées changent, actualisez la connexion au serveur MCP personnalisé et relancez toute la série d’évaluations avant de soumettre le plugin.
Si votre plugin propose une interface facultative, versionnez les identifiants de ses ressources lorsque des modifications du HTML, du JavaScript ou du CSS risquent d’empêcher un composant mis en cache de fonctionner.
Ajoutez des extensions MCP
Les extensions MCP d’OpenAI relient votre plugin à la barre latérale, à la zone de saisie et aux visionneuses de fichiers de ChatGPT. Consultez la page Extensions de plugins pour découvrir des exemples et suivre les étapes de configuration.
Rappels de sécurité
- Considérez toute entrée d’outil comme non fiable.
- Validez les paramètres et contrôlez les autorisations sur le serveur.
- Exigez une confirmation pour les actions d’écriture qui peuvent avoir des conséquences importantes.
- N’incluez ni secrets ni données sensibles dans les métadonnées ou les résultats des outils.
- Consignez suffisamment de contexte pour analyser les échecs, sans enregistrer d’informations d’authentification ni de données personnelles superflues.
- Limitez la fréquence des actions coûteuses en ressources ou dont les effets sont visibles à l’extérieur.