Ein MCP Server, der einem AI-Modell Tools bereitstellt, hat echte Handlungsmacht. Ohne Sicherheitsmaßnahmen kann ein kompromittierter Server Daten leaken, unautorisierte Aktionen ausführen oder als Angriffsvektor dienen.
server.tool(
"get_customer",
"Kundendaten abrufen",
{ customerId: z.string() },
async ({ customerId }, context) => {
// Auth-Token aus dem Context prüfen
const token = context.meta?.authToken;
if (!token || !await verifyToken(token)) {
return {
content: [{ type: "text", text: "Fehler: Nicht autorisiert" }],
isError: true
};
}
const customer = await db.getCustomer(customerId);
return { content: [{ type: "text", text: JSON.stringify(customer) }] };
}
);
const permissions: Record<string, string[]> = {
"read-only": ["get_customer", "list_orders", "search_products"],
"editor": ["get_customer", "list_orders", "update_order", "create_ticket"],
"admin": ["*"] // Alle Tools
};
function checkPermission(role: string, toolName: string): boolean {
const allowed = permissions[role];
return allowed?.includes("*") || allowed?.includes(toolName) || false;
}
Jeder Tool-Input muss validiert werden, bevor die Aktion ausgeführt wird:
server.tool(
"execute_query",
"SQL-Abfrage auf der Datenbank ausführen",
{
query: z.string()
.max(1000)
.refine(q => !q.toLowerCase().includes("drop"), "DROP nicht erlaubt")
.refine(q => !q.toLowerCase().includes("delete"), "DELETE nicht erlaubt")
.refine(q => q.toLowerCase().startsWith("select"), "Nur SELECT-Queries erlaubt")
},
async ({ query }) => {
const result = await db.query(query);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
}
);
const serverConfig = {
maxRequestsPerMinute: 60,
maxTokensPerRequest: 10000,
timeoutMs: 30000,
maxConcurrentRequests: 5
};
import { RateLimiter } from "./rate-limiter";
const limiter = new RateLimiter({ maxRequests: 60, windowMs: 60000 });
server.tool("search", "Suche durchführen", { query: z.string() },
async ({ query }) => {
if (!limiter.allow()) {
return {
content: [{ type: "text", text: "Rate Limit erreicht. Bitte warten." }],
isError: true
};
}
return { content: [{ type: "text", text: await search(query) }] };
}
);
Jede Aktion muss protokolliert werden:
async function auditLog(event: {
tool: string;
input: unknown;
output: unknown;
userId: string;
timestamp: Date;
success: boolean;
}) {
await db.insert("audit_log", event);
if (!event.success) {
await alerting.notify(`Tool-Fehler: ${event.tool}`, event);
}
}
Praxis-Tipp: Security ist kein nachträglicher Gedanke — es wird von Anfang an mitgebaut. Jeder MCP Server sollte mindestens Authentication, Input Validation und Audit Logging haben. Für Production kommen Rate Limiting und Sandboxing dazu.