真实世界的 MCP:把 Claude 接入你的数据库、API 和文件系统

三个月的 MCP 学习之旅接近尾声。老李的笔记本已经记满了 Client、Server、Transport、Tool、Prompt、Sampling——他甚至在社区贡献了一个 Postgres MCP Server 的实现。但今天下午,他把笔记本一合,抛出了最后一个问题。

“小王,咱们学了这么多,理论我都认可。但你说这些东西真的能在生产环境用吗?我见过太多技术——Hello World 跑得溜,一上生产就炸。MCP 扛得住吗?”

小王没急着回答,而是把笔记本屏幕转向老李,上面是三个运行中的服务面板。“这三个 MCP Server,已经在公司内部跑了两个月了。一个给客服团队用,一个给运维用,一个给咱们开发组用。你想先看哪个?”

老李一愣:“已经在用了?什么时候的事?”

“从你说‘下不为例’的那天开始,我就悄悄部署了。今天给你做一次正式汇报。”


案例一:PostgreSQL MCP Server——让客服 AI 能查订单

“第一个案例,客服部门的智能助手。”小王打开第一个面板,“客服每天被问最多的问题是‘我的订单到哪了’。以前 AI 只能从知识库里搜通用回答,用户要的是实时物流状态,AI 给的是‘请您登录查看’。现在接入了订单数据库的 MCP Server,AI 能直接查。”

他展示了这个 Server 的设计架构。它只暴露了三个工具:query_order_statusquery_order_historylookup_product_info。全都是只读查询,连 INSERTUPDATE 的影子都没有。

“这个 Server 有三层安全防护。第一层,只允许 SELECT 查询,SQL 里只要出现 INSERT、UPDATE、DELETE、DROP 任何一个关键词,直接拒绝。第二层,查询结果自动脱敏——手机号中间四位变星号,地址只显示到区。第三层,每次查询都记录审计日志——谁问了什么、返回了什么。”

typescript
// 订单查询 Server 的安全核心:只读 + 脱敏 + 审计
async function executeOrderQuery(sql: string, userId: string) {
  // 第一层:禁止写操作
  const upperSQL = sql.toUpperCase();
  const forbidden = ["INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "TRUNCATE"];
  for (const keyword of forbidden) {
    if (upperSQL.includes(keyword)) {
      throw new Error(`禁止的操作:${keyword}。本工具仅支持只读查询。`);
    }
  }
  
  // 执行查询
  const result = await db.query(sql);
  
  // 第二层:自动脱敏
  const sanitized = result.rows.map(row => ({
    ...row,
    phone: maskPhone(row.phone),      // 138****1234
    address: maskAddress(row.address)  // 北京市海淀区***
  }));
  
  // 第三层:审计日志
  await auditLog.record({ userId, sql, resultCount: sanitized.length, timestamp: new Date() });
  
  return sanitized;
}

老李指着那行 forbidden 数组:“这个黑名单够全吗?万一有人用 COPY 或者 TRUNCATE 呢?”

“已经加上了。而且我们内部有个安全 review 清单,每周检查一次黑名单是否覆盖了所有危险操作。这不是写完就完事的,是持续维护的。”


案例二:内部 API 网关 MCP——让 AI 成为运维助手

“第二个案例更大胆——运维团队接了一个 API 网关 MCP Server。”小王切换到另一个面板。

“以前运维半夜被叫起来重启服务、查日志、检查健康状态。现在他们把这些操作封装成了 MCP Tools:restart_servicefetch_logscheck_healthscale_replicas。Agent 接到告警后,能自动执行初步排查,只在需要确认时才叫醒值班人员。”

这个 Server 的权限设计比第一个更复杂。fetch_logscheck_health 是只读操作,任何认证用户都能调。restart_service 是写入操作,需要值班人员审批,而且只允许在维护窗口内执行。scale_replicas 是管理操作,只有运维经理的 token 才能调。

图:API 网关 MCP Server 的权限分级——不同操作,不同权限

“最精彩的是 fetch_logs 这个工具,”小王补充道,“它接受自然语言描述的时间范围——‘最近十分钟’、‘从下午三点开始’——然后自动转成日志查询的时间戳范围。Agent 调用的时候不需要理解底层的时间戳格式。”

老李若有所思:“所以这个 Server 不只是暴露 API,它还做了一层自然语言的适配?”

“对。好的 MCP Tool 不只是把 REST API 原样包一层,它会根据 AI 的使用习惯重新设计接口。AI 擅长用自然语言描述,不擅长记精确的日期格式。Tool 应该帮它补齐这个差距。”


案例三:项目文件管理 MCP——AI 版的 IDE 文件管理器

“第三个案例咱们组最熟。”小王打开一个文件树界面,“开发用的项目文件管理 Server。它让 Agent 能读取项目结构、搜索代码、创建分支、生成测试文件。”

这个 Server 的设计巧妙之处在于它的上下文感知。当 Agent 需要修改一个函数时,它不需要被告知“在 src/utils/validator.ts 第 45 行”——Agent 可以先用 search_code 搜索函数名,找到位置,然后用 read_file 读取上下文,最后用 edit_file 精准修改。

typescript
// 项目文件管理 Server 提供的核心 Tools
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "search_code",
      description: "在项目中搜索包含指定关键词的代码文件和行。返回文件路径、行号和代码片段。",
      inputSchema: {
        type: "object",
        properties: {
          keyword: { type: "string", description: "搜索关键词,支持正则" },
          file_pattern: { type: "string", description: "限定文件类型,如 *.ts" }
        },
        required: ["keyword"]
      }
    },
    {
      name: "read_file",
      description: "读取指定文件的完整内容或部分行。",
      inputSchema: {
        type: "object",
        properties: {
          path: { type: "string" },
          start_line: { type: "number", description: "起始行号(从1开始)" },
          end_line: { type: "number", description: "结束行号(可选)" }
        },
        required: ["path"]
      }
    },
    {
      name: "create_branch",
      description: "基于当前分支创建一个新分支。需要开发者确认。",
      inputSchema: {
        type: "object",
        properties: {
          branch_name: { type: "string", description: "新分支名,如 feature/add-validation" }
        },
        required: ["branch_name"]
      }
    }
  ]
}));

