MCP (Model Context Protocol),一篇就够了。
MCP (Model Context Protocol),一篇就够了。
MCP(Model Context Protocol)是AI领域的一项重要技术标准,它定义了应用程序和AI模型之间交换上下文信息的方式。本文将从使用者的角度出发,深入浅出地介绍MCP的核心概念、应用场景和开发实践,帮助读者快速掌握这一技术。
MCP是什么?
MCP起源于2024年11月25日Anthropic发布的一篇文章。它定义了应用程序和AI模型之间交换上下文信息的方式,使得开发者能够以一致的方式将各种数据源、工具和功能连接到AI模型,就像USB-C让不同设备能够通过相同的接口连接一样。MCP的目标是创建一个通用标准,使AI应用程序的开发和集成变得更加简单和统一。
为什么需要MCP?
MCP的出现是prompt engineering发展的产物。更结构化的上下文信息对模型的性能提升是显著的。我们在构造prompt时,希望能提供一些更具体的信息(比如本地文件、数据库、一些网络实时信息等)给模型,这样模型更容易理解真实场景中的问题。
想象一下没有MCP之前我们会怎么做?我们可能会人工从数据库中筛选或者使用工具检索可能需要的信息,手动地粘贴到prompt中。随着我们要解决的问题越来越复杂,手工把信息引入到prompt中会变得越来越困难。
为了克服手工prompt的局限性,许多LLM平台(如OpenAI、Google)引入了function call功能。这一机制允许模型在需要时调用预定义的函数来获取数据或执行操作,显著提升了自动化水平。
但是function call也有其局限性,我认为重点在于function call平台依赖性强,不同LLM平台的function call API实现差异较大。例如,OpenAI的函数调用方式与Google的不兼容,开发者在切换模型时需要重写代码,增加了适配成本。除此之外,还有安全性、交互性等问题。
数据与工具本身是客观存在的,只不过我们希望将数据连接到模型的这个环节可以更智能更统一。Anthropic基于这样的痛点设计了MCP,充当AI模型的"万能转接头",让LLM能轻松地获取数据或者调用工具。更具体地说,MCP的优势在于:
- 生态 - MCP提供很多现成的插件,你的AI可以直接使用。
- 统一性 - 不限制于特定的AI模型,任何支持MCP的模型都可以灵活切换。
- 数据安全 - 你的敏感数据留在自己的电脑上,不必全部上传。(因为我们可以自行设计接口确定传输哪些数据)
用户如何使用MCP?
对于用户来说,我们并不关心MCP是如何实现的,通常我们只考虑如何更简单地用上这一特性。具体的使用方式可以参考官方文档:For Claude Desktop Users。这里不再赘述,配置成功后可以在Claude中测试:
Can you write a poem and save it to my desktop?
Claude会请求你的权限后在本地新建一个文件。并且官方也提供了非常多现成的MCP Servers,你只需要选择你希望接入的工具,然后接入即可。
- Awesome MCP Servers
- MCP Servers Website
- Official MCP Servers
比如官方介绍的filesystem工具,它允许Claude读取和写入文件,就像在本地文件系统中一样。
MCP架构解构
MCP由三个核心组件构成:Host、Client和Server。让我们通过一个实际场景来理解这些组件如何协同工作:
假设你正在使用Claude Desktop (Host)询问:"我桌面上有哪些文档?"
- Host:Claude Desktop作为Host,负责接收你的提问并与Claude模型交互。
- Client:当Claude模型决定需要访问你的文件系统时,Host中内置的MCP Client会被激活。这个Client负责与适当的MCP Server建立连接。
- Server:在这个例子中,文件系统MCP Server会被调用。它负责执行实际的文件扫描操作,访问你的桌面目录,并返回找到的文档列表。
整个流程是这样的:你的问题 → Claude Desktop(Host) → Claude模型 → 需要文件信息 → MCP Client连接 → 文件系统MCP Server → 执行操作 → 返回结果 → Claude生成回答 → 显示在Claude Desktop上。
这种架构设计使得Claude可以在不同场景下灵活调用各种工具和数据源,而开发者只需专注于开发对应的MCP Server,无需关心Host和Client的实现细节。
原理:模型是如何确定工具的选用的?
在学习的过程中,我一直好奇一个问题:Claude(模型)是在什么时候确定使用哪些工具的呢?好在Anthropic为我们提供了详细的解释:
当用户提出一个问题时:
- 客户端(Claude Desktop / Cursor)将你的问题发送给Claude。
- Claude分析可用的工具,并决定使用哪一个(或多个)。
- 客户端通过MCP Server执行所选的工具。
- 工具的执行结果被送回给Claude。
- Claude结合执行结果构造最终的prompt并生成自然语言的回应。
- 回应最终展示给用户!
MCP Server是由Claude主动选择并调用的。有意思的是Claude具体是如何确定该使用哪些工具呢?以及是否会使用一些不存在的工具呢(幻觉)?
总结
MCP (Model Context Protocol)代表了AI与外部工具和数据交互的标准建立。通过本文,我们可以了解到:
- MCP的本质:它是一个统一的协议标准,使AI模型能够以一致的方式连接各种数据源和工具,类似于AI世界的"USB-C"接口。
- MCP的价值:它解决了传统function call的平台依赖问题,提供了更统一、开放、安全、灵活的工具调用机制,让用户和开发者都能从中受益。
- 使用与开发:对于普通用户,MCP提供了丰富的现成工具,用户可以在不了解任何技术细节的情况下使用;对于开发者,MCP提供了清晰的架构和SDK,使工具开发变得相对简单。
MCP还处于发展初期,但其潜力巨大。更重要的是生态吧,基于统一标准下构筑的生态也会正向地促进整个领域的发展。
以上内容已经覆盖了MCP的基本概念、价值和使用方法。对于技术实现感兴趣的读者,以下附录提供了一个简单的MCP Server开发实践,帮助你更深入地理解MCP的工作原理。
Appendix A:MCP Server开发实践
在了解MCP组件之后,很容易发现对绝大部分AI开发者来说,我们只需要关心Server的实现。因此,我这里准备通过一个最简单的示例来介绍如何实现一个MCP Server。MCP servers可以提供三种主要类型的功能:
- Resources(资源):类似文件的数据,可以被客户端读取(如API响应或文件内容)
- Tools(工具):可以被LLM调用的函数(需要用户批准)
- Prompts(提示):预先编写的模板,帮助用户完成特定任务
本教程将主要关注工具(Tools)。
A.I 使用LLM构建MCP的最佳实践
在开始之前,Anthropic为我们提供了一个基于LLM的MCP Server的最佳开发实践,总结如下:
- 引入domain knowledge(说人话就是,告诉他一些MCP Server开发的范例和资料)
- 访问https://modelcontextprotocol.io/llms-full.txt并复制完整的文档文本。(实测这个太长了,可以忽略)
- 导航到MCP TypeScript SDK或Python SDK Github项目中并复制相关内容。
- 把这些作为prompt输入到你的chat对话中(作为context)。
- 描述你的需求
- 你的服务器会开放哪些资源
- 它会提供哪些工具
- 它应该给出哪些引导或建议
- 它需要跟哪些外部系统互动
给出一个example prompt:
... (这里是已经引入的domain knowledge)
打造一个MCP服务器,它能够:
- 连接到我公司的PostgreSQL数据库
- 将表格结构作为资源开放出来
- 提供运行只读SQL查询的工具
- 包含常见数据分析任务的引导
剩下的部分也很重要,但是偏重于方法论,实践性较弱,我这里就不展开了,推荐大家直接看官方文档。
A.II 手动实践
本节内容主要参考了官方文档:Quick Start: For Server Developers。你可以选择直接跳过这部分内容或者进行一个速读。
这里我准备了一个简单的示例,使用Python实现一个MCP Server,用来统计当前桌面上的txt文件数量和获取对应文件的名字(你可以理解为一点用都没有,但是它足够简单,主要是为了难以配置环境的读者提供一个足够短的实践记录)。以下实践均运行在我的MacOS系统上。
Step1. 前置工作
- 安装Claude Desktop。
- Python 3.10+环境
- Python MCP SDK 1.2.0+
Step2. 环境配置
由于我使用的是官方推荐的配置:
# 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# 创建项目目录
uv init txt_counter
cd txt_counter
# 设置 Python 3.10+ 环境
echo "3.11" > .python-version
# 创建虚拟环境并激活
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch txt_counter.py
Question: 什么是uv呢和conda比有什么区别?
Answer: 一个用Rust编写的超快速(100x) Python包管理器和环境管理工具,由Astral开发。定位为pip和venv的替代品,专注于速度、简单性和现代Python工作流。
Step3. 构造一个prompt
"""
... (这里是已经引入的domain knowledge)
"""
打造一个MCP服务器,它能够:
- 功能:
- 统计当前桌面上的txt文件数量
- 获取对应文件的名字
要求:
- 不需要给出prompt和resource相关代码。
- 你可以假设我的桌面路径为/Users/{username}/Desktop
- Domain Knowledge复制于MCP Python SDK的README文件
Step4. 实现MCP Server
以下代码由Claude 3.7直接生成。当然,这主要是因为我的需求足够简单,当你需要实现一个复杂的MCP Server时,你可能需要多步的引导和Debug才能得到最终的代码。
import os
from pathlib import Path
from mcp.server.fastmcp import FastMCP
# 创建MCP Server
mcp = FastMCP("桌面TXT文件统计器")
@mcp.tool()
def count_desktop_txt_files() -> int:
"""Count the number of .txt files on the desktop."""
# Get the desktop path
username = os.getenv("USER") or os.getenv("USERNAME")
desktop_path = Path(f"/Users/{username}/Desktop")
# Count .txt files
txt_files = list(desktop_path.glob("*.txt"))
return len(txt_files)
@mcp.tool()
def list_desktop_txt_files() -> str:
"""Get a list of all .txt filenames on the desktop."""
# Get the desktop path
username = os.getenv("USER") or os.getenv("USERNAME")
desktop_path = Path(f"/Users/{username}/Desktop")
# Get all .txt files
txt_files = list(desktop_path.glob("*.txt"))
# Return the filenames
if not txt_files:
return "No .txt files found on desktop."
# Format the list of filenames
file_list = "\n".join([f"- {file.name}" for file in txt_files])
return f"Found {len(txt_files)} .txt files on desktransform: translateY(\n{file_list}"
if __name__ == "__main__":
# Initialize and run the server
mcp.run()
任务非常简单,只需要调用非常基本的os就可以完成。
Step5. 测试MCP Server
(官方没有这一步,但是我非常推荐大家这么做)
$ mcp dev txt_counter.py
Starting MCP inspector...
Proxy server listening on port 3000
? MCP Inspector is up and running at http://localhost:5173 ?
之后进入到给出的链接中,你大概能按下图进行操作:
如果成功,你应该能像我一样看到对应的输出(Tool Result)~
Step6. 接入Claude
最后一步就是把我们写好的MCP接入到Claude Desktop中。流程如下:
# 打开 claude_desktop_config.json (MacOS / Linux)
# 如果你用的是cursor或者vim请更换对应的命令
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
在配置文件中添加以下内容,记得替换/Users/{username}
为你的实际用户名,以及其他路径为你的实际路径。
{
"mcpServers": {
"txt_counter": {
"command": "/Users/{username}/.local/bin/uv",
"args": [
"--directory",
"/Users/{username}/work/mcp-learn/code-example-txt",// 你的项目路径(这里是我的)
"run",
"txt_counter.py"// 你的MCP Server文件名
]
}
}
}
- uv最好是绝对路径,推荐使用
which uv
获取。
配置好后重启Claude Desktop,如果没问题就能看到对应的MCP Server了。
Step7. 实际使用
接下来,我们通过一个简单的prompt进行实际测试:
能推测我当前桌面上txt文件名的含义吗?
它可能会请求你的使用权限,如图一所示,你可以点击Allow for This Chat
看起来我们MCP Server已经正常工作了。