Créer un MCP Server from scratch : guide complet pour développeurs

Environ 22 min de lecture · MACCOME

Public : développeurs backend ou IA qui veulent brancher Claude, Cursor ou VS Code sur APIs internes, bases de données et fichiers — sans réécrire une couche d'intégration par modèle. Résultat : un MCP Server fonctionnel, du prototype STDIO local au déploiement HTTP+SSE, avec un cas pratique base de connaissances pour workflows créatifs et techniques. Plan : rappel protocole, six erreurs fréquentes, matrices de décision, code Hello World / Tools / Resources / Prompts, débogage, huit étapes de mise en production, écosystème. Pour la couche protocole, voir le deep dive MCP.

Six erreurs qui bloquent votre premier MCP Server

  1. Traiter MCP comme une simple API REST : REST répond « l'appel est-il possible ? » ; MCP standardise la découverte runtime via tools/list, JSON Schema et sessions persistantes.
  2. Implémenter uniquement des Tools : sans Resources (contexte lecture) ni Prompts (modèles), le modèle appelle des outils avec un contexte incomplet — typique dans les workflows montage ou design où les assets ne sont pas exposés.
  3. Garder STDIO en production : les sous-processus locaux tombent quand le Mac se met en veille ou quand PATH diffère entre Terminal et launchd.
  4. Configurer l'auth par client : chaque entrée Cursor/Claude avec son propre jeton multiplie les erreurs et complique l'audit.
  5. Copier des serveurs communautaires sans pinning : environ 1 000 serveurs publics sans auth en 2026 — risque réel pour les pipelines créatifs contenant des médias clients.
  6. Déboguer uniquement dans l'UI : sans logs JSON-RPC structurés, timeouts et erreurs de schéma sont confondus avec des problèmes de canal.

Ce guide est le compagnon pratique du article protocole : ici, vous construisez ; là, vous comprenez pourquoi MCP s'impose comme standard.

Protocole MCP : Host, Client, Server

Le Host (Cursor, Claude Desktop, VS Code) embarque un MCP Client. Le Client maintient une session 1:1 avec chaque MCP Server en JSON-RPC 2.0. Le serveur expose Tools, Resources et Prompts, puis se connecte à vos systèmes — CRM, stockage créatif, Xcode build farm, etc.

CapabilityRôleMéthodes RPCCas d'usage créatif / tech
ToolsActions avec effets de bordtools/list, tools/callExporter une timeline Final Cut, déclencher un build Xcode, créer un ticket Jira
ResourcesContexte lisible (URI)resources/list, resources/readBrand guidelines, LUTs, storyboards Markdown, specs design system
PromptsModèles réutilisablesprompts/list, prompts/getReview colorimétrique, checklist livraison client, triage incident pipeline
TransportUsageContrainte
STDIODev local, poste uniqueDémarrage < 5 ms (bundle épinglé) ; un processus par instance
HTTP + SSEÉquipe distante, partageSession affinity ; TLS au reverse proxy

Étape 1 : préparer l'environnement

Prérequis : Node.js 20 LTS ou Python 3.11+, Git, un Host compatible MCP. Sur Mac Apple Silicon, alignez la version Node/Python entre postes — l'écart d'environnement est la cause n°1 des outils « non enregistrés » dans les studios qui alternent MacBook et Mac mini.

bash
mkdir mcp-hello && cd mcp-hello
npm init -y
npm install @modelcontextprotocol/sdk zod
# Python : python3 -m venv .venv && pip install mcp
SDKPackageAtout sur écosystème Apple
TypeScript@modelcontextprotocol/sdkIntégration Cursor/Claude rapide ; wrappers autour de CLI Apple
PythonmcpPipelines data, transcription, indexation médias

Étape 2 : Hello World en STDIO

Le serveur minimal répond à initialize et enregistre un outil « echo ». Résultat attendu : une entrée visible dans la liste d'outils du Host.

typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "hello-mcp", version: "1.0.0" });

server.tool(
  "echo",
  { message: z.string().describe("Texte à renvoyer") },
  async ({ message }) => ({ content: [{ type: "text", text: message }] })
);

await server.connect(new StdioServerTransport());
json
// ~/.cursor/mcp.json
{
  "mcpServers": {
    "hello-mcp": {
      "command": "node",
      "args": ["/chemin/absolu/mcp-hello/dist/index.js"]
    }
  }
}
info

Validation : chemins absolus pour command/args ; redémarrer le Host après modification. Vérifier tools/list dans l'inspecteur MCP.

Étape 3 : Tools — actions avec JSON Schema

Les Tools exécutent des effets de bord. Chaque outil exige un nom unique, un schéma Zod/JSON et des effets documentés. Exemple : interroger le statut d'un projet créatif dans le CRM.

typescript
server.tool(
  "get_project_status",
  {
    projectId: z.string().uuid(),
    includeDeliverables: z.boolean().default(false),
  },
  async ({ projectId, includeDeliverables }) => {
    const res = await fetch(`${process.env.CRM_BASE}/projects/${projectId}`);
    const data = await res.json();
    return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
  }
);

Bonnes pratiques Tools

  • Séparer lecture et écriture — deux serveurs ou namespaces pour le moindre privilège.
  • Limiter les données client dans les logs ; les médias et métadonnées créatives sont sensibles.
  • Erreurs structurées — le modèle distingue retry et escalade.

Étape 4 : Resources — contexte par URI

Les Resources fournissent des données en lecture. URIs stables : brand://guidelines/v2, kb://tutorial/color-grading.

typescript
server.resource(
  "brand_guide",
  "brand://guidelines/v2",
  async (uri) => ({
    contents: [{
      uri: uri.href,
      mimeType: "text/markdown",
      text: await fs.readFile("./data/brand-guide.md", "utf8"),
    }],
  })
);

Étape 5 : Prompts — workflows standardisés

Les Prompts encapsulent des scénarios récurrents : revue colorimétrique, checklist livraison motion, triage incident. Ils économisent des tokens par rapport aux longs system prompts dans le Host — utile quand Final Cut, Logic ou Xcode partagent le même agent.

typescript
server.prompt(
  "delivery_review",
  {
    project: z.string(),
    format: z.enum(["prores", "h264", "dnxhd"]),
  },
  ({ project, format }) => ({
    messages: [{
      role: "user",
      content: {
        type: "text",
        text: `Revue livraison ${project} (${format}) : specs, safe zones, métadonnées, 3 points bloquants.`,
      },
    }],
  })
);

Étape 6 : HTTP+SSE pour équipes distribuées

Dès qu'une équipe créative partage le même serveur (monteurs à distance, développeurs iOS), passez en HTTP+SSE. Prévoyez TLS, reverse proxy et affinité de session.

typescript
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";

const app = express();
let transport;
app.get("/sse", async (req, res) => {
  transport = new SSEServerTransport("/message", res);
  await server.connect(transport);
});
app.post("/message", express.json(), (req, res) => transport.handlePostMessage(req, res));
app.listen(8787);
Paramètre HTTPDevProduction
TLSlocalhost OKTerminaison nginx/Caddy, HSTS
Timeout 1er appel60 s30 s après prewarm
AuthOptionnelBearer ou OAuth 2.1 au point d'entrée

Étape 7 : débogage et tests

SymptômePreuve à collecterAction
Liste d'outils videCode sortie, stderrChemin absolu ; même utilisateur OS que le Host
Premier appel lentLogs npmÉpingler versions ; prewarm image
Schéma rejetéJSON-RPC -32602Comparer sortie tools/list
Timeout récurrentCPU, FDTool lecture seule en A/B
bash
npx @modelcontextprotocol/inspector node dist/index.js
# Attendu : initialize OK, tools/list >= 1, tools/call echo OK

Étape 8 : déploiement production

  • Process manager : launchd sur macOS avec EnvironmentFile explicite.
  • Secrets : jamais dans mcp.json versionné.
  • Observabilité : logs structurés par tools/call ; métriques p95 et sessions SSE actives.
  • Release : semver sur le serveur ; Host épingle la minor.

Cas pratique : base de connaissances créative

Combinez Resources (guides brand, tutos montage) avec un Tool semantic_search. Flux : le modèle liste les Resources, recherche, cite les URIs — réduit les hallucinations dans les workflows où la charte graphique et les specs techniques doivent rester alignées.

typescript
server.tool(
  "semantic_search",
  { query: z.string().min(3), topK: z.number().int().max(10).default(5) },
  async ({ query, topK }) => {
    const hits = await index.search(query, topK);
    return {
      content: [{
        type: "text",
        text: hits.map(h => `${h.uri}\n${h.snippet}`).join("\n---\n"),
      }],
    };
  }
);

Écosystème 2026 et suites possibles

  • 10 000+ serveurs communautaires — réutiliser avec pinning et revue sécurité.
  • AAIF (Linux Foundation) — gouvernance depuis Q2 2026.
  • A2A complète MCP pour l'orchestration agent-à-agent.
  • Lien avec le guide Agent Skill : Skills = paquets prompt dans le Host ; MCP = protocole d'outils portable.

Huit étapes de zéro à la production

  1. Choisir la stack (TS ou Python) et épingler les versions.
  2. Hello World STDIO validé dans l'inspecteur.
  3. Un Tool lecture + une Resource sur API réelle.
  4. Ajouter un Prompt pour un workflow récurrent (livraison, review, build).
  5. Configurer Cursor/Claude avec chemins absolus.
  6. Prototyper HTTP+SSE si équipe > 1.
  7. Auth, logs, revue sécurité avant données client.
  8. Hôte 7×24 pour sessions longues — pas un MacBook en veille.

Trois repères techniques

  • Coût d'intégration −38 à −55 % — un serveur pour Claude, GPT et Gemini.
  • Cold start STDIO < 5 ms (bundle épinglé) vs 30–60 s avec npx -y non épinglé.
  • 10 000+ serveurs (2026) — effet réseau sur l'écosystème outils.

Conclusion : prototype local vs exploitation stable

Un MCP Server sur le Mac de développement est le bon point de départ pour un studio ou une équipe produit. Trois limites apparaissent vite : les connexions STDIO/SSE coupent en veille, les environnements divergent entre créatifs et développeurs, et les workflows agent multi-étapes (montage automatisé, builds Xcode en chaîne) exigent une disponibilité continue. Les VM génériques sans macOS natif compliquent l'accès aux outchains Apple et aux simulateurs.

Pour des MCP Servers et agents en production — notamment sur workflows créatifs Apple — un nœud MACCOME Mac mini M4 / M4 Pro dédié 7×24 est souvent plus fiable qu'un MacBook local. Tarifs : tarifs location Mac mini ; prise en main : centre d'aide.

Questions fréquentes

Python ou TypeScript pour mon premier MCP Server ?

TypeScript pour Cursor/Claude en STDIO ; Python pour pipelines data et médias. Choisissez selon la stack existante.

STDIO ou HTTP+SSE en production ?

STDIO en solo. HTTP+SSE dès partage d'équipe — TLS, affinité et auth centralisée obligatoires.

MCP et Agent Skills : quelle différence ?

Skills = paquets dans le Host ; MCP = protocole d'outils cross-host. Voir le guide Agent Skill.

Quel hébergement pour MCP en production ?

Évitez la veille du MacBook pour les sessions longues. MACCOME propose des nœuds M4/M4 Pro 7×24. Tarifs et centre d'aide.