Model Context Protocol, kısaca MCP, yapay zeka modellerinin dış sistemlere bağlanmasını standart bir arayüzle sağlayan açık kaynak bir protokoldür. MCP server yazmak, bir AI asistanının şirketinizin veritabanına, ERP sistemine veya dahili API’ye erişmesini mümkün kılar. Bu rehberde sıfırdan bir MCP server oluşturmak için gereken Python kurulumunu, temel araç tanımlarını ve kurumsal ortamda dikkat edilmesi gereken güvenlik kurallarını ele alıyoruz.

MCP nedir ve neden kendi server’ınızı yazmak ister misiniz

MCP, Claude, GPT-4 veya benzeri modellerin harici araçlara standart bir protokol üzerinden bağlanmasına olanak tanır. Bunu bir USB-C konektörüne benzetebilirsiniz: her cihaz aynı bağlantıyı anlıyor, her yazılım aynı standarda göre yazılıyor.

Anthropic, MCP’yi 2024 sonunda açık kaynak olarak yayımladı. 2026 itibarıyla Cursor, Claude Desktop ve pek çok kurumsal araç MCP’yi destekliyor. Topluluk tarafından yazılmış yüzlerce hazır server var; ancak şirkete özel sistemler için kendi server’ınızı yazmanız gerekiyor.

Kendi server’ınızı yazmanın iki temel nedeni vardır. Birincisi, şirkete özel bir sisteme bağlanmak istiyorsunuzdur: dahili CRM, kendi geliştirdiğiniz veritabanı, özel API. Mevcut hazır server’lar bu sistemi tanımaz. İkincisi, mevcut server’ların izin verdiğinden farklı bir davranış tanımlamak istiyorsunuzdur.

Geliştirme ortamı kurulumu

Python 3.10 veya üzeri bir sürüm gereklidir. MCP’nin resmi Python SDK’sını kurmak için şu komutu çalıştırın:

pip install mcp

uv kullanıyorsanız:

uv add mcp

Proje klasörünüzü oluşturun:

mkdir mcp-kurumsal-server

cd mcp-kurumsal-server

touch server.py

Temel MCP server yapısı

Aşağıdaki kod, çalışan minimal bir MCP server örneğidir. Bu server, Claude Desktop veya Cursor’a “çalışan bilgisi getir” adında tek bir araç sunuyor:

from mcp.server import Server

from mcp.server.stdio import stdio_server

from mcp.types import Tool, TextContent

import asyncio

import json

# Örnek dahili veri — gerçek ortamda bu bir veritabanı sorgusu olur

CALISANLAR = {

    "EMP001": {"ad": "Ayşe Kaya", "departman": "Pazarlama", "kıdem": "Senior"},

    "EMP002": {"ad": "Mehmet Yılmaz", "departman": "Mühendislik", "kıdem": "Mid"},

}

server = Server("kurumsal-hr-server")

@server.list_tools()

async def list_tools():

    return [

        Tool(

            name="calisan_bilgisi_getir",

            description="Çalışan ID'sine göre ad, departman ve kıdem bilgisini döndürür.",

            inputSchema={

                "type": "object",

                "properties": {

                    "calisan_id": {

                        "type": "string",

                        "description": "Çalışanın benzersiz kimlik numarası (örn: EMP001)"

                    }

                },

                "required": ["calisan_id"]

            }

        )

    ]

@server.call_tool()

async def call_tool(name: str, arguments: dict):

    if name == "calisan_bilgisi_getir":

        calisan_id = arguments.get("calisan_id")

        calisan = CALISANLAR.get(calisan_id)

        

        if not calisan:

            return [TextContent(type="text", text=f"'{calisan_id}' ID'li çalışan bulunamadı.")]

        

        sonuc = json.dumps(calisan, ensure_ascii=False, indent=2)

        return [TextContent(type="text", text=sonuc)]

    

    return [TextContent(type="text", text=f"Bilinmeyen araç: {name}")]

async def main():

    async with stdio_server() as (read_stream, write_stream):

        await server.run(read_stream, write_stream, server.create_initialization_options())

if __name__ == "__main__":

    asyncio.run(main())

Bu kodu çalıştırmak için:

python server.py

Server stdio üzerinden çalışır; Claude Desktop veya Cursor bu server’ı başlatır ve araçları keşfeder.

Claude Desktop’a server’ı bağlamak

Claude Desktop’un konfigürasyon dosyasını açın:

macOS:

~/Library/Application Support/Claude/claude_desktop_config.json

Windows:

%APPDATA%\Claude\claude_desktop_config.json

