Ana içeriğe geç

Kaynaklar

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.

Kaynak, uygulamanın okuması için sunduğunuz veridir.

Ayrım bu. Araç, modelin çağırmaya karar verdiği şeydir. Kaynak ise uygulamanın yüklemeye (bir yapılandırma dosyası, bir kayıt, bir belge) ve bağlam olarak modelin önüne koymaya karar verdiği şeydir.

Bir kaynağı, sıradan bir Python fonksiyonunun üzerine @mcp.resource(uri) koyarak bildirirsiniz.

İlk kaynağınız

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.resource("config://app")
def get_config() -> str:
    """The active shop configuration."""
    return "theme=dark\nlanguage=en"

Şekli bir araçla aynı, bir fazlası var: URI. Kaynaklara adla değil, adresle erişilir. İstemci config://app ister, asla get_config istemez.

SDK geri kalanını yine fonksiyondan okur:

  • Ad, fonksiyonun adıdır: get_config.
  • İstemcinin gördüğü açıklama, docstring'dir.
  • İçerik, ne döndürürseniz odur.

resources/list sırasında istemci şunu alır:

{
  "name": "get_config",
  "uri": "config://app",
  "description": "The active shop configuration.",
  "mimeType": "text/plain"
}

config://app kaynağını okuduğunda ise fonksiyonunuz çalışır ve dönüş değeri metin olarak geri gelir:

result.contents  # [TextResourceContents(uri="config://app", mime_type="text/plain", text="theme=dark\nlanguage=en")]

Tip

Listeleme ucuzdur. Fonksiyonunuz resources/list sırasında çağrılmaz; yalnızca resources/read sırasında ve yalnızca istenen URI için çağrılır. Bin kaynak sunun, bedelini yalnızca birinin açtıkları için ödersiniz.

Deneyin

Sunucuyu MCP Inspector ile çalıştırın:

uv run mcp dev server.py

Yazdırdığı URL'yi açın ve Resources sekmesine gidin. config://app, açıklamasıyla birlikte listede. Tıklayın, Inspector onu okur: iki satırlık yapılandırmanız karşınızda.

Kaynak şablonları

Kayıt başına bir URI ölçeklenmez. URI'ye bir yer tutucu, fonksiyona da onunla eşleşen bir parametre koyun:

server.py
from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.resource("config://app")
def get_config() -> str:
    """The active shop configuration."""
    return "theme=dark\nlanguage=en"


@mcp.resource("users://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """A customer's profile."""
    return f"User {user_id}: 12 orders since 2021."

URI'de {user_id}, fonksiyonda user_id: str. Sözleşmenin tamamı bu.

Bu artık bir kaynak şablonu ve yeri değişir: resources/list yanıtından çıkar, onun yerine resources/templates/list yanıtında görünür; bir adres olarak değil, bir desen olarak:

{
  "name": "get_user_profile",
  "uriTemplate": "users://{user_id}/profile",
  "description": "A customer's profile.",
  "mimeType": "text/plain"
}

İstemci yer tutucuyu doldurur ve somut bir URI okur: users://42/profile, users://ada/profile. Hepsine tek bir fonksiyon yanıt verir; eşleşen değer user_id olarak geçirilir:

result.contents  # [TextResourceContents(uri="users://42/profile", text="User 42: 12 orders since 2021.")]

Sonuçtaki uri alanına dikkat edin. Bu, şablon değil, istemcinin istediği somut URI'dir.

Check

Yer tutucular ile parametreler uyuşmak zorunda. URI hâlâ {user_id} derken fonksiyon parametresinin adını user olarak değiştirirseniz dekoratör, herhangi bir istemci yanına bile yaklaşmadan, içe aktarma sırasında reddeder:

ValueError: Mismatch between URI parameters {'user_id'} and function parameters {'user'}

Bir uyuşmazlık ancak bir hata olabilir; bu yüzden SDK, sunucuyu böyle bir hatayla başlatmayı imkânsız kılar.

Yer tutucu sözdizimi RFC 6570 standardıdır: çok parçalı değerler için {+path}, isteğe bağlı sorgu parametreleri için {?q,lang} ve dahası. SDK ayrıca çıkarılan değerlere varsayılan olarak yol güvenliği denetimleri uygular. Tam başvuru için URI şablonları ve yol güvenliği sayfasına bakın.

get_user_profile, Context ile işaretlenmiş bir parametre de alabilir. SDK onu hiçbir zaman URI parametresi saymadan enjekte eder; size neler sağladığını Context nesnesi sayfası anlatır.

Döndürdükleriniz

str ile sınırlı değilsiniz. Her kaynağa bir mime_type verin ve neyi uygun görüyorsanız onu döndürün:

server.py
import base64

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.resource("docs://readme", mime_type="text/markdown")
def readme() -> str:
    """How to use this server."""
    return "# Bookshop\n\nSearch the catalog with the `search_books` tool."


@mcp.resource("stats://catalog", mime_type="application/json")
def catalog_stats() -> dict[str, int]:
    """Live counts for the catalog."""
    return {"books": 1204, "authors": 391}


@mcp.resource("covers://placeholder", mime_type="image/gif")
def placeholder_cover() -> bytes:
    """A 1x1 transparent GIF, shown when a book has no cover."""
    return base64.b64decode("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")
  • readme bir str döndürür, bu yüzden olduğu gibi gönderilir. Yaygın durum budur.
  • catalog_stats bir dict döndürür, bu yüzden SDK onu sizin için JSON metnine serileştirir:

    {
      "books": 1204,
      "authors": 391
    }
    
  • placeholder_cover bytes döndürür, bu yüzden istemci TextResourceContents yerine bir BlobResourceContents alır; baytlarınız blob alanında base64 ile kodlanmış olarak yer alır.

Aynı kural JSON'a serileştirilebilen başka her şey için de geçerlidir: bir liste, bir Pydantic modeli, bir dataclass. str değilse ve bytes değilse JSON olur.

mime_type'ı siz bildirirsiniz; varsayılan olarak text/plain. SDK, bunu tahmin etmek için döndürdüğünüz şeyi asla incelemez; bu yüzden etiketlemediğiniz bir dict kaynağı yine düz metin olarak duyurulur.

Tip

Bunları fonksiyondan türetmek istemediğinizde @mcp.resource(), name=, title= ve description= parametrelerini de kabul eder. Yazacak bir fonksiyon hiç olmadığında ise mcp.server.mcpserver.resources içinde, mcp.add_resource(...) ile kaydedeceğiniz hazır Resource sınıfları var (TextResource, BinaryResource, FileResource, HttpResource, DirectoryResource).

İstemci bir kaynağa abone de olabilir ve kaynak değiştiğinde bildirim alabilir; bu, hikâyenin istemci tarafı ve İstemci sayfasında anlatılır.

Özet

  • Bir fonksiyonun üzerindeki @mcp.resource(uri) onu kaynak yapar. URI adrestir, dönüş değeri içeriktir, docstring açıklamadır.
  • URI'deki bir {placeholder} onu şablon yapar: resources/templates/list altında listelenir ve eşleşen her URI'ye tek bir fonksiyon hizmet verir.
  • Yer tutucu adları fonksiyonun parametre adlarıyla aynı olmalıdır. Yanlış yaparsanız bunu üretimde değil, içe aktarma sırasında öğrenirsiniz.
  • Fonksiyonunuz kaynak listelendiğinde değil, okunduğunda çalışır.
  • str metin olur, bytes base64 blob olur, geri kalan her şey JSON metni olur. Etiketi mime_type= ile koyarsınız.
  • Araçlar modelin eyleme geçmesi içindir. Kaynaklar uygulamanın okuması içindir.

Üçüncü temel yapı taşı, yani bir kişinin menüden seçtiği, Prompt'lar.