2026-07-08
Bir Protokol Olarak Araçlar
Araçlar, başka hiçbir host'un keşfedemeyeceği hardcoded bir dict. Elle yazılmış minimal bir MCP server ve host, tool kullanımını discovery ve multiplexing'li bir JSON-RPC wire protokolüne dönüştürür.
Neler öğreneceksin
Core track production-şeklinde bir ajanla bitti: plan yapabiliyor, kötü bir step’ten toparlanabiliyor, koşular arasında hatırlayabiliyor, spirale girmeden önce kendini durdurabiliyor, bir crash’ten sağ çıkabiliyor, bir insan için duraklayabiliyor ve içine bakılabiliyor. Makul her ölçüye göre gerçek bir ajan. Yine de Part 1’den beri tutan ve hiç sorgulanmamış tek bir varsayım var: ajanın tool’ları aynı process’in içine gömülmüş hardcoded bir Python dictionary’si. Bu, Part 1’deki TOOL_SCHEMAS’tı ve o zamandan beri ajanın tüm aksiyon uzayı oldu. Sorun şu ki, bir process’teki bir dict başka bir ajanla paylaşılamaz, deploy time’da takas edilemez ya da onu import etmemiş bir host tarafından keşfedilemez. Her entegrasyon, ajanın kendi koduna elle lehimlenmiş özel bir wiring. Bu parça frontier track’i bunu düzelterek açıyor ve çözüm bir protokol. Model Context Protocol (MCP), “ne tür tool’ların var ve onları nasıl çağırırım” sorusunu bir wire protokolüne dönüştürür: bir server capability’leri ilan eder ve bir host onları JSON-RPC üzerinden keşfedip çağırır. Her iki tarafı da elle, yalnızca stdlib ile inşa ediyoruz. İlki, JSON-RPC isteklerini yanıtlayan bir MCP server: initialize handshake’i (protokol versiyonu artı capability negotiation), tools/list, tools/call ve MCP’nin üç server primitive’i, tools, resources ve prompts. İkincisi, handshake’i yapan, tools/list’i çağıran ve keşfedilen JSON inputSchema’yı doğrudan Part 1’in validator ve controller’ına besleyen bir MCP host: hardcoded dict’in yerini alır, sonra iki server’ı tek bir tool paletinde multiplex eder. Tool’lar bir protokol konuştuğu an, herhangi bir host herhangi bir server’ı kullanabilir ve ajanın aksiyon uzayı, neye bağlanırsa ondan, çalışma anında bir araya getirilir.
Ön koşullar
Temel Python ve JSON için bir his yeterli: bir object, bir liste, bir string. Hepsi bu. Part 1 yardımcı olur, çünkü host onun tool-argümanı validator’ını değiştirmeden yeniden kullanıyor, ve Part 2 yardımcı olur, çünkü buradaki refund dikkatle ele almayı öğrendiğimiz aynı side-effect üreten tool. Ama yazı kendi içinde bütünlüklü: daha önceki bir fikre yaslandığı yerde onu tek bir cümleyle yeniden ifade eder ve ReAct loop’unu yeniden öğretmez ya da validator’ı yeniden türetmez; bunlar Part 1 ve 2’ye aittir ve burada referans verilir. Eşlik eden kod, mcp_server_and_host.py, API anahtarı, ağ ve bağımlılık olmadan offline çalışır, böylece her satırı okuyup bu yazıdaki her JSON-RPC frame’ini kendiniz yeniden üretebilirsiniz. Varsayılan transport, gerçek protokol frame’leri yazdıran in-process bir shim’dir; gerçek LLM controller’ı (generate()) ve gerçek subprocess-over-stdio transport’u her biri tek bir adım uzaklıkta, tam olarak Part 1’den 11’e kadarki gibi.
Core track’ten beri yeni olan ne
Neyin yeni olduğu konusunda kesin olmak istiyorum, çünkü bu gerçekten yeni bir zemin, daha önceki serideki herhangi bir şeyin rafine edilmiş hâli değil. Şu ana kadarki her parça, ta RAG’e kadar, ajana tool’larını aynı şekilde verdi: yazarın wire ettiği bir tek-process dictionary’si olarak. RAG Part 19 bir tool dict’ini hardcode etti; buradaki Part 1 TOOL_SCHEMAS’ı hardcode etti; Part 6’daki memory tool’ları aynı in-process contract’la deklare edildi. Her durumda ajan tool’larını biliyordu, çünkü birisi onları ajanın kendi kaynağına yazmıştı. MCP’nin değiştirdiği şey, o bilginin kaynağı. Tool’lar, yazma anında import edilen sembollerden değil, çalışma anında JSON-RPC üzerinden gelen keşfedilmiş, şema ile tanımlanmış capability’ler hâline gelir. Bir server, bir tool’un adını, açıklamasını ve inputSchema’sını yayımlar; host onları sorarak öğrenir. Ve MCP tool’lardan fazlasını standartlaştırır: üç primitive tanımlar, tools (çağrılabilir aksiyonlar), resources (host’un fetch edebileceği read-only veri) ve prompts (adlandırılmış prompt template’leri), böylece bir server her üçünü tek bir handshake’in arkasında sunabilir. Bu parçanın yeniden inşa etmek yerine bilerek yeniden kullandığı tek şey Part 1’in validator’ı. Kontrol ettiği şema artık hardcoded bir dict’ten gelmiyor; tools/list’ten hat üzerinden geliyor. Aynı validator, aynı garanti, farklı kaynak. Ona referans veriyoruz ve onu yeniden türetmiyoruz.
Handshake ve discovery
Bir protokol bir handshake ile başlar, ve MCP’ninki initialize. Host, konuştuğu protokol versiyonunu ve kim olduğunu ilan ederek bağlantıyı açar; server, üzerinde anlaştığı versiyon, kendi kimliği ve desteklediği capability setiyle yanıt verir. İşte hat üzerindeki ilk iki frame, artefaktın gerçek çıktısından alıntılanmış:
--> {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "clientInfo": {"name": "agents-by-hand-host"}}}
<-- {"jsonrpc": "2.0", "id": 1, "result": {"protocolVersion": "2025-06-18", "serverInfo": {"name": "support-server"}, "capabilities": {"tools": {}, "resources": {}, "prompts": {}}}}
[host] connected to support-server (protocol 2025-06-18, capabilities: tools, resources, prompts)
O frame’lerin şeklini oku, çünkü bu sadece JSON-RPC: her istek "jsonrpc": "2.0", bir id, bir method ve params taşıyan bir JSON object’i; her yanıt id’yi echo eder ve ya bir result ya da bir error taşır. id, birkaçı aynı anda havadayken bile isteğin ve yanıtın eşleştirilmesini sağlayan şeydir. Handshake’te host protocolVersion: "2025-06-18" gönderir ve server aynı versiyonu geri onaylar: bu version negotiation, yıllar arayla yazılmış bir host ile bir server’ın başka hiçbir şey söylemeden önce bir lehçe üzerinde anlaşmasını sağlayan adım. Server ayrıca capability’lerini ilan eder: support-server tools, resources ve prompts deklare eder, yani her üç primitive’i de sunar. Yalnızca çağrılabilir aksiyonları olan bir server sadece tools ilan ederdi ve host ondan resources ya da prompts istememesi gerektiğini bilirdi. Handshake bitince host discovery call’unu yapar:
--> {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}
<-- {"jsonrpc": "2.0", "id": 2, "result": {"tools": [{"name": "search_policy", "description": "search the support/policy index", "inputSchema": {"type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"]}}, {"name": "process_refund", "description": "issue a refund for an order (side-effecting)", "inputSchema": {"type": "object", "properties": {"order_id": {"type": "string"}, "amount": {"type": "number"}}, "required": ["order_id", "amount"]}}]}}
[host] discovered tools: ['search_policy', 'process_refund']
O tek yanıt protokolün tüm meselesi. Host TOOL_SCHEMAS’ı import etmedi; sordu, ve server ona adları, açıklamaları ve inputSchema object’leriyle iki tool geri verdi. search_policy zorunlu bir query string’i alır; process_refund zorunlu bir order_id string’i ve zorunlu bir amount number’ı alır ve açıklaması onu side-effect üreten olarak işaretler. Host artık server’ın tüm aksiyon uzayını biliyor ve onu hat üzerinden öğrendi. discovered tools: ['search_policy', 'process_refund'] satırı, ajanın paletinin kaynağını hiç görmediği bir server’dan çalışma anında bir araya getirilmesi.
Üç primitive
MCP, bir server’ın açığa çıkarabileceği üç tür şeyi standartlaştırır ve bunlar ajanın gerçekten ihtiyaç duyduğu üç şeye karşılık gelir. Tools, side-effect’leri ya da hesabı olan çağrılabilir aksiyonlardır. Resources, bir doküman ya da bir config dosyası gibi, host’un URI ile fetch edebileceği read-only veridir. Prompts, host’un wording’i hardcode etmek zorunda kalmaması için server’ın küratörlüğünü yaptığı adlandırılmış, yeniden kullanılabilir prompt template’leridir. Tek handshake, üç primitive, her biri kendi method’uyla. İşte host her üçünü kullanırken, artefaktın gerçek çıktısından alıntılanmış:
tools/call:
--> {"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "search_policy", "arguments": {"query": "refund window"}}}
<-- {"jsonrpc": "2.0", "id": 3, "result": {"content": [{"type": "text", "text": "Refunds are accepted within 30 days; after the window a 10% restocking fee applies."}], "isError": false}}
[host] result: Refunds are accepted within 30 days; after the window a 10% restocking fee applies.
resources/read:
--> {"jsonrpc": "2.0", "id": 4, "method": "resources/read", "params": {"uri": "file:///policies/refund.md"}}
<-- {"jsonrpc": "2.0", "id": 4, "result": {"contents": [{"uri": "file:///policies/refund.md", "text": "Refunds within 30 days; 10% restocking fee after."}]}}
[host] resource text: 'Refunds within 30 days; 10% restocking fee after.'
prompts/get:
--> {"jsonrpc": "2.0", "id": 5, "method": "prompts/get", "params": {"name": "refund_decision"}}
<-- {"jsonrpc": "2.0", "id": 5, "result": {"messages": [{"role": "user", "content": {"type": "text", "text": "Decide the refund for {order}, citing the policy."}}]}}
[host] prompt template: 'Decide the refund for {order}, citing the policy.'
Her call’u kendi primitive’ine karşı oku. tools/call (id 3) search_policy’yi arguments: {"query": "refund window"} ile çalıştırır ve type: "text" olan bir content bloğu, Refunds are accepted within 30 days; after the window a 10% restocking fee applies., artı bir server’ın başarıyı tool-seviyesinde bir başarısızlıktan ayırt etme şekli olan isError: false geri alır. resources/read (id 4) file:///policies/refund.md URI’sini fetch eder ve metnini, Refunds within 30 days; 10% restocking fee after., döner: read-only veri, execution yok, adıyla çağrılmak yerine URI ile adreslenmiş. prompts/get (id 5) adlandırılmış template refund_decision’ı alır, ki Decide the refund for {order}, citing the policy. metniyle bir mesaj olarak geri gelir, host’un doldurup modeline gönderebileceği server-küratörlüğünde bir prompt. Üç method, üç primitive, hepsi aynı handshake’in ve aynı JSON-RPC envelope’unun arkasında. id’nin tırmandığına dikkat et (3, 4, 5), böylece her yanıt isteğiyle eşleşir, ve bunları çağıran host kodunun, hangi primitive’e uzandığından bağımsız olarak şekil olarak aynı olduğuna.
Keşfedilen şemalar controller’ı sürer
İşte protokolün karşılığını verdiği ve Part 1’e geri bağlandığı yer. Host’un process_refund için keşfettiği inputSchema, sıradan bir JSON Schema object’i, ve bu tam olarak Part 1’in validator’ının zaten kontrol etmeyi bildiği şey. Dolayısıyla host hat üzerinden keşfedilen şemayı doğrudan değiştirilmemiş validator’a verir ve controller’ın argüman kontrolü her zamanki gibi çalışır, sadece artık kurallar bir dict’ten değil ağ üzerinden geldi. Keşfedilen process_refund şemasına karşı doğrulanan üç argüman setini izle, artefaktın gerçek çıktısından alıntılanmış:
validate {"order_id": "ORD-3300", "amount": 180.0} -> OK
validate {"order_id": "ORD-3300"} -> REJECTED: missing required arg 'amount'
validate {"order_id": "ORD-3300", "amount": "lots"} -> REJECTED: arg 'amount' must be number
The schema was not hardcoded; it arrived from tools/list. Part 1's guarantee, over MCP.
Üçünü de oku. İyi biçimlendirilmiş bir call, {"order_id": "ORD-3300", "amount": 180.0}, geçer: her iki zorunlu key de mevcut ve amount bir number, dolayısıyla validator OK döner. amount’u düşür ve validator onu missing required arg 'amount' ile reddeder, çünkü şemanın (host’un hat üzerinden okuduğu) required listesi onu adlandırır. amount’u "lots" string’i olarak gönder ve arg 'amount' must be number ile reddedilir, çünkü şemanın properties’i amount’un type: "number" olduğunu söyler. Bu byte-byte Part 1 contract’ı, call hiç fire etmeden önce kontrol edilen tipli bir şema, sadece şema artık ajanın yazarının yazdığı bir şey değil. tools/list’ten geldi. Son satır bunu açıkça söyler: şema hardcode edilmedi, protokolden geldi, ve Part 1’in garantisi MCP üzerinde tutar. Aşağıdaki amiral figür, handshake’ten discovery’ye, oradan doğrulanmış bir call’a kadar tüm sekansta adım adım ilerlemeni sağlar, her JSON-RPC frame’inin hat üzerinden geçişini izleyerek.
Tek host, çok server
Tek bir server faydalıdır, ama bir protokolün gerçek erişimi birden fazlasıyla ortaya çıkar. Her server aynı handshake’i ve aynı discovery call’unu konuştuğu için, bir host aynı anda birkaçına bağlanıp onları multiplex edebilir: her birinin ilan ettiğini tek bir tool paletinde birleştirir, ve ajan onun üzerindeki herhangi bir tool’u, hangi server’ın arkasında olduğunu bilmeden ya da umursamadan çağırır. İşte host iki server’a, support-server ve bir catalog-server’a bağlanırken ve ortaya çıkan birleşik palet, artefaktın gerçek çıktısından alıntılanmış:
[host] connected to support-server (protocol 2025-06-18, capabilities: tools, resources, prompts)
[host] connected to catalog-server (protocol 2025-06-18, capabilities: tools)
[host] palette across 2 servers:
search_policy from support-server
process_refund from support-server
search_products from catalog-server
A multi-hop task now uses tools from different servers transparently:
search_products (catalog-server) -> Acme Corp was acquired by Globex in 2024.
search_products (catalog-server) -> Globex-branded wireless earbuds carry a 2-year limited warranty.
process_refund (support-server) available on the same palette
Paleti oku. support-server tools, resources, prompts ilan etti; catalog-server yalnızca tools ilan etti, ve host buna saygı duyar, ondan sunmadığı hiçbir şeyi istemez. Birleşik palet üç tool tutar: support-server’dan search_policy ve process_refund, ve catalog-server’dan search_products. Host her tool adından onu destekleyen server’a giden küçük bir map tutar, böylece ajan search_products’u çağırdığında host tools/call’u catalog-server’a yönlendirir ve process_refund’u çağırdığında support-server’a yönlendirir, hepsi ajanın mantığı değişmeden. Multi-hop koşu bunun çalıştığını gösterir: iki search_products call’u catalog-server’a vurur (Acme Corp was acquired by Globex in 2024. ve Globex-branded wireless earbuds carry a 2-year limited warranty. döndürerek), ve support-server’dan process_refund tam aynı palette hazır oturur. Protokolün bileşik getirisi budur: bir server ekle, ve onun tool’ları ajanın aksiyon uzayında basitçe belirir, yeni wiring yok, ajana edit yok.
Şimdi in-process, production’da stdio
Şimdi dürüst kısım, çünkü transport tüm feasibility sorusu ve üstünden el sallamak kolay. Eşlik eden koddaki varsayılan, in-process bir JSON-RPC shim: host server.handle(request)’i doğrudan, aynı Python process’inde, socket olmadan ve ikinci bir process işin içinde olmadan çağırır. Ama gönderdiği ve aldığı her mesaj verbatim yazdırılan gerçek bir JSON-RPC frame’i, dolayısıyla yukarıda okuduğun byte’lar tam olarak bir wire’dan geçecek byte’lar. Koşunun açılış satırı bunu söyler:
[transport] in-process JSON-RPC shim (default): the host calls server.handle()
directly, but every frame below is a real JSON-RPC message printed verbatim.
Koşuyu deterministic ve reproducible kılan şey budur: ağ yok, timing yok, koordine edilecek ikinci bir process yok, sadece protokol frame’lerine bürünmüş fonksiyon call’ları. Gerçek deployment farklıdır. Server kendi işletim sistemi process’i olarak çalışır ve host ona stdio üzerinden konuşur: JSON-RPC isteklerini server’ın standard input’una yazar ve yanıtları onun standard output’undan okur, bir lokal process diğerine boru bağlar, lokal bir server için hâlâ ağ gerekmez. Eşlik eden kod o path’i de gösterir, ama açıkça etiketlenmiş, açıklayıcı bir transcript olarak, dondurulmuş doğrulanmış bir koşu olarak değil. Tam olarak şöyle işaretlenmiştir:
THE REAL TRANSPORT (illustrative, not executed here): server as a subprocess over
stdio. Two local processes, no network. Shown for reference; the verified run above
uses the in-process shim.
$ python mcp_server.py # process A: reads JSON-RPC from stdin
host -> server (stdin): {"jsonrpc":"2.0","id":1,"method":"initialize",...}
server -> host (stdout): {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":...}}
host -> server (stdin): {"jsonrpc":"2.0","id":2,"method":"tools/list"}
server -> host (stdout): {"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}
(same frames as above, now crossing a pipe between two OS processes)
Akılda tutulacak şey, iki path’in yalnızca transport’ta farklı olması, protokolde değil. Frame’ler özdeş; değişen şey, handle()’ın aynı process’te bir fonksiyon call’u mu yoksa iki process arasında bir boru mu olduğu. Bu tasarım gereği: bir protokol tam olarak, byte’ların ne söylediğine dokunmadan nasıl yolculuk ettiğini takas etmeni sağlayan katmandır. In-process shim doğrulanmış varsayılandır, tam olarak protokolü process yönetiminin karmaşasından izole ettiği için, ve stdio path’i, tam aynı frame’leri taşıyan birkaç gerçek transport’tan biridir (lokal server’lar için stdio, uzak olanlar için HTTP). Stdio transcript’ini bilerek açıklayıcı olarak etiketledim: process başlatma, buffering ve protokol versiyonunun kendisi hızlı hareket eder, dolayısıyla onu byte-dondurulmuş bir koşu değil, şeklin sadık bir resmi olarak ele al.
Kenar notu: skills ve progressive tool disclosure
Çok sayıda server’a bağlanan bir host, palet büyüdüğü an bir ölçeklenme sorunuyla karşılaşır. Bir düzine server’a bağlan ve yüzlerce tool tutuyor olabilirsin, ve her birinin şemasını her turn’de modelin context’ine tıkmak hem pahalı hem kafa karıştırıcı: model hiç kullanmayacağı tool’ları okuyup geçmek zorunda ve fatura görevle değil katalogla büyür. Çözüm MCP’nin discovery call’larıyla doğal olarak eşleşir: progressive tool disclosure. Tüm şemaları en baştan prompt’a koymak yerine, host tool’ları aşamalı olarak açar, önce adlar ve tek satırlık açıklamalar, ve bir tool’un tam
inputSchema’sını yalnızca model gerçekten ona uzandığında fetch eder. Bu, skills’in arkasındaki aynı fikir: ajanın ucuza göz atıp gerektiğinde detaylı yükleyebileceği büyük bir capability kütüphanesi. MCP’nintools/list’i (ucuz, adlar ve açıklamalar) vetools/call’u (tam şema ve execution, yalnızca gerektiğinde ulaşılan) progressive disclosure’ın istediği tam olarak iki-aşamalı şekildir, dolayısıyla protokol ve disclosure stratejisi ekstra makine olmadan birbirine uyar.
💡 Deneyimden. Bu protokolün karşılığını en net verdiği an, bir entegrasyon yazmak yerine sildiğim gündü. Bir takımın ajanına elle wire edilmiş bir refund tool’umuz vardı, alışılmış özel iş: argüman şeması ajanın kodunda, HTTP call’u inline, error handling loop’a dolanmış. İkinci bir takım aynı capability’yi kendi ajanlarında istedi, ve eski cevap wiring’i kopyalamak, şemayı fork etmek ve sonsuza dek birbirinden hafifçe sapan iki versiyonu senkronda tutmak olurdu. Bunun yerine tool’u
tools/listüzerinden ilan eden küçük bir MCP server’a çektim ve her iki host’u ona yönelttim. İkinci takımın ajanı tool’u keşfetti,inputSchema’sını kendi validator’larına besledi ve onu çağırdı, kendi taraflarında sıfır yeni entegrasyon kodu ile. Şema sapamadı çünkü artık tam olarak bir tane vardı, protokolün arkasında yaşıyordu. Diğer ders handshake’ten geldi ve bir hikaye değil bir kurtarma olarak geldi: bağlandığımız bir server capability’lerinde yalnızcatoolsilan etti,resourcesyok, ve host’umuz ondan bir config dosyasınıresources/readedebileceğini varsaymıştı. Capability negotiationinitialize’da gerçekleştiği için, uyumsuzluk bağlantı anında temiz bir “bu server resources sunmuyor” olarak yüzeye çıktı, canlı bir koşunun üç adım içinde kafa karıştırıcı bir başarısızlık olarak değil. Handshake, bir runtime gizemi olacak şeyi bir startup kontrolüne dönüştürdü.
Özet / Çıkarımlar
- Ajanın tool’ları Part 1’den beri bir process’te hardcoded bir Python dict’iydi (
TOOL_SCHEMAS). Bir dict başka bir host’la paylaşılamaz, deploy time’da takas edilemez ya da onu import etmemiş kod tarafından keşfedilemez. Frontier track o dict’i bir protokolle değiştirerek açılır. - MCP tool kullanımını bir wire protokolüne dönüştürür. Bir server capability’leri ilan eder; bir host onları JSON-RPC üzerinden keşfeder ve çağırır (
"jsonrpc": "2.0", birid, birmethod,params, ve eşleşen birresultya daerror). Ajanın aksiyon uzayı, neye bağlanırsa o server’lardan çalışma anında bir araya getirilir. initializehandshake’i protokol versiyonunu (burada2025-06-18) müzakere eder ve capability’leri ilan eder.support-servertools, resources, promptsilan eder;catalog-serveryalnızcatoolsilan eder. Sonratools/listtool’ları keşfeder: hostsearch_policyveprocess_refund’u import ederek değil, sorarak öğrendi.- MCP tek bir handshake’in arkasında üç primitive tanımlar: tools (çağrılabilir aksiyonlar,
tools/callile), resources (URI ile fetch edilen read-only veri,resources/readile), ve prompts (adlandırılmış template’ler,prompts/getile). Her birini çağıran host kodu şekil olarak aynıdır. - Keşfedilen
inputSchemaPart 1’in validator’ını değiştirmeden sürer:{"order_id": "ORD-3300", "amount": 180.0}OKdoğrulanır,amount’u düşürmekREJECTED: missing required arg 'amount', veamount: "lots"REJECTED: arg 'amount' must be number. Aynı tipli-argüman garantisi, ama şema bir dict’ten değiltools/list’ten geldi. - Tek host çok server’ı multiplex eder: iki server’daki palet birleşimdir (
support-server’dansearch_policy,process_refund;catalog-server’dansearch_products), ve bir multi-hop görev onların arasında şeffafça çağrı yapar. Bir server ekle ve tool’ları basitçe belirir, yeni wiring olmadan. - Doğrulanmış varsayılan in-process bir JSON-RPC shim’dir (gerçek frame’ler, ağ yok); gerçek transport server’ı stdio üzerinden bir subprocess olarak çalıştırır (açıklayıcı, çalıştırılmamış bir transcript olarak gösterilir). İkisi yalnızca transport’ta farklıdır, protokolde değil; frame’ler özdeştir. Büyük bir palet progressive tool disclosure ile eşleşir (önce adlar, talep üzerine tam şema), skills ile aynı fikir.
Sözlük
- MCP (Model Context Protocol): “ne tür tool’ların var ve onları nasıl çağırırım”ı bir wire protokolüne dönüştüren bir standart, böylece bir server capability’leri ilan edebilir ve herhangi bir host onları keşfedip çağırabilir. Hardcoded, tek-process tool dict’inin yerini alır.
- JSON-RPC: MCP’nin üzerinde taşındığı mesaj formatı. Her istek
"jsonrpc": "2.0", birid, birmethodveparamstaşıyan bir JSON object’idir; her yanıtid’yi echo eder ve ya birresultya da birerrortaşır.idyanıtları isteklere eşleştirir. initializehandshake’i: bir bağlantıdaki ilk değiş tokuş, host’un protokol versiyonunu ve kimliğini ilan ettiği ve server’ın üzerinde anlaşılan versiyon, kimliği ve capability’leriyle yanıt verdiği yer. O tamamlanana kadar başka hiçbir şey olmaz.- protocolVersion / capability negotiation: handshake bir lehçe üzerinde anlaşır (burada
2025-06-18), böylece ayrı yazılmış bir host ve server interoperate edebilir, ve server hangi capability’leri desteklediğini ilan eder (tools, resources, prompts), böylece host ne isteyebileceğini bilir.catalog-servergibi yalnızca-toolsolan bir server’dan resources istenmez. - Üç primitive (tools / resources / prompts): bir MCP server’ının açığa çıkarabileceği üç tür şey. Tools çağrılabilir aksiyonlardır (
tools/call); resources URI ile fetch edilen read-only veridir (resources/read); prompts adlandırılmış, yeniden kullanılabilir prompt template’leridir (prompts/get). - inputSchema: bir tool’un argümanları için JSON Schema’sı,
tools/list’te taşınır (type,properties,required). Sadece veri olduğu için host onu doğrudan Part 1’in validator’ına besleyebilir; şema artık bir dict’ten değil hat üzerinden gelir. - Host vs server: server capability’lere sahip olur ve onları açığa çıkarır (
initialize,tools/list,tools/callve resource ile prompt method’larını yanıtlar); host bağlanır, keşfeder ve onları çağırır, sonra keşfedilen şemaları ajanın controller’ına besler. Ajan host tarafında yaşar. - Multiplexing: tek bir host’un birkaç server’a bağlanması ve ilan ettikleri capability’leri tek bir tool paletinde birleştirmesi, her tool adından onu destekleyen server’a bir map tutarak, böylece ajan herhangi bir tool’u hangi server’ın yerine getirdiğini bilmeden çağırır.
- In-process shim vs stdio transport: aynı frame’leri taşımanın iki yolu. In-process shim host’un
server.handle()’ı tek bir process’te doğrudan çağırmasını sağlar (deterministic, doğrulanmış varsayılan); stdio transport server’ı ayrı bir OS process’i olarak çalıştırır ve JSON-RPC’yi standard input ve output üzerinden boru bağlar (gerçek lokal deployment). Yalnızca transport’ta farklıdırlar, protokolde değil. - Progressive tool disclosure: yüzlerce tool tutan bir host için bir strateji, onları aşamalı olarak açar (önce adlar ve açıklamalar, tam
inputSchema’yı yalnızca model bir tool’a uzandığında) her şemayı prompt’a koymak yerine. Skills ile aynı fikir, ve MCP’nin ucuztools/list’i artı talep üzerinetools/call’u için doğal bir uyum.
Bu parçanın kuralı: ajanın tool’larını kendi process’ine hardcode etmeyi bırak, ve bunun yerine tool kullanımını bir protokol yap. Capability’lerini ilan eden bir server ve onları JSON-RPC üzerinden keşfeden bir host ayağa kaldır, protokol versiyonunu ve capability’leri bir initialize handshake’inde müzakere et, üç primitive’i (tools, resources, prompts) açığa çıkar, keşfedilen inputSchema’yı zaten sahip olduğun validator’a doğrudan besle, ve çok server’ı çalışma anında bir araya getirilen tek bir palette multiplex et. Reproducibility için in-process shim’i tut ve gerçek deployment için stdio transport’unu takas et; aynı frame’leri taşırlar. Bu, tool’ların özel bir dictionary’sini herhangi bir host’un bağlanabileceği, keşfedebileceği ve çağırabileceği bir şeye dönüştürür. Ama tartıştığımız her tool’un şekline dikkat et: ajanın doldurduğu ve server’ın çalıştırdığı tipli bir JSON fonksiyonu. Bazı görevler bu kalıba uymaz. İş “bu dizini keşfet, bu dosyaları dönüştür, bu şeyi hesapla” olduğunda, ajan yüzlerce tipli fonksiyonu çağırmak istemez; kod yazıp çalıştırmak ister. Part 13, The Code-Running Tool, ajana kod çalıştırmak ve bir bilgisayar işletmek için bir sandbox verir, ki bu muazzam derecede daha güçlü ve, ajan keyfi kod çalıştırabildiği an, muazzam derecede daha tehlikeli: kod çalıştırabildiği an gerçek hasar verebilir, ve sandbox faydalı bir ajanla felaket bir ajan arasında duran şeydir.