Dosyaya şunu ekleyin:

{

  "mcpServers": {

    "kurumsal-hr": {

      "command": "python",

      "args": ["/tam/yol/server.py"]

    }

  }

}

Claude Desktop’u yeniden başlatın. Artık Claude, “EMP001 numaralı çalışanın bilgisini getir” gibi bir istekle server’ınızı çağırabilir.

Gerçek bir veritabanıyla çalışmak

Üretim ortamında veriler sabit bir sözlükten değil, veritabanından gelir. SQLite ile basit bir entegrasyon örneği:

import sqlite3

def calisan_sorgula(calisan_id: str) -> dict | None:

    conn = sqlite3.connect("sirket.db")

    cursor = conn.cursor()

    

    cursor.execute(

        "SELECT ad, departman, kidem FROM calisanlar WHERE id = ?",

        (calisan_id,)

    )

    row = cursor.fetchone()

    conn.close()

    

    if row:

        return {"ad": row[0], "departman": row[1], "kıdem": row[2]}

    return None

PostgreSQL, MySQL veya kurumsal bir ORM kullanıyorsanız aynı mantık geçerlidir: araç handler’ı içinde veritabanı bağlantısı kurun, sorguyu çalıştırın ve sonucu döndürün.

Kurumsal ortamda güvenlik kuralları

MCP server, bir yapay zeka modelinin doğrudan çağırabileceği araçları barındırır. Bu nedenle güvenlik, geliştirmenin başından itibaren tasarıma dahil edilmelidir.

Araç kapsamını minimize edin. Server yalnızca gerçekten gerekli araçları sunmalıdır. “Her şeyi okuyabilir” bir araç tanımlamak yerine “yalnızca ilgili departmanın verilerini oku” şeklinde kısıtlayın.

Giriş doğrulaması yapın. Her araç handler’ında gelen parametreleri doğrulayın. SQL injection ve benzeri saldırılara karşı hazır olun. Parametreli sorgular kullanın, string birleştirme yapmayın.

Hassas veri döndürmeyin. Bir araç çalışan bilgisi getiriyorsa maaş, TC kimlik numarası veya ev adresi gibi hassas alanları API yanıtına dahil etmeyin. Yanıtı minimize edin.

Loglama ekleyin. Her araç çağrısını, kim tarafından ve hangi parametrelerle çağrıldığını kaydedin. Bu kayıtlar hem hata ayıklama hem de güvenlik denetimi için gereklidir:

import logging

logging.basicConfig(level=logging.INFO)

logger = logging.getLogger(__name__)

@server.call_tool()

async def call_tool(name: str, arguments: dict):

    logger.info(f"Araç çağrıldı: {name} | Parametreler: {arguments}")

    # ...

Ortam değişkenleri kullanın. Veritabanı şifreleri, API anahtarları veya bağlantı URL’leri asla kod içinde sabit yazılmamalıdır. .env dosyası ve python-dotenv kütüphanesi bu ihtiyacı karşılar.

Birden fazla araç tanımlamak

Gerçek kurumsal server’lar genellikle birden fazla araç içerir. Örneğin bir İK server’ı şu araçları barındırabilir: çalışan bilgisi getirme, departman listesi çekme, açık pozisyon sorgulama ve izin bakiyesi görüntüleme. Her araç için ayrı bir handler yazılır ve list_tools fonksiyonu tüm araçları listeler.

Bu mimariyi derinlemesine uygulamak ve kurumsal entegrasyon senaryolarını adım adım öğrenmek isteyenler için Model Context Protocol Eğitimi programı, server geliştirmeden kurumsal dağıtıma kadar tüm süreci kapsıyor.

MCP server’ı production ortamına almak

Geliştirme ortamında çalışan bir server’ı production’a taşırken birkaç adım gereklidir. Öncelikle server’ın bir process manager (örneğin PM2 veya systemd) tarafından yönetilmesi sağlanmalıdır. Sistem yeniden başlarsa server da otomatik olarak kalkmadır.

Server’ın Docker container içinde çalıştırılması da yaygın bir yaklaşımdır. Bu sayede bağımlılıklar izole edilir ve dağıtım tekrarlanabilir hale gelir.

Çok kullanıcılı kurumsal ortamlarda server’ın hangi kullanıcı adına çalıştığı ve hangi verilere erişim izni olduğu başlı başına bir tasarım kararıdır. “Tüm kullanıcılar aynı veri havuzuna erişebilir” ile “her kullanıcı yalnızca kendi verilerine erişir” arasındaki seçim, server mimarisini doğrudan etkiler.