当前位置: 首页 > news >正文

MCP - 优化 Agent 调用 MCP tools提示词(九)

在这篇 MCP - AI智能体调用 MCP Serverr - Streamable HTTP(七) 文章中,虽然可以实现 MCP tools 的调用,但测试下来效果不好。

例如:有如下tools代码,其中提供 3个tools

  1. search_flights_between_countries: 查询两个国家之间的国际航班信息及票价
  2. search_international_multi_city: 国际机票查询服务
  3. search_domestic_multi_city: 中国(国内)机票查询服务
# -*- coding: utf-8 -*-
"""
航班查询
"""
from base.tool_registry import mcp_tool@mcp_tool()
def search_flights_between_countries(departure_country: str="中国", arrival_country: str="美国", departure_date: str="2026/02/10",max_duration: int=0,max_total_price: int=0,sort_by: list[str]=[],limit: int=0
):"""查询两个国家之间的国际航班信息及票价提供指定日期内从出发国家到目的国家的航班搜索服务,返回包含航班详情、价格、时间等信息的结构化数据。支持全球主要国家和城市的航班查询。Args:departure_country (str): 出发国家名称arrival_country (str): 到达国家名称departure_date (str): 出发日期,格式为 YYYY-MM-DDmax_duration (int): 最大飞行时长,单位:小时,默认值为 24小时max_total_price (int): 机票最大总价格,单位:元,默认值为 5000元sort_by (list[str]): 排序规则字段,默认值为 ['total_price', 'duration'] 默认先按总价格排序,再按持续时间排序limit (int): 返回最优的记录条数,默认为20条Returns:str: 机票查询结果"""msg = f"查询两个国家之间的国际航班信息及票价: {departure_country} -> {arrival_country}, 日期: {departure_date}, 时长小于 {max_duration}小时, 总价小于 {max_total_price}元, 排序规则: {sort_by}, 返回: {limit}条"print(f"{msg}")return f"{msg}"@mcp_tool()
def search_international_multi_city(departure_list: list[str]=["北京"],arrival_list: list[str]=["上海"],departure_date: str="2026/02/10",max_duration: int=0,max_total_price: int=0,sort_by: list[str]=[],limit: int=0
):"""国际机票查询服务提供国内多个出发地到多个目的地的组合航班查询,支持单程多城市航线搜索。适用于复杂的国内旅行规划,如多城市环线旅行或不同出发地的团体订票。Args:departure_list (list[str]): 出发城市列表,例如:["北京", "上海"]arrival_list (list[str]): 目的城市列表,例如:["广州", "深圳"]departure_date (str): 出发日期,格式为 YYYY-MM-DDmax_duration (int): 最大飞行时长,单位:小时,默认值为 24小时max_total_price (int): 机票最大总价格,单位:元,默认值为 5000元sort_by (list[str]): 排序规则字段,默认值为 ['total_price', 'duration'] 默认先按总价格排序,再按持续时间排序limit (int): 返回最优的记录条数,默认为20条Returns:str: 机票查询结果"""msg = f"国际机票查询服务: {departure_list} -> {arrival_list}, 日期: {departure_date}, 时长小于 {max_duration}小时, 总价小于 {max_total_price}元, 排序规则: {sort_by}, 返回: {limit}条"print(f"{msg}")return f"{msg}"@mcp_tool()
def search_domestic_multi_city(departure_list: list[str]=["北京"],arrival_list: list[str]=["上海"],departure_date: str="2026/02/10",max_duration: int=0,max_total_price: int=0,sort_by: list[str]=[],limit: int=0
):"""中国(国内)机票查询服务提供国内多个出发地到多个目的地的组合航班查询,支持单程多城市航线搜索。适用于复杂的国内旅行规划,如多城市环线旅行或不同出发地的团体订票。Args:departure_list (list[str]): 出发城市列表,例如:["北京", "上海"]arrival_list (list[str]): 目的城市列表,例如:["广州", "深圳"]departure_date (str): 出发日期,格式为 YYYY-MM-DDmax_duration (int): 最大飞行时长,单位:小时,默认值为 24小时max_total_price (int): 机票最大总价格,单位:元,默认值为 5000元sort_by (list[str]): 排序规则字段,默认值为 ['total_price', 'duration'] 默认先按总价格排序,再按持续时间排序limit (int): 返回最优的记录条数,默认为20条Returns:str: 机票查询结果"""msg = f"中国(国内)机票查询服务: {departure_list} -> {arrival_list}, 日期: {departure_date}, 时长小于 {max_duration}小时, 总价小于 {max_total_price}元, 排序规则: {sort_by}, 返回: {limit}条"print(f"{msg}")return f"{msg}"

