Skip to content

test(factory): add provenance-bound MCP OAuth scope step-up fixtures #2005

Description

@groupthinking

Decision

ADOPT + TEST — add fixture-only, provenance-bound MCP OAuth scope step-up behavior to Agent Factory/EventRelay. Keep live authorization disabled.

Verified upstream change

The official TypeScript MCP SDK added per-operation OAuth scope challenges on September 16, 2026:

The SDK now supports scopeChallenge for tools, static/template resources, and prompts, returning HTTP 403 insufficient_scope with WWW-Authenticate before handler execution or SSE starts. The challenge should contain the minimal complete scope set required for the current operation.

Official conformance coverage is proposed but not yet merged:

Do not claim official conformance until that upstream work merges and EventRelay pins and executes it.

Why this matters

Agent Factory needs a safe way to pause an operation, request narrowly scoped authority, record the decision, and retry without treating model-generated content as authorization. This is directly relevant to tool execution, resource reads, prompt access, and durable EventRelay receipts.

A critical SDK boundary is that the scope callback runs before input-schema validation/transformation. Any request field used for dynamic authorization therefore needs explicit canonicalization and validation with the same semantics as the eventual handler.

Fixture-only implementation

  • Add a feature-flagged scope-challenge adapter with live OAuth disabled by default.
  • Cover tools/call, static and template resources/read, and prompts/get.
  • Return HTTP 403 before handler invocation or streaming when scopes are insufficient.
  • Emit the minimal complete required scope set and verified resource_metadata.
  • On the client path, union prior grants with newly challenged scopes before a fixture-only retry.
  • Record immutable receipts containing call ID, operation and target, prior scopes, challenged scopes, resource metadata, approval provenance, decision, retry result, and whether the handler ran.
  • Bind approval to exact operator, operation, target, scope set, resource, expiry, and revocation state.
  • Treat a challenge as a request for authorization—not authorization itself.

Security invariants

  • Model output, peer-agent messages, tool results, Skills content/cache metadata, Video Pack transcripts/OCR, mission-canvas text, and generated workspace files grant zero authority.
  • Validate and canonicalize dynamic scope inputs before policy evaluation.
  • Deny malformed identifiers, scope-confusion/hierarchy assumptions, incorrect resource metadata, canceled or revoked grants, and peer-agent “GO” instructions.
  • Reject repeated incremental challenges for a single operation; challenge once with the complete required set.
  • Prove the protected handler and any side effect did not execute before authorization.
  • No automatic spending, deployment, messaging, merge, or external write authority.

Acceptance criteria

  • Deterministic fixtures for all supported primitive types.
  • Low-scope request produces 403 plus a correctly formatted WWW-Authenticate challenge.
  • Full-scope retry succeeds and invokes the handler exactly once.
  • Negative-input and provenance-isolation matrix passes.
  • Machine-readable receipt distinguishes configured policy, observed enforcement, and exclusions.
  • Current SDK commit is pinned for fixture evidence.
  • Upstream conformance PR docs(triage): PR remediation matrix — 2026-07-03 refresh (16 open PRs) #481 is tracked as unmerged and excluded from any official-conformance claim.
  • CI, security, CodeQL, coverage, dependency, and secret checks pass.

Boundaries

No production activation, live OAuth exchange, provider spending, deployment, or merge is authorized by this issue.

Estimated effort: 1–2 engineering days.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions