掘金 人工智能 前天 17:23
《深入浅出MCP:全面了解,只需一篇文章!》
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了AI应用层实践心得,重点关注了模型上下文协议(MCP)在Agent应用开发中的应用和未来潜力。文章回顾了AI应用层的发展历程,分析了MCP协议的核心组件,并展望了MCP与A2A协议结合带来的变革。文章还涉及了对开源MCP Server的观察,以及对现有Agent构建平台和工具的思考。

🚀 MCP协议的核心在于统一LLM与外部数据和工具的通信,解决AI模型数据孤岛问题,提供安全访问和操作数据的接口。

🛠️ MCP协议定义了工具(Tools)、资源(Resources)、提示词(Prompts)等核心组件,其中工具允许服务器暴露可执行函数,实现与外部系统的交互。

📈 MCP协议的兴起推动了Agent构建平台的快速发展,加速了插件生态的集成,使得开发者可以更容易地接入社区提供的各种服务。

💡 MCP协议目前主要被用作工具服务器,但其潜力远不止于此,结合A2A协议,将有望重构Agent应用层开发生态,实现规模化落地和商业化前景。

背景

本文分享我在AI应用层两年的实践心得,结合社区观察与个人思考的见解。欢迎交流讨论,若有不足之处,敬请指正。

五一将至,时光飞逝。恰好两年前的五一前夕,我开始了AI应用层的探索之旅。

AI领域最大的挑战莫过于其快速迭代的节奏。技术更新如此迅猛,常让人难以跟上步伐。

当初以AI结合私域知识为起点,探索应用层的各种可能,最终确立了Agent构建平台的发展路线。Agent Builder平台一做就是近两年。有趣的是,每隔一段时间回顾自己构建的Agent,总觉得设计过于复杂。我认为这正是因为模型发展速度太快,作为AI应用层开发者,若不能及时享受模型进步带来的红利,恐怕就会被时代所淘汰。

过去两年AI应用层的变化

初期阶段:知识融合与检索

工具交互时代:能力扩展

结构化Agent构建

模型能力跃升

Agent + Computer Use兴起

协议标准化

未来展望

个人观点

我很看好MCP+A2A协议重构Agent应用层开发生态的潜力。MCP协议的统一将使LLM无缝对接传统应用开发能力,而随着模型能力持续进化,A2A协议勾勒的Agent互联的蓝图能有效避免重复造轮子。这一技术融合将为Agent应用带来真正规模化的落地机会和商业化前景。

Model Context Protocol

协议简述

MCP(Model Context Protocol,模型上下文协议) ,2024年11月,由 Anthropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而无法充分发挥潜力的难题,MCP 使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口。

关于此协议介绍的文章现在已经非常多了,感兴趣的可以阅读这个[13]中文站点,我就不再此过多赘述这个协议了。

我们来讨论一些有意思的东西。在开始谈论之前,先简单介绍一下这个协议的核心组成部分,达成共识!

核心组件

MCP客户端:可以配置使用MCP服务,比如Claude、Cline、Cursor都是比较优秀的客户端,本质还是基于LLM的应用。

MCP服务端:使用MCP协议开发的服务,通过MCP协议暴露的特定能力的轻量级程序。主要可以提供的特定能力是:

a、Tool

b、Resource

c、Prompt

传输层:目前支持STDIO协议(程序在本地启动)以及SSE协议(可远程启动),通过标准[14]JSON RPC 2.0协议通信。

工具(Tools) 👉 文档

工具是模型上下文协议(MCP)中的一个强大原语,它使服务器能够向客户端暴露可执行的功能。通过工具,LLM 可以与外部系统交互、执行计算并在现实世界中采取行动。

MCP 中的工具允许服务器暴露可执行的函数,这些函数可以被客户端调用并被 LLM 用来执行操作。工具的关键特点包括:

工具的定义:

{  name: string;          // 工具的唯一标识符  description?: string;  // 人类可读的描述  inputSchema: {         // 工具参数的 JSON Schema    type: "object",    properties: { ... }  // 工具特定的参数  }}

这个目前实践下来发现有一些痛点是工具输出格式未定义。这里MCP协议开发的一些示例服务器基本上都是返回自然语言(可能认为是给模型用的上下文,所以希望都是自然语言),社区目前讨论比较热的方向是对多模态的支持以及一些实际在用工具做产品交互时,比如工具的结果要做一些额外的处理渲染等,没有固定格式很不方便。

资源(Resources) 👉 文档

向 LLM 暴露来自服务器的数据和内容,资源是模型上下文协议(MCP)中的一个核心原语,它允许服务器暴露数据和内容,这些数据和内容可以被客户端读取并用作 LLM 交互的上下文。

{  uri: string;           // 资源的唯一标识符  name: string;          // 人类可读的名称  description?: string;  // 可选的描述  mimeType?: string;     // 可选的 MIME 类型}

1、服务器通过 resources/list 端点暴露具体资源列表。

2、要读取资源,客户端需要发出带有资源 URI 的 resources/read 请求。

3、服务器可以通过 notifications/resources/list_changed 通知客户端其可用资源列表发生了变化。

客户端可以订阅特定资源的更新,具体流程如下:

    客户端发送带有资源 URI 的 resources/subscribe当资源发生变化时,服务器发送 notifications/resources/updated客户端可以使用 resources/read 获取最新内容客户端可以使用 resources/unsubscribe 取消订阅

提示词(Prompts) 👉 文档

创建可重用的提示词模板和工作流。

提示词使服务器能够定义可重用的提示词模板和工作流,客户端可以轻松地将其呈现给用户和 LLM。它们提供了一种强大的方式来标准化和共享常见的 LLM 交互。

客户端可以通过 prompts/list 端点发现可用的提示词:

要使用提示词,客户端需要发出 prompts/get 请求:

同时还支持动态提示词,以及多步骤工作流。

采样(Sampling)👉 文档

让你的服务器从 LLM 请求补全,采样是一个强大的 MCP 功能,它允许服务器通过客户端请求 LLM 补全,从而实现复杂的代理行为,同时保持安全性和隐私性。

采样流程遵循以下步骤:

    服务器向客户端发送 sampling/createMessage 请求客户端审查请求并可以修改它客户端从 LLM 采样客户端审查补全结果客户端将结果返回给服务器

目前还没解锁这块的用法~,对这部分能力见解较少。

根目录(Roots) 👉 文档

根目录是 MCP 中定义服务器可以操作边界的一个概念。它为客户端提供了一种方式来告知服务器相关资源及其位置。

就比如web应用服务端声明www-root一回事,服务端暴露能力/资源需要有一个范围。

那这个协议解决了什么问题呢?

我认为最大的价值是,大家能够达成共识,彼此开发的给LLM使用的工具能够复用,大家能主动的用MCP协议的方式开放自己的API,这样带来的好处就是避免掉很多重复工作,Agent应用开发以一个更开放的方式玩。

这里有个有意思的数据增长图,数据来源自:[15]MCP Servers。这个平台会每天从Github爬和MCP相关的仓库,并收录MCP Server。

❕注意:这个协议是2024-11-05就已经出来了。

从25年1月1日至今,Github上关于MCP的仓库增长的趋势在2月底3月初有明显的增长趋势,4月比如支付宝、高德、playwright(微软开源的浏览器开发工具)等都将自己原来的服务以MCP协议也开放出去。

3月6日凌晨,Manus头顶「全球首款通用型AI Agent产品」的称号登上舞台,与此同时,国内的MetaGPT和开源社区CAMEL-AI两个团队在很短时间里推出了开源的Manus复刻项目。MetaGPT的Open Manus在GitHub上收获了7000多颗星星,CAMEL-AI打造的OWL在智能体测试基准GAIA开源榜单上的得分为57.7%。借势Manus,两个团队各自收获了一次破圈效果。

MCP在这个时间节点出现了一次增长,截止目前github每天新公开的仓库数量仍然处于一个较高的水位,说明开发者社区还是蛮热闹的,有较多开发者愿意参与到这个生态中。

目前国内几大Agent构建平台均已经支持了MCP协议,主要支持的方式还是通过MCP协议快速的扩充插件能力生态。

1、百宝箱

2、Coze

3、阿里云百炼

4、Model Scope

那这个带来的好处是什么呢,之前开发者可能需要用不同Agent开发平台插件体系去封装调用第三方服务SDK的逻辑,而现在Agent开发平台支持MCP协议之后,作为开发者不再需要去封装API了,而是写一个MCP Client即可接入使用社区所有的MCP Server,Agent应用平台可以快速的集成入社区更多的插件以及工具提供给开发者使用。

比如我截图了扣子的插件商店和百宝箱的插件商店,是能看到有许多重复的功能的,实际背后对应的服务可能是同一种服务,比如bing搜索都是去使用搜索API,但是基于两个平台自己有不同的数据模型,对插件的定义又不太一样,背后是各自平台的开发者把这些API封装成了平台的官方插件。

而现在MCP协议出来后的玩法是第三个开发者来开发这个服务,这个开发者可能是服务提供商(bing我没找到官方的),百

宝箱和扣子只需要支持MCP协议,作为MCP客户端即可集成使用这个能力。

截图来自[16]Bing MCP

看似是厂商多了一个SDK分发渠道而已?

确实如此,但我认为这才是最大的价值。之前厂商的服务可能支持小程序开发、WEB开发等等,现在可以多出一个类别叫Agent开发,有更多角色更多人员参与进来的生态才是有个相对健康以及可持续发展的生态。

但是据我观察现在MCP协议似乎被完成了纯工具服务器了,然而工具仅仅是MCP Server核心组件之一而已,协议还有Resource、Prompt、Samping、Root、Transport组件。这部分我认为需要结合A2A协议做更深度的融合。

之前的使用姿势是封装别人服务,很少选择自己开发新的服务。

一些有意思的MCP Server开源后,如文件系统、浏览器使用等,让大家做Agent的方向发生了一些变化,多Agent协同、Computer Use等。可以把多个MCP Server部署在一个容器中,这台容器就可以直接当做一台Agent可以使用的电脑,让AI像人一样可以用电脑完成一些复杂任务。

源码解析

重点解析下Client和Server通信,以及FastMCP如何支持SSE协议通信的。

Client Session

MCP ClientSession实现,处理和MCP服务器通信问题。

主要方法:

最终都是调用send_request 

async def send_request(        self,        request: SendRequestT,        result_type: type[ReceiveResultT],    ) -> ReceiveResultT:        """        Sends a request and wait for a response. Raises an McpError if the        response contains an error.        Do not use this method to emit notifications! Use send_notification()        instead.        """        request_id = self._request_id        self._request_id = request_id + 1        response_stream, response_stream_reader = anyio.create_memory_object_stream[            JSONRPCResponse | JSONRPCError        ](1)        self._response_streams[request_id] = response_stream        self._exit_stack.push_async_callback(lambda: response_stream.aclose())        self._exit_stack.push_async_callback(lambda: response_stream_reader.aclose())        jsonrpc_request = JSONRPCRequest(            jsonrpc="2.0",            id=request_id,            **request.model_dump(by_alias=True, mode="json", exclude_none=True),        )        # TODO: Support progress callbacks        await self._write_stream.send(JSONRPCMessage(jsonrpc_request))        try:            with anyio.fail_after(                None                if self._read_timeout_seconds is None                else self._read_timeout_seconds.total_seconds()            ):                response_or_error = await response_stream_reader.receive()        except TimeoutError:            raise McpError(                ErrorData(                    code=httpx.codes.REQUEST_TIMEOUT,                    message=(                        f"Timed out while waiting for response to "                        f"{request.__class__.__name__}. Waited "                        f"{self._read_timeout_seconds} seconds."                    ),                )            )        if isinstance(response_or_error, JSONRPCError):            raise McpError(response_or_error.error)        else:            return result_type.model_validate(response_or_error.result)

这里主要解决的是客户端和MCP协议有关的操作,底层通过JSON RPC2.0进行通信。

1、客户端发起请求:

2、请求发送:

3、服务器处理:

4、响应接收:

5、响应处理:

这个流程使用了异步编程模式,通过 anyio 库处理异步操作,使用 MemoryObjectSendStream  和 MemoryObjectReceiveStream  进行消息传递,使用 RequestResponder  管理请求生命周期。整个过程是类型安全的,使用了泛型来确保类型正确性。

sse.py实现

    主要函数 sse_client
@asynccontextmanagerasync def sse_client(    url: str,    headers: dict[str, Any] | None = None,    timeout: float = 5,    sse_read_timeout: float = 60 * 5,):    # 创建内存流用于通信    read_stream_writer, read_stream = anyio.create_memory_object_stream(0)    write_stream, write_stream_reader = anyio.create_memory_object_stream(0)

2. SSE建连

async with httpx.AsyncClient(headers=headers) as client:    async with aconnect_sse(        client,        "GET",        url,        timeout=httpx.Timeout(timeout, read=sse_read_timeout),    ) as event_source:        event_source.response.raise_for_status()

3. 两个主要的异步任务

a、SSE读取器

async def sse_reader():   async for sse in event_source.aiter_sse():       match sse.event:           case "endpoint":               # 处理端点URL               endpoint_url = urljoin(url, sse.data)               task_status.started(endpoint_url)                      case "message":               # 处理服务器消息               message = types.JSONRPCMessage.model_validate_json(sse.data)               await read_stream_writer.send(message)

b、post写入器

async def post_writer(endpoint_url: str):   async for message in write_stream_reader:       # 发送客户端消息到服务器       response = await client.post(           endpoint_url,           json=message.model_dump(...)       )

通信流程:

1、服务器 -> 客户端:

2、客户端 -> 服务器:

❕实际服务端SSE的端点是通过服务端返回的,可以自定义的。

实际TypeScript SDK已经支持了[17]Streamable HTTP

官方Python源码中的玩法是SSE+HTTP的方式,其实不需要服务端暴露两个端点的,只需要一个端点,根据不同的HTTP请求方法实现不同的逻辑:

但目前如果一个MCP Server只用了工具的话,是存在一个问题,那就是MCP Server是一个有状态的Server,官方也有讨论说可以改成无状态服务器。

这是在Reddit上一个讨论的[18]帖子

MCP实战篇

MCP使用的一个DEMO

这是Claude的截图,展示了一款MCP客户端及LLM应用程序。在截图中,我安装了一个名为[19] Filesystem的MCP Server,该服务器由MCP官方仓库提供。实际上,MCP Server通过工具列表和工具的运行时环境,实现了模型与Function Call的结合,进而处理用户任务。

刚才我们已经演示了MCP是如何使用的,并且一起讨论了MCP协议核心组件,接下来我们一起来讨论一下如何使用MCP来提效自己的工作,或者构建个人的AI助手。

去哪里找MCP Server

渠道一:官方仓库收录了一些自己开发和社区的MCP Server:[20]官方仓库收录

渠道二:第三方网站,目前收录比较全的主要是下面两个网站

a、[21]mcp.so

b、[22]mcpservers.cn

在第三方网站上收录的MCP Server数量相当可观,其中mcpservers.cn已收录超过30,000个服务器,而mcp.so也收录了超过10,000个。然而,这些服务器的质量参差不齐,数据大多来源于GitHub,还有部分为无效的MCP Server。值得关注的是mcpservers.cn站点的排序逻辑,该站点通过结合GitHub仓库的多个指标数据与平台内部的数据,计算出一个综合的排序因子,这种方法接近开放、贴近社区。网站每天都会从GitHub抓取与MCP相关的仓库,并更新每个仓库的指标,从而重新计算其排序得分,保持数据的及时性与准确性。排序系统

mcp.so上有一个调用排行,数据源来自何处目前尚未公开。

⚠️安全风险提示:MCP工具可能存在投毒的可能性,例如可能会通过LLM操控工具,获取个人隐私信息上传到第三方恶意服务器中。

如何安装到本地使用

首先,你需要一个支持MCP的客户端,比较出名的,官方收录的[23]Client列表

1、Claude:claude.ai/download

2、Cursor:www.cursor.com/cn

3、Cline:cline.bot/

本文以推出了MCP协议的Anthropic公司开发的Claude为示例来演示。

1、下载:claude.ai/download

需要科学上网

2、配置MCP

配置文件格式:

{  "mcpServers": {    "filesystem": {      "command": "npx",      "args": [        "-y",        "@modelcontextprotocol/server-filesystem",        "/Users/username/Desktop",        "/path/to/other/allowed/dir"      ]    }  }}

实际上,这个MCP Server会在Claude启动时自动加载,并在本地启动一个进程,因此本地必须具备相应的运行环境,否则该功能将无法正常使用。以filesystem为例,该Server需要使用npx命令,这意味着需要提供node的运行环境来确保其正常运行。

3、Claude背后发生了什么呢?

参考官方调试文档

日志会打印在:~/Library/Logs/Claude/ 目录下。

连接生命周期如下:

客户端日志:

服务端日志:

在客户端与服务端的交互过程中,首先由客户端发起初始化请求,服务端则返回初始化响应。在这个阶段,主要传递的内容包括客户端的基本信息(如名称和描述)以及所使用的MCP协议版本。同时,服务端会返回对应的基础信息(如名称和描述)及MCP协议版本。

成功建立连接后,Claude客户端会依次请求以下资源:

其中,Tool、Resources和Prompts是MCP协议中定义的核心组件,负责不同的功能和服务。然而,目前的filesystem仅实现了tool功能。对于其他未实现的功能,服务端将返回"Method not found"错误,提示用户该方法尚不可用。

list_tool 返回了Server支持的所有工具:

在接下来的对话中,LLM会根据用户的请求通过Function Call选择合适的工具来完成用户的任务。

如何更方便的本地使用?

MCP统一管理工具,跨语言技术栈的无缝体验

目前这个工具已经开源:github.com/jinyalong/o…

MCP协议现已支持Python、Java、Go、Node.js、C#和Kotlin等多种语言实现。我们的统一命令行工具消除了技术栈壁垒,让您一键安装任何语言开发的MCP Server,无需费心配置开发环境、管理配置文件或调试客户端设置。

只需一行命令,即可将您选择的MCP Server集成到个人AI助手中。

作为专注于MCP Server管理的工具,我们巧妙利用各语言生态中成熟的包管理器(如NPM、UV、PIP)所提供的强大基础能力,让您专注于AI应用开发而非底层技术挑战。

安装Filesystem演示

安装MCP Server管理工具到本地后,只需要一行命令会自动下载好MCP Server相关的依赖配置,并管理MCP Clients的目录,同时为你自动重启MCP客户端生效新安装的MCP Server。

omcp install modelcontextprotocol@filesystem 

此外,这个工具现已支持对Cursor和Claude客户端的管理。用户只需输入一行命令,即可快速安装MCP Server,自动检测并配置客户端设置,实现MCP Server与本地MCP客户端的无缝同步。这一功能极大地简化了管理流程,提高了操作效率。

如何远程使用MCP Server呢?

例如Cursor是支持配置SSE地址的MCP Server的,有的Server需要部署在远端,同时也可以避免运行环境是在本地可能引起一些安全问题。

方法一:改造MCP Server代码

大多数MCP Server开发者在编码时均用了STDIO协议,方便用户只需要粘贴一段配置即可直接使用MCP Server,而实际上官方是支持HTTP+SSE的协议的。

我们继续以FileSystem这个为例子,源码在这里:github.com/modelcontex…

// Start serverasync function runServer() {  const transport = new StdioServerTransport();  await server.connect(transport);  console.error("Secure MCP Filesystem Server running on stdio");  console.error("Allowed directories:", allowedDirectories);}runServer().catch((error) => {  console.error("Fatal error running server:", error);  process.exit(1);});

可以看到代码中,Server最终是通过STDIO协议启动的,如何改成SSE+HTTP协议的方式呢:

import express from "express";const app = express();const server = new Server({  name: "example-server",  version: "1.0.0"}, {  capabilities: {}});let transport: SSEServerTransport | null = null;app.get("/sse", (req, res) => {  transport = new SSEServerTransport("/messages", res);  server.connect(transport);});app.post("/messages", (req, res) => {  if (transport) {    transport.handlePostMessage(req, res);  }});app.listen(3000);

现在这个Server变成了一个HTTP服务了,只需要构建镜像或者是放到一台服务器上即可启动。

这样每个Server都需要改很麻烦,有没有什么一次性的解决方案呢?

MCP Proxy -> 远程部署任何一个MCP Server

目前我已经将此功能组件开源:github.com/jinyalong/m…

当前大部分MCP Server的传输层协议是STDIO协议,而官方支持的两种协议SSE+HTTP(这个社区在推动Streamble HTTP协议代替此方案,目前TypeScript已经支持了])/STDIO。这个组件主要有以下三种使用场景:

Scene1:一键托管MCP Server,即可集成如Agent平台扩充个人插件能力。目前百炼、百宝箱均已支持,有Fass部署方案,也有容器部署方案。

Scene2:多个MCP Server配合一些软件、文件系统等可以构建一个Agent Sandbox,作为Agent可以操作的电脑。目前Coze空间已支持。

Scene3:构建MCP Server集群,主要的价值在于可以扩充LLM的API服务或者是Agent应用平台的插件生态。

总结

过去两年,AI浪潮席卷各行各业,开发者常感到这领域有着强烈的"网红效应"——新技术迅速兴起,需要紧跟学习和应用。然而,真正能持续稳定发展的AI原生应用却寥寥无几,大多如昙花一现,主要受限于模型能力的发展空间和成本问题。

在这样的背景下,Cursor凭借Agent与传统应用的有效结合,成为了业内亮眼的产品。作为深耕RAG领域的Agent应用平台开发者,MCP和A2A协议的迅速崛起启发我们重新思考平台的终极目标。传统Agent应用开发平台工作流虽能平衡模型的不确定性与确定性,却也在一定程度上限制了模型潜能的发挥。

随着模型能力不断增强,业界正转向让AI承担更多思考和行动,减少人为干预的开发理念。正如那句调侃:"有多少人工,就有多少智能"。MCP、A2A等协议的出现,可能会像互联网早期的HTTP协议一样,最终成为无处不在、不可或缺的基础设施。

展望未来,Agent应用开发有望发展成一个不亚于甚至超越传统应用开发的庞大生态,让开发者充分释放创意和想法,创造真正能融入人们日常生活的AI原生应用。

参考资料

2、arxiv.org/abs/2312.10…

3、arxiv.org/abs/2210.03…

4、python.langchain.com/docs/introd…

5、www.llama.com/

6、platform.openai.com/docs/guides…

7、www.coze.cn/

8、dify.ai/

9、doraemon.alipay.com/

10、manus.im/

11、modelcontextprotocol.io/

12、github.com/google/A2A

13、docs.mcpservers.cn/introductio…

14、www.jsonrpc.org/specificati…

15、mcpservers.cn/growth

16、github.com/leehanchung…

17、github.com/modelcontex…

18、www.reddit.com/r/modelcont…

19、github.com/modelcontex…

20、github.com/modelcontex…

21、mcp.so/

22、mcpservers.cn

23、modelcontextprotocol.io/clients

24、bailian.console.aliyun.com/

25、tbox.alipay.com/

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

MCP协议 Agent AI应用 A2A协议
相关文章