MCP-Server-Entwicklung: Ihren ersten MCP-Dienst von Grund auf aufsetzen

Einleitung: Schreiben Sie Code in Cursor und wünschen Sie sich, dass die KI direkt die neueste Version Ihrer Projektabhängigkeiten nachschlägt? Oder analysieren Sie Daten in Claude und möchten, dass sie Informationen aus Ihrer Datenbank liest? Ohne MCP müssten Sie für jedes KI-Tool eine eigene Anpassungsschicht schreiben. Mit einem MCP Server reicht ein einziger Dienst – alle MCP-fähigen Clients können ihn nutzen. Dieser Artikel führt Sie von null an durch die Entwicklung eines vollständigen MCP Servers mit TypeScript.
Was ist MCP? Kernkonzepte in 3 Minuten
Die Geschichte eines USB-Anschlusses
Wer vor ein paar Jahren digitale Geräte genutzt hat, erinnert sich an die unbequeme Phase: Maus mit rundem Stecker, Tastatur mit eckigem, Drucker mit Parallelanschluss – jedes Gerät brauchte seinen eigenen Port. Dann kam USB und löste alles mit einem einzigen Anschluss.
MCP (Model Context Protocol) wird zum „USB-Standard“ der KI-Tool-Welt.
Ohne MCP brauchen Sie für jede Datenquelle eine eigene Anpassungsschicht: ein Plugin für Claude, eine Erweiterung für Cursor, noch eine für Windsurf … Die Komplexität ist N × M (N Datenquellen × M KI-Tools).
Mit MCP schreiben Sie einen MCP Server – alle MCP-fähigen Clients können ihn direkt aufrufen. Die Komplexität sinkt auf N + M.
Die Drei-Schichten-Architektur ist einfach:
+-------------+ +-------------+ +-------------+
| Host | -> | Client | -> | Server |
| (Claude) | | (MCP-Client)| | (Ihr Dienst)|
+-------------+ +-------------+ +-------------+
- Host: Die KI-Anwendung selbst, z. B. Claude Desktop oder Cursor
- Client: MCP-Client, kommuniziert mit dem Host
- Server: Ihr eigener Dienst mit den konkreten Funktionen
Drei Fähigkeiten des MCP Servers
Ein MCP Server kann drei verschiedene Funktionstypen bereitstellen:
| Fähigkeit | Zweck | Beispiel |
|---|---|---|
| Tools | Aktionen ausführen | Wetter abfragen, Nachricht senden, Datenbank lesen |
| Resources | Daten bereitstellen | Dateiinhalte, API-Antworten, Konfiguration |
| Prompts | Vordefinierte Vorlagen | Code-Review-Vorlage, Tagesbericht-Vorlage |
Tools sind wie „Funktionen“ – die KI kann sie aufrufen, um eine Aktion auszuführen; Resources sind „Datenquellen“ – die KI kann deren Inhalt lesen; Prompts sind „Vorlagen“ – sie helfen der KI, die Aufgabe schneller zu verstehen.
Unterschied zu anderen Artikeln: In manchen MCP-Tutorials sehen Sie Python mit FastMCP. Dieser Artikel nutzt das native TypeScript-SDK – besser geeignet für Frontend- und Full-Stack-Entwickler. Beide Ansätze sind funktional gleichwertig; wählen Sie die Sprache, die Sie kennen.
"https://modelcontextprotocol.io"
Entwicklungsumgebung vorbereiten
Voraussetzungen
Dieser Artikel setzt voraus, dass Sie:
- Node.js 18+ oder Bun 1.0+ installiert haben
- TypeScript kennen und wissen, was
interfaceundasync/awaitsind - Claude Desktop oder einen MCP-fähigen Client (Cursor, Windsurf usw.) nutzen
Wenn Sie Bun noch nicht kennen: Probieren Sie es aus – es ist deutlich schneller als npm und bringt TypeScript-Support mit, ohne ts-node extra konfigurieren zu müssen.
Projekt initialisieren
# Projektverzeichnis anlegen
mkdir mcp-weather-server && cd mcp-weather-server
# Initialisieren (mit Bun oder npm)
bun init -y
# oder npm init -y
# MCP TypeScript SDK installieren
bun add @modelcontextprotocol/sdk zod
# oder npm install @modelcontextprotocol/sdk zod
Zwei Abhängigkeiten:
@modelcontextprotocol/sdk: Offizielles MCP TypeScript SDKzod: Laufzeit-Typvalidierung in TypeScript, für Tool-Parameter-Schemas
TypeScript-Konfiguration
Mit bun init ist tsconfig.json bereits gesetzt. Bei manueller Konfiguration diese Optionen beachten:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"strict": true
}
}
moduleResolution: "bundler" ist wichtig für ESM-Module – sonst kann der Fehler „xxx is not defined“ auftreten.
Praxis: Wetterabfrage-MCP-Server von Hand
Dieses Tutorial führt Sie durch einen vollständigen MCP Server, der:
- KI-Aufrufe entgegennimmt
- die OpenWeatherMap-API für Echtzeitwetter abfragt
- formatierte Ergebnisse zurückgibt
Projektstruktur
mcp-weather-server/
+-- src/
| +-- index.ts # Einstieg
| +-- weather.ts # Wetter-Tool
| +-- resources.ts # Ressourcen
+-- package.json
+-- tsconfig.json
Der Code kann alles in index.ts stehen (wie in diesem Artikel) – Module erleichtern die Wartung.
Schritt 1: MCP-Server-Grundgerüst
Vom Einfachsten starten – ein lauffähiger MCP Server:
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Server-Instanz erstellen
const server = new McpServer({
name: "weather-service",
version: "1.0.0",
});
// Tool registrieren (Tools)
server.tool(
"get_weather",
"Aktuelle Wetterinformationen für eine Stadt abrufen",
{
city: z.string().describe("Stadtname, z. B. Berlin, München"),
},
async ({ city }) => {
// Tool-Implementierung folgt im nächsten Abschnitt
return { content: [{ type: "text", text: `Wetter für ${city} wird abgefragt...` }] };
}
);
// Server starten
const transport = new StdioServerTransport();
await server.connect(transport);
McpServer ist die Kernklasse des SDKs – name und version sind Pflicht. tool() registriert ein Tool: erster Parameter Name, zweiter Beschreibung, dritter Parameter-Schema, zuletzt die Ausführungsfunktion.
Schritt 2: Wetter-Tool implementieren (Kerncode)
Jetzt das Tool wirklich nutzbar machen – mit der kostenlosen OpenWeatherMap-API:
// src/weather.ts
import { z } from "zod";
// OpenWeatherMap API-Antworttyp
interface WeatherResponse {
name: string;
main: { temp: number; feels_like: number; humidity: number };
weather: [{ description: string }];
wind: { speed: number };
}
// Wetter-Tool-Implementierung
server.tool(
"get_weather",
"Aktuelle Wetterinformationen für eine Stadt abrufen",
{
city: z.string().describe("Stadtname, z. B. Berlin, München"),
},
async ({ city }) => {
const API_KEY = process.env.OPENWEATHER_API_KEY;
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric&lang=de`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`API-Anfrage fehlgeschlagen: ${response.status}`);
}
const data: WeatherResponse = await response.json();
// Formatiertes Ergebnis zurückgeben
return {
content: [
{
type: "text",
text: JSON.stringify({
city: data.name,
temperature: `${data.main.temp}°C`,
feels_like: `${data.main.feels_like}°C`,
description: data.weather[0].description,
humidity: `${data.main.humidity}%`,
wind_speed: `${data.wind.speed} m/s`,
}, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Abfrage fehlgeschlagen: ${error instanceof Error ? error.message : 'Unbekannter Fehler'}`,
},
],
isError: true,
};
}
}
);
Wichtig:
- API Key aus Umgebungsvariable: Schlüssel nie im Code hardcoden
- Fehlerbehandlung:
isError: truesignalisiert dem Client einen fehlgeschlagenen Aufruf - Typdefinition: Das Interface
WeatherResponselässt TypeScript die Datenstruktur prüfen
Registrieren Sie sich bei OpenWeatherMap, holen Sie einen kostenlosen API Key und setzen Sie die Umgebungsvariable:
export OPENWEATHER_API_KEY=your_api_key_here
Schritt 3: Resources hinzufügen (optional, empfohlen)
Mit Resources liefert Ihr Server schreibgeschützte Daten – z. B. Serverstatus für die KI:
// src/resources.ts
// Serverstatus bereitstellen
server.resource(
"server-status",
"status://server",
async (uri) => ({
contents: [
{
uri: uri.href,
text: JSON.stringify({
name: "Weather Service",
version: "1.0.0",
status: "running",
timestamp: new Date().toISOString(),
}, null, 2),
},
],
})
);
// API-Dokumentation bereitstellen
server.resource(
"api-docs",
"docs://api",
async (uri) => ({
contents: [
{
uri: uri.href,
text: `
# Weather MCP Server API
## Tools
- get_weather(city: string): Wetter für eine Stadt abrufen
## Resources
- status://server - Serverstatus
- docs://api - API-Dokumentation
`.trim(),
},
],
})
);
Die ersten beiden Parameter von resource() sind Name und URI, der dritte die Lese-Funktion. Die URI kann ein beliebiges Schema haben, z. B. status:// oder docs://.
Schritt 4: Prompts hinzufügen (Fortgeschritten)
Prompts sind vordefinierte Dialogvorlagen – z. B. eine „Wetterbericht“-Vorlage, in die die KI automatisch den Stadtnamen einsetzt:
// Vordefinierte Wetterbericht-Vorlage
server.prompt(
"weather_report",
"Einen formatierten Wetterbericht erzeugen",
{
city: z.string().describe("Stadtname"),
include_tips: z.boolean().optional().describe("Kleidungstipps einbeziehen"),
},
({ city, include_tips }) => ({
messages: [
{
role: "user",
content: {
type: "text",
text: `Bitte erstelle einen Wetterbericht für ${city}.${include_tips ? " Gib auch Kleidungsempfehlungen." : ""}`,
},
},
],
})
);
Der Rückgabewert von prompt() ist ein Nachrichtenarray mit role und content – die KI erhält so vorgegebenen Kontext.
Schritt 5: Einstiegsdatei vervollständigen
Alles in src/index.ts zusammenführen und Fehlerbehandlung ergänzen:
// src/index.ts (vollständig)
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: "weather-service",
version: "1.0.0",
});
// Alle Tools, Resources und Prompts registrieren
// ... (Code von oben)
// Fehlerbehandlung
process.stdin.on("error", (err) => {
console.error("Stdin-Fehler:", err);
process.exit(1);
});
process.stdout.on("error", (err) => {
console.error("Stdout-Fehler:", err);
process.exit(1);
});
// Sauberes Beenden
process.on("SIGINT", async () => {
await server.close();
process.exit(0);
});
// Server starten
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Weather Server gestartet, warte auf Verbindung...");
StdioServerTransport kommuniziert über Standard-Ein-/Ausgabe – Fehlerbehandlung für stdin/stdout ist wichtig. SIGINT ermöglicht sauberes Stoppen mit Strg+C.
Start mit bun run src/index.ts – die Meldung „gestartet“ bestätigt, dass alles läuft.
Client konfigurieren: Claude anbinden
Der Server steht – jetzt Claude Desktop oder Cursor daran anschließen.
Claude Desktop
Konfigurationsdatei:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Server-Eintrag hinzufügen:
{
"mcpServers": {
"weather": {
"command": "bun",
"args": ["run", "/absolute/path/to/mcp-weather-server/src/index.ts"],
"env": {
"OPENWEATHER_API_KEY": "Ihr API Key"
}
}
}
}
Hinweis: Der Pfad in args muss absolut sein – relative Pfade führen oft zu Startfehlern.
Cursor / Windsurf
Ähnliche Konfiguration in den IDE-Einstellungen unter MCP (Format wie oben).
Cursor-Konfiguration typischerweise:
- macOS:
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb - oder in der IDE: Einstellungen → KI → MCP → Server hinzufügen
Server testen
- Claude Desktop / Cursor neu starten
- In den Chat eingeben: „Wie ist das Wetter in Berlin?“
- Claude sollte Ihren MCP Server automatisch aufrufen
Erfolgreich sieht die Ausgabe etwa so aus:
{
"city": "Berlin",
"temperature": "18°C",
"feels_like": "16°C",
"description": "bewölkt",
"humidity": "65%",
"wind_speed": "3.2 m/s"
}
Häufige Probleme
| Problem | Mögliche Ursache | Lösung |
|---|---|---|
| Server nicht verbunden | Falscher Pfad | Absoluten Pfad in args prüfen |
| API Key ungültig | Umgebungsvariable fehlt | env-Konfiguration prüfen |
| Keine Antwort | TypeScript-Fehler | Zuerst mit bun build oder tsc kompilieren |
| Berechtigungsfehler | Config-Rechte | Konfigurationsdatei lesbar machen |
"https://github.com/modelcontextprotocol/typescript-sdk"
Erweiterung und Deployment
Weitere Tools
Wetterabfrage ist nur der Anfang. Möglich sind z. B.:
- Historisches Wetter: Historische API, Wetter eines vergangenen Tages
- Mehrstädte-Vergleich: Mehrere Städte parallel, Vergleichstabelle
- Wetterwarnungen: Prüfung auf Unwetterwarnungen
Registrierung wie bei get_weather, nur andere Logik.
Deployment-Optionen
Für Team-Nutzung reicht lokales stdio nicht. Vergleich:
| Methode | Einsatz | Vorteile | Nachteile |
|---|---|---|---|
| Lokales stdio | Persönlich, Entwicklung | Einfach, sicher | Nicht teilbar |
| HTTP/SSE | Team, mehrere Nutzer | Remote-Zugriff | Authentifizierung nötig |
| Serverless | Produktion | Auto-Skalierung | Cold-Start-Latenz |
Produktion
Authentifizierung: Bei HTTP-Deployment Pflicht. MCP unterstützt OAuth 2.1; einfacher API Key geht auch:
// API Key im Request-Header prüfen
const apiKey = request.headers.get("Authorization");
if (apiKey !== `Bearer ${process.env.API_KEY}`) {
return new Response("Unauthorized", { status: 401 });
}
Rate Limiting: Schutz vor Missbrauch und API-Kontingent-Erschöpfung – z. B. express-rate-limit oder Cloudflare Workers.
Logging: Mit pino oder winston Tool-Aufrufe protokollieren:
import pino from "pino";
const logger = pino();
server.tool("get_weather", /* ... */, async ({ city }) => {
logger.info({ city }, "Wetterabfrage");
// ...
});
Monitoring: Erfolgsrate und Antwortzeit – oft Prometheus + Grafana.
Fazit
Dieser Artikel zeigt, wie Sie einen MCP Server mit TypeScript von Grund auf schreiben:
- MCP-Kernkonzepte und Drei-Schichten-Architektur
- Server mit MCP TypeScript SDK
- Wetter-Tool (Tools)
- Serverstatus-Ressource (Resources)
- Wetterbericht-Vorlage (Prompts)
- Claude Desktop / Cursor anbinden
Als Nächstes können Sie:
- MCP-Wrapper für APIs bauen (GitHub, Slack, Notion …)
- MCP-Schnittstellen für interne Systeme (CRM, Datenbank)
- Die MCP-Community erkunden
Weiterführende Ressourcen:
Für MCP-Protokoll im Detail: MCP-Protokoll vertieft verstehen.
FAQ
Welche Vorkenntnisse brauche ich für MCP-Server-Entwicklung?
Was ist der Unterschied zwischen MCP Server und FastMCP?
Wie teste ich, ob der MCP Server funktioniert?
Kann ich den MCP Server remote deployen?
8 Min. Lesezeit · Veröffentlicht am: 19. März 2026 · Aktualisiert am: 14. Juli 2026
MCP Praxisleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
KI-Tools inkompatibel? Das MCP-Protokoll verbindet alle Tools nahtlos (mit Praxisbeispiel)
MCP-Protokoll im Detail: Wie es die Interoperabilität von KI-Tools löst – mit Praxisbeispiel zum schnellen Aufbau eines Wetterabfrage-Dienstes via FastMCP. Inklusive Code, Konfigurationsanleitung und FAQ – in 5 Minuten startklar.
Teil 1 von 4
Nächster
MCP-Praxis-Tutorial: Cursor direkt mit Datenbank und API verbinden – vollständige Konfigurationsanleitung
Schritt für Schritt MCP Server einrichten, damit Cursor und Claude direkt SQLite/PostgreSQL-Datenbanken abfragen und APIs aufrufen können. Mit vollständigen Codebeispielen und Lösungen für häufige Probleme – in 15 Minuten einsatzbereit.
Teil 3 von 4
Ähnliche Beiträge
Praktische MCP-Plugin-Empfehlungen: Sequential Thinking, Brave Search, Playwright – Installation & Anleitung

Praktische MCP-Plugin-Empfehlungen: Sequential Thinking, Brave Search, Playwright – Installation & Anleitung
Codex vs. Claude Code vs. Cursor: Im echten Projekt nach Workflow wählen, nicht nach Benchmarks


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen