如果你最近在折腾AI编程智能体,大概率绕不开MCP协议这个词。我去年底开始调研并主导落地了一套基于MCP的代码评审智能体,从协议选型、服务端搭建到权限审计,踩了不少坑,也沉淀了一些确实能复用出来的经验。这篇文章就是把这一整套技术实践做一个系统梳理:MCP协议到底解决什么问题、商业级编程智能体应该具备哪些核心能力、以及从零搭一个能真正放进团队工作流的代码评审智能体的完整流程。适合正在做AI编程工具、研发效能平台,或者打算把大模型接进内部系统的同学参考,不管你是架构师还是独立开发者,都能找到可以直接抄作业的部分。
1. 项目背景与整体设计思路
1.1 从"能聊代码"到"能干活"的智能体
大模型刚火那阵,最常见的用法是写代码时把文件贴进去让它分析、改写。后来有人做RAG,把代码库向量化,让模型能够"检索"仓库内容并回答问题,这解决了一部分知识获取的问题,但距离"自动干活"还差一大截——因为能回答问题不代表能操作仓库。
再往前走一步,大家发现真正想要的编程智能体是能读仓库、能跑测试、能提MR、能执行构建的"数字同事"。这引出一个标准问题:大模型本身不会主动调用工具,它需要一套标准方式去发现工具、调用工具、接收工具返回结果。MCP(Model Context Protocol)协议就是为这个场景设计的。
MCP可以理解成"AI应用界的USB-C接口"。USB-C把充电、传输、视频输出统一成一种物理接口,MCP则把工具调用、资源读取、提示词管理统一成一套开放协议。你做一个MCP Server,把公司的git操作、CI/CD状态、静态扫描命令、部署脚本都暴露给AI,大模型就能按照标准流程调用。这样做最大的好处是彻底解耦:上层换模型、换客户端,下面的工具服务完全不用动;工具也只需要实现一次,所有支持MCP协议的客户端都能复用。
我在选型时其实对比过自研工具协议、OpenAPI接入、Agent原生函数调用三条路线,最后选择MCP的核心原因有三点:
- 标准化收益明显,不需要为每个模型客户端单独定制工具封装层;
- 社区生态已经起来了,GitHub、Playwright、文件系统等常用Server都有现成实现可以借鉴;
- 支持stdio和HTTP两种传输,既能本地开发调试,也方便远程部署。
1.2 商业级编程智能体的技术目标与边界
我在这里反复强调"商业级",想表达的不是做一个炫酷demo,而是做一个能放到生产环境里被团队日常使用的系统。demo和产品的分水岭不在模型能力,而在工程能力。一个商业级的AI编程智能体至少要覆盖四层能力:
- 能力层:代码库理解、多文件编辑、测试执行、错误修复;
- 编排层:把大任务拆解成工具调用的子任务,处理依赖关系和失败重试;
- 安全层:权限管控、命令白名单、敏感信息过滤、操作审计;
- 可观测层:完整日志、调用链路、成本统计、效果评估。
很多人一开始只盯着能力层,觉得"模型能改代码"就万事大吉,结果放进真实团队一周就被权限问题和日志问题卡住。最典型的一个场景:智能体把整个仓库的所有文件全部读进上下文,或者随意执行高危命令,这种在demo里无所谓,在商业环境里直接就是事故。所以这篇文章后面讲的所有设计细节,基本都是围绕这四个层级展开的。
1.3 为什么选MCP而不是自研协议
自研工具协议听起来可控,实际上是个大坑。团队规模越小越容易踩进去:你有多少个工具就得定义多少种API,每个客户端都要重新对接一遍;换一个模型供应商,又要重复一轮联调。更麻烦的是,工具之间的能力复用会变得非常困难,每个项目组都自己造一套轮子,最后变成内部接口博物馆。
MCP把这一层标准化了,你可以直接利用社区已有的很多Server来搭建基础能力,比如GitHub Server、文件系统Server、Playwright Server。内部工具也只需要实现一个MCP Server,就能被所有支持MCP的客户端复用。选型逻辑其实很朴素:不要重复发明协议,把精力放在智能体的业务逻辑和工程化上。
我自己的体会是,协议本身不会让你的智能体"更聪明",但它能让你把聪明劲儿用在正确的地方。团队的时间和精力,应该花在工具设计、上下文策略、安全控制这些真正产生差异化的环节。
2. MCP协议核心机制与架构拆解
2.1 三层架构与角色定位
MCP协议把参与方分成三个角色,理解这三个角色是后面所有设计的基础。
- MCP Host:宿主程序,也就是AI客户端。常见的有Claude Desktop、支持MCP的IDE插件、你们自己搭建的Agent平台。Host负责跟用户交互,也负责调用大模型做决策。
- MCP Client:运行在Host内部,负责与MCP Server建立一对一的连接,完成请求转发和响应接收。
- MCP Server:轻量级进程,暴露工具、资源和提示词给客户端调用。一个Host可以同时连接多个Server。
这个模型很像浏览器和插件的关系。浏览器本身不实现PDF阅读器,插件实现了之后通过标准接口接入,浏览器负责调度和展示。MCP把"智能体需要用到的外部能力"全部收编成可插拔的模块,Host侧只需要关心协议对接,不需要关心每个工具内部怎么实现的。
一个很容易忽略的设计点:MCP连接是一对一的,不是广播式服务。也就是说,每个客户端会话需要独立建立连接,Server侧要考虑多会话的资源隔离。本地stdio模式还好说,进程是客户端拉起的;到了远程HTTP模式,就必须做多租户隔离和并发控制,否则一个用户的工具调用会污染另一个用户的状态。
2.2 三大核心原语:Tools、Resources、Prompts
MCP定义了三个核心原语,这是协议最重要的抽象,几乎是所有Server设计的思考框架。
- Tools:可调用的函数,由LLM决定什么时候调用。比如get_changed_files(获取变更文件)、run_tests(运行测试)。每个工具都有输入Schema,类似JSON Schema定义的参数列表。
- Resources:可读取的数据,通常由应用程序或用户决定何时读取。比如代码库里的某个文件、配置文件、项目文档。可以类比成"GET接口",需要被主动拉取,而不是让模型主动调用。
- Prompts:可复用的提示词模板,由用户手动触发。典型场景是把高频复杂任务固化下来,比如code_review(代码评审)、explain_this_code(解释这段代码),这样每次使用不需要重新写一大段Prompt。
这里有一个特别容易混淆的细节:工具和资源的权限方向不同。工具是模型主动调用执行动作,资源是由宿主或用户拉取内容。设计Server时,该用Resource还是Tool要想清楚。咨询类操作适合做成Resource,执行类操作适合做成Tool;把执行操作做成Resource是很危险的,等于让模型通过读数据间接触发副作用,审计和权限控制都会变得很别扭。
以代码评审智能体为例,读取某个文件的原始内容适合做成Resource,因为这个动作本身没有副作用;但是运行静态检查工具就必须做成Tool,因为它会启动一个进程、消耗计算资源、产生副作用。
2.3 传输层与连接生命周期
MCP目前支持两种传输方式:stdio和Streamable HTTP。stdio用于本地进程通信,客户端直接启动Server子进程,通过标准输入输出交换JSON-RPC消息。这种方式调试方便,没有网络开销,适合个人开发场景。Streamable HTTP用于远程通信,支持鉴权、多租户、负载均衡,是商业部署的主流选择。
协议消息基于JSON-RPC 2.0规范,完整的连接生命周期长这样:
- 客户端发送initialize请求,携带客户端名称、版本、协议版本和协议能力集;
- Server返回初始化响应,声明Server的能力集和协议版本;
- 双方协商成功后,客户端发送initialized通知;
- 连接进入在线状态,可以互相发送请求和通知;
- 连接关闭时,任意一方可以发起结束会话流程。
一个很容易踩坑的点是协议版本兼容。MCP协议到现在还在快速迭代,版本演进非常频繁,Server和Client版本不一致时常导致握手失败。生产环境一定要锁定协议版本,升级时要灰度,不能直接全量上。我见过不只一次因为两边SDK各自升级到新版,结果client和server都以为自己是对的,握手阶段就悄悄失败,日志里只有一句不清不楚的connection closed。
那段时间排查这类问题查到怀疑人生,后来养成了一个习惯:所有Server启动时打印当前SDK版本和协议版本,客户端启动时也打印对应版本,先把版本信息对齐再谈功能对接。
3. 商业级AI编程智能体的核心能力设计
3.1 代码理解与上下文工程
编程智能体的能力上限,很大程度取决于"它能不能找到该看的代码"。把整个仓库全部塞给大模型肯定不行,上下文窗口再大也经不起全量灌入,而且大量无关代码会稀释注意力,导致模型抓不到重点。
实践上我做两级召回:
- 粗召回:通过文件路径、符号索引、commit信息先定位候选文件列表;
- 精召回:基于依赖关系和调用关系做子图裁剪,只把真正相关的函数和依赖块带进上下文。
这里通常需要借助LSP(Language Server Protocol)做精确的符号定位,比如跳转到定义、查找引用、列出当前文件大纲。LSP索引提供了整个代码仓库的结构化语义信息,比纯文本切块的RAG方案要准确得多。如果你需要做一个"编程智能体底座",LSP索引加MCP工具出口是性价比很高的组合。
还有一个容易被低估的问题:上下文顺序。同样的代码,按照不同顺序拼接,模型的理解效果差异很大。我的经验是,要像写代码时查资料一样组织上下文:先放任务描述,再放核心入口文件,接着放依赖链路,最后放测试文件的断言逻辑。模型推理时是自回归的,顺序会影响早期的注意力分布,这一步值得反复调优。
3.2 工具编排与沙箱隔离
把工具暴露出去只是第一步。真实任务往往是多步骤的:定位变更文件、跑静态检查、跑单测、收集失败日志、尝试修复、再验证。智能体需要一个安全的"工作台"来执行代码,这个工作台就是沙箱。
沙箱方案在选型时有两条路线:纯进程隔离和容器隔离。纯进程方案实现简单,启动快,但隔离能力弱,适合只执行只读命令的轻量工具;容器方案隔离能力强,能限制CPU、内存、网络,适合执行编译、测试、代码生成这类重命令。我们的代码执行沙箱最终选了容器方案,工具层只暴露白名单内的命令,超时时间、内存限制、网络策略全部由沙箱统一管控。工具的定义刻意做得很收敛,宁可多定义两个细粒度工具,也不要搞一个大而全的"执行任意命令"工具。
沙箱之外要重点考虑工具的并发与限流。大模型经常会在一次推理里并行调用多个工具,如果工具后端是共享的git仓库或CI平台,很容易打爆服务。MCP协议本身不限制并行度,所以限流得自己做。我们用了一个比较简单的策略:每个客户端会话分配一个令牌桶,基础速率每秒两个请求,峰值五个;同时对CI类工具做全局并发限制,超过阈值的请求排队等待,而不是直接拒绝。排队体验比直接报错好得多,模型会把等待当成随机延迟,不会产生异常中断。
3.3 权限、审计与多租户
商业级和demo的分水岭就在权限和审计。我总结过一个关键原则:智能体不应该比用户拥有更多权限。用户说"帮我跑一下测试",智能体实际执行的是"在一个隔离容器里允许运行特定测试命令的白名单动作",而不是给模型一把任意shell的钥匙。
工具参数的收敛设计非常重要。凡是能枚举的就不要开放自由输入,能选择路径前缀的就不要给绝对路径权限。例如,运行测试的工具,scope参数应该限定为"unit"、"integration"、"e2e"这几个枚举值,由服务端映射到具体的测试目录,不能允许用户传任意路径。这一点必须坚持,因为大模型在工具参数生成上偶尔会出现让人意外的行为。
每次工具调用都要落审计日志,至少要包含这些字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| session_id | 会话标识 | sess_9f8a7d3e2b1c |
| user_id | 发起用户 | zhangsan |
| tool_name | 工具名 | run_tests |
| input_params | 入参摘要 | {"scope":"unit"} |
| output_summary | 出参摘要 | {"passed":42,"failed":1} |
| duration_ms | 工具耗时 | 18342 |
| token_cost | 估算成本 | 0.08元 |
| created_at | 调用时间 | 2025-06-11T10:22:31Z |
这些数据是安全审计的基础,也是效果分析和成本追踪的数据源。我见过很多团队连最基础的审计日志都没做,等出了事故才回头补,那基本就是灾难现场。成本追踪在商业落地里往往是被忽略的环节,实际上模型工具调用的token消耗非常快,没有一个逐调用级别的成本归因系统,很容易月底对账时傻眼。
多租户隔离主要分两类:数据隔离和资源隔离。数据隔离确保A项目组的成员看不到B项目组的代码库;资源隔离确保一个租户的并发工具调用不会占满所有人的CPU。这两层隔离在本地stdio模式很容易被忽略,因为stdio是一对一进程;但到了远程HTTP模式就必须认真做,尤其是多人共用Server实例时。
4. 实操:从零搭建一个基于MCP的代码评审智能体
4.1 准备工程与依赖
编程智能体的落地方式有很多,有的团队从UI入口做,有的从IDE插件做,我这次选择从"代码评审助手"切入,因为它边界清晰、价值明确,而且能覆盖MCP协议的主要能力点。
工程语言我选了Python,原因是官方SDK和社区封装库FastMCP都比较成熟,团队内部也更容易维护。整个工程结构长这样:
code-review-agent/ ├── server.py ├── config.yaml ├── requirements.txt ├── tools/ │ ├── __init__.py │ ├── git_tools.py │ ├── analysis_tools.py │ └── review_tools.py └── tests/ ├── test_git_tools.py └── test_review_tools.pyrequirements.txt 内容如下:
fastmcp>=2.0 GitPython pyyaml httpx使用GitPython封装git操作,用pyyaml读取配置文件,httpx留给后续调用内部代码评审接口时用。FastMCP是社区封装库,API比官方SDK简洁很多,尤其适合工具数量不多、希望快速出活的场景。
4.2 编写MCP Server骨架
用FastMCP定义一个服务器非常简洁:
from fastmcp import FastMCP mcp = FastMCP( "code-review-agent", instructions="你是一个代码评审助手。你可以获取变更文件列表、读取文件内容、运行测试,最后输出结构化评审意见。请优先验证高风险代码变更。", ) if __name__ == "__main__": mcp.run()这里有个版本细节要提醒大家:FastMCP的早期版本工具装饰器用@mcp.tool()(带括号),新版推荐@mcp.tool(不带括号)。我写这篇文章时基于带括号的写法,生产项目里最好以你安装版本的官方文档为准,代码库升级时这一行很容易悄悄变化导致工具注册不上。
pip install -r requirements.txt python server.py如果终端没有报错,说明Server进程能正常启动。接下来可以在另一个终端用MCP官方提供的Inspector工具做可视化调试,它能自动拉起Server进程,列出所有已注册的工具、参数Schema,并且可以手动调用任意工具看返回结果。
4.3 实现代码评审核心工具
第一个工具是获取变更文件列表。它的价值在于,让模型永远只关注当前评审范围内的文件,而不是把整个仓库都读一遍。
from git import Repo PROJECT_ROOT = "/workspace/demo-repo" @mcp.tool() def get_changed_files(base: str = "origin/main", head: str = "HEAD") -> list[str]: """返回base分支到head分支之间的变更文件路径列表。 Args: base: 基础分支,默认origin/main。 head: 对比分支,默认当前HEAD。 """ repo = Repo(PROJECT_ROOT) diff_output = repo.git.diff(base, head, name_only=True).splitlines() # 只保留常见源代码文件,去掉依赖锁文件和二进制文件 return [f for f in diff_output if f.endswith((".py", ".ts", ".js", ".go", ".rs"))]注意这里返回的文件列表做了扩展名过滤。一开始我没做过滤,结果模型把package-lock.json也当成代码文件读了,浪费上下文还产生噪音。加一个过滤条件看起来是个小改动,但对后续评审质量有明显提升。
第二个工具是读取指定文件的内容。这个工具本质上是文件读取能力的受控暴露:
from pathlib import Path ALLOWED_ROOT = Path(PROJECT_ROOT) @mcp.tool() def read_file(file_path: str, max_lines: int = 500) -> str: """读取仓库内指定文件的内容。 Args: file_path: 相对于仓库根目录的文件路径。 max_lines: 最大返回行数,防止上下文膨胀。 """ abs_path = (ALLOWED_ROOT / file_path).resolve() # 安全校验:确保解析后的路径仍位于仓库根目录内 if not abs_path.is_relative_to(ALLOWED_ROOT): raise ValueError("file_path must be inside repository root") content_lines = abs_path.read_text(encoding="utf-8").splitlines() return "\n".join(content_lines[:max_lines])这里is_relative_to的路径校验非常关键。如果不做路径穿越防护,"../../etc/passwd" 这种路径就能被传进来,在商业环境就是安全事故。工具接收用户可控参数时,做严格的入参校验是底线。
第三个工具是运行测试,并返回结构化结果。生产环境里这个工具必须对接沙箱,演示时我保留了最简单的subprocess实现,但加上了超时保护:
import subprocess @mcp.tool() def run_tests(scope: str = "unit") -> dict: """在沙箱环境中运行指定范围的测试,返回通过率和失败用例列表。 Args: scope: 测试范围,支持unit/integration/e2e。 """ if scope not in {"unit", "integration", "e2e"}: raise ValueError("scope must be one of unit/integration/e2e") cmd = ["pytest", "-q"] if scope == "unit": cmd.append("tests/unit") elif scope == "integration": cmd.append("tests/integration") else: cmd.append("tests/e2e") try: result = subprocess.run( cmd, capture_output=True, text=True, timeout=180, cwd=PROJECT_ROOT, ) except subprocess.TimeoutExpired: return {"passed": False, "error": "timeout"} return { "passed": result.returncode == 0, "exit_code": result.returncode, "stdout_tail": result.stdout[-2000:], "stderr_tail": result.stderr[-2000:], }返回结果只保留stdout和stderr的最后2000个字符,这个细节是为了控制上下文窗口。完整日志没有必要喂给模型,失败时的尾部信息通常足够定位问题;如果模型需要更多日志,可以再暴露一个专门读取日志文件的工具,按需读取。
第四个工具是综合生成评审意见。这一步本质上不是让模型自由发挥,而是先收集结构化证据(变更文件、diff内容、静态扫描结果),再让模型基于证据输出高优问题。工具内部可以调用一个独立的LLM接口,做一次专门的评审调用:
@mcp.tool() def generate_review(pr_number: int) -> list[dict]: """基于变更文件和测试结果生成PR评审意见列表。 Args: pr_number: 需要评审的PR编号。 """ changed_files = get_changed_files() evidence = [] for file_path in changed_files[:10]: content = read_file(file_path, max_lines=300) evidence.append({"file": file_path, "content": content}) # 这里调用内部LLM服务做结构化评审 review_result = call_review_llm(pr_number, evidence) return review_result这一层抽象的意义是,评审意见的生成策略可以独立迭代,工具是否运行成功不受模型上下文限制的干扰,也让评审输出格式始终保持结构化,方便后续接入群机器人或IM通知。
4.4 配置客户端接入与联调
Server写好了,下一步就是把它接到支持MCP的客户端里。以Claude Desktop为例,配置文件通常在claude_desktop_config.json:
{ "mcpServers": { "code-review-agent": { "command": "python", "args": ["/absolute/path/to/code-review-agent/server.py"], "env": { "PROJECT_ROOT": "/workspace/demo-repo" } } } }这里有几个细节需要特别提醒:
- command和args必须使用绝对路径,因为stdio模式下Server是作为子进程被客户端拉起的,工作目录不一定是你的项目目录;
- 环境变量可以在MCP配置里直接注入,这样Server代码里能读取PROJECT_ROOT这类变量,不用把仓库路径硬编码进代码;
- 首次接入时,先在终端手动执行一遍
python /absolute/path/to/server.py,确认没有报错再接客户端,能省下大量排查时间。
联调阶段我强烈推荐用MCP Inspector,它会很直观地列出所有工具、参数Schema、调用结果。我先用Inspector把四个工具全部手动调了一遍,确认返回结果正常,再切到真实客户端里做端到端测试。端到端测试时一定要给模型一个具体场景,比如"请帮我评审一下main分支最近3个commit的变更",而不是让模型自由发挥。
4.5 生产化改造:远程Server、鉴权与监控
本地stdio版本跑通只是第一步,商业级落地一定要考虑远程化。远程部署方式我推荐Streamable HTTP,整体架构变成客户端调用统一网关,网关再将请求转发到具体的MCP Server实例。
FastMCP支持HTTP模式的启动:
fastmcp run server.py --transport http --port 8000生产环境需要在前面加一层网关,统一处理四类事情:
- 鉴权:企业内部可以用SSO对接,推荐OAuth 2.1流程,最小实现也要有API Key鉴权;
- 连接复用:MCP HTTP连接是有状态的,网关要处理连接生命周期,尽量避免频繁建立和销毁连接;
- 负载均衡:多个Server实例背后挂服务发现,动态路由到健康实例;
- 审计日志:在这一层同时记录请求级别和工具级别的日志,方便做调用链追踪。
我对生产服务的监控指标一般拉五块:工具调用成功率、工具耗时分布、平均每会话工具调用次数、token消耗量、模型返回质量人工评分。其中token消耗量常常被忽略,但它是成本失控的第一预警信号。建议每天对账一次,粒度细化到工具级别,找出哪个工具最费token,才能针对性做上下文裁剪优化。
5. 常见问题与排查技巧实录
5.1 连接失败与协议版本不一致
这段时间被问得最多的问题就是"按理说都配好了,为什么连接不上"。这种问题第一件事看日志,第二件事看版本。
排查思路我整理成了一个固定流程:
- 手动启动Server,确认进程能正常起来;
- 用MCP Inspector连接,看工具列表是否展示;
- 检查客户端是否显示初始化失败或者工具超时;
- 如果依然失败,检查SDK版本和MCP协议版本。
MCP协议迭代很快,新旧版本不兼容的情况并不罕见。两个比较新的SDK都可能因为约定细节的变化导致握手失败。生产环境锁定版本是最省心的选择。
5.2 工具调用超时会话卡死
我的代码评审Agent刚上线时遇到过一个典型问题:模型调用了run_tests工具,但pytest跑了两分钟还没结束,模型一直在等待结果,整个会话就挂在那边。客户端在等待工具返回期间一般不会继续生成内容,用户体感就是"卡死了"。
解决思路是给工具设计快失败机制:
- 工具内部执行体一定要放到子进程里,设置硬超时,进程到点就kill;
- 超过30秒的任务应该设计成任务队列模式:先提交任务拿到task_id,再用轮询工具查询状态;
- 返回结果要结构化,至少告诉模型"任务还在进行中"还是"任务已失败"。
任务队列模式虽然多写点代码,但整体体验提升非常明显。模型学会了收到task_id后就主动轮询,不会一直干等。
5.3 上下文膨胀与召回质量差
“模型聊着聊着就失忆了”是编程智能体很常见的症状,本质原因通常不是模型窗口不够,而是我们把太多不重要的信息塞进了上下文。
解决上下文膨胀,我做了一个"返回结果瘦身"规范:
- 凡是列表类型的结果,最多返回前20条,并附带总数统计;
- 凡是文本类的结果,超过2000字符就截断并提示后续可按需读取;
- 工具内部不做任何输出的情况下,要返回一个精简的说明文本;
- 在业务层记录每个工具返回内容的估算token数,每天看报表,找出最费token的工具做专项优化。
5.4 沙箱逃逸与命令注入风险
代码执行类工具最怕的就是命令注入。我给编程智能体里的所有shell操作定了三条铁律:
- 绝不把用户输入直接拼进shell命令行;
- 优先使用subprocess列表形式传参,避免经过shell解释;
- 参数必须白名单校验,比如scope限定枚举,路径限定在仓库根目录内。
容器沙箱配置上,最小权限是一个原则。关闭特权模式,设置只读根文件系统,限制网络访问只允许内网域名,内存上限按工具类型区分:编译类工具给4GB,单测类工具给2GB,静态扫描给1GB。这些配置看起来琐碎,但都是真实碰过壁后的教训。
5.5 鉴权过期与多租户穿越
远程部署后一个高频问题是鉴权会有遗漏。stdio模式没有鉴权问题,因为进程是本地拉起的;但HTTP模式一开,等于把工具入口暴露到了网络上,鉴权就必须做扎实。
我见过一个团队把内部代码评审Agent绑到共有网关上,结果发现任何人拿到网关地址都能调用工具。解决办法需要好几层同时上:网关鉴权要强制每次请求验证合法用户身份,Server实例要按租户隔离部署,工具的入参校验要加上租户维度的路径前缀校验。把这几层都做好,才算真正把多租户问题解决掉。
6. 落地心得与扩展方向
这套基于MCP的代码评审智能体从设计到落地,前后大概花了一个半月,最大的体会有三点。
第一,协议只解决连接标准化,不解决智能本身。MCP确实让工具接入这件事变简单了,但真正决定智能体质量的是工具设计、上下文策略、权限控制这些工程细节。模型能力会迭代,MCP协议也会演化,但一套设计良好的工具边界和上下文组织策略,是能长期沉淀的资产。
第二,从一个足够小的场景切入,远比一步到位做一个"万能智能体"靠谱。代码评审这件事边界清晰:它只需要读代码、跑测试、写意见,不涉及修改代码。这个清晰边界让我们能快速上线、快速验证,然后再逐步扩展。如果一开始就想做全流程开发助手,大概率会因为范围失控而寸步难行。
第三,审计日志和成本追踪这些"不性感"的工程模块,一定要从第一天就做。后面补数据永远比一开始多写几十行日志包装函数要痛苦得多,而且在商业项目里,没有审计记录等于事故来临时没有安全带。
扩展方向上,我计划做四件事:把内部Wiki和告警平台都改造成MCP Server,让智能体能获取更多上下文;把高频Prompt沉淀成MCP Prompts模板,让这里的经验和规范能跨会话复用;基于工具调用tracing做每任务级别的成本归因,协调各业务线合理分摊AI成本;最终把智能体的能力也封装成内部API服务,让更多团队能复用同一套工具和权限体系。
最后再分享一个小技巧:MCP Server的instructions字段值得用心写。它相当于给所有工具的顶层使用说明,模型在进入会话时就会读到。我写过一版平平无奇的和一版精心组织的,前者的工具调用失误率明显高于后者。有时间的话,值得在这个字段上多打磨几轮。