Accueil / Articles / Notes pratiques : Les outils MCP au sein des applications d’entreprise : adapté aux débutants

Notes pratiques : Les outils MCP au sein des applications d’entreprise : adapté aux débutants

Guide pratique pas à pas : Outils MCP au sein des applications d’entreprise – Adapté aux débutants : contrats, vérifications et emplacements de code prêts à l’emploi pour les équipes qui utilisent ce modèle.

2925 mots

Les notes suivantes reconstituent une approche pratique pour aborder le sujet « MCP Tools Inside Enterprise Applications: A Beginner-Friendly Deep Dive ». L’accent est mis sur les contrats, les vérifications et les placeholders de code à insérer, plutôt que sur une présentation motivante. Lors de l’étape d’aperçu, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux éléments générés, définez les vérifications de succès et refusez toute exécution partielle silencieuse.

1. Le problème : pourquoi les entreprises avaient besoin de MCP en premier lieu

Le problème est que cette étape fonctionne le mieux lorsqu’elle est traitée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec ainsi que la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Mettez à disposition des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.

BEFORE MCP — the N x M integration problem

  ┌───────────┐        ┌─────────────┐
  │  Agent A  │───────▶│  CRM API    │  (custom connector #1)
  └───────────┘        └─────────────┘
  ┌───────────┐        ┌─────────────┐
  │  Agent A  │───────▶│  Ticketing  │  (custom connector #2)
  └───────────┘        └─────────────┘
  ┌───────────┐        ┌─────────────┐
  │  Agent B  │───────▶│  CRM API    │  (custom connector #3 -
  └───────────┘        └─────────────┘   yes, AGAIN, for a different agent)
  ┌───────────┐        ┌─────────────┐
  │  Agent B  │───────▶│  Data       │  (custom connector #4)
  └───────────┘        │  Warehouse  │
                       └─────────────┘
  N agents x M systems = N x M custom, non-reusable integrations.
  Every new agent re-implements auth, retries, schemas, error handling.
AFTER MCP — one protocol, many servers, many clients

  ┌───────────┐                          ┌───────────────────┐
  │  Agent A  │──┐                   ┌─▶│  MCP Server: CRM   │
  └───────────┘  │    ┌───────────┐  │   └───────────────────┘
                 ├───▶│    MCP   │───┤  ┌───────────────────┐
  ┌───────────┐  │    │  (shared  │  ├─▶│ MCP Server: Ticket │
  │  Agent B  │──┘    │  protocol)│  │   └───────────────────┘
  └───────────┘       └───────────┘  │  ┌──────────────────┐
                                     └─▶│ MCP Server: DW   │
                                        └──────────────────┘
  Any MCP-compatible agent can now talk to any MCP server.
  Build the connector once, reuse it everywhere.

2. Concepts fondamentaux, expliqués simplement

La phase « Explication des 2 concepts fondamentaux » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état du système avant de les valider automatiquement.

Les trois primitives qu’un serveur peut exposer

Ces trois primitives fonctionnent le mieux lorsqu’une étape est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement. Ces trois primitives fonctionnent le mieux lorsqu’une étape est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez toute complétion partielle silencieuse.

3. L’architecture, les trois couches ensemble

Pour la phase « Architecture All », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le parcours passe d’un environnement de démonstration à des environnements partagés. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple jeton porteur ne constitue pas une frontière entre les tenants.

┌─────────────────────────── HOST APPLICATION ───────────────────────────┐
│   e.g. an internal AI assistant, IDE plugin, support copilot           │
│                                                                        │
│   ┌───────────────┐        ┌───────────────┐       ┌───────────────┐   │
│   │  MCP Client 1 │        │  MCP Client 2 │       │  MCP Client 3 │   │
│   └───────┬───────┘        └───────┬───────┘       └───────┬───────┘   │
└───────────┼────────────────────────┼───────────────────────┼───────────┘
            │ JSON-RPC over          │ JSON-RPC over         │ JSON-RPC over
            │ stdio / HTTPS          │ stdio / HTTPS         │ stdio / HTTPS
            ▼                        ▼                       ▼
   ┌──────────────────┐     ┌──────────────────┐     ┌─────────────────┐
   │   MCP Server     │     │   MCP Server     │     │   MCP Server    │
   │  wraps HR system │     │  wraps Ticketing │     │  wraps Data     │
   │  (tools: lookup, │     │  (tools: create, │     │  Warehouse      │
   │   update)        │     │   status, close) │     │  (tools: query) │
   └──────────────────┘     └──────────────────┘     └─────────────────┘

4. Création de votre premier serveur MCP (Node.js / TypeScript)

Pour l’étape 4 « Construire votre premier projet », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.

4.1 Configuration du projet

Pendant la phase de mise en place du projet 4 1, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations ultérieures. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.

mkdir helpdesk-mcp-server && cd helpdesk-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript tsx @types/node
npx tsc --init

Pendant la phase de mise en place du projet 4 1, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définissez des vérifications de succès et refusez les terminations partielles silencieuses.

4.2 Le code du serveur

Lors de la phase 4.2 relative au serveur, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite des factures inattendues lorsque le système passe de l’environnement de démonstration à des environnements partagés. Journalisez le nom outil, l’hash des arguments, la latence et le résultat de chaque appel. Sans ce suivi, le débogage de boucles peut prendre des heures.

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

// --- A stand-in for a real internal ticketing API client ---
// In a real enterprise server this would call your ITSM system
// (ServiceNow, Jira Service Management, Zendesk, an internal API, etc.)
const ticketStore = new Map<string, { status: string; subject: string }>();
let nextId = 1000;
// 1. Create the server instance.
//    "name" and "version" identify this server to any client that connects.
const server = new McpServer({
  name: "helpdesk-mcp-server",
  version: "1.0.0",
});
// 2. Register a tool: create_support_ticket
server.registerTool(
  "create_support_ticket",
  {
    title: "Create Support Ticket",
    description:
      "Creates a new IT helpdesk ticket for the requesting employee.",
    inputSchema: {
      subject: z.string().describe("Short summary of the issue"),
      priority: z.enum(["low", "medium", "high", "urgent"]),
      employeeId: z.string().describe("Requesting employee's ID"),
    },
    outputSchema: {
      ticketId: z.string(),
      status: z.string(),
    },
  },
  async ({ subject, priority, employeeId }) => {
    const ticketId = `TCK-${nextId++}`;
    ticketStore.set(ticketId, { status: "open", subject });
    const output = { ticketId, status: "open" };
    // MCP tool results return a "content" array (what a human/LLM reads)
    // and, optionally, "structuredContent" (typed data other code can use).
    return {
      content: [
        {
          type: "text",
          text: `Created ticket ${ticketId} (priority: ${priority}) for employee ${employeeId}.`,
        },
      ],
      structuredContent: output,
    };
  }
);
// 3. Register a second tool: get_ticket_status
server.registerTool(
  "get_ticket_status",
  {
    title: "Get Ticket Status",
    description: "Looks up the current status of an existing support ticket.",
    inputSchema: {
      ticketId: z.string(),
    },
    outputSchema: {
      status: z.string(),
    },
  },
  async ({ ticketId }) => {
    const ticket = ticketStore.get(ticketId);
    if (!ticket) {
      // Returning isError lets the model know the call failed
      // WITHOUT crashing the whole conversation.
      return {
        content: [{ type: "text", text: `No ticket found with ID ${ticketId}.` }],
        isError: true,
      };
    }
    return {
      content: [{ type: "text", text: `Ticket ${ticketId} is currently "${ticket.status}".` }],
      structuredContent: { status: ticket.status },
    };
  }
);
// 4. Wire the server to a transport and start listening.
//    stdio is perfect for local development and desktop-hosted tools.
const transport = new StdioServerTransport();
await server.connect(transport);

4.3 Ce qui se passe réellement ici (théorie ligne par ligne)

Lorsque vous travaillez sur l’étape 4 3 What’s, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage des boucles d’agent prend des heures inutilement.

4.4 Le lancement

Lors de la phase « Le faire fonctionner » du cadre 4 4, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage des boucles d’agent prend des heures inutilement.

npx tsx src/server.ts

Lors de la phase « Le faire fonctionner » du cadre 4 4, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses.

5. Création d’un client MCP au sein d’une application d’entreprise

La phase 5 de création d’un MCP fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et des notes de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le projet passe de la démonstration aux environnements partagés.

// src/client.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

async function main() {
  // 1. Describe how to launch the server. Here we spawn it as a
  //    local subprocess - in production you'd more commonly point
  //    this at a remote HTTP-based server instead (see Section 6).
  const transport = new StdioClientTransport({
    command: "npx",
    args: ["tsx", "src/server.ts"],
  });
  // 2. Create a client and connect. This performs the MCP
  //    handshake and capability negotiation automatically.
  const client = new Client({ name: "internal-ai-assistant", version: "1.0.0" });
  await client.connect(transport);
  // 3. Discover what tools this server offers - this is the same
  //    mechanism an LLM uses to "learn" what it can do.
  const { tools } = await client.listTools();
  console.log("Available tools:", tools.map((t) => t.name));
  // 4. Call a tool, just like the LLM would.
  const result = await client.callTool({
    name: "create_support_ticket",
    arguments: {
      subject: "VPN keeps disconnecting",
      priority: "high",
      employeeId: "E-4821",
    },
  });
  console.log(result.content);
  await client.close();
}
main();

Pourquoi c’est important sur le plan conceptuel

La phase « Pourquoi c’est important sur le plan conceptuel » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état du système avant de les valider automatiquement.

6. Du prototype local au déploiement d’entreprise

La phase « 6 From Local Prototype » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement. La phase « 6 From Local Prototype » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute complétion partielle silencieuse.

// src/httpServer.ts
import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";

const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
  // In a real enterprise deployment, authentication middleware would
  // run BEFORE this point - verifying a bearer token, checking scopes,
  // and attaching the caller's identity to the request.
  const server = buildHelpdeskServer(); // same registerTool calls as before
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: undefined, // stateless mode: simplest to scale horizontally
  });
  res.on("close", () => transport.close());
  await server.connect(transport);
  await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => console.log("MCP server listening on :3000"));

