mcp-supabase-selfhosted 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,11 +9,11 @@ This skill guides the agent on how to correctly and safely utilize the `supabase
9
9
 
10
10
  ## 1. When to Use
11
11
  Activate this skill whenever the user asks to:
12
- - "Configurar un usuario de prueba en auth."
13
- - "Crear un bucket para mis imágenes."
14
- - "Revisar las políticas de seguridad RLS."
15
- - "Corregir problemas de rendimiento de la base de datos."
16
- - "Ver qué columnas tiene una tabla en mi Supabase."
12
+ - "Setup a test user in auth."
13
+ - "Create a bucket for my images."
14
+ - "Review RLS security policies."
15
+ - "Fix database performance issues."
16
+ - "See what columns a table has in my Supabase."
17
17
 
18
18
  ## 2. Security and RLS (Row Level Security) Mandates
19
19
  **Critical:** Because this MCP uses the `SUPABASE_SERVICE_ROLE_KEY` and direct PostgreSQL connections, **it bypasses Row Level Security (RLS) entirely.**
@@ -25,17 +25,18 @@ Activate this skill whenever the user asks to:
25
25
 
26
26
  ### A. Exploring the Database
27
27
  1. Run `list_tables` to see what exists.
28
- 2. Run `get_schema({ table_name: "X" })` to understand the columns before writing any SQL.
29
- 3. Run `get_advisors()` to check if there are missing indexes or security gaps.
28
+ 2. Run `get_schema({ table_name: "X" })` to understand columns before writing any SQL.
29
+ 3. Run `get_advisors()` to check for missing indexes or security gaps.
30
+ 4. Access the source of truth schema via the resource `supabase://database/schema`.
30
31
 
31
32
  ### B. Configuring Auth
32
33
  1. Use `list_users` to see who is registered.
33
- 2. Use `create_user({ email, password, email_confirm: true })` to bootstrap administrative or test accounts without needing an email SMTP server configured locally.
34
- 3. If asked to clean up, use `delete_user({ user_id })`.
34
+ 2. Use `create_user({ email, password, email_confirm: true })` to bootstrap administrative or test accounts without needing an SMTP server configured locally.
35
+ 3. If asked to clean up, use `delete_user({ user_id, confirm: true })`.
35
36
 
36
37
  ### C. Configuring Storage (Buckets)
37
38
  1. Use `list_buckets()` to check existing buckets.
38
- 2. Use `create_bucket({ bucket: "name", public: true/false })` to make a new one. Remember: making a bucket public allows read access without auth, but RLS policies are still recommended via `storage.objects` table.
39
+ 2. Use `create_bucket({ bucket: "name", public: true/false })` to make a new one. Remember: making a bucket public allows read access without auth, but RLS policies are still recommended via the `storage.objects` table.
39
40
  3. Use `list_files({ bucket: "name" })` to verify uploads.
40
41
 
41
42
  ### D. Debugging and Infrastructure
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.0] - 2026-06-04
9
+
10
+ ### Changed
11
+ - Translated the entire project to English for global distribution.
12
+ - Updated all tool descriptions and documentation.
13
+
14
+ ## [1.1.0] - 2026-06-04
15
+
16
+ ### Added
17
+ - Full support for MCP Resources (`supabase://database/schema`).
18
+ - Full support for MCP Prompts (`audit-security`).
19
+ - One-command execution support via `npx`.
20
+ - GitHub Actions CI for automated build/test/lint.
21
+
8
22
  ## [1.0.0] - 2026-06-01
9
23
 
10
24
  ### Added
@@ -14,6 +28,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
28
  - Auth tools: `list_users`, `create_user`, `delete_user`.
15
29
  - Storage tools: `list_buckets`, `create_bucket`, `delete_bucket`, `list_files`.
16
30
  - Docker support with Multi-stage builds.
17
- - One-command execution support via `npx`.
18
31
  - Initial test suite and linting configuration.
19
32
  - MIT License and community health files.
