feat(mcp): add branch cost confirmation elicitation - #394
Conversation
commit: |
24535f1 to
c06b135
Compare
Coverage Report for CI Build 33730957759Warning No base build found for commit Coverage: 96.466%Details
Uncovered Changes
Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats
💛 - Coveralls |
c06b135 to
bb4f0a7
Compare
Rodriguespn
left a comment
There was a problem hiding this comment.
This does read as #391 with the branch flow swapped in, and I can confirm the fixes from my earlier review all carried over (safe defaults on the elicitation action, drift check below decline/cancel, and the suffix driven off cost.recurrence rather than hardcoded).
Ran the elicitation suite locally (21 passing) plus a few probes of my own for the paths the suite doesn't cover, both cross-tool state and the single-tool enabledTools configs. Both behave correctly; I've left inline comments suggesting tests for them, plus a couple of small type/pricing notes. Nothing blocking.
One thing worth adding to the description: replay is better contained here than for projects. preview_branches has a real UNIQUE (project_id, branch_name) constraint (migration), so a replayed branch confirmation fails at the DB rather than relying on the read-then-check that covers create_project. Same known limit, weaker consequence.
4382f06 to
a00f977
Compare
|
Could you explain if there is a path to test this with our stdio server? I see here we don't populate + costConfirmation: {
+ requestStateKey: randomBytes(32),
+ principal: 'local-stdio-user',
+ enabledTools: ['create_project', 'create_branch'],
+ },I initially expected that old clients would continue to work the same as they have been with the old cost confirmation tools, and that new clients would use elicitations, regardless of transport. But from what I can tell, populating |
Apologies for the confusion here - after numerous chats with @gregnr the decision was taken not to add elicitation support to stdio (due to it being deprecated). To do a full e2e test for elicitations you'll need to run the mcp server via the platform setup (PR #37722) - i'll update the linked Linear ticket with a detailed runbook on how to get that setup and running. Thanks for taking the time to look at this. |
2370f11 to
07425eb
Compare
mattrossman
left a comment
There was a problem hiding this comment.
Tested this by fusing changes from #402 onto the branch locally to connect to Claude Code launched w/ the modern protocol flags:
MCP_SDK_GENERATION=v2 MCP_PROTOCOL_NEGOTIATION=auto claudeThis was my first time seeing elicitations working in Claude which was cool :) It was working as expected. Would love to get the HTTP dev server in so future stuff stays low lift to test.
Left a couple minor comments about test coverage opportunities. The Claude Code elicitation UI design is questionable w/ how it truncates info, but that's not something we have a lot control over and who knows how it'll change over time. Leaving it to you how you want to address the remaining feedback.
Noting this PR will partially address #285, in that the unavailable cost confirmation tools aren't needed w/ elicitations 🙌
07425eb to
07c889d
Compare
…owances Identify the $0.01344/hr rate and 30-day estimate in the create_branch cost confirmation prompt as standard/list-price figures before plan allowances or exemptions, and state that actual charges may be lower. Pins the qualifier in the existing branch-prompt assertion.
Replace the hand-built RegExp matcher with two plain toMatchObject checks: the existing hourly-rate substring check, plus a second check for the standard/list-price qualifier phrase.
07c889d to
6b363bb
Compare
Makes `tools/list` adapt to `costConfirmation.enabledTools` to prevent supported clients from getting prompted twice, from both the legacy tools and elicitation strategy, surfaced when testing supabase/platform#37717 The `tools` callback now receives the per-request `ServerContext` so `tools/list` can vary by client: - If both `create_project` and `create_branch` are in `costConfirmation.enabledTools`, `get_cost` and `confirm_cost` are no longer advertised. They stay callable, so a client that already knows the names keeps working. - If only one `create_` tool is enabled, the two cost tools are still advertised because the other `create_` tool still needs a `confirm_cost_id`, but their `type` argument is narrowed. - `create_project` and `create_branch` drop `confirm_cost_id` when they're in `enabledTools`, since a form-capable client confirms inline and never needs it. Legacy clients are unaffected. ## How to review Run the server over HTTP w/ `costConfirmation` enabled for both tools and connect a form-capable client (e.g. Claude Code w/ the SDK v2 flag as described [here](#394 (review))). The tool list should have no `get_cost` or `confirm_cost`, and `create_project` no longer has a `confirm_cost_id` argument. Connect again without declaring `elicitation` and both tools are back. ## Notes I renamed the test helper `setupFormCapable` to `setupModern` and made its capabilities explicit via a `FORM_CAPABLE` constant, because technically legacy clients can have form capabilities. The #391 test "a supplied `confirm_cost_id` cannot bypass the form" is now "is rejected". The field isn't in a form-capable client's schema anymore, so strict arg parsing errors instead of routing to the form.
🤖 I have created a release *beep* *boop* --- <details><summary>mcp-utils: 0.8.0</summary> ## [0.8.0](mcp-utils-v0.7.0...mcp-utils-v0.8.0) (2026-09-04) ### Features * **mcp:** add project cost confirmation elicitation ([#391](#391)) ([fb50882](fb50882)) * **mcp:** hide legacy cost tools from form-capable clients ([#411](#411)) ([2f04461](2f04461)) </details> <details><summary>mcp-server-supabase: 0.12.0</summary> ## [0.12.0](mcp-server-supabase-v0.11.0...mcp-server-supabase-v0.12.0) (2026-09-04) ### Features * group lints in `get_advisors` response ([#390](#390)) ([48d593a](48d593a)) * **mcp:** add branch cost confirmation elicitation ([#394](#394)) ([867a160](867a160)) * **mcp:** add project cost confirmation elicitation ([#391](#391)) ([fb50882](fb50882)) * **mcp:** hide legacy cost tools from form-capable clients ([#411](#411)) ([2f04461](2f04461)) ### Bug Fixes * ensure correct escaping in advisor ([#407](#407)) ([a6cf4a0](a6cf4a0)) * make server instructions intent-based instead of naming tools ([#372](#372)) ([fc54ea2](fc54ea2)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: supabase-releaser[bot] <223506987+supabase-releaser[bot]@users.noreply.github.com>
Stacked on #391. Review that first. This is part of AI-1091.
What kind of change does this PR introduce?
Feature: add form-mode cost confirmation to
create_branch.What is the current behavior?
#391 provides the shared confirmation codec/verifier,
ServerContext, result passthrough, and project flow. Branch creation still uses the existing hash validation.What is the new behavior?
Modern form clients can call
create_branchwithoutconfirm_cost_id. They receive an action-only, property-less prompt for $0.01344/hr (about $9.68 over 30 days).Acceptance creates the branch from signed arguments. Missing responses and changed costs re-prompt. A wrong-tool state or changed arguments fail. Decline and cancel create no branch.
Capability-free and URL-only clients keep hash validation. A supplied legacy ID cannot bypass the capable-client flow. Project-scoped injection works, and existing output fields such as
with_dataremain.How to Review
Server and shared state
packages/mcp-server-supabase/src/server.tspackages/mcp-server-supabase/src/tools/cost-confirmation.tsBranch handler and pricing
packages/mcp-server-supabase/src/tools/branching-tools.tspackages/mcp-server-supabase/src/pricing.tsBehavioral coverage
packages/mcp-server-supabase/src/server.test.tscreate_branchenabled only through the intended server path?BranchCost?Verification
pnpm --filter @supabase/mcp-server-supabase test src/server.test.ts -t "create_(project|branch) cost confirmation via elicitation"(17 passed)pnpm --filter @supabase/mcp-server-supabase build(typecheck + build passed)pnpm test:packed-platform-consumer(3 assertions passed)pnpm exec biome ci .(passed)Additional context
Commit
24535f1 chore: refresh management API typesadds two generated lines topackages/mcp-server-supabase/src/management-api/types.tsbecause the CI generation gate detected upstream schema drift. Feature behavior and verification remain unchanged.This does not change
create_project,mcp-utils, platform adapters, stdio, pricing values, manifests, or docs.Known limits: confirmations are not single-use, legacy IDs remain precomputable, and the branch rate remains the existing package constant.
AI-assisted; human review required.