Ana SayfaBlogClaude Code icin MCP Hub Kurdum: 12 Server, 90 Gun, 4 Vazgecmenin Hikayesi
AI & ML Tools

Claude Code icin MCP Hub Kurdum: 12 Server, 90 Gun, 4 Vazgecmenin Hikayesi

Emre Ferit Aslantas5 Haziran 202613 dkMakale
mcp claude-code homelab proxmox docker-compose lxc
Sponsored

Claude Code'u Mart 2026'da terminale tam zamanli aldigimda, ilk birkac hafta stdio transport ile her MCP server'i lokalde calistirdim. Filesystem, GitHub, Postgres, fetch — hepsi ~/.claude/mcp.json icinde, npm/uvx process'leri her oturum acilisinda yenisi spawn ediliyordu. Ev makinem isinmaya basladiginda ve uc farkli laptop'tan (Mac Mini M4, MacBook Air, is laptop'um) ayni MCP setup'ini istemeye basladigimda, MCP'leri merkezi bir hub'a tasimanin zamani geldigini anladim.

90 gun sonra Proxmox sunucumda CT102 olarak calisan bu hub'da 12 MCP server var, 4 tanesi de vazgectiklerim listesinde. Bu yazi, hangisinin gercekten isime yaradigini ve hangisinin "denedim ama haftada bir bile cagrilmadi" listesine girdigini anlatiyor.

Neden Merkezi Hub? "Lokal Calistir" Yaklasimi Neden Yetmedi

Lokal stdio-only setup'inin uc somut problemi vardi:

  1. Cold-start latencynpx -y @modelcontextprotocol/server-github ilk cagrida 4-6 saniye spin-up aliyordu. Claude Code'un ilk araç çağrısı sürekli "yavasla" hissi veriyordu.
  2. State paylasimi yok — memory server'in storage'i her laptop'ta ayri JSON dosyasinda. Mac Mini'de yazilan bir notu MacBook'tan goremiyordum.
  3. Secret tekrari — GitHub PAT, Sentry token, Postgres password... her makineda ayri yerde, donme zamani gelince hepsini elle guncellemek.

Cozum: MCP server'lari SSE (server-sent events) transport'la merkezi LXC container'da calistirip, her laptop'tan ayni endpoint'e baglanmak. Hub kendisi mcp.efa.local:8765 uzerinde dinliyor, Claude Code config'lerinde sadece tek bir HTTP URL var.

Donanim ve Yer Karari

CT102, Proxmox sunucumda 2 CPU + 2 GB RAM ile baslayan kucuk bir LXC. 12 MCP server koyduktan sonra RAM kullanimi ortalama ~880 MB, peak yaklasik 1.3 GB. CPU yuku idle'da %1-2, yogun puppeteer cagrisi sirasinda %25-30'a ciktigi oluyor.

LXC secimi gerekce: Docker-in-Docker yapmaya gerek yok (host networking sorunlu). Native Docker calisiyor, container kendisi lxc.apparmor.profile: unconfined ile baslatildi cunku puppeteer chrome sandboxing'i AppArmor ile catisiyordu.

# /etc/pve/lxc/102.conf
arch: amd64
cores: 2
features: keyctl=1,nesting=1
hostname: mcp-hub
memory: 2048
swap: 1024
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup2.devices.allow: c 10:200 rwm

features: nesting=1 Docker'in icinde sorunsuz calismasi icin. cgroup2.devices.allow satiri ise daha sonra eklediğim TUN cihazi icin (Tailscale subnet router olarak da kullaniyorum bu container'i ama o ayri konu).

12 Server: Ne Tutuldu, Ne Ise Yaradi

Hub'da su an calisan 12 MCP server ve haftalik tahmini cagri sayim (Claude Code session loglarindan grep ile saydim):

| Server | Haftalik cagri | Esas kullanim | |---|---|---| | filesystem | ~900 | Lokal dosya okuma/yazma | | github | ~340 | PR, issue, repo arama | | postgres | ~180 | efa-agent DB sorgulari | | memory | ~120 | Kalici kullanici notlari | | fetch | ~95 | HTTP GET, dokuman cekme | | sentry | ~60 | Production error inceleme | | sqlite | ~55 | Lokal not DB'si | | searxng | ~40 | Web arama (Google API yerine) | | time | ~35 | Timezone-aware tarih hesabi | | linear | ~28 | Task okuma/guncelleme | | puppeteer | ~12 | Screenshot, scraping | | slack | ~6 | Bildirim gonderme |

filesystem, github, postgres ucusu tum cagrilarin %70+'sini olusturuyor. Bu uc tanesi olmadan Claude Code'u terminal disinda kullanmak benim icin anlamsiz hale geliyor.

En Cok Sasirtan: memory Server

