Bloglara Dön

MCP Sunucusu Nasıl Yazılır? Pratik Örnek

MCP sunucusu yazmak sanılandan çok daha kolaydır. Bu rehberde TypeScript SDK ile bir “task manager” MCP sunucusu kuracağız. Rehberi bitirdiğinizde kendi araçlarınızı Claude Desktop, Cursor veya VS Code gibi client’lara bağlayabileceksiniz.

MCP’nin gücü tek bir sunucu yazıp birden fazla client tarafından paylaşılabilmesinde. Ekibinizin dahili araçlarını bir kez MCP sunucusu olarak yazın; herkes kendi tercih ettiği AI ürününde kullansın.

1. Kurulum

mkdir mcp-task-manager && cd mcp-task-manager
npm init -y
npm i @modelcontextprotocol/sdk zod better-sqlite3
npm i -D typescript @types/node tsx
npx tsc --init

2. Basit Sunucu Kodu

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: "task-manager",
  version: "1.0.0"
});

server.tool(
  "add_task",
  "Yeni bir görev ekler",
  { title: z.string(), priority: z.enum(["low","medium","high"]).default("medium") },
  async ({ title, priority }) => ({
    content: [{
      type: "text",
      text: `Görev eklendi: ${title} (${priority})`
    }]
  })
);

const transport = new StdioServerTransport();
await server.connect(transport);

3. Kalıcı Depolama Ekleme

import Database from "better-sqlite3";

const db = new Database("tasks.db");
db.exec(`CREATE TABLE IF NOT EXISTS tasks (
  id INTEGER PRIMARY KEY,
  title TEXT,
  priority TEXT,
  done INTEGER DEFAULT 0
)`);

server.tool("add_task", { title: z.string() }, async ({ title }) => {
  const result = db.prepare("INSERT INTO tasks (title, priority) VALUES (?, ?)")
    .run(title, "medium");
  return { content: [{ type: "text", text: `Eklendi (id ${result.lastInsertRowid})` }] };
});

server.tool("list_tasks", {}, async () => {
  const tasks = db.prepare("SELECT * FROM tasks WHERE done = 0").all();
  return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
});

4. Claude Desktop Entegrasyonu

claude_desktop_config.json içine ekleyin:

{
  "mcpServers": {
    "task-manager": {
      "command": "npx",
      "args": ["tsx", "/path/to/mcp-task-manager/index.ts"]
    }
  }
}

Claude Desktop’ı restart edin. Sağ alttaki 🔧 ikonunda add_task ve list_tasks görünecek.

5. Resource Ekleme

Model’in okuyabileceği veri (dosya, veritabanı satırı, URL) tanımlayın:

server.resource(
  "task://{id}",
  new ResourceTemplate("task://{id}", { list: undefined }),
  async (uri, { id }) => ({
    contents: [{
      uri: uri.href,
      text: JSON.stringify(db.prepare("SELECT * FROM tasks WHERE id = ?").get(id))
    }]
  })
);

6. Test

Claude’a “Yeni bir görev ekle: sunucu güncelle” yazın; MCP sunucunuz çağrılacak. “Görevleri listele” dediğinizde list_tasks aracını çağıracak.

7. HTTP Transport (Uzak Sunucu)

import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import express from "express";

const app = express();
app.post("/mcp", async (req, res) => {
  const transport = new StreamableHTTPServerTransport({});
  await server.connect(transport);
  await transport.handleRequest(req, res);
});
app.listen(3000);

8. Güvenlik

  • OAuth 2.1 ile kimlik doğrulama.
  • Kullanıcı bazlı yetkilendirme.
  • Kritik aksiyonlar için insan onayı (elicitation).
  • Rate limiting.
  • Loglama ve monitoring.

Sonraki Adımlar

  • Prompts tanımı (kullanıcıya hazır şablon).
  • Sampling ile sunucu → model çağrısı.
  • Progress notifications ile uzun süren işlemlerde ilerleme bildirimi.
  • Multi-tenant destek.
  • Docker + Kubernetes ile dağıtım.

Sıkça Sorulan Sorular

Python ile yazabilir miyim?

Evet, resmi Python SDK mevcut.

Cursor ile de çalışır mı?

Evet, Cursor v0.42+ MCP’yi destekliyor.

Sonuç

50-100 satırın altında bir MCP sunucusu yazıp gerçek bir agent’a bağlamak mümkün. Bu, agentic AI dünyasına en hızlı giriş noktalarından biri. Bir kez kurduğunuz altyapı; şirket içi tüm ekiplere aynı standarda erişim sağlar.