Skip to main content
Glama
lampmaster

shop-sql-mcp

by lampmaster

shop-sql-mcp

Un pequeño servidor MCP que ofrece a un agente de IA un acceso analítico de solo lectura a la base de datos SQLite shop.db a través de stdio.

El servidor hace tres cosas y nada más: lista las tablas, describe su esquema y ejecuta una única sentencia SQL de solo lectura por llamada con paginación impuesta por el servidor. Todo el razonamiento — qué uniones hacer, cómo agregar, cuándo consultar el esquema — pertenece al agente.

AI Agent
    |
    |  MCP over stdio
    v
shop-sql-mcp
    |
    +-- list_tables
    +-- describe_table
    +-- query_database
    |
    v
read-only SQLite connection
    |
    v
shop.db

Requisitos

  • Node.js 22.5 o superior (24+ recomendado). El servidor utiliza el módulo integrado node:sqlite, por lo que no hay ninguna dependencia nativa de SQLite que compilar.

  • No hay otros prerrequisitos de ejecución.

Related MCP server: mcpserve-py

Instalación

npm install

Configuración

La configuración es opcional. Por defecto, el servidor abre shop.db en la raíz del proyecto.

Variable

Por defecto

Significado

DATABASE_PATH

<project>/shop.db

Ruta al archivo SQLite. Las rutas relativas se resuelven con respecto a la raíz del proyecto, de modo que el servidor no depende del directorio de trabajo en el que se ejecuta.

Copia .env.example a .env si quieres conservar anulaciones locales. El propio servidor lee variables de entorno normales; ANTHROPIC_API_KEY, EVAL_MODEL y EVAL_MAX_STEPS de .env.example las usa solo npm run eval.

Compilación

npm run build

Compila src/ a dist/.

Ejecución

npm start              # runs the built server (dist/index.js)
npm run dev            # runs src/index.ts directly, no build step

El servidor habla MCP por stdin/stdout y no imprime nada más que diagnósticos en stderr, por lo que ejecutarlo en una terminal parece que se queda colgado — y eso es correcto. Está pensado para que lo lance un host de MCP.

Conexión a un agente MCP

Añade esto a la configuración de tu host MCP (claude_desktop_config.json de Claude Desktop, .mcp.json para Claude Code, o el archivo equivalente de tu host), usando una ruta absoluta al proyecto:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"]
    }
  }
}

Para ejecutarlo desde el código fuente sin compilar, apunta al punto de entrada TypeScript — Node lo ejecuta directamente:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/src/index.ts"]
    }
  }
}

Para leer una base de datos en otra ubicación:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"],
      "env": { "DATABASE_PATH": "/absolute/path/to/other.db" }
    }
  }
}

Con Claude Code también puedes registrarlo desde la línea de comandos:

claude mcp add shop-sql -- node /absolute/path/to/shop-sql-mcp/dist/index.js

Herramientas

list_tables

No tiene argumentos. Devuelve las tablas de usuario; las tablas internas sqlite_* quedan ocultas.

{
  "tables": [
    { "name": "customers" },
    { "name": "order_items" },
    { "name": "orders" },
    { "name": "products" }
  ]
}

describe_table

{ table: string }

Lee el esquema en vivo desde SQLite — no hay nada incrustado — e indica columnas, tipos, nulabilidad, claves primarias y claves externas:

{
  "table": "order_items",
  "columns": [
    { "name": "id", "type": "INTEGER", "nullable": false, "primaryKey": true },
    { "name": "order_id", "type": "INTEGER", "nullable": false, "primaryKey": false }
  ],
  "foreignKeys": [
    { "column": "order_id", "referencesTable": "orders", "referencesColumn": "id" },
    { "column": "product_id", "referencesTable": "products", "referencesColumn": "id" }
  ]
}

Un nombre desconocido es un error recuperable, no un cierre del proceso:

{ "error": { "code": "TABLE_NOT_FOUND", "message": "TABLE_NOT_FOUND: Table \"foo\" does not exist." } }

Nota: una columna que sea INTEGER PRIMARY KEY se muestra como nullable: false. table_info de SQLite dice lo contrario, pero esa columna es un alias de rowid y nunca puede contener NULL.

query_database

{ sql: string; limit?: number; offset?: number }

Ejecuta una única sentencia de solo lectura — SELECT ... o WITH ... SELECT ... — con soporte para JOIN, WHERE, GROUP BY, HAVING, ORDER BY, subconsultas, agregaciones y filtrado por fecha.

{
  "columns": ["category", "revenue"],
  "rows": [["Electronics", 1234567.89]],
  "returnedRows": 1,
  "limit": 100,
  "offset": 0,
  "hasMore": false
}

Las filas son arrays de valores en el orden de columns. Esto mantiene compactas las cargas útiles de resultados y evita ambigüedades cuando una consulta devuelve dos columnas con el mismo nombre.

Los fallos vuelven como resultado normal de la herramienta con isError activado y una respuesta corta y accionable, para que el agente pueda corregir su SQL e intentarlo de nuevo:

{ "error": { "code": "SQL_ERROR", "message": "no such column: total" } }

Códigos de error: SQL_ERROR, READ_ONLY_VIOLATION, MULTIPLE_STATEMENTS, TABLE_NOT_FOUND, INVALID_ARGUMENT, DATABASE_UNAVAILABLE. Las trazas de pila nunca se devuelven.

Paginación

La paginación la impone el servidor, no la SQL del modelo.

  • limit por defecto es 100, con un máximo de 500; offset por defecto es 0.

  • La consulta del agente se envuelve como SELECT * FROM (<your sql>) LIMIT ? OFFSET ?, por lo que una consulta que lleve su propio LIMIT 100000 no puede devolver más filas de las que marca limit.

  • El servidor obtiene internamente limit + 1 filas para decidir hasMore sin una segunda consulta de recuento, y devuelve como máximo limit.

  • Por tanto, una sola llamada nunca devuelve más de 500 filas, lo que evita que un SELECT * amplio inunde el contexto del modelo.

Para paginar los resultados, mantén la SQL idéntica (con un ORDER BY determinista) y avanza offset en limit mientras hasMore sea true.

Seguridad de solo lectura

Dos capas independientes, de modo que ninguna sea crítica por sí sola.

1. Validación SQL (src/sqlSafety.ts). Un pequeño lexer omite comentarios, literales de cadena e identificadores entre comillas, y después exige que:

  • la instrucción empiece por SELECT o WITH — una ingenua startsWith("SELECT") rechazaría los CTEs de solo lectura válidos;

  • haya exactamente una sola instrucción (se rechaza todo lo que venga después del primer ;, y un ; dentro de un literal o comentario no es un separador);

  • no aparezca ninguna palabra clave prohibida en ningún sitio, incluido dentro de un CTE: INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, REPLACE, ATTACH, DETACH, VACUUM, REINDEX, PRAGMA, ANALYZE, BEGIN, COMMIT, ROLLBACK, SAVEPOINT, load_extension, writable_schema.

El SQL prohibido siempre se rechaza con un error explícito — nunca se ignora en silencio ni se ejecuta parcialmente. REPLACE(a, b, c) sigue estando permitido como función escalar, ya que solo la sentencia REPLACE INTO es una escritura.

2. La propia conexión SQLite. shop.db se abre con new DatabaseSync(path, { readOnly: true }). Incluso si una escritura sortease la validación, SQLite la rechaza con "attempt to write a readonly database". La suite de pruebas lo comprueba directamente lanzando escrituras sobre la conexión y eludiendo el validador.

Las consultas erróneas o prohibidas se devuelven como errores de herramienta y nunca terminan el proceso, de modo que una sesión sobrevive cualquier número de intentos fallidos.

Ejecutar pruebas

npm test

Ejecuta solo la suite determinista — sin red, sin claves de API, sin LLM. El ejecutor de pruebas integrado de Node ejecuta los archivos TypeScript directamente. La cobertura incluye: list_tables, describe_table (columnas, tipos, nulabilidad, claves primarias, claves externas, tablas desconocidas), selección simple, filtrado, agregación, uniones, GROUP BY, CTEs de solo lectura, filtrado por fecha, paginación (límite por defecto, límite máximo, offset, límites de hasMore), SQL no válido, columnas y tablas desconocidas, rechazo de INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/REPLACE/ATTACH/DETACH/VACUUM/REINDEX/PRAGMA y de múltiples sentencias, prueba de que la base de datos queda byte-idéntica después de cada escritura rechazada, y llamadas MCP de extremo a extremo por stdio que confirman que el servidor sigue operativo tras errores.

Ejecutar la evaluación manualmente

export ANTHROPIC_API_KEY=sk-...
npm run eval

Inícielo manualmente. Está excluido deliberadamente de npm test porque enciende un LLM real contra el servidor MCP real sobre stdio y hace llamadas de API de pago.

Inicia el servidor, entrega al modelo las tres herramientas MCP más una herramienta submit_answer cuyo esquema JSON es fijo por tarea, y compara la respuesta estructurada contra un valor de referencia calculado directamente con SQLite, no contra texto en lenguaje natural. Las tareas cubren descubrimiento de tablas, descubrimiento de esquema en varios pasos, filtrado, ordenamiento, agregación, joins, gasto por cliente, recuento de pedidos por cliente, ventas por producto, ingresos por categoría, ingresos en 2025 y una petición destructiva que debe rechazarse (la comprobación también verifica que la base de datos quede sin cambios después).

Opcionales: EVAL_MODEL (por defecto claude-sonnet-5) y EVAL_MAX_STEPS (por defecto 24). El código de salida es distinto de cero si falla cualquier tarea.

Estructura

src/
  index.ts       MCP server: tool registration, stdio wiring, error shaping
  db.ts          read-only connection, path resolution, row/value normalisation
  tools.ts       the three tools: list_tables, describe_table, query_database
  sqlSafety.ts   single-statement read-only SQL validation
tests/
  sqlSafety.test.ts   validator, allowed and forbidden SQL
  tools.test.ts       tools against the real shop.db
  mcp.test.ts         end-to-end over stdio with a real MCP client
eval/
  tasks.ts       eval tasks and their SQLite reference values
  run.ts         LLM + MCP eval runner (manual)
shop.db

Dependencias

Paquete

Por qué

@modelcontextprotocol/server

El SDK oficial de tipo servidor MCP TypeScript (v2). Proporciona McpServer y transporte stdio para que no se implemente el protocolo a mano.

zod

Requerido por el SDK para los esquemas de entrada/salida de herramientas; es lo que expone al agente los tipos de argumento legibles por máquina.

typescript, @types/node

Solo en desarrollo: para compilar y verificar el tipado.

@modelcontextprotocol/client

Solo en desarrollo: el cliente MCP oficial, utilizado por las pruebas de extremo a extremo con stdio y el runner de evaluación.

SQLite proviene del node:sqlite incorporado en Node, las pruebas del ejecutor de pruebas incorporado en Node, y las llamadas HTTP de la evaluación del fetch incorporado — no se instala ningún driver, ORM, construcctor de consultas, framework web, registrador, framework de pruebas, analizador SQL ni SDK de LLM.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes SQLite database query tools and markdown document resources over JSON-RPC 2.0 stdio transport, enabling AI assistants to read and search documents and execute read-only SQL queries.
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets AI agents query local SQLite database files read-only using Node's built-in sqlite module, providing tools for listing tables, describing schemas, and running SQL queries.
    3
    15
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes any SQLite database as read-only MCP tools for AI assistants, enabling listing tables, describing schemas, and running SELECT queries with filtering, ordering, and pagination.

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lampmaster/shop-sql-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server