@modelcontextprotocol/server-memory baslangicta gozumden kacmis bir araçti. JSON graph store olarak duruyordu, "ne ise yarayacak ki" diye birakmistim. 90 gunun sonunda en degerli alistim olduğunu farkettim: oturumlar arasi context tasimak. "Eylul'de su projeyle ilgili X yapmistim, hatirla" gibi bir sey diyorum, Claude memory server'dan node'u cekiyor.

Ama bir uyari: graph store dosyasi 30 gunde 47 MB'a ulasti. Birkac bin node, ~12000 edge. Read latency hala iyi (<50ms) ama backup almasi gereken bir sey, B2 bucket'ima nightly cron ile gidiyor.

Docker Compose: Calisan Stack

Hub'in compose dosyasinin temizlenmis hali (token'lar .env'den geliyor):

# /opt/mcp-hub/docker-compose.yml
version: "3.9"

x-common: &common
  restart: unless-stopped
  networks: [mcphub]
  logging:
    driver: json-file
    options: { max-size: "10m", max-file: "3" }

services:
  gateway:
    image: supercorp/supergateway:0.4.0
    <<: *common
    ports: ["8765:8765"]
    command: >
      --sse --port 8765
      --upstream-url http://router:9000
    depends_on: [router]

  router:
    build: ./router
    <<: *common
    environment:
      - ROUTER_CONFIG=/etc/router/routes.yaml
    volumes:
      - ./router/routes.yaml:/etc/router/routes.yaml:ro

  mcp-filesystem:
    image: mcp/filesystem:latest
    <<: *common
    volumes:
      - /mnt/shared:/workspace:ro

  mcp-github:
    image: mcp/github:latest
    <<: *common
    environment:
      - GITHUB_TOKEN=${GITHUB_TOKEN}

  mcp-postgres:
    image: mcp/postgres:latest
    <<: *common
    environment:
      - DATABASE_URL=${EFA_AGENT_DB_URL}

  mcp-memory:
    image: mcp/memory:latest
    <<: *common
    volumes:
      - memory_data:/data
    environment:
      - MEMORY_FILE=/data/memory.json

  mcp-sentry:
    image: mcp/sentry:latest
    <<: *common
    environment:
      - SENTRY_AUTH_TOKEN=${SENTRY_TOKEN}
      - SENTRY_ORG=${SENTRY_ORG}

  mcp-puppeteer:
    image: mcp/puppeteer:latest
    <<: *common
    shm_size: 1gb
    cap_add: [SYS_ADMIN]

volumes:
  memory_data:

networks:
  mcphub:

Onemli noktalar:

  • Gateway katmani (supergateway) tum stdio MCP'leri SSE'ye ceviriyor. Boylece dis dunyaya tek HTTP endpoint sunuyorum.
  • Router ufak bir Go servisi, hangi tool cagrisinin hangi container'a gidecegine karar veriyor. Bunu kendim yazdim cunku ihtiyacim olan capability-based routing'i hazir bir yerde bulamadim.
  • Logging cap — MCP server'lari konusurken cok log uretiyor. 10MB/3 file cap olmasaydi container disk doldururdum (zaten bir kere doldu, ilk haftada).

Claude Code tarafindaki config:

// ~/.claude/mcp.json
{
  "mcpServers": {
    "homelab-hub": {
      "transport": "sse",
      "url": "https://mcp.efa.local/sse",
      "headers": {
        "Authorization": "Bearer ${HUB_TOKEN}"
      }
    }
  }
}

Tek satir konfigurasyon. Ev disindayken Tailscale uzerinden ayni adres calisiyor, hicbir laptop'ta MCP envanteri tutmuyorum.

Vazgectigim 4 Server

Bu kismi yazmasi en eglencelisi cunku homelab tutorial'larinda kimse "denedim, ise yaramadi" demiyor.

1. everything (test/demo server)

Reference implementation. Baslarken kurdum, "bir bakayim neler yapiyor". 90 gunde tek bir gercek cagri yapmadim. Calistigini gormek icin guzel, ama hub'da yer kaplamasi anlamsiz. Bir hafta sonra kaldirdim.

2. Google Drive MCP

Google Drive'imin icinden dosya okumak icin kurdum. Iki problem:

  • OAuth refresh token'i icin headless flow zorlaydi. Web flow'u tamamlamak icin SSH tunnel + browser combo gerekiyordu, her token expire'da ayni dansi yapmak istemedim.
  • Drive icinde tuttuğum dosyalarin %95'i zaten Markdown ve Git'te de var. Drive'a sadece "PDF saklama" icin guveniyorum, onlari da Claude Code'da cogu zaman okuma ihtiyacim olmadi.

