Skip to content

FastMCP output validator rejects 'submitted' status on CreateMediaBuyResponse oneOf #570

@bokelley

Description

@bokelley

What

CreateMediaBuyResponse has three valid branches per spec (schemas/cache/media-buy/create-media-buy-response.json):

  1. Successmedia_buy_id + packages, status from media-buy-status enum (pending_creatives | pending_start | active | paused | completed | rejected | canceled)
  2. Errorerrors array
  3. Submittedstatus: '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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions