Claude Code icin MCP Hub Kurdum: 12 Server, 90 Gun, 4 Vazgecmenin Hikayesi
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:
- Cold-start latency —
npx -y @modelcontextprotocol/server-githubilk cagrida 4-6 saniye spin-up aliyordu. Claude Code'un ilk araç çağrısı sürekli "yavasla" hissi veriyordu. - State paylasimi yok — memory server'in storage'i her laptop'ta ayri JSON dosyasinda. Mac Mini'de yazilan bir notu MacBook'tan goremiyordum.
- 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:
- Mount'u
/mnt/shared:/workspace:roolarak kisitladim. - Filesystem MCP'sinin allowlist'ini yazdim (sadece spesifik path'ler).
- 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.