Sonuc: 2 hafta kullandim, 3-4 gercek faydali cagri, ekonomik degil. Kapattim.

3. AWS Knowledge Base MCP

aws-kb-retrieval server. AWS dokumantasyonunu vector arama ile getiriyordu. Vazgecme sebebi farkliydi: cevaplar cogu zaman bayatti. AWS service guncellemeleri hizli, bana getirdigi belgeler 6-12 ay eski oluyordu. Tarayicidan aws.amazon.com/docs'a gitmek daha hizli ve guncel cikti. Iki haftada toplam ~7 cagri sonrasi kapattim.

4. Discord MCP (kismi vazgecme)

Slack'i tuttum, Discord'u attim. Calisma sebebi: Discord MCP'sinin yazma izinleri benim kullanim sekline (ekipte birden cok kanal var, yanlis kanala mesaj atmaktan korktum) uygun degildi. Slack'te tek workspace ve dikkatli bir whitelist yazdim. Discord icin ayni dikkati ayirmak istemedim.

En Pahaliya Mal Olan Hata

Ilk ay, mcp-filesystem server'ina yanlislikla /mnt/shared yerine / mount ettim — yani LXC container'in tum filesystem'i Claude Code'a expose oldu. Read-only oldugu icin felaket olmadi, ama bir oturumda Claude /etc/shadow okumayi denedi (kendiliginden, "sistem konfigurasyonuna bakayim" diyerek). Container'da root oldugu icin basarili oldu ve dosya icerigini context'e aldi.

O an boğazımda yumru oluştu. Hash'ler olsa bile public bir LLM transcript'inde /etc/shadow icerigi gormek istemiyorum. Ayni gun:

  1. Mount'u /mnt/shared:/workspace:ro olarak kisitladim.
  2. Filesystem MCP'sinin allowlist'ini yazdim (sadece spesifik path'ler).
  3. Audit log icin gateway'e tum tool call'larini stdout'a echo eden minik bir middleware ekledim, oradan Loki'ye gidiyor.

Ders: MCP server'lari "kucuk yardimci" gibi gozukur, ama capability surface'leri ciddi. Production'a benzer disiplin gerekiyor. Bu olaydan sonra her yeni server icin "en kotu senaryoda ne yapabilir?" sorusunu yaziyorum, sonra mount/scope kisitlamasini ona gore ayariyorum.

Latency: SSE Karari Karsisinda Stdio

Spin-up latency'sini cozdugumu yazdim ama bir trade-off var: SSE round-trip lokal stdio'dan biraz daha yavas. Olcumlerim (filesystem read_file call'i, kucuk dosya):

  • Lokal stdio (Mac Mini'de): p50 ~18ms, p95 ~45ms
  • Hub via SSE (Mac Mini → CT102 via 1Gbps LAN): p50 ~38ms, p95 ~95ms
  • Hub via Tailscale (kafe wifi): p50 ~140ms, p95 ~310ms

Ev icinde fark hissedilebilir ama is akisini bozmuyor. Disarida (Tailscale) filesystem ve puppeteer gibi cok call yapan server'lar yavas hissediliyor. Cozum: lokal cache stratejisi hala ariyorum, su an manuel "ev disindayken stdio fallback profili" tutuyorum.

Notlar

90 gunun ozet cikarmasi:

  • Merkezi MCP hub, 2'den fazla cihazdan Claude Code kullaniyorsaniz net kazan. Tek cihazdaysaniz, lokal stdio'da kalin — overhead'e degmez.
  • filesystem, github, ve cluster'iniza dair bir DB MCP'si — bu uclu tum kullanimimin %70'i. Geri kalan 9 server'i opsiyonel gorun.
  • Memory MCP'sini erken kurun, regulary backup alin. Olusturulan graph zamanla en degerli asset oluyor.
  • Capability scope'unu en bastan yazin. Mount'lar, allowlist'ler, token izin alanlari. "Sonra daraltirim" demek, bir gun kotu surpriz demek.
  • SSE gateway + container-per-MCP kombinasyonu, hub'i buyutmek ve kuculturken esnek tutuyor. Yeni MCP eklemek = compose'a 8 satir.

Bir sonraki yaziyi muhtemelen bu hub'in onune koymak istedigim rate limit + cost tracking proxy uzerine yazacagim. Su an MCP cagrilari sinirsiz, hicbir butce kontrolu yok; bir Cumartesi bunu duzenli bir middleware'a tasiyacagim. Kendi kurulumunuzda farkli kararlar aldiysaniz, GitHub uzerinden ulasin — ozellikle "su MCP'yi denediniz mi?" turu onerilere acim.

Sponsored

Haftalık DevOps Bülteni

Yeni tool incelemeleri, karşılaştırmalar ve DevOps trendleri haftada bir kutuna gelsin.