专栏名称: 阿里云开发者
阿里巴巴官方技术号,关于阿里的技术创新均将呈现于此
目录
相关文章推荐
白鲸出海  ·  日投两千AI素材,点点互动《Kingshot ... ·  2 小时前  
白鲸出海  ·  半年冲刺500万美元ARR,华裔00后打造永 ... ·  2 小时前  
腾讯  ·  腾讯应用宝,冲出手机屏幕 ·  3 天前  
51好读  ›  专栏  ›  阿里云开发者

面向多工具任务调度的两种路径:MCP vs Agent + Function call

阿里云开发者  · 公众号  · 科技公司  · 2025-06-04 08:30

正文

请到「今天看啥」查看全文


( '请输入:' ), # 提问示例:"现在几点了?""一个小时后几点""北京天气如何?" "role" : "user" } ] print ( "-" * 60 ) # 模型的第一轮调用 i = 1 first_response = get_response(messages) assistant_output = first_response[ 'choices' ][ 0 ][ 'message' ] print ( f"\n第 {i} 轮大模型输出信息: {first_response} \n" ) if assistant_output[ 'content' ] is None : assistant_output[ 'content' ] = "" messages.append(assistant_output) # 如果不需要调用工具,则直接返回最终答案 if assistant_output[ 'tool_calls' ] == None : # 如果模型判断无需调用工具,则将assistant的回复直接打印出来,无需进行模型的第二轮调用 print ( f"无需调用工具,我可以直接回复: {assistant_output[ 'content' ]} " ) return # 如果需要调用工具,则进行模型的多轮调用,直到模型判断无需调用工具 while assistant_output[ 'tool_calls' ] != None : # 如果判断需要调用查询天气工具,则运行查询天气工具 if assistant_output[ 'tool_calls' ][ 0 ][ 'function' ][ 'name' ] == 'get_current_weather' : tool_info = { "name" : "get_current_weather" , "role" : "tool" } # 提取位置参数信息 location = json.loads(assistant_output[ 'tool_calls' ][ 0 ][ 'function' ][ 'arguments' ])[ 'location' ] tool_info[ 'content' ] = get_current_weather(location) # 如果判断需要调用查询时间工具,则运行查询时间工具 elif assistant_output[ 'tool_calls' ][ 0 ][ 'function' ][ 'name' ] == 'get_current_time' : tool_info = { "name" : "get_current_time" , "role" : "tool" } tool_info[ 'content' ] = get_current_time() print ( f"工具输出信息: {tool_info[ 'content' ]} \n" ) print ( "-" * 60 ) messages.append(tool_info) assistant_output = get_response(messages)[ 'choices' ][ 0 ][ 'message' ] if assistant_output[ 'content' ] is None : assistant_output[ 'content' ] = "" messages.append(assistant_output) i += 1 print ( f"第 {i} 轮大模型输出信息: {assistant_output} \n" ) print ( f"最终答案: {assistant_output[ 'content' ]} " )

注意:需要注意的是这里的大模型判断的时候可能会识别到需要多个tools,所以才会需要用到循环,这个也是通过这个进行MCP的Client编写。

2.3 对比

从结构、扩展性、性能、可维护性等角度对 Agent + Function Call 与 MCP 进行对比。

2.3.1 结构对比

在结构设计方面,Agent + Function Call 通常采用单体式模式,即大语言模型直接在推理过程中,基于预定义的 tool list,动态判断并调用外部函数。这种方式强调轻量、快速,如 OpenAI 在其 Function Calling 文档中所述,模型在每轮对话中,可以基于工具描述(如 name、description 和 parameters)直接生成调用请求[2]。而 MCP 则采用了严格的 Client-Server 架构,将工具管理、数据上下文提供与模型推理解耦开来。根据 MCP 官方介绍,Host(如 LLM 应用)通过 Client 与 Server 建立连接,Server 统一管理各种工具、数据源和提示词资源[1]。结构上,MCP 更加标准化和模块化,天然适配大型系统的分布式部署与演进需求[6]。

2.3.2 扩展性对比

扩展性是衡量智能体系统可持续发展的重要指标。Agent + Function Call 由于本地 tightly-coupled(紧耦合)工具列表的特性,每增加或修改一个工具,都需同步更新模型侧的工具定义,维护成本较高。不同模型平台(如 OpenAI、Anthropic、通义千问)在 Function Call 支持的格式上也存在差异,跨模型迁移时需要额外适配[7]。相比之下,MCP 在设计上强调工具与模型的解耦。Server 端可独立发布、更新、下线工具,不需要重新训练或重启模型推理链路。MCP 也支持多种数据源(本地文件、数据库、远程 API 等)统一接入[2],极大提升了系统的扩展灵活性和多源融合能力。 这种松耦合设计被认为是未来智能系统发展的必然趋势,并有助于通过统一的访问控制和最小化授权来降低安全风险[8]。

2.3.3 性能对比

