Skip to content

Commit 9decc04

Browse files
committed
fix: skip pricing confirmation for creating branch
1 parent 8430ed1 commit 9decc04

File tree

2 files changed

+12
-102
lines changed

2 files changed

+12
-102
lines changed

packages/mcp-server-supabase/src/server.test.ts

-79
Original file line numberDiff line numberDiff line change
@@ -637,22 +637,12 @@ describe('tools', () => {
637637
const { callTool } = await setup();
638638
const project = mockProjects.values().next().value!;
639639

640-
const confirm_cost_id = await callTool({
641-
name: 'confirm_cost',
642-
arguments: {
643-
type: 'branch',
644-
recurrence: 'hourly',
645-
amount: BRANCH_COST_HOURLY,
646-
},
647-
});
648-
649640
const branchName = 'test-branch';
650641
const result = await callTool({
651642
name: 'create_branch',
652643
arguments: {
653644
project_id: project.id,
654645
name: branchName,
655-
confirm_cost_id,
656646
},
657647
});
658648

@@ -673,44 +663,15 @@ describe('tools', () => {
673663
});
674664
});
675665

676-
test('create branch without cost confirmation fails', async () => {
677-
const { callTool } = await setup();
678-
679-
const project = mockProjects.values().next().value!;
680-
681-
const branchName = 'test-branch';
682-
const createBranchPromise = callTool({
683-
name: 'create_branch',
684-
arguments: {
685-
project_id: project.id,
686-
name: branchName,
687-
},
688-
});
689-
690-
await expect(createBranchPromise).rejects.toThrow(
691-
'User must confirm understanding of costs before creating a branch.'
692-
);
693-
});
694-
695666
test('delete branch', async () => {
696667
const { callTool } = await setup();
697668
const project = mockProjects.values().next().value!;
698669

699-
const confirm_cost_id = await callTool({
700-
name: 'confirm_cost',
701-
arguments: {
702-
type: 'branch',
703-
recurrence: 'hourly',
704-
amount: BRANCH_COST_HOURLY,
705-
},
706-
});
707-
708670
const branch = await callTool({
709671
name: 'create_branch',
710672
arguments: {
711673
project_id: project.id,
712674
name: 'test-branch',
713-
confirm_cost_id,
714675
},
715676
});
716677

@@ -777,21 +738,11 @@ describe('tools', () => {
777738
const { callTool } = await setup();
778739
const project = mockProjects.values().next().value!;
779740

780-
const confirm_cost_id = await callTool({
781-
name: 'confirm_cost',
782-
arguments: {
783-
type: 'branch',
784-
recurrence: 'hourly',
785-
amount: BRANCH_COST_HOURLY,
786-
},
787-
});
788-
789741
const branch = await callTool({
790742
name: 'create_branch',
791743
arguments: {
792744
project_id: project.id,
793745
name: 'test-branch',
794-
confirm_cost_id,
795746
},
796747
});
797748

@@ -836,21 +787,11 @@ describe('tools', () => {
836787
const { callTool } = await setup();
837788
const project = mockProjects.values().next().value!;
838789

839-
const confirm_cost_id = await callTool({
840-
name: 'confirm_cost',
841-
arguments: {
842-
type: 'branch',
843-
recurrence: 'hourly',
844-
amount: BRANCH_COST_HOURLY,
845-
},
846-
});
847-
848790
const branch = await callTool({
849791
name: 'create_branch',
850792
arguments: {
851793
project_id: project.id,
852794
name: 'test-branch',
853-
confirm_cost_id,
854795
},
855796
});
856797

@@ -900,21 +841,11 @@ describe('tools', () => {
900841
const { callTool } = await setup();
901842
const project = mockProjects.values().next().value!;
902843

903-
const confirm_cost_id = await callTool({
904-
name: 'confirm_cost',
905-
arguments: {
906-
type: 'branch',
907-
recurrence: 'hourly',
908-
amount: BRANCH_COST_HOURLY,
909-
},
910-
});
911-
912844
const branch = await callTool({
913845
name: 'create_branch',
914846
arguments: {
915847
project_id: project.id,
916848
name: 'test-branch',
917-
confirm_cost_id,
918849
},
919850
});
920851

@@ -988,21 +919,11 @@ describe('tools', () => {
988919
const { callTool } = await setup();
989920
const project = mockProjects.values().next().value!;
990921

991-
const confirm_cost_id = await callTool({
992-
name: 'confirm_cost',
993-
arguments: {
994-
type: 'branch',
995-
recurrence: 'hourly',
996-
amount: BRANCH_COST_HOURLY,
997-
},
998-
});
999-
1000922
const branch = await callTool({
1001923
name: 'create_branch',
1002924
arguments: {
1003925
project_id: project.id,
1004926
name: 'test-branch',
1005-
confirm_cost_id,
1006927
},
1007928
});
1008929

packages/mcp-server-supabase/src/server.ts

+12-23
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ import {
1313
type ManagementApiClient,
1414
} from './management-api/index.js';
1515
import { generatePassword } from './password.js';
16-
import { getBranchCost, getNextProjectCost, type Cost } from './pricing.js';
16+
import {
17+
BRANCH_COST_HOURLY,
18+
getBranchCost,
19+
getNextProjectCost,
20+
type Cost,
21+
} from './pricing.js';
1722
import {
1823
AWS_REGION_CODES,
1924
getClosestAwsRegion,
@@ -124,7 +129,7 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
124129
}),
125130
get_cost: tool({
126131
description:
127-
'Gets the cost of creating a new project or branch. Never assume organization as costs can be different for each.',
132+
'Gets the cost of creating a new project. Never assume organization when creating a project as costs can be different for each.',
128133
parameters: z.object({
129134
type: z.enum(['project', 'branch']),
130135
organization_id: z
@@ -154,7 +159,7 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
154159
}),
155160
confirm_cost: tool({
156161
description:
157-
'Ask the user to confirm their understanding of the cost of creating a new project or branch. Call `get_cost` first. Returns a unique ID for this confirmation which should be passed to `create_project` or `create_branch`.',
162+
'Ask the user to confirm their understanding of the cost of creating a new project. Call `get_cost` first. Returns a unique ID for this confirmation which should be passed to `create_project`.',
158163
parameters: z.object({
159164
type: z.enum(['project', 'branch']),
160165
recurrence: z.enum(['hourly', 'monthly']),
@@ -504,33 +509,17 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
504509

505510
// Experimental features
506511
create_branch: tool({
507-
description:
508-
'Creates a development branch on a Supabase project. This will apply all migrations from the main project to a fresh branch database. Note that production data will not carry over. The branch will get its own project_id via the resulting project_ref. Use this ID to execute queries and migrations on the branch.',
512+
description: `Creates a development branch on a Supabase project. This will apply all migrations from the main project to a fresh branch database. Note that production data will not carry over. The branch will get its own project_id via the resulting project_ref. Use this ID to execute queries and migrations on the branch.
513+
514+
The cost of each active branch is $${BRANCH_COST_HOURLY} per hour. Always show this to the user before creating a branch and suggest deleting any unused branches to avoid incurring extra charges.`,
509515
parameters: z.object({
510516
project_id: z.string(),
511517
name: z
512518
.string()
513519
.default('develop')
514520
.describe('Name of the branch to create'),
515-
confirm_cost_id: z
516-
.string()
517-
.describe('The cost confirmation ID. Call `confirm_cost` first.'),
518521
}),
519-
execute: async ({ project_id, name, confirm_cost_id }) => {
520-
if (!confirm_cost_id) {
521-
throw new Error(
522-
'User must confirm understanding of costs before creating a branch.'
523-
);
524-
}
525-
526-
const cost = getBranchCost();
527-
const costHash = await hashObject(cost);
528-
if (costHash !== confirm_cost_id) {
529-
throw new Error(
530-
'Cost confirmation ID does not match the expected cost of creating a branch.'
531-
);
532-
}
533-
522+
execute: async ({ project_id, name }) => {
534523
const createBranchResponse = await managementApiClient.POST(
535524
'/v1/projects/{ref}/branches',
536525
{

0 commit comments

Comments
 (0)