2024 年底 Anthropic 开源了 Model Context Protocol(MCP),到现在一年半,月下载量已经破了 1.1 亿次。增速比当年 React 还猛。

但下载量不等于用好了。我在自己的项目里前后接了 6 个 MCP Server,过程中踩坑花的时间比写业务代码还多。把这些问题和解法记下来,你应该能少走几天弯路。

MCP 是什么,两句话说完

MCP 是个标准化的接口协议。AI 模型通过它调用外部工具——数据库、文件系统、API,什么都行。

之前每个工具都要单独写 function calling 的 schema,换个模型就得改一遍。MCP 统一了格式:Server 写一次,Claude、GPT、Gemini 都能用。架构就三层:

AI 模型 ←→ MCP Client ←→ MCP Server ←→ 外部工具

Client 集成在 AI 应用里(Claude Desktop、Cursor 自带),Server 你自己写或者用社区现成的。

下面说坑。

坑 1:配置路径写错,报错信息完全没用

Claude Desktop 的 MCP 配置文件位置:

# macOS
~/Library/Application Support/Claude/claude_desktop_config.json

# Windows
%APPDATA%\Claude\claude_desktop_config.json

# Linux
~/.config/Claude/claude_desktop_config.json

一个典型的 PostgreSQL 配置:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://user:pass@localhost:5432/mydb"
      ]
    }
  }
}

我第一次配的时候,连接串少写了端口号。Claude Desktop 给的报错就俩字:"Server disconnected"。没有堆栈,没有具体原因,什么都没有。

排查了半小时才发现问题。后来养成习惯:改完配置,先在终端手动跑一遍 Server 命令

npx -y @modelcontextprotocol/server-postgres "postgresql://user:pass@localhost:5432/mydb"

终端会直接打印错误信息,比如 "password authentication failed" 或者 "connection refused"。比 Claude Desktop 的报错有用得多。

这一步大概 10 秒钟,但能省你半小时。

坑 2:Server 启动了,工具列表却是空的

这个坑更隐蔽。Server 正常启动,Claude 也识别到了连接,但实际调用时它说"没有可用工具"。

我遇到过两个原因。

第一个:npx 缓存了旧版本的 Server。社区的 MCP Server 更新很频繁,npx 不一定每次都拉最新的。

# 方法 1:清缓存
npx clear-npx-cache

# 方法 2:指定 latest
npx -y @modelcontextprotocol/server-postgres@latest "postgresql://..."

第二个原因更坑:数据库连接本身没问题,但用户没有表的读权限。Server 不报错,只是返回空工具列表。

-- 给用户加上 SELECT 权限
GRANT SELECT ON ALL TABLES IN SCHEMA public TO your_user;
-- 别忘了未来新建的表也要有权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO your_user;

这个排查花了我将近一个下午。因为连接没报错,我一直在翻 MCP Client 的代码找问题,方向完全搞反了。

坑 3:符号链接会绕过文件系统的安全边界

文件系统 MCP Server 有个安全设计:你指定一个根目录,AI 只能访问这个目录和它的子目录。

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/yourname/projects"
      ]
    }
  }
}

试图读 /etc/passwd 会被拒绝。看起来很安全。

问题是:如果你的 projects 目录里有指向系统目录的符号链接,AI 能通过 symlink 读到外面的文件。比如 projects/configs -> /etc,AI 就能读 /etc 下的所有内容。

这不是 bug,是 POSIX 文件系统的工作方式。但对安全性来说是个隐患。

解决办法:

  1. 检查允许目录里有没有 symlink:find /Users/yourname/projects -type l
  2. 如果 Server 支持 --no-follow-symlinks 参数,开启它
  3. 给 MCP Server 的操作系统用户设置最小权限

坑 4:两个请求同时发,Server 直接卡死

MCP 用的是 JSON-RPC over stdio 传输。这意味着一个 Server 进程同一时刻只能处理一个请求。

我的 Agent 有时候会同时发两个查询(比如"对比 A 表和 B 表的数据"),第一个请求正常返回,第二个卡住了,等到超时才报错。

两个解决方案。

方案 1,多实例:

{
  "mcpServers": {
    "pg-read": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://...?application_name=read"]
    },
    "pg-write": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://...?application_name=write"]
    }
  }
}

方案 2,换传输方式。MCP 2025 年初加了 Streamable HTTP 传输,不走 stdio,天然支持并发。但需要 Server 端也支持这个传输方式,社区里大部分 Server 还在用 stdio。

我目前用方案 1,两个实例分别处理读和写,没再卡死过。

坑 5:AI 传参格式不对,docstring 写法决定成败

用 Python SDK 写自定义 MCP Server:

from mcp.server import Server
from mcp.types import TextContent

app = Server("sales-query")

@app.tool()
async def query_sales(
    region: str, start_date: str, end_date: str
) -> list[TextContent]:
    """查询指定区域和时间段的销售数据"""
    results = db.execute(
        "SELECT * FROM sales WHERE region = %s AND date BETWEEN %s AND %s",
        (region, start_date, end_date)
    )
    return [TextContent(type="text", text=format_results(results))]

代码本身没问题。问题出在 AI 传过来的参数。

start_date 这个参数,AI 有时候传 2026-05-15,有时候传 May 15, 2026,偶尔还会传 20260515。我的 SQL 只认第一种格式,后两种直接报错。

修复方法很简单,把 docstring 写具体:

@app.tool()
async def query_sales(
    region: str, start_date: str, end_date: str
) -> list[TextContent]:
    """查询指定区域和时间段的销售数据

    Args:
        region: 区域代码,只接受以下值:east, west, north, south
        start_date: 开始日期,格式 YYYY-MM-DD,例如 2026-01-01
        end_date: 结束日期,格式 YYYY-MM-DD,例如 2026-12-31
    """

AI 会读 docstring 来决定传参格式。写得越具体,格式错误越少。

加了详细 docstring 之后,参数格式错误从占总失败的 62% 降到了不到 10%。这是我做过的最简单也最有效的优化。

跑了两周的数据

我在一个内部数据分析项目里接了 PostgreSQL + 文件系统两个 MCP Server,让 Agent 自己查数据、生成周报。连续跑了两周,记了一些数字:

指标 第一周 第二周(优化后)
日均调用次数 34 次 51 次
工具调用成功率 78.4% 94.3%
平均响应时间 1.8 秒 1.2 秒
最慢一次 12.3 秒 4.1 秒

第一周到第二周的提升主要来自三件事:docstring 写详细、数据库加连接池(pgbouncer)、给大表加了合适的索引。

什么时候该用 MCP

用了这段时间,我的判断标准挺简单的:

用 MCP:你的工具要给两个以上的 AI 应用用,或者你想直接用社区已有的 Server。MCP 的价值在"写一次到处用"。

不用 MCP:只在一个应用里用、对延迟很敏感(MCP 每次调用多 200-500ms 序列化开销)、或者需要复杂的会话状态管理。这些场景直接写 function calling 更合适。

MCP 的官方 Server 仓库在 GitHub 搜 modelcontextprotocol/servers,目前有 30 多个官方维护的 Server,社区贡献的更多。挑一个你需要的试试,比自己从零写快得多。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