从零开始,构建一个与 GitHub、Slack 和 Asana 集成的、可在您的组织内扩展的 AI PR 评审机器人。
作者:ANCA IOANA MUSCALAGIU
日期:2025 年 8 月 19 日
本文是开源课程设计企业级 MCP 系统的第一课——这是一个免费课程,将教您如何架构和构建能够跨团队、跨工具扩展的 AI 驱动的开发者工作流。
在这趟共三节课的旅程中,您将学到如何:
运用简洁、模块化的、基于 MCP 的设计来架构大语言模型应用。 构建真实世界的开发者体验自动化工具,例如 AI PR 评审助手。 为系统的规模化和适应性选择正确的 AI 智能体架构。
课程列表:
第一课:为什么 MCP 颠覆了传统企业级 AI 架构 第二课:动手实践——使用 MCP 构建企业级 AI 系统 第三课:为 AI 系统选择正确的智能体架构
为什么 MCP 颠覆了传统企业级 AI 架构
如今,MCP (模型上下文协议) 无处不在。
只要你浏览任何开发者社区,都能看到关于如何快速启动一个 MCP 服务器、如何将其接入你的 IDE (集成开发环境),或是如何连接到 Claude Desktop 的教程。它很酷,很新潮,感觉就像是未来。
但大多数教程都浅尝辄止。它们只展示了如何将一个东西连接到另一个,却忽略了它为何值得你关注。MCP 真正的魅力不在于连接本身,而在于它如何改变你在规模化场景下设计自动化系统的方式。
本文不是又一篇「如何搭建服务器」的指南,而是探讨为什么你可能希望从一开始就将 MCP 作为系统的基石。读完本文,你将明白 MCP 真正的价值所在,并能判断是否值得从项目第一天就采用它。
大多数大语言模型项目始于一个提示词或一个临时的小技巧。而我们的项目则始于一个用例和解决方案架构,并在此基础上深入探讨如何实现它。
这个用例是什么?一个能在你同事看到你的拉取请求 (Pull Request) 之前就完成评审的 AI 助手。它快速、自动化且具备上下文感知能力。
你可以把它想象成一个从不鸽你 PR、从不纠结于分号、并且会认真阅读代码差异 (diff) 的代码评审员。
在这个系列中,我们将构建一个生产就绪的 PR 评审助手——一个由大语言模型驱动的系统,它能监听 GitHub 的拉取请求,对其进行分析,并将评审摘要直接发布到 Slack。这是一个真实的应用场景,包含了真实的系统集成和现实的约束。
但真正重要的是我们构建它的方式——我们使用的是 MCP,这是一个能让大语言模型系统变得模块化、可测试并为规模化而生的标准。
这是一篇侧重动手实践的指南,而不仅仅是理论。在本课中,我们将剖析设计决策;在下一课,我们将深入代码实现。(如果你已经迫不及待,可以直接跳转到 GitHub 仓库,边读边看。
在本课中,你将学到:
MCP 究竟是什么,以及它在真实 AI 系统中解决了什么问题。 其核心架构中的客户端、主机和服务器是如何协同工作的。 如何构建一个 PR 评审助手,并将 MCP 付诸实践。
目录:
MCP 到底是什么?(以及为什么你应该关心它?) 传统智能体设置 vs. 基于 MCP 的架构 MCP 的工作原理 使用 MCP 设计 PR 评审助手 为什么这种架构能够扩展(以及为什么你日后会感谢自己)
1. MCP 到底是什么?(以及为什么你应该关心它?)
AI 系统起初都很简单,但很快就会变得一团糟。只要增加几个工具,连接一些 API (应用程序接口),你很快就会发现自己正在处理脆弱的集成和无处不在的自定义胶水代码。
似乎每个框架、SDK (软件开发工具包) 或服务都在定义自己的工具格式、自己的输入输出处理方式,以及自己那套未被文档化的约定。有的期望 OpenAPI 风格的 schema,有的希望将函数签名嵌入 JSON,还有的则依赖于带有自定义解析逻辑的硬编码 Python 装饰器。
即便只是调用两个功能相同的工具,也可能需要完全不同的调用逻辑。
结果呢?所有东西都无法协同工作。
你最终会陷入在包装器之上编写适配器,又在适配器之上编写各种临时补丁的困境。工具无法复用,工作流与特定的实现紧密耦合,测试变成一场噩梦,而扩展或替换组件则感觉像是在处理一团乱麻般的代码。
这种碎片化不仅令人烦恼——它更是构建可维护、可扩展的大语言模型系统的核心瓶颈。
这正是 MCP 旨在解决的问题。
MCP 是一个协议,一个用于构建模块化、消息驱动的大语言模型系统的正式标准。它不仅仅是一个库或框架,更是一种架构 AI 软件的方法,使其不会在自身重量下崩溃。
它定义了客户端、主机和服务器之间的通信方式,明确了各自的角色和结构化的消息格式,从而让你的工作流默认就具备可组合、可测试和可扩展的特性。
可以把它想象成 HTTP:
协议定义了事物之间应该如何对话。 实现只是你选择使用它的方式。 多个系统可以相互交互,而无需为每一个系统编写定制的集成代码。
MCP 本身不带来任何新功能。
它带来的是结构。它只是将我们早已在工具使用型智能体中实践的模式,以一种能像真实软件一样扩展的形式正式化了。它捕捉了大语言模型系统在成熟过程中自然浮现出的设计模式,并为我们提供了一个构建它们的共享标准。
因此,与其为每个项目重新发明架构,MCP 为你提供了一种从第一天起就以一致、可互操作的方式正确构建系统的方法。
如果你希望你的 AI 工作流能够扩展、演进并保持清晰,你需要用协议的思维方式来思考——而不仅仅是提示词。
图 2:MCP 应用前后的工具集成对比
2. 传统智能体设置 vs. 基于 MCP 的架构
早期的智能体构建追求速成:接入几个工具,得到结果,然后继续下一个任务。但随着时间的推移,这些捷径会变成难以维护或扩展的混乱代码。
你可以将其看作是内联的、单体式智能体与 MCP 的对比,后者强制实现了清晰的关注点分离。当你看待工具的集成和管理方式时,这种方法的差异就变得显而易见了。
旧的方式:
工具被硬编码到智能体循环中(例如,一个 summarize_diff()
调用直接写在逻辑里)。没有清晰的抽象,因此任何改动都意味着编辑核心代码(提示:是的,这正是我们课堂上都点头认同的开闭原则!)。 扩展过程痛苦,跨不同框架复用工具几乎不可能。
MCP 的方式:
工具、资源和提示词位于独立的服务器上,与核心逻辑解耦。 一个标准接口使得智能体对扩展开放,对修改关闭,让你能接入多个服务器。 相同的接口使得工具可以在不同框架间复用,简化了扩展和实验过程。
这种关注点分离使你的工作流保持整洁,工具可复用,并且系统能随着需求变化而更容易地演进。
3. MCP 的工作原理
那么,MCP 究竟是如何实现这一切的呢?
它始于一个简单的理念:系统中的每个部分都有一个明确的职责。
MCP 的核心采用了一种基于角色的架构。在一个由 MCP 驱动的应用中,每个组件都扮演以下三种角色之一:
主机 (Host) – “智能体的大脑”。它收集上下文,决定使用哪些工具,并协调整个工作流。例如,一个 Python 应用、一个 IDE 或 Claude Desktop。 客户端 (Client) – 发起任务并直接与服务器对话,与每个 MCP 服务器保持一对一的连接。 服务器 (Server) – 暴露工具、资源和提示词,供 AI 应用程序使用。
可以这样理解:客户端请求,主机决策,服务器交付。
现在,让我们聚焦于 MCP 服务器最常见的任务之一——工具调用 (tool calling)——看看这些部分是如何协同工作的。
图 3:MCP 的工具调用工作流程
首先,MCP 客户端向 MCP 服务器询问有哪些可用的工具。
当工具列表返回后,大语言模型网关(即你的智能体逻辑)会选择合适的工具并填充参数——例如,请求运行 summarize_diff
。然后,客户端将该请求发送到服务器。
MCP 服务器执行被请求的工具,并将结果返回。客户端将结果传递给大语言模型,后者利用这个结果继续工作流并生成最终的响应。
因为 MCP 定义了一个通用协议,所以每个服务器都说同一种“语言”。
你的主机和客户端无需了解每个服务器的内部工作原理。它们只需发送一个请求,然后以标准格式接收响应即可。
这意味着你可以用一个服务器替换另一个——比如替换你的 PDF 处理器或更改你的 GitHub 集成——而无需触动系统的其余部分。
你也可以在不重写核心逻辑的情况下添加新的服务器,让你的系统随着时间推移而成长,而不是被一次性的集成所束缚。
为了理解这在实践中是如何运作的,让我们看一个涉及多个服务器的完整 MCP 架构:
图 4:MCP 架构
此图展示了实践中的 MCP 架构,其中一个单一的主机连接到系统中的多个服务器。
当你使用多个服务器时,整体流程依然相似——但有一个重要的变化:主机现在需要将每个请求路由到拥有相应工具的服务器。
主机仍然是流程的驱动者。它使用大语言模型来推理任务,然后通过其连接的 MCP 客户端将请求传递给适当的服务器。由于每个服务器暴露的工具不同,选择正确的服务器至关重要。
正如我们前面提到的,服务器处理实际的功能。它们提供诸如 summarize_diff
、get_jira_issue
或 extract_keywords
之类的工具,主机可以通过标准的 MCP 消息来调用它们。
但工具执行只是故事的一部分。让我们来探讨一下服务器还能提供什么。
服务器能提供什么?
大多数文章都将 MCP 服务器过度简化为“仅仅是工具”。
事实并非如此。服务器远不止是工具的端点。
它们可以暴露三种类型的东西:
工具 (Tools) – 可供调用的函数,如 send_slack_message
、summarize_diff
或fetch_weather
。资源 (Resources) – 可供检索的数据,例如来自本地文件系统或内部数据库的文件。 提示词 (Prompts) – 预定义的模板或系统消息,客户端可以填充并用于大语言模型的调用。
这些服务器就像模块化的构建块,每个都专注于单一目的,但都说着同一种 MCP “语言”。
它们使用什么协议?
MCP 在底层保持了简洁性:它完全构建在 JSON-RPC 之上。
这是一种轻量级协议,常用于微服务中进行服务器到服务器的通信,其中所有内容都编码为 JSON,并通过简单的请求-响应格式进行交换。
{
"jsonrpc": "2.0",
"method": "summarize_code",
"params": {
"file_path": "src/utils/helpers.py"
},
"id": 1
}
这个标准定义了客户端和服务器如何交换消息,但它并不将你锁定在某一种传输方式上。你可以选择最适合你环境的方式:
stdio (非常适合开发)
客户端将服务器作为一个子进程启动,并通过 stdin/stdout
进行通信。快速且同步。 非常适合将服务器作为 Python 模块运行或进行快速的本地测试。 流式 HTTP (生产就绪)
允许服务器以标准的 HTTP 响应或按需流式传输数据来回应。 支持可选的会话 ID,用于状态管理和恢复。 足够灵活,可用于从无服务器函数到大规模 AI 应用的任何场景。 以更好的可靠性和会话恢复能力取代了旧的 HTTP + SSE 方法。
我们如何保护它们?
既然我们知道服务器提供了实际的数据……我们该如何保护它们的安全呢?
当你将一个 MCP 服务器暴露给外部世界时,你实际上是在为你的系统打开一扇门。
如果有人获得了未经授权的访问,他们可以:
触发他们本不应有权访问的工具(想象一下部署代码或删除文件)。 从资源中拉取敏感数据。 滥用提示词进行非预期的自动化操作。
这并非危言耸un——任何开放的端点都可能成为攻击目标,MCP 服务器也不例外。
首选方案:OAuth 2.0
保护这些服务器最常用的方法是 OAuth 2.0。与分发一个对所有人(和所有事物)都有效的静态令牌不同,OAuth 发行有范围限制、有时间限制的令牌,并与特定的用户或系统绑定。
这意味着:
每个用户或客户端进行身份验证后,都会获得一个唯一的令牌。 令牌可以过期或被撤销,从而限制了长期风险。 访问权限可以被限定范围,因此一个用户可能只能读取数据,而另一个用户则可以运行管理工具。
这就是为什么 OAuth 2.0 成为生产环境中 MCP 部署的标准——它久经考验、灵活,并且能与许多身份提供商集成。
为了更直观地理解其工作原理,下面是一个 MCP 主机和远程 MCP 服务器之间典型的 OAuth 2.0 流程:
图 5:在 MCP 中使用 OAuth 2.0
让我们简要地过一遍图中的每个步骤:
MCP 主机使用其 client_id
和client_secret
向授权服务器进行身份验证。它会收到一个有范围限制的访问令牌——这不是一个万能凭证,而是仅限于该主机被允许执行的操作(例如,调用特定的工具,而非所有工具)。 MCP 主机向远程 MCP 服务器发送一个请求,并将令牌包含在 Authorization
头部中。MCP 服务器验证该令牌。 如果令牌有效且权限足够,服务器将执行请求的工具并返回结果。
这种设置确保了精细的访问控制,并保障了系统的安全。
4. 使用 MCP 设计 PR 评审助手
现在,让我们通过一个真实的用例来巩固这个心智模型。
想象一下,你想要一个 AI 队友,在拉取请求被创建的那一刻就对其进行评审,并将反馈发送给你的团队,而你无需动一根手指。不再需要等待忙碌的评审员,不再有半途而废的反馈,也不再需要在 Asana 的任务卡中翻找缺失的上下文。
我们都经历过这样的场景——评审员盯着上千行的代码差异,不知道从何看起;而提交者则像刷新航班状态一样不停地刷新页面。
那么,你该如何真正设计出这样的系统呢?
下图展示了一种使用 MCP 将其连接起来的方法:
图 6:PR 评审智能体的数据流
在我们的用例中,MCP 主机是一个由 Gemini 大语言模型驱动的 FastAPI 应用,通过一个 Webhook (网络钩子) 连接到你的 GitHub 仓库。它是那个在 PR 出现时立即做出反应并精确决定下一步该做什么的组件。
该主机运行一个单一的 MCP 客户端,连接到 MCP 全局服务器,后者将所有 MCP 服务器集中管理。它组织工具、提示词和资源,为它们打上标签,并让你能轻松地找到所需内容,而无需翻阅零散的配置文件。
对于这个设置,有四个 MCP 服务器负责处理繁重的工作——每个都有特定的职责:
GitHub MCP 服务器 – PR 上下文的主要来源。它拉取元数据、文件变更和代码差异,以便评审时能全面了解提议的修改内容。 Asana MCP 服务器 – 提供 PR 背后的任务级上下文。它能调出关联的任务和需求,这样你就能判断这些变更是否真正实现了承诺的功能。 Agent Scope MCP 服务器 – 评审逻辑的起点。主机从这里检索初始的 PR 评审提示词,确保大语言模型确切地知道如何构建和进行评估。 Slack MCP 服务器 – 处理交付的最后一步。它将完成的评审发布到正确的 Slack 频道,确保团队能在他们日常沟通的地方即时看到反馈。
现在我们了解了每个组件,让我们来走一遍整个流程:
一位开发者在 GitHub 中创建了一个拉取请求。 GitHub 向我们的 FastAPI 主机触发一个 PR opened
事件,并附带所有 PR 元数据。主机向 Agent Scope MCP 服务器(通过全局服务器)请求合适的 PR 评审提示词。 主机将 PR 数据和提示词发送给 Gemini,询问需要运行哪些工具。 Gemini 返回一个计划——例如,获取 PR 内容,抓取关联的任务。 主机调用全局 MCP 服务器来执行所需的工具并收集必要的数据。 每个 MCP 服务器与其外部 API 通信,执行任务,并将结果返回。 主机将这些结果发送给 Gemini,以生成最终的评审意见。 评审意见被发送到 Slack MCP 服务器,后者将其直接发布到团队频道。
注意:在某些情况下,Gemini 可能会在后续的轮次中请求额外的工具调用,这意味着步骤 5-9 可能会循环,直到所有必需的数据都被收集完毕且评审完成。
就这样,你的 PR 被评审、补充了上下文并分享给了团队——而你甚至还没来得及切换浏览器标签。
5. 为什么这种架构能够扩展(以及为什么你日后会感谢自己)
MCP 不仅仅是简洁的架构——它是一种面向未来的方式,用以构建不会在自身复杂性下崩溃的 AI 系统。
它之所以能够扩展,是因为每个组件都遵循相同的协议。增加一个新功能并不意味着要重写其他所有东西——仅仅是插入另一个组件那么简单。
你构建的不再是一个越来越难以维护的、庞大的单体系统,而是一系列能够自然组合在一起的、小而独立的单元。
现在,想象一下这个场景。
图 7:使用 MCP 设计的企业级开发者体验 (DevEx) 系统
假设你的企业想要三个开发者体验自动化工具:一个 PR 评审机器人、一个事件响应机器人,以及一个研究摘要工具。在大多数设置中,每个工具都需要自己与 GitHub、Slack、Jira 和其他服务进行集成。
有了 MCP,它们都连接到同一组共享的服务器。如果某个服务的流量很大——比如 Slack——你只需启动另一个同类型的服务器来分担负载。而同一个 GitHub 或 Jira 服务器可以在所有 AI 应用中复用,无论你将来增加多少个应用。
所有这些都意味着你能获得一些非常实在的好处。
可复用性 (Reusability)。 你可以用 Claude 替换 OpenAI 或 Gemini,而无需触动工作流的其余部分。你为一个项目构建的 Slack 服务器?你可以在其他十个项目中复用它。需要支持多个产品?只需为每个产品接入一个不同的地图服务器——无需胶水代码,也无需重复劳动。 可靠性 (Reliability)。 因为所有东西都通过一个标准接口运行,所以每一步都是可追溯的。你可以看到哪个服务器运行了哪个工具,输入和输出是什么。而且由于服务器是无状态且可模拟 (mockable) 的,编写测试变得非常直接。再也不用为了检查一个工具是否正常工作而去伪造端到端的流程了。 可扩展性 (Scalability)。 当你准备好扩展——真正地扩展时——你不会被锁定在一台机器或一个代码仓库里。服务器可以存在于不同的机器上,由不同的团队维护,甚至跨越组织边界。它在设计上就是分布式的。 成本效益 (Cost efficiency)。 共享服务器意味着你不用重复构建相同的集成。这节省了工程时间,降低了基础设施成本,并且可以在不中断服务的情况下将工作负载迁移到更便宜的环境中。
MCP 将微服务的思维方式带入了 AI 开发领域。
它将你的大语言模型工作流转变为可组合的基础设施——而不仅仅是围绕聊天模型的巧妙包装。
结论
至此,我们已经从“MCP 是个时髦词”走到了“我知道如何用 MCP 来架构我的下一个 AI 系统”。
理论时间结束了——现在是时候将它变为现实了。
在下一课中,我们将从头到尾完整地走一遍实现过程——启动服务器,通过主机将它们连接起来,并看着 PR 评审助手像团队中一直存在的一员那样,完成它的第一次完整评审。
已经感到好奇了?在这里查看完整的代码库:https://github.com/decodingml/enterprise-mcp-course
一键三连「点赞」「转发」「小心心」
欢迎在评论区留下你的想法!