7. Liste de contrôle des considérations de niveau entreprise

Pour l’étape 7 du tableau de contrôle des considérations de niveau entreprise, définissez les entrées, le responsable de l’étape et les critères d’achèvement avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple jeton porteur ne constitue pas une frontière entre les tenants.

8. Où cela se retrouve dans des cas d’usage réels en entreprise

Pour l’étape 8 « Where This Shows », définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.

9. Erreurs courantes auxquelles se heurtent les débutants

Pour l’étape des 9 erreurs courantes pour les débutants, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants. Pour l’étape des 9 erreurs courantes pour les débutants, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définissez des vérifications de succès et refusez les terminations partielles silencieuses.

10. Conclusion

Lors de l’étape des 10 points de clôture, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Conservez le nom outil, l’hash des arguments, la latence et le résultat de chaque appel. Sans ce suivi, le débogage de boucles d’agent prend des heures inutilement.

Liste de contrôle opérationnelle

Pour l’étape de la liste de contrôle opérationnelle, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché.

Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité et non un processus embrouillé.

Authentifiez à la passerelle et réautorisez au niveau du plan de données. Un jeton porteur seul ne constitue pas une frontière entre les tenants.

Rédigez un guide de procédures succinct : comment rotationner les clés, comment vider la file d’attente, comment annuler la dernière ingestion.

Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès, et refusez toute exécution partielle silencieuse.

Authentifiez à la passerelle et réautorisez au niveau du plan de données. Un jeton porteur seul ne constitue pas une frontière entre les tenants.

Au préalable de promouvoir l’ensemble technique, figez les versions, conservez une transcription exemplaire pour le chemin critique, et vérifiez les étapes de réversion. Les environnements partagés nécessitent des limites de débit, des contrôles d’attribution, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité solide à des démonstrations brillantes mais ponctuelles.

Note de batch pour 100916d5ed60 : gardez les clés du fournisseur hors du répertoire, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers de configuration d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.