关于MCP协议最值得看的一篇:起源、架构优势和未来

本文来自微信公众号:Founder Park,作者:Founder Park,原文标题:《关于MCP最值得看的一篇:MCP创造者聊MCP的起源、架构优势和未来》,题图来自:AI生成

MCP协议由Anthropic团队受LSP启发开发,旨在标准化AI应用与外部扩展的通信。其核心设计强调工具由模型调用、用户完全控制,支持工具、资源和提示三类交互。协议通过JSON-RPC实现双向通信,与OpenAPI互补,未来将聚焦状态化交互和安全授权。开发者可通过AI辅助快速构建服务器,生态发展正推动跨公司协作和多样化应用场景。

• 💡起源灵感:受LSP协议启发,解决AI应用与扩展的MxN集成难题

• ⚙️核心设计:工具由模型调用,资源与用户操作绑定,强调用户控制权

• 🔄互补关系:与OpenAPI分工协作,MCP适合复杂交互,OpenAPI适配API规范解析

• 🚀快速构建:利用AI辅助生成代码片段,简化服务器开发流程

• 🌐未来方向:推动状态化交互(Statefulness),平衡协议复杂性与操作便捷性

• 🤝生态发展:多家公司参与贡献,SDK支持多语言,目标成为社区驱动的开放标准

Anthropic 在去年发布的 MCP 协议,今年因为 Manus 和 Agent 的热潮,突然成为了 AI 领域最热门的协议。OpenAI、微软、Google 等大厂也纷纷支持协议,国内阿里云百炼、腾讯云也迅速跟进,上线了快速搭建平台。

但争议也不少,很多人质疑 MCP 和 API 区别不大、Anthropic 的工程师对互联网协议不怎么精通、以及协议太简单带来的安全问题等等。

让 MCP 协议的发明者来回答这些问题,再合适不过了。

在 Latent Space 最近的一起播客中,他们邀请到了 Anthropic 团队 MCP 协议的发明者——Justin Spahr-Summers、 David Soria Parra,详细聊了聊 MCP 的起源,以及他们对于 MCP 诸多想法:为何推出 MCP、 MCP 与现有的 API 有何不同、如何让 MCP 更好利用好工具等等。信息量很大,建议收藏阅读。

对谈嘉宾介绍:

  • Alessio Fanelli(主持人):Decibel 合伙人兼 CTO

  • swyx(主持人):Small AI 创始人

  • David Soria Parra:Anthropic 工程师

  • Justin Spahr-Summers:Anthropic 工程师

TLDR:

  • MCP 概念的“灵光一闪”来自 Anthropic 的一个内部项目 LSP(Language Server Protocol),两位工程师借由 LSP 的启发,想到能否做一个类似 LSP 的东西,从而把“AI 应用与扩展之间的通信”标准化。

  • MCP 的核心设计原则是:工具这个概念实际上不仅仅是工具本身,还与客户端应用程序息息相关,进而也与用户紧密相连。通过 MCP 的操作,用户应该拥有完全的控制权。工具由模型控制,指的是仅仅由模型来调用,而不是由用户主动指定使用某个工具(出于提示目的的情况除外)。

  • 开放 API 和 MCP 并非相互对立,而是非常互补。关键在于选择最适合特定任务的工具。如果目标是实现 AI 应用之间丰富的交互,MCP 更适合;如果希望模型能够轻松读取和解释 API 规范,开放 API 会是更好的选择。

  • 对于 MCP 服务器的快速构建,利用 AI 辅助编码是一种非常好的方式。在开发初期,将 MCP SDK 的代码片段放入 LLM 的上下文窗口,让 LLM 帮助构建服务器,结果往往很不错,细节可以在后期进一步优化,这是一种快速实现基本功能并进行迭代的好方法。同时,Anthropic 的 MCP 团队非常注重简化服务器的构建流程,便于 LLM 能够参与进来。

  • AI 应用、生态系统和 Agent 的未来发展方向会倾向于 Statefulness,同时这也是 Anthropic 的 MCP 核心团队内部最具争议的话题之一。在经过了多次讨论和迭代后,得出的结论是尽管目前看好 Statefulness 的未来,但不能因此背离现有的范式,必须在 Statefulness 的理念和实际操作的复杂性之间找到平衡。

一、MCP 是如何诞生的?

swyx(主持人):首先,MCP 是什么?

Justin:模型上下文协议,Model Context Protocol,简称 MCP,基本上是我们设计出来帮助 AI 应用拓展自身或集成插件生态系统的设计,具体而言,MCP 提供了一套通信协议,让 AI 应用(我们叫“客户端”)和各种外部扩展(我们叫“MCP 服务器”)能彼此协作。这里的“扩展”可以是插件、工具或者其它资源。

MCP 的目的就在于让大家在构建 AI 应用时,能够轻松引入外部服务、功能,或者调取更多数据,让应用拥有更丰富的能力。我们的命名中有“client-server”的概念,主要是为了强调交互模式,但本质就是在做一个“让 AI 应用更易扩展”的通用接口。

不过需要强调的是,MCP 关注 AI 应用而非模型本身,这是常见的误解。此外,我们认同将 MCP 类比为 AI 应用程序的 USB-C 接口,它是连接整个生态系统的通用接口。

swyx(主持人):客户端和服务器的特性意味着它是双向,就像 USB-C 接口一样,这很有意思。很多人尝试做相关研究、构建开源项目。我感觉 Anthropic 在争取开发者方面,比其他实验室都积极。好奇这背后是受外部影响,还是你们俩在某个房间里灵光一现想出来的?

David:实际上,大多就是我们俩在房间里灵光一现想出来的。这不是宏大战略的一部分。2024 年 7 月,我加入 Anthropic 不久,主要负责内部开发者工具。期间,我思考如何让更多员工深入整合现有模型,毕竟这些模型很棒,而且前景更好,自然是希望大家多用自家模型。

在工作中,基于我在开发工具方面的背景,很快就觉得有点沮丧,一方面因为 Claude Desktop 功能有限,无法拓展,而 IDE 又缺少 Claude Desktop 的实用功能,所以我只能在两者间来回复制内容很麻烦。久而久之。我意识到这是个 MxN 的问题,也就是多个应用程序与多种集成的难题,而用一种协议解决再合适不过。当时我还在做一个与 LSP(Language Server Protocol)相关的内部项目,没什么进展。综合这些想法,琢磨几周后,我有了构建某种协议的念头:能不能做一个类似 LSP 的东西?把这种“AI 应用与扩展之间的通信”标准化。

