10 000 serveurs MCP existent : voici ce qui différencie les bons
L'écosystème MCP comptait 10 000 serveurs en avril 2026. Sept pratiques qui séparent les serveurs MCP utiles de ceux abandonnés, avec des exemples tirés d'un serveur de production de 49 outils.
L'écosystème MCP comptait 10 000 serveurs publics en avril 2026. TypeScript, Python, Java, Kotlin, Les SDK C# et Swift ont atteint 97 millions de téléchargements mensuels combinés. OAuth 2.1 et transport HTTP diffusable sont stables. La Linux Foundation supervise la gouvernance. Claude Desktop, Curseur, Windsurf, Zed, Continuer, Sourcegraph Cody et Taskade Genesis sont tous livrés avec le support client MCP.
La plupart de ces 10 000 serveurs sont des expériences abandonnées. Noms d'outils vagues, pas de validation d'entrée, supprimés Surfaces d'API et messages d'erreur génériques. La poignée de développeurs qui reviennent sans cesse pour en partager sept pratiques.
Cet article couvre ces sept pratiques avec le code de production de
Le serveur MCP de Botoi, qui expose 49 outils sélectionnés à partir de plus de 150 points de terminaison d'API. Chaque
L'exemple de code provient du serveur en cours d'exécution à api.botoi.com/mcp.
1. Organiser les outils ; ne videz pas l'intégralité de votre API
La plus grosse erreur : enregistrer chaque point de terminaison d’API en tant qu’outil MCP. Botoi a plus de 150 points de terminaison. S'il s'agissait tous d'outils MCP, le manifeste de l'outil consommerait plus de 30 000 jetons avant une conversation démarre. Cela laisse moins de place à la question réelle de l'utilisateur et augmente les chances que le modèle choisisse la réponse. mauvais outil et ralentit chaque demande car le modèle doit lire des centaines d'outils définitions.
Botoi en enregistre 49. Les critères de sélection : les outils utilisés par les développeurs lors des sessions de codage (DNS recherche, décodage JWT, génération de hachage), les outils qui produisent des modèles de sortie structurés peuvent raisonner sur (validation JSON, détection PII) et des outils qui enregistrent un changement de contexte (encodage Base64, métadonnées URL extraction).
// curated-tools.ts - 49 tools from 150+ endpoints
export const CURATED_TOOLS: Record<string, CuratedTool> = {
lookup_dns: {
path: "/v1/dns/lookup",
method: "post",
title: "DNS Lookup",
description:
"Query DNS records (A, AAAA, MX, TXT, CNAME, NS) for a domain. " +
"Use when you need to check DNS configuration or troubleshoot domain resolution.",
annotations: { readOnlyHint: true, openWorldHint: true },
},
dev_hash: {
path: "/v1/hash",
method: "post",
title: "Hash Text",
description:
"Generate a hash (MD5, SHA-1, SHA-256, SHA-512) of input text. " +
"Use for checksums, data integrity, or fingerprinting.",
annotations: { readOnlyHint: true },
},
// ... 47 more curated tools
};
Les outils qui n'ont pas été retenus : les opérations par lots avec des charges utiles importantes (génération de PDF à partir de HTML), des outils qui renvoient des données binaires (image de code QR, capture d'écran) et des outils avec chevauchement fonctionnalité (trois points de terminaison de hachage différents regroupés en un seul). Chaque outil que vous ajoutez coûte des jetons. Traitez votre manifeste MCP comme un produit et non comme un miroir de vos documents API.
Règle générale : si vous disposez de plus de 50 outils, le modèle passe plus de temps à lire les définitions des outils. que de faire un travail utile. Auditez votre manifeste tous les trimestres et supprimez les outils sans aucune invocation.
2. Rédigez des descriptions d'outils qui aident le modèle à choisir correctement
Le modèle lit la description de votre outil pour décider s'il doit l'appeler. Une description vague comme "Est-ce que Des trucs DNS" obligent le modèle à deviner. Une description remplie de détails d'implémentation gaspille des jetons sur les informations dont le modèle n'a pas besoin.
Le modèle qui fonctionne : une phrase commençant par un verbe qui indique ce que fait l'outil, suivie de une deuxième phrase commençant par « Utiliser quand » qui décrit la condition de déclenchement.
Mauvaises descriptions
// Bad: vague, no trigger condition
{
name: "dns",
description: "Does DNS stuff"
}
// Bad: too long, includes implementation details
{
name: "dns_lookup_tool",
description: "This tool uses the DNS-over-HTTPS protocol to query Cloudflare's 1.1.1.1 resolver via a GET request to https://cloudflare-dns.com/dns-query with an Accept header of application/dns-json. It supports A, AAAA, MX, TXT, CNAME, and NS record types and returns the raw DNS response parsed into JSON format."
}
Bonnes descriptions
// Good: verb-first, one sentence what + one sentence when
{
name: "lookup_dns",
description:
"Query DNS records (A, AAAA, MX, TXT, CNAME, NS) for a domain. " +
"Use when you need to check DNS configuration or troubleshoot domain resolution."
}
// Good: specific about capabilities and trigger condition
{
name: "security_pii_detect",
description:
"Scan text for personal identifiable information (emails, phones, SSNs, credit cards). " +
"Use when you need to audit user input or log output for sensitive data before storage."
}
La première phrase concerne la sélection de l'outil : elle indique au modèle ce que fait l'outil et quelles sont ses entrées. accepte. La deuxième phrase sert à lever l'ambiguïté : lorsque deux outils peuvent correspondre, la clause "Utiliser quand" aide le modèle à choisir le bon.
Les 49 outils du serveur MCP de Botoi suivent ce modèle. Le résultat : les modèles choisissent systématiquement le
corriger l'outil du premier coup, même lorsque plusieurs outils ont des capacités qui se chevauchent (par exemple,
lookup_email contre. lookup_dns pour vérifier les enregistrements MX).
3. Utilisez les annotations des outils
La spécification MCP définit quatre conseils d'annotation : readOnlyHint, destructiveHint,
idempotentHint, et openWorldHint. La plupart des serveurs les ignorent. Modèles et
les clients qui respectent ces conseils prennent des décisions plus sûres : ils n'appelleront pas d'outils destructeurs sans
confirmation, ils réessayeront les outils idempotents en cas d'échec, et ils avertiront les utilisateurs avant les outils qui
contacter des services externes.
// Annotations from Botoi's curated-tools.ts
lookup_dns: {
path: "/v1/dns/lookup",
annotations: {
readOnlyHint: true, // reads data, changes nothing
openWorldHint: true, // contacts external DNS servers
},
},
storage_paste_create: {
path: "/v1/paste/create",
annotations: {
destructiveHint: true, // creates new data
idempotentHint: false, // each call creates a new paste
},
},
dev_hash: {
path: "/v1/hash",
annotations: {
readOnlyHint: true, // pure computation
idempotentHint: true, // same input = same output
},
},
| Annotation | Signification | Exemple |
|---|---|---|
readOnlyHint: true |
Lit les données, ne change rien | Recherche DNS, vérification SSL, géolocalisation IP |
destructiveHint: true |
Crée, met à jour ou supprime des données | Créer un collage, générer une URL courte |
idempotentHint: true |
Appelez plusieurs fois en toute sécurité avec la même entrée | Génération de hachage, formatage JSON |
openWorldHint: true |
Contacter les services externes | DNS sur HTTPS, WHOIS, métadonnées d'URL |
Les annotations ne coûtent presque rien en termes de taille de manifeste, mais elles donnent aux clients et aux modèles la possibilité de le faire. les métadonnées dont ils ont besoin pour planifier des flux de travail en plusieurs étapes en toute sécurité. Placez-les sur chaque outil.
4. Devenez apatride avec Streamable HTTP
Le transport SSE (Server-Sent Events) est obsolète dans la spécification MCP. Il fallait de la persévérance connexions, gestion de session et logique de reconnexion. HTTP streamable le remplace par le standard Requêtes HTTP POST transportant des charges utiles JSON-RPC 2.0. Aucune connexion persistante. Aucun état de session. Travaux avec chaque infrastructure HTTP : CDN, équilibreurs de charge, environnements d'exécution en périphérie, plates-formes sans serveur.
Le serveur MCP de Botoi fonctionne sur Cloudflare Workers. Chaque demande crée un nouveau McpServer
instance, enregistre les 49 outils, gère la demande et renvoie. Pas d'identifiant de session, pas de reconnexion
gestionnaire, aucun état à gérer entre les requêtes.
// MCP server on Cloudflare Workers with Streamable HTTP
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import {
WebStandardStreamableHTTPServerTransport
} from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
app.all("/mcp", async (c) => {
const apiKey =
c.req.header("X-API-Key") ||
c.req.header("Authorization")?.replace("Bearer ", "");
const server = createMcpServer(apiKey, c.env);
const transport = new WebStandardStreamableHTTPServerTransport();
await server.connect(transport);
return transport.handleRequest(c.req.raw);
});
La WebStandardStreamableHTTPServerTransport du SDK MCP fonctionne avec n'importe quel environnement d'exécution
qui prend en charge les standards du Web Request/Response API : Cloudflare Workers,
Deno Deploy, Bun, Vercel Edge Functions et Node.js 18+. Si vous démarrez un nouveau serveur MCP dans
2026, utilisez Streamable HTTP. Si vous utilisez un serveur SSE, migrez avant que les clients n'abandonnent la prise en charge.
Les serveurs sans état évoluent horizontalement sans coordination. Le point de terminaison MCP de Botoi fonctionne sur celui de Cloudflare réseau périphérique ; demande un itinéraire vers le centre de données le plus proche. Outils purement informatiques (hachage, Base64, Formatage JSON) répondent en moins de 50 ms.
5. Validez les entrées avec des schémas
Les outils MCP reçoivent du JSON arbitraire à partir des modèles. Un modèle peut envoyer
où vous attendez une chaîne, incluez des champs inconnus ou omettez les paramètres requis. Validation des entrées
avant que l'exécution ne détecte ces erreurs plus tôt et renvoie des commentaires structurés que le modèle peut utiliser pour
auto-correction.
L'approche de Botoi : le schema-builder.ts le module lit les définitions de chemin OpenAPI à
heure d'enregistrement et convertit chaque propriété en type Zod. Le SDK MCP valide les entrées par rapport
le schéma Zod avant l'exécution du gestionnaire d'outils.
// schema-builder.ts - OpenAPI to Zod conversion
import { z } from "zod";
import { paths } from "../../openapi-paths";
function mapPropertyToZod(
prop: OpenApiProperty,
isRequired: boolean
): z.ZodTypeAny {
let schema: z.ZodTypeAny;
if (prop.enum && prop.enum.length > 0) {
schema = z.enum(prop.enum as [string, ...string[]]);
} else {
switch (prop.type) {
case "number":
case "integer":
schema = z.number(); break;
case "boolean":
schema = z.boolean(); break;
default:
schema = z.string(); break;
}
}
if (!isRequired) schema = schema.optional();
return schema;
}
export function buildZodSchema(
apiPath: string,
method: "get" | "post"
): Record<string, z.ZodTypeAny> {
const operation = getOperation(apiPath, method);
if (!operation) return {};
const schema = operation.requestBody?.content?.["application/json"]?.schema;
if (!schema?.properties) return {};
const required = new Set(schema.required ?? []);
const result: Record<string, z.ZodTypeAny> = {};
for (const [key, prop] of Object.entries(schema.properties)) {
result[key] = mapPropertyToZod(prop, required.has(key));
}
return result;
}
La boucle d'enregistrement transmet le schéma généré comme inputSchema pour chaque outil :
// server.ts - register tools with Zod schemas
for (const [toolName, tool] of Object.entries(CURATED_TOOLS)) {
const zodSchema = buildZodSchema(tool.path, tool.method);
server.registerTool(toolName, {
title: tool.title,
description: tool.description,
inputSchema: zodSchema,
annotations: tool.annotations,
}, async (args: Record<string, unknown>) => {
return callApi(tool.path, tool.method, args, apiKey, env);
});
}
Cela signifie que chaque outil bénéficie d'une validation d'entrée gratuitement. Si le modèle envoie un entier où une chaîne est attendu, le SDK MCP renvoie une erreur structurée avant l'exécution de votre code de gestionnaire. Le modèle voit l'erreur, corrige l'entrée et réessaye.
6. Renvoie les erreurs structurées sur lesquelles le modèle peut raisonner
Lorsqu'un outil échoue, le modèle a besoin de suffisamment d'informations pour récupérer. "Quelque chose s'est mal passé" ne sert à rien. Une erreur structurée avec le nom du champ, ce qui était attendu et ce qui a été reçu donne au modèle un effacer le chemin pour réessayer avec la saisie corrigée.
Mauvaise réponse d'erreur
// Bad: the model can't fix this
{
"content": [{ "type": "text", "text": "Something went wrong" }],
"isError": true
}
Bonne réponse aux erreurs
// Structured error the model can reason about
{
"content": [
{
"type": "text",
"text": "{\\n \\"error\\": \\"validation_error\\",\\n \\"message\\": \\"Invalid record type\\",\\n \\"field\\": \\"type\\",\\n \\"expected\\": [\\"A\\", \\"AAAA\\", \\"MX\\", \\"TXT\\", \\"CNAME\\", \\"NS\\"],\\n \\"received\\": \\"INVALID\\"\\n}"
}
],
"isError": true
}
Botoi's callApi le wrapper capture l'erreur structurée de l'API REST sous-jacente et
le transmet à la réponse MCP avec isError: true:
// server.ts - API call wrapper with structured errors
async function callApi(
path: string,
method: string,
body: unknown,
apiKey: string | undefined,
env: Env
) {
const headers: Record<string, string> = {
"Content-Type": "application/json",
};
if (apiKey) headers["X-API-Key"] = apiKey;
const req = new Request(\`http://internal\${path}\`, {
method: method.toUpperCase(),
headers,
body: method === "post" ? JSON.stringify(body) : undefined,
});
const res = await appFetcher(req, env);
const json = await res.json();
if (!json.success) {
return {
content: [{
type: "text",
text: JSON.stringify(json.error, null, 2),
}],
isError: true,
};
}
return {
content: [{
type: "text",
text: JSON.stringify(json.data, null, 2),
}],
};
}
Le détail clé : le isError: true L'indicateur indique au modèle que l'appel de l'outil a échoué.
Le JSON structuré dans le text le champ lui dit pourquoi. Modèles formés sur les modèles d'utilisation des outils
lira l'erreur, identifiera le champ problématique et réessayera avec une valeur corrigée. Erreur générique
les chaînes forcent le modèle à deviner ou à abandonner.
7. Ajoutez une authentification sans interrompre l'expérience du développeur
Les serveurs MCP nécessitent une authentification. La spécification prend en charge OAuth 2.1 pour les flux d'autorisation complets, mais la plupart les outils de développement fonctionnent correctement avec le transfert de clé API. Le développeur ajoute sa clé au client MCP configurer une fois ; le serveur l'extrait des en-têtes de requête et le transmet à chaque appel d'API.
Voici la configuration client pour Claude Desktop avec une clé API :
// Client config: Claude Desktop
{
"mcpServers": {
"botoi": {
"type": "streamable-http",
"url": "https://api.botoi.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Le serveur extrait la clé soit du Authorization en-tête ou le
X-API-Key en-tête, puis le transmet à chaque appel d'API interne :
// server.ts - extract API key from MCP request headers
app.all("/mcp", async (c) => {
const apiKey =
c.req.header("X-API-Key") ||
c.req.header("Authorization")?.replace("Bearer ", "");
// Pass the key through to every API call
const server = createMcpServer(apiKey, c.env);
const transport = new WebStandardStreamableHTTPServerTransport();
await server.connect(transport);
return transport.handleRequest(c.req.raw);
});
Sans clé, le serveur fonctionne toujours. Botoi permet un accès anonyme à 5 requêtes par minute et 100 par jour, suffisant pour une utilisation occasionnelle lors d'une session de codage. Avec une clé, limite l'échelle à la niveau du plan du développeur. Cette approche signifie une intégration sans friction (aucune inscription requise pour l'essayer) avec un chemin de mise à niveau clair lorsque l'utilisation augmente.
La clé API du développeur ne quitte jamais le serveur MCP. Cela va de la configuration client au MCP en-tête de requête à l’appel API interne. Le modèle ne le voit jamais dans le contexte de la conversation.
Bon serveur MCP contre mauvais serveur MCP
| Traite | Mauvais serveur | Bon serveur |
|---|---|---|
| Nombre d'outils | Vide chaque point de terminaison (100+) | Organise des outils de grande valeur (moins de 50 ans) |
| Descriptions des outils | "Est-ce que le DNS fait des trucs" ou des murs de 200 mots | Verbe + ce qu'il fait + déclencheur "Utiliser quand" |
| Annotations | Manquant sur tous les outils | Défini sur chaque outil : readOnly, destructeur, idempotent, openWorld |
| Transport | SSE avec gestion de sessions | HTTP diffusable sans état |
| Validation des entrées | Aucun; plante suite à une mauvaise saisie | Schémas Zod générés à partir de la spécification OpenAPI |
| Réponses aux erreurs | "Quelque chose s'est mal passé" | JSON structuré avec champ, attendu et reçu |
| Authentification | Aucun, ou bloque entièrement l'utilisation anonyme | Transfert de clé API avec repli anonyme et limites de débit |
Le paysage de 10 000 serveurs
La croissance de 1 000 à 10 000 serveurs MCP en six mois s'est produite parce que le protocole s'est stabilisé. OAuth 2.1 a remplacé les modèles d'authentification ad hoc. HTTP diffusable a remplacé SSE. La Fondation Linux la gouvernance a donné aux entreprises la confiance nécessaire pour construire des serveurs de production. SDK en six langues réduits la barrière à l’entrée.
Mais la quantité n’apporte pas la qualité. La plupart de ces serveurs étaient des expériences de week-end qui n'ont jamais abouti. l'étape « enregistrer tous mes points de terminaison et voir ce qui se passe ». Les serveurs que les développeurs utilisent quotidiennement investi dans la conservation, les descriptions, les schémas, la gestion des erreurs et l'authentification. Ces cinq domaines sont ceux où 90 % de l'écart d'utilisabilité vit.
Si vous construisez un serveur MCP en 2026, la barre n'est pas "est-ce que ça marche". La barre est "fait le modèle choisissez le bon outil, comprenez l'erreur en cas de erreur et récupérez sans intervention humaine. Les sept pratiques ci-dessus vous y amènent.
Le serveur MCP de Botoi est ouvert aux tests. Connectez-vous depuis Claude Desktop, Claude Code, Cursor, VS Code, ou Windsurf en utilisant les configurations sur le Page de configuration MCP. Le manifeste complet de l'outil est à api.botoi.com/v1/mcp/tools.json, et le Documents sur l'API couvrent tous les points finaux derrière les outils.
FAQ
- Combien de serveurs MCP existe-t-il en 2026 ?
- L'écosystème MCP comptait 10 000 serveurs publics en avril 2026, contre environ 1 000 fin 2025. La croissance est tirée par la prise en charge stable d'OAuth 2.1, le transport HTTP Streamable remplaçant SSE et l'intégration client dans Claude Desktop, Cursor, Windsurf, Zed, Continue, Sourcegraph Cody et Taskade Genesis.
- Combien d’outils un serveur MCP doit-il exposer ?
- Il n’y a pas de limite stricte, mais moins c’est mieux. Chaque définition d'outil consomme des jetons dans la fenêtre contextuelle du modèle. Un manifeste de 150 outils peut coûter plus de 30 000 jetons avant le début de la conversation. Botoi organise 49 outils à partir de plus de 150 points de terminaison d'API. Visez moins de 50 outils bien décrits, à moins que votre cas d’utilisation n’exige plus.
- Quel transport MCP utiliser en 2026 ?
- HTTP streamable est le transport stable et recommandé. Le transport SSE (Server-Sent Events) est obsolète dans la spécification MCP. Streamable HTTP utilise le HTTP POST standard avec les charges utiles JSON-RPC 2.0, fonctionne avec n'importe quelle infrastructure HTTP (CDN, équilibreurs de charge, environnements d'exécution Edge) et ne nécessite aucune connexion persistante.
- Que sont les annotations de l’outil MCP et pourquoi sont-elles importantes ?
- Les annotations d'outils sont des indications de métadonnées définies dans la spécification MCP : readOnlyHint, destructiveHint, idempotentHint et openWorldHint. Ils indiquent aux modèles d’IA si un outil lit des données, écrit des données, peut réessayer en toute sécurité ou contacte des services externes. Les modèles utilisent ces astuces pour planifier des flux de travail en plusieurs étapes plus sûrs et éviter les appels destructeurs sans confirmation de l'utilisateur.
- Les serveurs MCP ont-ils besoin d'une authentification ?
- Oui. La spécification MCP inclut désormais OAuth 2.1 pour l'authentification. Même pour les configurations plus simples, exigez un jeton Bearer ou une clé API à chaque demande. L'accès anonyme devrait avoir des limites de débit strictes. Botoi permet un accès anonyme à raison de 5 requêtes par minute et 100 par jour, avec des limites plus élevées pour les clés authentifiées.
Commencez a construire avec botoi
150+ endpoints API pour la recherche, le traitement de texte, la generation d'images et les utilitaires pour developpeurs. Offre gratuite, sans carte bancaire.