Model Context Protocol (MCP) ile Global Kamu Verilerini AI Ajanlarına Bağlama Rehberi

Model Context Protocol (MCP) ile Global Kamu Verilerini AI Ajanlarına Bağlama Rehberi
Model Context Protocol (MCP) ile Global Kamu Verilerini AI Ajanlarına Bağlama Rehberi
Bizi Google'da tercih edilen kaynak yapın!

Yapay zeka ajanlarının harici veri kaynakları, yerel dosyalar ve kurumsal API’ler ile güvenli bir şekilde konuşmasını sağlayan açık kaynaklı Model Context Protocol (MCP), LLM entegrasyonlarında hantal ara katmanlar yazma ihtiyacını tamamen ortadan kaldırıyor. Geleneksel yöntemlerde bir yapay zeka modeline harici bir veri tabanını veya API uç noktasını entegre etmek için her modele ve her geliştirme ortamına özel ayrı ayrı “tool calling” fonksiyonları yazmak gerekiyordu. MCP standardı, bu karmaşıklığı tek bir protokol altında birleştirerek veriyi sunan kaynak ile veriyi tüketen ajan (Cursor IDE veya Claude Desktop gibi istemciler) arasında evrensel bir köprü kurar. Bu rehberde, istemci tarafından doğrudan yönetilen, durum bilgisi barındırmayan (stateless) ve alt süreç (child process) olarak tetiklenen Standart I/O (Stdio) transport katmanını kullanarak, Google Data Commons ve Birleşmiş Milletler veri havuzlarına erişen production-ready bir TypeScript MCP sunucusu inşa edeceğiz.

Geliştirme Ortamı ve Tip Güvenlikli Bağımlılıkların Kurulması

Geliştireceğimiz MCP sunucusunun hem derleme zamanında (compile-time) hem de çalışma zamanında (runtime) tip güvenliğini eksiksiz garanti altına almak için Node.js ortamında TypeScript ve şema tabanlı doğrulama kütüphanesi olan Zod mimarisini kuruyoruz. İlk adım olarak projemiz için izole bir dizin oluşturmalı ve Anthropic’in resmi MCP SDK paketlerini içeren bağımlılıkları terminal üzerinden projeye dahil etmeliyiz. Ayrıca yazacağımız TypeScript kodlarını her seferinde elle derlemekle uğraşmamak adına, modern bir çalışma zamanı yürütücüsü olan tsx paketini de geliştirici bağımlılıklarımıza ekliyoruz:

mkdir mcp-global-data && cd mcp-global-data
npm init -y
npm install @modelcontextprotocol/sdk dotenv zod
npm install --save-dev typescript @types/node tsx
npx tsc --init

Kurulum işlemleri tamamlandıktan sonra, projenin kök dizininde hassas verilerimizi koruyacak bir .env dosyası yapılandırmamız gerekiyor. API gizli anahtarlarını kaynak kodun içerisine doğrudan gömmek kurumsal güvenlik politikalarına aykırıdır ve kodun taşınabilirliğini zorlaştırır. Bu nedenle harici veri sağlayıcısından aldığınız geliştirici kimlik kimlik doğrulama anahtarını bu dosyaya güvenli bir şekilde tanımlayın:

DATA_COMMONS_KEY=your_production_api_key_here

TypeScript ile Güvenli MCP Araç Şemasının (Tool Schema) Kodlanması

Altyapımız hazır olduğuna göre, projenin yönetim merkezini oluşturacak olan server.ts dosyasını yazmaya başlayabiliriz. Buradaki en kritik mimari yaklaşım, büyük dil modellerinin (LLM) harici araçları çağırırken parametreleri manipüle etme veya yanlış biçimlendirme eğiliminin önüne geçmektir. Eğer şemamızı katı kurallarla sınırlandırmazsak, model eksik veya geçersiz bir parametre üreterek harici API kotamızı hızla tüketebilir ya da sunucumuzun kilitlenmesine neden olabilir. Bunun önüne geçmek için Zod şeması üzerinde ISO ülke kodunun tam olarak 3 karakterden oluşmasını ve sadece büyük harf barındırmasını zorunlu kılan bir regex (düzenli ifade) kontrolü uyguluyoruz. Sunucumuz, gelen isteği daha dış dünyaya fırlatmadan önce bu şemaya göre valide edecek ve hatalı istekleri anında izole edecektir:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as dotenv from "dotenv";