于是,我找到 Justin,分享了这个想法,幸运的是他很感兴趣,我们便一起着手构建。

从有想法开始,花了约一个半月构建协议并完成首次集成。Justin 在 Claude Desktop 首次集成中承担了大量工作,我则在 IDE 中做了许多概念验证,展示协议在 IDE 中的应用。在正式发布前,查看相关代码库能发现不少细节,这就是 MCP 大概的起源故事 。

Alessio(主持人):时间线是怎样的呢?我知道 11 月 25 日是正式发布日期。你们什么时候开始着手做这个项目的?

Justin:7 月左右,David 提出想法后,我很快就兴奋地与他着手构建 MCP。最初几个月,因为搭建包含客户端、服务器和 SDK 的通信协议有大量基础工作,所以进展很缓慢。但当东西能通过协议通信后,便令人兴奋起来,能构建各种奇妙的应用。

后来我们内部办了一场黑客松,一些同事用 MCP 编了可以控制 3D 打印机的服务器,还有实现“记忆功能”之类的扩展。这些原型大受欢迎,让我们相信这个想法能带来很大潜力。

swyx(主持人):回到构建 MCP,我们看到的只是最终成果,它明显受 LSP 启发,这点你们俩也承认。想问问构建时的工作量如何?构建过程主要是大量编写代码,还是做大量设计工作?我感觉设计工作占比大,比如选用 JSON-RPC,借鉴 LSP 的程度如何?还有哪些部分难度较大 ? 

Justin:我们从 LSP 获得很多灵感。David 在开发工具方面对 LSP 经验丰富,我主要从事产品或基础设施工作,LSP 对我来说是新事物。

从设计原则看,LSP 解决了 David 提到的 M x N Problem。之前,不同 IDE、编辑器和编程语言各自为政,你无法在 Vim 中使用 JetBrains 出色的 Java 支持,也无法在 JetBrains 中使用 Vim 出色的 C 语言支持。LSP 通过创建通用语言让各方能 “交流”,LSP 统一了协议,让“编辑器-语言”各自只需要实现一次。而我们的目标类似,只不过场景换成了“AI 应用-扩展”之间的对接。

具体细节上,我们采用 JSON-RPC 和双向通信概念之后,走向了不同方向。LSP 注重功能呈现,思考并提供不同的基本元素,而非语义的原则,我们也应用到 MCP 中。之后,我们花大量时间思考 MCP 中的每个基本元素及其差异的原因,这是大量的设计工作。一开始,我们想支持 TypeScript、Python 以及用于 Zed 集成的 Rust 三种语言,构建含客户端和服务器的 SDK,打造内部试验生态系统,并让本地 MCP 概念(涉及启动子进程等)稳定下来。

我们参考了针对 LSP 的诸多批评意见,尽量在 MCP 中改进。例如 LSP 在 JSON-RPC 上的某些做法太复杂,我们就做了一些更直接的实现方式。因为构建 MCP 时,我们选择在特定领域创新,在其他方面借鉴成熟的模式,比如选择 JSON-RPC 之类的并不重要,而将重点放在基本元素等创新上,这些方面借鉴前人成果对我们很有帮助 。

swyx(主持人):我对协议设计感兴趣,这里有很多内容能展开。你们已经提到 M x N Problem,其实从事开发者工具工作的人都遇到过,也就是 “万能盒子(Universal Box)” 问题。

基础设施工程的基本问题和解决办法是,要将很多东西连接到 N 个不同事物,弄个 “万能盒子” 就好。像优步、GraphQL、我曾工作的 Temporal 以及 React 都有这类问题。好奇你们在脸书时有没有解决过 N 乘以 N 的问题?

David:某种程度上确实如此。这是个很好的例子。我在版本控制系统等方面处理过很多这类问题。就是把问题都整合到一个大家能读写的东西里,构建“万能盒子”来解决。在开发者工具领域,这类问题随处可见。

swyx(主持人):有趣的是,构建“万能盒子”的人都会面临同样问题,也就是可组合性、远程与本地问题等。Justin 提到的功能呈现问题,有些本质相同的东西,却要明确概念让它的呈现方式不同。

二、MCP 的核心概念:工具、资源与提示缺一不可

swyx(主持人):看 MCP 文档时我就有这个疑问,为什么这两个东西要有区别呢?很多人将工具调用当成万能解法,实际上不同类型的工具调用意义不同,有时是资源,有时是执行操作,有时是其他用途。我想了解你们将哪些概念归为相近类别?为什么强调它们的重要? 

Justin:我们从应用开发者角度思考每个基本概念。开发应用时,不管是 IDE、Claude Desktop 或 Agent 界面,从用户的角度想要从集成中获取的功能,就会清晰很多,同时,工具调用是必要的,还要区分不同功能。

所以,MCP 最初的核心基本概念,后来又有所增加:

  • 工具(Tool):是核心。即直接给模型添加工具,让模型自行决定什么时候调用。对应用开发者而言,这类似“函数调用”,只是由模型发起的。

  • 资源(Resource):基本上指可添加到模型上下文的数据或背景信息,可由应用程序控制。例如:可能希望模型自动搜索并找到相关资源,进而将它们纳入上下文;也可能希望在应用程序中设置一个明确的用户界面功能,让用户通过下拉菜单、回形针式菜单等方式,使其成为发送给 LLM 信息的一部分,这些都是资源的应用场景。

  • 提示(Prompt):特意设计为由用户发起或由用户替换的文本或消息。打个比方,如果处于编辑器环境中,就如同斜杠命令,或者类似自动补全功能,比如有一个宏想要直接插入使用。

通过 MCP,我们对这些内容的不同呈现方式有自己的见解,但最终还是由应用开发者来决定。作为应用开发者,能得到这些以不同方式表达的概念很有用,可以根据这些确定合适的体验方式,形成差异化。从应用开发者的角度考虑,他们不想让应用千篇一律,在连接开放集成生态系统时,需要独特做法来创造最佳体验。

我觉得有两个方面:第一个方面是,目前工具调用在集成中占比超 95%,我期望更多客户端运用资源调用、提示调用。第一个实现的是提示功能,很实用,能构建可回溯的 MCP 服务器,这是用户驱动的交互,由用户决定信息导入时机,优于等待模型处理。同时希望更多 MCP 服务器用提示展示工具用法。

另一方面就是资源部分也很有潜力,设想一个 MCP 服务器公开文档、数据库等资源,客户端围绕这些构建一个完整的索引。因为资源内容丰富,不是由模型驱动公开,因为你可能拥有比在上下文窗口中实际可用的多得多的资源内容。期待未来几个月,应用程序能更好利用这些基本概念,打造更丰富的体验。

Alessio(主持人):拿着锤子,就想把所有东西都当成钉子,用工具调用解决一切问题。比如很多人用它进行数据库查询,而不是资源调用。我好奇在有 API 接口(如数据库)的情况下,使用工具和资源各有哪些优缺点?什么时候该用工具做 SQL 查询?什么时候该用资源处理数据?

Justin:我们区分工具与资源的方式是:工具由模型发起调用,由模型自行判断找到合适的工具并应用,如果想让 LLM 能运行 SQL 查询,把它设为工具合理。

资源使用更灵活,不过目前因为很多客户端不支持,情况很复杂。理想状态下,对于数据库表架构等内容,可以通过资源调用。用户能借这个告知应用相关信息开启对话,或者让 AI 应用自动查找资源。只要有列出实体并读取的需求,把它建模为资源就合理。资源通过 URI 唯一标识,可视为通用转换器,例如用 MCP 服务器解读用户输入的 URI。以 Zed 编辑器为例,它有一个提示库和 MCP 服务器交互填充提示,双方需就 URI 及数据格式达成一致,这是资源应用的很酷的交叉示例。

再回到应用开发者的角度,思考需求,把这种思路应用到实际中,比如,看看现有的应用功能,如果采用这种方式,哪些功能可以分离出来,由 MCP 服务器实现。基本上,任何有附件菜单的 IDE,自然都可以建模为资源。只是这些实现方式已经存在。

swyx(主持人): 是的,我在 Claude Desktop 中看到@符号时,立刻想到了这和 Cursor 的功能是一样的,现在其他用户也可以利用这个功能了。这个设计目标很棒,因为功能本身已经存在,人们可以很容易地理解并使用。我展示了那张图表,你们肯定也认同它的价值,我认为它非常有帮助,应该放在文档首页,这是一个很好的建议。

Justin: 你愿意为此提交一个 PR(Pull Request)吗?我们非常喜欢这个建议。

swyx(主持人): 好的,我去提交。

作为一名开发者关系人员,我一直致力于为人们提供清晰的指引,比如先列出关键要点,然后再花两小时进行详细讲解。所以,用一张图来涵盖核心内容非常有帮助。我很欣赏你们对提示(Prompt)的重视。在 ChatGPT 和 Claude 发展的早期,很多人尝试创建类似 GitHub 上的提示库、提示管理器库,但最终都没有真正流行起来。

确实,在这个领域需要更多的创新。人们期望提示具有动态性,而你们提供了这种可能性。我非常认可你们提到的多步骤提示(multi-step prompt)概念,这说明有时为了让模型正常运行,需要采取多步骤的提示方式或是突破一些限制。提示不仅仅是单次的对话输入,有时它是一连串的对话过程。

swyx(主持人):我觉得这正是资源和工具概念存在一定融合的地方,因为你现在提到有时需要一定程度的用户控制或应用程序控制,而在其他时候又希望由模型来控制。所以,现在我们是否只是在选择工具的一个子集?

David: 是的,我认为这是一个合理的担忧。归根结底,这是 MCP 的一个核心设计原则,即工具这个概念实际上不仅仅是工具本身,它与客户端应用程序息息相关,进而也与用户紧密相连。通过 MCP 的操作,用户应该拥有完全的控制权。我们说工具由模型控制,指的是仅仅由模型来调用,而不是由用户主动指定使用某个工具(当然,出于提示目的的情况除外,但这不应该作为常规的用户界面功能)。

但我认为,客户端应用程序或用户决定对 MCP 服务器提供的内容进行筛选和优化是完全合理的,例如客户端应用可以从 MCP 服务器获取工具描述并进行优化展示。在 MCP 的范式下,客户端应用应该拥有完全的控制权。此外,我们还有一个初步的想法:在协议中添加功能,允许服务器开发者对提示、资源和工具这些基本元素进行逻辑分组。这些分组可以被视为不同的 MCP 服务器,然后由用户根据自己的需求将它们组合起来使用。

三、MCP 与 OpenAPI:竞争还是互补?

swyx(主持人): 想谈谈 MCP 与开放 API(Open API)的对比,毕竟这显然是大家非常关注的问题之一。

Justin/David: 从根本上讲,开放 API 规范是一个非常强大的工具,我在开发 API 及其客户端时经常使用。但是,对于大型语言模型(LLM)的应用场景而言,开放 API 规范显得过于细化,它没有充分体现更高级别的、针对 AI 的特定概念,比如我们刚才提到的 MCP 基本概念以及应用开发者的思维模式。与仅仅提供一个 REST API 让模型去自由发挥相比,模型能够从专门为其设计的工具、资源、提示以及其他基本概念中获得更多益处。

另一方面,在设计 MCP 协议时,我们刻意使其具有一定的状态性。这是因为 AI 应用和交互在本质上更倾向于 Statefulness(有状态)。尽管 Stateless(无状态) 在一定程度上始终有其用武之地,但随着交互模式(如视频、音频等)的不断增加,Statefulness 会变得越来越受欢迎,因此,Statefulness 的协议也显得尤为有用。

实际上,开放 API 和 MCP 并非相互对立,而是相辅相成的。它们各有强大之处,而且非常互补。我认为关键在于选择最适合特定任务的工具。如果目标是实现 AI 应用之间丰富的交互,那么 MCP 就更适合;如果希望模型能够轻松读取和解释 API 规范,那么开放 API 会是更好的选择。早期已经有人在这两者之间搭建了桥梁,有一些工具可以将开放 API 规范转换为 MCP 形式进行发布,反之亦然,这很棒。

Alessio(主持人): 我在 AGI 工作室联合主持了一场黑客马拉松。作为个人 Agent 开发者,我看到有人构建了一个能够生成 MCP 服务器的个人 Agent:只需要输入 API 规范的 URL,它就可以生成对应的 MCP 服务器。你们如何看待这种现象?是不是意味着大多数 MCP 服务器仅仅是在现有 API 之上增加了一个层,而没有太多独特的设计?未来会一直是这样,主要依靠 AI 来对接已有的 API,还是会出现全新的、前所未有的 MCP 体验?

