万字长文,带你读懂Anthropic MCP
背景
- 原始时代——prompt转json。大家现在回头看看写在代码里面的prompt是否还有大量的提示词转结构化数据的要求。优点就是可以很快的事项让大模型给出符合格式的结果。缺陷也是很大,就是不可靠。常遇到的比如json的key错误,json格式不对,时间格式不匹配。
- 农耕时代——Plugins。2023年3月份,OpenAI 官方发布了重磅的「ChatGPT plugins」。也是大模型首次允许通过插件与外部应用交互的能力,也给了AI应用很大的想象。比如当前大模型都具备的实时信息检索,也是这个时候引入的。
- 铁器时代——Function Calling。2023年6月,OpenAI在GPT-3.5和GPT-4模型中首次引入Function Calling机制,赋予模型调用外部函数的能力,使其能够结合真实的数据或计算结果,而非单纯依赖模型自身的推理能力,这样不仅可以提高模型的可控性和准确性,还能让其更适应实际业务需求。Function Calling的意义在于让大模型结果闭环且可控,在大模型流程中加入函数能力,让其获取到外部数据,不必再自行幻想出来结果,并且结构化的输入给到大模型,输出的结果更加稳定。
- 蒸汽时代——Agent框架 Tools。Agent可以根据任务动态选择Tool是完成任务,所以Tool应该是大模型能力的补充。
- 电气时代——MCP。在上一时代中的Agent的Tool诞生可以补充大模型的缺失的能力和数据,但是还需要一个大问题,一个企业或者应用面对不同的大模型不同的系统如何快速集成到一起,一个个是开发Tools?这是一个重复且繁琐的工作。为此本文的主角——MCP协议诞生了。
MCP是什么?
- Function Calling是大模型与外部数字世界的交互方式。MCP是MCP host(chatbot或者AI工具)与外部工具/资源之间的交互方式。
- MCP比Plugins规范性更好,定义了清晰的数据格式、传输协议、身份验证方法等,能力也更强。
- GPTs是OpenAI的应用市场,主要是给人使用的。MCP server主要是给AI使用的,不直接给人用。
- MCP与Agent是合作关系,彼此有对应的关系:
Agent能力 | MCP特性 |
工具(技能)调用 | Tool |
LUI 交互 | Prompt |
感知 | Resource(Changed Notification) |
深度思考 | Resource(Listing/Reading Resources) |
- MCP的出现可以解决大模型的数据和能力补充问题,大模型的训练是在大量的数据上训练出来的,这些知识是过去的,也可能是不完整的,比如今天的天气数据,我们团队刚刚写出来的产品报告,需要帮助我在饿了么订外卖等。这些数据和能力是大模型不具备的。有了MCP后大模型就可以获取到最新的数据,拥有更多的能力补充,可以极大的降低幻觉,让AI更加可靠。
- MCP是通用的AI模型集成方法。上面的图已经说明了,没有MCP时候,AI模型访问多个系统意味着要处理大量的应用编程接口、软件开发工具包和身份验证方法。而且服务之间的连接会随着功能的增加出现指数式增长,必然会导致系统脆弱。MCP用一个标准接口取代了这种复杂性,大大简化了开发。
- MCP不绑定任何厂商。Anthropic开源了MCP规范,并由社区驱动。当前与AI模型是一致的,开放性才是不断增长的系统,大家一起努力才可以把生态构建出来。
MCP可以做什么?
场景一 AI模型治理与合规管理
场景二 实时上下文增强与知识更新
场景三 工具生态扩展与系统互联
场景四 企业级智能助手与Agent构建
MCP有什么?
组件
- MCP Hosts: 负责接收用户提问并与 AI 模型交互,充当容器和协调者:
- 创建和管理多个客户端实例
- 控制客户端连接权限和生命周期
- 协调 AI/LLM 集成和采样
- 管理Clients之间的上下文聚合
-
- MCP Clients:与服务器保持 1:1 连接的协议客户端,将Server连接到的客户端中,组成不同功能的应用:
- 和每个 server 建立一个有状态的会话
- 处理协议协商和能力交换
- 双向路由协议消息
- 管理订阅和通知
- 维护 servers 之间的安全边界
-
- MCP Servers: 轻量级程序,每个程序都通过标准化模型上下文协议公开特定功能:
- 通过 MCP 原语暴露resources、tools 和prompts
- 通过client 提供的接口请求sampling
- 可以是本地进程或远程服务
- 具备特定的功能
-
协议
- 协议层处理消息框架、请求/响应链接和高级通信模式。具备有状态的连接和能力协商。
- 传输层处理客户端和服务器之间的实际通信, MCP所有传输均使用 JSON-RPC 2.0 来交换消息。
- 消息类型定义请求和响应格式和处理机制。
传输层
通信传输机制 | 部署方式 | 网络要求 | 场景 | 应用 | |
Stdio transport 标准传输 | 本地子进程 | 无需网络 |
| filesystem | |
HTTP with SSE transport 带有 SSE 传输的 HTTP | 独立服务器进程 | 需要网络连接 |
| search | |
消息类型
消息类型 | 描述 | 约束 |
Requests | 用于具体操作的消息 |
|
Responses | 请求的响应 |
|
Notifications | 单向消息,不需要回复 | 不得包含 ID |
Requests
{ jsonrpc: "2.0"; id: string | number; method: string; params?: { [key: string]: unknown; }; }
- 彻底验证输入,验证 JSON-RPC 格式
- 使用类型安全架构
- 妥善处理错误
- 实施超时处置
Responses
{ jsonrpc: "2.0"; id: string | number; result?: { [key: string]: unknown; } error?: { code: number; message: string; data?: unknown; } }
{ uri: string; // Unique identifier for the resource name: string; // Human-readable name description?: string; // Optional description mimeType?: string; // Optional MIME type }
机制类型 | 机制描述 | 应用场景 | 核心特点 |
资源列表变更通知 | 服务器通过notifications/resources/list_changed通知客户端资源列表结构性变化 | 目录结构变动、新增资源类型等全局性更新 |
|
资源内容实时订阅 | 客户端通过resources/subscribe订阅资源,服务器通过notifications/resources/updated推送变更 | 日志文件追加、API数据刷新等动态内容更新 |
|
Streamable HTTP传输 | 新增流式传输协议,支持断点续传、无状态服务器及动态SSE升级 | 高并发场景、云平台部署、需要兼容CDN/API网关的场景 |
|
- 对长时间操作使用进度标记,可逐步报告进度
- 使用适当的错误代码,包含有用的错误消息和发生错误时清理资源
- 不要泄露敏感信息并记录与安全相关的错误
Notifications
{ jsonrpc: "2.0"; method: string; params?: { [key: string]: unknown; }; }
案例
初始化会话:initialized
{ "jsonrpc": "2.0", "id": 12, "method": "initialize", "params": { "protocolVersion": "1.0", "capabilities": { "roots": { "listChanged": true } }, "clientInfo": { "name": "test-client", "version": "1.0.0" } } }
{ "jsonrpc": "2.0", "id": 12, "result": { "protocolVersion": "2024-11-05", "capabilities": { "resources": { "subscribe": true, "listChanged": true }, "tools": { } }, "serverInfo": { "name": "secure-filesystem-server", "version": "0.4.1" } } }
发现可用的工具:tools/list
{ "jsonrpc": "2.0", "id": 12, "method": "tools/list", "params": { } }
{ "jsonrpc": "2.0", "id": 12, "result": { "tools": [ { "description": "Create a new directory or ensure a directory exists.", "inputSchema": { "type": "object", "properties": { "path": { "description": "Path of the directory to create", "type": "string" } }, "required": [ "path" ] }, "name": "create_directory" }, { "description": "Retrieve detailed metadata about a file or directory.", "inputSchema": { "type": "object", "properties": { "path": { "description": "Path to the file or directory", "type": "string" } }, "required": [ "path" ] }, "name": "get_file_info" }, { "description": "Returns the list of directories that this server is allowed to access.", "inputSchema": { "type": "object" }, "name": "list_allowed_directories" }, { "description": "Get a detailed listing of all files and directories in a specified path.", "inputSchema": { "type": "object", "properties": { "path": { "description": "Path of the directory to list", "type": "string" } }, "required": [ "path" ] }, "name": "list_directory" }, { "description": "Move or rename files and directories.", "inputSchema": { "type": "object", "properties": { "destination": { "description": "Destination path", "type": "string" }, "source": { "description": "Source path of the file or directory", "type": "string" } }, "required": [ "source", "destination" ] }, "name": "move_file" }, { "description": "Read the complete contents of a file from the file system.", "inputSchema": { "type": "object", "properties": { "path": { "description": "Path to the file to read", "type": "string" } }, "required": [ "path" ] }, "name": "read_file" }, { "description": "Recursively search for files and directories matching a pattern.", "inputSchema": { "type": "object", "properties": { "path": { "description": "Starting path for the search", "type": "string" }, "pattern": { "description": "Search pattern to match against file names", "type": "string" } }, "required": [ "path", "pattern" ] }, "name": "search_files" }, { "description": "Create a new file or overwrite an existing file with new content.", "inputSchema": { "type": "object", "properties": { "content": { "description": "Content to write to the file", "type": "string" }, "path": { "description": "Path where to write the file", "type": "string" } }, "required": [ "path", "content" ] }, "name": "write_file" } ] } }
发现可用的工具:tools/call
{ "jsonrpc": "2.0", "id": 12, "method": "tools/call", "params": { "name": "list_allowed_directories", "arguments": { "path": "/Users/ouerqiang/Downloads/1.txt" } } }
{ "jsonrpc": "2.0", "id": 12, "result": { "content": [ { "type": "text", "text": "Allowed directories:\n\n/Users/ouerqiang/project/gopath/src/github.com/mark3labs/mcp-filesystem-server (file:///Users/ouerqiang/project/gopath/src/github.com/mark3labs/mcp-filesystem-server)\n/Users/ouerqiang/Downloads (file:///Users/ouerqiang/Downloads)\n" } ] } }
发现可用的资源:resources/list
{ "jsonrpc": "2.0", "id": 12, "result": { "content": [ { "type": "text", "text": "Allowed directories:\n\n/Users/ouerqiang/project/gopath/src/github.com/mark3labs/mcp-filesystem-server (file:///Users/ouerqiang/project/gopath/src/github.com/mark3labs/mcp-filesystem-server)\n/Users/ouerqiang/Downloads (file:///Users/ouerqiang/Downloads)\n" } ] } }
{ "jsonrpc": "2.0", "id": 12, "resources": [ { "uri": "file://", "name": "File System", "description": "Access to files and directories on the local file system" } ] }
服务层
- Resources:客户端可以读取的类似文件的数据(例如 API 响应或文件内容)
- Tools:可由LLM调用的函数(需经用户批准)
- Prompts:预先编写的模板,帮助用户完成特定任务
客户端
- Sampling: 服务器发起的代理行为和递归交互。采样是一个强大的MCP功能,它允许服务器通过客户端请求AI模型完成,从而在保持安全性和隐私的同时实现复杂的代理行为。换句话说,Sampling把MCP Server从给AI模型提供资源的服务变成一个使用AI模型的用户。
业界MCP Client
MCP实践
- https://github.com/metoro-io/mcp-golang
- https://github.com/mark3labs/mcp-go
对比
核心功能对比
技术选型决策矩阵
总结
附录

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
三分钟掌握音频提取 | 在 Rust 中优雅地处理视频音频
前言 在多媒体开发中,从视频中提取音频是一个常见需求。比如,你可能需要分离背景音乐来单独欣赏,或者提取对白用于语音分析,甚至为视频生成字幕。无论目的如何,音频提取都是多媒体处理中的基础操作。 传统上,我们可以通过 FFmpeg 命令行工具快速实现这一功能,例如: ffmpeg -i input.mp4 -vn -acodec copy output.aac 这条命令用 -vn 禁用视频流,-acodec copy 直接拷贝音频流,简单高效。但对于 Rust 开发者来说,直接在代码中调用命令行工具可能会遇到一些麻烦,尤其是在需要深度集成或精细控制时。难道就没有更优雅的方式吗?本文将带你探索如何在 Rust 中处理音频提取,既实用又易懂,三分钟让你上手! 痛点与场景 在 Rust 项目中处理音视频时,开发者常常会遇到以下问题: 命令行调用不够灵活 通过 std::process::Command 执行 FFmpeg 命令需要启动外部进程,不仅增加了资源开销,还得手动处理错误和输出。万一路径不对或参数写错,调试起来也很头疼。 参数繁琐,学习成本高 FFmpeg 的参数多如牛毛,像 -vn、-...
- 下一篇
Spring Boot 项目 90% 存在这 15 个致命漏洞!你的代码在裸奔吗?
文章首发公众号【风象南】 Spring Boot 作为一款广泛使用的 Java 开发框架,虽然为开发者提供了诸多便利,但也并非无懈可击,其安全漏洞问题不容忽视。本文将深入探讨 Spring Boot 常见的安全漏洞类型、产生原因以及相应的解决方案,帮助开发者更好地保障应用程序的安全。 1. SQL 注入漏洞 漏洞描述: 当应用程序使用用户输入的数据来构建 SQL 查询时,如果没有进行适当的过滤或转义,攻击者就可以通过构造恶意的 SQL 语句来访问、修改甚至删除数据库中的数据。 危险指数: 💥💥💥💥💥 反面示例: @GetMapping("/users") public List<User> getUsers(@RequestParam String username) { String sql = "SELECT * FROM users WHERE username = '" + username + "'"; // ... 执行 SQL 查询 } 解决方案: 使用参数化查询:使用 JPA 或 MyBatis 等 ORM 框架,避免直接拼接 SQL 语句。 使用...
相关文章
文章评论
共有0条评论来说两句吧...