package/CONTRIBUTING.md CHANGED
@@ -9,12 +9,12 @@ By participating in this project, you are expected to uphold our Code of Conduct
9
9
  ## How Can I Contribute?
10
10
 
11
11
  ### Reporting Bugs
12
- - Use the [GitHub Bug Report template](.github/ISSUE_TEMPLATE/bug_report.md).
12
+ - Use the [GitHub Bug Report template](.github/ISSUE_TEMPLATE/bug_report.yml).
13
13
  - Provide a clear and descriptive title.
14
14
  - Describe the exact steps which reproduce the problem.
15
15
 
16
16
  ### Suggesting Enhancements
17
- - Use the [GitHub Feature Request template](.github/ISSUE_TEMPLATE/feature_request.md).
17
+ - Use the [GitHub Feature Request template](.github/ISSUE_TEMPLATE/feature_request.yml).
18
18
  - Explain why this enhancement would be useful to most users.
19
19
 
20
20
  ### Pull Requests
package/README.md CHANGED
@@ -1,52 +1,55 @@
1
1
  # Supabase Self-Hosted MCP Server
2
2
 
3
- Un servidor [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) diseñado específicamente para instancias **Self-Hosted de Supabase**.
3
+ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server designed specifically for **Self-Hosted Supabase** instances.
4
4
 
5
- A diferencia del servidor MCP oficial que depende en gran medida de las APIs de la nube de Supabase y del `project-ref`, esta versión se conecta directamente a tu base de datos PostgreSQL local y a las APIs locales (Auth/Storage) usando tu `SUPABASE_URL` y tu `SERVICE_ROLE_KEY`.
5
+ Unlike the official Supabase MCP server which heavily relies on Supabase Cloud APIs and the `project-ref`, this version connects directly to your local PostgreSQL database and local APIs (Auth/Storage) using your `SUPABASE_URL` and `SERVICE_ROLE_KEY`.
6
6
 
7
- ## Características
7
+ ## Features
8
8
 
9
- - **Introspección de Base de Datos:** Lista tablas y esquemas de tu Postgres.
10
- - **Ejecución SQL Raw:** Ejecuta consultas SQL directamente, permitiendo a la IA leer datos o modificar la estructura (bypass de RLS).
11
- - **Gestión de Autenticación:** Lista usuarios registrados en tu instancia.
12
- - **Gestión de Storage:** Lista buckets de almacenamiento.
9
+ - **Database Introspection:** List tables and schemas in your Postgres database.
10
+ - **Raw SQL Execution:** Execute SQL queries directly, allowing the AI to read data or modify the structure (bypassing RLS).
11
+ - **Authentication Management:** List and manage users registered in your instance.
12
+ - **Storage Management:** List buckets and files.
13
+ - **Resources:** Access the complete database schema via URI (`supabase://database/schema`).
14
+ - **Prompts:** Integrated prompt templates for security audits and optimization.
15
+ - **Infrastructure Diagnostics:** Monitor active connections and get performance advisors (unused indexes, cache health).
13
16
 
14
- ## Requisitos
17
+ ## Requirements
15
18
 
16
19
  - Node.js >= 18
17
- - Docker (opcional, pero recomendado)
20
+ - Docker (optional, but recommended)
18
21
 
19
- ## Instalación y Uso (Local)
22
+ ## Installation and Usage (Local)
20
23
 
21
- 1. Clona el repositorio:
24
+ 1. Clone the repository:
22
25
  ```bash
23
- git clone https://github.com/tu-usuario/mcp-supabase-selfhosted.git
26
+ git clone https://github.com/adiego-101/mcp-supabase-selfhosted.git
24
27
  cd mcp-supabase-selfhosted
25
28
  ```
26
29
 
27
- 2. Instala las dependencias y compila:
30
+ 2. Install dependencies and build:
28
31
  ```bash
29
32
  npm install
30
33
  npm run build
31
34
  ```
32
35
 
33
- 3. Crea tu archivo de entorno:
36
+ 3. Create your environment file:
34
37
  ```bash
35
38
  cp .env.example .env
36
39
  ```
37
- Rellena tus credenciales (asegúrate de usar la **Service Role Key**, ¡nunca la anónima!).
40
+ Fill in your credentials (ensure you use the **Service Role Key**, never the anonymous one!).
38
41
 
39
- ## Uso con Docker (Recomendado)
42
+ ## Usage with Docker (Recommended)
40
43
 
41
- La forma más limpia de utilizar este servidor en clientes IA (Cursor, Claude, Gemini) sin ensuciar tu entorno local es usar la imagen de Docker.
44
+ The cleanest way to use this server in AI clients (Cursor, Claude, Gemini) without cluttering your local environment is to use the Docker image.
42
45
 
43
- 1. Construye la imagen localmente:
46
+ 1. Build the image locally:
44
47
  ```bash
45
48
  docker build -t supabase-selfhosted-mcp .
46
49
  ```
47
50
 
48
- ### Configuración en Claude Desktop / Cursor
49
- Añade lo siguiente a tu archivo `claude_desktop_config.json` o configuración de Cursor:
51
+ ### Configuration in Claude Desktop / Cursor
52
+ Add the following to your `claude_desktop_config.json` or Cursor configuration:
50
53
 
51
54
  ```json
52
55
  {
@@ -58,7 +61,7 @@ Añade lo siguiente a tu archivo `claude_desktop_config.json` o configuración d
58
61
  "-i",
59
62
  "--rm",
60
63
  "-e", "SUPABASE_URL=http://host.docker.internal:8000",
61
- "-e", "SUPABASE_SERVICE_ROLE_KEY=tu-clave-aqui",
64
+ "-e", "SUPABASE_SERVICE_ROLE_KEY=your-key-here",
62
65
  "-e", "DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/postgres",
63
66
  "supabase-selfhosted-mcp"
64
67
  ]
@@ -66,39 +69,24 @@ Añade lo siguiente a tu archivo `claude_desktop_config.json` o configuración d
66
69
  }
67
70
  }
68
71
  ```
69
- *(Nota: usa `host.docker.internal` en lugar de `localhost` si tu base de datos corre en tu máquina host).*
72
+ *(Note: use `host.docker.internal` instead of `localhost` if your database is running on your host machine).*
70
73
 
71
- ### Configuración en Gemini CLI
72
- Puedes añadirlo en tu archivo `~/.gemini/settings.json`:
73
-
74
- ```json
75
- {
76
- "mcpServers": {
77
- "supabase-selfhosted": {
78
- "command": "docker",
79
- "args": [
80
- "run",
81
- "-i",
82
- "--rm",
83
- "-e", "SUPABASE_URL=...",
84
- "-e", "SUPABASE_SERVICE_ROLE_KEY=...",
85
- "-e", "DATABASE_URL=...",
86
- "supabase-selfhosted-mcp"
87
- ]
88
- }
89
- }
90
- }
74
+ ### One-Command Usage (via npx)
75
+ If you have the package installed or want to run it directly:
76
+ ```bash
77
+ npx mcp-supabase-selfhosted
91
78
  ```
92
79
 
93
- ## Seguridad y Buenas Prácticas
80
+ ## Security and Best Practices
94
81
 
95
- - **Acceso Directo:** Este MCP utiliza conexiones directas a DB y la `SERVICE_ROLE_KEY`. Esto significa que la IA conectada tendrá acceso **total y sin restricciones (bypassing RLS)** a tu instancia.
96
- - **Entornos:** Se recomienda encarecidamente utilizar esto **sólo en entornos de desarrollo local**, nunca apuntando a una base de datos de producción con datos reales sensibles.
97
- - **Transporte:** El servidor usa `stdio` (entrada/salida estándar), lo cual es el protocolo de seguridad predeterminado en aplicaciones de escritorio como Cursor y Claude.
82
+ - **Direct Access:** This MCP uses direct DB connections and the `SERVICE_ROLE_KEY`. This means the connected AI will have **full, unrestricted access (bypassing RLS)** to your instance.
83
+ - **Environments:** It is strongly recommended to use this **only in local development environments**, never pointing to a production database with sensitive real data.
84
+ - **Transport:** The server uses `stdio` (standard input/output), which is the default security protocol in desktop applications like Cursor and Claude.
85
+ - **Destructive Actions:** Tools like `delete_user` or `delete_bucket` require an explicit `confirm: true` flag to prevent accidental data loss.
98
86
 
99
- ## Contribuir
87
+ ## Contributing
100
88
 
101
- ¡Las contribuciones son bienvenidas! Sientete libre de abrir Issues o Pull Requests. Si planeas añadir una herramienta nueva, añádela en el directorio `src/tools/`.
89
+ Contributions are welcome! Feel free to open Issues or Pull Requests. If you plan to add a new tool, add it to the `src/tools/` directory.
102
90
 
103
- ## Licencia
91
+ ## License
104
92
  MIT
package/SECURITY.md CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  Currently, only the latest version of the Supabase Self-Hosted MCP server is supported with security updates.
6
6
 
7
- | Version | Supported |
8
- | ------- | ------------------ |
9
- | 1.0.x | :white_check_mark: |
10
- | < 1.0 | :x: |
7
+ | Version | Supported |
8
+ | ------- | --------- |
9
+ | 1.x.x | |
10
+ | < 1.0 | |
11
11
 
12
12
  ## Reporting a Vulnerability
13
13
 
@@ -5,12 +5,9 @@ dotenv.config();
5
5
  // Esquema de validación para las variables de entorno
6
6
  const envSchema = z
7
7
  .object({
8
- SUPABASE_URL: z.string().url('La URL de Supabase debe ser válida').optional(),
8
+ SUPABASE_URL: z.string().url('Supabase URL must be a valid URL').optional(),
9
9
  SUPABASE_SERVICE_ROLE_KEY: z.string().optional(),
10
- DATABASE_URL: z
11
- .string()
12
- .url('La URL de la base de datos (Postgres) debe ser válida')
13
- .optional(),
10
+ DATABASE_URL: z.string().url('Database URL (Postgres) must be a valid URL').optional(),
14
11
  })
15
12
  .refine((data) => {
16
13
  // Al menos una de las dos formas de conexión debe estar configurada
@@ -18,7 +15,7 @@ const envSchema = z
18
15
  const hasDBConnection = !!data.DATABASE_URL;
19
16
  return hasSupabaseAPI || hasDBConnection;
20
17
  }, {
21
- message: 'Debes configurar al menos DATABASE_URL o (SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY)',
18
+ message: 'You must configure at least DATABASE_URL or (SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY)',
22
19
  });
23
20
  export function getConfig() {
24
21
  try {
@@ -27,7 +24,7 @@ export function getConfig() {
27
24
  }
28
25
  catch (error) {
29
26
  if (error instanceof z.ZodError) {
30
- console.error(' Error de configuración. Faltan variables de entorno o son inválidas:');
27
+ console.error(' Configuration error. Environment variables are missing or invalid:');
31
28
  error.issues.forEach((e) => console.error(` - ${e.message}`));
32
29
  process.exit(1);
33
30
  }
@@ -10,26 +10,26 @@ export async function getDbPool() {
10
10
  }
11
11
  const config = getConfig();
12
12
  if (!config.DATABASE_URL) {
13
- throw new Error('DATABASE_URL no está configurada. Las herramientas de base de datos directa no funcionarán.');
13
+ throw new Error('DATABASE_URL is not configured. Direct database tools will not work.');
14
14
  }
15
15
  pgPool = new Pool({
16
16
  connectionString: config.DATABASE_URL,
17
- max: 10, // Límite máximo de conexiones activas para este MCP
18
- idleTimeoutMillis: 30000, // Cerrar conexiones inactivas después de 30s
19
- connectionTimeoutMillis: 5000, // Abortar intentos de conexión lentos
20
- statement_timeout: 10000, // (10s) Abortar consultas pesadas/erróneas generadas por la IA
17
+ max: 10, // Maximum active connections for this MCP
18
+ idleTimeoutMillis: 30000, // Close idle connections after 30s
19
+ connectionTimeoutMillis: 5000, // Abort slow connection attempts
20
+ statement_timeout: 10000, // (10s) Abort heavy/incorrect queries generated by the AI
21
21
  });
22
22
  try {
23
- // Verificamos la conexión con una consulta sencilla
23
+ // Verify connection with a simple query
24
24
  const client = await pgPool.connect();
25
25
  client.release();
26
- console.error(' Conectado exitosamente a PostgreSQL (Pool con timeouts configurados).');
26
+ console.error(' Successfully connected to PostgreSQL (Pool with timeouts configured).');
27
27
  return pgPool;
28
28
  }
29
29
  catch (error) {
30
30
  pgPool = null;
31
31
  const msg = error instanceof Error ? error.message : String(error);
32
- console.error(' Error conectando a PostgreSQL:', msg);
32
+ console.error(' Error connecting to PostgreSQL:', msg);
33
33
  throw error;
34
34
  }
35
35
  }
@@ -44,7 +44,7 @@ export async function query(sql, params = []) {
44
44
  }
45
45
  catch (error) {
46
46
  const msg = error instanceof Error ? error.message : String(error);
47
- console.error(' Error ejecutando query:', msg);
47
+ console.error(' Error executing query:', msg);
48
48
  throw error;
49
49
  }
50
50
  }
package/dist/index.js CHANGED
@@ -11,29 +11,52 @@ async function main() {
11
11
  // 2. Inicializar el servidor MCP
12
12
  const server = new Server({
13
13
  name: 'supabase-selfhosted-mcp',
14
- version: '1.0.0',
14
+ version: '1.2.0',
15
15
  }, {
16
16
  capabilities: {
17
17
  tools: {},
18
- resources: {},
18
+ resources: {
19
+ subscribe: true,
20
+ listChanged: true,
21
+ },
19
22
  prompts: {},
23
+ logging: {},
20
24
  },
21
25
  });
26
+ /**
27
+ * Helper to send log messages to the client.
28
+ */
29
+ const log = (message, level = 'info') => {
30
+ server.sendLoggingMessage({
31
+ level,
32
+ data: message,
33
+ });
34
+ console.error(`[${level.toUpperCase()}] ${message}`);
35
+ };
22
36
  // --- RECURSOS (Resources) ---
23
37
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
24
38
  return {
25
39
  resources: [
26
40
  {
27
41
  uri: 'supabase://database/schema',
28
- name: 'Esquema completo de la base de datos',
29
- description: 'Devuelve la estructura de todas las tablas y columnas del esquema public.',
42
+ name: 'Complete database schema',
43
+ description: 'Returns the structure of all tables and columns in the public schema.',
44
+ mimeType: 'application/json',
45
+ },
46
+ ],
47
+ resourceTemplates: [
48
+ {
49
+ uriTemplate: 'supabase://database/table/{name}',
50
+ name: 'Table specific schema',
51
+ description: 'Returns the schema for a specific table.',
30
52
  mimeType: 'application/json',
31
53
  },
32
54
  ],
33
55
  };
34
56
  });
35
57
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
36
- if (request.params.uri === 'supabase://database/schema') {
58
+ const { uri } = request.params;
59
+ if (uri === 'supabase://database/schema') {
37
60
  const sql = `
