MCP(Model Context Protocol)已经是 AI 客户端接入外部能力的事实标准,文件、数据库、内部 API 都通过它暴露成工具。中文资料大多停在概念层,真正卡人的是配置:传输方式怎么选、权限划到哪一层、连不上时该看哪里。下面从零把一个本地目录和一个 SQLite 数据库接进支持 MCP 的客户端。
一、先选传输方式:stdio 还是 HTTP
传输层决定客户端怎么找到服务器,这一步选错,后面的配置都是白费。
- stdio:客户端负责启动服务器进程,双方通过标准输入输出收发 JSON-RPC 消息。不监听端口、不经过网络,权限天然收敛在本机;代价是一个进程只服务一个客户端,无法常驻复用。
- HTTP:服务器独立常驻并监听端口,多个客户端可以同时连接。MCP 规范中的远程传输标准是 Streamable HTTP(2025-03-26 版规范起),早期的 HTTP + SSE 方案作为兼容保留。适合团队共享和容器化部署,但认证、TLS 与暴露面都要自己解决。
判断规则很直接:数据在本机、只给自己用、不需要长跑,选 stdio;要多人共用或放到服务器上,选 HTTP。混合架构也很常见——本地文件目录走 stdio,公司数据库走带 Bearer Token 的 HTTP 端点。
二、stdio 的配置写法
以官方参考实现里的文件系统服务器为例,它的参数就是允许访问的目录:
{
"mcpServers": {
"files": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/mcp-workspace"]
}
}
}
Claude Desktop 的配置文件在 macOS 是 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 在 %APPDATA%\Claude\ 目录下。命令建议写绝对路径(用 which npx 查出来),因为 GUI 客户端经常拿不到完整的 shell PATH,这是新手最容易踩的坑。
三、把 SQLite 数据库接进来
SQLite 用 Python 版参考服务器,uvx 或 pipx 都能拉起:
{
"mcpServers": {
"sqlite": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "/Users/me/mcp-workspace/data.db"]
}
}
}
它对外暴露 list_tables、describe_table、read_query,同时也带有 write_query 和 create_table。所以不要把它直接指向生产库本体:先复制一份快照,或把文件权限改成只读(chmod 400),让写操作在物理层面失败,而不是指望模型自觉。
四、权限边界划在哪里
- 目录只授权必需的最小范围。不要给家目录或根目录,父目录被授权等于整棵子树被授权。
- 数据库给副本或只读挂载;确实需要写入,就单独开一个库,与查询库分开。
- 服务器进程用独立系统用户运行,或放进容器里,只挂载被授权的目录。
- HTTP 端点默认只监听 127.0.0.1;对外暴露必须挂在反向代理后面,加 TLS 与 Token / OAuth 鉴权。
- 记住工具调用的返回内容会进入模型上下文,涉及密钥、个人信息的目录不要授权。
五、连接失败的排查路径
- 改完配置要彻底退出客户端再启动,托盘里残留的进程不算重启。
- 手动在终端跑一遍同样的命令,缺 node、uv、python 会立刻报出来。
- 服务器不能往 stdout 写日志。stdout 是 JSON-RPC 通道,任何一行多余输出都会让客户端解析失败,日志一律走 stderr。
- 看客户端日志:macOS 在 ~/Library/Logs/Claude/ 下的 mcp-server-*.log,Windows 在 %APPDATA%\Claude\logs。
- 用 MCP Inspector(npx @modelcontextprotocol/inspector)直连一次,能正常列出 tools/list 说明服务器没问题,故障点在客户端配置。
- HTTP 场景先 curl 端点:401/403 是鉴权问题,406 通常是 Accept 头没同时带 application/json 和 text/event-stream;反向代理要关闭响应缓冲,否则流式返回会被卡住。
- 报 EACCES、SQLITE_CANTOPEN、SQLITE_READONLY,基本是权限问题,回到上一节的边界设定检查。
六、小结
MCP 的复杂度不在协议本身,而在传输选择和权限收口。建议先用 stdio 把最小闭环跑通,确认 tools/list 正常返回,再判断是否有必要把它暴露成 HTTP 端点供多人使用。

