A handler that throws exceptions is a handler that breaks the conversation. The agent receives a crash and doesn't know whether:
The difference between an MCP that gets used and one that gets discarded is how it handles bad cases. The rule:
Errors are returned as structured data, not as exceptions. The agent can read data. It can't recover from a crash.
On the right you have the transfer_credits schema already done, plus a handler starter that works on the happy path but blows up on everything else.
Your job: add the validations so four different scenarios end with a clean result:
ok: true.ok: false with an identifiable error.ok: false with an identifiable error.ok: false, including how much is available.{
ok: false,
error: {
code: "insufficient_funds",
message: "Em has 200 credits, tried to transfer 999.",
balance: 200
}
}code. short, identifiable string. The agent reads it to decide what to do.message. human text. Can be shown to the user or used as context.balance helps the agent suggest a valid amount.This exercise does NOT execute your code. An LLM-judge reads your implementation and reasons about whether it would correctly handle the four scenarios. That means your code has to be readable. clear variable names, obvious control flow. The judge doesn't run, it infers.
Tip: structure as
if-returnearly. Each validation is a check + early return. No nesting, no else.