Ana içeriğe geç

Oturum grupları

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 Client tek bir sunucuya bağlanır. Gerçek uygulamalar ise çoğu zaman birden fazlasını ister (bir arama sunucusu, bir veritabanı sunucusu, dahili bir API) ve her biri için ayrı bir bağlantı ile ayrı bir araç listesiyle uğraşmak zorunda kalır.

ClientSessionGroup, birçok bağlantıyı tutan ve bunların sunduğu her şeyi tek bir görünümde birleştiren tek bir nesnedir.

İki sunucu

İki sıradan sunucuyla başlayın. Birbirleriyle hiçbir ilgileri yok, bu yüzden ikisi de doğal olarak aracına search adını vermiş:

library_server.py
from mcp.server import MCPServer

mcp = MCPServer("Library")


@mcp.tool()
def search(query: str) -> str:
    """Search the library catalog."""
    return f"3 books match {query!r}."


@mcp.resource("library://hours")
def hours() -> str:
    """When the library is open."""
    return "Mon-Fri 09:00-17:00"
web_server.py
from mcp.server import MCPServer

mcp = MCPServer("Web")


@mcp.tool()
def search(query: str) -> str:
    """Search the web."""
    return f"12 pages match {query!r}."

Tek grup

Bir ClientSessionGroup oluşturun ve her sunucu için bir kez connect_to_server'ı çağırın:

client.py
import asyncio

from mcp import ClientSessionGroup, StdioServerParameters


async def main() -> None:
    library = StdioServerParameters(command="uv", args=["run", "mcp", "run", "library_server.py"])
    web = StdioServerParameters(command="uv", args=["run", "mcp", "run", "web_server.py"])

    async with ClientSessionGroup() as group:
        await group.connect_to_server(library)
        await group.connect_to_server(web)

        result = await group.call_tool("search", {"query": "model context protocol"})
        print(result.structured_content)


if __name__ == "__main__":
    asyncio.run(main())
  • connect_to_server bir sunucu nesnesi değil, aktarım parametreleri alır: bir alt süreç başlatmak için StdioServerParameters (mcp'den) ya da zaten bir URL'de dinleyen bir sunucu için StreamableHttpParameters / SseServerParameters (mcp.client.session_group'tan).
  • group.tools, bağlı tüm sunucuların araçlarını içeren bir dict[str, Tool]'dur. group.resources ve group.prompts da aynı biçimdedir.
  • group.call_tool(name, arguments) adı arar, ona sahip olan oturumu bulur ve çağrıyı iletir. Hangi sunucu olduğunu hiçbir zaman söylemezsiniz.

Check

client.py dosyasını iki sunucunun yanına koyun ve çalıştırın. İkinci connect_to_server reddeder:

mcp.shared.exceptions.MCPError: {'search'} already exist in group tools.

Bu, ikinci sunucudan herhangi bir şey kaydedilmeden önce fırlatılan bir MCPError'dır. Bir ad grubun tamamında benzersiz olmalıdır ve sizin denetiminizde olmayan iki sunucu eninde sonunda çakışır.

component_name_hook

Bunu sunucularda değil, grupta düzeltirsiniz. (name, server_info) alan bir fonksiyon geçirin; grup, kaydettiği her ad üzerinde onu çalıştırır:

client.py
import asyncio

from mcp import ClientSessionGroup, StdioServerParameters
from mcp.types import Implementation


def by_server(name: str, server_info: Implementation) -> str:
    return f"{server_info.name}.{name}"


async def main() -> None:
    library = StdioServerParameters(command="uv", args=["run", "mcp", "run", "library_server.py"])
    web = StdioServerParameters(command="uv", args=["run", "mcp", "run", "web_server.py"])

    async with ClientSessionGroup(component_name_hook=by_server) as group:
        await group.connect_to_server(library)
        await group.connect_to_server(web)

        print(sorted(group.tools))
        result = await group.call_tool("Web.search", {"query": "model context protocol"})
        print(result.structured_content)


if __name__ == "__main__":
    asyncio.run(main())

Yeniden çalıştırın. print(sorted(group.tools)) artık ikisini de gösterir:

['Library.search', 'Web.search']
  • Anahtar sizindir. by_server onu server_info.name'den, yani her MCPServer(...)'ın oluşturulduğu addan üretti.
  • İçindeki Tool'a dokunulmaz: group.tools["Web.search"].name hâlâ "search"'tür ve call_tool'un ağ üzerinde gönderdiği ad budur. Önek hiçbir zaman sürecinizin dışına çıkmaz.
  • Bu yalnızca araçlarla sınırlı değil. Kütüphanenin hours kaynağı Library.hours olarak kaydedilir.

Tip

Kanca yalnızca çakışmalarda değil, her sunucudan gelen her ad üzerinde çalışır: yalnızca çakışmada önek ekleyen bir kip yoktur. Bir şema seçin ve her yerde uygulanmasına izin verin.

Sunucu ekleme ve kaldırma

connect_to_server, açtığı ClientSession'ı döndürür. O sunucuyu bir gün kaldırmak isterseniz bunu saklayın: await group.disconnect_from_server(session) sunucunun araçlarını, kaynaklarını ve prompt'larını gruptan kaldırır.

Elinizde zaten bağlı bir ClientSession varsa (Client.session bunlardan biridir), yeni bir aktarım açmak yerine onu await group.connect_with_session(server_info, session)'a verin. Aynı şekilde birleştirilir. Grup, kendisinin açmadığı bir oturumu hiçbir zaman kapatmaz. server_info, bileşen önekleri için sunucuya ad verir; 2026 neslinden bir bağlantıda client.server_info None olabilir (kimlik isteğe bağlıdır), bu durumda kendi Implementation(name=..., version=...)'ınızı geçirin.

Klasik el sıkışma

ClientSessionGroup, Client üzerine değil ClientSession üzerine kuruludur. Her connect_to_server klasik initialize el sıkışmasını yürütür. Protokol sürümleri sayfasında anlatılan server/discover yoklamasını hiçbir zaman göndermez. Her MCP sunucusu bu el sıkışmayı anlar; bu yüzden uyumluluk açısından hiçbir şey kaybetmezsiniz. Bunun tek anlamı, grubun daha iyisini yapabilecek bir sunucuya giderken daha eski ve daha yavaş yolu izlemesidir.

Özet

  • ClientSessionGroup birçok sunucu bağlantısını tutar ve bunların araçlarını, kaynaklarını ve prompt'larını birer dict'te birleştirir.
  • Her sunucu için connect_to_server(params). Aktarım parametreleri alır; bir Client'ın aldığı sunucu nesnesini ya da URL'yi asla almaz.
  • group.call_tool(name, arguments) çağrıyı sizin yerinize sahibi olan sunucuya yönlendirir.
  • Adlar grubun tamamında benzersiz olmalıdır; search aracı olan iki sunucu kendi hâllerine bırakılırsa bir arada bulunamaz.
  • component_name_hook= kaydedilen her adı yeniden yazar. Sözlük anahtarı değişir, ağ üzerindeki ad değişmez.
  • connect_with_session elinizde zaten olan bir oturumu ekler; disconnect_from_server bir oturumu kaldırır.

Bir grubun konuştuğu el sıkışma (ve bir Client'ın tercih ettiği daha hızlı olanı), Protokol sürümleri sayfasının konusudur.