Justin/David: 我认为这两种情况都会存在。一方面,“通过连接器将数据引入应用程序”这类需求始终是有价值的。尽管目前更多的是默认使用工具调用,但未来其他的基本概念或许更适合解决这类问题。即使它仍然是一个连接器或适配器层,通过适配不同的概念也能增加其价值。

另一方面,确实有机会出现一些有趣的应用场景,构建不仅仅充当适配器的 MCP 服务器。例如,一个内存 MCP 服务器可以让 LLM 在不同的对话中记住信息;一个顺序思维 MCP 服务器可以提升模型的推理能力。这些服务器并非与外部系统集成,而是为模型提供全新的思考方式。

无论如何,利用 AI 来构建服务器是完全可行的。即使需要实现的功能并非适配其他 API,而是具有原创性,模型通常也能找到实现的途径。确实,很多 MCP 服务器将会是 API 封装器,这既合理又有效,能帮助你取得很大进展。但我们目前仍处于探索阶段,还在不断探索能够实现的可能性。

随着客户端对这些基本概念支持的不断完善,将会涌现出丰富的体验。例如,一个能够“总结 Reddit 版块内容”的 MCP 服务器,目前还没有人构建,但协议本身完全能够实现。我认为,当人们的需求从“我只是想把我关心的事物连接到 LLM 上”转变为“我想要一个真正的工作流程,一个真正更丰富、我希望模型能够深入互动的体验”时,你就会看到这些创新应用应运而生。不过,目前在客户端支持的能力与服务器开发者想要实现的功能之间,确实存在着一个“先有鸡还是先有蛋”的问题。

四、怎么快速构建 MCP 服务器:用 AI 编程

Alessio(主持人): 我觉得 MCP 还有一个方面人们讨论得相对较少,那就是服务器的构建。对于那些想要开始构建 MCP 服务器的开发者,你们有什么建议吗?作为服务器开发者,如何在提供详细描述(让模型理解)与直接获取原始数据(留给模型后续自动处理)之间找到一个最佳平衡点?

Justin/David: 我有一些建议。MCP 的一个优点在于,构建一些简单的功能非常容易,大约半小时就能搭建好,虽然可能不完美,但足以满足基本需求。最好的入门方法是:选择你喜欢的编程语言,如果有相应的 SDK 就直接使用;构建一个你希望模型能与之交互的工具;搭建 MCP 服务器;将这个工具添加到服务器中;简单地编写一下工具的描述;通过标准输入输出协议将其连接到你喜欢的应用程序;然后观察模型能够如何使用它。

对于开发者来说,能够快速看到模型作用于他们所关注的事物上,这一点非常有吸引力,能够激发他们的热情,进而促使他们深入思考还需要哪些工具、资源和提示,以及如何评估效果并优化提示。这是一个可以不断深入探索的过程,但首先从简单的事情入手,看看模型如何与你关心的内容进行交互,这本身就充满了乐趣。MCP 为开发增添了趣味性,能够让模型快速发挥作用。

我还倾向于利用 AI 辅助编码。在开发初期,我们就发现可以将 MCP SDK 的代码片段放入 LLM 的上下文窗口,让 LLM 帮助构建服务器,结果往往很不错,细节可以在后期进一步优化。这是一种快速实现基本功能并进行迭代的好方法。从一开始,我们就非常注重简化服务器的构建流程,以便于 LLM 能够参与进来。在过去几年里,启动一个 MCP 服务器可能只需要 100 到 200 行代码,确实非常简单。如果没有现成的 SDK,你也可以将相关的规范或其他 SDK 提供给模型,让它帮助你构建部分功能。在喜欢的语言中进行工具调用通常也非常直接。

Alessio(主持人):我发现,服务器构建者在很大程度上决定了最终返回的数据格式和内容。比如在工具调用的例子中,像 Google Maps,返回哪些属性是由构建者决定的。如果缺少某种属性,用户就无法覆盖或修改它。这和我对一些 SDK 的不满之处类似:当人们构建 API 封装的 SDK 时,如果他们遗漏了 API 新增的参数,我就无法使用这些新功能。你们如何看待这个问题?用户应该拥有多大的干预能力,还是完全由服务器设计者来决定?

Justin/David: 关于 Google Maps 的例子,我们或许有一定的责任,因为它是我们发布的一个参考服务器。一般来说,至少目前,对于工具调用的结果,我们有意设计它不一定是结构化的 JSON 数据,也不一定需要匹配特定的模式,而是以文本、图像这类可以直接输入 LLM 的消息形式呈现。也就是说,我们倾向于返回大量的数据,并相信 LLM 能够从中筛选并提取它所关心的信息。我们在这方面做了很多努力,旨在让模型能够灵活地获取所需信息,因为这正是它的强项。我们思考的是如何充分发挥 LLM 的潜力,而不是过度地限制或指定,从而避免随着模型的改进而变得难以扩展。因此,在示例服务器中,理想的状态是所有结果类型都能直接从被调用的 API 原封不动地传递过来,由 API 自动传递数据。

Alessio(主持人): 在哪里划定这个界限确实是一个很难作出的决定。

David:这里我可能需要稍微强调一下 AI 在其中的作用。很多示例服务器是由 Claude 编写的,这一点并不令人意外。目前,人们往往习惯于用传统的软件工程方法来处理问题,但实际上我们需要重新学习如何为 LLM 构建系统并信任它们的能力。随着 LLM 每年都取得显著的进步,现在将处理数据的任务交给擅长此道的模型是一个明智的选择。这意味着我们可能需要放下过去二三十年、甚至四十年的传统软件工程实践经验。

从另一个角度来看 MCP,AI 的发展速度令人惊叹,既令人兴奋又带着一丝担忧。对于模型下一波能力的提升,最大的瓶颈可能在于与外部世界交互的能力,比如读取外部数据源、采取 Statefulness 的行动。在 Anthropic 工作时,我们非常重视安全的交互,并采取了相应的控制和校准措施。随着 AI 的发展,人们会期望模型具备这些能力,而将模型与外部连接是提升 AI 生产力的关键。MCP 也正是我们对未来发展方向及其重要性的一种押注。

Alessio(主持人): 说得对,我觉得任何带有“格式化”(formatted)字样的 API 属性都应该被移除。我们应该从所有接口获取原始数据。为什么需要预先格式化呢?模型肯定足够智能,能够自己对地址等信息进行格式化。所以这部分应该由终端用户来决定。

五、怎么让 MCP 更好调用更多工具?

swyx(主持人): 我还想问一个问题,一个 MCP 实现能够支持多少个相关功能?这涉及到广度与深度的问题,也与我们刚才讨论的 MCP 嵌套直接相关。

2024 年 4 月 Claude 推出首个百万 token 上下文示例时,曾表示能够支持 250 个工具,但在很多实际情况下,模型并不能真正有效地使用这么多工具。从某种意义上说,这是一个广度问题,因为没有工具调用工具的情况,只有模型和一层平铺的工具层级结构,这样很容易出现工具混淆。当工具的功能相似时,模型就可能调用错误的工具,导致结果不理想。对于在任何特定时间启用的 MCP 服务器的最大数量,你们有什么建议吗?

Justin: 坦白说,这个问题没有一个绝对的答案。一方面取决于你使用的模型,另一方面取决于工具的命名和描述是否足够清晰,能够让模型准确理解,避免混淆。理想的状态是将所有信息提供给 LLM,完全由它来处理一切,这也是 MCP 所设想的未来蓝图。但在现实应用中,客户端应用程序(即 AI 应用)可能需要做一些补充工作,比如筛选工具集,或者利用一个小型且快速的 LLM 先筛选出最相关的工具,然后再传递给大型模型。此外,也可以通过将一些 MCP 服务器设置为其他 MCP 服务器的代理来进行筛选。

至少对于 Claude 来说,支持数百个工具是比较稳妥的。不过对于其他模型的情况,目前还不清楚。随着时间的推移,情况应该会越来越好,所以对待限制需要保持谨慎,以免阻碍这种发展。能够支持的工具数量在很大程度上取决于描述的重叠程度。如果服务器的功能各不相同,工具名称和描述清晰且独特,那么能够支持的工具数量可能就会多于存在相似功能服务器(比如同时连接 GitLab 和 GitHub 服务器)的情况。

此外,这也与 AI 应用的类型有关。在构建高度智能化的应用时,你可能会减少向用户提问以及界面的可配置性;但在构建像 IDE 或聊天应用这样的程序时,允许用户在不同的时刻选择他们想要的功能集,而不是始终启用全部功能,这是完全合理的。

swyx(主持人): 最后,我们重点谈谈顺序思维服务器(Sequential Thinking MCP Server)。它具备分支功能,还能提供“更多编写空间”的能力,这些都非常有趣。另外,Anthropic 上周发布了一篇新的工程博客,介绍了他们的思考工具(Thinking Tool),社区对于顺序思维服务器和这个思考工具之间是否存在重叠产生了一些疑惑。实际上,这只是不同团队以不同的方式在做类似的事情,毕竟实现方法多种多样。

Justin/David: 据我所知,顺序思维服务器与 Anthropic 的思考工具没有直接的共同渊源。但这确实反映了一个普遍现象:为了让 LLM 进行更周全的思考、减少幻觉或达成其他目标,存在着许多不同的策略,可以从多个维度更全面、更可靠地展现效果。这正是 MCP 的强大之处——你可以构建不同的服务器,或者在同一个服务器中设置不同的产品或工具来实现多样化的功能,让 LLM 应用特定的思维模式来获得不同的结果。

所以,并不存在一种理想的、规定好的 LLM 思考方式。

swyx(主持人): 我认为不同的应用会有不同的用途,而 MCP 正是允许你实现这种多样化,对吗?

Justin/David: 没错。我觉得一些 MCP 服务器所采用的方法,恰恰填补了模型在当时自身能力上的空白。模型训练、准备和研究需要耗费大量时间,才能逐步提升其能力。就拿顺序思维服务器来说,它看起来可能很简单,但实际上并非如此,而且它可以在短短几天内搭建好。然而,如果想在模型内部直接实现这种复杂的思考功能,那绝不是几天就能完成的事情。

打个比方,如果我使用的模型不太可靠,或者有人觉得当前模型生成的结果整体上不够可靠,我可以设想构建一个 MCP 服务器,让模型针对一个查询尝试生成三次结果,然后再从中挑出最佳的一个。借助 MCP,就能够实现这种递归且可组合的 LLM 交互方式。

六、复杂的 MCP 和 Agent 有什么区别?

Alessio(主持人): 我接下来想问关于可组合性的问题。你们怎么看待将一个 MCP 引入另一个 MCP 的概念?对此有什么相关计划吗?比如,如果我想构建一个用于总结 Reddit 版块内容的 MCP,这可能需要调用一个对应 Reddit API 的 MCP,以及一个提供总结功能的 MCP。那么,我该如何构建这样一个“超级 MCP”呢?

Justin/David: 这是一个非常有意思的话题,可以从两个方面来看。

一方面,考虑构建像总结功能这样的组件。虽然它可能会调用 LLM,但我们希望它能够保持与具体的模型无关。这就涉及到了 MCP 的双向通信功能。以 Cursor 为例,它管理着与 LLM 的交互循环。服务器开发者可以通过 Cursor 向客户端(即用户所在的应用程序)请求执行某些任务,比如让客户端使用用户当前选择的模型进行总结,并将结果返回。这样,总结模型的选择就取决于 Cursor,而开发者无需在服务器端引入额外的 SDK 或 API 密钥,从而实现了与具体模型无关的构建。

另一方面,利用 MCP 构建更复杂的系统是完全可能的。你可以设想一个 MCP 服务器,它为 Cursor 或 Windsurf 这样的服务提供支持,同时这个服务器自身也作为一个 MCP 客户端,调用其他的 MCP 服务器来创造更丰富的体验。这体现了一种递归特性,在规范的授权等方面也体现了这种模式。你可以将这些既是服务器又是客户端的应用程序串联起来,甚至利用 MCP 服务器构建有 DAG (Directed Acyclic Graph)来实现复杂的交互流程。智能的 MCP 服务器甚至可以利用整个 MCP 服务器生态系统的能力。对此,人们已经做过相关的实验。如果再考虑到自动选择、安装等功能,还有很多可以实现的可能性。

目前,我们的 SDK 还需要添加更多细节,以便开发者能够更轻松地构建既是客户端又是递归 MCP 服务器的应用,或者更方便地复用多个 MCP 服务器的行为。这些是未来有待完善的内容,但它们已经可以展示一些目前虽然可行但尚未被广泛采纳的应用场景。

