Layer Separation
Clients MUST check
isError before deciding which extraction path to use. A response with isError: true MUST NOT be processed as a success response, even if it contains structuredContent with non-error data.
Extraction Algorithm
Clients MUST extract AdCP data from MCP tool results in this order:- Guard: reject error responses. If
isErroris truthy, return null. Error extraction is a separate path. structuredContent— If present and is a non-array object, return it. If the only key isadcp_error, return null (this is an error response missing theisErrorflag).- Text fallback — Iterate
content[]items in array order. For each item wheretype === 'text', enforce the configured response-size limit, then attemptJSON.parse. If the result is a non-array object, return it. Skip items that fail to parse, parse as non-objects, or contain only anadcp_errorkey. - No structured data found — Return null. The response is plain text with no machine-readable AdCP data.
Extraction Paths
structuredContent (Preferred)
MCP 2025-03-26 introducedstructuredContent for typed tool results. AdCP servers return the full response payload here:
structuredContent object IS the AdCP response — task-specific fields (products, media_buy_id, status, etc.) are at the top level, not nested.
When structuredContent carries the authoritative success payload, content MAY contain a terse human-readable summary. Producers SHOULD NOT serialize the complete AdCP payload again into content[].text; doing so doubles the wire bytes and model-context cost without adding information. A server supporting an older MCP client that cannot read structuredContent MAY instead put the JSON payload in text as the fallback form below and omit structuredContent. It should not emit both full copies.
Text Fallback
Older MCP servers (pre-2025-03-26) serialize the response as JSON incontent[].text:
structuredContent and text JSON exist, structuredContent takes precedence.
Relationship to Error Extraction
Success and error extraction are complementary:Security Considerations
Seller-Controlled Data
All data instructuredContent and content[].text is seller-controlled. The same prompt injection and data boundary requirements from Transport Error Mapping apply.
Size Limits
For pageable reads and other read-only tasks that support field projection, producers SHOULD target at most 128 KiB per serialized MCP response; see Managing response size. Clients SHOULD independently enforce a streamed limit on the complete serialized MCP message before buffering or JSON decoding. The recommended client safety limit is 4 MiB (4,194,304 bytes). For text fallback, also check thecontent[].text size before the inner JSON.parse, against that same limit rather than a tighter one — for a server that returns only content[].text, that item is the entire response, so a sub-limit figure there would silently become the effective cap. The larger safety limit is not a producer target: it bounds hostile or buggy input after normal interoperability guidance has failed.
The streamed limit is the MCP instance of the general client obligation to bound every agent response: count bytes as they arrive and abort rather than buffer-then-check, pre-reject an over-limit Content-Length, bound raw and decoded bytes, pair the cap with a deadline, bound JSON depth and node count after the cap passes, and fail with a distinct error instead of truncating. It applies to every MCP response the client reads — tools/call, tools/list, initialize, and the transport-native tasks/get and tasks/result results that carry an async CallToolResult. Leaving the async retrieval path unbounded is the same exhaustion with one extra hop.
A Streamable HTTP server MAY answer a POST with a single application/json body or with an SSE stream (text/event-stream), and the bound applies to both — a server does not escape it by choosing SSE. On the SSE path it applies to each event and to the cumulative bytes the client retains for one request, carried across Last-Event-ID resumption rather than reset by it, so an oversized result cannot be split across many frames or across a reconnect. On a non-HTTP transport (stdio) there is no Content-Length to pre-reject; the streaming count and the per-message bound still apply.
Clients SHOULD make the limit configurable per agent and per call. 4 MiB is the MCP default and is also the protocol-wide ceiling on a default, so a client raises the limit for a specific agent or a specific call rather than shipping a larger default. Implementations are free to default lower; the 4 MiB figure bounds hostile or buggy input after normal interoperability guidance has failed, and is not a size a producer may aim at.
Prototype Pollution
Clients MUST NOT merge extracted response objects into application state viaObject.assign or spread without filtering keys. Seller-controlled keys like __proto__ or constructor can trigger prototype pollution. Validate against the expected task response schema before merging.
Type Confusion
Clients MUST checkisError before success extraction. Without this guard, a client could process an error response as success data, leading to incorrect business logic (e.g., treating a RATE_LIMITED error as product data).
Client Library Requirements
Client libraries that implement this spec MUST:- Check
isErrorbefore extraction. Return null for error responses. - Prefer
structuredContent. Only fall back to text parsing whenstructuredContentis absent. - Validate parsed text. Only accept non-array objects from
JSON.parse. Reject arrays, strings, numbers, booleans, and null. - Handle
adcp_error-onlystructuredContent. WhenstructuredContentcontains only anadcp_errorkey, return null — this is an error response that may be missing theisErrorflag. - Do not require duplicated success data. Treat summary-only
content[].textas normal wheneverstructuredContentis present; never compare it with, or expect it to reproduce, the structured payload.
Test Vectors
Machine-readable test vectors are available at/static/test-vectors/mcp-response-extraction.json. Each vector contains:
path: extraction path (structuredContentortext_fallback)response: the MCP tool result envelopeexpected_data: the AdCP data that should be extracted (ornull)
See Also
- Transport Error Mapping — error extraction from MCP and A2A
- A2A Response Extraction — equivalent spec for A2A
- MCP Guide — MCP transport integration