shop-sql-mcp
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.dbRequisitos
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 installConfiguración
La configuración es opcional. Por defecto, el servidor abre shop.db en la raíz del proyecto.
Variable | Por defecto | Significado |
|
| 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 buildCompila src/ a dist/.
Ejecución
npm start # runs the built server (dist/index.js)
npm run dev # runs src/index.ts directly, no build stepEl 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.jsHerramientas
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.
limitpor defecto es 100, con un máximo de 500;offsetpor defecto es 0.La consulta del agente se envuelve como
SELECT * FROM (<your sql>) LIMIT ? OFFSET ?, por lo que una consulta que lleve su propioLIMIT 100000no puede devolver más filas de las que marcalimit.El servidor obtiene internamente
limit + 1filas para decidirhasMoresin una segunda consulta de recuento, y devuelve como máximolimit.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
SELECToWITH— una ingenuastartsWith("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 testEjecuta 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 evalIní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.dbDependencias
Paquete | Por qué |
| El SDK oficial de tipo servidor MCP TypeScript (v2). Proporciona |
| 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. |
| Solo en desarrollo: para compilar y verificar el tipado. |
| 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.
This server cannot be installed
Maintenance
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
- AlicenseAqualityCmaintenanceEnables safe, read-only SQL access to SQLite databases for AI agents, allowing schema exploration and SELECT queries with defense-in-depth protections.3MIT
- AlicenseNot gradedqualityDmaintenanceExposes 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.1MIT
- AlicenseAqualityBmaintenanceLets 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.315MIT
- FlicenseNot gradedqualityCmaintenanceExposes 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.
Related MCP Connectors
Explore, query, and inspect SQLite databases with ease. List tables, preview results, and view det…
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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