TypeScript ile Canlıya Alınabilir MCP Sunucusu Geliştirme ve Güvenlik Rehberi
Büyük Dil Modelleri (LLM'ler) sohbet arayüzlerinden otonom yazılım ajanlarına evrilirken temel bir mühendislik problemi ortaya çıkar: Yapay zeka modelleri kurumsal veritabanları, iç API'ler, geliştirici araçları ve dosya sistemleriyle hassas altyapıyı riske atmadan nasıl güvenle etkileşime girebilir?
Anthropic tarafından açık kaynak olarak sunulan Model Context Protocol (MCP), yapay zeka host'larını (Claude Desktop, Cursor IDE ve özel agent sistemleri) dış veri kaynaklarına ve araçlara bağlayan mimari bir standarttır.
Basit MCP öğreticileri yerel stdio bağlantılarını gösterirken, canlı (production) ortamlarda çalışan MCP sunucuları sıkı girdi doğrulaması (input validation), katman güvenliği, kimlik doğrulama middleware'i, oran sınırlama (rate limiting) ve hata izolasyonu gerektirir.
Bu rehberde, TypeScript ve @modelcontextprotocol/sdk kullanarak canlıya alınabilir, güvenlik testlerinden geçmiş bir MCP sunucusunun mimarisini, Anthropic Agent SDK entegrasyonunu ve kimlik doğrulama adımlarını inceleyeceğiz.
[!IMPORTANT] Production MCP Güvenliği İçin Temel Mimari Çözüm: Anthropic Agent SDK ve Model Context Protocol (MCP) kimlik doğrulama mimarisi üç kritik savunma katmanına dayanır:
- Taşıma Katmanı Güvenliği (TLS + Bearer/OAuth2 Token): Ajan el sıkışmasından önce Server-Sent Events (SSE) uç noktalarını kimlik denetiminden geçirme.
- Zod Katı Şema Doğrulaması: SQL enjeksiyonu ve prompt injection saldırılarını engellemek için tüm LLM araç argümanlarını tip seviyesinde denetleme.
- Dizin Geçişi Koruması (Path Traversal Defense): Ajanların sunucu ana dizininden dışarı çıkmasını engelleyen
path.resolve()kontrolleri.
MCP Güvenlik & Kimlik Doğrulama Matrisi
| Boyut | Stdio Transport | Remote SSE Transport | HTTP Stream Transport |
|---|---|---|---|
| Kimlik Doğrulama | İşletim Sistemi Süreç Yetkisi | Bearer Token / JWT / mTLS | API Key Header / OAuth 2.0 |
| Güvenlik Sınırı | Yerel Sandbox / UID İzolasyonu | Ağ Güvenlik Duvarı + CORS | Ters Proxy / API Gateway |
| En İyi Kullanım | Claude Desktop, Yerel IDE | Bulut AI Ajanları, Mikroservisler | Dağıtık Çoklu Ajan Sistemleri |
| Risk Faktörü | Düşük (Kullanıcı yetkisine bağlı) | Yüksek (Sıkı token koruması şart) | Orta (Standart web güvenliği) |
1. Model Context Protocol (MCP) Mimari Temelleri
MCP, LLM yürütmesini alt sistem kaynaklarından ayırmak için istemci-sunucu (client-server) mimarisini uygular:
- Host (AI Host): LLM'in çalıştığı ortam (Örn: Claude Desktop, Cursor IDE, LangChain agent).
- Client (MCP Client): Host içinde yer alan, protokol yeteneklerini yöneten ve araç çağrılarını ileten istemci.
- Server (MCP Server): İstemciye açık Kaynaklar (Resources), Araçlar (Tools) ve Prompt'lar sunan bağımsız servis.
graph LR
Host[AI Host / Claude / Cursor] <--> Client[MCP Client]
Client <-->|Stdio / SSE / HTTP| Server[Production MCP Server]
Server <--> Guard[Girdi Doğrulama & Zod Şeması]
Guard <--> DB[(Canlı Veritabanı)]
Guard <--> ExternalAPI[Harici API'ler]
MCP Tarafından Sunulan Temel Bileşenler
- Tools (Araçlar): LLM'in eylem gerçekleştirmesini sağlayan çalıştırılabilir fonksiyonlar (Örn: SQL sorgusu çalıştırma, güvenlik günlüğü tarama, webhook tetikleme).
- Resources (Kaynaklar): LLM'in okuma yetkisine sahip olduğu veri uç noktaları (Örn: yapılandırma dosyaları, sistem metrikleri, veritabanı kayıtları).
- Prompts (Şablonlar): Karmaşık ajan etkileşimlerini standartlaştıran parametreli istem şablonları.
2. Production TypeScript Projesinin Kurulumu
Kurumsal düzeyde bir MCP sunucusu geliştirmek için TypeScript projenizi sıkı tip güvenliği ve şema doğrulama bağımlılıklarıyla başlatın:
mkdir mcp-production-server
cd mcp-production-server
npm init -y
npm install @modelcontextprotocol/sdk zod dotenv express cors helmet
npm install -D typescript @types/node @types/express tsx
tsconfig.json dosyasını sıkı tip denetimi için yapılandırın:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
3. Canlıya Alınabilir MCP Sunucusunun Kodlanması
Güvenlik tespiti ve veri analizi yetenekleri sunan güvenli bir MCP sunucusu oluşturalım.
Adım 1: Sunucu Örneğinin Başlatılması
src/server.ts dosyasını oluşturun:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ErrorCode,
McpError,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
const server = new Server(
{
name: "production-security-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
resources: {},
},
}
);
Adım 2: Sıkı Zod Şeması ile Girdi Doğrulama
Girdi doğrulaması, Prompt Injection ve Veri Manipülasyonu saldırılarına karşı ilk savunma hattıdır. Tüm araç parametreleri için sıkı Zod şemaları tanımlayın:
const AuditLogQuerySchema = z.object({
environment: z.enum(["production", "staging", "development"]),
limit: z.number().int().min(1).max(100).default(20),
severity: z.enum(["LOW", "MEDIUM", "HIGH", "CRITICAL"]).optional(),
searchTerm: z.string().max(200).optional(),
});
type AuditLogQuery = z.infer<typeof AuditLogQuerySchema>;
Adım 3: Araç Kaydı ve Yetenek Bildirimi
Kapasite görüşmesi sırasında LLM'e kullanılabilir araçları bildirin:
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "query_audit_logs",
description: "Kurumsal güvenlik denetim günlüklerini filtrelenmiş olarak getirir.",
inputSchema: {
type: "object",
properties: {
environment: {
type: "string",
enum: ["production", "staging", "development"],
description: "İncelenecek hedef ortam",
},
limit: {
type: "number",
description: "Döndürülecek maksimum kayıt sayısı (1-100)",
},
severity: {
type: "string",
enum: ["LOW", "MEDIUM", "HIGH", "CRITICAL"],
description: "Günlük önem derecesine göre filtreleme",
},
searchTerm: {
type: "string",
description: "Arama terimi (maks 200 karakter)",
},
},
required: ["environment"],
},
},
],
};
});
Adım 4: Güvenli Araç Çalıştırma Yöneticisi
Araç çalıştırma işleyicisini hata sınırları (error boundaries) ve veri dezenfeksiyonu ile uygulayın:
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (name === "query_audit_logs") {
// Parametreleri Zod şemasına göre doğrula
const parseResult = AuditLogQuerySchema.safeParse(args);
if (!parseResult.success) {
throw new McpError(
ErrorCode.InvalidParams,
`Geçersiz araç parametreleri: ${parseResult.error.message}`
);
}
const { environment, limit, severity, searchTerm } = parseResult.data;
try {
// Doğrulanmış sorguyu altyapıda çalıştır
const logs = await fetchSecurityAuditLogs({
environment,
limit,
severity,
searchTerm,
});
return {
content: [
{
type: "text",
text: JSON.stringify(logs, null, 2),
},
],
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Bilinmeyen veritabanı hatası";
return {
content: [
{
type: "text",
text: `Çalıştırma başarısız: ${errorMessage}`,
},
],
isError: true,
};
}
}
throw new McpError(ErrorCode.MethodNotFound, `Bilinmeyen araç: ${name}`);
});
4. Canlı (Production) MCP Dağıtımlarında Güvenlik Sıkılaştırma
MCP sunucularını canlı ortamda çalıştırmak özel güvenlik gereksinimleri doğurur:
A. Girdi Dezenfeksiyonu ve Path Traversal Engelleme
LLM araç argümanlarından gelen ham metinleri doğrudan dosya yollarına veya kabuk (shell) komutlarına iletmeyin:
import path from "path";
export function sanitizeFilePath(baseDir: string, userPath: string): string {
const safePath = path.normalize(userPath).replace(/^(\.\.[\/\\])+/, "");
const resolvedPath = path.resolve(baseDir, safePath);
if (!resolvedPath.startsWith(baseDir)) {
throw new Error("Güvenlik Uyarısı: Path traversal girişimi tespit edildi.");
}
return resolvedPath;
}
B. Taşıma Katmanı Güvenliği: Stdio vs SSE
- Stdio Transport: Yerel çalıştırma için idealdir (Claude Desktop, Cursor). İşletim sistemi süreç izolasyonu doğal güvenlik sınırı sağlar.
- Server-Sent Events (SSE) Transport: Bulut dağıtımları için gereklidir. TLS (HTTPS), CORS kısıtlamaları ve Bearer Token / OAuth2 kimlik doğrulama başlıkları ile korunmalıdır.
C. Uzaktan SSE Taşıma Katmanı İçin Kimlik Doğrulama Middleware'i
MCP sunucusunu HTTP/SSE üzerinden sunarken taşıma katmanını Express kimlik doğrulama korumasıyla sarmalayın:
import express from "express";
import helmet from "helmet";
import cors from "cors";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
const app = express();
app.use(helmet());
app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(",") || ["https://gucluyumhe.dev"] }));
// Kimlik Doğrulama Koruması
app.use("/sse", (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
res.status(401).json({ error: "Yetkisiz: Geçersiz veya eksik Bearer token" });
return;
}
const token = authHeader.substring(7);
if (token !== process.env.MCP_SECRET_KEY) {
res.status(403).json({ error: "Yasaklandı: Geçersiz MCP gizli anahtarı" });
return;
}
next();
});
let sseTransport: SSEServerTransport;
app.get("/sse", async (req, res) => {
sseTransport = new SSEServerTransport("/messages", res);
await server.connect(sseTransport);
});
app.post("/messages", async (req, res) => {
await sseTransport.handlePostMessage(req, res);
});
app.listen(3001, () => {
console.log("Production MCP Sunucusu 3001 portunda SSE ile çalışıyor.");
});
5. Anthropic Agent SDK & TypeScript Güvenlik Mimarisi
Otonom ajanları Anthropic Agent SDK (@anthropic-ai/sdk) ve MCP ile TypeScript üzerinde çalıştırırken, ajanı güvenli bir MCP istemcisi (client) olarak yapılandırmalısınız:
import Anthropic from "@anthropic-ai/sdk";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
// Şifrelenmiş Bearer Token ile MCP İstemcisi Başlatma
const mcpTransport = new SSEClientTransport(
new URL("https://mcp.gucluyumhe.dev/sse"),
{
eventSourceInit: {
headers: {
Authorization: `Bearer ${process.env.MCP_BEARER_TOKEN}`,
"X-Agent-Identifier": "anthropic-agent-sdk-prod",
},
},
}
);
const mcpClient = new Client(
{
name: "KurumsalGuvenlikAjani",
version: "1.0.0",
},
{
capabilities: {
prompts: {},
resources: {},
tools: {},
},
}
);
// Araçları yürütmeden önce istemci bağlantısını tamamlayın
await mcpClient.connect(mcpTransport);
// Anthropic Claude İstemcisini Başlatın
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
// Doğrulanmış şemaları listeleyin
const availableTools = await mcpClient.listTools();
console.log(`${availableTools.tools.length} adet güvenli MCP aracı başarıyla bağlandı.`);
Dinamik Ajan Kimlik Doğrulama & Yetkilendirme İçin McpAuthMetadataRouter Kullanımı
Farklı yetki katmanlarına sahip çoklu otonom ajanların çalıştığı kurumsal sistemlerde McpAuthMetadataRouter tasarım desenini kullanın. Bu yönlendirici, gelen istekteki Bearer token'ı ve ajan kimliğini çözer, oturum süresini (TTL) doğrular ve ajanın sadece yetkili olduğu araçları (tools) çalıştırmasına izin verir:
import { Request, Response, NextFunction } from "express";
export interface McpAgentAuthContext {
agentId: string;
role: "admin" | "security_auditor" | "readonly_agent";
allowedTools: string[];
expiresAt: number;
}
/**
* McpAuthMetadataRouter
* Anthropic Agent SDK ve MCP sunucu araç çağrıları için dinamik auth ve yetki yönlendirmesi sağlar.
*/
export class McpAuthMetadataRouter {
private static sessions = new Map<string, McpAgentAuthContext>();
public static registerSession(bearerToken: string, context: McpAgentAuthContext): void {
this.sessions.set(bearerToken, context);
}
public static authorize(bearerToken: string, requestedTool: string): boolean {
const session = this.sessions.get(bearerToken);
if (!session) return false;
// Oturum süresi kontrolü (TTL)
if (Date.now() > session.expiresAt) {
this.sessions.delete(bearerToken);
return false;
}
// Joker karakter yetkisi veya hedeflenen araca özel yetki denetimi
return session.allowedTools.includes("*") || session.allowedTools.includes(requestedTool);
}
public static middleware() {
return (req: Request, res: Response, next: NextFunction): void => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith("Bearer ")) {
res.status(401).json({ error: "McpAuthMetadataRouter: Bearer Token eksik veya geçersiz" });
return;
}
const token = authHeader.substring(7);
const requestedTool = req.headers["x-mcp-tool-target"] as string;
if (requestedTool && !McpAuthMetadataRouter.authorize(token, requestedTool)) {
res.status(403).json({
error: `McpAuthMetadataRouter: Ajanın "${requestedTool}" aracını çalıştırma yetkisi bulunmuyor`,
});
return;
}
next();
};
}
}
Ajan SDK Dağıtımları İçin Güvenlik Kontrol Listesi
- Sıfır Güven (Zero-Trust) Yetkilendirme: Ajan rolü için yalnızca zorunlu araçları kaydedin (
McpAuthMetadataRouterile En Az Yetki Prensibi). - Zaman Aşımı Sınırları: Askıda kalan alt süreçleri ve servis dışı bırakma riskini önlemek için her araca en fazla 15 saniyelik limit koyun.
- Değiştirilemez Denetim Günlüğü (Audit Logging): Her araç çağrısını, girdi parametrelerini ve dönen yanıt özetlerini güvenli log sistemine yazın.
6. Canlıya Alma Stratejileri (Vercel, Railway, Docker)
Docker ve Railway / AWS ECS Dağıtımı
Süreç izolasyonu sağlamak için kapalı bir Dockerfile hazırlayın:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm ci
COPY src ./src
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3001
CMD ["node", "dist/server.js"]
Sıkça Sorulan Sorular (FAQ)
Model Context Protocol (MCP) TypeScript ile kimlik doğrulamayı nasıl sağlar?
TypeScript ile MCP kimlik doğrulaması taşıma katmanı (transport middleware) üzerinden yürütülür. Çekirdek protokol kendi başına bir auth standardı dayatmaz; ancak uzak sunucu bağlantılarında Server-Sent Events (SSE) veya HTTP akışları Bearer Token (JWT), OAuth2 veya karşılıklı TLS (mTLS) header'ları ile güvenceye alınır. Yerel Stdio taşımalarında ise işletim sistemi süreç yetkileri geçerlidir.
Anthropic Agent SDK uzak MCP sunucularına bağlanırken nasıl korunur?
Anthropic Agent SDK'yı korumak için SSEClientTransport başlıklarına şifrelenmiş Bearer token'lar verilmeli, uzak ağ geçidinde TLS 1.3 zorunlu tutulmalı, sıkı CORS politikaları uygulanmalı ve prompt injection saldırılarını bertaraf etmek için Zod şema doğrulaması kullanılmalıdır.
MCP'de Stdio ve SSE taşıma güvenliği arasındaki fark nedir?
Stdio taşımacılığı yerel ana makinedeki standart girdi/çıktı boruları üzerinden çalışır, yani araçlar ağa maruz kalmadan kullanıcının işletim sistemi yetkileriyle yürütülür. SSE (Server-Sent Events) taşımacılığı ise JSON-RPC paketlerini HTTP/HTTPS üzerinden ilettiğinden harici güvenlik duvarı, oran sınırlama (rate limit) ve token doğrulaması gerektirir.
MCP araçlarında prompt injection ve dizin geçişi saldırıları nasıl önlenir?
Gelen tüm parametreler Zod şemalarıyla doğrulanmalı, kaçış karakterleri (../) engellenmeli, dosya yolları path.resolve() ile izin verilen ana dizin altında kontrol edilmeli ve araç süreçleri root olmayan Docker konteynerlerinde çalıştırılmalıdır.
Sonuç
Model Context Protocol (MCP), statik LLM'leri kurumsal yapay zeka ajanlarına dönüştüren devrim niteliğinde bir standarttır. Sıkı Zod doğrulaması, dosya yolu dezenfeksiyonu, kimlik doğrulamalı SSE taşıma katmanı ve izole çalıştırma ortamları uygulayarak MCP sunucularınızı canlıya güvenle alabilirsiniz.
Tüm kaynak kodları ve açık kaynak araçları incelemek için GitHub profilimi ziyaret edebilir veya gucluyumhe.dev üzerinden iletişime geçebilirsiniz.
