Zum Hauptinhalt springen
IngenieurwesenMar 28, 2026

Ihren ersten MCP-Server erstellen: Praxisleitfaden fuer Entwickler

OS
Open Soft Team

Engineering Team

Was ist das Model Context Protocol (MCP)?

Das Model Context Protocol (MCP) ist ein offener Standard, der von Anthropic entwickelt wurde und definiert, wie AI-Anwendungen mit externen Datenquellen und Tools kommunizieren. Stellen Sie sich MCP als USB-C fuer die AI-Integration vor: So wie USB-C einen einzigen universellen Anschluss fuer Laden, Datenuebertragung und Bildschirmausgabe bietet, stellt MCP ein einziges universelles Protokoll bereit, um AI-Modelle mit Datenbanken, APIs, Dateisystemen und anderen Diensten zu verbinden. MCP eliminiert den Bedarf an individuellen Integrationen zwischen jeder AI-Anwendung und jedem Tool.

Im Jahr 2026 ist MCP zum dominierenden Standard fuer die AI-Tool-Kommunikation geworden. Gartner prognostiziert, dass 40 % der Unternehmensanwendungen bis Ende 2026 AI-Agenten enthalten werden, und MCP ist das Protokoll, das dies in grossem Massstab praktikabel macht. Vor MCP erforderte die Verbindung eines AI-Modells mit N Tools N individuelle Integrationen. Bei M AI-Anwendungen und N Tools benoetigte man M x N Integrationsadapter. MCP reduziert dies auf M + N: Jede AI-App implementiert einen MCP Client, jedes Tool implementiert einen MCP Server.

MCP-Architektur: Host, Client, Server und Transport

Das Verstaendnis der MCP-Architektur ist wesentlich, bevor Sie Code schreiben. Das Protokoll definiert vier Schluesselrollen:

KomponenteRolleBeispiel
HostDie AI-Anwendung, mit der Endbenutzer interagierenClaude Desktop, Cursor, VS Code Copilot
ClientDer MCP-Protokollhandler innerhalb des HostsIn die Host-Anwendung eingebaut
ServerStellt Tools, Resources und Prompts ueber MCP bereitIhr benutzerdefinierter Server (den wir erstellen)
TransportDie Kommunikationsschicht zwischen Client und Serverstdio, HTTP+SSE, Streamable HTTP

Der Kommunikationsfluss funktioniert folgendermassen:

  1. Der Host startet und initialisiert einen MCP Client fuer jeden konfigurierten Server.
  2. Der Client verbindet sich mit dem Server ueber einen Transport (stdio fuer lokal, HTTP fuer remote).
  3. Der Client sendet eine initialize-Anfrage und handelt Protokollversion und Faehigkeiten aus.
  4. Der Server antwortet mit seinen verfuegbaren Tools, Resources und Prompts.
  5. Wenn das AI-Modell externe Daten oder Aktionen benoetigt, ruft der Client die entsprechende Server-Methode auf.
  6. Der Server fuehrt die Operation aus und gibt Ergebnisse ueber JSON-RPC 2.0-Nachrichten zurueck.

Tools vs Resources vs Prompts

MCP-Server koennen drei Arten von Faehigkeiten bereitstellen:

  • Tools sind Funktionen, die das AI-Modell aufrufen kann. Sie akzeptieren strukturierte Eingaben und geben strukturierte Ausgaben zurueck. Beispiel: query_database(sql: string) oder send_email(to: string, subject: string, body: string).
  • Resources sind Daten, die das AI-Modell lesen kann. Sie werden durch URIs identifiziert und geben Inhalte zurueck. Beispiel: file:///path/to/document.md oder postgres://localhost/mydb/users.
  • Prompts sind wiederverwendbare Prompt-Vorlagen, die der Server bereitstellt. Sie helfen bei der Standardisierung der Interaktion der AI mit der Domaene des Servers. Beispiel: eine summarize_ticket-Vorlage fuer einen Jira MCP Server.

Schritt fuer Schritt: MCP-Server in TypeScript erstellen

Lassen Sie uns einen praktischen MCP-Server erstellen, der ein Tool zum Abfragen einer SQLite-Datenbank bereitstellt. Dies ist ein haeufiger Anwendungsfall: einem AI-Modell sicheren, schreibgeschuetzten Zugriff auf Ihre Anwendungsdaten zu geben.

Schritt 1: Projekt initialisieren

mkdir mcp-sqlite-server && cd mcp-sqlite-server
npm init -y
npm install @modelcontextprotocol/sdk better-sqlite3
npm install -D typescript @types/node @types/better-sqlite3
npx tsc --init

tsconfig.json konfigurieren:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "declaration": true
  },
  "include": ["src/**/*"]
}

Schritt 2: Server implementieren

src/index.ts erstellen:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import Database from "better-sqlite3";
import { z } from "zod";

const db = new Database(process.env.DB_PATH || "./data.db", {
  readonly: true,
});

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

server.tool(
  "query",
  "Fuehrt eine schreibgeschuetzte SQL-Abfrage auf der SQLite-Datenbank aus",
  {
    sql: z.string().describe("Die auszufuehrende SQL SELECT-Abfrage"),
  },
  async ({ sql }) => {
    const normalized = sql.trim().toUpperCase();
    if (!normalized.startsWith("SELECT")) {
      return {
        content: [{ type: "text", text: "Fehler: Nur SELECT-Abfragen sind erlaubt." }],
        isError: true,
      };
    }
    try {
      const rows = db.prepare(sql).all();
      return {
        content: [{ type: "text", text: JSON.stringify(rows, null, 2) }],
      };
    } catch (error) {
      return {
        content: [{ type: "text", text: `Abfragefehler: ${(error as Error).message}` }],
        isError: true,
      };
    }
  }
);

server.tool(
  "list_tables",
  "Listet alle Tabellen in der Datenbank mit ihren Schemas auf",
  {},
  async () => {
    const tables = db
      .prepare(
        `SELECT name, sql FROM sqlite_master
         WHERE type='table' AND name NOT LIKE 'sqlite_%'
         ORDER BY name`
      )
      .all();
    return {
      content: [{ type: "text", text: JSON.stringify(tables, null, 2) }],
    };
  }
);

Schritt 3: Kompilieren und lokal testen

npx tsc
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | node dist/index.js

Sie sollten eine JSON-RPC-Antwort mit den Faehigkeiten des Servers sehen.

Schritt 4: Denselben Server in Python erstellen

Fuer Python-Entwickler zeigen wir hier die aequivalente Implementierung mit dem offiziellen MCP Python SDK:

import sqlite3
import json
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("sqlite-query")
DB_PATH = "data.db"

@mcp.tool()
def query(sql: str) -> str:
    """Fuehrt eine schreibgeschuetzte SQL-Abfrage auf der SQLite-Datenbank aus."""
    normalized = sql.strip().upper()
    if not normalized.startswith("SELECT"):
        raise ValueError("Nur SELECT-Abfragen sind erlaubt.")
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    try:
        cursor = conn.execute(sql)
        rows = [dict(row) for row in cursor.fetchall()]
        return json.dumps(rows, indent=2, default=str)
    finally:
        conn.close()

@mcp.tool()
def list_tables() -> str:
    """Listet alle Tabellen in der Datenbank mit ihren Schemas auf."""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    try:
        cursor = conn.execute(
            "SELECT name, sql FROM sqlite_master "
            "WHERE type='table' AND name NOT LIKE 'sqlite_%'"
        )
        tables = [dict(row) for row in cursor.fetchall()]
        return json.dumps(tables, indent=2)
    finally:
        conn.close()

if __name__ == "__main__":
    mcp.run(transport="stdio")

Verbindung mit Claude Desktop

Claude Desktop unterstuetzt MCP-Server nativ. Um Ihren Server zu verbinden, bearbeiten Sie die Claude Desktop-Konfigurationsdatei:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "sqlite-query": {
      "command": "node",
      "args": ["/absolute/path/to/dist/index.js"],
      "env": {
        "DB_PATH": "/absolute/path/to/your/data.db"
      }
    }
  }
}

Starten Sie Claude Desktop neu. Sie sehen ein Hammer-Symbol in der Chat-Oberflaeche, das verfuegbare MCP-Tools anzeigt. Jetzt koennen Sie Claude Fragen stellen wie „Welche Tabellen gibt es in der Datenbank?“ oder „Zeige mir die 10 neuesten Benutzer nach Registrierungsdatum“ und Claude wird Ihren MCP-Server verwenden, um die Datenbank direkt abzufragen.

Verbindung mit Cursor

Cursor unterstuetzt ebenfalls MCP-Server. Fuegen Sie die Konfiguration in .cursor/mcp.json im Stammverzeichnis Ihres Projekts hinzu:

{
  "mcpServers": {
    "sqlite-query": {
      "command": "node",
      "args": ["./dist/index.js"],
      "env": {
        "DB_PATH": "./data.db"
      }
    }
  }
}

Nach dem Speichern starten Sie Cursor neu. Die MCP-Tools erscheinen im AI-Assistenten-Panel und koennen waehrend der Codegenerierung und Debugging-Sitzungen aufgerufen werden.

Testen und Debuggen Ihres MCP-Servers

Verwendung des MCP Inspector

Der MCP Inspector ist das offizielle Debugging-Tool. Er bietet eine Web-Oberflaeche zur Interaktion mit Ihrem Server:

npx @modelcontextprotocol/inspector node dist/index.js

Dies oeffnet eine Browser-Oberflaeche unter http://localhost:5173, wo Sie:

  • Alle registrierten Tools, Resources und Prompts anzeigen koennen
  • Tools mit benutzerdefinierten Eingaben aufrufen und Antworten ueberpruefen koennen
  • Den JSON-RPC-Nachrichtenstrom in Echtzeit ueberwachen koennen
  • Die Fehlerbehandlung durch Senden fehlerhafter Anfragen testen koennen

Haeufige Debugging-Probleme

