Skip to content

feat: form-mode cost confirmation via MCP elicitations - #367

Open
barryroodt wants to merge 20 commits into
mainfrom
barryroodt/mcp-elicitations-form
Open

feat: form-mode cost confirmation via MCP elicitations#367
barryroodt wants to merge 20 commits into
mainfrom
barryroodt/mcp-elicitations-form

Conversation

@barryroodt

@barryroodt barryroodt commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

#358 has merged, so this PR now targets main directly and the branch was rebased onto it. Merging this PR only opens a release PR. It does not ship the package.

What changed

This adds Human Confirmation for create_project and create_branch through MCP form elicitations, replacing the bypassable confirm_cost path on capable clients (AI-886).

  • mcp-utils owns the policy seam, signed Continuation State, replay protection, 120-second expiry, and handler plumbing. State keys must contain at least 32 bytes.
  • Supabase adds cost policies, stdio wiring, and the per-connection --disable-elicitations option from AI-1045. The platform PR handles disable_elicitations.
  • formDeliveryAvailable distinguishes BASE legacy clients, form-capable legacy clients, and generic clients without changing the optional Tool.formatResult contract.

The cost payload includes the live rate, a continuous-run projection, and its assumption. The prose remains PLACEHOLDER-COPY behind Design/PM sign-off, so tests pin the facts rather than the wording.

The branch is 20 commits atop main. The rebase dropped two management-API types-sync commits already upstream via #364/#369, and old review-thread SHAs from before the rebase are superseded.

Behavior contracts

Clients without form support plus opted-out connections keep the existing confirm_cost behavior. The complete BASE tools/list response contains 29 tools and hashes to SHA-256 7327d077b6bdacccfa9f5853d489be6a81f2b2763ca0cc344e0bb4e8fd47371d. Exact legacy text assertions also preserve execute_sql as {result:string} and its untrusted-data boundary.

On form-capable connections, confirm_cost is hidden from discovery but remains callable with migration guidance. Decline and cancel are structured terminal variants. Expiry returns recovery guidance. Tampered state, including an edited readable exp, remains an SDK-owned -32602.

humanConfirmationEnabled === false fails protected paid tools closed while ordinary tools continue working. The gate runs before replay consumption, so an in-flight confirmation can resume with the same state inside its TTL. Generic gate telemetry uses reason: gate; serving-path telemetry preserves the capability-specific reason.

Legacy-era sessions take capabilities from the initialize handshake. Legacy-wire results project through the contextual output schema.

Verification

Final tree 0aa1be8b849a3e53fb53b2a8af039013e810f49c (rebased onto main at fc54ea2):

  • format:check: clean
  • build: all three packages typecheck and build
  • mcp-utils: 69/69
  • mcp-server-supabase: 279/279 non-environmental tests (unit 258/258, stdio integration 21/21; the 258 include Supabase elicitations 26, cost policies 15, and the legacy server suite)
  • Packed platform consumer: 3/3, packed @supabase/mcp-server-supabase version 0.11.0
  • The postgrest localhost :54321 environmental tests were not re-run this round; build/typecheck covers that package.

Five Anthropic-key e2e tests were excluded locally because ANTHROPIC_API_KEY was missing. The real-Claude prompt-injection e2e passed 1/1 earlier in this branch's review, before the final local review. This verification does not claim a fresh pass at the current head.

A five-lane review covered correctness/contracts, security, tests, spec compliance, and structural simplification. The initial verdict was NOT_READY; all nine synthesized findings and one post-fix telemetry issue were fixed. The final verdict is READY with no critical or important findings.

Notes for reviewers

The runtime owns minting and verification because SDK v1's createRequestStateCodec hard-reads Date.now() and does not expose typed failure causes. The implementation remains byte-compatible, with codec parity and replay boundaries covered independently. Request-state parsing, replay, codecs, and handlers now have separate responsibilities, and SDK input uses InputResponseView.

A fresh pnpm install breaks under Corepack's floating pnpm 11.16. The repo uses pnpm 10.33.2 through mise; moving the build-script policy for pnpm 11 remains a follow-up.

Please leave release.yml and the release PR out of this change. The publish-preview label records the pkg.pr.new URL for the platform stack.

Part of AI-1091

@barryroodt
barryroodt requested a review from a team as a code owner August 18, 2026 16:29
@barryroodt barryroodt added the publish-preview Runs `publish-preview` workflow to publish preview packages via https://pkg.pr.new/ label Aug 18, 2026
@barryroodt
barryroodt requested review from gregnr and raulb August 18, 2026 16:29
@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@supabase/mcp-server-postgrest@0aa1be8
pnpm add https://pkg.pr.new/@supabase/mcp-server-supabase@0aa1be8
pnpm add https://pkg.pr.new/@supabase/mcp-utils@0aa1be8

commit: 0aa1be8

@barryroodt barryroodt self-assigned this Aug 19, 2026
@barryroodt
barryroodt marked this pull request as draft August 19, 2026 10:00
@barryroodt
barryroodt force-pushed the barryroodt/ai-1044-dual-era-serving branch 3 times, most recently from 6a006fa to ec9ebed Compare August 20, 2026 12:06
@barryroodt
barryroodt force-pushed the barryroodt/mcp-elicitations-form branch from c5660c9 to 0aa1be8 Compare August 24, 2026 11:11
@barryroodt
barryroodt changed the base branch from barryroodt/ai-1044-dual-era-serving to main August 24, 2026 11:11
@barryroodt
barryroodt marked this pull request as ready for review August 24, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

publish-preview Runs `publish-preview` workflow to publish preview packages via https://pkg.pr.new/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant