30分钟,用 MCP 给 AI 开个数据库后门
“Any sufficiently advanced technology is indistinguishable from magic.” — Arthur C. Clarke“我想在 Claude 里直接查线上用户数据能搞不”上周五下班前产品经理提了这个要求。以前碰到这种跟内网系统打交道的活我得老老实实写一套 REST API、搞鉴权、配前台页面折腾下来最少也得三四天。这次我试了下最近很火的 MCPModel Context Protocol。结果半小时写完当场上线。Claude 顺利查到了本地数据库。整个过程比预想的简单得多。为什么这玩意儿不需要写 API之前让 AI 调接口链路挺烦的AI 输出参数 - 你的客户端接住 - 发 HTTP 请求 - 后端处理 - 原路返回。MCP 走的是另一条路。它其实就是个标准总线。你在本地写个 Server通过标准输入输出stdio跟客户端比如 Claude Desktop通讯。AI 启动时会通过 JSON-RPC 问你的 Server“你能干啥”Server 把工具列表一扔AI 就可以直接下发参数调用了。没有网络通信不用配 Web 框架。你写的代码就是给 AI 用的一个“硬件驱动”。极简环境两步搭完直接在干净目录下跑初始化和装依赖别搞那些多余的脚手架# 装官方SDK和 SQLite 驱动npminit-ynpminstallmodelcontextprotocol/sdk zod better-sqlite3npminstall-Dtypescript types/node types/better-sqlite3npx tsc--inittsconfig.json里把target改成ES2022module和moduleResolution改成Node16就行多余的配置不用动。核心实现锁死 readonly整个 Server 的核心逻辑加起来不到60行代码// src/index.tsimport{McpServer}frommodelcontextprotocol/sdk/server/mcp.js;import{StdioServerTransport}frommodelcontextprotocol/sdk/server/stdio.js;import{z}fromzod;importDatabasefrombetter-sqlite3;// 必须只读。AI 有你给的一切权限不锁只读后果自负constdbnewDatabase(users.db,{readonly:true});constservernewMcpServer({name:db-query-server,version:1.0.0,});// 查用户工具server.tool(query_users,根据条件查询用户列表支持按 plan 筛选和 limit 限制,{plan:z.enum([free,pro,enterprise]).optional().describe(套餐类型),limit:z.number().min(1).max(100).default(10).describe(返回上限),},async({plan,limit}){letsqlSELECT id, name, email, plan FROM users;constparams:unknown[][];if(plan){sql WHERE plan ?;params.push(plan);}sql LIMIT ?;params.push(limit);constrowsdb.prepare(sql).all(...params);return{content:[{type:text,text:JSON.stringify(rows,null,2)}],};});consttransportnewStdioServerTransport();awaitserver.connect(transport);这段代码看似简单但有两个坑必须防住readonly: true这是保命的配置。MCP Server 是 AI 在你本地的“手”。AI 一旦脑子抽风发来一条DELETE FROM users你如果不锁只读本地引擎会二话不说直接执行。z.number().describe(返回上限)这里的describe不是用来写注释的。AI 读不懂你的核心代码它是完全靠 Zod 里的描述文字来判断这个参数该传什么的。描述写得越清晰AI 调用时传的参数就越准。stdio的死穴绝对路径与工作目录编译完tsc后需要改下 Claude Desktop 的配置。mac 上的配置文件在~/Library/Application Support/Claude/claude_desktop_config.json{mcpServers:{db-query:{command:node,args:[/Users/你的用户名/mcp-db-server/dist/index.js]}}}这里有两个很容易踩的深坑别用相对路径Claude Desktop 是系统后台进程它的启动目录跟你的项目目录完全没关系。不写绝对路径它根本找不着你的index.js。工作目录会飘因为 Server 是被 Claude Desktop 进程派生出来的如果你的数据库写的是相对路径users.db它会被建在 Claude 自己的缓存路径下导致你本地灌的测试数据完全查不到。代码里最好用path.resolve锁定数据库的绝对路径。搞定收工重启 Claude工具栏里已经能看到query_users了。我试着问了一句查查 pro 套餐的用户有哪些Claude 默默调了本地的query_users拿到数据后回复目前 pro 套餐的用户有张三和赵六。产品经理在旁边看傻了回去就把那个“用户数据查询后台”的需求单给关了。如果只是想极速验证一些内网数据的投射用 MCP 确实比写一套 REST API 舒服得多。 数据来源与参考资料Model Context Protocol Spec: Anthropic MCP Docs.TypeScript MCP SDK Ref: Github Repository docs.better-sqlite3 documentation: SQLite Node driver manual.

相关新闻