主题
工具链与 MCP 平台
一句话:工具链决定模型能碰到哪些真实系统,MCP 把“接系统”收敛成一个标准协议;换来的是接一次、多个 AI 工具复用,代价是必须多一层平台化的权限、审计和版本治理。
为什么需要
没有统一协议时,集成成本按“AI 工具数 × 内部系统数”增长。每换一个编辑器或 CLI,就要重写一遍 Git、CI、数据库、监控的适配;每个适配各自拿着长期 token,权限比开发者本人还大。结果是三个具体问题:AI 能做什么说不清,出了事查不到是谁调的,换工具时集成全部作废。选型上的痛点同样具体:演示效果好的工具,往往把代码传到云端、把模型写死、把审计留空,等合规评审时才返工,迁移成本远高于当初省下的评估时间。
核心机制
形态决定能力边界
| 形态 | 能看到的上下文 | 主要代价 |
|---|---|---|
| IDE / 编辑器(VS Code / JetBrains 插件、Cursor 类 AI 原生 IDE) | 当前文件、索引到的仓库与编辑器状态 | 跨仓库长任务弱,审计依赖插件;AI 原生 IDE 索引更强但绑定编辑器 |
| CLI Agent(Claude Code、Codex CLI、Aider) | Shell、测试、Git、构建产物 | 无 GUI,权限大,必须配沙箱 |
| 云端 Agent(Copilot coding agent / cloud agent、Devin、Replit Agent;Workspace 已退役,以官方文档为准) | 上传后的仓库与托管环境 | 代码出网,过程黑盒,按任务计费 |
| 自托管 Agent / 插件(OpenHands、Continue 等;LangGraph 属编排层) | 自行接入的模型与工具 | GPU、运维、质量全部自担 |
这张表不是强弱排序,而是运行位置决定它能看见什么、能改什么、能留下什么证据。需要跑测试和改多文件的场景,CLI Agent 天然占优;代码不能出内网时,只有自托管一列可选。
按约束选型
| 场景 | 第一约束 | 组合思路 | 要接受的代价 |
|---|---|---|---|
| 个人 | 迭代速度、成本 | Cursor 类 IDE + Claude Code 类 CLI 互补 | 配置分散,无统一审计 |
| 10 人以下 | 协作与统一账单 | 团队版 IDE + 统一 Git/CI | 权限仍偏粗,靠约定 |
| 中大型企业 | 合规、可审计、可集成 | 企业版 + 自建 MCP 平台 + 自定义审查 | 平台建设与运营人力 |
| 代码极敏感 | 数据不出网 | Continue 类自托管插件 + 私有化模型 + OpenHands 类沙箱 Agent | GPU 与模型运维 |
| 快速原型 | 从想法到上线的时间 | Replit 类云端 Agent + 托管部署 | 不适合直接演进为生产 |
判断顺序应是:数据边界 → 权限与审计 → 生态与集成 → 成本 → 能力。前两项是硬约束,后三项可以随时间改善;反过来按 demo 效果选,通常会在评审阶段推倒重来。
模型选型:壳和内核分开评估
| 评估项 | 该问的问题 | 对架构的影响 |
|---|---|---|
| 能力与上下文 | 多文件重构、长链路调用是否稳;有效上下文多大 | 决定任务边界与检索摘要策略 |
| 延迟与成本 | 补全是否跟手;按 token 还是按席位,缓存是否计费 | 补全与 Agent 分模型,决定是否做路由 |
| 合规与私有化 | 是否用于训练、日志留多久;有无可部署权重 | 决定能否用公有云 API、是否必须私有化 |
具体版本、上下文长度和价格以官方文档为准。工程上的结论是:在工具和模型之间加一层网关做路由与计量,补全走低延迟便宜模型,多步 Agent 走强模型,主模型故障时可降级。绑定单一模型,等于把成本和合规风险一起写死。
MCP 三层:把 N×M 收敛成 N+M
Host 是用户面对的 AI 应用,负责会话、编排和最终权限决策;Client 嵌在 Host 里,一条连接对应一个 Server,负责 JSON-RPC 编解码和能力发现;Server 把外部系统的能力翻译成标准原语。分层的收益是 Host 不必理解每个系统的鉴权方式,权限和限流可以按连接隔离;代价是多一个要部署和升级的单元。三层是概念分工,不是部署拓扑:stdio 本地 Server 没有网络跳,Streamable HTTP 才多一跳。
工具调用由 Host 侧发起,Server 只暴露能力;同一 Server 可被多个 Host 复用,但每个 Host 各自做权限。最终鉴权仍落在 Git、监控这些后端系统上,Server 只是翻译层,不能拿它当安全边界。
三个原语各解决什么
| 原语 | 解决的问题 | 典型形态 | 权限含义 |
|---|---|---|---|
| Tools | 模型要“做事” | 带 JSON Schema 的函数 | 有副作用,需分级与审计 |
| Resources | 模型要“看背景” | 只读文档、Schema、配置 | 只读,可按 URI 授权 |
| Prompts | 团队要“复用问法” | 带参数的模板入口 | 无副作用,影响输出质量 |
不把三者都塞进 Tool,是因为只读上下文一旦变成“调用”,既会被计入配额,也很难和真正的写操作分开授权。Resources 让 Host 决定何时注入,Prompts 让规范以可发现的方式固化,而不是散落在各人的收藏夹里。Tools / Resources / Prompts 是核心能力,不是协议全貌;Tasks 等扩展在后续修订中加入,Roots / Sampling / Logging 等客户端能力的支持范围与演进以官方文档为准。
协议分工:别把所有互操作都塞进 MCP
MCP 管 Agent↔工具 / 数据;A2A(Agent2Agent)管 Agent↔Agent;ACP(Agent Client Protocol)管编辑器↔Agent;AGENTS.md、Skills、hooks 管约束与流程。 它们解决的是不同边界上的握手,一个协议覆盖不了工具、代理、编辑器和流程四层。判断标准是谁和谁说话:调工具用 MCP,委派任务用 A2A,编辑器驱动 Agent 用 ACP,把团队约定固化进仓库用 AGENTS.md / Skills / hooks。 混用会让权限模型和审计口径各说各话;先把边界配对,再谈用哪个协议。
企业平台与接入范围
个人用 MCP 是每个工具各自配 Server;企业需要平台,因为只有平台能回答“谁、以什么权限、调了什么、结果如何”。核心组件是:注册中心(服务发现、健康检查、版本)、网关(统一入口、路由、限流、熔断)、权限中心(RBAC + 工具级授权)、审计(调用与结果)、开发者门户(模板、测试、发布)、安全扫描(依赖漏洞与注入风险)。
内部系统接入按通用类别划分:代码库(读文件、搜代码、建 PR)、CI/CD(触发构建、看日志、回滚)、数据库(只读查询、Schema、慢查询)、API 文档(接口定义与示例)、监控告警(指标、告警、大盘)、工单(查询与创建)、知识库(规范与决策记录)、配置中心(查询与灰度,修改需审批)、容器平台(状态、日志、重启)、协作工具(通知与消息)。每类先做只读,写能力按风险等级逐个放开。
自定义 Server 的六条硬约束
- 粒度:一个工具做一件事。
manage_service这种万能工具会让模型猜参数,拆成get_status、get_logs、restart后选择准确率明显更高。 - 输入校验:Schema 只是给模型看的,服务端必须再校验类型、范围、枚举,防注入和越权 ID。
- 幂等:Agent 会重试。写工具接受
idempotency_key,重复请求返回同一结果,而不是创建两条工单。 - 超时:默认 30s 量级;长任务返回 job id,另给查询工具,不要让连接挂住。
- 错误可读:返回
code + message + hint,例如“权限不足,需要 ops 角色”,而不是裸堆栈。 - 只读优先 + 结果限额:查询默认限量(如 50 条),避免一次返回把上下文撑爆。
安全治理:五层控制与风险分级
五层是身份认证(AI 以当前用户身份调用,而非共享账号)、工具级 RBAC、数据脱敏、高危审批、审计追溯。风险分级则决定审批范围:R0 只读公开可直接调用;R1 只读敏感加权限与脱敏;R2 创建操作加审计;R3 修改操作加人工审批;R4 删除或不可逆操作禁止 AI 直接执行。
分级的目的是把审批留给真正不可逆的动作。全量拦截会迅速产生审批疲劳,人开始无脑点同意,审批就退化成橡皮图章;R4 直接拒绝而不是审批,也是同一个原因。审计要能还原调用链,而不只是记一条“调用成功”。
第三方 MCP / Skill / 扩展的信任边界:工具描述是不可信输入,可能藏提示注入;只接允许列表内的 Server / Skill,版本钉住并校验来源与签名,凭证按最小权限发放并定期轮换,出现异常要能一键 kill switch。完整威胁模型见 06-安全、沙箱与供应链。
MCP 还是直接写适配
用 MCP 的条件是:多个 Host 要复用、需要统一权限与审计、准备长期维护。直接写 API 适配更合适的情况是:只有一个 AI 工具、一次性验证、对延迟极敏感,或已有成熟 SDK 包一层就够。一个反直觉的结论是,MCP 的收益随接入的 Host 数量增长;只接一两个工具时,协议、部署和平台治理的成本高于它省下的适配工作。常见做法是内部仍写 API 适配,外层再包一个 MCP Server。
实战场景
事故复盘:MCP 接了一屏工具,Agent 开始犯蠢
怎么死:平台一期把“接入数量”当成果,三周内注册 22 个 Server、137 个工具,全量挂到默认 Host 上——每个角色一打开会话就是一屏工具。随后故障不是“调不通”,而是三类更难归因的犯蠢:
- 选错工具:问“昨天支付成功率”,请求被路由到 BI 平台的
run_sql,在生产大表上跑了一次全量扫描,触发慢查询告警;本该用的指标查询工具就在同一个命名空间里,只是没被选中。 - 参数混用:
query_logs/get_logs/search_log三个近义工具来自三个 Server,参数名和分页语义各不相同,模型把它们当一个用,于是同一个查询换一种写法就失败一次。 - 上下文被吃掉:137 条工具描述与 schema 在每次会话开头全量注入,占掉输入的大头,真正留给代码和日志的预算不够,回答开始丢约束。
代价是端到端变慢而不是变快:一次本来十分钟能确认的排查跑了四十分钟,中间多两次误调用与一次回滚;更贵的是 review 成本——工具调用次数上去了,结论反而更难核对。根因不在模型,在“工具命名空间是全局的”这个事实:正文边界条目已经点名工具数量过多会降低选择准确率(经验值,需按团队校准),而注册中心只解决了“谁都能上架”,没解决“谁该看见什么”。
收敛过程,三步,顺序不能反:
- 按角色白名单:默认拒绝,逐角色装配。开发日常集 12 个、SRE 排障集 18 个、分析只读集 9 个(经验值,需按团队任务分布校准);装配在 Host 侧按当前用户角色决定,而不是把 22 个 Server 全连上。
- 动态挂载:按任务阶段切换工具集,编码阶段不挂生产写工具,发布阶段才挂;一个任务结束重开会话,而不是在同一会话里续用全套工具。
- 命名与描述治理:同类能力合并到同一个 Server、共用一张动词表(
get_*/list_*/trigger_*),描述必须写清“什么时候不要用我”——正文六条硬约束第一条(manage_service拆成get_status/get_logs/restart)说的就是这个;近义工具靠描述分工,不靠模型猜。
前后对比要自己量,不看厂商数字:
| 指标 | 收敛前 | 收敛后 | 怎么采 |
|---|---|---|---|
| 单次会话可见工具数 | 全量 137 | 按角色 9–18 | Host 侧 ListTools 返回计数 |
| 误调用(选错工具或参数) | 每周多条,归因分散 | 残余集中在近义动词 | 故障归因表,按工具名分类 |
| 工具描述占输入的比例 | 每轮固定开销,挤掉代码预算 | 只占对应子集 | 网关按段计量(描述 / 代码 / 日志) |
判断标准要从“Server 数”换成“任务成功率与误调用率”。接入数量本身不是资产:它同时是上下文成本、选择成本与权限面。
案例:把内部 CI 接成 MCP 的正确姿势
第一版怎么死的:按 CI 的 REST API 一比一翻译,28 个端点变成 28 个工具,包含 delete_pipeline、update_pipeline、update_runner_config,凭证用共享 service account。两周内两次险情:一次 Agent 为了“重跑这个构建”去调 update_pipeline,顺手把别人流水线的并发数改了;一次用 get_project_logs 一次拉回 6 MB 构建日志,把整段上下文填满,之后的每一轮回答都在缺约束的状态下生成。这两次的共同点是全量 API 把“能做什么”交给模型现场决定,而共享账号让权限比开发者本人还大——正文“为什么需要”里点名的三个问题一次凑齐。
重做后的形状:只暴露三个动词,能力收窄而不是镜像后端。
python
@mcp.tool()
def ci_trigger(project: str, ref: str, replay_of: str | None = None,
idempotency_key: str | None = None) -> dict:
"""触发一次构建。仅限调用者本人有 read 权限的项目。返回 job_id,不阻塞。
重跑请传 replay_of=原 job_id,不要修改流水线配置。"""
@mcp.tool()
def ci_status(job_id: str) -> dict:
"""查询单个 job 的状态与失败阶段,只读。"""
@mcp.tool()
def ci_logs(job_id: str, stage: str | None = None,
offset: int = 0, limit: int = 100) -> dict:
"""按行取日志片段。返回截断后的片段、next_offset 与完整日志的 URI。"""三条设计决定各自挡掉一类事故:
- 动词表就是权限表:删除、改配置、改并发一律不暴露。按正文风险分级,改流水线配置属 R3(人工审批才动),删除属 R4(禁止 AI 直接执行);“重跑”折叠成
ci_trigger的replay_of参数加幂等键,而不是新增一个写工具(对应六条硬约束里的幂等)。 - 权限按人透传:Host 用 on-behalf-of 的 OAuth token 调用,Server 只做翻译不做鉴权,CI 侧仍按真实用户判权。于是“这个人在 CI 里没权限的项目,通过 MCP 也不可能有”,审计也才能回溯到人——这一条决定了事故能不能复盘(见 10-最佳实践与质量保障)。
- 返回体积控制:日志按行分片、默认限量并返回
next_offset,完整日志作为 Resource 暴露 URI 供人查看而不是全部塞进上下文。注意这里和查询类工具的“默认限量 50 条”是两条独立限额(一条控结果集规模,一条控上下文体积),都要按任务实测校准,而不是共用一个数字;超时按正文的 30s 量级配置,长任务一律返回 job id 另配ci_status。失败时返回code + message + hint(例如“需要 ops 角色,向 owner 申请”),Agent 才可能据此选择重试、换路还是找人——裸堆栈只会诱发重复误调用。
一句取舍:Server 的工具表由“Agent 要完成的任务”倒推,不由后端 API 的表面积决定。接一个系统的正确产出是能力收窄;接口设计、版本与下线的平台动作仍按正文生产动作那一条走,任务层的拆分节奏参见 07-企业工作流与大代码库。
最小上手
Python 3.10+,pip install "mcp[cli]"(版本以官方文档为准)。下面是一个只读的 API 文档 Server,省略了 docs 客户端实现、鉴权、日志与错误处理:
python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("api-docs")
# docs 为内部文档客户端,省略实现
@mcp.tool()
def search_api(keyword: str, service: str | None = None, limit: int = 20) -> list[dict]:
"""搜索内部 API 文档,只读,最多返回 50 条。"""
limit = max(1, min(limit, 50))
return docs.search(keyword, service)[:limit]
if __name__ == "__main__":
mcp.run() # 默认 stdio;平台部署用 transport="streamable-http"本地验证用 mcp dev server.py 打开 Inspector,能看到 search_api 并手动调用;能看到返回 JSON,说明工具声明和调用链都通了。接进 Host 时在配置里登记 command 与 args(如 python server.py)即可。
生产动作
- 注册:每个 Server 必须有 owner、用途、数据分级、风险等级;无 owner 不上架,避免僵尸服务。
- 权限:用 OAuth 代表真实用户(on-behalf-of),禁用共享 service account;工具级 RBAC,默认拒绝。
- 审计:记录调用者、工具名、参数摘要、结果状态、耗时、trace id;敏感参数脱敏后落库。
- 限流:按用户、工具、Server 三个维度限并发与 QPS;
timeout=30s量级,查询结果上限 50 条。 - 版本:语义化版本 + 兼容窗口;工具改名或删参数视为破坏性变更,旧名保留一个周期并告警。
- 下线:先标
deprecated并通知调用方,观察到零调用后从注册中心摘除,审计记录保留。 - 排障:现象是 Agent 报工具不存在 → 查注册中心与
ListTools→ 判断是版本未发布还是权限过滤;现象是调用超时 → 看网关耗时与 Server 日志 → 区分下游慢还是结果过大。
边界
- MCP 不是安全沙箱:协议层能拦调用,但真正的权限必须在后端系统执行;模型和 Host 都可能被绕过。
- 协议有固定成本:多一跳、多一个部署单元,工具描述本身占上下文;工具数量过多会降低选择准确率(经验值)。
- 原语支持不齐:Tools 最通用,Resources 和 Prompts 在不同 Host 上支持程度不一,跨工具的可移植性不宜高估。
- 平台化早期是负担:10 人以下先做统一配置和集中 token 管理,等接入系统超过个位数再建网关。
- 云端 Agent 的边界是合规不是能力:代码不能出网时,再强的自主 Agent 也不在候选集里。
讲清楚
工具链让模型碰到真实系统,也让企业可控。形态无绝对优劣:IDE 插件轻但上下文窄,CLI Agent 能跑测试但权限大,云端 Agent 适合长任务但代码出网,自托管 Agent 最强但运维全担,选型先看数据边界与审计,再看生态成本。MCP 把 N 乘 M 的适配收敛成 N 加 M:Host 管权限,Client 管连接,Server 翻译出 Tools、Resources、Prompts。Host 越多收益越大,只接一个时直接适配更划算;落地重点在注册、权限、审计、限流、版本和下线,按风险分级决定哪些操作需人工确认。
适用:以 MCP 官方规范最新版本为准;2025–2026 的修订调整了会话模型并加入 Tasks / Extensions 等能力,旧客户端 / 服务端兼容性需核对 | 初稿 2026-10