Skip to content

Commit 0c100bc

Browse files
committed
feat: support branching workflow via mcp
1 parent ba13b18 commit 0c100bc

File tree

2 files changed

+175
-5
lines changed

2 files changed

+175
-5
lines changed

packages/mcp-server-supabase/src/management-api/types.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,9 @@ export interface components {
13461346
/** @enum {string} */
13471347
message: "ok";
13481348
};
1349+
BranchActionBody: {
1350+
migration_version?: string;
1351+
};
13491352
BranchUpdateResponse: {
13501353
workflow_run_id: string;
13511354
/** @enum {string} */
@@ -2364,6 +2367,10 @@ export interface components {
23642367
version: string;
23652368
name?: string;
23662369
}[];
2370+
V1CreateMigrationBody: {
2371+
query: string;
2372+
name?: string;
2373+
};
23672374
V1RunQueryBody: {
23682375
query: string;
23692376
};
@@ -2705,7 +2712,11 @@ export interface operations {
27052712
};
27062713
cookie?: never;
27072714
};
2708-
requestBody?: never;
2715+
requestBody: {
2716+
content: {
2717+
"application/json": components["schemas"]["BranchActionBody"];
2718+
};
2719+
};
27092720
responses: {
27102721
201: {
27112722
headers: {
@@ -2733,7 +2744,11 @@ export interface operations {
27332744
};
27342745
cookie?: never;
27352746
};
2736-
requestBody?: never;
2747+
requestBody: {
2748+
content: {
2749+
"application/json": components["schemas"]["BranchActionBody"];
2750+
};
2751+
};
27372752
responses: {
27382753
201: {
27392754
headers: {
@@ -2761,7 +2776,11 @@ export interface operations {
27612776
};
27622777
cookie?: never;
27632778
};
2764-
requestBody?: never;
2779+
requestBody: {
2780+
content: {
2781+
"application/json": components["schemas"]["BranchActionBody"];
2782+
};
2783+
};
27652784
responses: {
27662785
201: {
27672786
headers: {
@@ -5310,7 +5329,11 @@ export interface operations {
53105329
};
53115330
cookie?: never;
53125331
};
5313-
requestBody?: never;
5332+
requestBody: {
5333+
content: {
5334+
"application/json": components["schemas"]["V1CreateMigrationBody"];
5335+
};
5336+
};
53145337
responses: {
53155338
200: {
53165339
headers: {

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

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
267267
name,
268268
query,
269269
},
270-
} as any // TODO: remove once API spec updated to include body
270+
}
271271
);
272272

273273
assertSuccess(response, 'Failed to apply migration');
@@ -345,6 +345,153 @@ export function createSupabaseMcpServer(options: SupabaseMcpServerOptions) {
345345

346346
assertSuccess(response, 'Failed to fetch TypeScript types');
347347

348+
return response.data;
349+
},
350+
}),
351+
// Experimental features
352+
create_branch: tool({
353+
description:
354+
'Creates a development branch with migrations from production project.',
355+
parameters: z.object({
356+
project_id: z.string(),
357+
name: z
358+
.string()
359+
.default('develop')
360+
.describe('Name of the branch to create'),
361+
}),
362+
execute: async ({ project_id, name }) => {
363+
const response = await managementApiClient.POST(
364+
'/v1/projects/{ref}/branches',
365+
{
366+
params: {
367+
path: {
368+
ref: project_id,
369+
},
370+
},
371+
body: {
372+
branch_name: name,
373+
},
374+
}
375+
);
376+
377+
assertSuccess(response, 'Failed to create branch');
378+
379+
return response.data;
380+
},
381+
}),
382+
list_branches: tool({
383+
description: 'Lists all development branches.',
384+
parameters: z.object({
385+
project_id: z.string(),
386+
}),
387+
execute: async ({ project_id }) => {
388+
const response = await managementApiClient.GET(
389+
'/v1/projects/{ref}/branches',
390+
{
391+
params: {
392+
path: {
393+
ref: project_id,
394+
},
395+
},
396+
}
397+
);
398+
399+
assertSuccess(response, 'Failed to list branches');
400+
401+
return response.data;
402+
},
403+
}),
404+
delete_branch: tool({
405+
description: 'Deletes a development branch.',
406+
parameters: z.object({
407+
branch_id: z.string(),
408+
}),
409+
execute: async ({ branch_id }) => {
410+
const response = await managementApiClient.DELETE(
411+
'/v1/branches/{branch_id}',
412+
{
413+
params: {
414+
path: {
415+
branch_id,
416+
},
417+
},
418+
}
419+
);
420+
421+
assertSuccess(response, 'Failed to delete branch');
422+
423+
return response.data;
424+
},
425+
}),
426+
merge_branch: tool({
427+
description:
428+
'Merges migrations and edge functions from a development branch to production.',
429+
parameters: z.object({
430+
branch_id: z.string(),
431+
}),
432+
execute: async ({ branch_id }) => {
433+
const response = await managementApiClient.POST(
434+
'/v1/branches/{branch_id}/merge',
435+
{
436+
params: {
437+
path: {
438+
branch_id,
439+
},
440+
},
441+
body: {},
442+
}
443+
);
444+
445+
assertSuccess(response, 'Failed to merge branch');
446+
447+
return response.data;
448+
},
449+
}),
450+
reset_branch: tool({
451+
description:
452+
'Resets migrations on a development branch to a prior version.',
453+
parameters: z.object({
454+
branch_id: z.string(),
455+
}),
456+
execute: async ({ branch_id }) => {
457+
const response = await managementApiClient.POST(
458+
'/v1/branches/{branch_id}/reset',
459+
{
460+
params: {
461+
path: {
462+
branch_id,
463+
},
464+
},
465+
body: {},
466+
}
467+
);
468+
469+
assertSuccess(response, 'Failed to reset branch');
470+
471+
return response.data;
472+
},
473+
}),
474+
rebase_branch: tool({
475+
description:
476+
'Rebases development branch back on production in case it drifted.',
477+
parameters: z.object({
478+
branchId: z.string(),
479+
}),
480+
execute: async ({ branchId }) => {
481+
const response = await managementApiClient.POST(
482+
'/v1/branches/{branch_id}/push',
483+
{
484+
params: {
485+
path: {
486+
branch_id: branchId,
487+
},
488+
},
489+
body: {},
490+
}
491+
);
492+
493+
assertSuccess(response, 'Failed to rebase branch');
494+
348495
return response.data;
349496
},
350497
}),

0 commit comments

Comments
 (0)