shop-sql-mcp
shop-sql-mcp
一个小型 MCP 服务器,通过 stdio 为 AI 代理提供对 shop.db SQLite 数据库的只读分析访问。
该服务器只做三件事,不多做:它列出表、描述表结构,并在每次调用时运行一条只读 SQL 语句,且由服务器强制分页。所有推理——做哪些 JOIN、如何聚合、何时查看 schema——都由代理负责。
AI Agent
|
| MCP over stdio
v
shop-sql-mcp
|
+-- list_tables
+-- describe_table
+-- query_database
|
v
read-only SQLite connection
|
v
shop.db要求
Node.js 22.5 或更新版本(推荐 24+)。该服务器使用内置的
node:sqlite模块,所以没有需要编译的原生 SQLite 依赖。没有其他运行时依赖。
Related MCP server: mcpserve-py
安装
npm install配置
配置是可选的。默认情况下,服务器在项目根目录打开 shop.db。
变量 | 默认值 | 含义 |
|
| SQLite 文件的路径。相对路径基于项目根目录解析,因此服务器不依赖于启动时的工作目录。 |
如果想保留本地覆盖配置,请将 .env.example 复制为 .env。服务器本身读取普通环境变量;.env.example 中的 ANTHROPIC_API_KEY、EVAL_MODEL 和 EVAL_MAX_STEPS 仅由 npm run eval 使用。
构建
npm run build将 src/ 编译到 dist/。
运行
npm start # runs the built server (dist/index.js)
npm run dev # runs src/index.ts directly, no build step服务器在 stdin/stdout 上进行 MCP 通信,并且只在 stderr 上打印诊断信息,因此在终端中运行它看起来像卡住了——这是正常现象。它应由 MCP 宿主启动。
连接 MCP 代理
将下面内容添加到你的 MCP 宿主配置中(Claude Desktop 的 claude_desktop_config.json、Claude Code 的 .mcp.json,或你的宿主对应的配置文件),并使用项目的绝对路径:
{
"mcpServers": {
"shop-sql": {
"command": "node",
"args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"]
}
}
}若要直接从源码运行而不先构建,请指向 TypeScript 入口点——Node 会直接执行它:
{
"mcpServers": {
"shop-sql": {
"command": "node",
"args": ["/absolute/path/to/shop-sql-mcp/src/index.ts"]
}
}
}要读取其他位置的数据库:
{
"mcpServers": {
"shop-sql": {
"command": "node",
"args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"],
"env": { "DATABASE_PATH": "/absolute/path/to/other.db" }
}
}
}对于 Claude Code,你还可以从命令行注册它:
claude mcp add shop-sql -- node /absolute/path/to/shop-sql-mcp/dist/index.js工具
list_tables
无参数。返回用户表;内部 sqlite_* 表会被隐藏。
{
"tables": [
{ "name": "customers" },
{ "name": "order_items" },
{ "name": "orders" },
{ "name": "products" }
]
}describe_table
{ table: string }实时从 SQLite 读取表结构——没有硬编码内容——报告列、类型、可空性、主键和外键:
{
"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" }
]
}未知名称是可恢复的错误,不会导致崩溃:
{ "error": { "code": "TABLE_NOT_FOUND", "message": "TABLE_NOT_FOUND: Table \"foo\" does not exist." } }注意:INTEGER PRIMARY KEY 列会被报告为 nullable: false。SQLite 的 table_info 会返回不同的结果,但这种列是 rowid 的别名,永远不可能为 NULL。
query_database
{ sql: string; limit?: number; offset?: number }运行一条只读语句——SELECT ... 或 WITH ... SELECT ...——支持 JOIN、WHERE、GROUP BY、HAVING、ORDER BY、子查询、聚合以及日期过滤。
{
"columns": ["category", "revenue"],
"rows": [["Electronics", 1234567.89]],
"returnedRows": 1,
"limit": 100,
"offset": 0,
"hasMore": false
}行是按照 columns 顺序排列的值数组。这让结果数据保持紧凑,并且在查询产生两个同名列时也不会产生歧义。
失败会作为普通工具结果返回,设置 isError,并附带简短、可操作的信息,让代理能够修复其 SQL 并重试:
{ "error": { "code": "SQL_ERROR", "message": "no such column: total" } }错误代码:SQL_ERROR、READ_ONLY_VIOLATION、MULTIPLE_STATEMENTS、TABLE_NOT_FOUND、INVALID_ARGUMENT、DATABASE_UNAVAILABLE。堆栈跟踪永远不会返回。
分页
分页由服务器强制执行,而不是由模型的 SQL 控制。
limit默认为 100,最大 500;offset默认为 0。代理的查询会被包装为
SELECT * FROM (<your sql>) LIMIT ? OFFSET ?,因此即使查询自带LIMIT 100000,返回的行数也不会超过limit。服务器内部会获取
limit + 1行来判断hasMore,不需要第二次计数查询,并且最多返回limit行。因此单次调用永远不会返回超过 500 行,这样宽范围的
SELECT *就不会淹没模型的上下文。
要分页遍历结果,请保持 SQL 不变(使用确定性的 ORDER BY),并在 hasMore 为 true 时让 offset 按 limit 递增。
只读安全性
两层独立防护,因此没有任何一层需要单独负责。
1. SQL 验证(src/sqlSafety.ts)。一个小型词法分析器跳过注释、字符串字面量和带引号的标识符,然后要求:
语句以
SELECT或WITH开头——简单的startsWith("SELECT")会拒绝合法的只读 CTE;只能有一条语句(第一个
;之后的所有内容都会被拒绝,字面量或注释中的;不算分隔符);任何地方都不能出现禁止的关键字——包括嵌套在 CTE 内部:
INSERT、UPDATE、DELETE、CREATE、DROP、ALTER、REPLACE、ATTACH、DETACH、VACUUM、REINDEX、PRAGMA、ANALYZE、BEGIN、COMMIT、ROLLBACK、SAVEPOINT、load_extension、writable_schema。
禁止的 SQL 总是会被显式错误拒绝——绝不会被静默忽略,也绝不会被部分执行。REPLACE(a, b, c) 作为标量函数仍然是允许的,因为只有 REPLACE INTO 语句才是写操作。
2. SQLite 连接本身。shop.db 使用 new DatabaseSync(path, { readOnly: true }) 打开。即使写操作绕过 SQL 验证,SQLite 也会以 "attempt to write a readonly database" 拒绝它。测试套件通过绕过验证器直接在连接上执行写操作来验证这种行为。
错误或禁止的查询会作为工具错误返回,并且绝不会导致进程终止,因此会话可以承受任意多次失败尝试。
运行测试
npm test只运行 确定性 测试套件——无网络、无 API 密钥、无 LLM。Node 内置测试运行器直接执行 TypeScript 源码。覆盖范围包括:list_tables、describe_table(列、类型、可空性、主键、外键、未知表)、简单 SELECT、过滤、聚合、连接、GROUP BY、只读 CTE、日期过滤、分页(默认 limit、最大 limit、offset、hasMore 边界)、无效 SQL、未知列和表、拒绝 INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/REPLACE/ATTACH/DETACH/VACUUM/REINDEX/PRAGMA 和多个语句、证明每次写入被拒绝后数据库内容完全一致,以及通过 stdio 进行端到端 MCP 调用确认服务器在错误后仍然可用。
手动运行 eval
export ANTHROPIC_API_KEY=sk-...
npm run eval请手动启动它。 它特意被排除在 npm test 之外,因为它会通过 stdio 驱动真实 LLM 对接真实 MCP 服务器,并产生付费 API 调用。
它会启动服务器,把三个 MCP 工具以及一个 submit_answer 工具交给模型,后者的 JSON schema 针对每个任务固定,并将结构化答案与直接从 SQLite 计算的参考值进行比较——而不是与自然语言文本进行比较。任务覆盖:表发现、多步 schema 发现、过滤、聚合、连接、客户总消费、客户订单数、产品销量、类别收入、2025 年收入,以及一个必须被拒绝的破坏性请求(检查还会验证数据库在之后没有被修改)。
可选配置:EVAL_MODEL(默认为 claude-sonnet-5)和 EVAL_MAX_STEPS(默认为 12)。如果任何任务失败,退出码非零。
目录结构
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依赖
包 | 说明 |
| 官方 MCP TypeScript SDK(v2)。提供 |
| SDK 用于工具输入/输出 schema 的依赖;它向代理发布机器可读的参数类型。 |
| 仅开发依赖:构建和类型检查。 |
| 仅开发依赖:官方 MCP 客户端,用于 stdio 端到端测试和 eval 运行器。 |
SQLite 来自 Node 内置的 node:sqlite,测试来自 Node 内置的测试运行器,eval 的 HTTP 调用来自内置的 fetch——没有安装任何数据库驱动、ORM、查询构建器、Web 框架、日志库、测试框架、SQL 解析器或 LLM SDK。
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