
Bu makale, Cortex XSOAR 6.13’ün, CortexSynapse açık kaynak MCP sunucusu üzerinden Claude Desktop’a bağlanması; süreç boyunca karşılaşılan üç ardışık entegrasyon hatasının teşhisi ve kalıcı çözümünü içerir.
Cortex XSOAR’ı Claude Desktop’a MCP üzerinden bağlamak için CortexSynapse Docker imajını kullanırken üç farklı sorunla karşılaşıldı:
Üçü çözüldükten sonra get_incidents, xsiam_get_alerts, update_incident, xsoar_indicators_search gibi tüm MCP araçları çalışır hale geldi.
Bir SOC için Cortex XSOAR, incident orkestrasyonunun merkezidir. Buna Claude Desktop’un doğal dil ara yüzünü bir LLM destekli SOC katmanı olarak eklediğinizde şu use-case’ler açılır:
Bunu sağlamak için MCP (Model Context Protocol) kullanılır. MCP, LLM client’ı (Claude Desktop/CoWork) ile harici sistemler (XSOAR, XSIAM, Splunk vb.) arasında standart bir köprü sunar. CortexSynapse, XSOAR/XSIAM API’sini MCP araçlarına dönüştüren açık kaynak bir Python sunucusudur ve Docker imajı olarak çalıştırılır.
Akış:
Kullanıcı (Claude Desktop UI)
│
▼
Claude (LLM)
│ MCP tool call (JSON-RPC)
▼
Docker container: cortexsynapse ──HTTPS──► Cortex XSOAR API
│
▼
JSON response (incident, alert, indicator vb.)
Claude Desktop her oturumda container’ı claude_desktop_config.json’daki tanıma göre docker run ile başlatır; oturum kapandığında –rm flag’i sayesinde container otomatik silinir.
Bu kurulumdan önce sahip olmanız gerekenler:
| Bileşen | Sürüm | Amaç |
|---|---|---|
| Claude Desktop (desktop app) | Güncel | LLM client + MCP host |
| Docker Desktop for Windows | 4.71.0 | MCP sunucusunu container olarak çalıştırma |
| PowerShell | Komutları çalıştırma | |
| Python | 3.10 ve üzeri (Windows tarafında) | Patch script’lerini çalıştırmak ve direct API testleri için |
| Cortex XSOAR | 6.x veya 8.x (XSIAM dahil) | API erişilebilir olmalı |
| XSOAR API Key | Web tipinde | Settings → Integrations → API Keys → “Get Your Key” |
| CortexSynapse kaynak kodu | https://github.com/amshamah419/CortexSynapse | İmajı build etmek için |
Not: API key oluştururken minimum gerekli yetkilerle başlayın. Read-only test için “Read Only” rolü, response aksiyonları için ek izinler ekleyin. Key’i hiçbir transcript, screenshot veya log içinde paylaşmayın; sızdığını fark ederseniz revoke ve rotate edin.
Bu makaledeki hata-ayıklama sürecinden öğrendiklerimle düzenlenmiş, sorunlara denk gelmemeniz için iyileştirilmiş sıralama.
3.1. CortexSynapse kaynağını indir
GitHub’dan klonla veya ZIP indir, Desktop’a aç
cd C:\Users\<kullanıcı>\Desktop
Sonuç: C:\Users\<kullanıcı>\Desktop\CortexSynapse-main\ (Dockerfile, server/, codegen/, specs/ içerir)
3.2. Body double-encoding patch’ini Dockerfile’a ekle
CortexSynapse’in 1.27.0 sürümünde, MCP’nin body parametresi httpx istemcisine olduğu gibi iletildiğinde XSOAR çift kodlanmış JSON string olarak görüyor. Üretilmiş üç dosyaya (generated_xsoar_tools.py, generated_xsiam_tools.py, generated_unified_tools.py) tek satırlık bir patch yeterli ama bu dosyalar build sırasında python -m codegen.generator ile yeniden üretildiği için patch’i Dockerfile’a, codegen adımının hemen ardına eklemek gerekiyor.
PowerShell’de (kaynak klasörünün içindeyken):
cd C:\Users\<kullanıcı>\Desktop\CortexSynapse-main
@’
import pathlib
p = pathlib.Path(“Dockerfile”)
text = p.read_text(encoding=”utf-8″)
needle = “RUN python -m codegen.generator”
patch_line = “\nRUN sed -i \”s|json=body|json=(json.loads(body) if isinstance(body, str) else body)|g\” /app/server/generated_xsoar_tools.py /app/server/generated_xsiam_tools.py /app/server/generated_unified_tools.py”
if “json.loads(body)” in text:
print(“Dockerfile zaten patched”)
else:
p.write_text(text.replace(needle, needle + patch_line), encoding=”utf-8″)
print(“Dockerfile patched”)
‘@ | python
Bu blok Python’u çağırarak Dockerfile’ı güvenli şekilde değiştirir.
3.3. İmajı build et
docker build –no-cache -t cortexsynapse-patched .
–no-cache, eski layer’ların yanlışlıkla yeniden kullanılmasını engeller. Build sonunda Successfully tagged cortexsynapse-patched:latest görmelisiniz.
3.4. Patch’in imaja yansıdığını doğrula
docker run –rm cortexsynapse-patched grep -c “json.loads(body)” `
/app/server/generated_xsoar_tools.py `
/app/server/generated_xsiam_tools.py `
/app/server/generated_unified_tools.py
Beklenen çıktı:
/app/server/generated_xsoar_tools.py:1
/app/server/generated_xsiam_tools.py:1
/app/server/generated_unified_tools.py:8
0 görüyorsanız Dockerfile patch satırı işlememiş demektir; 3.2’deki Python bloğunu yeniden çalıştırın.
3.5. Claude Desktop MCP konfigürasyonunu yaz
Dosya yolu: %APPDATA%\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json
{
“mcpServers”: {
“cortex-xsoar”: {
“command”: “docker”,
“args”: [
“run”, “-i”, “–rm”, “–read-only”,
“–security-opt=no-new-privileges”,
“-e”, “XSOAR_API_URL”,
“-e”, “XSOAR_API_KEY”,
“-e”, “VERIFY_SSL=false”,
“cortexsynapse-patched”
],
“env”: {
“XSOAR_API_URL”: “https://xsoar.ornek.com”,
“XSOAR_API_KEY”: “<API_KEY_BURAYA>”
}
}
}
}
Üç kritik nokta:
3.6. Claude Desktop’u tamamen yeniden başlat
İlk soruda Claude cortexsynapse-patched imajıyla yeni bir container başlatır ve XSOAR araçları kullanılabilir hale gelir.
3.7. Doğrulama sorgusu
Claude Desktop’ta yazın:
“XSOAR’daki son 5 incident’ı listele”
Beklenen sonuç: id, name, severity, status, owner, created kolonlarıyla bir tablo. Hata gelirse sonraki bölümde yer alan analizlere odaklanın.
Bu bölüm, sorunlar ortaya çıkarsa nasıl tanılayacağınızı gösterir. Sıralama, gerçek hata-ayıklama sürecindeki sırayla aynıdır, biri çözülmeden bir sonrakine geçilemiyor.
Sorun 1 — [SSL: CERTIFICATE_VERIFY_FAILED] self-signed certificate
Tanılama: İlk MCP çağrısında SSL doğrulama hatası.
İlk çözüm: Container XSOAR_VERIFY_SSL=false yok diye doğrulamaya kalkıyor. Claude Desktop config’ine XSOAR_VERIFY_SSL=false eklendi, ama hata aynı kaldı.
Kritik tanılama: Container’ın gerçekten hangi env değişkenini okuduğunu bulmak için kaynak kodda arandı:
docker exec <container_adı> sh -c “grep -rniE ‘verify_ssl|verify=’ /app/server 2>/dev/null”
Çıktı:
/app/server/security.py:132: “verify_ssl”: os.getenv(“VERIFY_SSL”, “true”).lower() == “true”
/app/server/generated_xsoar_tools.py:27: verify = os.getenv(“VERIFY_SSL”, “true”).lower() == “true”
Öğrenilen: Kod VERIFY_SSL okuyor, prefix’siz. Yanlış env adı set edildiği görüldü.
Çözüm: Claude Desktop config’inde VERIFY_SSL=false (3.5’teki nihai konfigürasyondaki gibi).
Çıkarılan ders: “Env değişkeni set ettim ama kod onu görmüyor” şüphesinde, container’ın kaynak kodunda env okuma satırını grep’leyin. Başka bir tartışmaya yer kalmaz.
Sorun 2 — Boş cevap veya <a href=”/#/404″>See Other</a>
Tanılama: SSL düzeldikten sonra MCP çağrıları boş string ya da 303 redirect ile UI’ya yönlendirme dönüyor.
Kritik tanılama: Direkt API çağrısı ile MCP’yi devreden çıkarıp ham HTTP cevabı incelendi:
Powershell üzerinde
@’
import os, httpx
key = os.getenv(“XSOAR_API_KEY”)
for u in [“https://10.10.20.20//incidents/search”, “https://10.10.20.20/incidents/search”]:
r = httpx.post(u,
headers={“Authorization”: key, “Content-Type”:”application/json”, “Accept”:”application/json”},
json={“filter”:{“size”:1}}, verify=False, follow_redirects=False, timeout=10)
print(u, “->”, r.status_code, “LEN”, len(r.text), “LOC:”, r.headers.get(“location”,””))
‘@ | docker exec -i <container_adı> python
Sonuç:
https://10.10.20.20//incidents/search -> 307 LEN 0 LOC: /incidents/search ← çift slash, redirect
https://10.10.20.20/incidents/search -> 200 LEN 5865 LOC: ← tek slash, başarılı
Öğrenilen: XSOAR_API_URL=https://10.10.20.20/ değerinde sondaki / ile birleştirilen /incidents/search route’u https://10.10.20.20//incidents/search üretiyor. XSOAR çift slash’ı 307 redirect ile temiz path’e yönlendiriyor; CortexSynapse’in httpx istemcisi default follow_redirects=False çalıştığı için cevabı boş alıyor.
Çözüm: Claude Desktop config’indeki XSOAR_API_URL değerinden sondaki / silindi.
Çıkarılan ders: API URL’lerinde trailing slash yorucu olabilir.
Sorun #3 — 400 Bad Request: json: cannot unmarshal string into Go value
Tanılama: SSL ve URL düzeldi, MCP artık XSOAR’a başarıyla bağlanıyor ama her body alan endpoint’te şu hata:
{“id”: “bad_request”, “status”: 400, “title”: “Bad request”,
“detail”: “Request body is not well-formed. It must be JSON.”,
“error”: “json: cannot unmarshal string into Go value of type entities.SearchIncidentsData”}
XSOAR gönderilen body’yi JSON-encoded string olarak görüyor, beklediği object değil.
Kritik tanılama: İstek dispatch kodu okundu:
# /app/server/generated_xsoar_tools.py
async def handler(arguments: Dict[str, Any]) -> List[types.TextContent]:
body = arguments.get(“body”)
…
resp = await client.request(
method=method, url=url,
params=_sanitize_query(query),
headers=_sanitize_headers(headers),
json=body,
)
Body normalde JSON nesnesi olarak gitmeli. Ama bizim tarafta önce yazıya çevriliyor. Sonra httpx bunu tekrar JSON’a çevirince XSOAR’a beklenen JSON değil, JSON gibi görünen bir yazı gidiyor. Bu yüzden XSOAR body’yi okuyamıyor.
Çözüm: Sunucu tarafında body string ise parse et.
json=(json.loads(body) if isinstance(body, str) else body)
Önemli Nokta: İnce ama önemli bir detay var: Bu düzeltmeyi sadece host üzerindeki .py dosyalarına yapmak yeterli değil. Çünkü CortexSynapse Docker imajı build edilirken RUN python -m codegen.generator komutu çalışıyor ve bu üç dosyayı container içinde yeniden oluşturuyor. Yani host tarafında patch’lediğimiz dosyaların üzerine build sırasında tekrar yazılıyor.
Doğru çözüm: Patch’i Dockerfile’a, codegen adımının hemen ardına ek bir RUN sed -i … satırı olarak yerleştirmek. Bölüm 3.2’deki Python script’i tam olarak bunu yapıyor.
Patch uygulandıktan sonra builder stage şöyle görünür:
# … (önceki adımlar)
COPY server/ server/
COPY codegen/ codegen/
COPY specs/ specs/
RUN python -m codegen.generator
# ↓↓↓ EKLENEN SATIR ↓↓↓
RUN sed -i “s|json=body|json=(json.loads(body) if isinstance(body, str) else body)|g” \
/app/server/generated_xsoar_tools.py \
/app/server/generated_xsiam_tools.py \
/app/server/generated_unified_tools.py
# ↑↑↑ EKLENEN SATIR ↑↑↑
RUN python -m build
# … (stage-1 ile devam)
Bu satır, üretim adımı bittikten sonra üç jeneratör çıktısındaki json=body ifadesini koşullu parse edici hale dönüştürür. Build cache’leniyorsa –no-cache ile tekrar build alın.
Patch uygulanmış imaj çalıştığında MCP üzerinden bu örnek dönecektir:
Claude Desktop sorgusu:
XSOAR’daki son 5 incident’ı listele
Beklenen MCP çağrısı (özet):
tool: get_incidents
platform: xsoar
body: {“filter”: {“page”: 0, “size”: 5, “sort”: [{“field”: “created”, “asc”: false}]}}
Beklenen sonuç (örnek tablo):
| ID | Name | Severity | Status | Owner | Created (UTC) |
|---|---|---|---|---|---|
| 34763 | Test | 3 (High) | 1 (Active) | L1-L1 | 2026-04-16 12:06 |
| 34748 | test3 | 0 (Unknown) | 0 (Pending) | L1-L1 | 2026-03-19 08:27 |
| 34747 | test2 | 0 (Unknown) | 0 (Pending) | L1-L1 | 2026-03-19 08:26 |
| 34746 | test1 | 0 (Unknown) | 0 (Pending) | L1-L1 | 2026-03-19 08:26 |
| 34740 | test cti 2 | 1 (Low) | 1 (Active) | L1-L1 | 2026-03-13 15:48 |
Severity referansı (Cortex XSOAR): 0=Unknown, 0.5=Informational, 1=Low, 2=Medium, 3=High, 4=Critical Status referansı: 0=Pending, 1=Active, 2=Closed, 3=Archived
Aşağıdaki komutlar bu projede defalarca işe yaradı. Bir SOC engineer’ın MCP entegrasyon problemlerinde başvurabileceği “first responder” set’i:
# Çalışan container’ları gör
docker ps –format “{{.Names}} {{.Image}}”
# Container’ın aktif env değişkenleri
docker exec <NAME> env | findstr /I “XSOAR VERIFY API”
# MCP server log’u (initialize, tool list, hata mesajları)
docker logs –tail 100 <NAME>
# Container’ın kaynak kodunda bir terimi grep’le
docker exec <NAME> sh -c “grep -rniE ‘pattern’ /app/server”
# Direct API testi (MCP’yi devreden çıkar)
@’
import os, httpx
url = os.getenv(“XSOAR_API_URL”).rstrip(“/”) + “/incidents/search”
r = httpx.post(url,
headers={“Authorization”: os.getenv(“XSOAR_API_KEY”),
“Content-Type”:”application/json”, “Accept”:”application/json”},
json={“filter”:{“size”:1}}, verify=False, timeout=10)
print(r.status_code, r.text[:300])
‘@ | docker exec -i <NAME> python
# Imaj içinde patch var mı?
docker run –rm <IMAGE> grep -c “json.loads(body)” /app/server/generated_xsoar_tools.py
CortexSynapse-patched çalışır hale geldikten sonra MCP üzerinden kullanılabilen tool’ların bir kısmı:
| Tool | Senaryo |
|---|---|
| get_incidents | “Son 24 saatte yüksek severity’li, owner’ı atanmamış incident’ları listele” |
| update_incident | “ID 34763’ü ‘In Progress’ yap ve owner’ı bana ata” |
| xsoar_indicators_search | “Son 7 gün içinde feed’lerden gelen IP indicator’larını getir, reputation’a göre filtrele” |
| xsiam_get_alerts | “Endpoint X üzerinde son 1 saatte tetiklenen alert’leri çek” |
| xsiam_start_xql_query | Doğal dilden XQL sorgusu kurma (LLM-assisted hunt) |
| xsiam_isolate / xsiam_unisolate | Endpoint izolasyonu / geri alma |
| xsiam_run_script | Belirli endpoint’lerde script çalıştırma (DFIR triage) |
Bu vaka, açık kaynak bir MCP sunucusunun gerçek bir kurumsal XSOAR ortamına entegrasyonunda karşılaşılan üç farklı katmandaki sorunun (env adı uyuşmazlığı, URL trailing slash, body double-encoding, multi-stage build patch konumu) sırasıyla nasıl tanımlanıp çözüldüğünü gösterdi. Bu hatalardan hiçbiri kaynaklarda yazmıyordu; her biri kaynak kodu okuyarak, direct API testleriyle ve Docker build davranışını tersine çevirerek ortaya çıktı.
SOC otomasyonunda LLM katmanını orkestrasyona bağlamak herkesin söylediği kadar tak-çalıştır bir iş değil ama hangi katmanda neyin nasıl çalıştığını bir kez kavradığınızda, tekrar kuruluşu oldukça kısalıyor.
-