在性能方面,Agent + Function Call 因调用链条短(模型直接调用本地或小范围工具函数),在单次任务响应延迟上具有明显优势。特别是在低并发、轻量任务场景下,如简单的天气查询、汇率换算,能够提供极快的响应体验[2][3]。然而,随着任务复杂度提升,特别是涉及多轮调用、复杂工作流编排时,Agent 本地调度可能出现瓶颈。而 MCP 架构虽然引入了 Client-Server 的通信开销,但其 Server 可通过分布式部署、异步处理、负载均衡等手段优化整体性能表现[1]。相关研究也指出,在复杂任务密集型场景下,微服务式架构(如 MCP)在系统稳定性和高可用性方面优于单体式设计[9]。

2.3.4 可维护性对比

系统可维护性直接关系到长周期系统演进与运营成本。Agent + Function Call 由于将工具描述、调用逻辑与模型 tightly bundled,在实际维护中,若工具数量庞大、版本频繁更新,容易导致接口变更混乱,且缺乏统一的调用日志和监控体系[7]。MCP 在这一点上具有显著优势。根据 MCP 官方文档,Client 和 Server 均能独立记录调用日志,支持细粒度的性能监控、故障排查和审计[1]。此外,MCP Server 层可以独立设置访问权限、安全策略,实现数据与工具访问的最小化授权(principle of least privilege)[8]。在企业级应用环境下,MCP 更易满足合规性、审计与安全隔离要求。

三、实践

针对搬栈 AI 化的业务需求,分别基于 MCP 协议和 Agent + Function Call 两种方式进行了实践探索与效果验证,旨在评估不同方案在多轮任务调度场景下的适配性与应用优势。

3.1 MCP 实践

本节介绍 MCP(Model Context Protocol)在实际项目中的应用方式与配置过程。

针对搬栈 AI 化的业务需求,进行了 MCP 场景的实施探索。整体采用本地部署方式,严格遵循官方文档指引,并结合实际环境进行了适配与改写,实现了完整的 MCP 接入链路。

通过实践可以明确,基于 MCP 协议的系统搭建主要包含两个关键组成部分:

  • Client 作为 LLM 应用(如智能体或 IDE 插件)的一部分,负责发起与 Server 的连接、发送上下文请求以及接收工具调用结果。

  • Server 作为独立服务存在,统一管理工具资源(如 API 接口、数据库服务、本地文件系统等),并按需提供给 Client 调用。

基于通义模型,具体搭建流程如下:

1.搭建 Client

Client 侧基于标准的 MCP 客户端框架(例如调用 DashScope 等服务),配置 LLM 模型、连接 Server,并在推理过程中实现工具调度与调用链路闭环。

client部分代码--大模型选择tools

client = OpenAI(            # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",            api_key=os.getenv("DASHSCOPE_API_KEY"),            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",        )
        completion = client.chat.completions.create(            # 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models            model="qwen-plus",            messages=messages,            tools=self.tools,        )
        response = completion.model_dump_json()
        print(response)        assistant_output = json.loads(response)['choices'][0]['message']        print(f"assistant_output{assistant_output}")

client部分代码--大模型确定tools后的调用模型


        if assistant_output['content']:            final_text.append(assistant_output['content'])        while assistant_output['tool_calls'] != None:            print(f"tool_name{assistant_output['tool_calls']}")            tool_name = assistant_output['tool_calls'][0]['function']['name']            tool_args = assistant_output['tool_calls'][0]['function']['arguments']            tool_args = json.loads(tool_args)
            # Execute tool call            tool_result = await self.session.call_tool(tool_name, tool_args)            #print(tool_result.content[0].text)            #tool_results.append({"call": tool_name, "result": result})            final_text.append(                f"[Calling tool {tool_name} with args {tool_args}]")                            messages.append({                "role""assistant",                "content": assistant_output['content'],                "tool_calls": assistant_output['tool_calls'            })            

client部分代码--大模型把query+tools信息+大模型回复整合后进行再输出

# Continue conversation with tool results            prompt = "不需要改变原结构,输出原来的结构,除了产品信息,前后都要用中文"            messages.append({                "role""tool",                "content": tool_result.content[0].text,                "tool_call_id": completion.choices[0].message.tool_calls[0].id,                "prompt":prompt            })
            completion = client.chat.completions.create(                model="qwen-plus",                messages=messages            )            assistant_output = completion.model_dump()['choices'][0]['message']            if  assistant_output['content'is None:                assistant_output['content'] = ""            messages.append(assistant_output)            final_text.append(completion.choices[0].message.content)

2.搭建 Server

Server 侧需实现符合 MCP 规范的服务端逻辑,注册可供调用的工具资源。每个工具以标准的 function schema 方式对外暴露,支持参数定义、调用路径和返回格式规范化管理。

tool举例--查询阿里云某个产品对应模块信息

@mcp.tool()async def descirbe_pricing_modules(owner_id: int = None,                        product_code: str = None,                        product_type: str = None,                        subscription_type: str = None,) -> str:    """查询阿里云某个产品对应模块信息(DescribePricingModule),product_code 和 subscription_type订阅类型是必选项。"""    await ensure_connected()
    def sync_call():        req = bss_models.DescribePricingModuleRequest(            product_code=product_code,            product_type=product_type,            subscription_type=subscription_type        )        runtime = util_models.RuntimeOptions()        return client.describe_pricing_module_with_options(req, runtime)






请到「今天看啥」查看全文