What
CreateMediaBuyResponse has three valid branches per spec (schemas/cache/media-buy/create-media-buy-response.json):
- Success —
media_buy_id + packages, status from media-buy-status enum (pending_creatives | pending_start | active | paused | completed | rejected | canceled)
- Error —
errors array
- Submitted —
status: 'submitted' + task_id (async task envelope)
When a platform returns the third branch (e.g., salesagent's _create_media_buy_impl maps internal pending_approval → wire status='submitted' for tenants with human_review_required=True), FastMCP's per-tool output validator rejects with:
mcp_error: Output validation error: 'submitted' is not one of ['pending_creatives', 'pending_start', 'active', 'paused', 'completed', 'rejected', 'canceled']
The validator is checking against the media-buy-status enum unconditionally instead of resolving the response oneOf based on shape. The submitted branch's status: Literal['submitted'] discriminator should produce a clean branch resolution but doesn't.
Repro
salesagent kill-nginx greenfield (core/platforms/_delegate.py:_delegate_create_media_buy) calls _create_media_buy_impl. With wonderstruck tenant human_review_required=True, the impl returns the submitted-branch envelope. FastMCP rejects.
Workaround
tenant.human_review_required = False — forces the synchronous success branch. Production tenants needing manual approval can't ship until the validator resolves the oneOf.
What we'd want
The output validator should:
- Recognize CreateMediaBuyResponse as a discriminated union
- Resolve the branch by looking at top-level fields (
status='submitted' + task_id → submitted branch; errors → error branch; media_buy_id + packages → success branch)
- Validate the resolved branch's schema, not the wrong one's enum
Current behavior makes the async-approval flow unreachable on MCP transport.
Filed by
salesagent live GAM CRUD probe — surfaced when driving real create_media_buy against Wonderstruck tenant. Tracked as salesagent #41.
What
CreateMediaBuyResponse has three valid branches per spec (schemas/cache/media-buy/create-media-buy-response.json):
media_buy_id+packages,statusfrom media-buy-status enum (pending_creatives | pending_start | active | paused | completed | rejected | canceled)errorsarraystatus: 'submitted'+task_id(async task envelope)When a platform returns the third branch (e.g., salesagent's
_create_media_buy_implmaps internalpending_approval→ wirestatus='submitted'for tenants withhuman_review_required=True), FastMCP's per-tool output validator rejects with:The validator is checking against the media-buy-status enum unconditionally instead of resolving the response oneOf based on shape. The submitted branch's
status: Literal['submitted']discriminator should produce a clean branch resolution but doesn't.Repro
salesagent kill-nginx greenfield (
core/platforms/_delegate.py:_delegate_create_media_buy) calls_create_media_buy_impl. With wonderstruck tenanthuman_review_required=True, the impl returns the submitted-branch envelope. FastMCP rejects.Workaround
tenant.human_review_required = False— forces the synchronous success branch. Production tenants needing manual approval can't ship until the validator resolves the oneOf.What we'd want
The output validator should:
status='submitted'+task_id→ submitted branch;errors→ error branch;media_buy_id+packages→ success branch)Current behavior makes the async-approval flow unreachable on MCP transport.
Filed by
salesagent live GAM CRUD probe — surfaced when driving real
create_media_buyagainst Wonderstruck tenant. Tracked as salesagent #41.