Terug naar Journal
6 min leestijd

Standaardisering van AI-integraties met Model Context Protocol (MCP)

Een praktische handleiding voor het bouwen en beveiligen van aangepaste MCP-servers om bedrijfsgegevens veilig te koppelen aan AI-ontwikkelaarsagenten.

AI AgentsMCPNode.jsEnterprise ArchitectureAPI Security
Standaardisering van AI-integraties met Model Context Protocol (MCP)

Het koppelen van grote taalmodellen (LLM's) aan interne gegevensbronnen en systemen is historisch gezien een gefragmenteerde ad-hoc klus geweest. Elk AI-ontwikkelingsproject begint meestal met het schrijven van aangepaste API-wrappers, het in kaart brengen van JSON-schema's of het schrijven van eigen lijmcode binnen orkestratie-runtimes om tool-aanroepen te beheren.

Als je overstapt van OpenAI naar Anthropic, of als je ontwikkelaars overstappen van de ene AI-gestuurde IDE naar de andere, moet je vaak de integratielaag herschrijven.

Deze wrijving is de reden waarom het Model Context Protocol (MCP), een open standaard onder leiding van Anthropic, snel terrein wint. Net zoals het Language Server Protocol (LSP) standaardiseerde hoe compilers communiceren met code-editors, standaardiseert MCP hoe AI-modellen communiceren met gegevensbronnen en ontwikkelaarstools.

Hier is een praktische handleiding voor het bouwen, structureren en beveiligen van een aangepaste MCP-server om bedrijfsgegevens veilig bloot te stellen aan je ontwikkelaarsagenten.


De architectuur: ontkoppeling van clients en servers

Het kernontwerpprincipe van MCP is ontkoppeling. In plaats van API-integraties rechtstreeks in de runtime van een agent te coderen, introduceert MCP een client-serverarchitectuur:

[ AI Agent / IDE ] (MCP Client)
       │
       │ (JSON-RPC 2.0 over Stdio or SSE)
       ▼
[ Custom MCP Server ]
       │
       ├─► Secure Database (PostgreSQL / BigQuery)
       ├─► Internal Microservices
       └─► Local Development Tools
  • MCP Client: De coördinator (bijv. Cursor, Windsurf of een aangepaste LangChain-orchestrator). Deze beheert de LLM-redenering, houdt gebruikerscontext bij en start tool-aanvragen.
  • MCP Server: Een lichtgewicht proces of service die drie kernprimitieven blootstelt:
    1. Prompts: Herbruikbare sjablonen voor het sturen van modelinteracties.
    2. Resources: Alleen-lezen gegevensbronnen (bestandsinhoud, databaserijen, API-antwoorden).
    3. Tools: Uitvoerbare functies die bewerkingen kunnen uitvoeren of externe API's kunnen aanroepen.

Een aangepaste MCP-server bouwen in TypeScript

Laten we een productierijpe Node.js MCP-server bouwen met de officiële TypeScript-SDK. Deze server zal een beveiligde tool blootstellen om te zoeken in interne databasegegevens (bijvoorbeeld kandidaten of casestudy's) met ingebouwde runtime argumentvalidatie.

1. Projectinitialisatie

Stel eerst een TypeScript-project in en installeer de benodigde afhankelijkheden:

npm init -y
npm install @modelcontextprotocol/sdk zod
npm install --save-dev typescript @types/node
npx tsc --init

2. Serverimplementatie

Hieronder staat de code voor een beveiligde, stdio-gebaseerde MCP-server. We registreren een zoektool en gebruiken zod om strikte schemavalidatie af te dwingen op inkomende payloads:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";

// 1. Initialize the MCP Server
const server = new Server(
  {
    name: "enterprise-search-service",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {}, // Advertise tool capabilities to the client
    },
  }
);

// 2. Define the Search Schema using Zod
const CandidateSearchSchema = z.object({
  query: z.string().min(2),
  limit: z.number().optional().default(5),
  department: z.enum(["Engineering", "Design", "Product", "Sales"]).optional(),
});

// 3. Register Available Tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "search_candidates",
        description: "Search internal database for candidates matching specific skills and departments.",
        inputSchema: {
          type: "object",
          properties: {
            query: { type: "string", description: "Search term or required skill" },
            limit: { type: "number", description: "Maximum records to return" },
            department: { type: "string", enum: ["Engineering", "Design", "Product", "Sales"] },
          },
          required: ["query"],
        },
      },
    ],
  };
});

