(
{
projectRef,
connectionString,
@@ -152,7 +154,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse) {
'Content-Type': 'application/json',
...(authorization && { Authorization: authorization }),
},
- IS_PLATFORM ? undefined : queryPgMetaSelfHosted
+ IS_PLATFORM ? undefined : executeQuery
)
: { result: [] }
diff --git a/apps/studio/pages/api/mcp/index.ts b/apps/studio/pages/api/mcp/index.ts
new file mode 100644
index 0000000000000..d57898fe4907e
--- /dev/null
+++ b/apps/studio/pages/api/mcp/index.ts
@@ -0,0 +1,76 @@
+import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
+import { createSupabaseMcpServer, SupabasePlatform } from '@supabase/mcp-server-supabase'
+import { stripIndent } from 'common-tags'
+import { commaSeparatedStringIntoArray, fromNodeHeaders } from 'lib/api/apiHelpers'
+import { getDatabaseOperations } from 'lib/api/self-hosted/mcp'
+import { DEFAULT_PROJECT } from 'lib/constants/api'
+import { NextApiRequest, NextApiResponse } from 'next'
+import { z } from 'zod'
+
+const supportedFeatureGroupSchema = z.enum(['docs', 'database'])
+
+const mcpQuerySchema = z.object({
+ features: z
+ .string()
+ .transform(commaSeparatedStringIntoArray)
+ .optional()
+ .describe(
+ stripIndent`
+ A comma-separated list of feature groups to filter tools by. If not provided, all tools are available.
+
+ The following feature groups are supported: ${supportedFeatureGroupSchema.options.map((group) => `\`${group}\``).join(', ')}.
+ `
+ )
+ .pipe(z.array(supportedFeatureGroupSchema).optional()),
+})
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ switch (req.method) {
+ case 'POST':
+ return handlePost(req, res)
+ default:
+ res.setHeader('Allow', ['POST'])
+ return res.status(405).json({ error: { message: `Method ${req.method} Not Allowed` } })
+ }
+}
+
+async function handlePost(req: NextApiRequest, res: NextApiResponse) {
+ const { error, data } = mcpQuerySchema.safeParse(req.query)
+
+ if (error) {
+ return res.status(400).json({ error: error.flatten().fieldErrors })
+ }
+
+ const { features } = data
+ const headers = fromNodeHeaders(req.headers)
+
+ const platform: SupabasePlatform = {
+ database: getDatabaseOperations({ headers }),
+ }
+
+ try {
+ const server = createSupabaseMcpServer({
+ platform,
+ projectId: DEFAULT_PROJECT.ref,
+ features,
+ })
+
+ const transport = new StreamableHTTPServerTransport({
+ sessionIdGenerator: undefined, // Stateless, don't use session management
+ enableJsonResponse: true, // Stateless, discourage SSE streams
+ })
+
+ await server.connect(transport)
+ await transport.handleRequest(req, res, req.body)
+ } catch (error) {
+ // Errors at this point will be due MCP setup issues
+ // Future errors will be handled at the JSON-RPC level within the MCP protocol
+ if (error instanceof Error) {
+ return res.status(400).json({ error: error.message })
+ }
+
+ return res.status(500).json({ error: 'Unable to process MCP request', cause: error })
+ }
+}
+
+export default handler
diff --git a/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts b/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts
index 3a88a32927d03..f52341b9c83df 100644
--- a/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts
+++ b/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts
@@ -1,7 +1,6 @@
-import { fetchPost } from 'data/fetchers'
import { constructHeaders } from 'lib/api/apiHelpers'
import apiWrapper from 'lib/api/apiWrapper'
-import { PG_META_URL } from 'lib/constants'
+import { executeQuery } from 'lib/api/self-hosted/query'
import { NextApiRequest, NextApiResponse } from 'next'
export default (req: NextApiRequest, res: NextApiResponse) =>
@@ -22,12 +21,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const handlePost = async (req: NextApiRequest, res: NextApiResponse) => {
const { query } = req.body
const headers = constructHeaders(req.headers)
- const response = await fetchPost(`${PG_META_URL}/query`, { query }, { headers })
+ const { data, error } = await executeQuery({ query, headers })
- if (response.error) {
- const { code, message } = response.error
- return res.status(code).json({ message, formattedError: message })
+ if (error) {
+ const { code, message } = error
+ return res.status(code ?? 500).json({ message, formattedError: message })
} else {
- return res.status(200).json(response)
+ return res.status(200).json(data)
}
}
diff --git a/apps/studio/pages/api/v1/projects/[ref]/database/migrations.ts b/apps/studio/pages/api/v1/projects/[ref]/database/migrations.ts
index 22d43e313b6d8..57b65860d7fcd 100644
--- a/apps/studio/pages/api/v1/projects/[ref]/database/migrations.ts
+++ b/apps/studio/pages/api/v1/projects/[ref]/database/migrations.ts
@@ -1,10 +1,8 @@
import { NextApiRequest, NextApiResponse } from 'next'
-import { fetchPost } from 'data/fetchers'
import { constructHeaders } from 'lib/api/apiHelpers'
import apiWrapper from 'lib/api/apiWrapper'
-import { PG_META_URL } from 'lib/constants'
-import { makeRandomString } from 'lib/helpers'
+import { applyAndTrackMigrations, listMigrationVersions } from 'lib/api/self-hosted/migrations'
export default (req: NextApiRequest, res: NextApiResponse) =>
apiWrapper(req, res, handler, { withAuth: true })
@@ -22,79 +20,29 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(405).json({ error: { message: `Method ${method} Not Allowed` } })
}
}
-const listMigrationVersions =
- 'select version, name from supabase_migrations.schema_migrations order by version'
const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
const headers = constructHeaders(req.headers)
+ const { data, error } = await listMigrationVersions(headers)
- const response = await fetchPost(
- `${PG_META_URL}/query`,
- { query: listMigrationVersions },
- { headers }
- )
-
- if (response.error) {
- const { code, message } = response.error
- return res.status(code).json({ message })
+ if (error) {
+ const { code, message } = error
+ return res.status(code ?? 500).json({ message })
} else {
- return res.status(200).json(response)
+ return res.status(200).json(data)
}
}
-export const initialiseHistoryTable = `begin;
-
-create schema if not exists supabase_migrations;
-create table if not exists supabase_migrations.schema_migrations (version text not null primary key);
-alter table supabase_migrations.schema_migrations add column if not exists statements text[];
-alter table supabase_migrations.schema_migrations add column if not exists name text;
-
-commit;`
-
-export function applyAndTrackMigrations(query: string, name?: string) {
- // Escapes literals using postgres dollar quoted string
- const dollar = `$${makeRandomString(20)}$`
- const quote = (s?: string) => (s ? dollar + s + dollar : `''`)
- return `begin;
-
--- apply sql from post body
-${query};
-
--- track statements in history table
-insert into supabase_migrations.schema_migrations (version, name, statements)
-values (
- to_char(current_timestamp, 'YYYYMMDDHHMISS'),
- ${quote(name)},
- array[${quote(query)}]
-);
-
-commit;`
-}
-
const handlePost = async (req: NextApiRequest, res: NextApiResponse) => {
const headers = constructHeaders(req.headers)
+ const { query, name } = req.body
+
+ const { data, error } = await applyAndTrackMigrations({ query, name, headers })
- const { error } = await fetchPost(
- `${PG_META_URL}/query`,
- { query: initialiseHistoryTable },
- { headers }
- )
if (error) {
const { code, message } = error
- return res.status(code).json({ message, formattedError: message })
- }
-
- const { query, name } = req.body
- const response = await fetchPost(
- `${PG_META_URL}/query`,
- { query: applyAndTrackMigrations(query, name) },
- { headers }
- )
-
- if (response.error) {
- const { code, message } = response.error
- return res.status(code).json({ message, formattedError: message })
+ return res.status(code ?? 500).json({ message, formattedError: message })
} else {
- return res.status(200).json(response)
+ return res.status(200).json(data)
}
}
diff --git a/apps/studio/pages/project/[ref]/editor/index.tsx b/apps/studio/pages/project/[ref]/editor/index.tsx
index 6133db86b6629..9d1d533a775a2 100644
--- a/apps/studio/pages/project/[ref]/editor/index.tsx
+++ b/apps/studio/pages/project/[ref]/editor/index.tsx
@@ -2,6 +2,7 @@ import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { useParams } from 'common'
+import { LOAD_TAB_FROM_CACHE_PARAM } from 'components/grid/SupabaseGrid.utils'
import SidePanelEditor from 'components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor'
import DefaultLayout from 'components/layouts/DefaultLayout'
import { EditorBaseLayout } from 'components/layouts/editors/EditorBaseLayout'
@@ -31,10 +32,15 @@ const TableEditorPage: NextPageWithLayout = () => {
// Handle redirect to last opened table tab, or last table tab
if (lastOpenedTable !== undefined) {
- router.push(`/project/${projectRef}/editor/${history.editor}`)
+ router.push(
+ `/project/${projectRef}/editor/${history.editor}?${LOAD_TAB_FROM_CACHE_PARAM}=true`
+ )
} else if (lastTabId) {
const lastTab = tabStore.tabsMap[lastTabId]
- if (lastTab) router.push(`/project/${projectRef}/editor/${lastTab.metadata?.tableId}`)
+ if (lastTab)
+ router.push(
+ `/project/${projectRef}/editor/${lastTab.metadata?.tableId}?${LOAD_TAB_FROM_CACHE_PARAM}=true`
+ )
}
}
}, [isHistoryLoaded])
diff --git a/apps/studio/pages/project/[ref]/reports/database.tsx b/apps/studio/pages/project/[ref]/reports/database.tsx
index c5314558f909a..1e9c5ea0730e2 100644
--- a/apps/studio/pages/project/[ref]/reports/database.tsx
+++ b/apps/studio/pages/project/[ref]/reports/database.tsx
@@ -42,6 +42,8 @@ import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import type { NextPageWithLayout } from 'types'
import { AlertDescription_Shadcn_, Alert_Shadcn_, Button } from 'ui'
import { ReportChartUpsell } from 'components/interfaces/Reports/v2/ReportChartUpsell'
+import { POOLING_OPTIMIZATIONS } from 'components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.constants'
+import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
const DatabaseReport: NextPageWithLayout = () => {
return (
@@ -107,6 +109,16 @@ const DatabaseUsage = () => {
})
const { data: poolerConfig } = usePgbouncerConfigQuery({ projectRef: project?.ref })
+ // PGBouncer connections
+ const { data: addons } = useProjectAddonsQuery({ projectRef: project?.ref })
+ const computeInstance = addons?.selected_addons.find((addon) => addon.type === 'compute_instance')
+ const poolingOptimizations =
+ POOLING_OPTIMIZATIONS[
+ (computeInstance?.variant.identifier as keyof typeof POOLING_OPTIMIZATIONS) ??
+ (project?.infra_compute_size === 'nano' ? 'ci_nano' : 'ci_micro')
+ ]
+ const defaultMaxClientConn = poolingOptimizations.maxClientConn ?? 200
+
const { can: canUpdateDiskSizeConfig } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'projects',
@@ -117,19 +129,13 @@ const DatabaseUsage = () => {
}
)
- const REPORT_ATTRIBUTES = getReportAttributes(
- org!,
- project!,
- diskConfig,
- maxConnections,
- poolerConfig
- )
+ const REPORT_ATTRIBUTES = getReportAttributes(diskConfig)
const REPORT_ATTRIBUTES_V2 = getReportAttributesV2(
org!,
project!,
diskConfig,
maxConnections,
- poolerConfig
+ defaultMaxClientConn
)
const { isLoading: isUpdatingDiskSize } = useProjectDiskResizeMutation({
diff --git a/apps/studio/state/tabs.tsx b/apps/studio/state/tabs.tsx
index 348528335f31b..f7ddd272e5dc5 100644
--- a/apps/studio/state/tabs.tsx
+++ b/apps/studio/state/tabs.tsx
@@ -1,3 +1,4 @@
+import { LOAD_TAB_FROM_CACHE_PARAM } from 'components/grid/SupabaseGrid.utils'
import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { partition } from 'lodash'
@@ -286,7 +287,7 @@ function createTabsState(projectRef: string) {
case 'f':
case 'p':
router.push(
- `/project/${router.query.ref}/editor/${tab.metadata?.tableId}?schema=${tab.metadata?.schema}`
+ `/project/${router.query.ref}/editor/${tab.metadata?.tableId}?schema=${tab.metadata?.schema}&${LOAD_TAB_FROM_CACHE_PARAM}=true`
)
break
}
diff --git a/apps/studio/tests/pages/api/mcp/index.test.ts b/apps/studio/tests/pages/api/mcp/index.test.ts
new file mode 100644
index 0000000000000..a7ed2d428e7a2
--- /dev/null
+++ b/apps/studio/tests/pages/api/mcp/index.test.ts
@@ -0,0 +1,78 @@
+import { describe, it, expect, beforeEach } from 'vitest'
+import { createMocks } from 'node-mocks-http'
+import { mswServer } from 'tests/lib/msw'
+import handler from '../../../../pages/api/mcp/index'
+
+describe('/api/mcp', () => {
+ beforeEach(() => {
+ // Disable MSW for these tests
+ mswServer.close()
+ })
+
+ describe('Method handling', async () => {
+ it('should handle POST requests', async () => {
+ const { req, res } = createMocks({
+ method: 'POST',
+ query: {},
+ body: {},
+ })
+
+ await handler(req, res)
+
+ expect(res._getStatusCode()).not.toBe(405)
+ })
+
+ it('should return 405 for non-POST methods', async () => {
+ const { req, res } = createMocks({
+ method: 'GET',
+ })
+
+ await handler(req, res)
+
+ expect(res._getStatusCode()).toBe(405)
+ expect(JSON.parse(res._getData())).toEqual({
+ error: { message: 'Method GET Not Allowed' },
+ })
+ expect(res._getHeaders()).toEqual({ allow: ['POST'], 'content-type': 'application/json' })
+ })
+ })
+
+ describe('Query validation', async () => {
+ it('should accept valid feature groups', async () => {
+ const { req, res } = createMocks({
+ method: 'POST',
+ query: { features: 'docs,database' },
+ body: {},
+ })
+
+ await handler(req, res)
+
+ expect(res._getStatusCode()).not.toBe(400)
+ })
+
+ it('should reject invalid feature groups', async () => {
+ const { req, res } = createMocks({
+ method: 'POST',
+ query: { features: 'invalid,unknown' },
+ body: {},
+ })
+
+ await handler(req, res)
+
+ expect(res._getStatusCode()).toBe(400)
+ expect(JSON.parse(res._getData())).toHaveProperty('error')
+ })
+
+ it('should work without features parameter', async () => {
+ const { req, res } = createMocks({
+ method: 'POST',
+ query: {},
+ body: {},
+ })
+
+ await handler(req, res)
+
+ expect(res._getStatusCode()).not.toBe(400)
+ })
+ })
+})
diff --git a/apps/www/components/Forms/ApplyToSupaSquadForm.tsx b/apps/www/components/Forms/ApplyToSupaSquadForm.tsx
index 498418badc97e..e57df832a626b 100644
--- a/apps/www/components/Forms/ApplyToSupaSquadForm.tsx
+++ b/apps/www/components/Forms/ApplyToSupaSquadForm.tsx
@@ -75,6 +75,7 @@ const tracks: Track[] = [
const productAreasOfInterest: string[] = [
'Auth',
+ 'AI Builders',
'Branching',
'Client libraries',
'Database / Postgres',
diff --git a/apps/www/components/Supasquad/FeatureIcon.tsx b/apps/www/components/Supasquad/FeatureIcon.tsx
index a312031c38ee5..e873f0c67bd63 100644
--- a/apps/www/components/Supasquad/FeatureIcon.tsx
+++ b/apps/www/components/Supasquad/FeatureIcon.tsx
@@ -4,6 +4,7 @@ import { cn } from 'ui'
import type { Feature } from '~/data/open-source/contributing/supasquad.utils'
import {
Award,
+ Bot,
Zap,
MessageSquare,
DollarSign,
@@ -13,10 +14,12 @@ import {
LifeBuoy,
Wrench,
Shield,
+ Lock,
} from 'lucide-react'
const ICONS = {
award: Award,
+ bot: Bot,
zap: Zap,
'message-square': MessageSquare,
'dollar-sign': DollarSign,
@@ -26,6 +29,7 @@ const ICONS = {
'life-buoy': LifeBuoy,
wrench: Wrench,
shield: Shield,
+ lock: Lock,
} as const
type IconName = keyof typeof ICONS
diff --git a/apps/www/data/open-source/contributing/supasquad.tsx b/apps/www/data/open-source/contributing/supasquad.tsx
index 7897c9dd98c9f..41ce63e044fc2 100644
--- a/apps/www/data/open-source/contributing/supasquad.tsx
+++ b/apps/www/data/open-source/contributing/supasquad.tsx
@@ -1,4 +1,4 @@
-import { Image } from 'ui'
+import { Badge, Image } from 'ui'
import { companyStats } from '~/data/company-stats'
export const data = {
@@ -147,6 +147,43 @@ export const data = {
},
],
},
+ featured: {
+ id: 'featured',
+ label: '',
+ heading: (
+ <>
+ Featured
+ We're especially looking for
+ >
+ ),
+ subheading:
+ "These are the areas where we need the most help right now. If you have expertise in any of these domains, we'd love to hear from you!",
+ features: [
+ {
+ id: 'ai-builders',
+ icon: 'bot',
+ heading: (
+
+ AI Builders High Priority
+
+ ),
+ subheading:
+ "Help our users who are building with AI + Supabase. If you've vibed a bunch of projects but understand what's happening under the hood, we'd love to talke with you .",
+ },
+
+ {
+ id: 'realtime',
+ icon: 'zap',
+ heading: (
+
+ Realtime High Priority
+
+ ),
+ subheading:
+ 'Help the team by writing docs, creating examples, and making sure our guides are up to date. Experience with React and friends is an extra bonus.',
+ },
+ ],
+ },
benefits: {
id: 'benefits',
heading: Benefits for our members,
diff --git a/apps/www/pages/open-source/contributing/supasquad.tsx b/apps/www/pages/open-source/contributing/supasquad.tsx
index fd1da161f31f1..bd20b0a78cda2 100644
--- a/apps/www/pages/open-source/contributing/supasquad.tsx
+++ b/apps/www/pages/open-source/contributing/supasquad.tsx
@@ -6,9 +6,10 @@ import Layout from 'components/Layouts/Default'
import ProductHeader from 'components/Sections/ProductHeader2'
import { data as content } from 'data/open-source/contributing/supasquad'
+import { Separator } from 'ui'
-const Quotes = dynamic(() => import('components/Supasquad/Quotes'))
const WhySupaSquad = dynamic(() => import('components/Supasquad/FeaturesSection'))
+const FeaturedSection = dynamic(() => import('components/Supasquad/FeaturesSection'))
const PerfectTiming = dynamic(() => import('components/Supasquad/PerfectTiming'))
const Benefits = dynamic(() => import('components/Supasquad/FeaturesSection'))
const ApplicationFormSection = dynamic(() => import('components/Supasquad/ApplicationFormSection'))
@@ -32,7 +33,11 @@ const BeginnersPage: NextPage = () => {
sectionContainerClassName="lg:gap-4"
/>
{/* */}
+
+
+
+
=18'}
'@monaco-editor/loader@1.4.0':
@@ -8115,13 +8124,16 @@ packages:
'@supabase/functions-js@2.4.4':
resolution: {integrity: sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==}
- '@supabase/mcp-server-supabase@0.4.4':
- resolution: {integrity: sha512-GYgd4R+TTnQICjLxmdW0RRQREqG8Ix+1f9D8kroPASt25p/F60ohD8jPx53l7ym3qjb05Jy5tpJW2pss+ifV5g==}
+ '@supabase/mcp-server-supabase@0.5.5':
+ resolution: {integrity: sha512-te1XM2i+h3NBUgJ/8z9PkNCKaJ268VzFI3Qx5RA97s8eGtH94NyPy3lOIZAh3BFAOFHDpcB7Mn1b0oCTGFxg5g==}
hasBin: true
'@supabase/mcp-utils@0.2.1':
resolution: {integrity: sha512-T3LEAEKXOxHGVzhPvxqbAYbxluUKNxQpFnYVyRIazQJOQzZ03tCg+pp3LUYQi0HkWPIo+u+AgtULJVEvgeNr/Q==}
+ '@supabase/mcp-utils@0.2.2':
+ resolution: {integrity: sha512-hg4IR1iw2k3zdCiB5abvROSsVK/rOdUoyai3N97uG7c3NSQjWp0M6xPJEoH4TJE63pwY0oTc4eQAjXSmTlNK4Q==}
+
'@supabase/node-fetch@2.6.15':
resolution: {integrity: sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==}
engines: {node: 4.x || >=6.0.0}
@@ -9239,6 +9251,10 @@ packages:
abstract-logging@2.0.1:
resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
+ accepts@1.3.8:
+ resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+ engines: {node: '>= 0.6'}
+
accepts@2.0.0:
resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
engines: {node: '>= 0.6'}
@@ -10196,6 +10212,10 @@ packages:
constant-case@3.0.4:
resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==}
+ content-disposition@0.5.4:
+ resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
+ engines: {node: '>= 0.6'}
+
content-disposition@1.0.0:
resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
engines: {node: '>= 0.6'}
@@ -10682,6 +10702,10 @@ packages:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'}
+ depd@1.1.2:
+ resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
+ engines: {node: '>= 0.6'}
+
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
@@ -13677,6 +13701,10 @@ packages:
peerDependencies:
esbuild: ^0.25.2
+ media-typer@0.3.0:
+ resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
+ engines: {node: '>= 0.6'}
+
media-typer@1.1.0:
resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
engines: {node: '>= 0.8'}
@@ -13695,6 +13723,9 @@ packages:
resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==}
engines: {node: '>= 0.10.0'}
+ merge-descriptors@1.0.3:
+ resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
+
merge-descriptors@2.0.0:
resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
engines: {node: '>=18'}
@@ -13721,6 +13752,10 @@ packages:
meshoptimizer@0.18.1:
resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
+ methods@1.1.2:
+ resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
+ engines: {node: '>= 0.6'}
+
micromark-core-commonmark@1.1.0:
resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
@@ -14379,6 +14414,18 @@ packages:
node-mock-http@1.0.0:
resolution: {integrity: sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ==}
+ node-mocks-http@1.17.2:
+ resolution: {integrity: sha512-HVxSnjNzE9NzoWMx9T9z4MLqwMpLwVvA0oVZ+L+gXskYXEJ6tFn3Kx4LargoB6ie7ZlCLplv7QbWO6N+MysWGA==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@types/express': ^4.17.21 || ^5.0.0
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/express':
+ optional: true
+ '@types/node':
+ optional: true
+
node-pty@1.0.0:
resolution: {integrity: sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==}
@@ -14532,9 +14579,6 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
- object-inspect@1.13.1:
- resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
-
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -16420,10 +16464,6 @@ packages:
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
engines: {node: '>= 0.4'}
- side-channel@1.0.6:
- resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
- engines: {node: '>= 0.4'}
-
side-channel@1.1.0:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
@@ -17357,6 +17397,10 @@ packages:
resolution: {integrity: sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==}
engines: {node: '>=16'}
+ type-is@1.6.18:
+ resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
+ engines: {node: '>= 0.6'}
+
type-is@2.0.1:
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
engines: {node: '>= 0.6'}
@@ -20160,11 +20204,6 @@ snapshots:
'@deno/shim-deno': 0.18.2
undici: 6.21.2
- '@deno/eszip@0.84.0':
- dependencies:
- '@deno/shim-deno': 0.18.2
- undici: 6.21.2
-
'@deno/shim-deno-test@0.5.0': {}
'@deno/shim-deno@0.18.2':
@@ -21786,15 +21825,22 @@ snapshots:
lodash: 4.17.21
postcss: 8.5.3
+ '@mjackson/headers@0.11.1': {}
+
+ '@mjackson/multipart-parser@0.10.1':
+ dependencies:
+ '@mjackson/headers': 0.11.1
+
'@mjackson/node-fetch-server@0.2.0': {}
- '@modelcontextprotocol/sdk@1.12.1(supports-color@8.1.1)':
+ '@modelcontextprotocol/sdk@1.18.0(supports-color@8.1.1)':
dependencies:
ajv: 6.12.6
content-type: 1.0.5
cors: 2.8.5
cross-spawn: 7.0.6
eventsource: 3.0.7
+ eventsource-parser: 3.0.6
express: 5.1.0(supports-color@8.1.1)
express-rate-limit: 7.5.0(express@5.1.0(supports-color@8.1.1))
pkce-challenge: 5.0.0
@@ -26167,11 +26213,11 @@ snapshots:
dependencies:
'@supabase/node-fetch': 2.6.15
- '@supabase/mcp-server-supabase@0.4.4(supports-color@8.1.1)':
+ '@supabase/mcp-server-supabase@0.5.5(supports-color@8.1.1)':
dependencies:
- '@deno/eszip': 0.84.0
- '@modelcontextprotocol/sdk': 1.12.1(supports-color@8.1.1)
- '@supabase/mcp-utils': 0.2.1(supports-color@8.1.1)
+ '@mjackson/multipart-parser': 0.10.1
+ '@modelcontextprotocol/sdk': 1.18.0(supports-color@8.1.1)
+ '@supabase/mcp-utils': 0.2.2(supports-color@8.1.1)
common-tags: 1.8.2
graphql: 16.11.0
openapi-fetch: 0.13.8
@@ -26181,7 +26227,15 @@ snapshots:
'@supabase/mcp-utils@0.2.1(supports-color@8.1.1)':
dependencies:
- '@modelcontextprotocol/sdk': 1.12.1(supports-color@8.1.1)
+ '@modelcontextprotocol/sdk': 1.18.0(supports-color@8.1.1)
+ zod: 3.25.76
+ zod-to-json-schema: 3.24.5(zod@3.25.76)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@supabase/mcp-utils@0.2.2(supports-color@8.1.1)':
+ dependencies:
+ '@modelcontextprotocol/sdk': 1.18.0(supports-color@8.1.1)
zod: 3.25.76
zod-to-json-schema: 3.24.5(zod@3.25.76)
transitivePeerDependencies:
@@ -27989,6 +28043,11 @@ snapshots:
abstract-logging@2.0.1: {}
+ accepts@1.3.8:
+ dependencies:
+ mime-types: 2.1.35
+ negotiator: 0.6.3
+
accepts@2.0.0:
dependencies:
mime-types: 3.0.1
@@ -29075,6 +29134,10 @@ snapshots:
tslib: 2.8.1
upper-case: 2.0.2
+ content-disposition@0.5.4:
+ dependencies:
+ safe-buffer: 5.2.1
+
content-disposition@1.0.0:
dependencies:
safe-buffer: 5.2.1
@@ -29521,6 +29584,8 @@ snapshots:
denque@2.1.0: {}
+ depd@1.1.2: {}
+
depd@2.0.0: {}
dependency-graph@0.11.0: {}
@@ -29773,7 +29838,7 @@ snapshots:
is-string: 1.0.7
is-typed-array: 1.1.13
is-weakref: 1.0.2
- object-inspect: 1.13.1
+ object-inspect: 1.13.4
object-keys: 1.1.1
object.assign: 4.1.5
regexp.prototype.flags: 1.5.2
@@ -31782,7 +31847,7 @@ snapshots:
dependencies:
es-errors: 1.3.0
hasown: 2.0.2
- side-channel: 1.0.6
+ side-channel: 1.1.0
internal-slot@1.1.0:
dependencies:
@@ -33207,6 +33272,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ media-typer@0.3.0: {}
+
media-typer@1.1.0: {}
memfs@4.14.1:
@@ -33222,6 +33289,8 @@ snapshots:
memorystream@0.3.1: {}
+ merge-descriptors@1.0.3: {}
+
merge-descriptors@2.0.0: {}
merge-stream@2.0.0: {}
@@ -33236,6 +33305,8 @@ snapshots:
meshoptimizer@0.18.1: {}
+ methods@1.1.2: {}
+
micromark-core-commonmark@1.1.0:
dependencies:
decode-named-character-reference: 1.0.2
@@ -34316,6 +34387,21 @@ snapshots:
node-mock-http@1.0.0: {}
+ node-mocks-http@1.17.2(@types/node@22.13.14):
+ dependencies:
+ accepts: 1.3.8
+ content-disposition: 0.5.4
+ depd: 1.1.2
+ fresh: 0.5.2
+ merge-descriptors: 1.0.3
+ methods: 1.1.2
+ mime: 1.6.0
+ parseurl: 1.3.3
+ range-parser: 1.2.1
+ type-is: 1.6.18
+ optionalDependencies:
+ '@types/node': 22.13.14
+
node-pty@1.0.0:
dependencies:
nan: 2.22.1
@@ -34488,8 +34574,6 @@ snapshots:
object-hash@3.0.0: {}
- object-inspect@1.13.1: {}
-
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -36735,7 +36819,7 @@ snapshots:
'@babel/core': 7.26.10(supports-color@8.1.1)
'@babel/parser': 7.27.0
'@babel/plugin-transform-typescript': 7.27.0(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)
- '@modelcontextprotocol/sdk': 1.12.1(supports-color@8.1.1)
+ '@modelcontextprotocol/sdk': 1.18.0(supports-color@8.1.1)
commander: 10.0.1
cosmiconfig: 8.3.6(typescript@5.9.2)
deepmerge: 4.3.1
@@ -36895,13 +36979,6 @@ snapshots:
object-inspect: 1.13.4
side-channel-map: 1.0.1
- side-channel@1.0.6:
- dependencies:
- call-bind: 1.0.7
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.1
-
side-channel@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -37920,6 +37997,11 @@ snapshots:
type-fest@4.30.0: {}
+ type-is@1.6.18:
+ dependencies:
+ media-typer: 0.3.0
+ mime-types: 2.1.35
+
type-is@2.0.1:
dependencies:
content-type: 1.0.5
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 8213a05b6f3a9..6bc95206355e5 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -23,3 +23,5 @@ minimumReleaseAge: 10080
minimumReleaseAgeExclude:
- 'ai'
- '@ai-sdk/*'
+ - '@supabase/mcp-server-supabase'
+ - '@supabase/mcp-utils'