swyx(主持人): 这听起来非常令人兴奋,我相信很多人会从中获得很多想法和灵感。那么,这种既是服务器又是客户端的 MCP,可以算作是一种 Agent 吗?从某种程度上说,Agent 是你发出一个请求,它会去执行一些你可能不完全清楚的底层操作。在你和最终的原始数据来源之间存在一层抽象。你们对于 Agent 有什么独到的见解吗?

Justin/David: 我认为通过 MCP 的方式确实可以构建一个 Agent。这里需要区分的是,仅仅作为一个 Agent 的 MCP 服务器加上客户端,与一个真正的 Agent 之间的区别。例如,在一个 MCP 服务器内部,可以借助客户端提供的 sample loop(示例循环)来丰富体验,并让模型调用工具,这样来构建一个真正的 Agent,这种构建方式相对直接。

在 MCP 与 Agent 的关系方面,我们有几种不同的思考方向:

其一,MCP 可能是一种很好的方式来表达 Agent 的能力,但也许目前还缺少一些能够提升用户交互体验的特性或功能,这些应该被考虑纳入到 MCP 协议中。

其二,可以将 MCP 作为构建 Agent,或者让不同 Agent 之间相互组合的基础通信层。 当然,也存在其他可能性,比如认为 MCP 更应该专注于 AI 应用层面的集成,而不是过多地关注 Agent 的概念本身。 这仍然是一个正在探讨中的问题,每个方向都有其权衡之处。回到之前关于“万能盒子”的类比,在设计协议和管理生态系统时,我们需要特别小心的一点是避免功能过于繁杂,不能让协议试图包罗万象,否则可能导致其在各个方面都表现不佳。关键的问题在于,Agent 在多大程度上能够自然地融入现有的模型和范式框架内,又或者在多大程度上它应该作为一个独立的实体存在,这仍然是一个尚未完全解决的问题。

swyx(主持人): 我认为,当实现双向通信,让客户端和服务器能够合二为一,并且可以将工作委托给其他的 MCP 服务器时,它就更像是 Agent 了。我很欣赏你们始终牢记简洁性的重要,不试图解决所有问题。

七、MCP 下一步:如何让协议更可靠?

swyx(主持人):近期关于从有状态服务器到无状态服务器的更新引起了大家的兴趣。你们选择服务器发送事件(SSE)作为发布协议和传输方式,并且支持 pluggable(可插拔,指更具灵活性)的传输层,这背后的原因是什么?是受到了 Jared Palmer 推文的影响,还是早已在筹备之中?

Justin/David:并不是,几个月前我们就在 GitHub 上公开讨论过 Statefulness 与 Stateless 相关的难题,并一直在权衡。我们认为 AI 应用、生态系统和 Agent 的未来发展方向倾向于 Statefulness。这是 MCP 核心团队内部最具争议的话题之一,经过了多次讨论和迭代。最终的结论是,尽管我们看好 Statefulness 的未来,但不能因此背离现有的范式,必须在 Statefulness 的理念和实际操作的复杂性之间找到平衡。因为如果要求 MCP 服务器保持长期持续连接,部署和运营的难度会非常大。最初的 SSE 传输设计,其基本理念是你部署一个 MCP 服务器后,客户端可以连接进来并保持近乎无限期的连接,这对任何需要进行大规模运营的人来说,都是一个很高的要求,不是一个理想的部署或运营模式。

因此,我们思考如何平衡 Statefulness 的重要性与操作维护的简便性。我们推出的可流式传输的 HTTP 传输方式,包括 SSE,其设计思路是循序渐进的。服务器可以是一个普通的 HTTP 服务器,通过 HTTP POST 请求获取结果。然后可以逐步增强功能,比如支持结果的流式传输,甚至允许服务器主动向客户端发出请求。只要服务器和客户端支持 Session Resumption(会话恢复,即可以在断开连接后重新连接并继续传输),就能够在兼顾 Statefulness 交互的同时,实现便捷的扩展,并能更好地应对网络不稳定等状况。

Alessio(主持人):是的,还包括会话 ID。关于未来的身份验证,你们有什么计划吗?目前,对于一些 MCP,我只需要在命令行中粘贴我的 API 密钥。你们认为未来的发展方向是什么?会不会有类似于 MCP 专属的配置文件之类的东西来管理认证信息?

Justin/David: 在协议的下一版修订草案中,我们已经纳入了授权(authentication)规范。目前主要关注的是用户到服务器的授权,采用的是 OAuth 2.1 或其现代子集。这种方式的效果不错,大家也正在以此为基础进行构建。这能够解决不少问题,因为你肯定不希望用户随意粘贴 API 密钥,特别是考虑到未来大多数服务器会是远程服务器,它们之间需要进行安全的授权。

在本地环境下,由于授权信息定义在传输层,这意味着需要进行数据帧封装(设置请求头),而标准的输入输出(stdin/stdout)是无法直接实现的。不过,在本地运行使用标准输入输出的程序时,操作非常灵活,甚至可以打开浏览器来处理授权流程。关于在本地是否使用 HTTP 进行授权,我们内部目前尚未完全确定,贾斯汀倾向于支持,而我个人不太赞同,存在争议。

对于授权设计,我认为和协议的其他内容一样,我们力求相当精简,解决实际痛点,功能先做到最简化,再根据实际需求和痛点逐步扩展,避免过度设计。设计协议需要非常谨慎,因为一旦犯错,基本上就无法挽回,否则会破坏向后兼容性。因此,我们只接受或添加那些经过充分考量和验证的内容,先让社区通过扩展机制进行临时尝试,直到有更广泛的共识表明某些功能确实应该添加到核心协议中,并且我们有能力在未来持续提供支持,这样做会更容易、更稳健。

以授权和 API 密钥为例,我们进行了大量头脑风暴。当前的授权方式(OAuth 2.1 子集)已经能够满足 API 密钥的使用场景。一个 MCP 服务器可以作为 OAuth 授权服务器并添加相关功能,但如果你访问其“/authorize”网页,它可能只是提供一个文本框让你输入 API 密钥。虽然这可能不是最理想的方式,但因为它确实符合现有的模式,并且在当下是可行的。我们担心如果添加过多其他选项,客户端和服务器都需要考虑和实现更多情况,反而增加了复杂性。

