在快速发展的AI编程助手领域,有两个概念经常被一起提及,甚至被一些开发者和技术文章所混淆:Function Calling 和 Model Context Protocol (MCP)。是不是一定要LLM具备Function Calling能力,才能有效利用MCP与外部工具交互呢?答案可能和你想象的不一样。今天,我们就来澄清这个常见的误解,并深入流行的VSCode插件——Cline的源码,看看它是如何巧妙解决这个问题的。
看到这里,你可能已经有点明白了:MCP负责的是“通信管道”的标准,而Function Calling是某些LLM拥有的“智能大脑”的一部分。理论上,只要LLM应用能按照MCP规定的格式发出请求,MCP就能工作,并不强制要求LLM本身具备原生的Function Calling能力。
误解的产生往往源于一个看似合理的逻辑链:
这个逻辑没错,但它忽略了一点:LLM产生“调用哪个工具以及如何调用”的结构化输出,不一定非要依赖其内置的Function Calling能力。
VSCode上广受欢迎的Cline插件就是一个很好的例子。它支持通过OpenRouter这样的平台接入上百种不同的LLM。显然,这些LLM中只有少数具备原生的Function Calling能力,但这并不妨碍用户在Cline中使用各种MCP Server提供的强大功能。
Cline是如何做到的呢?答案就藏在它的开源代码里,具体来说是src/core/prompts/system.ts
文件中的SYSTEM_PROMPT
函数。这个函数构建了一个极其详尽、长达近千行的系统提示词(System Prompt)。
这个System Prompt就像一份详细的说明书,告诉LLM:
<tool_name>
<parameter1_name>value1parameter1_name>
<parameter2_name>value2parameter2_name>
...
tool_name>
<read_file>
<path>src/main.jspath>
read_file>
LLM被要求严格遵守这种XML格式来发起工具调用。
execute_command
)、读文件(read_file
)、写文件(write_to_file
)等,并详细说明了它们的用途、参数和使用格式。 (有趣的是,根据源码注释,Cline的这几个基础工具调用是通过VSCode API实现的,并未走MCP通道)。
<execute_command>
<command>npm install reactcommand>
<requires_approval>truerequires_approval>
execute_command>
<write_to_file>
<path>src/App.jspath>
<content>
// 完整的JS代码内容...
content>
write_to_file>
use_mcp_tool
(使用MCP服务器提供的工具)和access_mcp_resource
(访问MCP服务器提供的资源)。
<use_mcp_tool>
<server_name>example-weather-serverserver_name>
<tool_name>get_forecasttool_name>
<arguments>
{
"city": "北京",
"days": 3
}
arguments>
use_mcp_tool>
<access_mcp_resource>
<server_name>example-weather-serverserver_name>
<uri>weather://San Francisco/currenturi>
access_mcp_resource>
例如,如果连接了一个天气查询的MCP Server,System Prompt里就会包含类似这样的描述:
## example-weather-server (`node /path/to/weather-server/build/index.js`)
### Available Tools
- get_forecast: Get weather forecast for a city
Input Schema:
{
"type": "object",
"properties": { ... }, // 详细的参数定义
"required": ["city"]
}
### Resource Templates
- weather://{city}/current (Current weather for a given city): ...
### Direct Resources
- weather://San Francisco/current (Current weather in San Francisco): ...
通过这种方式,即使LLM本身没有Function Calling能力,它也能通过阅读这份极其详尽的System Prompt,“学习”到当前可用的所有工具(包括来自MCP Server的)以及如何按照规定的XML格式来请求调用它们。Cline的后端代码再解析这个XML输出,转换成真正的MCP请求发送出去。
Cline的这种做法非常聪明,它以兼容性换取了一些潜在的代价:
关于上述缺点的第二点,一个有趣的参考来自 Berkeley Function-Calling Leaderboard。这个排行榜评估了各种LLM在Function Calling任务上的表现。值得注意的是,排行榜也将“使用System Prompt引导LLM进行工具调用”的方式纳入了比较。
结果有些出人意料:对于像OpenAI的GPT-4o和o1这样的顶尖模型,使用System Prompt的方式在某些测试维度上,表现甚至优于或显著优于它们自身的原生Function Calling能力!
GPT-4o: Function Calling (FC) vs. System Prompt (Prompt)
当然,对于大多数其他LLM来说,原生Function Calling的表现通常还是更好一些,但差距并没有想象中那么大。这表明,只要System Prompt设计得足够好、足够清晰,通过Prompt引导的方式完全可以达到非常理想的工具调用效果。 Cline的做法在平衡通用性和准确性上是相当成功的。
(注:Cline团队未来或许可以考虑优化,比如先检测LLM是否支持原生Function Calling,如果支持则优先使用,以节省Token。)
所以,回到最初的问题:MCP必须依赖Function Calling吗?答案是否定的。
MCP只是一个通信协议。虽然实现MCP交互需要LLM能够生成结构化的工具调用指令,但这并不一定需要LLM具备原生的Function Calling能力。通过像Cline那样精心设计、内容详尽的System Prompt,完全可以引导几乎任何LLM“学会”如何按照MCP的要求与外部世界互动。
理解了这一点,能帮助我们更清晰地认识当前LLM Agent架构,也更能体会到像Cline这样优秀工具在设计上的巧思。下一次当你使用或开发类似的AI应用时,就能更深刻地理解其背后的运作机制了。
想探索AI前沿?来 ChatTools (https://chat.chattools.cn)!聚合GPT-4o(支持图片编辑)、Claude 3.7 Sonnet、DeepSeek-R1、Gemini等顶尖模型。亮点:Midjourney免费无限生图!