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.