// Mock database resolver
async function queryDatabase(query: string, limit: number, dept?: string) {
  // Real implementation would connect to Cloud SQL / BigQuery
  return [
    { id: 101, name: "Sarah Connor", role: "Staff Platform Engineer", tags: ["Kubernetes", "Go", "MACH"] },
    { id: 102, name: "Marcus Wright", role: "Solutions Architect", tags: ["Next.js", "React", "AI Agents"] }
  ];
}

// 4. Handle Tool Executions
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name !== "search_candidates") {
    throw new Error(`Tool ${request.params.name} not found`);
  }

  try {
    // Validate the arguments at runtime
    const args = CandidateSearchSchema.parse(request.params.arguments);

    // Fetch secure records
    const results = await queryDatabase(args.query, args.limit, args.department);

    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(results, null, 2),
        },
      ],
    };
  } catch (error: any) {
    return {
      content: [
        {
          type: "text",
          text: `Error validating arguments: ${error.message}`,
        },
      ],
      isError: true,
    };
  }
});

// 5. Start Server Transport (stdio is standard for local IDE integrations)
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Enterprise Search MCP Server running on stdio");

Beveiliging aanscherpen voor zakelijk gebruik

Hoewel het schrijven van de TypeScript-code eenvoudig is, vereist het blootstellen van interne productiegerelateerde gegevens aan LLM's strikte operationele beveiligingsmaatregelen. AI-modellen zijn gevoelig voor hallucinaties, prompt-injecties en onbedoelde tool-uitvoeringslussen.

Dit zijn de vier pijlers van MCP-beveiliging in zakelijke omgevingen:

1. Schemavalidatie en invoersanitatie

Vertrouw nooit argumenten die door een LLM zijn gegenereerd. Valideer parameters altijd met bibliotheken zoals Zod, en zuiver tekenreeksen om database-risico's te voorkomen:

  • Gebruik geparametriseerde query's of ORM's om SQL-injectie te voorkomen.
  • Valideer directorypaden om directory-traversal-exploits te voorkomen als je tool lokale bestanden leest.

2. Authenticatie en OAuth-contextoverdracht

Wanneer je binnen een bedrijfsnetwerk draait, moet je het autorisatieniveau verifiëren van de gebruiker achter de agent.

  • Exposeer MCP via Server-Sent Events (SSE) in plaats van stdio. Hiermee kan de MCP-server als een onafhankelijke microservice achter een API Gateway draaien.
  • Stuur het identiteitstoken (JWT) van de gebruiker mee in de aanvraagheaders, zodat je MCP-server Row-Level Security (RLS) kan afdwingen in de doeldatabase.

3. Human-in-the-Loop (HITL) goedkeuringen

Het blootstellen van leestools (zoals search_candidates) brengt weinig risico met zich mee. Het blootstellen van schrijftools (zoals update_records of deploy_service) is echter gevaarlijk.

  • Implementeer expliciete goedkeuringen voor schrijfacties. De MCP-client moet schrijfaanvragen onderscheppen en de ontwikkelaar een diff tonen met de wijzigingen die de agent wil doorvoeren.
[ Agent Tool Request ] ──► [ Security Middleware ] ──► (Diff Check / UI Popup)
                                                             │
                  ┌──────────────────────────────────────────┘
                  ▼
         [ User Approves? ] ──(Yes)──► [ Execute Write on Server ]

4. Ratenbegrenzing en vangrails

Agenten kunnen in recursieve redeneerlussen terechtkomen waarin ze een tool tientallen keren in een paar seconden aanroepen, wat leidt tot zware databasebelasting of hoge tokenkosten.

  • Dwing een limiet af op de aanvraagfrequentie (rate limiting) per sessie.
  • Beperk de maximale grootte van resultaten om token-overloop te voorkomen.

Blik vooruit: Legacy-systemen blootstellen als AI-primitieven

De kracht van het Model Context Protocol is dat het legacy software-interfaces transformeert in schone, vindbare mogelijkheden.

Door interne databases, implementatiescripts en API's in een gestandaardiseerde MCP-laag in te kapselen, zorg je ervoor dat elke AI-tool – of het nu een editor als Cursor, een terminalhulp of een autonome implementatieagent is – veilig, voorspelbaar en zonder extra vertaalkosten met je bedrijfslogica kan communiceren.

Share this article