Summary
Downstream (salesagent) drives mock-ad-server behaviors via request headers (AdCPTestContext.from_headers(...)). The SDK's TestControllerStore is storyboard-shaped — transitions are triggered via the comply_test_controller skill, not via headers. The two models don't compose; downstreams that adopt TestControllerStore lose their header-driven test scaffolding.
Proposed fix
Add a test_context_factory hook to register_test_controller() / create_mcp_server(test_controller=...) that lets downstream derive the test-runtime context from request headers before the skill dispatches. Minimum signature:
TestContextFactory = Callable[[RequestMetadata, Mapping[str, str]], Any]
def register_test_controller(
mcp: Any,
store: TestControllerStore,
*,
test_context_factory: TestContextFactory | None = None,
) -> None: ...
When set, the factory is invoked per tool call with request headers — it returns whatever test-runtime context the seller's mock-ad-server code expects, which the handler can read off ToolContext.metadata["test_context"].
Alternative (lower ambition): document the integration pattern without adding a hook. Downstream reads headers from their own middleware (via ContextVars) and sets ToolContext.metadata["test_context"] inside their context_factory.
Acceptance
- One of the two shapes above — prefer the hook since it formalizes the pattern.
- Section in
docs/handler-authoring.md under a new "Testing hooks" heading showing header-driven + storyboard-driven testing side-by-side.
- Integration test exercising the factory against a mock seller.
Context
Roadmap item PR-R (Phase 2) from .context/sdk-adoption-roadmap.md. Not a blocker for MCP migration; becomes relevant when salesagent's header-driven test framework needs to coexist with storyboard compliance testing.
Summary
Downstream (salesagent) drives mock-ad-server behaviors via request headers (
AdCPTestContext.from_headers(...)). The SDK'sTestControllerStoreis storyboard-shaped — transitions are triggered via thecomply_test_controllerskill, not via headers. The two models don't compose; downstreams that adoptTestControllerStorelose their header-driven test scaffolding.Proposed fix
Add a
test_context_factoryhook toregister_test_controller()/create_mcp_server(test_controller=...)that lets downstream derive the test-runtime context from request headers before the skill dispatches. Minimum signature:When set, the factory is invoked per tool call with request headers — it returns whatever test-runtime context the seller's mock-ad-server code expects, which the handler can read off
ToolContext.metadata["test_context"].Alternative (lower ambition): document the integration pattern without adding a hook. Downstream reads headers from their own middleware (via ContextVars) and sets
ToolContext.metadata["test_context"]inside theircontext_factory.Acceptance
docs/handler-authoring.mdunder a new "Testing hooks" heading showing header-driven + storyboard-driven testing side-by-side.Context
Roadmap item PR-R (Phase 2) from
.context/sdk-adoption-roadmap.md. Not a blocker for MCP migration; becomes relevant when salesagent's header-driven test framework needs to coexist with storyboard compliance testing.