Ana içeriğe geç

Hataları ele alma

Makine çevirisi

Bu sayfa İngilizce dokümantasyondan otomatik olarak çevrildi; esas alınması gereken sürüm İngilizce sayfadır. Yanlış görünen bir şey varsa, nasıl bildireceğinizi Çeviriler sayfası açıklar.

Bir araç iki şekilde başarısız olabilir ve SDK bu ikisini çok farklı ele alır.

Sıradan bir istisna fırlatırsanız bunu model görür. MCPError fırlatırsanız bunu protokol görür.

Bu sayfa, hangisini seçeceğinizle ilgili.

Modelin düzeltebileceği bir hata

Bir şeyi arayıp bulan bir araç düşünün; arama sonuçsuz kalsın:

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")

CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}


@mcp.tool()
def get_author(title: str) -> str:
    """Look up the author of a book in the catalog."""
    if title not in CATALOG:
        raise ValueError(f"No book titled {title!r} in the catalog.")
    return CATALOG[title]

Bu iki satırda MCP'ye özgü hiçbir şey yok. get_author, herhangi bir Python fonksiyonunun yapacağı gibi düz bir ValueError fırlatır.

Katalogda olmayan bir başlıkla çağırın ve sonuca bakın:

result.is_error            # True
result.content             # [TextContent(text="Error executing tool get_author: No book titled 'Nothing' in the catalog.")]
result.structured_content  # None
  • İstek başarılı oldu. Ortada bir sonuç var; çağıran tarafta hiçbir şey fırlatılmadı.
  • is_error değeri True; istisnanızın mesajı (başına araç adı eklenmiş olarak) content'te, tam da modelin okuduğu yerde.
  • structured_content değeri None. Başarısız bir çağrının yapılandırılacak bir dönüş değeri yoktur.

Bu bir araç hatasıdır ve aracınızın fırlattığı her istisna için varsayılan davranış budur. Neredeyse her zaman istediğiniz şey de budur.

Aracınızı çağıran modeldir. Argümanları o seçti. Bu yüzden araç hatası, konuşmada bir tur demektir: model "No book titled 'Nothing' in the catalog." mesajını okur, başlığı yanlış tahmin ettiğini anlar ve daha iyi bir başlıkla tekrar çağırır. Tek bir raise yazdınız ve kendi kendini düzelten bir ajan elde ettiniz.

Tip

Bir araçtan hata mesajını asla return ile döndürmeyin. Döndürülen bir dizenin is_error=False değeri vardır; bu yüzden modele (ve her istemci arayüzüne) araç çalışmış ve yanıt o dizeymiş gibi görünür. raise kullanın. Sinyali veren bayraktır.

Modelin düzeltemeyeceği bir hata

Şimdi ValueError yerine MCPError koyun.

server.py
from mcp import MCPError
from mcp.server import MCPServer
from mcp.types import INVALID_PARAMS

mcp = MCPServer("Bookshop")

CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}


@mcp.tool()
def get_author(title: str) -> str:
    """Look up the author of a book in the catalog."""
    if title not in CATALOG:
        raise MCPError(code=INVALID_PARAMS, message=f"No book titled {title!r} in the catalog.")
    return CATALOG[title]

MCPError, SDK'nın protokol hatasıdır. Araç sarmalayıcısının yakalamadığı tek istisna budur: yayılır ve tools/call isteğinin tamamı bir sonuç yerine JSON-RPC hatasıyla başarısız olur.

{
  "code": -32602,
  "message": "No book titled 'Nothing' in the catalog."
}
  • Sonuç yoktur. content yok, is_error yok: modelin okuyacağı hiçbir şey yok.
  • Hatayı bunun yerine host uygulama alır; tıpkı araç hiç var olmasaydı alacağı gibi.
  • code, message ve data bozulmadan ulaşır. INVALID_PARAMS sabiti -32602 değerini taşır; mcp.types onu ve diğer JSON-RPC hata kodlarını (INVALID_REQUEST, INTERNAL_ERROR, ...) sabit olarak dışa aktarır, böylece hiçbir zaman sihirli bir sayı yazmazsınız.

Check

Aynı arama, aynı sonuçsuzluk; ama bu kez çağrı istemci tarafında döndürmek yerine fırlatır:

mcp.shared.exceptions.MCPError: No book titled 'Nothing' in the catalog.

İlk sürüm modele tepki verebileceği bir cümle vermişti. Bu sürüm ona hiçbir şey vermez. get_author için bu kesinlikle daha kötüdür; bir sonraki bölümün konusu da budur.

Hangisini fırlatmalı

İki yol, iki farklı soruyu yanıtlar.

  • Yürütme başarısızlığı için herhangi bir istisna fırlatın: aracınızın yapmaya çalıştığı şey işe yaramadı. Çağrıyı model seçti, bu yüzden sonucunu da model görmeli ve toparlanma şansı bulmalı. Yanlış yazılmış bir başlık, zaman aşımına uğrayan bir dış API, var olmayan bir satır: hepsi araç hatası.
  • İsteğin kendisi reddedilmesi gerektiğinde MCPError fırlatın: istemcide aracınızın bağımlı olduğu bir yetenek eksik, sunucu kimseye hizmet verecek durumda değil, çağıran taraf zorunlu bir adımı atlamış. Modelin hiçbir yeniden denemesi bunları düzeltmez; bu yüzden mesajı ona vermenin bir kazancı yok.

