Skip to content

MCP slice 1: unblock /mcp and extract the idempotency protocol #804

Closed as not planned

Description

@mforce

Slice 1 of #789 (EPIC: MCP server support). Startable now. It is independent of #788, because this is pipeline work that does not care how a caller authenticated.

This is the largest risk in the entire epic. It is not the tool code.

Why it blocks everything

IdempotencyMiddleware triggers on all of POST/PUT/PATCH/DELETE, /mcp is not exempt, and an authenticated MCP call resolves a tenant. With no Idempotency-Key header, the middleware returns 400. MCP Streamable HTTP sends everything as POST, initialize and tools/list included, and no MCP client knows this repo's header contract.

MCP does not function at all until /mcp is exempted. Keys do not merely collide. The first handshake gets a hard 400. This blocks even a read-only demo, which #770's original estimate did not account for.

Scope

  • Exempt /mcp by endpoint metadata (HandlesOwnIdempotencyAttribute), not a path literal, with a guard asserting the set of bearers is exactly {"/mcp"}.
  • Extract Make API write idempotency atomic across replicas #307's claim/execute/publish protocol into IIdempotentUnit, keyed by an explicit IdempotencyScope(AccountId, OperationKey, CallerKey, RequestFingerprint) rather than the URL.
  • The middleware becomes the first adapter with OperationKey = Sha256($"{Method}:{Path}"), byte-identical to today, including the /api/v1/me user-scoping special case.

The rule that makes this safe

AtomicIdempotencyProtocolTests and the other #307 suites must pass UNEDITED. An edit to one of them in this PR means stop and review. It is not a fix. That is the entire mitigation for the risk this slice carries.

Run a local adversarial pass on the diff before the first push, per AGENTS.md. The #269 SingleAttemptExecution interaction, the #345 /error re-entry skip, and the steal-loss rollback path are each easy to preserve almost correctly.

Design

docs/plans/770-mcp-server/. Read 02-guards.md rows 17-24 before writing tests.

Note: if #788's OAuth work lands first and the write tool ends up routed through the existing HTTP endpoint over loopback, this extraction may be avoidable entirely. docs/plans/788-mcp-oauth/01-decision.md records that alternative. Price it before extracting.

Activity

  1. added
    sliceThin vertical work item
    area:apiAPI/endpoint layer
    priority:tier3Real product weight, real cost
    size:LSeveral days; wide blast radius or unresolved scope
    epic-789MCP server support (#789)
    on Sep 13, 2026
  2. added this to the MCP server support milestone on Sep 13, 2026
  3. mforce commented on Oct 6, 2026

    @mforce
    OwnerAuthor

    Closed as superseded in the 2026-10-06 re-evaluation. Nothing here is dropped; the work is split between two slices:

    Verified on main at 8cb14e67: the middleware still returns 400 for an /mcp POST without a key, and no exemption or extracted protocol exists.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiAPI/endpoint layerepic-789MCP server support (#789)priority:tier3Real product weight, real costsize:LSeveral days; wide blast radius or unresolved scopesliceThin vertical work item

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions