Skip to content

Phase 2: TestControllerStore + AdCPTestContext header-driven compatibility (PR-R) #227

@bokelley

Description

@bokelley

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions