Skip to main content
A v3 tool can fail while the MCP transport succeeds. Always inspect the tool result: a failure has isError: true and a structured body. Read structuredContent.code and the fields beside it, never the rendered text.

The error shape

Two results that are not errors

result
{ "status": "needs_input", "question": "…", "missingFields": ["budget.currency"] }. A required fact is missing. Ask the person the question, then call again with the answer. Never invent a value to get past it.
result
{ "status": "pending_confirmation", "confirmationUid": "cnf_…", "summary": "…", "expiresAt": "…", "writeExecuted": false }. The write is paused for a person’s approval. Show the summary; after they approve, call the same tool again with confirm: true and the confirmationUid (for a campaign launch, confirmLaunch: true). Confirmations expire after 15 minutes.

Common codes

NOT_FOUND deliberately hides whether an object exists in some other account. Do not read it as evidence about accounts you cannot see.

Partial results

Some tools talk to many sellers at once, so success is not all-or-nothing.
  • Proposal requests report each seller separately: quoted, products or failed, with a summary such as “Asked 9 sellers · 6 responded · 2 pending · 1 failed”. Keep the good answers; one failed seller does not spoil the execution.
  • Campaign launch returns mediaBuysExecuted and one entry in errors per failed media buy, each with recovery (transient, correctable or terminal) and retrySafe. Launching again resubmits only the failed draft buys.

Retrying safely

  1. If a call timed out or the connection dropped, read first: the write may have happened.
  2. Retry a write with the same idempotencyKey only if it is the same logical attempt. Change the key when you change the request.
  3. After a REVISION_CONFLICT, re-read, re-decide, then write with the new revision. Do not blindly bump the number.