Alessio(主持人): 你们有没有考虑过 scopes(作用域)的概念?昨天我们和 Agent.ai 的创建人 Dharmesh Shah 做了一期节目。他举了一个关于电子邮件的例子:他拥有自己所有的电子邮件,希望能有更细粒度的 Scopes 控制,比如“你只能访问这些类型的邮件”,或者“只能访问发给这个人的邮件”。如今,大多数作用域通常是基于 REST API 设计的,即你能访问哪些特定的端点。你们认为未来模型有可能理解并利用 Scopes 层,从而动态地限制传输的数据吗?

Justin/David: 我们认识到 Scopes 存在潜在的需求,也进行过讨论,但将它添加到协议中需要非常谨慎。我们的标准是,首先要找到当前实现方式无法解决的实际问题,然后在 MCP 结构的可扩展性基础上进行原型构建,并且证明它能够带来良好的用户体验后,才会考虑将其正式纳入协议。授权(authentication)的情况有所不同,它更多是从顶层(top-down)设计的。

每次听到对 Scopes 的描述,我们都觉得很有道理,但我们需要具体的端到端用户案例来明确当前实现方式的不足之处,这样才能进一步展开讨论。考虑到可组合性和逻辑分组的设计理念,我们通常建议将 MCP 服务器设计得比较小巧,大量不同的功能最好由独立的、离散的服务器来实现,然后在应用层进行组合。也有人提出反对意见,不赞成让单个服务器承担对多个不同服务的授权任务,认为这些服务本身就应该对应各自独立的服务器,然后再在应用层面进行组合。

八、MCP 服务器分发的安全问题

Alessio(主持人): 我认为 MCP 一个很出色的设计是它的编程语言无关性。据我了解,Anthropic 没有官方的 Ruby SDK,OpenAI 也没有。尽管像 Alex Rudall 这样的开发者在构建这些工具包方面表现出色,但有了 MCP,我们不再需要为各种编程语言分别适配 SDK,只需要创建一个被 Anthropic 认可的标准接口就可以了,这一点非常棒。

swyx(主持人): 关于 MCP 的注册中心(MCP Registry),目前已经出现了五六个不同的注册中心,而且官方最初宣布的注册中心已经停止运营了。注册中心的服务模式,如提供下载量、点赞数、评价和信任机制等,很容易让人联想到传统的软件包仓库(比如 npm 或 PyPI),但这让我觉得不太可靠。因为即使有了社交证明,下一次更新也可能让一个原本受信赖的软件包面临安全威胁。这种滥用信任系统的情况,感觉就像是建立信任体系反而因为信任系统本身而遭受损害。因此,我更倾向于鼓励人们使用 MCP Inspector,因为它只需要查看通信流量,很多安全问题或许就能通过这种方式被发现并解决。你们如何看待注册中心的安全问题和供应链风险?

Justin/David: 没错,您说得完全正确。这确实是所有注册中心都可能面临的典型供应链安全问题。针对这个问题,行业内有不同的解决方案。比如,可以采取类似苹果 App Store 的模式,对软件进行严格审核,组建自动化系统和人工审核团队来完成这项工作。这确实是解决这类问题的一种方法,在某些特定的场景下是可行的。但我认为在开源生态系统中,这种模式可能不太适用,因为开源生态系统通常采用的是类似 MCP 注册中心、npm 包管理器和 PyPI(Python 包索引)这样的去中心化或社区驱动的方式。

swyx(主持人): 这些仓库本质上都面临着供应链攻击的问题。目前已经在官方代码库中发布的一些核心服务器,特别是像内存服务器、推理/思考服务器这类比较特殊的服务器。它们似乎不仅仅是简单地封装现有 API,而且使用起来可能比直接操作 API 更便捷。

以内存服务器为例,虽然市场上有一些专注于内存功能的初创公司,但使用这个 MCP 内存服务器,代码量大约只有 200 行,非常简单。当然,如果需要更复杂的扩展,可能需要采用更成熟的方案。但如果只是想快速引入内存功能,它提供了一个非常好的实现,可能就不需要依赖那些公司的产品了。对于这些非 API 封装型的特殊服务器,你们有没有什么特别的故事可以分享?

Justin/David: 其实没有太多特别的故事。很多这类服务器都源于我们之前提到的黑客马拉松。当时,人们对 MCP 的想法很感兴趣,Anthropic 内部一些想要实现内存功能或尝试相关概念的工程师,就可以借助 MCP 快速搭建出以往难以实现的原型。你不再需要成为某个领域的端到端专家,也不需要特定的资源或私有代码库,就能为你的应用或服务添加例如内存之类的功能。很多服务器就是这样诞生的。同时,我们在发布时也在考虑要展示多大范围的功能可能性。

swyx(主持人): 我完全同意。我认为这在一定程度上成就了你们发布的成功,提供了丰富的示例供人们直接复制粘贴并在此基础上进行扩展。我还想重点提一下文件系统 MCP 服务器,它提供了编辑文件的功能。我记得之前在播客中,Eric 曾展示过他出色的 bench 项目,社区对其中开源的文件编辑工具非常感兴趣。市面上有一些相关的库和方案将这种文件编辑能力视为核心知识产权,而你们直接将这个功能开源出来,这真的非常酷。

Justin/David: 文件系统服务器是我个人最喜欢的功能之一。它解决了我当时遇到的一个实际限制,我有一个业余的游戏项目,非常希望能将它与云服务以及 David 之前提到的“工件(artifacts)”关联起来。而能够让云服务与本地机器进行交互,这一点意义非常重大,我非常喜欢这个功能。

这是一个典型的例子,这个服务器的诞生源于我们在创建 MCP 过程中遇到的挫折以及对这种功能的需求。从遭遇问题,到开发出 MCP 和这个服务器,有着清晰直接的演进脉络,Justin 对此尤其有感触。所以,它在我们心中占有特殊的地位,可以被视为这个协议的一种精神起源点。

九、MCP 现在已经是多家公司参与的大型项目了

swyx(主持人): 关于 MCP 的讨论非常热烈。如果人们想参与这些辩论和讨论,应该通过什么渠道呢?是直接在规范的代码库讨论页面上吗?

Justin/David: 在互联网上发表意见相对容易,但真正去付诸实践却需要付出努力。我和 Jason 都是传统的开源理念支持者,我们认为在开源项目中,实际的贡献至关重要。如果你通过实际工作,用具体的例子展示了你的成果,并且为你在软件开发工具包(SDK)中想要的扩展功能投入了精力,那么你的想法更有可能被项目采纳。如果只是停留在发表意见的层面,你的声音可能会被忽略。我们当然重视各种讨论,但考虑到有限的时间和精力,我们会优先关注那些投入了更多实际工作的人。

