使用说明
MCP Idempotency演示(流式HTTP、Python)
此仓库包含一个最小的演示,说明MCP工具调用中的幂等性,使用 python,the MCP Python SDK,以及 流式HTTP 运输。
注: 首选方法是引入一个新的顶级属性 idempotencyKey 到CallToolRequest。这使得幂等性明确且是必需的,而不仅仅是一段可选或可忽略的元数据。通过制造 idempotencyKey 作为一级属性,客户端和服务器都清楚幂等性是协议的核心部分,可以减少歧义和意外遗漏的风险。但是,此演示在 _meta 现场(_meta.io.modelcontextprotocol/idempotency-key)以避免破坏当前的MCP规范。两种形式见下文。
组件
server_non_idempotent.py:带工具的MCP服务器:make_payment(IBAN, BIC, amountMinorUnits, currency)– 不 幂等性;重试时,它会再次收费。get_balance()–退货{ "balanceMinorUnits": <int> }.get_transactions()–退货{ "transactions": [...] }.
server_idempotent.py:工具相同,但make_payment用途_meta.io.modelcontextprotocol/idempotency-key是 幂等性。使用相同密钥重试 不 申请付款 再一次。client.py:一个客户:- 呼叫
get_balance. - 呼叫
make_payment一次(服务器速度较慢,因此HTTP客户端超时)。 - 重试
make_payment同样的论点。 - 呼叫
get_balance和get_transactions再次打印结果。
- 呼叫
客户端对非幂等服务器运行此序列一次,对 幂等服务器,因此您可以直接比较结果。
创建venv
uv venv
安装依赖项
uv install -r requirements.txt
运行服务器(流式HTTP)
在一个终端中:
uv run server_non_idempotent.py
在另一个终端中:
uv run server_idempotent.py
两台服务器都公开了MCP 流式HTTP 接受JSON POST请求的端点。此演示使用保留密钥方法实现兼容性:
{
"tool": "make_payment",
"params": {
"IBAN": "...",
"BIC": "...",
"minorUnits": 2500,
"currency": "EUR"
},
"_meta": {
"io.modelcontextprotocol/idempotency-key": "73c2eaf4-8cc4-4ba4-908f-7017f0aa2f4f"
}
}
首选(未来)方法:
{
"tool": "make_payment",
"params": {
"IBAN": "...",
"BIC": "...",
"minorUnits": 2500,
"currency": "EUR"
},
"idempotencyKey": "73c2eaf4-8cc4-4ba4-908f-7017f0aa2f4f"
}
运行演示客户端
两台服务器都在运行时:
uv run client.py
您应该注意:
- 非幂等服务器
- 第一
make_payment调用:客户端记录超时,但服务器已经应用了付款。 - 第二
make_payment调用:服务器应用支付 再次 (无幂等性),因此get_balance显示两个借记和get_transactions包含两个匹配的付款。
- 第一
- 临时服务器
- 第一
make_payment调用:客户端超时,但服务器应用一次支付并存储 这_meta.io.modelcontextprotocol/idempotency-key. - 第二
make_payment用同样的电话_meta.io.modelcontextprotocol/idempotency-key:服务器 不 再次申请付款,因此get_balance仅显示一笔借记get_transactions只有一笔付款。
- 第一
这提供了一个具体的、端到端的说明,说明为什么幂等性对于安全重试支付等工具很有价值。虽然此演示在中使用了保留密钥 _meta 为了兼容性,建议的方法是 idempotencyKey MCP规范中的一级属性。