Self-Hosted Supabase MCP Server

Interactúa con instancias autoalojadas de Supabase para introspección, gestión e interacción de bases de datos.

Documentación

Self-Hosted Supabase MCP Server

License: MIT smithery badge

Overview

Este proyecto proporciona un servidor de Protocolo de Contexto de Modelo (MCP) diseñado específicamente para interactuar con instancias de Supabase autoalojadas. Cubre la brecha entre los clientes MCP (como extensiones de IDE) y tus proyectos de Supabase locales o alojados de forma privada, permitiendo la introspección de bases de datos, gestión e interacción directamente desde tu entorno de desarrollo.

Este servidor fue construido desde cero, tomando lecciones de la adaptación del servidor MCP oficial de Supabase cloud, para proporcionar una implementación mínima y enfocada, adaptada al caso de uso de autoalojamiento.

Propósito

El objetivo principal de este servidor es permitir a los desarrolladores que utilizan instalaciones de Supabase autoalojadas aprovechar las herramientas basadas en MCP para tareas como:

  • Consultar esquemas y datos de bases de datos.
  • Gestionar migraciones de bases de datos.
  • Inspeccionar estadísticas y conexiones de bases de datos.
  • Gestionar usuarios de autenticación.
  • Interactuar con Supabase Storage.
  • Generar definiciones de tipos.

Evita las complejidades del servidor cloud oficial relacionadas con la gestión de múltiples proyectos y las API específicas de la nube, ofreciendo una experiencia simplificada para entornos autoalojados de un solo proyecto.

Características (Herramientas implementadas)

Las herramientas se clasifican por nivel de privilegio:

  • Las herramientas regulares son accesibles por cualquier JWT de Supabase autenticado (rol authenticated o service_role).
  • Las herramientas privilegiadas requieren un JWT service_role (modo HTTP) o acceso directo a la base de datos/clave de servicio (modo stdio).

Esquema y Migraciones

HerramientaDescripciónPrivilegio
list_tablesLista las tablas en los esquemas de la base de datosRegular
list_extensionsLista las extensiones de PostgreSQL instaladasRegular
list_available_extensionsLista todas las extensiones disponibles (instalables)Regular
list_migrationsLista las migraciones aplicadas desde supabase_migrations.schema_migrationsRegular
apply_migrationAplica una migración SQL y la registra en supabase_migrations.schema_migrationsPrivilegiada
list_table_columnsLista las columnas de una tabla específicaRegular
list_indexesLista los índices de una tabla específicaRegular
list_constraintsLista las restricciones de una tabla específicaRegular
list_foreign_keysLista las claves foráneas de una tabla específicaRegular
list_triggersLista los disparadores (triggers) de una tabla específicaRegular
list_database_functionsLista las funciones de base de datos definidas por el usuarioRegular
get_function_definitionObtiene la definición fuente de una funciónRegular
get_trigger_definitionObtiene la definición fuente de un disparadorRegular

Operaciones de Base de Datos y Estadísticas

HerramientaDescripciónPrivilegio
execute_sqlEjecuta una consulta SQL arbitrariaPrivilegiada
explain_queryEjecuta EXPLAIN ANALYZE en una consultaPrivilegiada
get_database_connectionsMuestra conexiones activas (pg_stat_activity)Regular
get_database_statsRecupera estadísticas de la base de datos (pg_stat_*)Regular
get_index_statsMuestra estadísticas de uso de índicesRegular
get_vector_index_statsMuestra estadísticas de índices pgvectorRegular

Seguridad y RLS

HerramientaDescripciónPrivilegio
list_rls_policiesLista las políticas de seguridad a nivel de fila (RLS) para una tablaRegular
get_rls_statusMuestra el estado habilitado/deshabilitado de RLS para tablasRegular
get_advisorsRecupera avisos de asesoramiento de seguridad y rendimientoRegular

Configuración del Proyecto

HerramientaDescripciónPrivilegio
get_project_urlDevuelve la URL de Supabase configuradaRegular
verify_jwt_secretComprueba si el secreto JWT está configuradoRegular

Herramientas de Desarrollo y Extensión

HerramientaDescripciónPrivilegio
generate_typescript_typesGenera tipos de TypeScript a partir del esquema de la base de datosRegular
rebuild_hooksReinicia el worker pg_net (si se utiliza)Privilegiada
get_logsRecupera entradas de registro recientes (stack de analítica o respaldo CSV)Regular

Gestión de Usuarios de Autenticación

HerramientaDescripciónPrivilegio
list_auth_usersLista usuarios de auth.usersRegular
get_auth_userRecupera detalles de un usuario específicoRegular
create_auth_userCrea un nuevo usuario en auth.users (contraseña con hash bcrypt mediante pgcrypto)Privilegiada
update_auth_userActualiza los detalles de un usuario (contraseña con hash bcrypt si se cambia)Privilegiada
delete_auth_userElimina un usuario de auth.usersPrivilegiada

Storage

HerramientaDescripciónPrivilegio
list_storage_bucketsLista todos los buckets de almacenamientoRegular
list_storage_objectsLista los objetos dentro de un bucket específicoRegular
get_storage_configRecupera la configuración del bucket de almacenamientoRegular
update_storage_configActualiza la configuración del bucket de almacenamientoPrivilegiada

Inspección en Tiempo Real

HerramientaDescripciónPrivilegio
list_realtime_publicationsLista las publicaciones de PostgreSQL (p. ej., supabase_realtime)Regular

Herramientas Específicas de Extensiones

HerramientaDescripciónPrivilegio
list_cron_jobsLista los trabajos programados (requiere la extensión pg_cron)Regular
get_cron_job_historyMuestra el historial de ejecución reciente de un trabajo cronRegular
list_vector_indexesLista los índices pgvector (requiere la extensión pgvector)Regular

Funciones Edge

HerramientaDescripciónPrivilegio
list_edge_functionsLista las Funciones Edge desplegadasRegular
get_edge_function_detailsObtiene detalles y metadatos de una Función EdgeRegular
list_edge_function_logsRecupera registros recientes de una Función EdgeRegular

Acerca de supabase_migrations.schema_migrations

Las herramientas list_migrations y apply_migration dependen de la tabla supabase_migrations.schema_migrations. Esta tabla es creada y gestionada por la CLI de Supabase — no forma parte del propio servidor MCP.

Cómo se crea la tabla:

La tabla se crea automáticamente cuando inicializas o ejecutas migraciones con la CLI de Supabase:

supabase db push        # pushes local migrations to a remote database
supabase migration up   # applies pending local migration files

Si nunca has ejecutado la CLI de Supabase contra tu base de datos, la tabla no existirá y list_migrations devolverá un error. Puedes crearla manualmente con:

CREATE SCHEMA IF NOT EXISTS supabase_migrations;
CREATE TABLE IF NOT EXISTS supabase_migrations.schema_migrations (
    version text NOT NULL PRIMARY KEY,
    name    text NOT NULL DEFAULT '',
    inserted_at timestamptz NOT NULL DEFAULT now()
);

Diferencia de esquema vs. Supabase oficial:

La plataforma cloud de Supabase rastrea columnas adicionales (p. ej., statements, dirty). Este servidor MCP utiliza el esquema mínimo (versión + nombre + inserted_at) que es compatible con el flujo de trabajo de desarrollo local de la CLI de Supabase. Si tu tabla existente tiene columnas adicionales, simplemente se ignoran.

Configuración e Instalación

Instalación mediante Smithery

Para instalar Self-Hosted Supabase MCP Server para Claude Desktop automáticamente mediante Smithery:

npx -y @smithery/cli install @HenkDz/selfhosted-supabase-mcp --client claude

Requisitos previos

  • Bun v1.1 o posterior (reemplaza Node.js/npm — se utiliza para el runtime y las compilaciones)
  • Acceso a tu instancia de Supabase autoalojada (URL, claves y, opcionalmente, una cadena de conexión directa a PostgreSQL).

Pasos

  1. Clonar el repositorio:
    git clone <repository-url>
    cd selfhosted-supabase-mcp
    
  2. Instalar dependencias:
    bun install
    
  3. Compilar el proyecto:
    bun run build
    
    Esto compila el código fuente de TypeScript a JavaScript en el directorio dist.

Configuración

El servidor requiere detalles de configuración para tu instancia de Supabase. Estos se pueden proporcionar mediante argumentos de línea de comandos o variables de entorno. Los argumentos de CLI tienen prioridad.

Requeridos:

  • --url <url> o SUPABASE_URL=<url>: La URL HTTP principal de tu proyecto de Supabase (p. ej., http://localhost:8000).
  • --anon-key <key> o SUPABASE_ANON_KEY=<key>: La clave anónima de tu proyecto de Supabase.

Opcionales (pero recomendados/requeridos para ciertas herramientas):

  • --service-key <key> o SUPABASE_SERVICE_ROLE_KEY=<key>: La clave de rol de servicio de tu proyecto de Supabase. Requerida para herramientas privilegiadas y para la creación automática de la función auxiliar execute_sql al inicio.
  • --db-url <url> o DATABASE_URL=<url>: La cadena de conexión directa a PostgreSQL para tu base de datos de Supabase (p. ej., postgresql://postgres:password@localhost:5432/postgres). Requerida para herramientas que necesitan acceso directo a la base de datos (apply_migration, herramientas de Auth, herramientas de Storage, consultas pg_catalog).
  • --jwt-secret <secret> o SUPABASE_AUTH_JWT_SECRET=<secret>: El secreto JWT de tu proyecto de Supabase. Requerido cuando se utiliza --transport http y lo necesita la herramienta verify_jwt_secret.
  • --tools-config <path>: Ruta a un archivo JSON que especifica qué herramientas habilitar (lista blanca). Si se omite, todas las herramientas están habilitadas. Formato: {"enabledTools": ["tool_name_1", "tool_name_2"]}.

Opciones de transporte HTTP (cuando se utiliza --transport http):

  • --port <number>: Puerto del servidor HTTP (predeterminado: 3000).
  • --host <string>: Host del servidor HTTP (predeterminado: 127.0.0.1).
  • --cors-origins <origins>: Lista separada por comas de orígenes CORS permitidos. El valor predeterminado es solo localhost.
  • --rate-limit-window <ms>: Ventana de límite de velocidad en milisegundos (predeterminado: 60000).
  • --rate-limit-max <count>: Máximo de solicitudes por ventana de límite de velocidad (predeterminado: 100).
  • --request-timeout <ms>: Tiempo de espera de solicitud en milisegundos (predeterminado: 30000).

Notas importantes:

  • Función auxiliar execute_sql: Muchas herramientas dependen de una función public.execute_sql dentro de tu base de datos de Supabase para la ejecución de SQL mediante RPC. El servidor intenta comprobar la existencia de esta función al inicio. Si falta y se proporcionan service-key y db-url, intentará crear la función automáticamente. Si la creación falla o no se proporcionan las claves, las herramientas que dependen únicamente de RPC pueden fallar.
  • Acceso directo a la base de datos: Las herramientas que interactúan directamente con esquemas privilegiados (auth, storage) o catálogos del sistema (pg_catalog) generalmente requieren que DATABASE_URL esté configurado.
  • Implementaciones con Coolify / proxy inverso:
    • El DATABASE_URL debe utilizar el nombre de host interno accesible desde donde se ejecuta el proceso del servidor MCP, no el dominio público.
    • Un error ECONNRESET durante el inicio significa que el DATABASE_URL no se puede alcanzar desde el contexto de red del servidor.
    • El servidor aún se iniciará correctamente y todas las herramientas que no requieren una conexión directa a la base de datos seguirán funcionando con normalidad.

Seguridad

Transporte HTTP (recomendado para acceso remoto)

Cuando se ejecuta con --transport http, el servidor aplica:

  • Autenticación JWT en todos los endpoints /mcp utilizando tu SUPABASE_AUTH_JWT_SECRET.
  • Control de acceso basado en privilegios (RBAC) — la reclamación role en el JWT determina qué herramientas son accesibles:
    • service_role: Acceso completo (todas las herramientas, incluidas las privilegiadas).
    • authenticated: Solo herramientas regulares.
    • anon: Sin acceso a herramientas.
  • Límite de velocidad — límite de solicitudes configurable por dirección IP.
  • CORS — lista de orígenes permitidos configurable (el valor predeterminado es solo localhost).
  • Cabeceras de seguridad — X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, etc.
  • Tiempos de espera de solicitud — tiempo de espera configurable para evitar el agotamiento de recursos.

Transporte Stdio (desarrollo local)

El modo Stdio no tiene autenticación — todas las herramientas (incluidas las privilegiadas) son accesibles. Está pensado únicamente para clientes locales de confianza (p. ej., una extensión de IDE que se ejecuta en tu máquina local). Se imprime una advertencia al inicio cuando se utiliza este modo.

Manejo de contraseñas para herramientas de usuarios de autenticación

create_auth_user y update_auth_user aceptan una contraseña en texto plano del cliente MCP y la hashean inmediatamente con bcrypt (mediante la extensión pgcrypto de PostgreSQL: crypt($password, gen_salt('bf'))) antes de almacenarla en auth.users. La contraseña en texto plano nunca se almacena. Las contraseñas se pasan como parámetros de consulta (no se interpolan como cadenas en SQL), lo que previene la inyección SQL.

Nota: La contraseña viaja a través del transporte MCP en texto plano entre el cliente y el servidor MCP. Esto es inherente a la interfaz del protocolo MCP e inevitable en esta capa. Utilice el transporte HTTP con terminación TLS (por ejemplo, detrás de Kong/nginx) para la protección de la red.

Seguridad de la ejecución SQL

Todas las operaciones de base de datos en el servidor MCP utilizan consultas parametrizadas ($1, $2, ...) para prevenir la inyección SQL. La herramienta execute_sql es una excepción intencional: ejecuta SQL arbitrario por diseño (es el propósito de la herramienta). Esta herramienta está restringida al nivel de privilegio service_role para limitar la exposición.

Uso

Modo Stdio (clientes MCP locales)

Ejecute el servidor usando Bun, proporcionando la configuración necesaria:

# Using CLI arguments (stdio mode — default)
bun run dist/index.js --url http://localhost:8000 --anon-key <your-anon-key> \
  --db-url postgresql://postgres:password@localhost:5432/postgres \
  --service-key <your-service-key>

# Example with tool whitelisting via config file
bun run dist/index.js --url http://localhost:8000 --anon-key <your-anon-key> \
  --tools-config ./mcp-tools.json

# Or configure using environment variables and run:
# export SUPABASE_URL=http://localhost:8000
# export SUPABASE_ANON_KEY=<your-anon-key>
# export DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres
# export SUPABASE_SERVICE_ROLE_KEY=<your-service-key>
bun run dist/index.js

Modo HTTP (Docker / acceso remoto)

bun run dist/index.js \
  --transport http \
  --port 3100 \
  --host 0.0.0.0 \
  --url http://kong:8000 \
  --anon-key <your-anon-key> \
  --service-key <your-service-key> \
  --jwt-secret <your-jwt-secret> \
  --db-url postgresql://postgres:password@db:5432/postgres

El modo HTTP requiere --jwt-secret. Todas las solicitudes /mcp deben incluir un JWT de Supabase válido en el encabezado Authorization: Bearer <token>.

El servidor se comunica mediante stdio (predeterminado) o HTTP (Streamable HTTP Transport) y está diseñado para ser invocado por una aplicación cliente MCP (por ejemplo, una extensión de IDE como Cursor). El cliente se conectará al flujo stdio o al endpoint HTTP del servidor para listar y llamar a las herramientas disponibles.

Ejemplos de Configuración de Cliente

A continuación se muestran ejemplos de cómo configurar clientes MCP populares para usar este servidor autoalojado.

Importante:

  • Reemplace los marcadores de posición como <your-supabase-url>, <your-anon-key>, <your-db-url>, <path-to-dist/index.js>, etc., con sus valores reales.
  • Asegúrese de que la ruta al archivo del servidor compilado (dist/index.js) sea correcta para su sistema.
  • Tenga cuidado al almacenar claves sensibles directamente en archivos de configuración, especialmente si se confirman en el control de versiones. Considere usar variables de entorno o métodos más seguros cuando el cliente lo admita.

Cursor

  1. Cree o abra el archivo .cursor/mcp.json en la raíz de su proyecto.

  2. Agregue la siguiente configuración:

    {
      "mcpServers": {
        "selfhosted-supabase": { 
          "command": "bun",
          "args": [
            "run",
            "<path-to-dist/index.js>", // e.g., "/home/user/selfhosted-supabase-mcp/dist/index.js"
            "--url",
            "<your-supabase-url>", // e.g., "http://localhost:8000"
            "--anon-key",
            "<your-anon-key>",
            // Optional - Add these if needed by the tools you use
            "--service-key",
            "<your-service-key>",
            "--db-url",
            "<your-db-url>", // e.g., "postgresql://postgres:password@host:port/postgres"
            "--jwt-secret",
            "<your-jwt-secret>",
            // Optional - Whitelist specific tools
            "--tools-config",
            "<path-to-your-mcp-tools.json>" // e.g., "./mcp-tools.json"
          ]
        }
      }
    }
    

Visual Studio Code (Copilot)

VS Code Copilot permite usar variables de entorno completadas mediante entradas solicitadas, lo que es más seguro para las claves.

  1. Cree o abra el archivo .vscode/mcp.json en la raíz de su proyecto.

  2. Agregue la siguiente configuración:

    {
      "inputs": [
        { "type": "promptString", "id": "sh-supabase-url", "description": "Self-Hosted Supabase URL", "default": "http://localhost:8000" },
        { "type": "promptString", "id": "sh-supabase-anon-key", "description": "Self-Hosted Supabase Anon Key", "password": true },
        { "type": "promptString", "id": "sh-supabase-service-key", "description": "Self-Hosted Supabase Service Key (Optional)", "password": true, "required": false },
        { "type": "promptString", "id": "sh-supabase-db-url", "description": "Self-Hosted Supabase DB URL (Optional)", "password": true, "required": false },
        { "type": "promptString", "id": "sh-supabase-jwt-secret", "description": "Self-Hosted Supabase JWT Secret (Optional)", "password": true, "required": false },
        { "type": "promptString", "id": "sh-supabase-server-path", "description": "Path to self-hosted-supabase-mcp/dist/index.js" },
        { "type": "promptString", "id": "sh-supabase-tools-config", "description": "Path to tools config JSON (Optional, e.g., ./mcp-tools.json)", "required": false }
      ],
      "servers": {
        "selfhosted-supabase": {
          "command": "bun",
          "args": [
            "run",
            "${input:sh-supabase-server-path}",
            "--tools-config", "${input:sh-supabase-tools-config}"
           ],
          "env": {
            "SUPABASE_URL": "${input:sh-supabase-url}",
            "SUPABASE_ANON_KEY": "${input:sh-supabase-anon-key}",
            "SUPABASE_SERVICE_ROLE_KEY": "${input:sh-supabase-service-key}",
            "DATABASE_URL": "${input:sh-supabase-db-url}",
            "SUPABASE_AUTH_JWT_SECRET": "${input:sh-supabase-jwt-secret}"
          }
        }
      }
    }
    
  3. Cuando use Copilot Chat en modo Agente (@workspace), debería detectar el servidor. Se le pedirá que ingrese los detalles (URL, claves, ruta) cuando el servidor se invoque por primera vez.

Otros Clientes (Windsurf, Cline, Claude)

Adapte la estructura de configuración mostrada para Cursor o la documentación oficial de Supabase, reemplazando command y args con el comando bun run y los argumentos para este servidor, similar al ejemplo de Cursor:

{
  "mcpServers": {
    "selfhosted-supabase": { 
      "command": "bun",
      "args": [
        "run",
        "<path-to-dist/index.js>", 
        "--url", "<your-supabase-url>", 
        "--anon-key", "<your-anon-key>", 
        "--service-key", "<your-service-key>", 
        "--db-url", "<your-db-url>", 
        "--jwt-secret", "<your-jwt-secret>",
        "--tools-config", "<path-to-your-mcp-tools.json>"
      ]
    }
  }
}

Consulte la documentación específica de cada cliente sobre dónde colocar el archivo de configuración mcp.json o equivalente.

Integración de Docker con Supabase Autoalojado

Este servidor MCP se puede integrar directamente en una pila de Docker Compose de Supabase autoalojado, haciéndolo disponible junto con otros servicios de Supabase a través de la puerta de enlace de la API de Kong.

Resumen de la Arquitectura

Cuando se integra con Docker:

  • El servidor MCP se ejecuta en modo de transporte HTTP (no stdio)
  • Se expone a través de Kong en /mcp/v1/*
  • La autenticación JWT es manejada por el propio servidor MCP
  • El servidor tiene acceso directo a la base de datos y a todas las claves de Supabase

Pasos de Configuración

1. Agregue el Servidor MCP como un Submódulo de Git

Desde su directorio de Docker de Supabase:

git submodule add https://github.com/HenkDz/selfhosted-supabase-mcp.git selfhosted-supabase-mcp

2. Cree el Dockerfile

Cree volumes/mcp/Dockerfile:

# Dockerfile for selfhosted-supabase-mcp HTTP mode
# Multi-stage build using Bun runtime for self-hosted Supabase

FROM oven/bun:1.1-alpine AS builder

WORKDIR /app

# Copy package files from submodule
COPY selfhosted-supabase-mcp/package.json selfhosted-supabase-mcp/bun.lock* ./

# Install dependencies
RUN bun install --frozen-lockfile || bun install

# Copy source code
COPY selfhosted-supabase-mcp/src ./src
COPY selfhosted-supabase-mcp/tsconfig.json ./

# Build the application
RUN bun build src/index.ts --outdir dist --target bun

# Production stage
FROM oven/bun:1.1-alpine AS runner

WORKDIR /app

# Create non-root user for security
RUN addgroup --system --gid 1001 mcp && \
    adduser --system --uid 1001 --ingroup mcp mcp

# Copy built application from builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# Set ownership
RUN chown -R mcp:mcp /app

USER mcp

# Default environment variables
ENV NODE_ENV=production

# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:3100/health || exit 1

# Expose HTTP port
EXPOSE 3100

# Start the MCP server in HTTP mode
CMD ["bun", "run", "dist/index.js"]

3. Agregue el Servicio MCP a docker-compose.yml

Agregue esta definición de servicio a su docker-compose.yml:

## MCP Server - Model Context Protocol for AI integrations
## DISABLED BY DEFAULT - Add 'mcp' to COMPOSE_PROFILES to enable
mcp:
  container_name: ${COMPOSE_PROJECT_NAME:-supabase}-mcp
  profiles:
    - mcp
  build:
    context: .
    dockerfile: ./volumes/mcp/Dockerfile
  restart: unless-stopped
  healthcheck:
    test:
      [
        "CMD",
        "wget",
        "--no-verbose",
        "--tries=1",
        "--spider",
        "http://localhost:3100/health"
      ]
    timeout: 5s
    interval: 10s
    retries: 3
  depends_on:
    db:
      condition: service_healthy
    rest:
      condition: service_started
  environment:
    SUPABASE_URL: http://kong:8000
    SUPABASE_ANON_KEY: ${ANON_KEY}
    SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY}
    SUPABASE_AUTH_JWT_SECRET: ${JWT_SECRET}
    DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
  command:
    [
      "bun",
      "run",
      "dist/index.js",
      "--transport", "http",
      "--port", "3100",
      "--host", "0.0.0.0",
      "--url", "http://kong:8000",
      "--anon-key", "${ANON_KEY}",
      "--service-key", "${SERVICE_ROLE_KEY}",
      "--jwt-secret", "${JWT_SECRET}",
      "--db-url", "postgresql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
    ]

4. Agregue Rutas de la Puerta de Enlace de la API de Kong

Agregue las rutas MCP a volumes/api/kong.yml en la sección services:

## MCP Server routes - Model Context Protocol for AI integrations
## Authentication is handled by the MCP server itself (JWT validation)
- name: mcp-v1
  _comment: 'MCP Server: /mcp/v1/* -> http://mcp:3100/*'
  url: http://mcp:3100/
  routes:
    - name: mcp-v1-all
      strip_path: true
      paths:
        - /mcp/v1/
  plugins:
    - name: cors
      config:
        origins:
          - "$SITE_URL_PATTERN"
          - "http://localhost:3000"
          - "http://127.0.0.1:3000"
        methods:
          - GET
          - POST
          - DELETE
          - OPTIONS
        headers:
          - Accept
          - Authorization
          - Content-Type
          - X-Client-Info
          - apikey
          - Mcp-Session-Id
        exposed_headers:
          - Mcp-Session-Id
        credentials: true
        max_age: 3600

5. Habilite el Servicio MCP

El servicio MCP usa perfiles de Docker Compose, por lo que está deshabilitado por defecto. Para habilitarlo:

Opción A: Establecer en el archivo .env:

COMPOSE_PROFILES=mcp

Opción B: Habilitar en tiempo de ejecución:

docker compose --profile mcp up -d

Acceso al Servidor MCP

Una vez en ejecución, el servidor MCP está disponible en:

  • Interno (desde otros contenedores): http://mcp:3100
  • Externo (a través de Kong): http://localhost:8000/mcp/v1/

Autenticación

Cuando se ejecuta en modo HTTP, el servidor MCP valida los JWT usando el JWT_SECRET configurado. Los clientes deben incluir un JWT de Supabase válido en el encabezado Authorization:

Authorization: Bearer <supabase-jwt>

El claim role del JWT determina el acceso:

  • service_role: Acceso completo a todas las herramientas (regulares + privilegiadas)
  • authenticated: Acceso solo a herramientas regulares
  • anon: Sin acceso a herramientas

Verificación de Salud

El servidor MCP expone un endpoint de salud:

curl http://localhost:8000/mcp/v1/health

Consideraciones de Seguridad

Al implementar mediante Docker:

  1. El servidor MCP se ejecuta como un usuario no root (mcp:mcp)
  2. La autenticación JWT se aplica para todas las llamadas a herramientas
  3. Las herramientas privilegiadas (como execute_sql) requieren JWT service_role
  4. CORS se configura mediante Kong: ajuste los orígenes para su implementación

Desarrollo

  • Lenguaje: TypeScript
  • Compilación: bun build (mediante bun run build)
  • Runtime: Bun v1.1+
  • Ejecutor de pruebas: bun test
  • Dependencias: Gestionadas mediante bun (bun.lock)
  • Bibliotecas principales: @supabase/supabase-js, pg (node-postgres), zod (validación), commander (argumentos CLI), @modelcontextprotocol/sdk (framework del servidor MCP), express, jsonwebtoken.

Licencia

Este proyecto está licenciado bajo la Licencia MIT. Consulte el archivo LICENSE para obtener más detalles.