Skip to content
~/sph.sh

MCP İleri Düzey Kalıplar: Yetenekler, İş Akışları, Entegrasyon ve RBAC

Model Context Protocol implementasyonları için kurumsal düzeyde kalıplar: araç bileşimi, çoklu ajan orkestrasyonu, rol tabanlı erişim kontrolü ve production gözlemlenebilirlik.

Özet

MCP benimsenmesi lansmanından bu yana hızla büyümüş olsa da, içeriklerin çoğu temel sunucu implementasyonunu kapsıyor. Bu yazı bir sonraki seviyeyi hedefliyor: uygun çoklu ajan iş akışları, araç bileşim kalıpları, RBAC ile kurumsal düzeyde güvenlik ve production gözlemlenebilirlik ile sofistike MCP tabanlı sistemlerin nasıl tasarlanacağı. Odak noktası, ölçekte çalışan kalıplar ve neyin başarılı olup neyin ileride sorun yarattığına dair somut örnekler.

Ölçeklendirme Zorluğu

Temel MCP entegrasyonlarını başarıyla deploy eden organizasyonlar, ölçeklendikçe öngörülebilir zorluklarla karşılaşıyor:

Araç Patlaması: 5 araçla başlayıp 10 sunucu üzerinde 50'ye büyümek, ajanlar için keşif ve seçim sorunları yaratıyor.

İzin Karmaşıklığı: Farklı kullanıcıların farklı araç erişimine ihtiyacı var. Junior bir geliştirici production deployment'ları tetiklememeli, ancak ince taneli erişim kontrolünü nasıl uyguluyorsunuz?

İş Akışı Orkestrasyonu: Karmaşık görevler sıralı veya paralel birden fazla araç gerektiriyor. Araç zincirlerini güvenilir bir şekilde koordine etmek kendi başına bir mühendislik problemi haline geliyor.

Çoklu Ajan Koordinasyonu: Birlikte çalışan birden fazla AI ajanının farklı araç alt kümelerine ihtiyacı var. Çatışmaları önlemek ve uygun izolasyonu sağlamak dikkatli tasarım gerektiriyor.

Denetim ve Uyumluluk: Düzenlemeye tabi sektörler tam denetim izleri gerektiriyor. Kimin neyi, ne zaman ve hangi sonuçlarla çağırdığını izlemek pazarlık konusu değil.

Kalıp 1: Araç Tasarımı ve Anotasyon

İyi tasarlanmış MCP araçları, onları birleştirilebilir ve bakımı yapılabilir kılan ortak özellikler paylaşır. MCP'de tanıtılan anotasyon sistemi, hem ajanların hem de kullanıcıların araç davranışını anlamasına yardımcı olan metadata sağlar.

Note: Bu yazıdaki kalıplar MCP spesifikasyonu sürüm 2025-11-05'e dayanmaktadır. API detayları daha yeni spesifikasyon sürümlerinde değişebilir.

Kapsamlı Araç Anotasyonları

typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";import { z } from "zod";
const server = new McpServer({  name: "deployment-server",  version: "1.0.0",});
// Kapsamlı anotasyonlarla araç// Not: server.tool() araç kaydı için üst düzey SDK API'sidirserver.tool(  "deploy_service",  {    service: z.string().describe("Deploy edilecek servis adı"),    environment: z.enum(["staging", "production"]).describe("Hedef ortam"),    version: z.string().regex(/^\d+\.\d+\.\d+$/).describe("Semantik versiyon"),  },  {    title: "Servis Deploy Et",    description: "Belirtilen ortama bir servisin deployment'ını tetikler",    annotations: {      // İstemciler için davranışsal ipuçları (MCP spesifikasyonu 2025-11-05)      readOnlyHint: false,        // Bu araç durumu değiştirir      destructiveHint: false,     // Yıkıcı değil (geri alınabilir)      idempotentHint: false,      // Birden fazla çağrı birden fazla deployment oluşturur      openWorldHint: true,        // Dış sistemlerle etkileşime girer    },  },  async ({ service, environment, version }) => {    // Uygun hata işleme ile implementasyon    const result = await deploymentService.deploy(service, environment, version);
    return {      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],    };  });

Yapısal Sonuçlar için Output Şemaları

Yapısal veri döndüren araçlar, programatik sonuç işlemeyi mümkün kılan output şemalarından faydalanır.

Note: outputSchema özelliği SDK sürüm 1.0.0 veya üstünü gerektirir. Implementasyondan önce SDK sürümünüzün bu özelliği desteklediğini doğrulayın.

typescript
server.tool(  "get_service_metrics",  {    service: z.string(),    timeRange: z.enum(["1h", "24h", "7d", "30d"]),  },  {    title: "Servis Metriklerini Al",    description: "Bir servis için performans metriklerini alır",    annotations: {      readOnlyHint: true,      idempotentHint: true,    },    // Output şeması yapısal içerik doğrulamasını etkinleştirir    outputSchema: z.object({      service: z.string(),      period: z.string(),      metrics: z.object({        requestCount: z.number(),        errorRate: z.number(),        p50Latency: z.number(),        p99Latency: z.number(),      }),    }),  },  async ({ service, timeRange }) => {    const metrics = await metricsService.getMetrics(service, timeRange);
    return {      content: [{ type: "text", text: JSON.stringify(metrics) }],      // Programatik erişim için yapısal içerik      structuredContent: metrics,    };  });

Araç Bileşim Kalıpları

Karmaşık işlemler genellikle birden fazla aracı zincirlemeyi gerektirir. İşte çalışan kalıplar:

typescript
// Kalıp 1: Sıralı Araç Zinciri Konfigürasyonuconst deploymentChain = {  chain: [    {      tool: "validate_config",      inputPath: "$.config",      outputPath: "$.validation",    },    {      tool: "run_tests",      inputPath: "$.validation.service",      outputPath: "$.testResults",    },    {      tool: "deploy_service",      inputPath: "$.validation",      outputPath: "$.deployment",    },  ],};
// Kalıp 2: Paralel Araç Yürütmeconst healthCheckConfig = {  parallel: [    { tool: "check_service_health", params: { service: "api" } },    { tool: "check_service_health", params: { service: "database" } },    { tool: "check_service_health", params: { service: "cache" } },  ],  merge: "$.healthStatus", // Sonuçları birleştir};
// Kalıp 3: Koşullu Araç Yürütmeconst conditionalDeployConfig = {  condition: "$.environment === 'production'",  ifTrue: [    { tool: "get_deployment_approval" },    { tool: "notify_stakeholders" },    { tool: "deploy_service" },  ],  ifFalse: [    { tool: "deploy_service" },  ],};

Kalıp 2: Çoklu Ajan İş Akışı Orkestrasyonu

Birden fazla AI ajanının farklı araç erişimiyle işbirliği yapması gerektiğinde, bir orkestratör kalıbı koordinasyon ve izolasyon sağlar.

Orkestratör Implementasyonu

Note: HTTP+SSE transport'u kullanımdan kaldırılmıştır. Yeni implementasyonlar için Streamable HTTP transport'u (StreamableHTTPClientTransport) kullanın. Transport sınıf adları SDK sürümüne göre değişebilir - yüklü SDK'nıza göre doğrulayın.

typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";// Transport import'u - SDK sürümünüze göre sınıf adını doğrulayın// import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
interface AgentConfig {  name: string;  role: string;  servers: string[];  permissions: string[];}
interface WorkflowStep {  name: string;  agent: string;  tool: string;  params: Record<string, any>;  outputKey: string;  timeout?: number;  onError: "abort" | "continue" | "rollback";  parallel?: WorkflowStep[];}
class MultiAgentOrchestrator {  private agents: Map<string, AgentConfig> = new Map();  private mcpClients: Map<string, Client> = new Map();
  async registerAgent(config: AgentConfig): Promise<void> {    const client = new Client({      name: `agent-${config.name}`,      version: "1.0.0",    });
    // Atanan MCP sunucularına bağlan    // Not: Yeni implementasyonlar için StreamableHTTPClientTransport kullanın    for (const serverUrl of config.servers) {      await client.connect(new StreamableHTTPClientTransport(serverUrl));    }
    // Mevcut araçları ajan izinlerine göre filtrele    const tools = await client.listTools();    const allowedTools = tools.filter(tool =>      this.checkToolPermission(tool, config.permissions)    );
    console.log(`Ajan ${config.name}, ${allowedTools.length} araçla kaydedildi`);
    this.agents.set(config.name, config);    this.mcpClients.set(config.name, client);  }
  async executeWorkflow(workflow: WorkflowDefinition): Promise<WorkflowResult> {    const executionId = crypto.randomUUID();    const results: Map<string, any> = new Map();
    console.log(`İş akışı ${workflow.name} başlatılıyor (${executionId})`);
    for (const step of workflow.steps) {      try {        if (step.parallel) {          // Paralel adımları eşzamanlı yürüt          const parallelResults = await Promise.all(            step.parallel.map(subStep =>              this.executeStep(subStep, results, executionId)            )          );
          // Paralel sonuçları birleştir          parallelResults.forEach((result, index) => {            results.set(step.parallel[index].outputKey, result);          });        } else {          // Sıralı adımı yürüt          const result = await this.executeStep(step, results, executionId);          results.set(step.outputKey, result);        }      } catch (error) {        if (step.onError === "continue") {          console.log(`Adım ${step.name} başarısız, devam ediliyor: ${error.message}`);          results.set(step.outputKey, { error: error.message });        } else if (step.onError === "rollback") {          await this.rollbackWorkflow(executionId, results);          throw error;        } else {          throw error;        }      }    }
    return {      executionId,      status: "completed",      results: Object.fromEntries(results),    };  }
  private async executeStep(    step: WorkflowStep,    context: Map<string, any>,    executionId: string  ): Promise<any> {    const agent = this.agents.get(step.agent);    const client = this.mcpClients.get(step.agent);
    if (!agent || !client) {      throw new Error(`Ajan ${step.agent} bulunamadı`);    }
    // İş akışı bağlamından parametreleri çöz    const params = this.resolveParams(step.params, context);
    // Yürütmeden önce izni doğrula    if (!this.checkToolPermission({ name: step.tool }, agent.permissions)) {      throw new Error(`Ajan ${step.agent}, araç ${step.tool} için izne sahip değil`);    }
    // Timeout ile yürüt    const result = await Promise.race([      client.callTool({ name: step.tool, arguments: params }),      this.timeout(step.timeout || 30000),    ]);
    // Denetim loglama    await this.auditLog({      executionId,      agent: step.agent,      tool: step.tool,      params,      result: result.isError ? "failure" : "success",      timestamp: new Date().toISOString(),    });
    if (result.isError) {      throw new Error(`Araç ${step.tool} başarısız: ${result.content[0]?.text}`);    }
    return result.content;  }
  private checkToolPermission(    tool: { name: string },    permissions: string[]  ): boolean {    // İzin formatı: "tool:*", "tool:read", "tool:deploy:staging"    for (const perm of permissions) {      if (perm === "tool:*") return true;      if (perm === `tool:${tool.name}`) return true;      if (perm.startsWith(`tool:${tool.name}:`)) return true;    }    return false;  }}

İş Akışı Tanımı Örneği

typescript
const productionDeploymentWorkflow: WorkflowDefinition = {  name: "production-deployment",  steps: [    {      name: "validate",      agent: "validator",      tool: "validate_deployment_config",      params: { service: "$.input.service", version: "$.input.version" },      outputKey: "validation",      onError: "abort",    },    {      name: "parallel-checks",      parallel: [        {          name: "health-check",          agent: "health-checker",          tool: "check_service_health",          params: { service: "$.input.service" },          outputKey: "health",          onError: "abort",        },        {          name: "security-scan",          agent: "security-scanner",          tool: "scan_vulnerabilities",          params: { version: "$.input.version" },          outputKey: "security",          onError: "abort",        },      ],      onError: "abort",    },    {      name: "get-approval",      agent: "approval-bot",      tool: "request_deployment_approval",      params: {        service: "$.input.service",        validation: "$.validation",        security: "$.security",      },      outputKey: "approval",      timeout: 300000, // İnsan onayı için 5 dakika      onError: "abort",    },    {      name: "deploy",      agent: "deployer",      tool: "deploy_service",      params: {        service: "$.input.service",        version: "$.input.version",        approvalId: "$.approval.id",      },      outputKey: "deployment",      onError: "rollback",    },  ],};

Kalıp 3: Rol Tabanlı Erişim Kontrolü

Kurumsal MCP deployment'ları ince taneli erişim kontrolü gerektirir. İşte RBAC'ı öznitelik tabanlı koşullarla birleştiren bir kalıp.

İzin Modeli

typescript
import { z } from "zod";
interface Permission {  resource: string;      // "tool:deploy_service", "resource:config:*"  action: string;        // "invoke", "read", "write"  conditions?: {         // İsteğe bağlı ABAC koşulları    environment?: string[];    timeWindow?: { start: string; end: string };    maxCost?: number;  };}
interface Role {  name: string;  permissions: Permission[];  inherits?: string[];   // Rol kalıtımı}
interface User {  id: string;  email: string;  roles: string[];  attributes: Record<string, any>;}

RBAC Servis Implementasyonu

typescript
class MCPAuthorizationService {  private roles: Map<string, Role> = new Map();
  constructor() {    this.initializeRoles();  }
  private initializeRoles(): void {    // Rol hiyerarşisini tanımla    const roles: Role[] = [      {        name: "viewer",        permissions: [          { resource: "tool:list_*", action: "invoke" },          { resource: "tool:get_*", action: "invoke" },          { resource: "tool:check_*", action: "invoke" },          { resource: "resource:*", action: "read" },        ],      },      {        name: "developer",        inherits: ["viewer"],        permissions: [          {            resource: "tool:deploy_service",            action: "invoke",            conditions: { environment: ["development", "staging"] },          },          { resource: "tool:run_tests", action: "invoke" },          { resource: "tool:build_artifact", action: "invoke" },        ],      },      {        name: "senior_developer",        inherits: ["developer"],        permissions: [          {            resource: "tool:deploy_service",            action: "invoke",            conditions: { environment: ["development", "staging", "production"] },          },          { resource: "tool:rollback_deployment", action: "invoke" },        ],      },      {        name: "admin",        permissions: [          { resource: "*", action: "*" },        ],      },    ];
    for (const role of roles) {      this.roles.set(role.name, role);    }  }
  async authorize(    user: User,    tool: string,    params: Record<string, any>  ): Promise<AuthorizationResult> {    const permissions = this.getEffectivePermissions(user);
    for (const perm of permissions) {      if (this.matchesResource(perm.resource, `tool:${tool}`)) {        if (perm.action === "*" || perm.action === "invoke") {          // ABAC koşullarını kontrol et          if (perm.conditions) {            const conditionResult = this.evaluateConditions(              perm.conditions,              params,              user            );            if (!conditionResult.allowed) {              return {                allowed: false,                reason: conditionResult.reason,                requiredElevation: this.suggestElevation(tool, params),              };            }          }          return { allowed: true };        }      }    }
    return {      allowed: false,      reason: `Kullanıcı ${user.email}, araç ${tool} için izne sahip değil`,      requiredElevation: this.suggestElevation(tool, params),    };  }
  private getEffectivePermissions(user: User): Permission[] {    const permissions: Permission[] = [];    const processedRoles = new Set<string>();
    const processRole = (roleName: string) => {      if (processedRoles.has(roleName)) return;      processedRoles.add(roleName);
      const role = this.roles.get(roleName);      if (!role) return;
      // Önce miras alınan rolleri işle (derinlik öncelikli)      if (role.inherits) {        for (const inherited of role.inherits) {          processRole(inherited);        }      }
      permissions.push(...role.permissions);    };
    for (const roleName of user.roles) {      processRole(roleName);    }
    return permissions;  }
  private evaluateConditions(    conditions: Permission["conditions"],    params: Record<string, any>,    user: User  ): { allowed: boolean; reason?: string } {    // Ortam kısıtlaması    if (conditions?.environment) {      const requestedEnv = params.environment;      if (!conditions.environment.includes(requestedEnv)) {        return {          allowed: false,          reason: `Ortam ${requestedEnv} izin verilmiyor. İzin verilenler: ${conditions.environment.join(", ")}`,        };      }    }
    // Zaman penceresi kısıtlaması    if (conditions?.timeWindow) {      const now = new Date();      const hour = now.getHours();      const [startHour] = conditions.timeWindow.start.split(":").map(Number);      const [endHour] = conditions.timeWindow.end.split(":").map(Number);
      if (hour < startHour || hour >= endHour) {        return {          allowed: false,          reason: `İşlem sadece ${conditions.timeWindow.start} ile ${conditions.timeWindow.end} arasında izin veriliyor`,        };      }    }
    return { allowed: true };  }
  private matchesResource(pattern: string, resource: string): boolean {    if (pattern === "*") return true;
    const regexPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");    return new RegExp(`^${regexPattern}$`).test(resource);  }}

Güvenli MCP Sunucu Entegrasyonu

typescript
class SecureMCPServer {  private server: McpServer;  private authService: MCPAuthorizationService;
  constructor(config: SecureServerConfig) {    this.server = new McpServer(config);    this.authService = new MCPAuthorizationService();  }
  secureTool(    name: string,    schema: z.ZodType,    options: ToolOptions,    handler: ToolHandler  ) {    this.server.tool(name, schema, options, async (params, context) => {      const user = context.meta?.user as User;
      if (!user) {        return {          content: [{ type: "text", text: "Kimlik doğrulama gerekli" }],          isError: true,        };      }
      // Yetkilendirmeyi kontrol et      const authResult = await this.authService.authorize(user, name, params);
      if (!authResult.allowed) {        // Reddedilen erişimi denetle        await this.auditLog({          action: "tool_denied",          user: user.email,          tool: name,          reason: authResult.reason,        });
        return {          content: [{            type: "text",            text: `Erişim reddedildi: ${authResult.reason}${              authResult.requiredElevation                ? `\n${authResult.requiredElevation}`                : ""            }`,          }],          isError: true,        };      }
      // Başarılı erişimi denetle      await this.auditLog({        action: "tool_invoked",        user: user.email,        tool: name,        params,      });
      return handler(params, context);    });  }}

Kalıp 4: Progresif Yetkilendirme

Tüm izinleri önceden vermek yerine, progresif yetkilendirme hassas işlemler için gerektiğinde scope'ları yükseltir.

typescript
class ProgressiveAuthorizationService {  private baseScopes = ["mcp:tools:read", "mcp:resources:read"];  private scopeHistory: Map<string, Set<string>> = new Map();
  async getInitialToken(userId: string): Promise<TokenResponse> {    const token = await this.oauthClient.getToken({      grant_type: "client_credentials",      scope: this.baseScopes.join(" "),      user_id: userId,    });
    this.scopeHistory.set(userId, new Set(this.baseScopes));    return token;  }
  async elevateScope(    userId: string,    requiredScope: string,    justification: string  ): Promise<ElevationResult> {    const currentScopes = this.scopeHistory.get(userId) || new Set();
    if (currentScopes.has(requiredScope)) {      return { elevated: true, token: await this.getCurrentToken(userId) };    }
    // İstenen scope için uygunluğu kontrol et    const canElevate = await this.checkElevationEligibility(userId, requiredScope);
    if (!canElevate.eligible) {      return {        elevated: false,        reason: canElevate.reason,        approvalRequired: true,        approvalWorkflow: this.getApprovalWorkflow(requiredScope),      };    }
    // Yükseltilmiş token iste    const elevatedToken = await this.oauthClient.getToken({      grant_type: "client_credentials",      scope: [...currentScopes, requiredScope].join(" "),      user_id: userId,      justification,    });
    currentScopes.add(requiredScope);    this.scopeHistory.set(userId, currentScopes);
    await this.auditLog({      action: "scope_elevated",      user: userId,      scope: requiredScope,      justification,    });
    return { elevated: true, token: elevatedToken };  }
  private getScopeRequirements(): Record<string, ScopeRequirement> {    return {      "mcp:deploy:staging": {        minRole: "developer",        requiresApproval: false,        expiresIn: 3600, // 1 saat      },      "mcp:deploy:production": {        minRole: "senior_developer",        requiresApproval: true,        approvers: ["tech-lead", "sre-oncall"],        expiresIn: 1800, // 30 dakika      },      "mcp:admin": {        minRole: "admin",        requiresApproval: true,        approvers: ["security-team"],        expiresIn: 900, // 15 dakika      },    };  }}

Kalıp 5: Hata İşleme ve Kurtarma

Production MCP deployment'ları, retry stratejileri ve circuit breaker'larla sağlam hata işleme gerektirir.

Hata Sınıflandırması

typescript
enum MCPErrorCode {  // Protokol hataları  PARSE_ERROR = -32700,  INVALID_REQUEST = -32600,  METHOD_NOT_FOUND = -32601,  INVALID_PARAMS = -32602,  INTERNAL_ERROR = -32603,
  // Araca özgü hatalar  TOOL_EXECUTION_FAILED = -32000,  TOOL_TIMEOUT = -32001,  TOOL_UNAUTHORIZED = -32002,  TOOL_RATE_LIMITED = -32003,  TOOL_DEPENDENCY_FAILED = -32004,}
interface RecoverableError {  code: MCPErrorCode;  message: string;  retryable: boolean;  retryAfterMs?: number;  suggestedAction?: string;}

Retry Mantıklı Hata İşleyici

typescript
class MCPErrorHandler {  private retryPolicies: Map<MCPErrorCode, RetryPolicy> = new Map([    [MCPErrorCode.TOOL_TIMEOUT, { maxRetries: 3, backoffMs: 1000, multiplier: 2 }],    [MCPErrorCode.TOOL_DEPENDENCY_FAILED, { maxRetries: 5, backoffMs: 500, multiplier: 1.5 }],    [MCPErrorCode.TOOL_RATE_LIMITED, { maxRetries: 3, backoffMs: 5000, multiplier: 2 }],  ]);
  async executeWithRecovery<T>(    toolName: string,    executor: () => Promise<T>,    timeoutMs: number = 30000  ): Promise<T> {    let lastError: RecoverableError | null = null;    let attempt = 0;
    while (true) {      try {        return await Promise.race([          executor(),          this.createTimeout(timeoutMs),        ]);      } catch (error) {        lastError = this.classifyError(error, toolName);        attempt++;
        console.log(`Araç ${toolName} başarısız (deneme ${attempt}):`, {          code: lastError.code,          message: lastError.message,          retryable: lastError.retryable,        });
        if (!lastError.retryable) break;
        const policy = this.retryPolicies.get(lastError.code);        if (!policy || attempt >= policy.maxRetries) break;
        const backoff = policy.backoffMs * Math.pow(policy.multiplier, attempt - 1);        const jitter = Math.random() * 0.1 * backoff;
        await this.sleep(backoff + jitter);      }    }
    throw this.createToolError(lastError!, toolName);  }
  private classifyError(error: any, toolName: string): RecoverableError {    if (error.code === "ETIMEDOUT" || error.message?.includes("timeout")) {      return {        code: MCPErrorCode.TOOL_TIMEOUT,        message: `Araç ${toolName} zaman aşımına uğradı`,        retryable: true,        suggestedAction: "Servis sağlığını kontrol edin veya timeout'u artırın",      };    }
    if (error.response?.status === 429) {      return {        code: MCPErrorCode.TOOL_RATE_LIMITED,        message: `Araç ${toolName} rate limit'e ulaştı`,        retryable: true,        retryAfterMs: parseInt(error.response.headers["retry-after"]) * 1000 || 5000,      };    }
    if (error.response?.status >= 500) {      return {        code: MCPErrorCode.TOOL_DEPENDENCY_FAILED,        message: `Araç ${toolName} backend hatası`,        retryable: true,      };    }
    return {      code: MCPErrorCode.TOOL_EXECUTION_FAILED,      message: `Araç ${toolName} başarısız: ${error.message}`,      retryable: false,    };  }}

Circuit Breaker Kalıbı

typescript
class CircuitBreaker {  private state: "closed" | "open" | "half-open" = "closed";  private failures = 0;  private lastFailureTime = 0;
  constructor(    private readonly threshold: number = 5,    private readonly resetTimeout: number = 30000  ) {}
  async execute<T>(operation: () => Promise<T>): Promise<T> {    if (this.state === "open") {      if (Date.now() - this.lastFailureTime > this.resetTimeout) {        this.state = "half-open";      } else {        throw new Error("Circuit breaker açık");      }    }
    try {      const result = await operation();      this.onSuccess();      return result;    } catch (error) {      this.onFailure();      throw error;    }  }
  private onSuccess(): void {    this.failures = 0;    this.state = "closed";  }
  private onFailure(): void {    this.failures++;    this.lastFailureTime = Date.now();
    if (this.failures >= this.threshold) {      this.state = "open";      console.log(`Circuit breaker ${this.failures} hatadan sonra açıldı`);    }  }}

Kalıp 6: Gözlemlenebilirlik Stack'i

Production MCP deployment'ları metrikler, tracing ve denetim loglama genelinde kapsamlı gözlemlenebilirlik gerektirir.

typescript
import { trace, SpanStatusCode } from "@opentelemetry/api";import { Counter, Histogram, Gauge } from "prom-client";
class MCPObservability {  private tracer = trace.getTracer("mcp-server");
  // Prometheus metrikleri  private requestCounter = new Counter({    name: "mcp_tool_requests_total",    help: "Toplam MCP araç çağrıları",    labelNames: ["tool", "status", "user_role"],  });
  private requestDuration = new Histogram({    name: "mcp_tool_duration_seconds",    help: "MCP araç yürütme süresi",    labelNames: ["tool"],    buckets: [0.1, 0.5, 1, 2, 5, 10, 30],  });
  private activeRequests = new Gauge({    name: "mcp_active_requests",    help: "Şu anda yürütülen MCP istekleri",  });
  async observedToolExecution<T>(    toolName: string,    user: User,    params: Record<string, any>,    executor: () => Promise<T>  ): Promise<T> {    return this.tracer.startActiveSpan(`tool:${toolName}`, async (span) => {      const startTime = Date.now();      this.activeRequests.inc();
      try {        span.setAttributes({          "mcp.tool.name": toolName,          "mcp.user.id": user.id,          "mcp.user.role": user.roles.join(","),          "mcp.params": JSON.stringify(this.sanitizeParams(params)),        });
        const result = await executor();
        span.setStatus({ code: SpanStatusCode.OK });        this.requestCounter.inc({          tool: toolName,          status: "success",          user_role: user.roles[0],        });
        return result;      } catch (error) {        span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });        span.recordException(error);
        this.requestCounter.inc({          tool: toolName,          status: "error",          user_role: user.roles[0],        });
        throw error;      } finally {        const duration = (Date.now() - startTime) / 1000;        this.requestDuration.observe({ tool: toolName }, duration);        this.activeRequests.dec();        span.end();      }    });  }
  private sanitizeParams(params: Record<string, any>): Record<string, any> {    const sensitiveKeys = ["password", "token", "secret", "apiKey"];    const sanitized = { ...params };
    for (const key of Object.keys(sanitized)) {      if (sensitiveKeys.some(s => key.toLowerCase().includes(s))) {        sanitized[key] = "[REDACTED]";      }    }
    return sanitized;  }}

Uyumluluk için Denetim Loglama

typescript
class AuditLogger {  private buffer: AuditEvent[] = [];
  constructor(private config: AuditConfig) {    // Her 10 saniyede batch flush    setInterval(() => this.flush(), 10000);  }
  log(event: {    action: string;    user: User;    resource: string;    result: "success" | "failure" | "denied";    params?: Record<string, any>;  }): void {    const auditEvent: AuditEvent = {      timestamp: new Date().toISOString(),      eventId: crypto.randomUUID(),      userId: event.user.id,      userEmail: event.user.email,      userRoles: event.user.roles,      action: event.action,      resource: event.resource,      params: this.sanitizeForAudit(event.params),      result: event.result,      serverVersion: this.config.serverVersion,      environment: this.config.environment,    };
    this.buffer.push(auditEvent);
    // Güvenlik açısından kritik olaylar için anında flush    if (event.result === "denied" || this.isCriticalAction(event.action)) {      this.flush();    }  }
  private async flush(): Promise<void> {    if (this.buffer.length === 0) return;
    const batch = [...this.buffer];    this.buffer = [];
    try {      await Promise.all([        this.sendToCloudWatch(batch),        this.writeToLocalLog(batch),      ]);    } catch (error) {      console.error("Denetim flush başarısız:", error);      this.buffer.unshift(...batch); // Başarısız olayları yeniden kuyruğa al    }  }
  private isCriticalAction(action: string): boolean {    return ["deploy:production", "delete", "permission_change", "scope_elevation"]      .some(c => action.includes(c));  }}

Nereden Başlamalı: Kurumsal MCP Oluşturma

Bu yazıdaki kalıplar bunaltıcı gelebilir. İşte takılıp kalmadan implementasyona nasıl yaklaşılacağı.

Yetkilendirme değil, kimlik doğrulama ile başlayın. İnce taneli RBAC hakkında endişelenmeden önce temel kimlik doğrulamayı çalıştırın. Token'ları doğrulayan ve isteklere kullanıcı bağlamı ekleyen basit bir middleware yeterli. İzinleri daha sonra üzerine katmanlayabilirsiniz.

Soyutlamadan önce bir iş akışını uçtan uca çalıştırın. Cazip olan genel amaçlı bir orkestratör oluşturmak. Direneyin. En kritik çoklu adımlı operasyonunuzu seçin ve iş akışını hardcode'layın. Kalıpları ancak karşılaştırmak için iki veya üç çalışan iş akışınız olduğunda çıkarın.

Gözlemlenebilirliği sorunlar ortaya çıktıktan sonra değil, erken ekleyin. İlk MCP sunucunuzu birinci günden metrikler ve tracing ile enstrümante edin. Yetkilendirme sorunları ortaya çıktığında (ve çıkacaklar), neler olduğunu görebildiğiniz için kendinize teşekkür edeceksiniz.

Progresif yetkilendirme karmaşıklığa değer. Kullanıcıları minimal scope'larla başlatıp talep üzerine yükseltmek, baştan geniş izinler vermekten daha fazla iş gibi görünüyor. Ama sağladığı güvenlik duruşu ve denetim netliği yatırımı haklı çıkarır. Retrofit etmek için çok fazla aracınız olmadan önce implement edin.

Circuit breaker'lar basamaklı hataları önler. MCP sunucularınız harici servisleri çağırıyorsa (veritabanları, API'ler, diğer servisler), bu çağrıları hemen circuit breaker'larla sarın. Onlar olmadan yavaş bir bağımlılık tüm ajan sisteminizi çökertebilir.

Anahtar prensip: her kalıp belirli bir ölçeklendirme ağrı noktasını ele alır. Kalıpları acıyı hissettiğinizde implement edin, öncesinde değil. Temel auth ile çalışan bir sistem, mükemmel RBAC ile tamamlanmamış bir sistemden iyidir.

Yaygın Tuzaklar

Aşırı İzin Verme

Geliştirme sırasında yetkilendirme hatalarından kaçınmak için geniş izinler vermek güvenlik borcu yaratır. Minimal başlayın, gerçek ihtiyaçlara göre kademeli olarak ekleyin.

Monolitik Araçlar

Her şeyi yapan büyük araçlar oluşturmak onları güvenliğini sağlamayı, test etmeyi ve birleştirmeyi zorlaştırır. Birbirine zincirlenen küçük, odaklı araçlar tasarlayın.

Kısmi Hataları Görmezden Gelme

İş akışlarının ya tamamen başarılı ya da tamamen başarısız olduğunu varsaymak tutarsız durumlara yol açar. İş akışı durumunu izleyin, telafi eylemleri uygulayın ve hata noktalarından devam etmeyi destekleyin.

Context Penceresi Körlüğü

Araçlardan aşırı veri döndürmek context penceresi kapasitesini boşa harcar. Sadece ilgili verileri döndürün, yapısal output şemaları kullanın ve büyük sonuçlar için progresif yükleme uygulayın.

Sonradan Düşünülen Güvenlik

İlk implementasyondan sonra güvenlik eklemek mimari yeniden çalışmaya yol açar. RBAC'ı ilk günden tasarlayın, herhangi bir araçtan önce güvenlik middleware'i uygulayın.

Temel Çıkarımlar

RBAC temeldir: Kurumsal deployment'lar için isteğe bağlı değil. İzin modelinizi erken tasarlayın.

Progresif yetkilendirme çalışır: Minimal scope'larla başlayın, gerektiğinde yükseltin. Her şeyi önceden yetkilendirmeyin.

Birleştirilebilir araçlar daha iyi ölçeklenir: Birbirine zincirlenen küçük araçlar, monolitik alternatiflerden daha bakımı yapılabilir ve esnek.

Kısmi hatalar için plan yapın: İş akışları devam ettirilebilir olmalı. Durumu izleyin ve telafi kalıpları uygulayın.

Gözlemlenebilirlik her şeyi mümkün kılar: Ölçemediğinizi güvenliğini sağlayamaz veya optimize edemezsiniz. Baştan metrikler, tracing ve denetim loglamaya yatırım yapın.

Gateway kalıbı operasyonları basitleştirir: Çoklu sunucu deployment'ları için bir gateway kimlik doğrulama, yönlendirme ve izlemeyi merkezileştirir.

Kaynaklar

İlgili Yazılar