MCP.json 配置完整教程与实战示例
写代码的时候,我越来越依赖 Claude Code、Cursor 这类 AI 编程工具。用得越深,越发现一个绕不开的坎:AI 只能“看”,不能“动”。它帮你翻项目文件、跑测试、查数据库,靠的是一套叫 MCP 的外部工具协议,而 mcp.json 就是那本“通讯录”,告诉 AI 工具该去哪里调服务。今天专门把这份配置文件的写法和实战经验整理出来,填上文档没写清楚的那些坑。
这套配置的受众很明确:在用或用过 Claude Code、Cline、Windsurf、Cursor 等支持 MCP 的 AI 编程工具,想让 AI 真正操作真实环境的人。看完你至少能自己写出一份可运行的 mcp.json,遇到报错也知道从哪下手查。我会先从结构讲起,再给完整实战示例,最后是踩坑实录。
1. 先搞懂 MCP 和 mcp.json 之间的关系
1.1 MCP 到底解决什么问题
MCP 全称 Model Context Protocol,说人话就是:给 AI 模型开了一个“万能插头”。以前 AI 能力再强,也只能在你提供的文本上下文里绕圈,它不知道你本地磁盘上有什么文件、数据库里存了什么记录、GitHub 上哪个 Issue 还没关。MCP 协议把这个限制打破了——AI 可以通过一套标准化的消息格式,去调用外部工具,拿回真实世界的数据。
这就像给一个只会看菜单的人,配了一个能伸向后厨的手。菜单是对话,后厨是工具。MCP 服务器就是这个“手”,它负责把 AI 的请求翻译成具体的命令(比如读文件、查表、调 API),再把结果翻译回 AI 能懂的文本。
关键点是:所有 MCP 服务器的连接信息、启动参数、环境变量,都被统一写在一个 JSON 文件里,这个文件就是 mcp.json。你只需要告诉支持 MCP 的客户端“去加载这个文件”,它就能自动拉起一堆工具服务。
1.2 配置文件在项目里怎么放
mcp.json 的常见位置有三个,各有各的用途:
- 项目级:放在当前项目根目录,文件名也叫
.mcp.json(带点)或mcp.json。项目级配置只对当前项目生效,适合放这个项目专用的工具,比如数据库连接、项目独有的脚本。 - 用户级:放在用户主目录下,Claude Code 里默认是
~/.claude.json这类文件,对所有项目生效,适合放通用工具,比如文件系统、GitHub。 - 编辑器级:Cursor 和 VS Code 的 MCP 配置面板里可以单独加,等效于一个全局配置,只是入口在 GUI 界面里。
我个人的习惯是:全局要用的工具放用户级,项目专属的工具一律放到项目目录的 .mcp.json,这样 clone 下来新仓库时配置文件跟着走,团队成员直接就能用同一套工具,省去大量沟通成本。
1.3 为什么说它是 AI 工具链里的“基础设施”
如果只把 mcp.json 当成一个普通配置文件,你大概率会在某个奇怪的问题上卡上半小时。它本质上是一个进程编排文件:客户端会读取这个 JSON,然后按照里面的 command 自动启动子进程,再跟子进程建立标准输入输出的通信通道(stdio)。
所以配置里每一个字段都直接影响进程能不能正常启动、能不能连上。写错一个路径,AI 面板上显示的可能不是“启动失败”,而是幽怨地转圈然后提示超时。我一直建议把 mcp.json 当成“生产环境部署脚本”来对待,而不是随便填个命令试运气。这样心态对,后面遇到问题才不会慌。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. mcp.json 核心字段拆解,每个字符都要理解
2.1 找一个最小可运行的配置当模板
先看一个最基本、能立刻跑起来的例子:
json复制{
"mcpServers": {
"github": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
这个配置声明了一个叫 github 的 MCP 服务,用 npx 启动 GitHub 官方 MCP 包,然后传入了一个 GITHUB_PERSONAL_ACCESS_TOKEN 环境变量。看懂这三行,后面 90% 的配置都能举一反三。
顶层节点固定叫 mcpServers,你所有的服务都要挂在这个节点下面。每个服务是一个 key-value 结构,key 是服务名(自己起,要见名知意),value 是服务参数。
2.2 command、args、env、type 四个字段的角色
command:指定启动方式。最常见的有这几种:npx(Node 生态)、uvx(Python 生态)、python或python3(直接跑脚本)、docker(容器化跑)。args:数组形式,按顺序传给命令的参数。重点是参数顺序,npx -y 包名 路径参数和npx 包名 -y 路径参数的含义完全不同,命令行的解析顺序是严格从左到右的。env:对象形式,定义这个子进程的环境变量。你可以写死字符串,也可以像${GITHUB_TOKEN}这样引用当前 shell 里已有的环境变量。推荐用后者,避免把密钥明文写在文件里。type:连接类型。默认是stdio,即通过标准输入输出通信。如果漏写,大部分客户端会按stdio处理。只有远程 MCP 服务才需要显式写成"type": "http",并配合url字段使用。
2.3 这些字段的“为什么”比“是什么”更重要
为什么 command 推荐用 npx -y 而不是 npx?因为不带 -y 时,如果包没下载过,npx 会交互式地问“是否安装?”,而 MCP 客户端是在后台启动子进程,根本没法交互,于是进程就一直挂起,AI 那边显示“连接中”,实际上是在等一个永远不会出现的确认。
为什么 env 要用 ${VAR} 而不是直接写 token?因为 mcp.json 可能会被提交到 Git 仓库,写明文 token 等于把密钥公之于众。用变量引用,是通用且安全的做法,即使仓库被 clone 出去也不会泄露。
为什么路径参数要放在 args 里而不是 env 里?因为很多 MCP 包的设计就是从命令行参数读取路径,环境变量只负责传认证信息。你把路径塞进 env,大概率是什么效果也没有,因为服务器程序压根不会去读那个变量。
3. 五种实战场景,从零到一完整抄作业
3.1 文件系统 MCP:让 AI 直接读写项目目录
最常见的需求是让 AI 能直接查看和编辑本地文件,而不只是粘贴代码片段。官方文件系统服务器是 @modelcontextprotocol/server-filesystem,配置如下:
json复制{
"mcpServers": {
"project-files": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/me/projects/my-app",
"/Users/me/projects/shared-lib"
],
"env": {}
}
}
}
注意 args 里最后两行是目录路径列表,可以传多个,表示这个 MCP 服务器允许访问哪些目录。路径必须是绝对路径,相对路径在这里无效。
这里有个安全细节:你能给这个 MCP 开多少目录,决定了 AI 的“手”能伸多长。如果只让它处理当前项目,就只开项目目录;如果想让 AI 辅助搜索多个代码库,再把共享目录加进去。别图省事直接开根目录 /,AI 的权限边界完全依赖你设置的路径范围。
3.2 GitHub MCP:管理 Issue、PR、代码搜索
GitHub 官方 MCP 在团队协作场景特别有用。AI 可以直接拉取仓库列表、读 Issue、创建 PR,甚至帮你把聊天内容整理成 Issue 发布。配置如下:
json复制{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
GITHUB_TOKEN 需要提前在系统环境变量里配置好。在 Linux/macOS 上,写在 ~/.bashrc 或 ~/.zshrc 里:
bash复制export GITHUB_TOKEN="ghp_xxxx"
Windows 用户可以在 PowerShell 执行 setx GITHUB_TOKEN "ghp_xxxx",设置后需要重开终端才能生效。
这个 token 的权限不要无脑给全部,MCP 工具用到什么就给什么。比如只做代码搜索的,给 repo 读取权限就够了;要创建 PR 的,再给 issues:write、pulls:write。给太多权限,万一 token 泄露,损失范围会失控。
3.3 数据库 MCP:AI 直查 SQLite / PostgreSQL
数据库接入是最能直观感受“AI 真的能干活”的场景。SQLite 的 MCP 服务器配置相当简洁:
json复制{
"mcpServers": {
"local-sqlite": {
"command": "uvx",
"args": [
"mcp-server-sqlite",
"--db-path",
"/Users/me/data/app.db"
],
"env": {}
}
}
}
我用的是 uvx 而不是 npx,因为这个包是 Python 生态的。如果你机器上没装 uv,需要先安装:
bash复制pip install uv
PostgreSQL 的场景稍微复杂一点,但核心思路一样。连接串这种敏感信息走环境变量:
json复制{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://localhost:5432/mydb"
],
"env": {
"PGPASSWORD": "${PGPASSWORD}"
}
}
}
}
这里要多说一句。很多新手把数据库连接串直接写进 mcp.json,然后提交到 Git——这是我最不推荐的做法。连接串里有数据库密码,等于给整条数据库开了一条公开后门。用 ${PGPASSWORD} 引用外部变量,让连接串里只留用户名和库名,安全性会高一个档次。
3.4 自定义脚本 MCP:用 Python 写一个专属工具
官方包解决不了所有场景,比如公司内部有一个特殊接口,只有一组签名规则才能调用。这时候可以自己写一个 MCP 服务器,把内部接口包装成 AI 可用的工具。
最简单的脚手架只需要一个 Python 文件:
python复制from mcp.server.fastmcp import FastMCP
mcp = FastMCP("internal-api")
@mcp.tool()
def query_order(order_id: str) -> str:
"""查询内部订单状态"""
# 这里是你的业务逻辑
return f"订单 {order_id} 状态:已发货"
if __name__ == "__main__":
mcp.run()
然后 mcp.json 这样配:
json复制{
"mcpServers": {
"internal-api": {
"command": "python",
"args": ["/path/to/my_mcp_server.py"],
"env": {}
}
}
}
用这种方案,AI 就能直接调用 query_order 这个函数,相当于把内部接口的能力安全地暴露给了聊天窗口。写自定义 MCP 服务器时,我强烈建议给每个工具函数加上清晰的中文或英文 docstring,因为这个描述就是 AI 决定“什么时候该用这个工具”的依据。描述写得含糊,AI 会频繁调用错的工具,或者在不需要时也去试。
3.5 远程 HTTP MCP:连接线上服务
如果你有一个部署在远程服务器上的 MCP 服务,或者用第三方 MCP 托管平台,配置就从 stdio 切换到 http:
json复制{
"mcpServers": {
"remote-api": {
"type": "http",
"url": "https://mcp.internal.example.com/mcp",
"headers": {
"Authorization": "Bearer ${MCP_API_TOKEN}"
}
}
}
}
这种模式的好处是不用本地跑任何进程,启动速度快,也不依赖本地运行时环境。缺点是每次调用都有网络开销,而且依赖远程服务的稳定性。如果团队共享一个 MCP 服务,远程部署是比每个人都本地拉包更合理的方案。
4. 配置到生效的完整流程,别在最后一步掉链子
4.1 在 Claude Code 里加载并验证配置
Claude Code 是通过 claude mcp 命令来管理的。我的标准操作流程是:
bash复制# 加载项目级的 .mcp.json
claude mcp add --transport stdio --config .mcp.json
# 或者手动添加单个服务器
claude mcp add github -- npx -y @modelcontextprotocol/server-github
配置完成后,在 Claude Code 会话中输 /mcp,就能看到所有服务器及连接状态。看到绿色的已连接,说明配置没问题。
这里有一个很常见的误解:改了 mcp.json 文件后,直接在对话里跟 AI 说“刷新 MCP”,通常不会生效。MCP 服务器是启动进程,配置变了必须重启会话才能重新加载。所以每次改完配置,别急着问 AI 摸不摸得到,先把会话重启一次再说。
4.2 Cursor / Windsurf / VS Code 里怎么弄
Cursor 走的是菜单设置:Settings -> MCP,点加号手动填命令,或者直接指定 .mcp.json 路径。Windsurf 路径类似,在 MCP 面板里添加。
VS Code 生态则更多依赖扩展,比如 Cline,在插件设置里填写 MCP 服务器配置,格式和 mcp.json 完全一致。说实话,各个客户端的入口不一样,但底层读的 JSON 结构是通用的。所以我的建议是:先有一份能用的 mcp.json,到了任何工具里都只是“导入”的差别,而不是重新学一套配置。
4.3 用日志和调试命令定位连接问题
MCP 工具连不上的现象很迷惑人——AI 面板显示连接中,然后超时。这时候先别怀疑网络,按优先级排查:
先问“进程起来了没有”。用 ps aux | grep mcp 查看相关进程是否存在。如果没有进程,说明 command 或 args 写错,或者运行时缺失。
再问“进程为什么退出”。打开日志目录,Claude Code 的日志一般存放在 ~/.claude/logs/,Cursor 的在用户数据目录下。打开日志文件搜 MCP 相关关键字,基本能看到错误原因,最常见的是 “spawn npx ENOENT”——这表示找不到 npx 命令。
最后实在定位不了,可以手动在终端里运行一遍启动命令,看真实输出:
bash复制npx -y @modelcontextprotocol/server-github
如果这段命令本身在终端里就能报错,问题就不在 MCP 配置,而在系统环境。
5. 高频坑位合集,每一条都是真金白银换来的
5.1 Windows 路径和转义问题
Windows 下的路径分隔符是反斜杠 \,在 JSON 里必须写成 \\ 才能被正确解析。比如:
json复制{
"mcpServers": {
"files": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "D:\\projects\\my-app"]
}
}
}
如果你写成 "D:\projects\my-app",JSON 解析就会出错,因为 \p 和 \m 不是合法的转义序列。更省事的方式是统一用正斜杠:"D:/projects/my-app",Windows 系统基本都能识别。
5.2 npx 首次安装太慢导致的超时
第一次运行 MCP 服务器时,npx 需要从 npm 仓库下载包。如果网络状况一般,下载过程可能超过客户端的等待时间,最终显示连接失败。这不是你配置错了,纯粹是网络问题。
我的解决方案是提前手动装好包,让 MCP 启动时不再需要联网下载:
bash复制npm install -g @modelcontextprotocol/server-github
然后 command 改成直接调全局命令。比如:
json复制{
"mcpServers": {
"github": {
"command": "server-github",
"args": [],
"env": {}
}
}
}
这样启动瞬间完成,省去每次等待下载的时间。缺点是需要手动确认全局包的版本,没有 npx -y 那么强的灵活性。生产环境我一般倾向全局安装,开发时用 npx 就行。
5.3 多个 MCP 工具造成上下文被“吃掉”
MCP 工具的数量不是越多越好。每个工具的说明、参数定义都会作为系统提示的一部分注入到模型上下文里。挂十个八个 MCP 服务器,AI 的可用上下文窗口就被吃掉一大截,对话质量会明显下降。
所以我建议:项目级配置只放这个项目真正会用到的服务。通用型工具(比如文件系统)放用户级配置,项目专属工具(比如数据库、内部 API)放项目级。这样每个会话加载的 MCP 数量保持在 3 到 5 个,效果和性能是最平衡的。
5.4 工具返回超长内容反而打断思路
还有一个容易被忽略的问题:MCP 工具返回的结果,会原封不动塞回给 AI,中间不经过整理。如果你的工具函数返回一个 10000 行的日志,AI 的上下文可能就被这段日志“轰炸”了,接下来几轮对话质量都会受影响。
写自定义 MCP 工具时,我习惯在返回前做截断和摘要。比如只返回前 200 行、统计总行数,或者提炼关键错误信息。这样 AI 拿到的永远是精华,而不是噪音。
6. 安全边界,配置里必须给自己画的红线
6.1 敏感信息永远不要落盘到配置文件
把数据库密码、API token、私钥写进 mcp.json,即使不上传到 Git,也存在本地泄漏风险。尤其是项目目录如果被做成了 tar 包、拷贝到新机器,配置文件里躺着的明文密钥就被打包带走了。
我的做法是:所有敏感值一律用 ${VAR} 引用外部环境变量,mcp.json 里只保留变量名。同时建议在 .gitignore 里加上:
gitignore复制.mcp.json
如果团队需要共享配置模板,就提交一份 mcp.example.json,里面放占位符,大家 clone 后复制成 .mcp.json 再填自己的变量值。
6.2 控制 AI 可调用工具的能力边界
文件系统 MCP 给目录路径时要克制,数据库 MCP 最好只连只读账号,GitHub token 权限范围按最小集给。这些边界控制是从配置层面就限制 AI 的操作范围,而不是等到 AI 已经执行了危险操作再去补救。
我一直强调一个观念:AI 没有“常识性的犹豫”。它看到工具就调用,不会多想“这个操作是不是太危险”。所以配置里的权限边界,就是唯一的安全护栏。你给它开多少权限,它就有多大破坏力。
6.3 定期检查已配置的 MCP 列表
时间一长,之前配的 MCP 可能已经不再使用,或者有些第三方包已经不再维护。建议每隔一两个月跑一次 claude mcp list,看看当前挂了多少服务,把不用的、不再维护的清理掉。一是减少上下文占用,二是避免有安全漏洞的旧包继续运行。
7. 再往前走一步:MCP 配置的工程化玩法
7.1 用 CLAUDE.md 约束 AI 对 MCP 工具的使用习惯
Claude Code 会在项目里读取 CLAUDE.md 文件,把它作为项目约定注入到对话上下文。这个文件不仅写代码规范,也可以写 MCP 使用约定。比如:
markdown复制- 使用 github MCP 时,创建 PR 前必须先列出该分支的变更文件
- 使用数据库 MCP 时,禁止执行 DELETE 和 DROP 操作
- 文件系统操作默认只读,除非用户明确要求修改
有了这份约定,AI 调用工具时就更“有分寸”,不会擅自执行破坏性操作。这比靠大模型随机涌现的安全意识靠谱得多。
7.2 多环境切换:dev、staging、prod 的配置管理
当 MCP 配置越来越复杂,一份配置打天下的模式就不好用了。我见过一种很实用的做法:把不同的环境变量写进不同的 .env 文件,用启动脚本动态选择配置。
比如 .env.dev 里写 DATABASE_URL=postgresql://dev:dev@localhost:5432/devdb,.env.prod 里写生产地址。启动前先指定环境变量文件,再启动 Claude Code:
bash复制set -a; source .env.dev; set +a; claude
这样同一份 mcp.json,通过不同的环境变量加载,就能访问不同环境的数据库,配置文件本身不需要改动。
7.3 自己搭一套轻量 MCP 工具库
如果你在一个团队里被问到:“AI 能帮我查 JIRA 吗?”“AI 能操作我们的发布平台吗?”——与其去网上找现成包,不如自己写一个聚合 MCP 服务器,把所有内部接口统一封装进去。这也是我从个人使用到团队推广 MCP 之后,觉得收益最大的一件事:所有内部系统的能力,都在一个 AI 可触达的地方,而不是让每个人各配各的、五花八门。
脚本语言可选 Python 或 Node.js,核心就是包一层 FastMCP 或者 @modelcontextprotocol/sdk,把现有 API 映射成工具函数。写好后部署成 HTTP 服务,团队成员只用一个远程地址就能共享能力,配置成本降到了最低。
8. 给新手的最后一个建议
我从第一次踩到 MCP 超时到现在,最大的心得是:配置 MCP 不要追求“多”,要追求“准”。每次只加一个服务器,验证通了再往下走。一次加五个,出了问题你根本不知道是哪个配置的锅。
调试时耐心点。先确认 mcp.json 的 JSON 格式正确,再确认启动命令在终端能跑通,最后才去怀疑客户端的问题。按这个顺序排,90% 的问题都能在十分钟内定位完。剩下的 10%,多半是远端服务的认证或者网络策略问题,考验的就不是配置能力,而是排查经验了。
