Agents SDK+MCP智能体开发

2025年3月27号,Agents SDK正式官宣支持MCP使用,这也使得Agents SDK的实际应用场景得到拓展。

现在,我们仅需在创建Agent的时候,将MCP服务器视作为一项工具,即可顺利调用MCP服务器进行Agent开发。换而言之,就是如果使用Agents SDK作为Agent开发框架,则可以零门槛快速接入MCP海量服务器生态。

一、Agents SDK + MCP基础调用流程(单个MCP服务 + stdio模式)

我们接下来使用高德天气查询API开发一个MCP服务,并将其作为工具在Agents中调用。

环境准备

需先安装如下依赖

  • pip install openai-agents
  • pip install mcp
  • pip install httpx
  • pip install python-dotenv

开发高德天气查询MCP server端

新建weather_server.py文件代码如下,

python 复制代码
#weather_server.py
import json
import httpx
from typing import Any
from mcp.server.fastmcp import FastMCP
from dotenv import load_dotenv
import os

# 从 .env 文件加载环境变量
load_dotenv()

# 初始化 MCP 服务器
mcp = FastMCP("WeatherServer")

async def fetch_weather(city: str) -> dict[str, Any] | None:
    """
    从 高德天气查询API 获取天气信息。
    :param city: 城市编码(城市adcode,如 110101)
    :return: 天气数据字典;若出错返回包含 error 信息的字典
    """

    #高德天气查询 API 配置
    BASE_URL = "https://restapi.amap.com/v3/weather/weatherInfo"
    API_KEY = os.getenv('AMAP_API_KEY')  # 获取环境变量中的高德API Key,也可直接替换成自己的高德API Key
    
    params = {
        "city": city,
        "key": API_KEY,
        "extensions": "base", # base:返回实况天气; all:返回预报天气
        "output": "JSON"
    }

    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(BASE_URL, params=params, timeout=30.0)
            response.raise_for_status()
            return response.json()  # 返回字典类型
        except httpx.HTTPStatusError as e:
            return {"error": f"HTTP 错误: {e.response.status_code}"}
        except Exception as e:
            return {"error": f"请求失败: {str(e)}"}

def format_weather(data: dict[str, Any] | str) -> str:
    """
    将天气数据格式化为易读文本。
    :param data: 天气数据(可以是字典或 JSON 字符串)
    :return: 格式化后的天气信息字符串
    """
    # 如果传入的是字符串,则先转换为字典
    if isinstance(data, str):
        try:
            data = json.loads(data)
        except Exception as e:
            return f"无法解析天气数据: {e}"

    # 如果数据中包含错误信息,直接返回错误提示
    if "error" in data:
        return f"⚠️ {data['error']}"

    # 列表可能为空,因此用 [0] 前先提供默认字典
    lives_list = data.get("lives", [{}])
    live_data = lives_list[0]
    
    # 提取数据时做容错处理
    province = live_data.get("province", "未知")
    city = live_data.get("city", "未知")
    weather = live_data.get("weather", "未知")
    temperature = live_data.get("temperature", "N/A")
    humidity = live_data.get("humidity", "N/A")
    winddirection = live_data.get("winddirection", "未知")
    windpower = live_data.get("windpower", "N/A")

    return (
        f"🌍 {province}, {city}\n"
        f"🌤 天气: {weather}\n"
        f"🌡 温度: {temperature}°C\n"
        f"💧 湿度: {humidity}%\n"
        f"🌬 风速: {winddirection}风, {windpower}级\n"
    )

@mcp.tool()
async def query_weather(city: str) -> str:
    """
    输入指定城市的城市编码(城市adcode,如 110101),返回今日天气查询结果。
    :param city: 城市编码(城市adcode,如 110101)
    :return: 格式化后的天气信息
    """
    data = await fetch_weather(city)
    return format_weather(data)

if __name__ == "__main__":
    # 以标准 I/O 方式运行 MCP 服务器
    mcp.run(transport='stdio')

使用Agents SDK创建Agents并与MCP服务通信。

在新版的Agents SDK中,Agents SDK可以将某个对应的Agent封装为client,并外部定义好的server进行通信。

新建run_agent_weather.py文件,代码如下:

python 复制代码
# ------------------------------
#     查询天气单MCP工具Agent
# ------------------------------
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel, Agent, Runner, set_default_openai_client
from agents.mcp import MCPServerStdio, MCPServerStdioParams
import asyncio
import os
import logging
# pip install python-dotenv
from dotenv import load_dotenv
import os

# 从 .env 文件加载环境变量
load_dotenv()

# 完全禁用所有日志
logging.getLogger().setLevel(logging.CRITICAL)

# 自定义模型对象
external_client = AsyncOpenAI(
    base_url="https://api.deepseek.com",
    api_key=os.getenv('DEEPSEEK_API_KEY'), 
)
# 设置默认模型
set_default_openai_client(external_client)

# 创建模型对象
deepseek_model = OpenAIChatCompletionsModel(
    openai_client=external_client,
    model="deepseek-chat"
)

# 定义mcp连接和agent调用函数
async def run_with_mcp_detailed():
    """详细调试 MCP 连接过程"""
    try:
        print("步骤1: 创建 MCP Server的连接参数...")
        stdio_params = MCPServerStdioParams(
            command="python",
            #mcp server对应的文件路径
            args=["weather_server.py"]
        )
        print("✓ 参数创建成功")
        
        print("步骤2: 创建 MCP Server 实例对象...")
        mcp_server = MCPServerStdio(
            #mcp server的自定义名称(叫啥都行)
            name="Weather Server",
            params=stdio_params,
            cache_tools_list=True
        )
        print("✓ MCPServerStdio 实例创建成功")
        
        print("步骤3: 连接mcp server...")
        async with mcp_server as server:
            print("✓ MCP 服务器连接成功")
            
            print("步骤4: 创建 Agent...")
            agent = Agent(
                name="Assistant",
                instructions="你是一名助人为乐的助手,可以使用天气查询工具帮助用户查询天气。请使用get_weather工具来查询天气信息。请根据用户想要查询的地区选择最合适的城市编码,无需要用户二次确认",
                mcp_servers=[server], #指定给当前agent绑定的mcp server(外部工具)
                model=deepseek_model
            )
            print("✓ Agent 创建成功")

            print("步骤5: 运行agent...")
            message = "请帮我查询上海今天天气如何?"
            print(f"用户提问: {message}")
            result = await Runner.run(starting_agent=agent, input=message)
            print(f"助手回复: {result.final_output}")
            
    except Exception as e:
        print(f"❌ 错误发生在: {e}")
        import traceback
        traceback.print_exc()

# 运行
if __name__ == "__main__":
    # 运行主程序
    asyncio.run(run_with_mcp_detailed())

执行天气查询 Agent

在cmd中执行命令python run_agent_weather.py,效果如下:

二、Agents SDK 接入多个MCP服务器

理论上,一个MCP服务器能同时运行多个外部函数,而一个MCP Client则可以连接多个MCP服务器。

如何将Agents SDK同时接入多个MCP服务器?

这里我们写一个同时可"查询天气"并把"内容写入本地"的多MCP服务的Agents。 "天气查询"MCP服务还使用上面的代码,这里新写一个"内容写入本地"的伪代码示例MCP服务。

新建write_server.py文件,代码如下:

python 复制代码
import json
import httpx
from typing import Any
from mcp.server.fastmcp import FastMCP

# 初始化 MCP 服务器
mcp = FastMCP("WriteServer")
USER_AGENT = "write-app/1.0"

@mcp.tool()
async def write_file(content: str) -> str:
    """
    将指定内容写入本地文件。
    :param content: 必要参数,字符串类型,用于表示需要写入文档的具体内容。
    :return:是否成功写入
    """
    # 实现一个伪写文件方法
    return "已成功写入本地文件。"

if __name__ == "__main__":
    # 以标准 I/O 方式运行 MCP 服务器
    mcp.run(transport='stdio')

使用Agents SDK创建Agents并连接多个MCP服务。

新建run_agent_multiTool.py文件,代码如下:

python 复制代码
# --------------------------------
#  查询天气并写入信息多MCP工具Agent
# --------------------------------
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel, Agent, Runner, set_default_openai_client
from agents.mcp import MCPServerStdio, MCPServerStdioParams
import asyncio
import os
import logging
# pip install python-dotenv
from dotenv import load_dotenv
import os

# 从 .env 文件加载环境变量
load_dotenv()

# 完全禁用所有日志
logging.getLogger().setLevel(logging.CRITICAL)

# 自定义模型对象
external_client = AsyncOpenAI(
    base_url="https://api.deepseek.com",
    api_key=os.getenv('DEEPSEEK_API_KEY'), 
)

# 设置默认模型
set_default_openai_client(external_client)

# 创建模型对象
deepseek_model = OpenAIChatCompletionsModel(
    openai_client=external_client,
    model="deepseek-chat"
)

# 定义mcp连接和agent调用函数
async def run_with_mcp_detailed():
    """详细调试 MCP 连接过程"""
    try:
        print("步骤1: 创建 MCP服务器参数...")
         # 创建天气服务器参数
        weather_params = MCPServerStdioParams(
            command="python",
            args=["weather_server_amap.py"]
        )
        # 创建写作服务器参数
        write_params = MCPServerStdioParams(
            command="python", 
            args=["write_server.py"]
        )
        print("✓ 参数创建成功")
        
        print("步骤2: 创建 MCP服务器实例...")
        weather_server = MCPServerStdio(
            params=weather_params,
            name="Weather Server",
            cache_tools_list=True
        )
        write_server = MCPServerStdio(
            params=write_params,
            name="Write Server", 
            cache_tools_list=True
        )
        print("✓ MCPServerStdio 实例创建成功")
        
        print("步骤3: 同时连接两个 MCP 服务器...")
        async with weather_server as ws, write_server as wrs:
            print("✓ 两个 MCP 服务器连接成功")
            
            print("步骤4: 创建 Agent(集成两个服务器的工具)...")
            agent = Agent(
                name="MultiTool Assistant",
                instructions="""你是一个多功能助手,可以同时使用天气查询和本地文档写入的能力。
你可以使用的工具包括:
1. 天气查询工具 - 查询全球城市的天气信息
2. 本地文档写入 - 帮助用户将相关数据写入本地文档进行保存
请根据用户的需求智能选择合适的工具:
- 当用户询问天气时,使用天气查询工具
- 当用户需要写入数据保存时,使用本地文档写入工具
- 如果用户的需求涉及多个方面,可以组合使用多个工具
- 如果不知道使用哪个工具,可以询问用户澄清""",
                mcp_servers=[ws, wrs],  # 传入两个服务器
                model=deepseek_model
            )
            print("✓ Agent 创建成功")

            print("步骤5: 运行查询...")
            message = "请帮我查询上海天气,并写入本地文档。"
            print(f"用户提问: {message}")
            result = await Runner.run(starting_agent=agent, input=message)
            print(f"助手回复: {result.final_output}")
            
    except Exception as e:
        print(f"❌ 错误发生在: {e}")
        import traceback
        traceback.print_exc()

# 运行
if __name__ == "__main__":
    # 运行主程序
    asyncio.run(run_with_mcp_detailed())

执行多MCP Agents

在cmd中执行命令python run_agent_multiTool.py,效果如下:

三、Agents SDK + MCP基础调用流程(单个MCP服务 + SSE模式)

以12306的MCP 服务器应用为例:新建文件run_agent_sse_12306.py,代码如下:

python 复制代码
from openai import AsyncOpenAI
from agents import OpenAIChatCompletionsModel, Agent, Runner, set_default_openai_client
import asyncio
import os
import logging
from agents.mcp import MCPServerSse
# pip install python-dotenv
from dotenv import load_dotenv
import os

# 从 .env 文件加载环境变量
load_dotenv()

# 完全禁用所有日志
logging.getLogger().setLevel(logging.CRITICAL)

# 自定义模型对象
external_client = AsyncOpenAI(
    base_url="https://api.deepseek.com",
    api_key=os.getenv('DEEPSEEK_API_KEY'), 
)
# 设置默认模型
set_default_openai_client(external_client)

# 创建模型对象
deepseek_model = OpenAIChatCompletionsModel(
    model="deepseek-chat",
    openai_client=external_client
)

# 定义mcp连接和agent调用函数
async def run_with_sse():
    """使用 SSE 传输方式"""
    try:#创建sse模式下的mcp server对象
        async with MCPServerSse(
            name="Train Server",
            params={
                #url就是mcp server配置信息中的链接地址。可从魔塔社区获取。
                "url": "https://mcp.api-inference.modelscope.net/ad61d61d2e7847/sse"
            }
        ) as server:
            
            agent = Agent(
                name="Assistant",
                instructions="你是一名车票查询的助手",
                mcp_servers=[server],
                model=deepseek_model
            )

            message = "帮我查询今天下午北京到上海的高铁余票信息"
            print(f"用户提问: {message}")
            result = await Runner.run(starting_agent=agent, input=message)
            print(f"助手回复: {result.final_output}")
            
    except Exception as e:
        print(f"SSE 错误: {e}")

# 运行
if __name__ == "__main__":
    # 运行主程序
    asyncio.run(run_with_sse())

在cmd中执行命令python run_agent_sse_12306.py,效果如下:

相关推荐
大模型真好玩17 小时前
LangGraph智能体开发设计模式(四)——LangGraph多智能体设计模式:网络架构
人工智能·langchain·agent
明月(Alioo)17 小时前
AIGC入门,在Mac上基于Ollama和phi3:mini的完整Agent/Subagent例子
机器学习·aigc·agent·subagent
视觉&物联智能19 小时前
【杂谈】-多智能体系统的效能悖论:协作优势的认知边界
ai·llm·agent·智能体·人工 智能
爱吃泡芙的小白白21 小时前
Agent学习——反思模式
学习·agent·学习记录
沈询-阿里1 天前
Skills vs MCP:竞合关系还是互补?深入解析Function Calling、MCP和Skills的本质差异
人工智能·ai·agent·ai编程
酩酊仙人1 天前
fastmcp构建mcp server和client
python·ai·mcp
且去填词1 天前
DeepSeek API 深度解析:从流式输出、Function Calling 到构建拥有“手脚”的 AI 应用
人工智能·python·语言模型·llm·agent·deepseek
EdisonZhou1 天前
MAF快速入门(11)并行工作流
llm·aigc·agent·.net core
职业码农NO.12 天前
AI 技术栈完整解析,从 GPU 到应用的五层架构
人工智能·架构·系统架构·aigc·agent
沛沛老爹2 天前
Skills高级设计模式(一):向导式工作流与模板生成
java·人工智能·设计模式·prompt·aigc·agent·web转型