diff --git a/apps/docs/content/guides/ai-tools/mcp.mdx b/apps/docs/content/guides/ai-tools/mcp.mdx index 799d72aea89..0cfcc6e6af1 100644 --- a/apps/docs/content/guides/ai-tools/mcp.mdx +++ b/apps/docs/content/guides/ai-tools/mcp.mdx @@ -56,7 +56,7 @@ The Supabase MCP server provides tools organized into feature groups. All groups ### Debugging -- `get_logs` - Retrieve service logs (API, Postgres, Edge Functions, Auth, Storage, Realtime) +- `query_logs` - Run a read-only SQL query against project logs to filter, aggregate, or join across log fields - `get_advisors` - Get security and performance advisors ### Development diff --git a/apps/studio/evals/dataset.ts b/apps/studio/evals/dataset.ts index 2339bda628a..e82c6064779 100644 --- a/apps/studio/evals/dataset.ts +++ b/apps/studio/evals/dataset.ts @@ -11,7 +11,7 @@ export const dataset: AssistantEvalCase[] = [ prompt: 'Check if my project is having issues right now and tell me what to fix first.', }, expected: { - requiredTools: ['get_advisors', 'get_logs'], + requiredTools: ['get_advisors', 'query_logs'], }, metadata: { category: ['debugging', 'rls_policies'] }, }, diff --git a/apps/studio/lib/ai/prompts.ts b/apps/studio/lib/ai/prompts.ts index 3ffa11c6828..9aeb7b460e4 100644 --- a/apps/studio/lib/ai/prompts.ts +++ b/apps/studio/lib/ai/prompts.ts @@ -741,7 +741,7 @@ export const CHAT_PROMPT = ` - Use \`deploy_edge_function\` solely for deployment, not for presenting example code. ## Project Health Checks - Use \`get_advisors\` to identify project issues; if unavailable, suggest the user use the Supabase dashboard. -- Use \`get_logs\` to access recent project logs. +- Use \`query_logs\` to access recent project logs by running a read-only SQL query against them. ## Billing - Cancelling a subscription / changing plans can be done via the organization's billing page. Link directly to https://supabase.com/dashboard/org/_/billing. - To check organization usage, use the organization's usage page. Link directly to https://supabase.com/dashboard/org/_/usage. diff --git a/apps/studio/lib/ai/tool-filter.test.ts b/apps/studio/lib/ai/tool-filter.test.ts index 47e93de82ee..dfd026ed96f 100644 --- a/apps/studio/lib/ai/tool-filter.test.ts +++ b/apps/studio/lib/ai/tool-filter.test.ts @@ -34,7 +34,7 @@ describe('tool allowance by opt-in level', () => { list_policies: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, // Log tools get_advisors: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, - get_logs: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, + query_logs: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, } as unknown as ToolSet const filtered = filterToolsByOptInLevel(mockTools, optInLevel as any) @@ -61,7 +61,7 @@ describe('tool allowance by opt-in level', () => { expect(tools).not.toContain('list_extensions') expect(tools).not.toContain('list_edge_functions') expect(tools).not.toContain('list_branches') - expect(tools).not.toContain('get_logs') + expect(tools).not.toContain('query_logs') expect(tools).not.toContain('get_advisors') }) @@ -77,7 +77,7 @@ describe('tool allowance by opt-in level', () => { expect(tools).toContain('list_policies') expect(tools).toContain('search_docs') expect(tools).not.toContain('get_advisors') - expect(tools).not.toContain('get_logs') + expect(tools).not.toContain('query_logs') }) it('should return UI, schema and log tools for schema_and_log opt-in level', () => { @@ -92,7 +92,7 @@ describe('tool allowance by opt-in level', () => { expect(tools).toContain('list_policies') expect(tools).toContain('search_docs') expect(tools).toContain('get_advisors') - expect(tools).toContain('get_logs') + expect(tools).toContain('query_logs') }) it('should return all tools for schema_and_log_and_data opt-in level', () => { @@ -107,7 +107,7 @@ describe('tool allowance by opt-in level', () => { expect(tools).toContain('list_policies') expect(tools).toContain('search_docs') expect(tools).toContain('get_advisors') - expect(tools).toContain('get_logs') + expect(tools).toContain('query_logs') }) }) @@ -126,7 +126,7 @@ describe('filterToolsByOptInLevel', () => { search_docs: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, // Log tools get_advisors: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, - get_logs: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, + query_logs: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, // Unknown tool - should be filtered out entirely some_other_tool: { execute: vitest.fn().mockResolvedValue({ status: 'success' }) }, } as unknown as ToolSet @@ -182,7 +182,7 @@ describe('filterToolsByOptInLevel', () => { 'list_branches', 'list_policies', 'get_advisors', - 'get_logs', + 'query_logs', ]) }) @@ -196,14 +196,14 @@ describe('filterToolsByOptInLevel', () => { 'list_branches', 'list_policies', 'get_advisors', - 'get_logs', + 'query_logs', ]) }) it('should stub log tools for schema opt-in level', async () => { const tools = filterToolsByOptInLevel(mockTools, 'schema') - await expectStubsFor(tools, ['get_advisors', 'get_logs']) + await expectStubsFor(tools, ['get_advisors', 'query_logs']) }) // No execute_sql tool, so nothing additional to stub for schema_and_log opt-in level @@ -276,7 +276,7 @@ describe('toolSetValidationSchema', () => { execute_sql: { inputSchema: z.object({}), execute: vitest.fn() }, deploy_edge_function: { inputSchema: z.object({}), execute: vitest.fn() }, rename_chat: { inputSchema: z.object({}), execute: vitest.fn() }, - get_logs: { inputSchema: z.object({}), execute: vitest.fn() }, + query_logs: { inputSchema: z.object({}), execute: vitest.fn() }, } const validationResult = toolSetValidationSchema.safeParse(allExpectedTools) diff --git a/apps/studio/lib/ai/tool-filter.ts b/apps/studio/lib/ai/tool-filter.ts index e1af605f4ac..b818829fffa 100644 --- a/apps/studio/lib/ai/tool-filter.ts +++ b/apps/studio/lib/ai/tool-filter.ts @@ -26,7 +26,7 @@ export const toolSetValidationSchema = z.record( 'list_branches', 'search_docs', 'get_advisors', - 'get_logs', + 'query_logs', // Local tools 'execute_sql', @@ -101,7 +101,7 @@ export const TOOL_CATEGORY_MAP: Record = { // Log tools - MCP and local get_advisors: TOOL_CATEGORIES.LOG, - get_logs: TOOL_CATEGORIES.LOG, + query_logs: TOOL_CATEGORIES.LOG, } /** diff --git a/apps/studio/lib/ai/tools/mcp-tools.test.ts b/apps/studio/lib/ai/tools/mcp-tools.test.ts index 5290cd99b01..afd17d9f18a 100644 --- a/apps/studio/lib/ai/tools/mcp-tools.test.ts +++ b/apps/studio/lib/ai/tools/mcp-tools.test.ts @@ -24,7 +24,7 @@ const FULL_REMOTE_TOOLS = { list_edge_functions: { description: 'edge functions' }, list_branches: { description: 'branches' }, get_advisors: { description: 'advisors' }, - get_logs: { description: 'get logs' }, + query_logs: { description: 'query logs' }, execute_sql: { description: 'execute sql' }, deploy_edge_function: { description: 'deploy' }, } @@ -53,7 +53,7 @@ describe('ai/tools/mcp-tools getMcpTools', () => { const result = await getMcpTools(BASE_PARAMS) expect(result).toHaveProperty('list_tables') - expect(result).toHaveProperty('get_logs') + expect(result).toHaveProperty('query_logs') expect(result).not.toHaveProperty('execute_sql') expect(result).not.toHaveProperty('deploy_edge_function') }) diff --git a/apps/studio/lib/ai/tools/mcp-tools.ts b/apps/studio/lib/ai/tools/mcp-tools.ts index f895f6d90b9..407ad3a40cf 100644 --- a/apps/studio/lib/ai/tools/mcp-tools.ts +++ b/apps/studio/lib/ai/tools/mcp-tools.ts @@ -34,7 +34,7 @@ const EXPECTED_MCP_TOOLS = [ 'list_edge_functions', 'list_branches', 'get_advisors', - 'get_logs', + 'query_logs', ] as const satisfies readonly SupabaseMcpToolName[] export const getMcpTools = async ({ diff --git a/apps/studio/lib/ai/tools/mock-tools.test.ts b/apps/studio/lib/ai/tools/mock-tools.test.ts index d696d2d762d..9e86efbb9c4 100644 --- a/apps/studio/lib/ai/tools/mock-tools.test.ts +++ b/apps/studio/lib/ai/tools/mock-tools.test.ts @@ -31,7 +31,7 @@ describe('ai/tools/mock-tools getMockTools', () => { expect(result).toHaveProperty('search_docs', SEARCH_DOCS) // A couple of the deterministic mocks, to confirm the merge expect(result).toHaveProperty('list_tables') - expect(result).toHaveProperty('get_logs') + expect(result).toHaveProperty('query_logs') }) // This is the regression guard: if the eval's MCP wiring breaks (contract diff --git a/apps/studio/lib/ai/tools/mock-tools.ts b/apps/studio/lib/ai/tools/mock-tools.ts index f12d9b0e55e..049b0b5fecb 100644 --- a/apps/studio/lib/ai/tools/mock-tools.ts +++ b/apps/studio/lib/ai/tools/mock-tools.ts @@ -13,11 +13,10 @@ const getAdvisorsInputSchema = z.object({ type: z.enum(['security', 'performance']).optional(), }) -const getLogsInputSchema = z.object({ - limit: z.number().min(1).max(100).optional(), - level: z.enum(['debug', 'info', 'warning', 'error']).optional(), - source: z.enum(['postgres', 'auth', 'storage', 'edge_function']).optional(), - search: z.string().optional(), +const queryLogsInputSchema = z.object({ + sql: z.string().min(1), + iso_timestamp_start: z.string().optional(), + iso_timestamp_end: z.string().optional(), }) const listPoliciesInputSchema = z.object({ @@ -218,40 +217,13 @@ function createMockGetAdvisorsTool() { }) } -function createMockGetLogsTool() { +function createMockQueryLogsTool() { return tool({ - description: 'Fetches recent project logs for debugging or health checks (mocked).', - inputSchema: getLogsInputSchema, - execute: async ({ - limit = 10, - level, - source, - search, - }: { - limit?: number - level?: 'debug' | 'info' | 'warning' | 'error' - source?: 'postgres' | 'auth' | 'storage' | 'edge_function' - search?: string - }) => { - let filtered = MOCK_LOGS_DATA - - if (level) { - filtered = filtered.filter((entry) => entry.level === level) - } - - if (source) { - filtered = filtered.filter((entry) => entry.source === source) - } - - if (search) { - const needle = search.toLowerCase() - filtered = filtered.filter((entry) => - `${entry.message} ${entry.target}`.toLowerCase().includes(needle) - ) - } - - return filtered.slice(0, limit) - }, + description: + 'Runs a read-only SQL query against recent project logs for debugging or health checks (mocked).', + inputSchema: queryLogsInputSchema, + // Deterministic mock: returns static log data regardless of the SQL passed. + execute: async () => MOCK_LOGS_DATA, }) } @@ -335,7 +307,7 @@ export async function getMockTools(overrides: MockToolOverrides | undefined, sig list_extensions: createMockListExtensionsTool(), list_edge_functions: createMockListEdgeFunctionsTool(), get_advisors: createMockGetAdvisorsTool(), - get_logs: createMockGetLogsTool(), + query_logs: createMockQueryLogsTool(), list_policies: createMockListPoliciesTool(), } } diff --git a/apps/studio/lib/api/self-hosted/logs.ts b/apps/studio/lib/api/self-hosted/logs.ts index f80e115ba3a..8a35fc409f1 100644 --- a/apps/studio/lib/api/self-hosted/logs.ts +++ b/apps/studio/lib/api/self-hosted/logs.ts @@ -1,6 +1,4 @@ import assert from 'node:assert' -import { LogsService } from '@supabase/mcp-server-supabase/platform' -import { stripIndent } from 'common-tags' import { WrappedResult } from './types' import { assertSelfHosted } from './util' @@ -71,67 +69,3 @@ export async function retrieveAnalyticsData({ throw error } } - -export function getLogQuery(service: LogsService, limit: number = 100): string { - assertSelfHosted() - - switch (service) { - case 'api': { - return stripIndent` - select id, edge_logs.timestamp, event_message, request.method, request.path, request.search, response.status_code - from edge_logs - cross join unnest(metadata) as m - cross join unnest(m.request) as request - cross join unnest(m.response) as response - order by timestamp desc - limit ${limit}; - ` - } - case 'branch-action': { - throw new Error('Branching is only supported in the hosted Supabase platform') - } - case 'postgres': { - return stripIndent` - select postgres_logs.timestamp, id, event_message, parsed.error_severity, parsed.detail, parsed.hint - from postgres_logs - cross join unnest(metadata) as m - cross join unnest(m.parsed) as parsed - order by timestamp desc - limit ${limit}; - ` - } - case 'edge-function': { - return stripIndent` - select id, function_edge_logs.timestamp, event_message - from function_edge_logs - order by timestamp desc - limit ${limit} - ` - } - case 'auth': { - return stripIndent` - select id, auth_logs.timestamp, event_message, metadata.level, metadata.status, metadata.path, metadata.msg as msg, metadata.error from auth_logs - cross join unnest(metadata) as metadata - order by timestamp desc - limit ${limit}; - ` - } - case 'storage': { - return stripIndent` - select id, storage_logs.timestamp, event_message from storage_logs - order by timestamp desc - limit ${limit}; - ` - } - case 'realtime': { - return stripIndent` - select id, realtime_logs.timestamp, event_message from realtime_logs - order by timestamp desc - limit ${limit}; - ` - } - default: { - throw new Error(`Unsupported log service: ${service}`) - } - } -} diff --git a/apps/studio/lib/api/self-hosted/mcp.test.ts b/apps/studio/lib/api/self-hosted/mcp.test.ts index 04936ab180a..940240d2973 100644 --- a/apps/studio/lib/api/self-hosted/mcp.test.ts +++ b/apps/studio/lib/api/self-hosted/mcp.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { getDevelopmentOperations } from './mcp' +import { getDebuggingOperations, getDevelopmentOperations } from './mcp' vi.mock('./settings', () => ({ getProjectSettings: vi.fn(), @@ -10,6 +10,14 @@ vi.mock('./generate-types', () => ({ generateTypescriptTypes: vi.fn(), })) +vi.mock('./logs', () => ({ + retrieveAnalyticsData: vi.fn(), +})) + +vi.mock('./lints', () => ({ + getLints: vi.fn(), +})) + describe('api/self-hosted/mcp', () => { describe('getDevelopmentOperations.getPublishableKeys', () => { let getProjectSettingsMock: ReturnType @@ -78,4 +86,55 @@ describe('api/self-hosted/mcp', () => { ) }) }) + + describe('getDebuggingOperations', () => { + let retrieveAnalyticsDataMock: ReturnType + + beforeEach(async () => { + vi.clearAllMocks() + vi.unstubAllEnvs() + const logs = await import('./logs') + retrieveAnalyticsDataMock = vi.mocked(logs.retrieveAnalyticsData) + }) + + afterEach(() => { + vi.unstubAllEnvs() + }) + + it('getLogs is not supported on self-hosted (query_logs supersedes it)', async () => { + const ops = getDebuggingOperations({}) + + // `get_logs` is hidden by the MCP server whenever `queryLogs` is present, + // so this method is unreachable over MCP and throws defensively. + await expect(ops.getLogs('default', { service: 'api' })).rejects.toThrow( + 'get_logs is not supported on self-hosted' + ) + expect(retrieveAnalyticsDataMock).not.toHaveBeenCalled() + }) + + it('queryLogs throws when logs are disabled (self-hosted default)', async () => { + vi.stubEnv('ENABLED_FEATURES_LOGS_ALL', 'false') + + const ops = getDebuggingOperations({}) + + await expect(ops.queryLogs!('default', { sql: 'select 1' })).rejects.toThrow( + 'Logs are disabled on this instance' + ) + expect(retrieveAnalyticsDataMock).not.toHaveBeenCalled() + }) + + it('queryLogs passes the model-provided SQL straight through when logs are enabled', async () => { + vi.stubEnv('ENABLED_FEATURES_LOGS_ALL', 'true') + retrieveAnalyticsDataMock.mockResolvedValue({ data: ['log entry'], error: null }) + + const ops = getDebuggingOperations({}) + await ops.queryLogs!('default', { sql: 'select * from edge_logs' }) + + expect(retrieveAnalyticsDataMock).toHaveBeenCalledWith( + expect.objectContaining({ + params: expect.objectContaining({ sql: 'select * from edge_logs' }), + }) + ) + }) + }) }) diff --git a/apps/studio/lib/api/self-hosted/mcp.ts b/apps/studio/lib/api/self-hosted/mcp.ts index cd4b5ba2793..6b6cd819609 100644 --- a/apps/studio/lib/api/self-hosted/mcp.ts +++ b/apps/studio/lib/api/self-hosted/mcp.ts @@ -6,13 +6,15 @@ import { DebuggingOperations, DevelopmentOperations, ExecuteSqlOptions, - GetLogsOptions, + QueryLogsOptions, } from '@supabase/mcp-server-supabase/platform' +import { isFeatureEnabled, type Feature } from 'common/enabled-features' +import { getEnabledFeaturesOverrideDisabledList } from 'common/enabled-features/overrides' import { DEFAULT_EXPOSED_SCHEMAS } from './constants' import { generateTypescriptTypes } from './generate-types' import { getLints } from './lints' -import { getLogQuery, retrieveAnalyticsData } from './logs' +import { retrieveAnalyticsData } from './logs' import { applyAndTrackMigrations, listMigrationVersions } from './migrations' import { executeQuery } from './query' import { getProjectSettings } from './settings' @@ -113,18 +115,42 @@ export function getDevelopmentOperations({ } } +// Logs are disabled by default for self-hosted; enabled via the +// `docker-compose.logs.yml` override, which sets ENABLED_FEATURES_LOGS_ALL=true. +function assertLogsEnabled() { + const disabledFeatures = getEnabledFeaturesOverrideDisabledList(process.env) as Feature[] + + if (!isFeatureEnabled('logs:all', disabledFeatures)) { + throw new Error( + 'Logs are disabled on this instance. Enable the `docker-compose.logs.yml` override to query logs.' + ) + } +} + export function getDebuggingOperations({ headers, }: GetDebuggingOperationsOptions): DebuggingOperations { return { - async getLogs(projectRef: string, options: GetLogsOptions) { - const sql = getLogQuery(options.service) + // Self-hosted logs are served by Logflare, which speaks BigQuery SQL. + logsDialect: 'bigquery', + // `query_logs` replaces `get_logs` on self-hosted. Declaring `queryLogs` + // makes the MCP server hide `get_logs` from clients (see `getDebuggingTools` + // in @supabase/mcp-server-supabase), so this method is never reached over + // MCP. The `DebuggingOperations` interface still requires it, so it throws + // defensively rather than serving logs. + async getLogs() { + throw new Error('get_logs is not supported on self-hosted; use query_logs instead.') + }, + async queryLogs(projectRef: string, options: QueryLogsOptions) { + assertLogsEnabled() + // Pass the model's SQL straight through to the Logflare `logs.all` + // endpoint, which accepts an arbitrary `sql` param. const { data, error } = await retrieveAnalyticsData({ name: 'logs.all', projectRef, params: { - sql, + sql: options.sql, iso_timestamp_start: options.iso_timestamp_start, iso_timestamp_end: options.iso_timestamp_end, }, diff --git a/apps/studio/package.json b/apps/studio/package.json index 2e747959ece..f574d56d9ff 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -72,7 +72,7 @@ "@stripe/stripe-js": "9.1.0", "@stripe/sync-engine": "1.0.32", "@supabase/auth-js": "catalog:", - "@supabase/mcp-server-supabase": "^0.7.0", + "@supabase/mcp-server-supabase": "^0.10.0", "@supabase/pg-meta": "workspace:*", "@supabase/realtime-js": "catalog:", "@supabase/shared-types": "0.1.91", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a7d8ca02a5..1f808f0d497 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -985,8 +985,8 @@ importers: specifier: 'catalog:' version: 2.112.3 '@supabase/mcp-server-supabase': - specifier: ^0.7.0 - version: 0.7.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76) + specifier: ^0.10.0 + version: 0.10.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76) '@supabase/pg-meta': specifier: workspace:* version: link:../../packages/pg-meta @@ -3864,10 +3864,6 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-community/regexpp@4.12.2': resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -7719,15 +7715,15 @@ packages: resolution: {integrity: sha512-gfv481mTOVWtZIJgXupxZpni2V2UWPf6jeF/jOK7HdMHdH+mt6sU0sHHwf0POsPip8ltlulu9OUHgwVzl5ddRw==} engines: {node: '>=22.0.0'} - '@supabase/mcp-server-supabase@0.7.0': - resolution: {integrity: sha512-t0sOS27T5mDxp6jUYSh3zuyjWhYZarbXCPUO7HTVSyPq2smY6d5UM4Lko81eawYCSRDE8qwDZOKnVkXwCS4RSg==} + '@supabase/mcp-server-supabase@0.10.0': + resolution: {integrity: sha512-CVnB+4wBFsQeYwr5phNZyG33nNPUVBAJFB99vn55Z5Zn5+sxopybBPeYtrz8J9rqLkXad/xb7Xow4sz0JMq/XQ==} hasBin: true peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 zod: ^3.25.0 || ^4.0.0 - '@supabase/mcp-utils@0.4.0': - resolution: {integrity: sha512-mJ06GYLLZGW4zfz4yl08P2wrx0ORqW5iIAFyqvWJAInIjoa3w7EfJs/h+RbvCE+x7UYuSQeDUXpLJc4lJWDBKA==} + '@supabase/mcp-utils@0.6.0': + resolution: {integrity: sha512-4r7RTEMZgFw4VqTgsQrM0KUWXdEOASPHEjIfuBaGb0SXPHIIe6W8xBnocidjtfQnKagxMJb0RXY4rqwwShJ2zw==} peerDependencies: '@modelcontextprotocol/sdk': ^1.25.2 zod: ^3.25.0 || ^4.0.0 @@ -11303,10 +11299,6 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -19382,8 +19374,6 @@ snapshots: eslint: 9.37.0(jiti@2.7.0)(supports-color@8.1.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} - '@eslint-community/regexpp@4.12.2': {} '@eslint/compat@2.1.0(eslint@9.37.0(jiti@2.7.0)(supports-color@8.1.1))': @@ -23731,18 +23721,18 @@ snapshots: dependencies: tslib: 2.8.1 - '@supabase/mcp-server-supabase@0.7.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76)': + '@supabase/mcp-server-supabase@0.10.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76)': dependencies: '@mjackson/multipart-parser': 0.10.1 '@modelcontextprotocol/sdk': 1.29.0(supports-color@8.1.1)(zod@3.25.76) - '@supabase/mcp-utils': 0.4.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76) + '@supabase/mcp-utils': 0.6.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76) common-tags: 1.8.2 gqlmin: 0.3.1 graphql: 16.11.0 openapi-fetch: 0.13.8 zod: 3.25.76 - '@supabase/mcp-utils@0.4.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76)': + '@supabase/mcp-utils@0.6.0(@modelcontextprotocol/sdk@1.29.0(supports-color@8.1.1)(zod@3.25.76))(zod@3.25.76)': dependencies: '@modelcontextprotocol/sdk': 1.29.0(supports-color@8.1.1)(zod@3.25.76) zod: 3.25.76 @@ -27722,8 +27712,8 @@ snapshots: eslint@9.37.0(jiti@2.7.0)(supports-color@8.1.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.7.0)(supports-color@8.1.1)) - '@eslint-community/regexpp': 4.12.1 + '@eslint-community/eslint-utils': 4.10.1(eslint@9.37.0(jiti@2.7.0)(supports-color@8.1.1)) + '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.0(supports-color@8.1.1) '@eslint/config-helpers': 0.4.0 '@eslint/core': 0.16.0 @@ -27743,7 +27733,7 @@ snapshots: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - esquery: 1.5.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -27777,10 +27767,6 @@ snapshots: esprima@4.0.1: {} - esquery@1.5.0: - dependencies: - estraverse: 5.3.0 - esquery@1.7.0: dependencies: estraverse: 5.3.0