掃描 2,500 個公開 MCP 伺服器:72 個涉及資金操作,均未説明如何中途停止
We scanned 2,500 public MCP servers. 72 touch money. None mentions a kill switch.
作者掃描 2,500 個公開 MCP 伺服器,發現 72 個涉及付款、轉帳、交易或資金管理,但都沒有文件説明如何在操作途中停止。文章提出三項控制檢查:在操作前執行任務、每日及交易對手的硬性預算上限;提供可由第三方獨立驗證的簽署收據;並讓停止開關與預算檢查走相同路徑,故障時拒絕操作。
We scanned 2,500 public MCP servers. 72 of them touch money. None of them mentions a kill switch.
That sentence started as a marketing line. Then we checked it, and it held: across the public MCP registries, the servers that actually move funds — payments, transfers, trading, treasury — ship without a documented way to stop them mid-flight. Plenty of servers describe what they can do. Almost none describe what they must not do, or who can stop them.
This post is about the gap, and the three checks we ended up implementing.
The gap is not authentication
Most MCP servers get authentication right-ish: an API key, an OAuth token, a scoped credential. That answers "who is calling". It does not answer:
- how much may this call spend, in total, before someone notices?
- what happens when the agent retries a payment four times?
- who can revoke the permission at 3am, and how fast?
Those are mandate questions, not auth questions. A credential says you may act. A mandate says you may act this much, this way, until this moment.
Check 1: a budget that is enforced, not logged
The common pattern is to log spend and alert on it. That is observability, not control. By the time the alert fires, the money is gone.
What worked for us: an envelope that the tool call must present, with a hard ceiling per task, per day, and per counterparty. The check runs before the side effect, and a failure is a refusal, not a warning. The important detail is that the ceiling lives outside the agent's context — if the model can edit its own limit, it is not a limit.
Check 2: a receipt that survives the agent
Agent output is easy to fake and easy to lose. If a payment happened, the evidence must be verifiable by a third party who does not trust the agent, the model provider, or us.
We settled on a signed receipt over a canonical JSON encoding (RFC 8785), with the hash chain anchored per task. Two properties matter more than the format:
- Deterministic — the same event must produce byte-identical output, otherwise signatures drift and audits fail.
- Standalone — verification must not require our server to be alive. A dead service must not be able to invalidate history.
Check 3: a stop that is faster than the loop
An agent loop can issue hundreds of calls per minute. A kill switch that requires a deploy, a config push, or a support ticket is not a kill switch.
The stop has to be checked on the same path as the budget, and it has to fail closed. We test it by flipping it during a live run and confirming the next call is refused — not by reading the code and assuming.
What we learned from the 2,500 servers
- Capability is documented; restraint is not. README files list tools. Very few list limits.
- "Human in the loop" usually means a chat message. A message is not a gate: it does not block, it does not expire, and it leaves no receipt.
- Registries reward demos. A server that can send USDC gets attention. A server that refuses to send too much gets none — until someone needs the refusal.
If you run an agent that touches money, the audit is short: find the ceiling, find the receipt, find the stop. If any of the three lives only in the prompt, you have a suggestion, not a control.
The scan data and the checks are public: karta.rta.lat/report. The MCP server that implements them is attest.rta.lat.
We publish the method, not the marketing: if a number here is wrong, tell us and we will correct it in public.
來源:DEV Community · dev.to