mcp model context protocol python ai agent llm araçları claude desktop mcp server

MCP Server Nasıl Yazılır? Python ile Adım Adım Rehber

Orta
person Yapay Zeka Uzmanı
list_altİçindekilerexpand_more
  1. 01Kurulum ve Gereksinimler
  2. 02İlk MCP Server: Basit Bir Tool
  3. 03Pratik Tool Örnekleri
  4. 04Dosya okuma tool’u
  5. 05Hesap makinesi tool’u
  6. 06Resource ve Prompt Ekleme
  7. 07Claude Desktop’a Bağlama
  8. 08SSE Transport: Remote Server
  9. 09Hata Ayıklama İpuçları
  10. 10Birden Fazla Tool’u Modüler Yönetme
  11. 11MCP’nin Ötesi: Agent Mimarileri
  12. 12Sonraki Adımlar
Editorial tech-magazine cover illustration about Python MCP server development and API communication, server-to-client connection diagrams, glowing JSON-RPC data nodes, abstract artificial-intelligence motifs (glowing neural networks, flowing data, subtle circuitry), sophisticated modern concept art, clean balanced composition, soft cinematic studio lighting, rich depth of field, premium color grading in deep navy blues with cyan and magenta accents, highly detailed, polished editorial 8k. No text, no words, no letters, no captions, no logos, no watermark, no UI.

Hazır MCP server’lar bir noktaya kadar yeterli. Dosya sistemi, GitHub, web tarama… bunlar herkese lazım olduğu için zaten paketlenmiş. Ancak kendi şirket veritabanına, iç API’ına ya da özel bir iş akışına bağlanmak istediğinde hazır server bulamazsın. O noktada tek seçenek kendi server’ını yazmak.

Bu rehberde sıfırdan başlayıp Claude Desktop’a bağlanabilen, gerçek bir tool barındıran bir MCP server oluşturacağız. Kodlar çalışır durumdadır, kopyala-yapıştır düzeyinde.

MCP’nin ne olduğunu ve neden 2026’nın standart entegrasyon katmanı haline geldiğini biliyorsan doğrudan kuruluma geçebilirsin. Bilmiyorsan o makaleye önce göz atmak işi hızlandırır.

Kurulum ve Gereksinimler

Python 3.10 veya üstü gerekiyor. uv paket yöneticisi kullanıyorsan kurulum tek komut:

uv add mcp

Klasik pip ile de aynı sonuç:

pip install mcp

Bağımlılıkları doğrulamak için:

python -c "import mcp; print(mcp.__version__)"

Test ortamı için Claude Desktop’u indirmişsen claude_desktop_config.json dosyasına erişimin olacak. macOS’ta bu dosya ~/Library/Application Support/Claude/ içinde, Windows’ta %APPDATA%\Claude\ içinde.

İlk MCP Server: Basit Bir Tool

Bir MCP server, model ile dış sistemler arasında duran basit bir Python süreci. Model bir tool çağırdığında server kodu çalışır, sonuç JSON olarak modele döner.

Aşağıdaki kod tam çalışır bir server örneği. Bir tool barındırır: girilen metni büyük harfe çevirir.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("ilk-server")

@mcp.tool()
def buyuk_harf(metin: str) -> str:
    """Girilen metni büyük harfe çevirir."""
    return metin.upper()

if __name__ == "__main__":
    mcp.run()

@mcp.tool() dekoratörü fonksiyonu otomatik olarak bir MCP tool’una dönüştürür. Fonksiyonun docstring’i modele tanımlama olarak iletilir; bu yüzden açıklayıcı yazmak önemli. Python tip belirteçleri (str, int, list[str] vb.) tool’un input schema’sını oluşturur.

Varsayılan transport stdio’dur. Server çalışınca stdin/stdout üzerinden JSON-RPC mesajları bekler. Claude Desktop da dahil tüm yerel istemciler bu transport’u destekler.

Pratik Tool Örnekleri

Gerçek bir server’da birden fazla tool olur. Aşağıda iki yaygın senaryo var: dosya okuma ve hesaplama.

Dosya okuma tool’u

from mcp.server.fastmcp import FastMCP
from pathlib import Path

mcp = FastMCP("dosya-server")

@mcp.tool()
def dosya_oku(yol: str) -> str:
    """Belirtilen dosya yolundaki metni okur ve döndürür."""
    dosya = Path(yol)
    if not dosya.exists():
        return f"Hata: {yol} bulunamadı."
    if not dosya.is_file():
        return f"Hata: {yol} bir dosya değil."
    try:
        return dosya.read_text(encoding="utf-8")
    except Exception as e:
        return f"Okuma hatası: {e}"

@mcp.tool()
def dizin_listele(yol: str) -> list[str]:
    """Belirtilen dizindeki dosya ve klasör adlarını listeler."""
    dizin = Path(yol)
    if not dizin.is_dir():
        return [f"Hata: {yol} bir dizin değil."]
    return [oge.name for oge in dizin.iterdir()]

if __name__ == "__main__":
    mcp.run()

