Şirket içi sistemleri MCP aracılığıyla Claude Code'a bağlayın — genel fetch sunucusundan özel MCP Server yazmaya kadar; dağıtım platformları, izleme, bilet sistemleri ve araç tasarım ilkelerini kapsar.
Bir önceki yazıda veritabanı bağlantısını ele almıştık. Veritabanlarının standart protokolleri var, bu yüzden entegrasyonu nispeten kolay. Ama çoğu ekibin günlük çalışması başka birçok dahili sisteme de bağlı: deployment platformu, izleme paneli, ticket sistemi, dahili API'ler, konfigürasyon merkezi.
Bu sistemlerin genellikle hazır bir MCP Server'ı yok, ama neredeyse hepsi HTTP API sunuyor. Bu yazıda MCP kullanarak bu dahili araçları Claude Code'a nasıl bağlayacağınızı anlatacağız; böylece Claude doğrudan monitoring kontrolü yapabilir, deployment durumunu görebilir ve ticket'ları yönetebilir.
Dahili araçları entegre etmenin iki yolu var:
Yol 1: Genel amaçlı HTTP MCP Server kullanmak
Toplulukta herhangi bir REST API'yi MCP aracına dönüştürebilen genel amaçlı MCP Server'lar mevcut. Bir API açıklama dosyası yazıyorsunuz, server bunu Claude'un çağırabileceği araçlara dönüştürüyor. API yapısı basit olan ve karmaşık mantık gerektirmeyen senaryolar için uygun.
Yol 2: Kendi MCP Server'ınızı yazmak
TypeScript veya Python MCP SDK'sı ile özel bir Server yazıyorsunuz; araç tanımları, parametre doğrulama ve hata yönetimi üzerinde tam kontrol sağlıyorsunuz. Birden fazla API'yi birleştirmeniz, veri dönüşümü yapmanız veya iş mantığı eklemeniz gereken senaryolar için uygun.
Bu yazıda her iki yolu da ele alacağız, basit olandan başlayarak.
En hafif çözüm, Anthropic'in resmi @anthropic-ai/mcp-server-fetch paketini kullanmaktır; Claude'un doğrudan HTTP request göndermesini sağlar. Konfigürasyon son derece basit:
{
"mcpServers": {
"fetch": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-server-fetch"]
}
}
}
Yapılandırma tamamlandıktan sonra Claude dahili API'leri doğrudan çağırabilir:
Deployment platformundaki https://deploy.internal.com/api/v1/services/user-service adresinin mevcut durumunu kontrol et
Claude bir GET request gönderir, yanıtı alır ve sizin için analiz eder.
Ancak bu yaklaşımın belirgin sınırlamaları var:
Geçici kullanım için uygun, uzun vadeli çözüm olarak uygun değil.
Bir dahili sistemi sürekli kullanmanız gerekiyorsa, özel bir MCP Server yazmak daha iyi bir seçimdir. Aşağıda gerçek bir senaryo ile gösterelim: şirketin deployment platformunu entegre etme.
Deployment platformunuzun şu API'leri sunduğunu varsayalım:
GET /api/v1/services — Tüm servisleri listeleGET /api/v1/services/:name/status — Servis durumunu görüntülePOST /api/v1/services/:name/deploy — Deployment tetikleGET /api/v1/services/:name/logs — Son deployment loglarını görüntüleÖnce projeyi başlatın:
mkdir mcp-deploy && cd mcp-deploy
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
npx tsc --init
Ana kod src/index.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const API_BASE = process.env.DEPLOY_API_URL!;
const API_TOKEN = process.env.DEPLOY_API_TOKEN!;
async function api(path: string, method = "GET", body?: unknown) {
const res = await fetch(`${API_BASE}${path}`, {
method,
headers: {
Authorization: `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) {
throw new Error(`API error: ${res.status} ${await res.text()}`);
}
return res.json();
}
const server = new McpServer({
name: "deploy-platform",
version: "1.0.0",
});
// Tüm servisleri listele
server.tool("list_services", "列出部署平台上的所有服务及其状态", {}, async () => {
const data = await api("/api/v1/services");
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
});
// Belirli bir servisin durumunu görüntüle
server.tool(
"service_status",
"查看指定服务的当前部署状态、版本号和健康检查结果",
{ name: z.string().describe("服务名称,如 user-service") },
async ({ name }) => {
const data = await api(`/api/v1/services/${name}/status`);
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
// Deployment loglarını görüntüle
server.tool(
"deploy_logs",
"查看指定服务最近的部署日志",
{
name: z.string().describe("服务名称"),
limit: z.number().optional().default(10).describe("返回条数,默认 10"),
},
async ({ name, limit }) => {
const data = await api(`/api/v1/services/${name}/logs?limit=${limit}`);
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
// Deployment tetikle
server.tool(
"trigger_deploy",
"触发指定服务的部署。这是一个写操作,会实际影响生产环境",
{
name: z.string().describe("服务名称"),
version: z.string().describe("要部署的版本号或 git ref"),
},
async ({ name, version }) => {
const data = await api(`/api/v1/services/${name}/deploy`, "POST", {
version,
});
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}
);
const transport = new StdioServerTransport();
server.connect(transport);
Derleme:
npx tsc
{
"mcpServers": {
"deploy": {
"command": "node",
"args": ["/path/to/mcp-deploy/dist/index.js"],
"env": {
"DEPLOY_API_URL": "https://deploy.internal.com",
"DEPLOY_API_TOKEN": "your-api-token"
}
}
}
}
Token'ı .claude/settings.local.json dosyasına koyun (git'e commit etmeyin), URL'yi .claude/settings.json dosyasına koyun (git'e commit edin, ekiple paylaşın).
Yapılandırma tamamlandıktan sonra konuşmalar doğal bir hal alır:
user-service şu an ne durumda?
→ Claude service_status("user-service") çağırır
→ Sonuç: çalışıyor, sürüm v2.3.1, son deployment 2 saat önce, health check'ler tamamı geçti
Son deployment'larda başarısız olan var mı?
→ Claude deploy_logs("user-service", 20) çağırır
→ Logları analiz eder, 3. deployment'ın health check zaman aşımı nedeniyle geri alındığını bildirir
user-service'i v2.3.2'ye deploy et
→ Claude trigger_deploy("user-service", "v2.3.2") çağırır
→ Araç açıklamasında "yazma işlemi" olarak işaretlendiği için Claude önce sizden onay ister
Bu, ciddi şekilde düşünülmesi gereken bir soru.
Okuma işlemlerini rahatlıkla entegre edin. Durum kontrolü, log görüntüleme, ticket arama — bu işlemlerin yan etkisi yok, Claude hata yapsa bile bir kayıp olmaz.
Yazma işlemleri iki kategoriye ayrılır:
Düşük riskli yazma işlemleri entegre edilebilir, ancak araç açıklamasında açıkça belirtin. Claude, yan etkisi olarak işaretlenmiş işlemler için otomatik olarak kullanıcı onayı ister. Örneğin ticket oluşturma, mesaj gönderme, konfigürasyon güncelleme.
Yüksek riskli yazma işlemlerini entegre etmemeniz önerilir. Kaynak silme, rollback tetikleme, yetki değiştirme — bu işlemlerin sonuçları ciddi ve geri döndürülemez, manuel yapılması daha güvenli.
Yazma işlemlerini entegre etmek zorundaysanız, en azından iki şey yapın:
| Sistem | Sunulan Araçlar | Notlar |
|---|---|---|
| Deployment Platformu (K8s / Kamal) | Servis durumu görüntüleme, log görüntüleme, deployment tetikleme | Yazma işlemleri için onay ekleyin |
| İzleme Sistemi (Grafana / Datadog) | Metrik görüntüleme, alarm geçmişi görüntüleme | Sorgu zaman aralığını sınırlayın, çok fazla veri çekmekten kaçının |
| Ticket Sistemi (Jira / Linear) | Ticket arama, ticket oluşturma, durum güncelleme | Ticket oluşturma yazma işlemidir ama düşük riskli |
| Dahili Dokümantasyon (Notion / Confluence) | Doküman arama, sayfa içeriği okuma | Sayfalamaya dikkat edin, tek seferde çok fazla çekmeyin |
| Konfigürasyon Merkezi (Consul / etcd) | Konfigürasyon okuma, ortam farklarını karşılaştırma | Sadece okuma yapın, yazma işlemi entegre etmeyin |
| CI/CD (GitHub Actions / Jenkins) | Build durumu görüntüleme, build tetikleme | Build tetikleme orta riskli yazma işlemidir |
MCP aracı yazmak, API yazmaktan farklıdır. API programcılar içindir, araçlar AI içindir. Dikkat edilmesi gereken birkaç ilke:
Araç adları açık ve anlaşılır olmalı
✗ get_svc_stat — Claude kısaltmanın anlamını doğru tahmin edemeyebilir
✓ service_status — Ne işe yaradığı hemen anlaşılıyor
Açıklamalar AI için yazılmalı
Araç açıklaması insanlar için yazılmış bir dokümantasyon değil, Claude'un "bu aracı ne zaman çağırmalıyım" kararını vermesi için bir referanstır. Açıklamada şunlar belirtilmeli: bu araç ne yapar, ne döndürür, ne zaman kullanılmalı.
✗ "Servis durumunu getir"
✓ "Belirtilen servisin mevcut deployment durumunu, sürüm numarasını ve health check sonuçlarını görüntüler. Kullanıcı bir servisin normal çalışıp çalışmadığını sorduğunda kullanılır"
Parametreleri zod ile net bir şekilde tanımlayın
.describe() içeren parametreler sayesinde Claude ne dolduracağını bilir. Açıklaması olmayan parametrelerde Claude yalnızca isme göre tahmin yürütebilir.
Yapılandırılmış veri döndürün
MCP araçları metin döndürür, ama mümkün olduğunca formatlanmış JSON döndürün. Claude yapılandırılmış veriyi düz metinden çok daha doğru işler.
Uygun granülarite
Karmaşık bir iş akışını tek bir araca sıkıştırmayın. Basit bir sorguyu da üç araca bölmeyin. İlke şu: bir araç, bağımsız ve anlamlı tek bir işlemi tamamlar.
MCP Server kodu birkaç yere konulabilir:
Proje repository'si içinde (başlangıç için önerilen)
your-project/
├── .claude/settings.json
├── mcp-servers/
│ └── deploy/
│ ├── src/index.ts
│ ├── package.json
│ └── tsconfig.json
└── ...
Avantajı, kod ve konfigürasyonun bir arada olmasıdır; ekip clone edip bağımlılıkları yükleyince hemen kullanmaya başlayabilir.
Ayrı repository
MCP Server birden fazla projede kullanılacaksa, ayrı bir repository'ye koyup npm paketi veya Docker image olarak yayınlayın.
{
"mcpServers": {
"deploy": {
"command": "npx",
"args": ["-y", "@yourcompany/mcp-deploy-server"]
}
}
}
Global kurulum
Şirket genelinde kullanılan MCP Server'lar için (örneğin merkezi kimlik doğrulama veya merkezi log platformu entegrasyonu), global olarak kurup ~/.claude/settings.json dosyasında yapılandırın.
MCP Server geliştirirken en sık karşılaşılan sorunlar "Claude aracımı çağırmıyor" veya "çağırdı ama hata aldı" şeklindedir.
Server'ın başladığından emin olun
Claude Code'u yeniden başlattıktan sonra /mcp yazarak bağlı MCP Server listesini görüntüleyin. Server'ınız listede yoksa command ve args'ı kontrol edin.
Server'ı bağımsız olarak test edin
MCP Server stdio üzerinden iletişim kurar, doğrudan terminalde test edilebilir:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/index.js
Araç listesi döndürülüyorsa, Server'ın kendisinde sorun yok demektir.
Claude'un araç çağrı loglarını inceleyin
Claude Code her araç çağrısının girdisini ve çıktısını gösterir. Parametreler yanlış iletiliyorsa, genellikle araç açıklaması veya parametre tanımı yeterince net olmadığından Claude yanlış anlamıştır.
Şimdi gerçek bir örnekle hepsini bir araya getirelim. Sentry'yi Claude Code'a entegre ederek production hatalarını doğrudan sorgulayabilmeyi sağlayalım.
server.tool(
"search_errors",
"在 Sentry 中搜索最近的错误。用于排查线上问题、查看错误趋势",
{
query: z.string().describe("搜索关键词,如错误信息、函数名"),
hours: z.number().optional().default(24).describe("查看最近多少小时的错误"),
},
async ({ query, hours }) => {
const since = new Date(Date.now() - hours * 3600000).toISOString();
const data = await api(
`/api/0/projects/${ORG}/${PROJECT}/issues/?query=${encodeURIComponent(query)}&start=${since}&sort=date`
);
const summary = data.map((issue: any) => ({
title: issue.title,
count: issue.count,
firstSeen: issue.firstSeen,
lastSeen: issue.lastSeen,
link: issue.permalink,
}));
return {
content: [{ type: "text", text: JSON.stringify(summary, null, 2) }],
};
}
);
server.tool(
"error_details",
"查看 Sentry 中某个错误的详细信息,包括堆栈和最近一次事件",
{ issueId: z.string().describe("Sentry issue ID") },
async ({ issueId }) => {
const [issue, latest] = await Promise.all([
api(`/api/0/issues/${issueId}/`),
api(`/api/0/issues/${issueId}/events/latest/`),
]);
return {
content: [
{
type: "text",
text: JSON.stringify(
{
title: issue.title,
count: issue.count,
users: issue.userCount,
stacktrace: latest.entries?.find(
(e: any) => e.type === "exception"
),
},
null,
2
),
},
],
};
}
);
Entegrasyon tamamlandıktan sonra production sorunlarını araştırma konuşması şöyle olur:
Son 4 saatte yeni 500 hatası var mı?
→ Claude Sentry'de arama yapar
→ 3 yeni issue bulur, en ciddisi 120 kullanıcıyı etkilemiş
→ Otomatik olarak stack trace çeker, null pointer exception olduğunu tespit eder
→ Kodda ilgili konumu bulur, düzeltme önerisi sunar
Sorunu keşfetmekten kodu bulmaya kadar tüm süreç tek bir konuşmada tamamlanır.
Bu yazıda MCP ile dahili araçları nasıl entegre edeceğinizi anlattık. Temel fikir şu: dahili sistemin HTTP API'si var → bir MCP Server yazarak sarmalayın → Claude doğrudan kullanabilir.
Bu yazıdaki tüm örnekler mevcut API'leri sarmalamaktadır — deployment platformu ve Sentry zaten kendi arayüzlerine sahip, MCP Server yalnızca yönlendirme ve uyarlama görevi üstleniyor. Bir sonraki yazıda farklı bir senaryo ele alacağız: ihtiyacınız olan yeteneğin hazır bir API'si olmadığında, sıfırdan bir MCP Server nasıl oluşturulur, kendi mantığınızı nasıl uygularsınız, state yönetimini nasıl yaparsınız ve karmaşık çok adımlı etkileşimleri nasıl yönetirsiniz.