Kararı tek bir soru verir: daha akıllı bir model bundan kaçınabilir miydi? Evet -> sıradan istisna. Hayır -> MCPError.

Bu ölçüte göre get_author'ın ikinci sürümü yanlış seçim yaptı: daha iyi bir başlık sorunu çözer, yani model mesajı görmeyi hak ediyordu. O sürüm size mekanizmayı göstermek için orada, onu önermek için değil.

Info

MCPError, from mcp import MCPError ile içe aktarılır ve code, message ile isteğe bağlı bir data yükü alır. Bunlara ne koyarsanız istemci onu alır: SDK, fırlatılan bir MCPError'ı temizlemek yerine olduğu gibi iletir.

Var olmayan bir kaynak

Kaynaklar da aynı çizgiyi çeker ve yaygın durum için adlandırılmış bir istisna sunar.

server.py
from mcp.server import MCPServer
from mcp.server.mcpserver.exceptions import ResourceNotFoundError

mcp = MCPServer("Bookshop")

CATALOG = {"Dune": "Frank Herbert", "Neuromancer": "William Gibson"}


@mcp.resource("books://{title}")
def book(title: str) -> str:
    """The catalog entry for one book."""
    if title not in CATALOG:
        raise ResourceNotFoundError(f"No book titled {title!r} in the catalog.")
    return f"{title} by {CATALOG[title]}"

books://{title} bir şablondur. Her başlıkla eşleşir; bu yüzden "URI düzgün biçimli" ile "kitap var" iki farklı sorudur ve ikincisini yalnızca fonksiyonunuz yanıtlayabilir.

Yanıtlayamadığında ResourceNotFoundError fırlatın. SDK bunu, spesifikasyonun eksik bir kaynağa atadığı protokol hatasına dönüştürür: data'da istenen URI ile birlikte -32602; böylece istemci hangi okumanın başarısız olduğunu bilir.

{
  "code": -32602,
  "message": "No book titled 'Nothing' in the catalog.",
  "data": {"uri": "books://Nothing"}
}

Burada is_error=True taşıyan yarım bir sonuç olmadığına dikkat edin. Bir kaynak okuması ya içerik döndürür ya da başarısız olur: kaynakların yalnızca protokol yolu vardır. Şablonlar ve kaynaklarla ilgili diğer her şey Kaynaklar sayfasında.

Hiç fırlatmadığınız hatalar

Hatalı bir argüman fonksiyonunuza asla ulaşmaz.

get_author'a dize olmayan bir title gönderin; SDK sizi çağırmadan önce onu girdi şemasına göre reddeder. Bu da modelin okuyup düzeltebileceği türden, aynı is_error=True araç hatasıdır. Araçlar sayfası aynı reddi bir Field(le=50) kısıtıyla gösterir.

Bu, yazmadığınız koca bir raise ifadesi sınıfı demektir: kendi tür ipuçlarınızı yeniden doğrulamayın.

Info

Bu sayfadaki her şey bir istemcinin gördüğüdür; testleri yazarken kullanacağınız bellek içi Client da tam olarak aynı şeyi görür. raise_exceptions=True bile bir araç hatasını tekrar traceback'e çevirmez: o bayrak devreye girebilecek noktaya geldiğinde istisnanız çoktan is_error=True sonucuna dönüşmüştür. Doğrulamayı sonuç üzerinde yapın. Test etme sayfası bu kalıbı anlatır.

Özet

  • Bir araçta herhangi bir istisna fırlatın -> çağrı, mesajınız content'te olacak şekilde is_error=True döndürür. Model bunu okur ve yeniden deneyebilir. Varsayılan budur.
  • MCPError fırlatın -> çağrının kendisi bir JSON-RPC hatasıyla başarısız olur. Model hiçbir şey görmez; bununla host ilgilenir. code, message ve data bozulmadan ulaşır.
  • Belirleyici soru: daha akıllı bir model bundan kaçınabilir miydi? Evet -> istisna. Hayır -> MCPError.
  • Bir kaynak işleyicisinden ResourceNotFoundError -> protokolün -32602 kodu, URI data'da.
  • Hatalı argümanlar, fonksiyonunuz çalışmadan önce şemaya göre reddedilir; bunlar için raise yazmazsınız.
  • from mcp import MCPError; hata kodu sabitleri mcp.types'tan gelir.

Hatalar halloldu. Bir sunucunun sunduğu her şey bu kadar. Her işleyicinin çalışırken neleri okuyabildiği ve istemciye geri neler yapabildiği bir sonraki bölümde: İşleyicinin içinde.

En sık karşılaşacağınız SDK hatalarının tam metni, her birinin ne anlama geldiği ve her biri için tek hamlelik çözüm Sorun giderme sayfasında.