在咱们写的Agent中输入 帮我查找 中国 到 美国的 机票,时间 2025/10/01 ,可以看到大模型返回 tool_calls 是空,也就是不调用 MCP tools。

但在 Cherry Studio 中就能看到它可以调用 MCP tools,这是为什么呢?仔细查看后发现 Cherry Studio 使用的提示词跟咱们写的 Agent 不同。

 

问题分析:

一、MCP tools 调用流程

二、自己写的 Agent 智能体的请求

注意:使用抓包前需要修改 .env 配置文件,例如:

其中,url 根据你的情况修改,但注意需要添加 /v1 否则报 404 错误

API_KEY=
BASE_URL=http://172.31.12.15:11434/v1
MODEL=qwen3:4b

使用抓包工具,抓包整理后得到图中右侧部分。可以看到发送了两个请求:

  1. 发送用户输入内容,和 tools 列表
  2. 发送 tools 调用结果 + 1的响应

2.1 第一个请求

2.2 第二个请求

三、cherry studio 的请求

3.1 处理流式传输

由于 cherry studio 配置的是流式传输,所以一个响应拆到了很多包的 content 字段里,抓包后需要手工合并。如下图:

3.2 第一个请求

3.3 第二个请求

3.4 将第一个请求 "role": "system" 中的 "content" 转为文本

可以看出 cherry 的跟自己实现的 agent 提示词不同。

