A shopping server returns a basket_id handle from create_basket and states a 24-hour lifetime in that tool's description. Two days later, the model calls add_item with the old basket_id. What should the server return?
Select an answer to reveal the explanation.
Short Explanation
It's like handing in a coat-check ticket from last week: the attendant tells you it's expired so you can check your coat again. That's a tool execution error the model can read and act on. The trap is a protocol error that the model may never see.
Full Explanation
The tools specification gives non-normative guidance on stateful tools. Because MCP has no protocol-level session, servers that need state across calls return an explicit handle from a creation tool and accept it on later calls, and the guidance covers expiry directly: a call against an expired or unknown handle should return a tool execution error that says so, so the model can recover by creating a new one. A tool execution error is a normal result with isError set to true and actionable text. Returning -32602 treats the problem as a malformed request, but the call is structurally valid; the failure is business logic, which belongs in a tool execution error that clients should pass to the model. Silently recreating a basket under the old ID loses the user's items without telling anyone and lets a stale handle masquerade as valid state. Asking the user to re-authenticate misdiagnoses the problem, since nothing about identity changed and the basket is gone because of its lifetime, not because of credentials. Exam caveat: for authenticated servers a handle is a name, not a capability, so the server must also check the caller's authorization against the handle on every call. Operational check: call add_item with an expired handle and confirm an isError result naming the expiry and suggesting create_basket.