.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorial/task_mcp.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorial_task_mcp.py: .. _mcp: MCP ========================= 本章将介绍 AgentScope 对 MCP(Model Context Protocol)的以下支持: - 支持 **HTTP** (StreamableHTTP 和 SSE)和 **StdIO** 类型的 MCP 服务器 - 提供 **有状态** 和 **无状态** 两种 MCP 客户端 - 提供 **MCP 级别** 和 **函数级别** 的 MCP 工具管理 这里的有状态/无状态是指客户端是否会维持与 MCP 服务器的会话(session)。 无状态客户端只会在调用工具发生时建立会话,并在工具调用结束后立即销毁会话,是一种轻量化的使用方式。 下表总结了支持的 MCP 客户端类型和协议: .. list-table:: 支持的 MCP 客户端类型和协议 :header-rows: 1 * - 客户端类型 - HTTP(StreamableHTTP 和 SSE) - StdIO * - 有状态客户端 - ``HttpStatefulClient`` - ``StdIOStatefulClient`` * - 无状态客户端 - ``HttpStatelessClient`` - .. GENERATED FROM PYTHON SOURCE LINES 33-40 .. code-block:: Python import asyncio import json import os from agentscope.mcp import HttpStatefulClient, HttpStatelessClient from agentscope.tool import Toolkit .. GENERATED FROM PYTHON SOURCE LINES 41-61 MCP 客户端 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 在 AgentScope 中,MCP 客户端负责 - 连接到 MCP 服务器, - 从服务器获取工具函数,以及 - 调用 MCP 服务器中的工具函数。 AgentScope 中有两种类型的 MCP 客户端:**有状态** 和 **无状态**。 它们仅在 **如何管理与 MCP 服务器的会话** 方面有所不同。 - 有状态客户端:有状态 MCP 客户端在其生命周期内 **维持与 MCP 服务器的持久会话**。开发者应显式调用 ``connect()`` 和 ``close()`` 方法来管理会话的生命周期。 - 无状态客户端:无状态 MCP 客户端在调用工具函数时创建新会话,在工具函数调用完成后立即销毁会话,更加轻量化。 .. note:: - StdIO MCP 服务器只有有状态客户端,当调用 ``connect()`` 时,它将在本地启动 MCP 服务器然后连接到它。 - 对于有状态客户端,开发者必须确保在调用工具函数时客户端已连接。 以高德地图 MCP 服务器为例,有状态和无状态客户端的创建非常相似: .. GENERATED FROM PYTHON SOURCE LINES 61-76 .. code-block:: Python stateful_client = HttpStatefulClient( # 用于标识 MCP 的名称 name="mcp_services_stateful", transport="streamable_http", url=f"https://mcp.amap.com/mcp?key={os.environ['GAODE_API_KEY']}", ) stateless_client = HttpStatelessClient( # 用于标识 MCP 的名称 name="mcp_services_stateless", transport="streamable_http", url=f"https://mcp.amap.com/mcp?key={os.environ['GAODE_API_KEY']}", ) .. GENERATED FROM PYTHON SOURCE LINES 77-99 有状态和无状态客户端都提供以下方法: .. list-table:: MCP 客户端方法 :header-rows: 1 * - 方法 - 描述 * - ``list_tools`` - 列出 MCP 服务器中所有可用的工具。 * - ``get_callable_function`` - 通过名称从 MCP 服务器获取可调用的函数对象。 MCP 作为工具 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AgentScope 提供了对 MCP 工具的细粒度管理,包括 MCP 级别和函数级别的管理。 MCP 级别管理 -------------------------------- 您可以将 MCP 服务器的所有工具一次性注册到 ``Toolkit`` 中,如下所示。 .. tip:: 可选地,开发者可以通过指定组名来管理工具。有关分组工具管理,请参考 :ref:`tool` 部分。 .. GENERATED FROM PYTHON SOURCE LINES 99-130 .. code-block:: Python toolkit = Toolkit() async def example_register_stateless_mcp() -> None: """注册无状态客户端 MCP 工具的示例。""" # 从 MCP 服务器注册所有工具 await toolkit.register_mcp_client( stateless_client, # group_name="map_services", # 可选的组名 ) print("注册的 MCP 工具总数:", len(toolkit.get_json_schemas())) maps_geo = next( tool for tool in toolkit.get_json_schemas() if tool["function"]["name"] == "maps_geo" ) print("\n示例 ``maps_geo`` 函数:") print( json.dumps( maps_geo, indent=4, ensure_ascii=False, ), ) asyncio.run(example_register_stateless_mcp()) .. rst-class:: sphx-glr-script-out .. code-block:: none 注册的 MCP 工具总数: 15 示例 ``maps_geo`` 函数: { "type": "function", "function": { "name": "maps_geo", "description": "将详细的结构化地址转换为经纬度坐标。支持对地标性名胜景区、建筑物名称解析为经纬度坐标", "parameters": { "type": "object", "properties": { "address": { "type": "string", "description": "待解析的结构化地址信息" }, "city": { "type": "string", "description": "指定查询的城市" } }, "required": [ "address" ] } } } .. GENERATED FROM PYTHON SOURCE LINES 131-133 要移除已注册的工具,可以使用 ``remove_tool_function`` 函数,或使用 ``remove_mcp_clients`` 移除特定 MCP 的所有工具。 .. GENERATED FROM PYTHON SOURCE LINES 133-150 .. code-block:: Python async def example_remove_mcp_tools() -> None: """移除 MCP 工具的示例。""" print("移除前的工具总数:", len(toolkit.get_json_schemas())) # 通过名称移除特定的工具函数 toolkit.remove_tool_function("maps_geo") print("工具数量:", len(toolkit.get_json_schemas())) # 通过名称移除 MCP 客户端的所有工具 await toolkit.remove_mcp_clients(client_names=["mcp_services_stateless"]) print("工具数量:", len(toolkit.get_json_schemas())) asyncio.run(example_remove_mcp_tools()) .. rst-class:: sphx-glr-script-out .. code-block:: none 移除前的工具总数: 15 工具数量: 14 工具数量: 0 .. GENERATED FROM PYTHON SOURCE LINES 151-165 函数级别管理 -------------------------------- 注意到开发者有对 MCP 工具进行更细粒度控制的需求,例如对工具结果进行后处理,或使用它们创建更复杂的工具函数。 因此,AgentScope 支持通过工具名从 MCP 客户端获取可调用的函数对象,这样开发者可以 - 直接调用它, - 将其包装到自己的函数中,或以任何其它方式进行使用。 此外,开发者可以指定是否将工具函数执行结果包装成 ``ToolResponse`` 对象,以便与 ``Toolkit`` 无缝使用。 如果设置 ``wrap_tool_result=False``,将返回原始结果类型 ``mcp.types.CallToolResult``。 以 ``maps_geo`` 函数为例,可以将其获取为可调用的函数对象,如下所示: .. GENERATED FROM PYTHON SOURCE LINES 165-194 .. code-block:: Python async def example_function_level_usage() -> None: """使用函数级别 MCP 工具的示例。""" func_obj = await stateless_client.get_callable_function( func_name="maps_geo", # 是否将工具结果包装到 AgentScope 的 ToolResponse 中 wrap_tool_result=True, ) # 您可以获取其名称、描述和 JSON schema print("函数名称:", func_obj.name) print("函数描述:", func_obj.description) print( "函数 JSON schema:", json.dumps(func_obj.json_schema, indent=4, ensure_ascii=False), ) # 直接调用函数对象 res = await func_obj( address="天安门广场", city="北京", ) print("\n函数调用结果:") print(res) asyncio.run(example_function_level_usage()) .. rst-class:: sphx-glr-script-out .. code-block:: none 函数名称: maps_geo 函数描述: 将详细的结构化地址转换为经纬度坐标。支持对地标性名胜景区、建筑物名称解析为经纬度坐标 函数 JSON schema: { "type": "function", "function": { "name": "maps_geo", "description": "将详细的结构化地址转换为经纬度坐标。支持对地标性名胜景区、建筑物名称解析为经纬度坐标", "parameters": { "type": "object", "properties": { "address": { "type": "string", "description": "待解析的结构化地址信息" }, "city": { "type": "string", "description": "指定查询的城市" } }, "required": [ "address" ] } } } 函数调用结果: ToolResponse(content=[{'type': 'text', 'text': '{"results":[{"country":"中国","province":"北京市","city":"北京市","citycode":"010","district":"东城区","street":[],"number":[],"adcode":"110101","location":"116.397755,39.903179","level":"兴趣点"}]}'}], metadata=None, stream=False, is_last=True, is_interrupted=False, id='2025-08-27 03:47:11.631_df039b') .. GENERATED FROM PYTHON SOURCE LINES 195-203 进一步阅读 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 有关更多详细信息,请参见: - :ref:`tool` - :ref:`agent` .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 8.815 seconds) .. _sphx_glr_download_tutorial_task_mcp.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: task_mcp.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: task_mcp.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: task_mcp.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_