A shopping server returns a cart handle from create_cart and accepts it as an argument on later tool calls. User B, holding a valid token of their own, guesses user A's handle and adds items to A's cart. What fix addresses the root cause?
Select an answer to reveal the explanation.
Short Explanation
A cart handle is a name tag, not a key. Anyone can read a name tag, so you check who's actually holding it: the server ties each handle to the user in the verified token and turns everyone else away. Headers, hints and self-reported client names don't prove a thing.
Full Explanation
MCP is stateless, so servers that keep state across calls mint an explicit handle and receive it back as an ordinary tool argument. The security best practices on state handle hijacking say servers that implement authorization MUST verify all inbound requests and MUST NOT treat possession of a handle as authentication. Servers SHOULD use secure, non-deterministic handles and SHOULD bind handles server-side to the authenticated user, for example by keying stored state as user ID plus handle where the user ID comes from the verified token, rejecting the handle from any other principal. Moving the handle into a header changes where the value travels but not who may present it, and the 2026-07-28 revision has no protocol sessions to attach it to. A destructiveHint is an untrusted hint to the host about tool behavior; it may add a prompt for user B but does nothing to stop B acting on A's cart. Matching on clientInfo fails because that field is self-reported, unverified and explicitly not to be relied on for security decisions. Exam caveat: for unauthenticated servers a handle is necessarily a bearer value, so it needs high entropy and a bounded lifetime. Operational check: call add_item with a handle created under another account's token and confirm the server rejects it.