Bu tool’u Claude ile test ettiğinde şunu söyleyebilirsin: “Desktop’umdaki rapor.txt dosyasını okur musun?” Claude, dosya_oku tool’unu çağırır, sonucu kullanıcıya sunar.

Hesap makinesi tool’u

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hesap-server")

@mcp.tool()
def topla(a: float, b: float) -> float:
    """İki sayıyı toplar."""
    return a + b

@mcp.tool()
def yuzde_hesapla(toplam: float, yuzde: float) -> float:
    """Toplam değerin belirtilen yüzdesini hesaplar."""
    return toplam * (yuzde / 100)

@mcp.tool()
def faiz_hesapla(anapara: float, faiz_orani: float, yil: int) -> float:
    """Basit faiz formülüyle toplam tutarı hesaplar."""
    return anapara * (1 + faiz_orani / 100) ** yil

if __name__ == "__main__":
    mcp.run()

Tool’ların type hint’leri burada kritik. float ve int yazmazsan model yanlış tipte argüman gönderebilir.

Resource ve Prompt Ekleme

Tool’ların yanı sıra MCP iki farklı yapıyı daha destekler: resource ve prompt.

Resource, modele bağlam olarak sunulan statik ya da dinamik veridir. Tool gibi çalıştırılmaz, doğrudan okunur. Bir veritabanı şeması, API dokümantasyonu ya da konfigürasyon dosyası resource için uygun adaydır.

@mcp.resource("config://uygulama-ayarlari")
def uygulama_ayarlari() -> str:
    """Uygulama konfigürasyonunu döndürür."""
    return """
    ortam: production
    log_seviyesi: INFO
    maks_istek: 100
    """

Prompt, sık kullanılan talimat şablonlarını model ile paylaşmak için kullanılır. Model istemci prompt’ları listeleyebilir ve seçilen prompt’u doğrudan konuşma bağlamına ekleyebilir.

@mcp.prompt()
def kod_inceleme() -> str:
    """Kod inceleme için standart talimat seti."""
    return """
    Kodu şu kriterlere göre değerlendir:
    1. Güvenlik açıkları
    2. Performans sorunları
    3. Okunabilirlik
    4. Test kapsamı eksiklikleri
    Bulgular için her maddeyi ayrı bir paragrafta yaz.
    """

Tool’dan farkı: tool bir eylem gerçekleştirir ve sonuç döndürür; resource ile prompt bağlam sağlar. Function calling mekanizmasının LLM sistemleriyle nasıl çalıştığını anlıyorsan tool/resource ayrımı daha net oturur.

Claude Desktop’a Bağlama

Server’ı yazdıktan sonra Claude Desktop’a tanıtmak gerekir. Bunun için claude_desktop_config.json dosyasını düzenlersin.

macOS için dosya yolu:

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

Windows için dosya yolu:

%APPDATA%\Claude\claude_desktop_config.json

Dosyada şu formatta bir mcpServers bloğu ekle:

{
  "mcpServers": {
    "dosya-server": {
      "command": "python",
      "args": ["/Users/kullanici/projeler/dosya-server.py"]
    }
  }
}

uv ile çalıştırıyorsan:

{
  "mcpServers": {
    "dosya-server": {
      "command": "uv",
      "args": ["run", "/Users/kullanici/projeler/dosya-server.py"]
    }
  }
}

Dosyayı kaydedip Claude Desktop’u yeniden başlat. Sol alt köşedeki eklenti simgesine tıkla; server’ının tool’larını listede görmelisin. Tool isimleri görünüyorsa bağlantı başarılı.

Birden fazla server eklemek için mcpServers nesnesine yeni anahtarlar eklersin:

{
  "mcpServers": {
    "dosya-server": {
      "command": "python",
      "args": ["/projeler/dosya-server.py"]
    },
    "hesap-server": {
      "command": "python",
      "args": ["/projeler/hesap-server.py"]
    }
  }
}

SSE Transport: Remote Server

Stdio transport yalnızca aynı makinedeki istemciler için geçerli. Eğer server’ı bir bulut ortamında barındırıp birden fazla istemcinin erişmesini istiyorsan SSE (Server-Sent Events) transport kullanman gerekir.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("uzak-server")

@mcp.tool()
def sunucu_saati() -> str:
    """Sunucunun o anki saatini döndürür."""
    from datetime import datetime
    return datetime.now().isoformat()

if __name__ == "__main__":
    mcp.run(transport="sse", host="0.0.0.0", port=8080)

Bu server http://sunucu-ip:8080/sse adresinde dinler. İstemci tarafında bağlantı URL’si şöyle görünür:

{
  "mcpServers": {
    "uzak-server": {
      "url": "http://sunucu-ip:8080/sse"
    }
  }
}

SSE transport’u ne zaman tercih etmeli?

  • Birden fazla kullanıcının aynı server’a erişeceği durumlarda
  • Server’ın kendi makinende değil bir VPS ya da konteynerde çalıştığı durumlarda
  • Uzun süreli bağlantıların gerektiği streaming senaryolarında

Yerel geliştirme için stdio her zaman daha basittir. SSE, üretim ortamı ya da ekip paylaşımı için devreye girer.

Hata Ayıklama İpuçları

MCP server’larında en yaygın sorunlar şunlar:

Server başlamıyor. Python yolu yanlıştır ya da bağımlılık eksiktir. Terminal’de server’ı doğrudan çalıştırıp hata mesajını gör:

python /projeler/dosya-server.py

Hata yoksa stdin bekler (normal). Ctrl+C ile çık.

Tool’lar Claude’da görünmüyor. Config dosyasını kaydettiğinde Claude Desktop’u yeniden başlatmayı unutmuş olabilirsin. Alternatif olarak JSON sözdiziminde hata olabilir; bir JSON doğrulayıcıya yapıştır.

Tool çağrısı çalışmıyor. Fonksiyon imzasını kontrol et. Tip belirteçleri yanlışsa model yanlış argüman gönderir. str | None gibi opsiyonel parametre varsa = None varsayılan değerini de ekle.

MCP Inspector resmi hata ayıklama aracıdır. Terminal üzerinden server’ına bağlanıp tool’ları test edebilirsin:

npx @modelcontextprotocol/inspector python /projeler/server.py

Tarayıcıda bir arayüz açılır. Tool’ları seç, argüman gir, yanıtı gör. Claude Desktop olmadan test için en hızlı yöntemdir.

Log seviyelerini yükseltmek de işe yarar. FastMCP için:

import logging
logging.basicConfig(level=logging.DEBUG)

Bu satırı server’ın başına ekleyince tüm JSON-RPC mesajları terminale düşer. Transport sorunlarını bu çıktıyla tespit edersin.

Birden Fazla Tool’u Modüler Yönetme

Tek dosyaya onlarca tool koymak bakımı zorlaştırır. FastMCP bu sorunu include mekanizmasıyla çözer: her modül kendi FastMCP örneğini oluşturur, ana server bunları birleştirir.

# dosya_tools.py
from mcp.server.fastmcp import FastMCP
from pathlib import Path

dosya_mcp = FastMCP("dosya-modulu")

@dosya_mcp.tool()
def dosya_oku(yol: str) -> str:
    """Dosya içeriğini okur."""
    return Path(yol).read_text(encoding="utf-8")
# ana_server.py
from mcp.server.fastmcp import FastMCP
from dosya_tools import dosya_mcp

mcp = FastMCP("ana-server")
mcp.include(dosya_mcp, prefix="dosya")

if __name__ == "__main__":
    mcp.run()

prefix="dosya" eklenince dosya_oku tool’u Claude’da dosya_dosya_oku olarak görünür. Prefix isim çakışmalarını önler. Büyük server’larda bu modüler yaklaşım kod organizasyonunu önemli ölçüde kolaylaştırır.

MCP’nin Ötesi: Agent Mimarileri

Kendi MCP server’ını yazdıktan sonra doğal soru şu oluyor: “Bu tool’ları bir agent’ın kendi başına kullanmasını nasıl sağlarım?”

Agentic coding paradigması MCP’yi tam da bu noktada kullanır. Bir agent çalışma döngüsünde MCP araçlarına erişir, hangi tool’u ne zaman çağıracağına model karar verir ve araç çıktılarını bir sonraki adımın bağlamına ekler.

LangChain ve benzeri framework’ler MCP araçlarını kendi tool zincirlerine entegre etmek için adaptörler sunuyor. Eğer Python’da zaten bir LangChain pipeline’ın varsa MCP araçlarını bu pipeline’a eklemek birkaç satır iş.

MCP bu ekosistemde bir transport standardı olarak kalır; nasıl HTTP uygulamanın ne yaptığından bağımsızsa MCP de modelin ya da framework’ün tercihinden bağımsızdır. Bugün Claude Desktop için yazdığın server yarın bir LangGraph agent’ına ya da başka bir MCP-uyumlu istemciye de hizmet eder.

Sonraki Adımlar

Temel bir server yazdın. Şimdi nereye gidebileceğin:

  • Gerçek veri kaynağı bağlama: PostgreSQL, SQLite ya da bir REST API’ı tool olarak sar. psycopg2 ya da httpx ekle, bağlantı mantığını tool fonksiyonuna yaz, aynı pattern çalışır.
  • Authentication: Hassas API’lar için environment variable üzerinden anahtar oku. Config dosyasındaki env bloğuna anahtarları ekleyebilirsin.
  • Deployment: Docker ile paketleyip bir sunucuya at, SSE transport’a geç. Birden fazla kişi aynı server’ı kullanabilir.
  • Test: MCP Inspector ile her tool’u ayrı ayrı test et. Unit test için tool fonksiyonlarını doğrudan çağırabilirsin; MCP katmanı test gerektirmez.

Daha fazla MCP kaynağı için Model Context Protocol’ün resmi belgeleri iyi bir başlangıç noktası.

auto_stories İlgili Makaleler