mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix: pass exposedSchemas to getLints in MCP advisor operations (#43790)
## Summary - MCP `getSecurityAdvisors` and `getPerformanceAdvisors` now pass `exposedSchemas` to `getLints`, fixing empty advisor results in local/self-hosted environments - Extracts `DEFAULT_EXPOSED_SCHEMAS` constant shared between the MCP handler and the `run-lints` API route (cc @joshenlim related https://github.com/supabase/supabase/pull/40043) - Adds unit tests for `enrichLintsQuery` and the MCP advisor operations ## The bug The MCP advisor tools (`get_advisors`) return empty arrays (`[]`) for **all** scenarios when running locally via `supabase start`. No security or performance advisors are surfaced, even when the database has clear issues (e.g., tables with no RLS). ### Root cause In `lib/api/self-hosted/mcp.ts`, both `getSecurityAdvisors` and `getPerformanceAdvisors` call `getLints({ headers })` **without passing `exposedSchemas`**: ```typescript // Before (mcp.ts:131) const { data, error } = await getLints({ headers }) ``` When `exposedSchemas` is `undefined`, `enrichLintsQuery` in `lints.ts` skips the `SET LOCAL pgrst.db_schemas = '...'` SQL statement: ```typescript // lints.ts:23 ${!!exposedSchemas ? `set local pgrst.db_schemas = '${exposedSchemas}';` : ''} ``` Without this GUC being set, the splinter SQL queries filter results using `current_setting('pgrst.db_schemas', 't')` — which returns an empty string in local environments. Every schema-filtered lint matches no schemas and returns zero rows. ### Why this only affects local/self-hosted environments In **hosted Supabase**, PostgREST sets the `pgrst.db_schemas` GUC on its own database connections based on the project's API configuration. The Studio MCP server in production reads the same project configuration, so the GUC is already available. **Locally**, PostgREST runs in a separate Docker container and only sets this GUC on _its own_ connections. Studio connects directly to PostgreSQL (bypassing PostgREST), so `current_setting('pgrst.db_schemas', 't')` returns `''`. The HTTP API endpoint (`/api/platform/.../run-lints`) already worked because `run-lints.ts` passes `exposedSchemas: 'public, storage'` — this parameter was simply never added to the MCP code path. ## How we verified the fix ### 1. Tests written to fail against the previous code We wrote two test files that target the exact bug: **`tests/unit/lints/enrichLintsQuery.test.ts`** — validates the SQL generation: - Confirms `SET LOCAL pgrst.db_schemas` is included when `exposedSchemas` is provided - Confirms it's omitted when `undefined` or empty (documenting current behavior) **`tests/unit/lints/mcp-advisors.test.ts`** — validates the MCP operations: - Asserts `getSecurityAdvisors` passes `exposedSchemas` to `getLints` - Asserts `getPerformanceAdvisors` passes `exposedSchemas` to `getLints` - Asserts the value matches `DEFAULT_EXPOSED_SCHEMAS` - Verifies SECURITY/PERFORMANCE category filtering still works Before the fix, the two `exposedSchemas` assertions failed: ``` FAIL getSecurityAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" FAIL getPerformanceAdvisors should pass exposedSchemas to getLints → expected { Object (headers) } to have property "exposedSchemas" ``` ### 2. Fix applied, all tests pass After adding `exposedSchemas: DEFAULT_EXPOSED_SCHEMAS` to both MCP operations, all 14 tests pass (9 new + 5 existing MCP tests). ## Test plan run `supabase start`, create a table without RLS, call `get_advisors` via MCP — should return `rls_disabled_in_public` lint --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
89895a7286
commit
62426253c3
6 files changed
+151
-13
No files matched your search
@@ -1,5 +1,10 @@
|
||||
// Constants specific to self-hosted environments
|
||||
|
||||
// Schemas exposed via PostgREST Data API, read from the PGRST_DB_SCHEMAS env var
|
||||
// that is passed to the Studio container via docker-compose / CLI.
|
||||
export const DEFAULT_EXPOSED_SCHEMAS =
|
||||
process.env.PGRST_DB_SCHEMAS ?? 'public,storage,graphql_public'
|
||||
|
||||
export const ENCRYPTION_KEY = process.env.PG_META_CRYPTO_KEY || 'SAMPLE_KEY'
|
||||
export const POSTGRES_PORT = parseInt(process.env.POSTGRES_PORT || '5432', 10)
|
||||
export const POSTGRES_HOST = process.env.POSTGRES_HOST || 'db'
|
||||
|
||||
@@ -19,7 +19,13 @@ export type ResponseData =
|
||||
|
||||
export const enrichLintsQuery = (query: string, exposedSchemas?: string) => {
|
||||
return `
|
||||
set pg_stat_statements.track = none;
|
||||
do $$
|
||||
begin
|
||||
set pg_stat_statements.track = none;
|
||||
exception when others then
|
||||
-- not a superuser or extension not installed, skip silently
|
||||
end
|
||||
$$;
|
||||
${!!exposedSchemas ? `set local pgrst.db_schemas = '${exposedSchemas}';` : ''}
|
||||
-- source: dashboard
|
||||
-- user: ${'self host'}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
GetLogsOptions,
|
||||
} from '@supabase/mcp-server-supabase/platform'
|
||||
import { ResponseError } from 'types'
|
||||
import { DEFAULT_EXPOSED_SCHEMAS } from './constants'
|
||||
import { generateTypescriptTypes } from './generate-types'
|
||||
import { getLints } from './lints'
|
||||
import { getLogQuery, retrieveAnalyticsData } from './logs'
|
||||
@@ -128,7 +129,10 @@ export function getDebuggingOperations({
|
||||
return data
|
||||
},
|
||||
async getSecurityAdvisors(_projectRef) {
|
||||
const { data, error } = await getLints({ headers })
|
||||
const { data, error } = await getLints({
|
||||
headers,
|
||||
exposedSchemas: DEFAULT_EXPOSED_SCHEMAS,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
@@ -137,7 +141,10 @@ export function getDebuggingOperations({
|
||||
return data.filter((lint) => lint.categories.includes('SECURITY'))
|
||||
},
|
||||
async getPerformanceAdvisors(_projectRef) {
|
||||
const { data, error } = await getLints({ headers })
|
||||
const { data, error } = await getLints({
|
||||
headers,
|
||||
exposedSchemas: DEFAULT_EXPOSED_SCHEMAS,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
|
||||
Reference in new issue
Block a user