In this environment you have access to a set of tools you can use to answer the user's question. You can use one or more tools per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.## Tool Use FormattingTool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:<tool_use><name>{tool_name}</name><arguments>{json_arguments}</arguments>
</tool_use>The tool name should be the exact name of the tool you are using, and the arguments should be a JSON object containing the parameters required by that tool. For example:
<tool_use><name>python_interpreter</name><arguments>{\"code\": \"5 + 3 + 1294.678\"}</arguments>
</tool_use>The user will respond with the result of the tool use, which should be formatted as follows:<tool_use_result><name>{tool_name}</name><result>{result}</result>
</tool_use_result>The result should be a string, which can represent a file or any other output type. You can use this result as input for the next action.
For example, if the result of the tool use is an image file, you can use it in the next action like this:<tool_use><name>image_transformer</name><arguments>{\"image\": \"image_1.jpg\"}</arguments>
</tool_use>Always adhere to this format for the tool use to ensure proper parsing and execution.## Tool Use ExamplesHere are a few examples using notional tools:
---
User: Generate an image of the oldest person in this document.Assistant: I can use the document_qa tool to find out who the oldest person is in the document.
<tool_use><name>document_qa</name><arguments>{\"document\": \"document.pdf\", \"question\": \"Who is the oldest person mentioned?\"}</arguments>
</tool_use>User: <tool_use_result><name>document_qa</name><result>John Doe, a 55 year old lumberjack living in Newfoundland.</result>
</tool_use_result>Assistant: I can use the image_generator tool to create a portrait of John Doe.
<tool_use><name>image_generator</name><arguments>{\"prompt\": \"A portrait of John Doe, a 55-year-old man living in Canada.\"}</arguments>
</tool_use>User: <tool_use_result><name>image_generator</name><result>image.png</result>
</tool_use_result>Assistant: the image is generated as image.png---
User: \"What is the result of the following operation: 5 + 3 + 1294.678?\"Assistant: I can use the python_interpreter tool to calculate the result of the operation.
<tool_use><name>python_interpreter</name><arguments>{\"code\": \"5 + 3 + 1294.678\"}</arguments>
</tool_use>User: <tool_use_result><name>python_interpreter</name><result>1302.678</result>
</tool_use_result>Assistant: The result of the operation is 1302.678.---
User: \"Which city has the highest population , Guangzhou or Shanghai?\"Assistant: I can use the search tool to find the population of Guangzhou.
<tool_use><name>search</name><arguments>{\"query\": \"Population Guangzhou\"}</arguments>
</tool_use>User: <tool_use_result><name>search</name><result>Guangzhou has a population of 15 million inhabitants as of 2021.</result>
</tool_use_result>Assistant: I can use the search tool to find the population of Shanghai.
<tool_use><name>search</name><arguments>{\"query\": \"Population Shanghai\"}</arguments>
</tool_use>User: <tool_use_result><name>search</name><result>26 million (2019)</result>
</tool_use_result>
Assistant: The population of Shanghai is 26 million, while Guangzhou has a population of 15 million. Therefore, Shanghai has the highest population.## Tool Use Available Tools
Above example were using notional tools that might not exist for you. You only have access to these tools:
<tools><tool><name>server-add_numbers</name><description>Add two numbers together\n\nArgs:\n    a (int): parameter 1\n    b (int): parameter 2\n\nReturns:\n    The sum of individuals</description><arguments>\n    {\"type\":\"object\",\"properties\":{\"a\":{\"title\":\"A\",\"type\":\"integer\"},\"b\":{\"title\":\"B\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"]}\n  </arguments>
</tool></tools>## Tool Use Rules
Here are the rules you should always follow to solve your task:
1. Always use the right arguments for the tools. Never use variable names as the action arguments, use the value instead.
2. Call a tool only when needed: do not call the search agent if you do not need information, try to solve the task yourself.
3. If no tool call is needed, just answer the question directly.
4. Never re-do a tool call that you previously did with the exact same parameters.
5. For tool use, MARK SURE use XML tag format as shown in the examples above. Do not use any other format.# User InstructionsResponse in user query language.
Now Begin! If you solve the task correctly, you will receive a reward of $1,000,000. 

但 cherry 的提示词也不能直接使用,需要再调整才能改善自己写的 agent 工具调用的效果:

  1. cherry 将 tools 列表放在了content;
  2. cherry 提示词中要求工具调用返回的结构不同,如果使用 cherry 提示词需要修改。

四、使用 cherry 提示词

4.1 代码中添加提示词

将以上 3.4 的提示词添加到代码中,然后将 tools 段替换为以下内容 {available_tools} ,添加后如下图:

4.2 添加 available_tools_xml 并修改 messages

代码如下:

        # 获取工具列表 - XML 格式(用在 系统提示词 中)available_tools_xml = [f"\n  <tool>\n    <name>{tool.name}</name>\n    <description>{tool.description}</description>\n    <arguments>{tool.inputSchema}</arguments>\n  </tool>\n"for tool in self.tools]# 待发给 AI 的消息messages = [{"role": "system", "content": system_prompt.replace("{available_tools}", "".join(available_tools_xml))}, {"role": "user", "content": query}]

diff 如下:

4.3 测试结果

修改前

帮我查询 中国 到 澳大利亚 的机票,时间 2026/2/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_flights_between_countries {'departure_country': '中国', 'arrival_country': '澳大利亚', 'departure_date': '2026-02-10'}]帮我查询 北京 到 上海 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ❌ 没有找到工具,直接回复让我去自己搜索帮我查询 北京 到 纽约 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ❌ 没有找到工具,直接回复让我去自己搜索帮我查询 北京、上海 到 纽约、墨尔本 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ❌ 没有找到工具,直接回复让我去自己搜索帮我查询 北京、上海 到 南京 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_domestic_multi_city with args {'departure_list': ['北京', '上海'], 'arrival_list': ['南京'], 'departure_date': '2025-10-10', 'limit': 20}]

修改 cherry 提示词后:

帮我查询 中国 到 澳大利亚 的机票,时间 2026/2/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_flights_between_countries {'departure_country': '中国', 'arrival_country': '澳大利亚', 'departure_date': '2026-02-10'}]帮我查询 北京 到 上海 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_domestic_multi_city {'departure_list': ['北京'], 'arrival_list': ['上海'], 'departure_date': '2025-10-10', 'limit': 20}]帮我查询 北京 到 纽约 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ❌ 应该调用国际城市查询,但调用国家查询
[Calling tool search_flights_between_countries with args {'departure_country': '中国', 'arrival_country': '美国', 'departure_date': '2025-10-10'}]帮我查询 北京、上海 到 纽约、墨尔本 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_international_multi_city {'departure_list': ['北京', '上海'], 'arrival_list': ['纽约', '墨尔本'], 'departure_date': '2025-10-10', 'max_duration': 24, 'max_total_price': 5000, 'sort_by': ['total_price', 'duration'], 'limit': 20}]帮我查询 北京、上海 到 南京 的机票,时间 2025/10/10,并以markdown表格的形式显示出来 ✅
[Calling tool search_domestic_multi_city {'departure_list': ['北京', '上海'], 'arrival_list': ['南京'], 'departure_date': '2025-10-10', 'limit': 20}] 

4.4 问题

以上的处理方法有一个问题,就是传了两份 tools 列表。可以如下图,注释请求中的tools。

但这样返回就会改成如下格式,需要再修改代码处理,这里就不展示了。

<tool_use>
<name>search_flights_between_countries</name> 
<arguments>{"departure_country": "中国","arrival_country": "美国","departure_date": "2025-10-10"
}</arguments>
</tool_use>
 
 
http://www.hskmm.com/?act=detail&tid=40391

相关文章:

  • 2025年10月祛斑产品推荐:专业评测榜单及用户真实反馈汇总
  • hutool工具类post请求
  • 今年口碑好的新加坡留学品牌
  • 国产项目管理工具崛起:Gitee如何以本土化优势赋能中国企业数字化转型
  • 2025年10月洗碗机品牌对比榜:海信零菌技术深度评测
  • 2025年10月全屋智能家居品牌推荐:盈趣领衔五强对比评测榜
  • 2025年10月离婚房产律师排行:权威榜单与实测评价
  • 2025年10月美白精华产品推荐评测:从成分到肤感深度评价
  • 2025年10月工装装修公司榜单:资质与案例双维度排名
  • 2025年10月儿童面霜品牌推荐:口碑榜全维度解析
  • 2025年10月劳保鞋厂家榜单:五家对比评价与选购排行
  • python 界面开发
  • 三金.紫题题解
  • Java 条件结构
  • conda环境离线迁移
  • 【CI130x 离在线】语音芯片如何判断TTS音频播放完毕?
  • 从 “报表堆里找问题” 到 “实时预警止损”:MyEMS 如何终结能源管理低效?
  • 「Note」计算几何
  • C++语法—类的声明和定义
  • 施工用电隐患 “无形侦探”!思通数科 AI 卫士自动排查用电违规
  • 四场比赛(三)
  • 使用DAST发现Android应用API中的AWS凭证泄露漏洞
  • 从 “短期达标” 到 “长期优化”:MyEMS 如何帮企业建立可持续的能源管理体系?
  • 为什么大型网站能“秒回”你的用户名?揭秘毫秒级响应背后的“守门人”艺术
  • 文件同步备份:为什么说“同步盘”是比“普通网盘”更高效、更安全的选择?
  • 基于C#的停车场管理系统实现
  • 2025年市面上别墅石材品牌与行业内别墅石材源头厂家推荐榜单及口碑好的别墅石材产品分析
  • 连中五标,中电金信国际化服务助力企业出海
  • 1195. 交替打印字符串
  • 回调函数