• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase-community / supabase-mcp / 16727694595

04 Aug 2025 03:41PM UTC coverage: 96.357% (+0.03%) from 96.328%
16727694595

push

github

web-flow
Merge pull request #119 from supabase-community/charis/user-agent

fix: add user-agent string to content api requests

225 of 244 branches covered (92.21%)

Branch coverage included in aggregate %.

17 of 17 new or added lines in 3 files covered. (100.0%)

2076 of 2144 relevant lines covered (96.83%)

34.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.58
/packages/mcp-server-supabase/src/tools/account-tools.ts
1
import { tool } from '@supabase/mcp-utils';
2✔
2
import { z } from 'zod';
3
import type { SupabasePlatform } from '../platform/types.js';
4
import { type Cost, getBranchCost, getNextProjectCost } from '../pricing.js';
5
import { AWS_REGION_CODES } from '../regions.js';
6
import { hashObject } from '../util.js';
7

8
export type AccountToolsOptions = {
9
  platform: SupabasePlatform;
10
};
11

12
export function getAccountTools({ platform }: AccountToolsOptions) {
2✔
13
  return {
95✔
14
    list_organizations: tool({
95✔
15
      description: 'Lists all organizations that the user is a member of.',
95✔
16
      parameters: z.object({}),
95✔
17
      execute: async () => {
95✔
18
        return await platform.listOrganizations();
2✔
19
      },
2✔
20
    }),
95✔
21
    get_organization: tool({
95✔
22
      description:
95✔
23
        'Gets details for an organization. Includes subscription plan.',
95✔
24
      parameters: z.object({
95✔
25
        id: z.string().describe('The organization ID'),
95✔
26
      }),
95✔
27
      execute: async ({ id: organizationId }) => {
95✔
28
        return await platform.getOrganization(organizationId);
1✔
29
      },
1✔
30
    }),
95✔
31
    list_projects: tool({
95✔
32
      description:
95✔
33
        'Lists all Supabase projects for the user. Use this to help discover the project ID of the project that the user is working on.',
95✔
34
      parameters: z.object({}),
95✔
35
      execute: async () => {
95✔
36
        return await platform.listProjects();
2✔
37
      },
2✔
38
    }),
95✔
39
    get_project: tool({
95✔
40
      description: 'Gets details for a Supabase project.',
95✔
41
      parameters: z.object({
95✔
42
        id: z.string().describe('The project ID'),
95✔
43
      }),
95✔
44
      execute: async ({ id }) => {
95✔
45
        return await platform.getProject(id);
2✔
46
      },
2✔
47
    }),
95✔
48
    get_cost: tool({
95✔
49
      description:
95✔
50
        'Gets the cost of creating a new project or branch. Never assume organization as costs can be different for each.',
95✔
51
      parameters: z.object({
95✔
52
        type: z.enum(['project', 'branch']),
95✔
53
        organization_id: z
95✔
54
          .string()
95✔
55
          .describe('The organization ID. Always ask the user.'),
95✔
56
      }),
95✔
57
      execute: async ({ type, organization_id }) => {
95✔
58
        function generateResponse(cost: Cost) {
5✔
59
          return `The new ${type} will cost $${cost.amount} ${cost.recurrence}. You must repeat this to the user and confirm their understanding.`;
5✔
60
        }
5✔
61
        switch (type) {
5✔
62
          case 'project': {
5✔
63
            const cost = await getNextProjectCost(platform, organization_id);
4✔
64
            return generateResponse(cost);
4✔
65
          }
4✔
66
          case 'branch': {
5✔
67
            const cost = getBranchCost();
1✔
68
            return generateResponse(cost);
1✔
69
          }
1✔
70
          default:
5✔
71
            throw new Error(`Unknown cost type: ${type}`);
×
72
        }
5✔
73
      },
5✔
74
    }),
95✔
75
    confirm_cost: tool({
95✔
76
      description:
95✔
77
        '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`.',
95✔
78
      parameters: z.object({
95✔
79
        type: z.enum(['project', 'branch']),
95✔
80
        recurrence: z.enum(['hourly', 'monthly']),
95✔
81
        amount: z.number(),
95✔
82
      }),
95✔
83
      execute: async (cost) => {
95✔
84
        return await hashObject(cost);
8✔
85
      },
8✔
86
    }),
95✔
87
    create_project: tool({
95✔
88
      description:
95✔
89
        'Creates a new Supabase project. Always ask the user which organization to create the project in. The project can take a few minutes to initialize - use `get_project` to check the status.',
95✔
90
      parameters: z.object({
95✔
91
        name: z.string().describe('The name of the project'),
95✔
92
        region: z.optional(
95✔
93
          z
95✔
94
            .enum(AWS_REGION_CODES)
95✔
95
            .describe(
95✔
96
              'The region to create the project in. Defaults to the closest region.'
95✔
97
            )
95✔
98
        ),
95✔
99
        organization_id: z.string(),
95✔
100
        confirm_cost_id: z
95✔
101
          .string({
95✔
102
            required_error:
95✔
103
              'User must confirm understanding of costs before creating a project.',
95✔
104
          })
95✔
105
          .describe('The cost confirmation ID. Call `confirm_cost` first.'),
95✔
106
      }),
95✔
107
      execute: async ({ name, region, organization_id, confirm_cost_id }) => {
95✔
108
        const cost = await getNextProjectCost(platform, organization_id);
2✔
109
        const costHash = await hashObject(cost);
2✔
110
        if (costHash !== confirm_cost_id) {
2✔
111
          throw new Error(
×
112
            'Cost confirmation ID does not match the expected cost of creating a project.'
×
113
          );
×
114
        }
×
115

116
        return await platform.createProject({
2✔
117
          name,
2✔
118
          region,
2✔
119
          organization_id,
2✔
120
        });
2✔
121
      },
2✔
122
    }),
95✔
123
    pause_project: tool({
95✔
124
      description: 'Pauses a Supabase project.',
95✔
125
      parameters: z.object({
95✔
126
        project_id: z.string(),
95✔
127
      }),
95✔
128
      execute: async ({ project_id }) => {
95✔
129
        return await platform.pauseProject(project_id);
1✔
130
      },
1✔
131
    }),
95✔
132
    restore_project: tool({
95✔
133
      description: 'Restores a Supabase project.',
95✔
134
      parameters: z.object({
95✔
135
        project_id: z.string(),
95✔
136
      }),
95✔
137
      execute: async ({ project_id }) => {
95✔
138
        return await platform.restoreProject(project_id);
1✔
139
      },
1✔
140
    }),
95✔
141
  };
95✔
142
}
95✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc