Bug
The MCP and A2A error paths build the structured adcp_error envelope but never echo the request's context extension into the response. The success paths do echo it (inject_context in mcp_tools.py:2030), so any handler that raises AdcpError produces a response that violates the AdCP context-echo contract — buyers lose correlation IDs, idempotency hints, and other agent-to-agent state.
Repro
A handler calls raise AdcpError('PERMISSION_DENIED', message='nope'). The wire response carries structuredContent.adcp_error but no top-level context field, even though the request supplied one.
Affected paths
- MCP:
src/adcp/server/serve.py:1787-1804 — except ADCPError and the decisioning-AdcpError branch both call build_mcp_error_result(exc) without passing kwargs (the raw params).
- A2A:
src/adcp/server/a2a_server.py:237 — _send_adcp_error is invoked with (event_queue, context, exc) but not the parsed request params that carry the wire context extension.
- Builders:
src/adcp/server/translate.py:167 (build_mcp_error_result) and src/adcp/server/a2a_server.py:426 (_send_adcp_error) take exc only, with no surface to receive raw request params.
Symptom
Three storyboard runners fail on the AdcpError-raise path because the asserted echoed-context fields are missing from error responses.
Fix
- Plumb raw params into the error-result builders on both transports.
- After building the structured envelope, run
inject_context(raw_params, envelope) so the context field is echoed at the same level the success path uses.
- Add tests covering both transports' error path with and without a request
context field.
Plan to land as a single PR.
Bug
The MCP and A2A error paths build the structured
adcp_errorenvelope but never echo the request'scontextextension into the response. The success paths do echo it (inject_contextinmcp_tools.py:2030), so any handler that raisesAdcpErrorproduces a response that violates the AdCP context-echo contract — buyers lose correlation IDs, idempotency hints, and other agent-to-agent state.Repro
A handler calls
raise AdcpError('PERMISSION_DENIED', message='nope'). The wire response carriesstructuredContent.adcp_errorbut no top-levelcontextfield, even though the request supplied one.Affected paths
src/adcp/server/serve.py:1787-1804—except ADCPErrorand the decisioning-AdcpError branch both callbuild_mcp_error_result(exc)without passingkwargs(the raw params).src/adcp/server/a2a_server.py:237—_send_adcp_erroris invoked with(event_queue, context, exc)but not the parsed requestparamsthat carry the wirecontextextension.src/adcp/server/translate.py:167(build_mcp_error_result) andsrc/adcp/server/a2a_server.py:426(_send_adcp_error) takeexconly, with no surface to receive raw request params.Symptom
Three storyboard runners fail on the AdcpError-raise path because the asserted echoed-context fields are missing from error responses.
Fix
inject_context(raw_params, envelope)so thecontextfield is echoed at the same level the success path uses.contextfield.Plan to land as a single PR.