38
61
  SELECT table_name, column_name, data_type
39
62
  FROM information_schema.columns
@@ -44,7 +67,28 @@ async function main() {
44
67
  return {
45
68
  contents: [
46
69
  {
47
- uri: request.params.uri,
70
+ uri,
71
+ mimeType: 'application/json',
72
+ text: JSON.stringify(rows, null, 2),
73
+ },
74
+ ],
75
+ };
76
+ }
77
+ // Handle Resource Templates (Specific Table)
78
+ const tableMatch = uri.match(/^supabase:\/\/database\/table\/(.+)$/);
79
+ if (tableMatch) {
80
+ const tableName = tableMatch[1];
81
+ const sql = `
82
+ SELECT column_name, data_type, is_nullable, column_default
83
+ FROM information_schema.columns
84
+ WHERE table_schema = 'public' AND table_name = $1
85
+ ORDER BY ordinal_position;
86
+ `;
87
+ const rows = await query(sql, [tableName]);
88
+ return {
89
+ contents: [
90
+ {
91
+ uri,
48
92
  mimeType: 'application/json',
49
93
  text: JSON.stringify(rows, null, 2),
50
94
  },
@@ -59,7 +103,7 @@ async function main() {
59
103
  prompts: [
60
104
  {
61
105
  name: 'audit-security',
62
- description: 'Realiza una auditoría de seguridad completa de la instancia de Supabase.',
106
+ description: 'Performs a complete security audit of the Supabase instance.',
63
107
  },
64
108
  ],
65
109
  };
@@ -67,13 +111,13 @@ async function main() {
67
111
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
68
112
  if (request.params.name === 'audit-security') {
69
113
  return {
70
- description: 'Auditoría de seguridad de Supabase',
114
+ description: 'Supabase Security Audit',
71
115
  messages: [
72
116
  {
73
117
  role: 'user',
74
118
  content: {
75
119
  type: 'text',
76
- text: 'Por favor, realiza los siguientes pasos para auditar mi instancia:\n1. Usa get_advisors para detectar problemas de rendimiento y RLS.\n2. Usa list_rls_policies para revisar todas las reglas de acceso activas.\n3. Usa get_active_connections para ver si hay accesos sospechosos o bloqueos.\n4. Finalmente, entrégame un reporte detallado con recomendaciones de seguridad.',
120
+ text: 'Please perform the following steps to audit my instance:\n1. Use get_advisors to detect performance and RLS issues.\n2. Use list_rls_policies to review all active access rules.\n3. Use get_active_connections to see if there are suspicious accesses or blocks.\n4. Finally, provide a detailed report with security recommendations.',
77
121
  },
78
122
  },
79
123
  ],
@@ -124,9 +168,9 @@ async function main() {
124
168
  // 5. Configurar el transporte stdio (entrada/salida estándar)
125
169
  const transport = new StdioServerTransport();
126
170
  await server.connect(transport);
127
- console.error(' Servidor MCP de Supabase Self-Hosted iniciado correctamente.');
171
+ log('Supabase Self-Hosted MCP Server started successfully.', 'info');
128
172
  }
129
173
  main().catch((error) => {
130
- console.error(' Error fatal al iniciar el servidor MCP:', error);
174
+ console.error('Fatal error starting MCP server:', error);
131
175
  process.exit(1);
132
176
  });
@@ -10,17 +10,17 @@ export function getSupabaseClient() {
10
10
  }
11
11
  const config = getConfig();
12
12
  if (!config.SUPABASE_URL || !config.SUPABASE_SERVICE_ROLE_KEY) {
13
- throw new Error('SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY son obligatorias para utilizar las herramientas de Auth y Storage.');
13
+ throw new Error('SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY are required to use Auth and Storage tools.');
14
14
  }
15
- // Creamos el cliente usando la service role key.
16
- // IMPORTANTE: En el contexto de un MCP (que actúa como un super admin), es seguro
17
- // y necesario usar la service role key, pero el usuario debe estar consciente de esto.
15
+ // Create client using the service role key.
16
+ // IMPORTANT: In an MCP context (acting as super admin), it is safe
17
+ // and necessary to use the service role key, but the user should be aware of this.
18
18
  supabaseClient = createClient(config.SUPABASE_URL, config.SUPABASE_SERVICE_ROLE_KEY, {
19
19
  auth: {
20
20
  autoRefreshToken: false,
21
21
  persistSession: false,
22
22
  },
23
23
  });
24
- console.error(' Cliente Supabase API inicializado.');
24
+ console.error(' Supabase API client initialized.');
25
25
  return supabaseClient;
26
26
  }