“这个 Server 最让我意外的是,”老李指着屏幕,“它让 Agent 能真正参与代码开发了。以前 AI 只能建议代码片段,现在它能自己找到该改的文件、读完上下文、然后精准修改。”

“而且所有操作都有审计。谁让 Agent 改了什么文件、什么时候改的、diff 是什么——全记录在 Git 历史里。出问题可以回滚,可以追责。”


三个案例背后的通用模式

小王把三个案例的架构图并列投在屏幕上。

“这三个 Server 虽然场景完全不同,但底层的设计模式是一样的。”他一条条总结。

权限包裹:每个 Server 只暴露最小必要工具集。数据库 Server 只有查询,运维 Server 分级授权,文件 Server 只操作指定项目目录。

限制声明:Server 初始化时通过 capabilities 明确声明自己能做什么、不能做什么。Client 一看就知道这个 Server 的边界在哪。

审计日志:所有 Tool 调用都记录——谁、什么时候、调了什么、参数是什么、结果是什么。日志不可篡改,存储在 Agent 访问不到的地方。

错误信息设计:Tool 返回的错误信息不只是错误码,而是包含可读的描述和下一步建议。AI 看到“订单号格式错误:应以 ORD- 开头”就能理解并引导用户,而不是看到一个冰冷的 400 Bad Request

老李靠在椅背上,看着这三个面板上的绿色运行状态灯,沉默了很长时间。然后他拧开保温杯,枸杞的香气飘了出来。

“三个月前你跟我说 MCP,我以为是又一个炒作的概念。现在它已经在公司里跑了两个多月,客服响应时间降了 40%,运维半夜被叫起来的次数少了一半。我得承认——这东西确实有用。”

小王正要接话,老李摆摆手:“下不为例啊。以后有新技术,你别再偷偷部署完了才告诉我。”

他站起来,走到白板前,在上面画了一个大的方框,里面写着三个字:下一步。

“接下来我想把咱们的 RAG 知识库也接上 MCP。不光是 Claude Desktop 能用,所有支持 MCP 的 AI 应用都能接入我们的知识库和工具。你下周给我一个方案。”

小王比了个 OK,看着老李走出会议室。保温杯里的枸杞晃晃悠悠,像 MCP 生态里那些正在被连接起来的数据源和工具——不再是孤岛,而是一张正在生长的网。

MCP 生态全景:社区 Server、最佳实践和下一步
MCP Sampling:让 Server 反过来"请教" LLM