dotenv.config();

// Evrensel MCP Sunucu Nesnesinin Başlatılması
const server = new McpServer({
  name: "global-data-commons-server",
  version: "1.0.0",
});

// Küresel İstatistik Aracı Şemasının ve Mantığının Tanımlanması
server.tool(
  "get_country_metrics",
  {
    countryCode: z.string().length(3).regex(/^[A-Z]{3}$/).description("3 haneli büyük harf ISO ülke kodu (Örn: TUR, USA, DEU)"),
    metric: z.string().min(2).description("İstenen istatistiksel değişken (Örn: Count_Person, Amount_EconomicActivity_GrossDomesticProduct)"),
  },
  async ({ countryCode, metric }) => {
    const apiKey = process.env.DATA_COMMONS_KEY;
    if (!apiKey) {
      return {
        content: [{ type: "text", text: "Hata: DATA_COMMONS_KEY ortam değişkeni eksik." }],
        isError: true,
      };
    }

    const apiUrl = `https://datacommons.org{countryCode}&metric=${metric}`;
    
    try {
      const response = await fetch(apiUrl, {
        headers: { 
          'Content-Type': 'application/json',
          'X-API-Key': apiKey
        }
      });

      if (!response.ok) {
        throw new Error(`Dış API Hatası Durum Kodu: ${response.status}`);
      }

      const data = await response.json();
      
      return {
        content: [{ 
          type: "text", 
          text: `[Data Commons API Yanıtı] ${metric} (${countryCode}): ${JSON.stringify(data)}` 
        }],
      };
    } catch (error) {
      return {
        content: [{ type: "text", text: `İşlem Başarısız: ${(error as Error).message}` }],
        isError: true,
      };
    }
  }
);

// Stdio Katmanının Dinlemeye Alınması
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Sunucusu Standart I/O üzerinden başarıyla bağlandı ve hazır.");

Yerel İstemcilerin (Claude Desktop ve Cursor) Konfigüre Edilmesi

Geliştirdiğimiz bu MCP sunucusu Standart Giriş/Çıkış (Stdio) transport kanallarını kullanmaktadır. Bu yaklaşımın ağ mimarisi açısından muazzam bir avantajı vardır: Sunucumuz arka planda sürekli olarak belirli bir HTTP portunu işgal etmez, işletim sistemi üzerinde ekstra bir ağ dinleyicisi açmaz ve sunucu kaynaklarını rölantide tüketmez. Bunun yerine, yapay zeka istemcisi (örneğin Cursor veya Claude) tanımladığımız araca ihtiyaç duyduğu milisaniyede bu betiği bir alt süreç (child process) olarak tetikler, veriyi çeker ve işlem tamamlandığında süreci sonlandırır. Claude Desktop entegrasyonunu tamamlamak için kullandığınız işletim sistemine bağlı olarak ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) veya %APPDATA%Claudeclaude_desktop_config.json (Windows) konumundaki ayar dosyasını açarak mevcut kök JSON nesnesinin içerisine yerel projenizin mutlak yolunu (absolute path) içeren şu konfigürasyonu eklemelisiniz:

{
  "mcpServers": {
    "global-data-commons": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/mcp-global-data/server.ts"],
      "env": {
        "DATA_COMMONS_KEY": "GERÇEK_API_ANAHTARINIZ"
      }
    }
  }
}

Eğer günlük yazılım geliştirme süreçlerinizi, kod üretiminizi ve dökümantasyon taramalarınızı Cursor IDE üzerinden yönetiyorsanız entegrasyon adımları tamamen arayüz tabanlıdır. Cursor editörünün üst menüsünden sırasıyla Settings -> Features -> MCP adımlarını takip edin. Karşınıza çıkan ekranda yeni bir sunucu ekleme butonuna basarak isim alanına projenizi sembolize eden global-data-commons etiketini girin. Tip seçimini command olarak belirledikten sonra komut girdi alanına yerel dizininizi işaret edecek şekilde npx tsx /absolute/path/to/mcp-global-data/server.ts komutunu enjekte ederek ajanınızın küresel veri havuzuna anında bağlanmasını sağlayabilirsiniz.

