什么是MCP
MCP 起源于 2024 年 11 月 25 日 Anthropic 发布的文章:Introducing the Model Context Protocol。
MCP 是一个开放协议,它为应用程序向 LLM 提供上下文的方式进行了标准化。你可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化的方式一样,MCP 为 AI 模型连接各种数据源和工具提供了标准化的接口。
如下图

可以看出,MCP 就是以更标准的方式让 LLM Chat 使用不同工具,更简单的可视化如下图所示,这样你应该更容易理解“中间协议层”的概念了。Anthropic 旨在实现 LLM Tool Call 的标准。

MCP架构

MCP 由三个核心组件构成:Host、Client 和 Server。
这里主要涉及到三个角色:主机、服务器和客户端。
Host是发起连接的 LLM 应用程序(如 Claude Desktop 或 IDE)
Client在主机应用程序内部与服务器保持 1:1 连接
Server向客户端提供上下文、工具和提示
Why MCP
LLM的一些缺点:
1.会产生幻觉。
2.结果并不总是真实的。
- 对时事的了解有限或一无所知。
4.很难应对复杂的计算。
为了解决这个问题出现了一系列的技术或者手段

简介
Function Calling 的核心思想: 将大语言模型的语言理解能力与外部工具的功能结合起来,让大语言模型能够理解用户的意图,并调用合适的工具来完成任务。例如,通过 Function Calling,大语言模型可以:
调用天气 API获取实时天气信息: 不再局限于提供过时的天气预报,而是可以告诉你此时此刻的天气状况,就像你打开手机上的天气应用一样。
调用订票网站 API 预订机票: 不再只是告诉你如何订票,而是可以直接帮你完成订票操作,就像一个专业的旅行代理一样。
调用代码执行程序: 可以执行代码来完成各种任务,例如数据分析、图像处理等,就像一个经验丰富的程序员一样。
多模态感知和工具利用等策略来扩展其感知和行动空间
function call 实现伪代码
# 定义可调用的函数列表 (AI 可使用的工具)
functions = [
{
"name": "get_weather",
"description": "获取指定城市的天气信息",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名称"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
},
{
"name": "track",
"description": "追踪指定股票的实时价格",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"description": "需要追踪的股票代码"
}
},
"required": ['symbol']
}
}
...
]
# 用户输入处理
user_input = "北京今天气温多少度?"
# AI 模型处理流程
def process_request(input_text):
# 1\. 语义理解
intent = understand_intent(input_text) # 识别用户意图
# 2\. 判断是否需要调用函数
if intent == "weather_inquiry":
# 3\. 提取函数调用参数
params = extract_parameters(
input_text,
function_schema=functions["get_weather"]["parameters"]
)
# 4\. 生成函数调用指令
function_call = {
"name": "get_weather",
"arguments": params
}
# 5\. 执行函数调用(可能对接外部API)
if validate_parameters(function_call):
weather_data = external_api_call(
function_call["name"],
function_call["arguments"]
)
# 6\. 将结构化数据转换为自然语言响应
response = generate_response(weather_data)
return response
# 其他意图处理...
else:
return generate_general_response(input_text)
# 执行处理流程
final_response = process_request(user_input)
print(final_response)
从上面伪代码可以看到 function call 主要干了两件事。
1.判断是否要调用某个预定义的函数。
2.如果要调用,从用户输入的文本里提取出函数所需要的函数值。
将这个过程标准化,变为一个协议,所有的LLM都可以调用 这个就是MCP
MCP 协议都包括什么
https://www.claudemcp.com/zh/specification
如何使用 MCP?
https://zhuanlan.zhihu.com/p/30102885373 mcp服务和资源网站
https://www.claudemcp.com/zh/servers
以cursor为例演示
MCP 原理
在学习的过程中,我一直好奇一个问题:Claude(模型)是在什么时候确定使用哪些工具的呢?
解释:
当用户提出一个问题时:
graph LR
A[用户输入自然语言] --> B[LLM 解析意图]
B --> C[生成 MCP 工具调用指令]
C --> D[MCP Client 发送请求]
D --> E[MCP Server 调用工具]
E --> F[工具执行并返回结果]
F --> G[LLM 整合结果生成回答]
G --> H[用户获得最终响应]
// 伪代码:LLM 服务端处理
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: 'YOUR_KEY' });
async function callLLM(userQuery: string): Promise<string> {
const prompt = `
请将用户问题转换为 MCP 工具调用指令(JSON格式):
问题:${userQuery}
可用工具清单:
- 代码分析工具: analyze_code,参数 { file_path: string, check_type: 'memory_leak' | 'performance' }
- 数据查询工具: query_database,参数 { sql: string }
输出示例:
{ "tool_name": "analyze_code", "parameters": { "file_path": "src/App.cpp", "check_type": "memory_leak" } }
`;
const completion = await openai.chat.completions.create({
messages: [{ role: 'user', content: prompt }],
model: 'gpt-4',
});
return completion.choices[0].message.content;
}
- Cursor 分析可用的工具,并决定使用哪一个(或多个)。
2.客户端通过 MCP Server 执行所选的工具。
3.工具的执行结果被送回给 Cursor。
4.Cursor 结合执行结果构造最终的 prompt 并生成自然语言的回应。
5.回应最终展示给用户!
6.由 LLM(Cursor)确定使用哪些 MCP Server。
7.执行对应的 MCP Server 并对执行结果进行重新处理
... # 省略了无关的代码
async def start(self):
# 初始化所有的 mcp server
for server in self.servers:
await server.initialize()
# 获取所有的 tools 命名为 all_tools
all_tools = []
for server in self.servers:
tools = await server.list_tools()
all_tools.extend(tools)
# 将所有的 tools 的功能描述格式化成字符串供 LLM 使用
# tool.format_for_llm() 我放到了这段代码最后,方便阅读。
tools_description = "\n".join(
[tool.format_for_llm() for tool in all_tools]
)
# 这里就不简化了,以供参考,实际上就是基于 prompt 和当前所有工具的信息
# 询问 LLM(Claude) 应该使用哪些工具。
system_message = (
"You are a helpful assistant with access to these tools:\n\n"
f"{tools_description}\n"
"Choose the appropriate tool based on the user's question. "
"If no tool is needed, reply directly.\n\n"
"IMPORTANT: When you need to use a tool, you must ONLY respond with "
"the exact JSON object format below, nothing else:\n"
"{\n"
' "tool": "tool-name",\n'
' "arguments": {\n'
' "argument-name": "value"\n'
" }\n"
"}\n\n"
"After receiving a tool's response:\n"
"1\. Transform the raw data into a natural, conversational response\n"
"2\. Keep responses concise but informative\n"
"3\. Focus on the most relevant information\n"
"4\. Use appropriate context from the user's question\n"
"5\. Avoid simply repeating the raw data\n\n"
"Please use only the tools that are explicitly defined above."
)
messages = [{"role": "system", "content": system_message}]
while True:
# Final... 假设这里已经处理了用户消息输入.
messages.append({"role": "user", "content": user_input})
# 将 system_message 和用户消息输入一起发送给 LLM
llm_response = self.llm_client.get_response(messages)
... # 后面和确定使用哪些工具无关
class Tool:
"""Represents a tool with its properties and formatting."""
def __init__(
self, name: str, description: str, input_schema: dict[str, Any]
) -> None:
self.name: str = name
self.description: str = description
self.input_schema: dict[str, Any] = input_schema
# 把工具的名字 / 工具的用途(description)和工具所需要的参数(args_desc)转化为文本
def format_for_llm(self) -> str:
"""Format tool information for LLM.
Returns:
A formatted string describing the tool.
"""
args_desc = []
if "properties" in self.input_schema:
for param_name, param_info in self.input_schema["properties"].items():
arg_desc = (
f"- {param_name}: {param_info.get('description', 'No description')}"
)
if param_name in self.input_schema.get("required", []):
arg_desc += " (required)"
args_desc.append(arg_desc)
return f"""
Tool: {self.name}
Description: {self.description}
Arguments:
{chr(10).join(args_desc)}
"""
其他MCP
vite-plugin-vue-mcp
参考
https://www.claudemcp.com/zh/docs/introduction
https://zhuanlan.zhihu.com/p/663770472
https://zhuanlan.zhihu.com/p/1892612293252065003
https://zhuanlan.zhihu.com/p/29001189476