1、什么是 MCP
1.1 MCP 介绍
MCP(Model Context Protocol,模型上下文协议) 起源于 2024 年 11 月 25 日 Anthropic 发布的文章:Introducing the Model Context Protocol。
可以用“AI 扩展坞”来比喻 MCP 在 AI 领域的作用。就像现代扩展坞可以连接显示器、键盘、移动硬盘等多种外设,为笔记本电脑瞬间扩展功能一样,MCP Server 作为一个智能中枢平台,能够动态接入各类专业能力模块(如知识库、计算工具、领域模型等)。当 LLM 需要完成特定任务时,可以像"即插即用"般调用这些模块,实时获得精准的上下文支持,从而实现能力的弹性扩展。这种架构打破了传统 AI 模型的封闭性,让大语言模型像搭载了多功能扩展坞的超级工作站,随时都能获取最合适的专业工具。
1.2 为什么要有 MCP
终结工具调用碎片化
不同模型在定义 Function Call(函数调用)时,采用的结构和参数格式各不相同,使得对多模型集成、统一管理和标准化接入变得复杂而繁琐。
属性维度 | OpenAI | Claude | Gemini | LLaMA |
---|---|---|---|---|
调用结构名称 | tool_calls | tool_use | functionCall | function_call |
参数格式 | JSON字符串 | JSON对象 | JSON对象 | JSON对象 |
特殊字段 | finish_reason 字段 | 包含id 和`` | args 字段命名 | 与OpenAI结构相似 |
对于开发者来说,针对不同模型去实现不同的工具调用方法,所谓的定制化开发不仅消耗大量时间和资源,而且维护也变得困难。
而 MCP 作为一种 AI 模型的标准化接入协议,能够显著简化模型之间的集成。
实现多功能应用与创新体验的突破
MCP 的潜力不仅限于连接现有工具,它还在推动客户端应用向“万能应用”演进,并创造全新的用户体验。
以代码编辑器 Cursor 为例,作为 MCP 客户端,用户可以通过集成不同的 MCP 服务器,将其转变为具备 Slack 消息收发、邮件发送(Resend MCP)、甚至图像生成(Replicate MCP)等多种功能的综合工作站。
更具创造力的是,在单一客户端中组合多个 MCP 服务器可以解锁复杂的新流程。例如,AI 代理可以一边生成前端界面代码,一边调用图像生成服务器为主页创作视觉元素。这种模式超越了传统应用的单一功能限制,为用户带来多样化的操作体验。
2、MCP Server 开发
MCP server 是 MCP 架构中的关键组件,目前提供 3 种主要类型的功能,
- 资源(Resources):类似文件的数据,可以被客户端读取,如 文件内容。
- 工具(Tools):可以被 LLM 调用的函数。
- 提示(Prompts):预先编写的prompt模板,帮助用户完成特定任务。
还有其他两种(samping 和 roots)但是目前还没被很好的支持。
以开发一个企业微信机器人 mcp server 为例,用到的是社区sdk typescript-sdk 。(https://github.com/modelcontextprotocol/typescript-sdk)
2.1 项目搭建开发
可以参考官方 quickstart(https://modelcontextprotocol.io/quickstart/server)
环境:nodejs > v16 (我用的是 v22.6)
npm init -y
# Install dependencies
npm install @modelcontextprotocol/sdk zod
npm install -D @types/node typescript
mkdir src
touch src/index.ts
创建 mcp-server 实例
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
export const server = new McpServer({
name: "wechat-mcp-server",
version: "0.0.1",
});
可以直接使用 sdk 封装好的 McpServer 函数。
创建 tools 工具
定义 mcp 提供给 client 或者 llm 使用的工具,企业微信机器人主要就是 发送文本、发送 markdown、发送图片等等,这里我们举例一个发送文本的工具实现
text.ts
// Helper function for sending WeChat messages
export async function sendWeChatTextMessage(webhookKey: string, content: string, chatid: string =
"@all_group", mentioned_list?: string[], mentioned_mobile_list?: string[], visible_to_user?: string):
Promise<boolean> {
const WECHAT_API_BASE = ` http://in.qyapi.wbin/webhook/send?key=${ webhookKey}`;
const headers = {
"Content-Type": "application/json", };
const body = JSON.stringify({
"msgtype": "text",
"text": {
"content": content,
"mentioned_list": mentioned_list,
"mentioned_mobile_list": mentioned_mobile_list
},
"chatid": chatid,
"visible_to_user": visible_to_user ? visible_to_user.split('|') : undefined
});
try {
const response = await fetch(WECHAT_API_BASE, { headers, method: "POST", body });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return true;
} catch (error) {
console.error("Error sending WeChat message:", error);
return false;
} }
通过 server.tool 注册发送文本工具,注册工具有四个函数,比如有些可以加描述,有些是0参数调用等等,选一个合适自己的即可。我们这里必须需要知道回调的 webhook key 和 content 。
import { sendWeChatTextMessage } from "./text.js";
// Register WeChat message tool
server.tool(
"sendWeChatTextMessage",
"send WeChat text message",
{
webhookKey: z.string().describe("WeChat webhook key"), // 必填
content: z.string().describe("WeChat message content"),// 必填
chatid: z.string().describe("WeChat message chatid").optional(), // optional 选填
mentioned_list: z.array(z.string()).describe("WeChat message mentioned list").optional(),
mentioned_mobile_list: z.array(z.string()).describe("WeChat message mentioned mobile list").optional(),
},
async ({ webhookKey, content, chatid, mentioned_list, mentioned_mobile_list }) => {
const success = await sendWeChatTextMessage(webhookKey, content, chatid, mentioned_list,
mentioned_mobile_list);
if (!success) {
return {
content: [
{
type: "text",
text: "Failed to send WeChat message",
},
],
};
}
return {
content: [
{
type: "text",
text: "WeChat message sent successfully",
},
],
};
},
);
发送文本工具就注册好了,其他功能工具开发类似。
创建resource资源
这里我们放一个企业微信机器人的文档。
server.resource(
"api",
"file:///api.md",
async (uri) => {
try {
console.info(uri)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const filePath = path.join(__dirname.replace('build', 'assets'), 'api.md');
const content = await fs.promises.readFile(filePath, 'utf-8');
return {
contents: [{
uri: uri.href,
text: content
}]
};
} catch (error) {
return {
contents: [{
uri: uri.href,
text: "读取文件失败"
}]
};
}
});
创建prompt
提示符是可重用的模板,可以帮助LLMs有效地与服务器交互。这里我们可以做一个参数检查的prompt。
server.prompt(
"parameter_check",
"参数检查",
{
param: z.string().describe("参数"),
apiContent: z.string().describe("API文档")
},
({ param,apiContent }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `
<instruction>
<instructions>
1. 接收API文档文本和用户数据作为输入。
2. 从API文档中提取所有参数的要求,包括参数名称、类型、是否必需、默认值等信息。
3. 对照用户提供的数据,检查每个参数是否满足API的要求。
4. 对于每个参数,记录以下信息:
- 参数名称
- 用户提供的值
- 是否满足API要求(是/否)
- 如果不满足,说明原因
5. 将所有检查结果整理成一个清晰的报告,确保输出不包含任何XML标签。
6. 确保报告的格式简洁明了,便于用户理解。
</instructions>
<examples>
<example>
<input>
API文档文本: "参数: username, 类型: string, 必需: 是; 参数: age, 类型: integer, 必需: 否;"
用户数据: "{\"username\": john_doe, \"age\": 25}"
</input>
<output>
"参数: username, 用户提供的值: john_doe, 满足要求: 是; 参数: age, 用户提供的值: 25, 满足要求: 是;"
</output>
</example>
</examples>
</instruction>
API文档文本:${apiContent}
用户数据:${param}
`
}
}]
}
)
);
2.2 运行调试
可以使用社区Inspector工具来调试我们的mcp。我使用的版本是v0.6.0,如果是用devcloud开发的同学可能会无法调试使用,因为代理地址写死了是localhost,导致连接失败,已经给社区提了PR #201并合并,远程开发的同学可以直接拉源码或者等待工具发布新版本。
调试tools
调试resource
调试prompt
3、MCP Client 开发
MCP Client的主要任务是连接到MCP Server,可以通过标准输入/输出或 SSE (Server-Sent Events) 与 MCP 服务器进行通信。
3.1 实现步骤
初始化客户端和会话对象
class MCPClient:
def __init__(self):
# 初始化 session 和 client 对象
self.session: Optional[ClientSession] = None
self._streams_context: Optional[sse_client] = None
self._session_context: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack() # 初始化异步退出栈
连接到MCP服务
async def connect_to_sse_server(self, server_url: str):
"""连接到使用 SSE 传输的 MCP 服务器"""
if not server_url.startswith(" http://" ) and not server_url.startswith(" https://" ):
raise ValueError("服务器 URL 必须以 ' http://' 或 'https://' 开头")
# 存储上下文管理器以保持其存活
self._streams_context = sse_client(url=server_url)
streams = await self._streams_context.__aenter__()
self._session_context = ClientSession(*streams)
self.session: ClientSession = await self._session_context.__aenter__()
# 初始化
await self.session.initialize()
async def connect_to_server(self, server_script_path: str):
"""
连接到通过标准输入/输出通信的 MCP 服务器
参数:
server_script_path: 服务器脚本路径(.py 或 .js 文件)
示例: "server.py" 或 "server.js"
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
有两种连接方式,分别是:
- stdio(标准输入输出通信)。
- HTTP with Server-Sent Events (SSE)(HTTP 服务端发送事件)。
清理资源
class MCPClient:
def __init__(self):
# 初始化 session 和 client 对象
self.session: Optional[ClientSession] = None
async def connect_to_sse_server(self, server_url: str):
"""连接到使用 SSE 传输的 MCP 服务器"""
if not server_url.startswith(" http://" ) and not server_url.startswith(" https://" ):
raise ValueError("服务器 URL 必须以 ' http://' 或 'https://' 开头")
# 存储上下文管理器以保持其存活
self._streams_context = sse_client(url=server_url)
streams = await self._streams_context.__aenter__()
self._session_context = ClientSession(*streams)
self.session: ClientSession = await self._session_context.__aenter__()
# 初始化
await self.session.initialize()
async def cleanup(self):
"""清理 session 和 streams"""
if self._session_context:
await self._session_context.__aexit__(None, None, None)
if self._streams_context:
await self._streams_context.__aexit__(None, None, None)
3.2 调用
async def main():
if len(sys.argv) < 2:
print("用法: uv run client.py <SSE MCP 服务器的 URL (例如 " "=""> http://localhost:8080/sse)>" )
print("或: uv run client.py <MCP 服务器脚本路径 (例如 server.py)>")
sys.exit(1)
client = MCPClient()
try:
# stdio 连接方式
# await client.connect_to_server(server_script_path=sys.argv[1])
# sse 连接方式
await client.connect_to_sse_server(server_url=sys.argv[1])
print("\n连接到服务器...")
response = await client.session.list_prompts()
response1 = await client.session.list_tools()
response2 = await client.session.list_resources()
print("response", response)
print("response1", response1)
print("response2", response2)
finally:
try:
await client.cleanup()
except Exception as e:
print(f"清理错误: {e}")
4、MCP的工作原理
4.1 MCP架构
MCP采用的是C/S结构,一个MCP host应用可以链接多个MCP servers。
- Host(主机):例如cursor、cline,负责接收你的提问并与模型交互。
- Client(客户端):运行在Host内,mcp client 与 mcp server保持 1:1 连接,当用户在交互界面输入问题时,模型来决定使用1个或者多个工具,通过client来调用server执行具体操作。
- Server(服务):在这个例子中,文件系统 MCP Server 会被调用。它负责执行实际的文件扫描操作,访问你的桌面目录,并返回找到的文档列表。
4.2 json-rpc
在我们用inspector调试我们的mcp-server时,请求参数里会有jsonrpc字段,在mcp中 client 和 server 之间的传输均采用了JSON-RPC 2.0 来交换消息。
主要特点包括:
- 简单易用: 相比于其他 XML-RPC 协议,JSON-RPC 使用 JSON 格式更容易理解和处理,因为 JSON 是一种人类可读的文本格式,同时被多种编程语言广泛支持。
- 轻量级: JSON-RPC 没有复杂的格式和规则,是一种轻量级的协议,非常适合嵌入式系统和网络环境不理想的情况下使用。
- 无状态: JSON-RPC 是无状态的协议,每次请求都是独立的,不依赖于之前的通信。
- 语言中立: 不限于某一种编程语言,被各种编程语言广泛支持。
- 支持批处理: JSON-RPC 还支持批处理模式,即在一个请求中发送多个 RPC 调用,以提高效率。
那么,如何系统的去学习大模型LLM?
作为一名从业五年的资深大模型算法工程师,我经常会收到一些评论和私信,我是小白,学习大模型该从哪里入手呢?我自学没有方向怎么办?这个地方我不会啊。如果你也有类似的经历,一定要继续看下去!这些问题啊,也不是三言两语啊就能讲明白的。
所以我综合了大模型的所有知识点,给大家带来一套全网最全最细的大模型零基础教程。在做这套教程之前呢,我就曾放空大脑,以一个大模型小白的角度去重新解析它,采用基础知识和实战项目相结合的教学方式,历时3个月,终于完成了这样的课程,让你真正体会到什么是每一秒都在疯狂输出知识点。
由于篇幅有限,⚡️ 朋友们如果有需要全套 《2025全新制作的大模型全套资料》,扫码获取~
👉大模型学习指南+路线汇总👈
我们这套大模型资料呢,会从基础篇、进阶篇和项目实战篇等三大方面来讲解。
👉①.基础篇👈
基础篇里面包括了Python快速入门、AI开发环境搭建及提示词工程,带你学习大模型核心原理、prompt使用技巧、Transformer架构和预训练、SFT、RLHF等一些基础概念,用最易懂的方式带你入门大模型。
👉②.进阶篇👈
接下来是进阶篇,你将掌握RAG、Agent、Langchain、大模型微调和私有化部署,学习如何构建外挂知识库并和自己的企业相结合,学习如何使用langchain框架提高开发效率和代码质量、学习如何选择合适的基座模型并进行数据集的收集预处理以及具体的模型微调等等。
👉③.实战篇👈
实战篇会手把手带着大家练习企业级的落地项目(已脱敏),比如RAG医疗问答系统、Agent智能电商客服系统、数字人项目实战、教育行业智能助教等等,从而帮助大家更好的应对大模型时代的挑战。
👉④.福利篇👈
最后呢,会给大家一个小福利,课程视频中的所有素材,有搭建AI开发环境资料包,还有学习计划表,几十上百G素材、电子书和课件等等,只要你能想到的素材,我这里几乎都有。我已经全部上传到优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费
】
相信我,这套大模型系统教程将会是全网最齐全 最易懂的小白专用课!!