麦当劳 MCP 实测:一个藏在 inputSchema 里的参数
麦当劳放出了官方 MCP Server(mcp.mcd.cn,35 个 tool),我拿它做了个小工具, 顺手记录了 6 条官方文档没写、但会直接导致调用失败的契约。
先说最有意思的那条 ------ 它解释了一个现象。
一、roundList 只存在于 inputSchema 里
calculate-price 的正文 description 完全没有提到 roundList 这个参数。 它只出现在 inputSchema.properties.items.items.properties.roundList, 描述只有三个字:「套餐子项」。
json
{
"items": {
"items": {
"properties": {
"roundList": {
"description": "套餐子项",
"type": "array"
}
}
}
}
}
而 roundList 正是套餐内商品换购的唯一入口。
也就是说:麦当劳开放了「换掉套餐里的可乐」这个能力, 但因为参数只躺在 schema 里、正文没写,绝大多数人根本没发现它。
------这大概就是为什么当时榜单上 100 个项目里,没有一个做套餐换购。
二、单位方向相反(最坑的一个)
python
# query-meals 返回的价格:元字符串,schema 里没写单位
{"currentPrice": "33.5"} # 字符串!单位是元
# calculate-price 接收的价格:整数,schema 明写"单位分"
{"price": 3450} # 整数,单位是分
一个进一个出,一个元一个分,一个字符串一个整数。 schema 里只有后者标了单位。我第一次调用时直接 int("33.5") 崩了。
我的做法:在 adapter 层统一转成整数分,全项目只在这一层接触原始字段。
python
def parse_money(raw: str) -> int:
"""元字符串 → 整数分。"""
return round(Decimal(raw) * 100)
三、前导说明格式不统一
MCP 返回的 JSON 前面会垫一段说明文字,但不是每个 tool 都有:
query-meals→ 带Original Response前导query-nearby-stores→ 不带
所以解析前必须先剥前导,且不能硬编码那行标题:
python
def strip_preamble(text: str) -> str:
"""剥掉 MCP 响应前导说明,返回纯 JSON。"""
start = text.find("{")
if start < 0:
raise ValueError("响应中找不到 JSON")
return text[start:]
四、query-my-coupons 返回的是 Markdown,不是 JSON
这个 tool 不吐 JSON。想结构化处理只能自己解析 Markdown 表格。 我直接绕开了:这个数据对我的场景不是必需的。
教训:不要假设同一种传输格式。
五、条件价:canWithOrder
query-meals 返回的 currentPrice 不总是你能真正付的价格。
python
{"discountType": "随单购麦金卡优惠", "canWithOrder": True}
这类餐品标的是「买卡才成立」的价格。不买卡,按划线原价付款。 我实测到最大差额:¥49.90 vs ¥114.50,差 ¥64.60。
判断逻辑:
python
def is_conditional(item) -> bool:
"""是否为「随单购」条件价。"""
return "随单购" in (item.discount_type or "") or item.can_with_order
六、双人餐位的 minQuantity = 2
双人套餐的座位 minQuantity 是 2, 构造 roundList 时 quantity 必须取 max(1, min_quantity), 否则核价出来的金额不对(少算一份)。
python
quantity = max(1, round_.min_quantity)
最终做出的东西
一个零依赖 的套餐换购分析工具:只用 Python 标准库,不需要 MCP Token, python demo.py 直接跑 ------ 因为我把真实响应录进了 fixtures/。
实测门店 40 个套餐的结论:
- 33 个(82%)存在「与默认同价的替换选项」,合计 129 个
- 20 个(50%)默认搭配比可达最低价更贵,最高贵 ¥4.00
- 单个套餐最多 8 个免费替换(全明星双人分享餐八件套,54 个候选选项)
- 18 个餐品是「随单购麦金卡」条件价,最大差 ¥64.60
所有金额都由 calculate-price 真实核价回填,不是估算。
换购说到底就一句话:这些都是同一份钱能买到的东西,只是菜单不会告诉你。
项目(MIT,含 52 项单测 + CI): github.com/huwell88/mc...
我参加了麦当劳的开发者大赛,如果这篇对你有用,欢迎点个 Star 支持一下 🙏
补充:我还把 roundList 的调用契约写成了文档(MCP_INTEGRATION.md), 以及一份完整的数据溯源(fixtures/README.md,含采集门店与时间), 接入 McD MCP 的话可以直接参考。