一文看懂什么是MCP(大模型上下文)?用来干什么的?怎么用它?
本文技术性比较强,适合从事技术人员阅读,非技术人员可以了解个大概。
那么,什么是MPC(Model Context Protocol)? 本文介绍下MCP的基本概念、功能价值、工作原理、能做什么以及怎么开发使用,文章最后附带一些相关的学习资料站,基本上学习MCP看这一文就足够了。
打个广告,我开发的这个mcp server插件开源地址:https://github.com/fengin/image-gen-server.git
对接国内的即梦平台,需要注册平台账号,一天一个账号可以免费调用88次,足够用了
无缝与cursor集成,你提你的任务需求,cursor会自动根据你项目的上下文,帮你生成好提示词和调用工具生成,大大提升软件开发效率。
想知道如何开发的?看这里:开发一个MCP Server与Cursor集成,给Cursor插上翅膀!
先看看在Cursor里面的使用效果:
一、什么是MCP(Model Context Protocol)
定义
MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由 Anthropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而无法充分发挥潜力的难题,MCP 使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口。
MCP 的价值
举个栗子,在过去,为了让大模型等 AI 应用使用我们的数据,要么复制粘贴,要么上传下载,非常麻烦。
即使是最强大模型也会受到数据隔离的限制,形成信息孤岛,要做出更强大的模型,每个新数据源都需要自己重新定制实现,使真正互联的系统难以扩展,存在很多的局限性。
现在,MCP 可以直接在 AI 与数据(包括本地数据和互联网数据)之间架起一座桥梁,通过 MCP 服务器和 MCP 客户端,大家只要都遵循这套协议,就能实现“万物互联”。
有了MCP,可以和数据和文件系统、开发工具、Web 和浏览器自动化、生产力和通信、各种社区生态能力全部集成,实现强大的协作工作能力,它的价值远不可估量。
MCP 与 Function Calling 的区别
MCP(Model Context Protocol),模型上下文协议
Function Calling,函数调用
这两种技术都旨在增强 AI 模型与外部数据的交互能力,但 MCP 不止可以增强 AI 模型,还可以是其他的应用系统。
数据安全性
这样一个理想的“万物互联”生态系统看着很让人着迷。
但是大家是不是担心通过 MCP Server 暴露出来的数据会泄露或被非法访问,这个头疼的问题 MCP 也考虑到了。
MCP 通过标准化的数据访问接口,大大减少了直接接触敏感数据的环节,降低了数据泄露的风险。
还有,MCP 内置了安全机制,确保只有经过验证的请求才能访问特定资源,相当于在数据安全又加上了一道防线。同时,MCP协议还支持多种加密算法,以确保数据在传输过程中的安全性。
例如,MCP 服务器自己控制资源,不需要将 API 密钥等敏感信息提供给 LLM 提供商。这样一来,即使 LLM 提供商受到攻击,攻击者也无法获取到这些敏感信息。
不过,MCP 这套协议/标准,需要大家一起来共建,这个生态才会繁荣,现在,只是测试阶段,一切才刚刚开始,当然,还会涌现出更多的问题。
工作原理
MCP 协议采用了一种独特的架构设计,它将 LLM 与资源之间的通信划分为三个主要部分:客户端、服务器和资源。
客户端负责发送请求给 MCP 服务器,服务器则将这些请求转发给相应的资源。这种分层的设计使得 MCP 协议能够更好地控制访问权限,确保只有经过授权的用户才能访问特定的资源。
工作流程
以下是 MCP 的基本工作流程:
初始化连接:客户端向服务器发送连接请求,建立通信通道。
发送请求:客户端根据需求构建请求消息,并发送给服务器。
处理请求:服务器接收到请求后,解析请求内容,执行相应的操作(如查询数据库、读取文件等)。
返回结果:服务器将处理结果封装成响应消息,发送回客户端。
断开连接:任务完成后,客户端可以主动关闭连接或等待服务器超时关闭。
核心架构
MCP 遵循客户端-服务器架构(client-server),其中包含以下几个核心概念:
MCP 主机(MCP Hosts):发起请求的 LLM 应用程序(例如 Claude Desktop、IDE 或 AI 工具)。
MCP 客户端(MCP Clients):在主机程序内部,与 MCP server 保持 1:1 的连接。
MCP 服务器(MCP Servers):为 MCP client 提供上下文、工具和 prompt 信息。
本地资源(Local Resources):本地计算机中可供 MCP server 安全访问的资源(例如文件、数据库)。
远程资源(Remote Resources):MCP server 可以连接到的远程资源(例如通过 API)。
MCP Client
MCP client 充当 LLM 和 MCP server 之间的桥梁,MCP client 的工作流程如下:
MCP client 首先从 MCP server 获取可用的工具列表。
将用户的查询连同工具描述通过 function calling 一起发送给 LLM。
LLM 决定是否需要使用工具以及使用哪些工具。
如果需要使用工具,MCP client 会通过 MCP server 执行相应的工具调用。
工具调用的结果会被发送回 LLM。
LLM 基于所有信息生成自然语言响应。
最后将响应展示给用户。
Claude Desktop 和Cursor都支持了MCP Server接入能力,它们就是作为 MCP client来连接某个MCP Server感知和实现调用。
MCP Server
MCP server 是 MCP 架构中的关键组件,它可以提供 3 种主要类型的功能:
资源(Resources):类似文件的数据,可以被客户端读取,如 API 响应或文件内容。
工具(Tools):可以被 LLM 调用的函数(需要用户批准)。
提示(Prompts):预先编写的模板,帮助用户完成特定任务。
这些功能使 MCP server 能够为 AI 应用提供丰富的上下文信息和操作能力,从而增强 LLM 的实用性和灵活性。
你可以在 MCP Servers Repository 和 Awesome MCP Servers 这两个 repo 中找到许多由社区实现的 MCP server。使用 TypeScript 编写的 MCP server 可以通过 npx 命令来运行,使用 Python 编写的 MCP server 可以通过 uvx 命令来运行。
通信机制
MCP 协议支持两种主要的通信机制:基于标准输入输出的本地通信和基于SSE(Server-Sent Events)的远程通信。
这两种机制都使用 JSON-RPC 2.0 格式进行消息传输,确保了通信的标准化和可扩展性。
本地通信:通过 stdio 传输数据,适用于在同一台机器上运行的客户端和服务器之间的通信。
远程通信:利用 SSE 与 HTTP 结合,实现跨网络的实时数据传输,适用于需要访问远程资源或分布式部署的场景。
二、MCP能做什么?
引入各种各样的MCP Sever能力,可以大大扩展一些AI工具的能力,比如我们常用的Cursor和Claude
这些官方参考服务器展示了 MCP 核心功能和 SDK 的使用:
数据和文件系统
文件系统 - 具有可配置访问控制的安全文件操作
PostgreSQL - 具有架构检查功能的只读数据库访问
SQLite - 数据库交互和商业智能功能
Google Drive - Google Drive 的文件访问和搜索功能
开发工具
Git - 用于读取、搜索和操作 Git 仓库的工具
GitHub - 仓库管理、文件操作和 GitHub API 集成
GitLab - 支持项目管理的 GitLab API 集成
Sentry - 从 Sentry.io 获取和分析问题
Web 和浏览器自动化
Brave Search - 使用 Brave 的搜索 API 进行网络和本地搜索
Fetch - 为 LLM 使用优化的网络内容获取和转换
Puppeteer - 浏览器自动化和网页抓取功能
生产力和通信
Slack - 频道管理和消息功能
Google Maps - 位置服务、路线和地点详情
Memory - 基于知识图谱的持久记忆系统
AI 和专业工具
EverArt - 使用各种模型的 AI 图像生成
Sequential Thinking - 通过思维序列进行动态问题解决
AWS KB Retrieval - 使用 Bedrock Agent Runtime 从 AWS Knowledge Base 检索
官方集成的工具
这些 MCP 服务器由公司维护,用于其平台:
Axiom - 使用自然语言查询和分析日志、跟踪和事件数据
Browserbase - 在云端自动化浏览器交互
Cloudflare - 在 Cloudflare 开发者平台上部署和管理资源
E2B - 在安全的云沙箱中执行代码
Neon - 与 Neon 无服务器 Postgres 平台交互
Obsidian Markdown Notes - 读取和搜索 Obsidian 知识库中的 Markdown 笔记
Qdrant - 使用 Qdrant 向量搜索引擎实现语义记忆
Raygun - 访问崩溃报告和监控数据
Search1API - 用于搜索、爬虫和网站地图的统一 API
Tinybird - 与 Tinybird 无服务器 ClickHouse 平台交互
社区的一些工具
不断发展的社区开发服务器生态系统扩展了 MCP 的功能:
Docker - 管理容器、镜像、卷和网络
Kubernetes - 管理 pod、部署和服务
Linear - 项目管理和问题跟踪
Snowflake - 与 Snowflake 数据库交互
Spotify - 控制 Spotify 播放和管理播放列表
Todoist - 任务管理集成
更多的可以查看社区服务器列表: MCP Servers Repository
三、怎么使用和开发MCP Server
使用
目前支持的部分工具列表(更多见这里):
Claude Desktop 使用示例
以 Claude Desktop 为例,配置 MCP 客户端的步骤如下:
安装 Claude Desktop: 确保已在 macOS 或 Windows 系统上安装最新版本的 Claude Desktop。
配置 MCP 服务器: 在 Claude Desktop 的配置文件中,配置入口Claude Desktop—>菜单—>Settings—>Developer—>Edit Config:
添加所需的 MCP 服务器信息,例如:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
},
"git": {
"command": "uvx",
"args": ["mcp-server-git", "--repository", "path/to/git/repo"]
}
}
}
这里的@modelcontextprotocol/server-filesystem、mcp-server-git是对应的一些MCP Server,可以是开源找来的,也可以是你自己开发的。
配置完后,在主界面对话题右下角就有个锤子出现了,有几个锤子就是配置几个,然后对话中如果涉及使用该工具的,claude就会自动调用
Cursor中 使用示例
Cursor工具中集成mcp server功能对开发增加效率非常明显,配置入口在:文件—>首选项—>Cursor Settings—>Features—>MCP Server—>Add new MCP Server
配置完后,你需要画图的地方给它提要求就行了,它会自动感知,按上下文生成prompt并调用工具生成图片:
生成的图片质量还不错,符合开发需要的图片
开发MCP Server
MCP只是一个协议,只要符合这个协议,理论上所有的语言都可以开发,这里展示用python构建一个简单的 MCP 天气服务器并将其连接到宿主程序 Claude for Desktop的示例:
以下示例如果获取天气接口比较麻烦,具体的实现业务可以不写,你仅写一个hello world返回也可以。主要server.py实现的功能为三步:
注册服务名:server = Server("weather")
注册工具列表描述:@server.list_tools() 注解的方法,注意出入参规范要求
实现具体的工具方法:@server.call_tool()注解的方法,注意出入参规范要求
前置知识
本快速入门假设你熟悉:
Python
LLM(如 Claude)
系统要求
对于 Python,请确保你安装了 Python 3.9 或更高版本。
配置环境
首先,让我们安装 uv
并设置 Python 项目和环境:
curl -LsSf https://astral.sh/uv/install.sh | sh
安装完成后请重启终端,以确保 uv
命令可以被正确识别。
现在,让我们创建并设置项目:
# 为项目创建新目录
uv init weather
cd weather
# 创建虚拟环境并激活
uv venv
# 实测windows下命令打.\.venv\Scripts\activate
source .venv/bin/activate
# 安装依赖
uv add mcp httpx
# 删除模板文件,windows下手动吧
rm hello.py
# 创建我们的文件,windows下手动吧
mkdir -p src/weather
touch src/weather/__init__.py
touch src/weather/server.py
将以下代码添加到 pyproject.toml
:
...rest of config
[build-system]
requires = [ "hatchling",]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/weather"]
[project.scripts]
weather = "weather:main"
将以下代码添加到 __init__.py
:
from . import server
import asyncio
def main():
"""包的主入口点。"""
asyncio.run(server.main())
# 可选:在包级别暴露其他重要项
__all__ = ['main', 'server']
现在让我们开始构建服务器。
构建服务器
1. 导入包
将以下内容添加到 server.py
的顶部:
from typing import Any
import asyncio
import httpx
from mcp.server.models import InitializationOptions
import mcp.types as types
from mcp.server import NotificationOptions, Server
import mcp.server.stdio
2. 设置实例
然后初始化服务器实例和 NWS API 的基础 URL:
# mcp核心协议源码对unicode编码处理还有bug,需手动指定为utf-8
stdin.reconfigure(encoding='utf-8')
stdout.reconfigure(encoding='utf-8')
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
server = Server("weather")
3. 实现工具列表
我们需要告诉客户端有哪些工具可用。list_tools()
装饰器会注册这个处理程序:
@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
"""
列出可用的工具。
每个工具使用 JSON Schema 验证来指定其参数。
"""
return [
types.Tool(
name="get-alerts",
description="获取指定州的天气预警",
inputSchema={
"type": "object",
"properties": {
"state": {
"type": "string",
"description": "两字母州代码(例如 CA、NY)",
},
},
"required": ["state"],
},
),
types.Tool(
name="get-forecast",
description="获取指定位置的天气预报",
inputSchema={
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "位置的纬度",
},
"longitude": {
"type": "number",
"description": "位置的经度",
},
},
"required": ["latitude", "longitude"],
},
),
]
这里定义了我们的两个工具:get-alerts
和 get-forecast
。
4. 辅助函数
接下来,让我们添加用于查询和格式化国家气象服务 API 数据的辅助函数:
async def make_nws_request(client: httpx.AsyncClient, url: str) -> dict[str, Any] | None:
"""向 NWS API 发送请求并进行适当的错误处理。"""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/geo+json"
}
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""将预警特征格式化为简洁的字符串。"""
props = feature["properties"]
return (
f"事件:{props.get('event', '未知')}\n"
f"区域:{props.get('areaDesc', '未知')}\n"
f"严重程度:{props.get('severity', '未知')}\n"
f"状态:{props.get('status', '未知')}\n"
f"标题:{props.get('headline', '无标题')}\n"
"---"
)
5. 实现工具执行
工具执行处理程序负责实际执行每个工具的逻辑。让我们添加它:
@server.call_tool()
async def handle_call_tool(
name: str, arguments: dict | None
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
"""
处理工具执行请求。
工具可以获取天气数据并通知客户端变化。
"""
if not arguments:
raise ValueError("缺少参数")
if name == "get-alerts":
state = arguments.get("state")
if not state:
raise ValueError("缺少州参数")
# 将州代码转换为大写以确保格式一致
state = state.upper()
if len(state) != 2:
raise ValueError("州代码必须是两位字母(例如 CA, NY)")
async with httpx.AsyncClient() as client:
alerts_url = f"{NWS_API_BASE}/alerts?area={state}"
alerts_data = await make_nws_request(client, alerts_url)
if not alerts_data:
return [types.TextContent(type="text", text="获取预警数据失败")]
features = alerts_data.get("features", [])
if not features:
return [types.TextContent(type="text", text=f"{state} 没有活跃的预警")]
# 将每个预警格式化为简洁的字符串
formatted_alerts = [format_alert(feature) for feature in features[:20]] # 仅取前20个预警
alerts_text = f"{state} 的活跃预警:\n\n" + "\n".join(formatted_alerts)
return [
types.TextContent(
type="text",
text=alerts_text
)
]
elif name == "get-forecast":
try:
latitude = float(arguments.get("latitude"))
longitude = float(arguments.get("longitude"))
except (TypeError, ValueError):
return [types.TextContent(
type="text",
text="无效的坐标。请提供有效的纬度和经度数字。"
)]
# 基本坐标验证
if not (-90 <= latitude <= 90) or not (-180 <= longitude <= 180):
return [types.TextContent(
type="text",
text="无效的坐标。纬度必须在 -90 到 90 之间,经度在 -180 到 180 之间。"
)]
async with httpx.AsyncClient() as client:
# 首先获取网格点
lat_str = f"{latitude}"
lon_str = f"{longitude}"
points_url = f"{NWS_API_BASE}/points/{lat_str},{lon_str}"
points_data = await make_nws_request(client, points_url)
if not points_data:
return [types.TextContent(type="text", text=f"获取坐标 {latitude}, {longitude} 的网格点数据失败。此位置可能不受 NWS API 支持(仅支持美国位置)。")]
# 从响应中提取预报 URL
properties = points_data.get("properties", {})
forecast_url = properties.get("forecast")
if not forecast_url:
return [types.TextContent(type="text", text="从网格点数据获取预报 URL 失败")]
# 获取预报
forecast_data = await make_nws_request(client, forecast_url)
if not forecast_data:
return [types.TextContent(type="text", text="获取预报数据失败")]
# 格式化预报周期
periods = forecast_data.get("properties", {}).get("periods", [])
if not periods:
return [types.TextContent(type="text", text="没有可用的预报周期")]
# 将每个周期格式化为简洁的字符串
formatted_forecast = []
for period in periods:
forecast_text = (
f"{period.get('name', '未知')}:\n"
f"温度: {period.get('temperature', '未知')}°{period.get('temperatureUnit', 'F')}\n"
f"风: {period.get('windSpeed', '未知')} {period.get('windDirection', '')}\n"
f"{period.get('shortForecast', '无可用预报')}\n"
"---"
)
formatted_forecast.append(forecast_text)
forecast_text = f"{latitude}, {longitude} 的预报:\n\n" + "\n".join(formatted_forecast)
return [types.TextContent(
type="text",
text=forecast_text
)]
else:
raise ValueError(f"未知工具: {name}")
6. 运行服务器
最后,实现主函数来运行服务器:
async def main():
# 使用标准输入/输出流运行服务器
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationOptions(
server_name="weather",
server_version="0.1.0",
capabilities=server.get_capabilities(
notification_options=NotificationOptions(),
experimental_capabilities={},
),
),
)
# 如果你想连接到自定义客户端,这是必需的
if __name__ == "__main__":
asyncio.run(main())
你的服务器已经完成!运行 uv run src/weather/server.py
以确认一切正常。
让我们现在测试你的服务器,从现有的 MCP 宿主程序,Claude for Desktop。
测试你的服务器与 Claude for Desktop
首先,确保你已经安装了 Claude for Desktop。你可以在这里安装最新版本。
接下来,在Claude for Desktop中配置你的MCP服务器,这个在“Claude Desktop 使用示例”章节中有说明。
Windows配置
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"C:\\ABSOLUTE\PATH\TO\PARENT\FOLDER\weather",
"run",
"weather"
]
}
}
}
MacOS/Linux配置
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather"
]
}
}
}
这告诉 Claude for Desktop:
有一个名为 “weather” 的 MCP 服务器
通过运行
uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather
来启动它
保存文件,并重新启动 Claude for Desktop。
现在你可以通过在 Claude for Desktop 中运行以下命令来测试你的服务器:
Sacramento 的天气怎么样?
Texas 有什么活跃的天气预警?
幕后原理
当你提出一个问题时:
客户端将你的问题发送给 Claude
Claude 分析可用的工具并决定使用哪个工具
客户端通过 MCP 服务器执行选定的工具
结果返回给 Claude
Claude 组织一个自然语言响应
响应显示给你!
四、核心的MCP 学习资料
作为AI全书布道者,刚接触MCP也是一头雾水,MCP在2024年年底左右才出来,为了开发一个MCP服务,找过很多资料学习,我把这些其中比较好的学习资料挑选了下,分享给大家,方便大家阅读,也免得大家去网上找零散的资料了。
官方资料
协议源码:https://github.com/modelcontextprotocol (含mcp核心源码/各种sdk)
中文学习
中文站:https://mcpcn.com (不确定是否官方)
中文站2:https://modelcontextprotocol.info/zh-cn/docs/ (和上面内容基本一样)
框架和实践
FastMCP框架:https://github.com/jlowin/fastmcp (一个python快速开发mcp server的框架)
Cursor里配置:https://docs.cursor.com/advanced/model-context-protocol (cursor里面加mcp server说明)
Cursor图片生成插件:https://aibook.ren/archives/mcp-server-for-cursor (本站开发的一款图片生成的MCP Server)
970+MCP Servers:https://www.pulsemcp.com/servers (970多个MCP Servers)
其他实践
Python MCP Server 开发详解:https://www.aisharenet.com/mcp-he-python-mcp-s/
Anthropic的MCP如何使用:https://juejin.cn/post/7442320575749537807