Bloga dön

Flask ile özel MCP adaptör katmanı: araç tanımları, yönlendirme ve hata ayıklama

Hazır MCP Server çözümleri çoğunlukla yalnızca temel işlemleri sunar; Agent iş adımlarını her seferinde yeniden birleştirip hataları değerlendirmek zorunda kalır. İnce bir Flask adaptör katmanı araç tanımlarını, yönlendirmeyi, yürütmeyi, doğrulamayı ve hata anlamlarını tek yerde toplar.

Bir tarayıcı ortamını AI Agent ile bağlarken kaçınılmaz bir durum vardır: standart araçlar temel işlemleri verir, ancak iş eylemlerini sizin birleştirmeniz gerekir.

Somut bir örnek düşünelim. Bir veri toplama çalışmasını tamamlamak için gerçek akış “bölgeye göre bir ortam aç, çıkışı bağla, ısınma için bir kez ziyaret et ve çıkışın çalıştığını doğrula” şeklindedir; ancak bundan sonra işi Agent’a verirsiniz. Hazır bir MCP Server genellikle ortam açma, gezinme, tıklama ve ekran görüntüsü alma gibi tek adımlı araçlar sunar. Yukarıdaki birleşik mantığı sizin için kimse kurmaz. Agent her seferinde sıralamayı sıfırdan yapmak zorundadır; bu yavaştır ve ara adımlardan biri başarısız olduğunda ne yapılacağına da kendisi karar vermelidir.

Adaptör katmanı tam olarak bunun içindir: birleştirme mantığını, doğrulamayı ve durumu kendi tarafınızda tutup dışarıya yalnızca tek bir iş eylemi açarsınız.

Minimum çalışabilir yapı

Çalışan bir adaptör katmanı yalnızca üç parçaya ihtiyaç duyar: araç tanımları, istek yönlendirme ve yürütme ile sonuç dönüşü. Flask kullanıldığında hepsi tek bir süreçte yer alabilir.

MCP 适配层把工具声明、JSON-RPC 路由、执行器和结构化结果串成可重试的业务流程

Önce araç tanımlarına bakalım; bunlar Agent’ın ne görebileceğini belirler.

# adapter/tools.py
TOOLS = [
    {
        "name": "prepare_environment",
        "description": "Bir bölge için kullanılabilir bir ortam hazırla ve tamamlandığında ortam kimliğini döndür",
        "inputSchema": {
            "type": "object",
            "properties": {
                "region": {"type": "string", "description": "Çıkış bölgesi, örneğin US-CA"},
                "purpose": {"type": "string", "description": "Yeniden kullanım ve kota istatistikleri için amaç etiketi"},
                "timeout": {"type": "integer", "minimum": 10, "maximum": 120, "default": 60},
            },
            "required": ["region"],
            "additionalProperties": False,
        },
    },
    {
        "name": "open_page",
        "description": "Belirtilen ortamda bir sayfa aç ve etkileşime hazır olana kadar bekle",
        "inputSchema": {
            "type": "object",
            "properties": {
                "env_id": {"type": "string"},
                "url": {"type": "string"},
            },
            "required": ["env_id", "url"],
            "additionalProperties": False,
        },
    },
]

Yönlendirici JSON-RPC yöntemlerini dağıtır. İstemci önce tools/list ister, ardından adıyla tools/call çağrısı yapar.

# adapter/app.py
from flask import Flask, request, jsonify
from adapter.tools import TOOLS
from adapter.runner import run_tool

app = Flask(__name__)

@app.post("/mcp")
def mcp():
    req = request.get_json(force=True)
    method, rid = req.get("method"), req.get("id")

    if method == "tools/list":
        return jsonify({"jsonrpc": "2.0", "id": rid, "result": {"tools": TOOLS}})

    if method == "tools/call":
        name = req["params"]["name"]
        args = req["params"].get("arguments", {})
        return jsonify({"jsonrpc": "2.0", "id": rid, "result": run_tool(name, args)})

    return jsonify({"jsonrpc": "2.0", "id": rid,
                    "error": {"code": -32601, "message": "method not found"}})

Yürütme katmanı, ortam API’sine ve sayfa protokolüne dokunan tek yerdir. Çok adımlı akışlar burada tamamlanır, hatalar da burada tek biçimli bir formata dönüştürülür.

# adapter/runner.py
def run_tool(name, args):
    try:
        payload = HANDLERS[name](**args)
        return ok(payload)
    except ToolError as e:
        return fail(e.code, e.retryable, e.message)

Dönüş formatını erken belirlemek faydalıdır. Alt seviyedeki ham istisnaları Agent’a göndermeyin; bu dizeleri yorumlamaya çalışır ve anlamsız kararlar verebilir. Sonuç kodu içeren bir yapı belirleyin; örneğin {"ok": false, "code": "env_unavailable", "retryable": true, "attempts": 3}. Böylece Agent yalnızca iki şeye karar verir: yeniden denenebilir mi ve bir insana aktarılmalı mı?

Parametreler nasıl tasarlanmalı

Araçların kapsamını API uçlarına göre değil, iş eylemlerine göre belirleyin. Her alt seviye endpoint’i ayrı bir araç olarak sarmalamak aslında soyutlama yapmamak demektir; Agent hâlâ adımları kendisi sıralamak zorunda kalır.

Parametrelerde net bir ayrım vardır: modelin karar vermesi gerekenler ve adaptör katmanının kendi karar vermesi gerekenler. Bölge, amaç ve hedef URL ilk gruptadır ve model tarafından doldurulur. Hata ayıklama portu, dahili kuyruk adları ve hangi ortam havuzunun kullanılacağı ikinci gruptadır; bunları schema içine koymayın, çünkü model er ya da geç yanlış dolduracaktır.

Seçiciler kolayca sorun çıkarabilir. Sayfa yapısı değiştiğinde, sabit seçicilere bağlı çağrılar topluca bozulabilir. Modelin “giriş düğmesi” gibi görece kararlı, anlamsal bir hedef göndermesine izin verin; seçici eşlemesini adaptör katmanında tutun. Böylece değişiklik gerektiğinde tek bir yer düzeltilir.

Sayısal parametrelerin mutlaka üst sınırı olmalıdır. timeout, yeniden deneme sayısı veya sayfa sayısı schema içinde maximum ile sınırlandırılmazsa model çok büyük bir değer verebilir ve tek bir çağrı on dakikadan uzun süren bir işe dönüşebilir. Döngü anlamı taşıyan her aracın açık bir bitiş noktası olmalıdır. “Veri kalmayana kadar sayfalamaya devam et” demek yerine max_pages gibi bir alanla sınırı kapatın.

İdempotent davranış da düşünülmelidir. Çağıran taraf bir task_id göndersin; yinelenen istekler önceki sonucu doğrudan döndürerek Agent’ın retry sırasında ikinci kez ortam açmasını önler.

Dönüş değerlerini küçük tutun. Ekran görüntüsünü base64 olarak döndürmeyin; bir dosya referansı verin. Liste sonuçlarında tüm tabloyu bağlama koymak yerine count ve kırpma işareti kullanın.

Hata ayıklarken önce şu üç noktaya bakın

stdio kullanıldığında JSON-RPC stdout’u kullanır; bu nedenle loglar kesinlikle stdout’a yazılmamalıdır. Gelişigüzel bir print protokol ayrıştırmasını anında bozabilir ve uzun süre hata aramanıza yol açabilir. Logları düzenli olarak stderr’e veya bir dosyaya gönderin.

MCP 适配层按标准输出分流、工具列表、逐步追踪和固定夹具的顺序排查问题

tools/list ilk kontrol noktasıdır. Tanımlar yüklenmediyse sonraki çağrıların hiçbiri gerçekleşmez. Önce araç adlarını, schema yapısını ve additionalProperties nedeniyle parametrelerin engellenip engellenmediğini kontrol edin.

İkinci kontrol noktası adım adım trace kaydıdır. Her çağrı için task_id, parametre özeti, süre ve sonuç kodunu kaydedin. Bir sorun olduğunda bunun ortam açma, gezinme veya doğrulama aşamasında mı takıldığını görebilirsiniz. Başarısız örneklerin özgün parametrelerini saklayın ve aynen yeniden oynatın; yeniden üretilebilen bir bug çok daha hızlı düzeltilir.

Üçüncü kontrol noktası sabit bir fixtures setidir: içeriği kararlı bir test sayfası ve değişmeyen birkaç öğe konumlayıcısı. Adaptör katmanındaki her değişiklikten sonra smoke test çalıştırmak, sözlü doğrulamadan çok daha verimlidir.

Yetki sınırları

Adaptör katmanı, tüm sistemde yetkinin en yoğun toplandığı yerdir: kimlik bilgileri, ortamlar ve sayfa işlemleri onun elindedir. Sınırların burada uygulanması gerekir.

Kimlik bilgilerini araç parametrelerinde veya model bağlamında değil, sunucu tarafı yapılandırmada tutun. Araçları risk seviyesine göre ayırın: ekran görüntüsü alma ve metin çıkarma gibi salt okunur araçlar varsayılan olarak açık; tıklama, gönderme ve silme gibi yazma araçları varsayılan olarak kapalı olmalı ve görev için geçici olarak açılmalıdır. Böylece model yanlış karar verse bile zarar sınırlı kalır.

Ortamları amaca göre izole edin. Farklı hesaplar ve farklı görevler farklı ortamlar kullanmalı; tek bir ortamı karıştırmayın. Çoklu hesap yönetiminde ortam oluşturma, ağ çıkışı bağlama ve durum bakımı özel bir ortam katmanına verilebilir. PurpleMark gibi araçlar bu katmanı ayırır; adaptör katmanı ise yalnızca iş akışı birleştirmesi ve doğrulamadan sorumlu olur.

Denetim loglarını saklayın. Hangi görevin ne zaman hangi ortamı kullandığı ve hangi yazma araçlarını çağırdığı zaman bazında dışa aktarılabilmelidir. Gerçek bir sorun çıktığında süreci yeniden oluşturmanın tek yolu bu kayıttır.

Son olarak kesin sınır: adaptör katmanı platform kurallarını aşmaya yarayan hiçbir yol sunmamalıdır. Toplu kayıt, doğrulamayı aşma veya sahte kimlik oluşturma gibi eylemleri araç olarak paketlemeyin ve “dahili araç” adı altında da açmayın. Bir araç modele açıldığı anda çağrılar otomatik gerçekleşebilir; önceden güvenilir bir engelleme noktası yoktur ve sonradan oluşan zarar geri alınamaz.

Protokol sürümleri ve alan tanımları için resmi MCP belgelerini esas alın.