关于 MCP 相关的讨论和通知数量非常庞大,我们需要找到更具扩展性的架构来与社区进行互动,从而确保讨论是有价值和成效的。运营一个成功的开源项目,有时需要作出一些可能让部分人不满意的艰难决定。作为项目的维护者和管理者,必须明确项目的实际愿景,并坚定地朝着既定的方向推进,即使有人不认同也没有关系,因为总可能存在更适合他们理念的项目。

以 MCP 为例,它只是解决通用领域相关问题的众多方案之一。如果你不认可核心维护者所选择的方向,开源的优势就在于你有更多的选择,你可以选择“fork”项目。我们确实期望获得社区反馈,也努力让反馈机制更具扩展性,但同时我们也会凭直觉作出我们认为正确的抉择。这可能会在开源讨论中引发很多争议,但这有时也是这类开源项目,尤其是在快速发展领域项目的本质所在。

swyx(主持人): 幸运的是,你们对于作出艰难决定似乎并不陌生。Facebook 的开源项目提供了不少经验可以借鉴,即使没有直接参与,也能了解参与者的做法。我深度参与了 React 的生态系统,之前成立了一个工作小组,讨论过程是公开的。工作小组的每个成员都有发言权,而且都是有实际工作和重要贡献的人,这种模式在一段时间内很有帮助。关于 GraphQL,它的发展轨迹和早期热度与现在的 MCP 有些相似。我经历了 GraphQL 的发展过程,最终 Facebook 将其捐赠给了开源基金会。

这引出了一个问题:MCP 是否也应该这样做?这个问题并非简单的“是”或“否”,其中存在权衡。目前大多数人对 Anthropic 在 MCP 上的工作是满意的,毕竟是你们创造并管理着它。但当项目发展到一定规模时,可能会遇到瓶颈,意识到这是一个由公司主导的项目。人们最终会期望真正的开放标准由非营利组织来推动,具备多方利益相关者和良好的治理流程,例如由 Linux 基金会或 Apache 基金会管理的那些项目。我知道现在讨论这个问题可能为时尚早,但想听听你们对此的看法?

Justin/David: 开源领域的治理确实是一个有趣且复杂的问题。一方面,我们全力致力于将 MCP 打造成一个开放标准、开放协议和开放项目,欢迎所有有兴趣的人参与进来。目前进展顺利,例如可流式传输 HTTP 的很多想法就来自于 Shopify 等不同的公司,这种跨公司的合作非常有效。但我们确实担心官方标准化,尤其是通过传统的标准化机构或相关流程,在 AI 这样快速发展的领域,这些流程可能会显著拖慢项目的发展速度。因此,我们需要找到一个平衡点:如何在保持现有各方积极参与和贡献的同时,解决他们在治理模式方面可能存在的顾虑或问题,找到正确的未来方向,而无需经历反复的组织架构变动。

我们真心希望 MCP 是一个真正的开放项目。虽然它由 Anthropic 发起,并且我和 David 都在 Anthropic 工作,但我们不希望它仅仅被视为“Anthropic 的协议”。我们希望各个 AI 实验室和公司都能参与进来或者利用它。这非常有挑战性,需要努力平衡各方利益,避免陷入“委员会决策导致项目停滞”的困境。开源领域存在多种成功的管理模式,我认为其中大部分微妙之处都围绕着企业的赞助和企业在决策过程中的话语权。我们会妥善应对这些相关问题,我们绝对希望 MCP 最终成为一个真正的社区项目。

实际上,目前已经有很多非 Anthropic 的员工拥有 MCP 代码的提交和管理权限。例如,Pydantic 团队对 Python SDK 拥有提交权限;Block 等公司对规范作出了诸多贡献;Java、C#、Kotlin 等语言的 SDK 分别由 Microsoft、JetBrains、Spring AI 等不同的公司负责完成,并且这些团队拥有完全的管理权限。所以,如果你仔细观察,它实际上已经是一个由多家公司共同参与的大型项目,很多人都在其中贡献力量,不仅仅是我们两个人对项目拥有提交权限和相关权利。

Alessio(主持人): 对于未来的 MCP 服务器或客户端,你们有什么特别的“愿望清单”吗?有没有哪些你们特别希望人们能够构建,但目前还没有实现的功能?

Justin/David: 我希望看到更多 Support for Sampling 的客户端。我也希望有人能构建一些特定的服务器,比如能够总结 Reddit 讨论线程内容的服务器,或者获取《星战前夜:晨曦》(EVE Online)上周动态的服务器。我特别希望前者(采样客户端)能够与模型无关——并不是说我不想用除了 Claude 之外的其他模型(因为目前 Claude 是最好的),而是纯粹希望有一个 Support for Sampling 的客户端框架。

更广泛地说,如果能有更多支持完整 MCP 规范的客户端就更好了。我们在设计时考虑了逐步采用的可能性,如果这些精心设计的基本概念能够得到广泛应用,那将非常棒。回想我最初参与 MCP 工作的动机,以及对文件系统服务器的兴奋点——

我在业余时间是一名游戏开发者,所以我非常希望能够看到一个与 Godot 引擎集成的 MCP 客户端或服务器(我当时就是用 Godot 引擎开发游戏)。这样一来,将 AI 集成到游戏中就会变得非常轻松,或者能够让 Claude 来运行和测试我的游戏。比如说,让 Claude 玩《宝可梦》游戏。现在已经有实现这个想法的基础了。再进一步,从现在开始,让 Claude 使用 Blender 为你构建 3D 模型,怎么样?

swyx(主持人): 坦白说,甚至像着色器代码(shader code)之类的东西理论上都可以实现。这确实已经超出了我的专业领域了。但当你给予开发者们支持和工具后,他们能做到的事情真的非常惊人。我们正和 David Hersh 一起筹备一场“Claude 玩《宝可梦》”的黑客马拉松。本来我并没有将 MCP 融入其中的计划,但现在看来或许可以考虑了。

本文来自微信公众号:Founder Park,作者:Founder Park

  • Related Posts

    高通杀进英伟达腹地:不造芯片,造“电厂”

    为什么世界上所有人都盯着英伟达呢?

    一个视频看懂四中全会:十五五规划都讲了哪些事?

    这些领域变化值得持续关注!

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注

    bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak bokep anak
    xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn xnxx porn