Skip to content

[Buyer Gap] Make authenticated Global Ask MCP browser-safe and admission-bounded #269

Description

@seonghobae

Buyer problem

Canonical MCP Global Ask is now PR #270. A browser client must preflight its authenticated Streamable HTTP request, and the ingress must bound actual request bytes before OAuth or SDK JSON parsing. Separately, a rate-limited authenticated principal needs protocol-compatible retry guidance without leaking another principal's counters.

Delivery slices

Slice A — browser and request-byte admission: PR #286

Required behavior:

  • validate Host and every present Origin before OAuth;
  • handle an exact allowed-Origin OPTIONS preflight without bearer authentication, database access, quota consumption, or tool invocation;
  • never accept or reflect *, null, prefix, suffix, credential-bearing, path-bearing, query-bearing, or fragment-bearing configured Origins;
  • emit Vary: Origin on Origin-sensitive responses;
  • expose the MCP protocol/session headers and WWW-Authenticate so an allowed browser client can read OAuth resource discovery;
  • retain no-Origin support for Codex and other non-browser clients;
  • enforce MCP_MAX_REQUEST_BYTES before OAuth and SDK JSON parsing;
  • reject invalid, negative, non-ASCII, duplicate, conflicting, or mismatched content length/framing;
  • count streamed bodies independently of Content-Length and reject over-limit data immediately;
  • replay an admitted body byte-for-byte once;
  • return stable no-store 400/413 errors without echoing request content.

PR #286 is Draft and depends on #270. It is not accepted until reconstructed/restacked on the current #270 exact head and all exact-head gates pass.

Slice B — distributed per-principal rate limiting: not yet complete

Required behavior:

  • consume quota only after a bearer token has resolved to a provisioned LineageWeave principal;
  • use a distributed Valkey-backed window shared across MCP process instances;
  • key counters by opaque principal/account identity and never expose another principal's counters;
  • return an MCP/HTTP-compatible rate-limit failure with a bounded Retry-After derived from the actual window;
  • successful requests and preflight/Host/Origin/body-admission failures do not carry Retry-After;
  • fail closed or explicitly unavailable according to an ADR if the distributed limiter is unavailable; do not silently fall back to a process-local counter;
  • preserve feat: expose authenticated MCP Global Ask #270's RBAC, ABAC, citation, source, orchestrator, and explicit external-verification boundaries.

RED→GREEN acceptance tests

  1. Allowed exact-Origin preflight succeeds with the exact response headers and no bearer challenge.
  2. Unsafe configured Origins prevent startup; unsafe request Origins fail before authentication and are not reflected.
  3. Allowed-Origin 401 exposes WWW-Authenticate to browser JavaScript.
  4. No-Origin non-browser POST still reaches the normal OAuth challenge.
  5. Oversized declared and streamed bodies fail before downstream parsing/tool invocation.
  6. Invalid/ambiguous framing and declared/actual mismatches fail with stable codes.
  7. An under-limit body preserves the canonical Global Ask question contract.
  8. A principal exceeding its distributed allowance receives bounded retry metadata; successful and pre-auth failures do not.
  9. Existing authorization, citations, semantic retrieval, and external-verification contracts remain unchanged.

Scope boundary

Do not mix this issue with semantic/KG retrieval and public corroboration (#276), evidence-honest knowledge-cutoff work (#271), conversation persistence, unrelated REST CORS, or provider-specific model logic.

Buyer completion signal

A browser MCP client can discover OAuth, complete preflight, submit a bounded authenticated Global Ask, and recover predictably from a principal-specific distributed rate limit without weakening exact-origin, request-framing, RBAC/ABAC, citation, or evidence boundaries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions