You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(server): add response_enhancer callback (JS #2161 parity)
Add a server-wide response_enhancer callback that stamps cross-cutting
fields on every response class — framework-tool successes, custom-tool
successes (get_task_status / list_tasks), the pre-auth
get_adcp_capabilities discovery response, and structured adcp_error
responses — uniformly across the MCP and A2A transports.
The Python SDK has no single response finalizer, so the enhancer is wired
at the three dispatch seams that converge the response classes, all AFTER
inject_context (so a buggy enhancer cannot re-introduce a stripped
credential into the echo envelope):
1. Success — create_tool_caller (mcp_tools.py): after inject_context and
before validate_response, so a conformance-breaking mutation surfaces
as VALIDATION_ERROR rather than shipping malformed. Covers framework
tools, custom tools, and get_adcp_capabilities on both transports.
2. MCP errors — build_mcp_error_result (translate.py).
3. A2A errors — _send_adcp_error (a2a_server.py).
Also closes the A2A comply_test_controller gap: that skill bypasses
create_tool_caller via _call_test_controller, so the enhancer is applied
there too (context echoed first to preserve the credential-echo invariant).
The enhancer supports both a context-blind Callable[[dict], None] and a
context-aware Callable[[str, dict, ToolContext | None], None], dispatched
by signature arity. It runs synchronously, mutates in place, and a raised
exception is caught + logged at WARNING — a buggy enhancer must not become
a transport error.
response_enhancer threads through ServeConfig, serve(), all three
_serve_* transport paths, create_mcp_server / create_a2a_server, and the
in-process build_asgi_app / build_test_client test harness.
adcp.decisioning.serve.serve forwards it via **serve_kwargs. The
ResponseEnhancer type alias is exported from adcp.server (matching
ServeConfig / SkillMiddleware; adcp.__all__ snapshot unchanged).
Idempotency note: the cache commits the pre-enhancement response, so a
replay re-runs the enhancer — non-idempotent enhancers diverge on replay.
Closes#926
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(server): document response_enhancer coverage seams
The ResponseEnhancer / serve() docstrings claimed the enhancer applies to
"every response". Two paths are not enhanced:
- the MCP comply_test_controller sandbox path returns the handler result
directly without a success-path enhancer call (its A2A counterpart is
stamped);
- a handler that returns (vs raises) a raw L3 {"adcp_error": {...}}
envelope is skipped by the success-path guard and never reaches the
raised-error finalizers.
Document the exact enhanced paths and these two gaps on the canonical
ResponseEnhancer docstring, point _apply_response_enhancer at it, and
soften the serve() docstrings from "every response". Docstring-only; no
behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments