Einen MCP Server in 50 Zeilen bauen
MCP (Model Context Protocol) ermoeglicht es Ihnen, KI-Agenten neue Faehigkeiten zu geben. In diesem Abschnitt bauen Sie einen funktionierenden MCP Server von Grund auf.
MCP-Zusammenfassung
MCP ist das Standardprotokoll zur Verbindung von KI-Agenten mit Tools:
Agent (Client) <-> MCP Server (Tool)
| |
LLM-Gehirn Ihr Code
Entscheidet, Fuehrt die
welches Tool eigentliche
genutzt wird Arbeit aus
Was ein MCP Server bereitstellt:
- Tools -- Funktionen, die der Agent aufrufen kann (suchen, berechnen, abfragen)
- Resources -- Daten, die der Agent lesen kann (Dateien, Datenbanken, Konfigurationen)
- Prompts -- Vorlagen-Prompts fuer haeufige Aufgaben
Wenn Sie einen MCP Server bauen, kann jeder MCP-kompatible Agent (Claude Code, OpenCode, Cursor usw.) ihn sofort nutzen.
Ihr erster MCP Server
Ein Wetter-Lookup-Tool in unter 50 Zeilen:
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",
version: "1.0.0",
});
// Ein Tool definieren
server.tool(
"get_weather",
"Get current weather for a city",
{
city: z.string().describe("City name, e.g. 'London'"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
},
async ({ city, units }) => {
// In Produktion eine echte Wetter-API aufrufen
const temp = Math.round(Math.random() * 30 + 5);
const conditions = ["sunny", "cloudy", "rainy", "snowy"];
const condition = conditions[Math.floor(Math.random() * 4)];
return {
content: [{
type: "text",
text: `Weather in ${city}: ${temp}°${units === "celsius" ? "C" : "F"}, ${condition}`,
}],
};
}
);
// Server starten
const transport = new StdioServerTransport();
await server.connect(transport);
Das war's. 30 Zeilen tatsaechlicher Code, und jeder MCP-Agent kann jetzt das Wetter pruefen.
Das Projekt einrichten
Schritt-fuer-Schritt-Einrichtung:
mkdir mcp-weather && cd mcp-weather
npm init -y
npm install @modelcontextprotocol/sdk zod
Zu package.json hinzufuegen:
{
"type": "module",
"scripts": {
"start": "node index.js"
}
}
index.js erstellen mit dem Code von der vorherigen Folie.
Bei Ihrem Agenten registrieren (z.B. Claude Code-Konfiguration):
{
"mcpServers": {
"weather": {
"command": "node",
"args": ["/path/to/mcp-weather/index.js"]
}
}
}
Wenn Sie jetzt Claude Code fragen "What's the weather in Berlin?", wird es Ihren MCP Server aufrufen.
Resources hinzufuegen
Resources lassen Agenten Daten von Ihrem Server lesen:
// Eine Resource hinzufuegen, die Staedtedaten bereitstellt
server.resource(
"cities",
"cities://list",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify([
{ name: "London", country: "UK", timezone: "GMT" },
{ name: "Berlin", country: "DE", timezone: "CET" },
{ name: "Tokyo", country: "JP", timezone: "JST" },
]),
}],
})
);
Resources sind nuetzlich fuer:
- Konfigurationsdateien
- Datenbankschemas
- Dokumentation
- Alle Referenzdaten, die der Agent benoetigen koennte
Praxisnahe MCP Server
Praktische MCP Server, die Sie bauen koennen:
Datenbank-Abfrage-Tool:
server.tool("query_db", "Run a read-only SQL query", {
sql: z.string().describe("SQL SELECT query"),
}, async ({ sql }) => {
// Sicherheit: nur SELECT-Anweisungen erlauben
if (!sql.trim().toUpperCase().startsWith("SELECT")) {
return { content: [{ type: "text", text: "Error: Only SELECT queries allowed" }] };
}
const results = await db.query(sql);
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
});
Jira-Integration:
server.tool("create_ticket", "Create a Jira ticket", {
project: z.string(),
title: z.string(),
description: z.string(),
priority: z.enum(["P0", "P1", "P2", "P3"]),
}, async ({ project, title, description, priority }) => {
const ticket = await jira.createIssue({ project, title, description, priority });
return { content: [{ type: "text", text: `Created ${ticket.key}: ${ticket.url}` }] };
});
Monitoring-Dashboard:
server.tool("get_metrics", "Get application metrics", {
service: z.string(),
period: z.enum(["1h", "24h", "7d"]),
}, async ({ service, period }) => {
const metrics = await prometheus.query(service, period);
return { content: [{ type: "text", text: formatMetrics(metrics) }] };
});
MCP-Sicherheits-Best-Practices
Ihr MCP Server hat echte Macht -- sichern Sie ihn ab:
1. Eingabevalidierung (bereits durch Zod-Schemas abgedeckt)
// Zod validiert Typen und Einschraenkungen automatisch
city: z.string().max(100).describe("City name")
2. Standardmaessig nur Lesezugriff
- Mit schreibgeschuetzten Tools beginnen (Abfragen, Lookups)
- Schreiboperationen nur bei Bedarf hinzufuegen
- Bestaetigungsaufforderungen fuer destruktive Aktionen verwenden
3. Rate Limiting
const rateLimiter = new Map();
function checkRate(toolName) {
const count = rateLimiter.get(toolName) || 0;
if (count > 100) throw new Error("Rate limit exceeded");
rateLimiter.set(toolName, count + 1);
// Jede Minute zuruecksetzen
}
4. Audit-Logging
// Jeden Tool-Aufruf protokollieren
server.tool("query_db", ..., async (args) => {
console.error(`[AUDIT] query_db called with: ${JSON.stringify(args)}`);
// ... ausfuehren
});
Mehrere MCP Server verbinden
Agenten werden maechtig, wenn sie mehrere Tools nutzen koennen:
Agent (Claude Code)
+-- MCP: Dateisystem (eingebaut)
+-- MCP: GitHub (Issues, PRs)
+-- MCP: Datenbank (Abfragen)
+-- MCP: Monitoring (Metriken)
+-- MCP: Ihr benutzerdefinierter Server
Beispiel-Workflow mit mehreren MCP Servern:
Sie: "Check if there are any open P0 tickets, then look at
the related code and monitoring metrics to diagnose them"
Agent:
-> [Jira MCP] Offene P0-Tickets abrufen -> 2 gefunden
-> [File MCP] Betroffene Code-Dateien lesen
-> [Monitoring MCP] Fehlerraten fuer diese Services abrufen
-> Synthese: "Ticket PROJ-123 is caused by a null check
missing in user-service.js:42. Error rate spiked at 3am."
Jeder MCP Server macht eine Sache gut. Der Agent orchestriert sie zusammen, um komplexe Probleme zu loesen.
---quiz question: Was sind die drei Arten von Faehigkeiten, die ein MCP Server bereitstellen kann? options:
- { text: "Lesen, Schreiben und Loeschen", correct: false }
- { text: "Tools (aufrufbare Funktionen), Resources (lesbare Daten) und Prompts (Vorlagen-Prompts)", correct: true }
- { text: "Eingabe, Verarbeitung und Ausgabe", correct: false } feedback: MCP Server bieten Tools (ausfuehrbare Funktionen wie Abfragen oder API-Aufrufe), Resources (lesbare Daten wie Konfigurationen oder Schemas) und Prompts (wiederverwendbare Prompt-Vorlagen fuer haeufige Aufgaben).
---quiz question: Warum sollten MCP Server mit schreibgeschuetzten Tools beginnen? options:
- { text: "Weil Schreiboperationen langsamer sind", correct: false }
- { text: "Um das Risiko zu minimieren -- schreibgeschuetzte Operationen koennen nicht versehentlich kritische Daten loeschen oder aendern", correct: true }
- { text: "Weil MCP keine Schreiboperationen unterstuetzt", correct: false } feedback: Schreibgeschuetzte Tools (Abfragen, Lookups, Statusabfragen) sind sicher zum Experimentieren. Schreiboperationen (Erstellen, Aktualisieren, Loeschen) bergen Risiken und sollten sorgfaeltig mit ordnungsgemaesser Validierung, Bestaetigung und Audit-Logging hinzugefuegt werden.
---quiz question: Was macht MCP im Vergleich zu individuellen Tool-Integrationen so leistungsfaehig? options:
- { text: "MCP ist schneller als individuelle Integrationen", correct: false }
- { text: "Jeder MCP-kompatible Agent kann jeden MCP Server nutzen -- es ist ein universeller Standard", correct: true }
- { text: "MCP Server sind immer kostenlos", correct: false } feedback: MCP ist ein universelles Protokoll. Sobald Sie einen MCP Server bauen, kann jeder MCP-kompatible Agent (Claude Code, OpenCode, Cursor usw.) ihn sofort nutzen -- keine individuelle Integration pro Agent noetig.