← 返回教程库

接现成 MCP server,还是自己写一个:两条路怎么选

最后更新 2026-06-24
你将学到
  • 先用现成 MCP server 把 GitHub/数据库/浏览器/文件系统接进 Agent,会配置会验证
  • 分清「接现成」和「自己写」的边界,知道什么时候非自己写不可
  • 看懂一个最小 MCP server 的三段骨架:声明工具、处理调用、返回结果
  • 用一份接入 checklist 和故障排查表,把「连不上 / 工具不被调 / 鉴权失败」逐个拆掉

你想让 Agent 能读你 GitHub 仓库的 issue,或者查一下生产库里某张表的数据。第一个念头往往是"那我得写个 MCP server 把它们接进来"。先别急着写代码——这件事大概率有人已经替你写好了。接现成 MCP server 是第一选择,自己写是退而求其次。 这一节先教你把现成的 server 接进 Agent 客户端,再讲清什么时候你绕不开"自己写一个",最后给你一个最小 server 的骨架,让你心里有底。

这篇适合谁:知道 MCP 是给 Agent 连外部系统的协议,但还没真正接过一个 server、也没自己写过的人。读完你能接通第一个现成 server,并且知道哪天该自己动手。


先认清一件事:大多数系统已有现成 server

MCP 生态最大的红利,是常见系统的 server 早就被官方或社区写好了。你要连的多半在这几类里:

  • 代码托管:GitHub、GitLab 这类,能读 issue、PR、文件、提交。
  • 数据库:Postgres、SQLite、MySQL 这类,能查询、(按配置)读写表。
  • 浏览器:能让 Agent 打开网页、点击、抓内容、截图(自动化与抓取常用)。
  • 文件系统:能读写指定目录下的文件,给 Agent 一块"工作区"。

这些 server 的价值在于:你不用懂它内部怎么跟 GitHub API 打交道、怎么管数据库连接池,你只管把它"挂"到 Agent 客户端上。 它暴露的工具(比如 list_issuesrun_queryread_file)Agent 直接就能调。

选哪个 server,认准两点:优先官方维护的(modelcontextprotocol 组织下的,或系统厂商自己出的),其次看社区项目的活跃度(近期有没有更新、issue 有没有人理)。具体哪些 server 可用、包名叫什么,以官方文档为准,生态更新很快,别照记忆里的旧名字找。


最小可用:把一个现成 server 接进客户端

接 server 的本质,是在你 Agent 客户端的配置文件里登记一段——告诉客户端"用什么命令把这个 server 跑起来"。绝大多数客户端(Claude Code、Cursor、各类支持 MCP 的工具)都是这个套路:一个 JSON 配置,列出每个 server 的启动命令和参数。

以"接一个文件系统 server"为例,配置长这样(字段名、包名以你客户端和该 server 的官方文档为准,下面是结构示意):

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@some-org/server-filesystem", "/Users/you/workspace"],
      "env": {}
    }
  }
}

逐段读懂它:

  • "filesystem":你给这个 server 起的名字,随便取,方便你自己认。
  • "command" + "args":怎么把 server 进程拉起来。这里是用 npx 跑一个 npm 包,最后那个路径参数把 server 能访问的范围限定在某个目录——这点很重要,等于给它划了活动边界。
  • "env":传给 server 进程的环境变量,鉴权信息(token、密码)一般走这里,后面细讲。

存盘后重启客户端(或触发它重新加载 MCP 配置)。逐步预期是这样:

  1. 客户端启动时,按配置把每个 server 进程拉起来
  2. 客户端跟 server 握手,问它"你都有哪些工具",把工具列表读回来。
  3. 这些工具的名字和说明,进入 Agent 的可用工具清单——这时你问 Agent "把 workspace 下的 README 读出来",它就会去调那个 read_file 工具。

如果客户端有 MCP 状态面板,你会看到这个 server 显示"已连接"、列出它的工具数。看到工具列表 = 接通成功的第一个信号。


接现成 server checklist

接每一个现成 server,按这四步走,基本不会翻车:

  1. :优先官方/厂商出的,其次看社区活跃度;确认它暴露的工具确实覆盖你要的操作(要读 PR,就确认它有读 PR 的工具)。
  2. :在客户端 MCP 配置里登记启动命令(command + args),用参数把访问范围收窄(限目录、限只读、限某个库),别一上来给全权限。
  3. 鉴权:需要 token/密码的,放进 env 环境变量或客户端的密钥管理里,绝不把密钥硬写进会被提交的配置文件。
  4. 验证:重启客户端 → 看 server 是否"已连接"、工具列表是否出现 → 让 Agent 实际调一次("列一下我仓库最近的 issue"),看它真能拿到数据

这四步——选、配、鉴权、验证——任意一步缺了,都会在后面变成一个难查的 bug。尤其第四步,别接完就以为成了,一定让 Agent 真跑一次


什么时候必须自己写 server

现成 server 覆盖不了的,才轮到自己写。典型信号有两个:

  • 你要暴露的是"你自己的东西":你公司内部的 API、私有的业务数据库视图、一套自研工单系统、某个只有你们才有的内部服务。这些没有现成 server,因为只有你知道它长什么样。
  • 现成 server 给的工具粒度不对:比如现成数据库 server 只给你一个"执行任意 SQL"的工具,但你想给 Agent 暴露的是几个受控的、业务语义明确的操作("查某客户的订单状态"而不是"裸跑 SQL")——这时自己写一个薄薄的 server 包一层,更安全也更好用。

一句话判断:现成 server 是把"通用系统"接进来,自己写 server 是把"你独有的能力"暴露出去。 前者用别人的轮子,后者你得造一个——但这个轮子比你想象的小。


自己写一个最小 server:三段骨架

不管用哪个语言的 SDK,一个 MCP server 的骨架都是同样三段:声明有哪些工具 → 处理工具被调用 → 返回结构化结果。下面用伪代码示意这个结构(具体的 SDK 函数名、装饰器名以官方文档为准,各语言 SDK 写法不同,这里讲的是思路):

# 最小 MCP server 骨架(思路示意,API 名以官方 SDK 文档为准)

server = MCPServer(name="my-internal-api")

# 第一段:声明工具——名字、说明、参数 schema
@server.tool(
    name="get_order_status",
    description="按订单号查订单当前状态。输入订单号,返回状态和最近更新时间。",
)
def get_order_status(order_id: str):
    # 第二段:处理调用——这里是你真正干活的地方
    try:
        order = internal_api.fetch_order(order_id)   # 调你自己的内部 API
    except NotFound:
        # 第三段(错误分支):返回结构化错误,不是裸抛异常
        return {"ok": False, "error": "order_not_found",
                "message": f"订单 {order_id} 不存在"}

    # 第三段(正常分支):返回结构化结果
    return {"ok": True,
            "status": order.status,
            "updated_at": order.updated_at}

server.run()   # 起服务,等客户端来连

三段各自在干什么:

  • 声明工具:你告诉 Agent "我这有个工具叫 get_order_status,干什么用、要传什么参数"。description 写得好不好,直接决定 Agent 会不会、会不会在对的时候调它(这点下一节会专门展开)。
  • 处理调用:Agent 决定调这个工具时,客户端把参数发过来,你的函数体就是真正执行的逻辑——查库、调内部 API、算个结果。
  • 返回结果:把结果包成结构化数据(这里用 {"ok": ..., ...})返回。出错时别直接抛裸异常,而是返回一个 Agent 能读懂的错误对象(order_not_found + 中文 message),它才知道"这是没找到,不是系统崩了",可能换个订单号重试。

把这个 server 起起来、按前面"接现成"的同一套配置登记进客户端,Agent 就多了一个 get_order_status 工具——而它背后连的是你公司独有的系统。这就是"把你的 API 暴露给任意 Agent"的全部魔法。


故障排查表

接 server 最常卡在这三类问题上,按这张表对症下药:

现象 可能原因 怎么排查 / 解法
server 连不上(客户端显示未连接 / 报错) 启动命令错、包没装上、路径不对、server 进程起来就崩 手动在终端跑一遍那条 command + args,看它能不能独立启动并打印日志;包名/命令拼写核对官方文档;看客户端的 MCP 日志里 server 的 stderr
连上了,但 Agent 不调那个工具 工具 description 写得模糊,Agent 不知道何时该用;或工具名跟意图对不上 把 description 改成"什么场景用、输入啥、输出啥"讲清楚;在提问里更明确地指向那件事;确认工具确实出现在工具列表里
鉴权失败(调用时报 401/403/未授权) token 没传进去、传错位置、过期、权限范围不够 确认密钥放在 env 或客户端密钥管理里且拼写正确;单独用 curl/客户端直连那个系统验证密钥本身有效;检查 token 的 scope 是否覆盖你要的操作
工具调了,但返回一团乱 / Agent 看不懂 server 返回的是裸异常字符串或非结构化文本 改成返回结构化结果(成功/失败字段 + 清晰 message),见上面骨架的第三段
server 起来了但每次调用都超时 你的内部 API/数据库本身慢,或连接没复用 先在 server 外面单独压一下后端响应时间;复用连接、加超时与重试,别让 Agent 干等

排查口诀:先确认 server 自己能独立跑起来(脱离客户端,在终端手动启动),再排客户端配置,最后排鉴权。多数"连不上"其实是 server 自己就没起来。


变体:三种常见接法

同样是接 server,场景不同,做法略有差别:

  • 接只读的现成 server(最安全的起步):比如只读文件系统、只读数据库视图。给 Agent 探路、做检索很合适,几乎没有破坏风险,新手强烈建议从这种开始
  • 接能写的现成 server(要划边界):比如能改文件、能写库的。务必用参数把范围收死(限目录、限某张表、限某个仓库),并想清楚"Agent 误操作的最坏后果"。
  • 自己写一个薄包装 server(控制粒度):不想把"裸 SQL"或"全量 API"丢给 Agent,就自己写个 server,只暴露几个业务语义明确的工具,把危险操作挡在 server 里面。这是企业内部最常见、也最值得的做法。

动手挑战

  1. 挑一个只读的现成 server(文件系统或数据库只读视图都行),按 checklist 接进你的 Agent 客户端,让 Agent 真的读出一条数据。全程记下你卡在哪一步——多半是配置或鉴权。
  2. 找一件"现成 server 给不了你"的内部能力(一个内部接口、一张业务表的某个查询),照三段骨架写一个只有一个工具的最小 server,把它接通。先跑通"声明—处理—返回"的闭环,别贪多。
  3. 把第 2 题那个工具的返回,从"成功就返数据、失败就抛异常"改成"成功/失败都返结构化结果",再故意触发一次失败,看 Agent 拿到结构化错误后的反应跟拿到裸异常有什么不同。

小结 · 你现在掌握了什么

  • 你知道接现成 MCP server 是第一选择:GitHub、数据库、浏览器、文件系统这些通用系统,官方/社区多半已经写好,你只管配进客户端。
  • 你会用「选 / 配 / 鉴权 / 验证」四步 checklist 接通一个现成 server,并且懂得接完一定让 Agent 真跑一次才算成。
  • 你能分清边界:现成 server 接通用系统,自己写 server 暴露你独有的能力——尤其是内部 API、私有数据、需要控制粒度的场景。
  • 你看懂了一个最小 server 的三段骨架(声明工具 → 处理调用 → 返回结构化结果),以及"返回结构化错误而非裸异常"为什么关键。
  • 你有了一张故障排查表,能把"连不上 / 工具不被调 / 鉴权失败"逐个拆开。

下一步:会接、会写之后,真正决定 server 好不好用的是设计——工具该有几个、错误怎么返、鉴权放哪。看本级下一节「工具 / server 设计原则」;想看整条路的位置就对照 三支柱路线图,或回 AI Agent 智能体阶梯 看全级安排。

👉 看看 AI 数字员工落地指南,或了解 数字员工搭建实战课。需要为企业落地方案,欢迎找我们聊 企业服务

📄 来源 / 自校链接

本文为学习整理,关键步骤与代码请结合下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为学习与落地整理,AI 工具与平台更新较快,关键步骤请结合官方最新资料验证。见免责声明