Production Seviyesi Performans İçin Önbellek (Caching) Katmanı

Yapay zeka modelleri mantıksal akıl yürütme (reasoning) süreçleri işletirken veya karmaşık bir kod algoritması üzerinde çalışırken, çok kısa zaman aralıklarında aynı aracı mükerrer parametrelerle üst üste tetikleme eğilimi gösterirler. Eğer sunucumuz ajandan gelen her yinelenen istek için doğrudan harici kamu API uç noktalarına HTTP isteği fırlatırsa, hem ağ gecikmesi (network latency) nedeniyle ajanın yanıt süresi uzayacak hem de harici sunucuların katı istek sınırlarına (Rate Limits) çarparak engellenecektir. Bu mimari tıkanıklığı aşmak amacıyla, sunucu katmanında durumsuz yapıyı bozmadan çalışacak bir bellek haritası (Memory Map) kurmak zorunludur. Belirleyeceğimiz TTL (Time-To-Live) süresi boyunca aynı parametrelerle gelen istekler harici ağa hiç çıkmadan doğrudan RAM üzerinden milisaniyeler içinde yanıtlanır:

interface CacheEntry {
  value: string;
  timestamp: number;
}

const localCache = new Map<string, CacheEntry>();
const CACHE_TTL_MS = 1000 * 60 * 15; // 15 Dakikalık Önbellek Ömrü

// Sunucu Tool Gövdesinde fetch İstetiği Öncesi Çalışacak Kontrol Bloğu:
const cacheKey = `${countryCode}:${metric}`;
const cachedData = localCache.get(cacheKey);

if (cachedData && (Date.now() - cachedData.timestamp < CACHE_TTL_MS)) {
  return {
    content: [{ type: "text", text: cachedData.value }]
  };
}

// Harici API İsteyi Başarılı Olduktan Sonra Belleğe Yazma Adımı:
localCache.set(cacheKey, {
  value: JSON.stringify(data),
  timestamp: Date.now()
});

Bağlam Penceresi (Context Window) Güvenliği İçin Veri Sıkıştırma Fonksiyonu

Kamu veri tabanlarından ve Birleşmiş Milletler istatistik sunucularından dönen ham veriler genellikle geçmişe dönük onlarca yılı kapsayan, yüzlerce satırlık JSON dizilerinden oluşur. Bu boyuttaki ham bir veriyi olduğu gibi LLM’e beslemek büyük bir mimari hatadır. Bu durum hem her istekte token maliyetlerinizi katlayarak cüzdanınızı boşaltır hem de modelin asıl prompt odağını kaybetmesine, yani literatürde “loss in the middle” (ortadaki veriyi kaçırma) olarak bilinen dikkat dağınıklığına yol açar. Sunucu katmanında tasarlayacağımız akıllı bir agregasyon fonksiyonu ile gelen ham veriyi ayıklayıp, meta verilerden arındırarak sadece ajanın analiz etmek istediği en güncel uç noktaları modele dönmek en profesyonel yaklaşımdır:

function compressPayload(rawData: any): string {
  if (!rawData || !rawData.observations) {
    return JSON.stringify(rawData);
  }
  
  // Kronolojik olarak sıralayıp sadece en güncel 3 veri noktasını filtreleme
  const sortedObservations = rawData.observations
    .sort((a: any, b: any) => b.date.localeCompare(a.date))
    .slice(0, 3);
    
  return JSON.stringify({
    info: "Bağlam penceresi optimizasyonu için veri sunucu katmanında sıkıştırılmıştır.",
    latest_metrics: sortedObservations
  });
}

Yukarıda yazdığımız compressPayload fonksiyonundan süzülen optimize edilmiş veri, modelin bağlam penceresini kirletmeden tam olarak ihtiyaç duyduğu istatistiksel özeti sunar. MCP standartları sayesinde yapay zeka ajanları, API yapılarının getirdiği karmaşıklıktan ve ham veri gürültüsünden tamamen izole bir şekilde, dünya gerçekleriyle doğrudan konuşabilir hale gelir.