ProblemUrsacheLoesung
Server erscheint nicht in Claude DesktopKonfigurationspfad oder JSON-SyntaxfehlerJSON validieren, absolute Pfade ueberpruefen
Fehler „Tool not found“Tools nicht vor der Verbindung registriertTools vor dem Aufruf von server.connect() registrieren
Timeout bei Tool-AufrufenLangandauernde Operation ohne FortschrittFortschrittsbenachrichtigungen ueber server.sendProgress() hinzufuegen
stderr-Ausgabe beschaedigt das Protokollconsole.log schreibt auf stdout (stdio-Transport)console.error() fuer Logging bei stdio verwenden
Verbindungsabbruch nach InaktivitaetTransport-TimeoutHeartbeat implementieren oder HTTP-Transport verwenden

Best Practices fuer die Produktion

  1. Eingabevalidierung: Validieren und bereinigen Sie immer Tool-Eingaben. Verwenden Sie Zod-Schemas (TypeScript) oder Pydantic-Modelle (Python) fuer strenge Typueberpruefung.

  2. Standardmaessig schreibgeschuetzt: Beginnen Sie mit schreibgeschuetztem Zugriff. Fuegen Sie Schreibfaehigkeiten nur hinzu, wenn sie wirklich benoetigt werden, und fordern Sie immer eine Bestaetigung fuer destruktive Operationen an.

  3. Fehlerbehandlung: Geben Sie strukturierte Fehlermeldungen mit isError: true zurueck. Legen Sie niemals interne Stack-Traces oder Datenbank-Verbindungsstrings offen.

  4. Protokollierung: Protokollieren Sie alle Tool-Aufrufe mit Zeitstempel, Eingaben und Ausfuehrungsdauer. Verwenden Sie stderr fuer die Protokollierung (nicht stdout) bei stdio-Transport.

  5. Ratenbegrenzung: Implementieren Sie Tool-spezifische Ratenbegrenzungen, um zu verhindern, dass unkontrollierte AI-Schleifen Ihre Backend-Dienste ueberlasten.

  6. Timeout: Setzen Sie Ausfuehrungs-Timeouts fuer alle Tool-Handler. AI-Modelle koennen Tools aufrufen, die teure Abfragen ausloesen — schuetzen Sie Ihre Infrastruktur.

  7. Umgebungstrennung: Verwenden Sie Umgebungsvariablen fuer alle Konfigurationen. Codieren Sie niemals Datenbank-URLs, API-Schluessel oder Dateipfade fest ein.

  8. Versionierung: Verwenden Sie semantische Versionierung fuer Ihren MCP-Server. Der initialize-Handshake umfasst eine Versionsverhandlung — inkompatible Aenderungen erfordern einen Major-Versionsbump.

FAQ

F: Was ist der Unterschied zwischen MCP und Function Calling? A: Function Calling (verwendet von OpenAI, Anthropic und anderen) definiert Tools inline in jeder API-Anfrage. MCP externalisiert Tool-Definitionen auf eigenstaendige Server, die von MCP-kompatiblen Hosts entdeckt und genutzt werden. Function Calling ist pro Anfrage; MCP ist ein persistentes Protokoll mit Stateful Sessions.

F: Kann ich MCP mit anderen Modellen als Claude verwenden? A: Ja. MCP ist ein offenes Protokoll. OpenAI, Google DeepMind und Microsoft haben seit Anfang 2026 MCP-Unterstuetzung in ihre Plattformen integriert. Jede AI-Anwendung, die einen MCP Client implementiert, kann sich mit jedem MCP Server verbinden.

F: Ist MCP nur fuer lokale Tools? A: Nein. Obwohl der stdio-Transport fuer lokale Server konzipiert ist, unterstuetzen die HTTP+SSE- und Streamable-HTTP-Transporte entfernte MCP-Server. Sie koennen einen MCP-Server als netzwerkzugaenglichen Cloud-Dienst bereitstellen.

F: Wie handhabt MCP die Authentifizierung? A: Das Protokoll unterstuetzt OAuth 2.0 fuer entfernte Server. Lokale stdio-Server erben den Sicherheitskontext des Host-Prozesses. Fuer Enterprise-Deployments kann ein MCP-Gateway die Authentifizierung und Autorisierung zentralisieren.

F: Welche Sprachen koennen zum Erstellen eines MCP-Servers verwendet werden? A: Offizielle SDKs sind fuer TypeScript, Python, Java, Kotlin, C# und Swift verfuegbar. Community-SDKs umfassen Rust, Go, Ruby und PHP. Das Protokoll ist sprachunabhaengig — jede Sprache, die JSON-RPC ueber stdio oder HTTP lesen/schreiben kann, kann einen MCP-Server implementieren.

F: Wie aktualisiert man einen MCP-Server ohne den Host neu zu starten? A: MCP unterstuetzt Faehigkeitsaenderungs-Benachrichtigungen. Wenn sich die Tools Ihres Servers aendern, kann der Server eine notifications/tools/list_changed-Nachricht senden, die den Client auffordert, die Tool-Liste erneut abzurufen. Bei stdio-Servern muss der Host normalerweise neu gestartet werden. HTTP-Server koennen ohne Host-Neustart aktualisiert werden.