Tip
提示
以下將 MCP (主要指服務端) 和 FunctionCall (主要指 OpenAI chat 規範的函數調用) 都籠統稱為 “插件”,方便快速理解,
- 模型本身不具備調用 function 或 mcp Server 的能力
- 兩者都是告訴遠程模型,客戶端具備那些額外能力 (如天氣插件、數據庫插件、畫圖插件),模型依據當前上下文 (當前語句),判斷當前場景是否應該執行某幾個插件,以及參數是什麼,並返回一個特殊的響應,將結果返回到客戶端
- 模型本身只是返回各種 "文本"
- 當客戶端 (如 CherryStudio、NextChat、openwebui) 觀察到模型返回了某種特殊的響應文本,客戶端就執行模型響應文本中告知的插件,當然,客戶端可以完全無視模型的特殊響應
一個簡易的流程如下
FunctionCall#
以獲取本地天氣為例子
請求結構如下:
通過 functions
或 tools
(最新的 functions
的別名) 告知了模型,當前客戶端具備獲取天氣的能力
{
"messages": [
{
"role": "system",
"content": "你是一個有幫助的助手。"
},
{
"role": "user",
"content": "今天上海天氣怎麼樣?,濕度怎麼樣?"
}
],
"functions": [
{
"name": "get_localtion_weather",
"description": "get_localtion_weather,獲取某個地點的當前天氣情況",
"parameters": {
"type": "object",
"properties": {
"localtion": {
"type": "string",
"description": "localtion,地點"
},
"need_humidity":{
"type":"boolean",
"description":"是否返回濕度,默認為false"
}
},
"required": [
"localtion"
]
}
}
],
"function_call": "auto",
"temperature": 0.5,
"stream":false,
"model": "gpt-4o"
}
curl --location 'https://api.xxxxx.com/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer sk-xxxxx' \
--data '{
"messages": [
{
"role": "system",
"content": "你是一個有幫助的助手。"
},
{
"role": "user",
"content": "今天上海天氣怎麼樣?,濕度怎麼樣?"
}
],
"functions": [
{
"name": "get_localtion_weather",
"description": "get_localtion_weather,獲取某個地點的當前天氣情況",
"parameters": {
"type": "object",
"properties": {
"localtion": {
"type": "string",
"description": "localtion,地點"
},
"need_humidity":{
"type":"boolean",
"description":"是否返回濕度,默認為false"
}
},
"required": [
"localtion"
]
}
}
],
"function_call": "auto",
"temperature": 0.5,
"stream":false,
"model": "gpt-4o"
}'
響應結構如下:
客戶端執行本地的 get_localtion_weather
函數
整體流程如圖所示 (下圖截取自 OpenAI 的文檔,翻譯來自沉浸式翻譯)
MCP#
簡單理解:functionCall 是大家自己寫自己的,沒有一種統一的約定,而 MCP 是一種君子約定,mcpServer (查詢天氣插件) 遵循 MCP 協議開發,由 mcpClient (Cursor) 調用,原本需要自己寫函數,現在變成了調用別人的庫
MCP 重點在於 MCP 客戶端 (Cherry Studio
) 如何發現 MCP 服務端 ("插件")、理解 “插件” 具備的能力、調用 “插件”、獲取 “插件” 的響應結果
至於
- 將當前具備的插件功能發送到模型 (functions (別名 tools) 描述方式、提示詞方式)
- MCP 客戶端 (
Cherry Studio
) 如何根據模型的響應判斷執行是否執行 “插件”,執行那幾個插件,則是客戶端自己定義 - MCP 客戶端將插件執行結果返回給模型,也是可以自己定義
以下部分只是在應用領域領域,舉例描述了結合 MCP 對話流程,並沒有對 MCP 這個 “君子約定” 做具體的詳解
Cherry Studio
舉例#
配置 mcpServers 如下,其中只有一個獲取 和風天氣
的 server
源自:HeFeng Weather MCP Server | Glama
{
"mcpServers": {
"hefeng-weather": {
"isActive": true,
"command": "npx",
"args": [
"hefeng-mcp-weather@latest",
"--apiKey=key-123132131321"
]
}
}
}
對話如下
- 查看本地攔截的第一次請求,可以發現是通過 tools 描述的方式,告訴模型,本地具備那些 “插件” 以及具備什麼能力
{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "今天上海天氣怎麼樣?"
}
],
"temperature": 0.7,
"max_tokens": 2000,
"stream": true,
"tools": [
{
"type": "function",
"function": {
"name": "fd71edc4f65924613b9fd8330e78eb243",
"description": "獲取中國國內的天氣預報",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "逗號分隔的經緯度信息 (e.g., 116.40,39.90)"
},
"days": {
"type": "string",
"enum": [
"now",
"24h",
"72h",
"168h",
"3d",
"7d",
"10d",
"15d",
"30d"
],
"description": "預報天數,now為實時天氣,24h為24小時預報,72h為72小時預報,168h為168小時預報,3d為3天預報,以此類推"
}
}
}
}
}
]
}
- 查看第一次響應,模型判斷是否執行觸發調用插件。
模型判斷執行需要用到 "天氣插件",模型本身只是做了判斷
- MCP 客戶端 (
Cherry Studio
) 執行 “天氣插件”,可以簡單看作調用了一个別人寫好的包或 API - 將執行結果返回給模型,也就是加入對話上下文
{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "今天上海天氣怎麼樣?"
},
{
"role": "assistant",
"tool_calls": [
{
"id": "call_M4eYNv6oPaLunpZLe1iWdfiK",
"function": {
"name": "fd71edc4f65924613b9fd8330e78eb243",
"arguments": "{\"days\":\"now\",\"location\":\"121,31\"}"
},
"type": "function"
}
]
},
{
"role": "tool",
"content": "[{\"type\":\"text\",\"text\":\"地點: 121,31\\n觀測時間: 2025-03-27T16:51+08:00\\n天氣: 陰\\n溫度: 13°C\\n體感溫度: 12°C\\n風向: 東北風\\n風力: 1級\"}]",
"tool_call_id": "call_M4eYNv6oPaLunpZLe1iWdfiK"
}
],
"temperature": 0.7,
"max_tokens": 2000,
"stream": true,
"tools": [
{
"type": "function",
"function": {
"name": "fd71edc4f65924613b9fd8330e78eb243",
"description": "獲取中國國內的天氣預報",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "逗號分隔的經緯度信息 (e.g., 116.40,39.90)"
},
"days": {
"type": "string",
"enum": [
"now",
"24h",
"72h",
"168h",
"3d",
"7d",
"10d",
"15d",
"30d"
],
"description": "預報天數,now為實時天氣,24h為24小時預報,72h為72小時預報,168h為168小時預報,3d為3天預報,以此類推"
}
}
}
}
}
]
}
- 模型結合上下文 (發送的對話歷史) 進行響應
截取其中一部分
Cherry Studio
是通過 functionCall 的方式,判斷應該執行那些 “插件” 的功能
自定義協議 (使用系統提示詞的方式)#
你是一個智能助手,你具備MCP功能,MCP可以理解為一種本地功能插件,當用戶的語句需要調用插件時,你應該嚴格按照以下規定返回,規定如下:
<plug>
<pn>插件名稱</pn>
<fn>函數名稱(功能名稱)</fn>
<arg1>參數</arg1>
<arg2>參數2<arg2>
<arg3>參數3<arg3>
<plug/>。
當本地執行了某插件後,結果回按照以下格式返回
<tool_res>
<plug>
<pn>插件名稱</pn>
<fn>函數名稱(功能名稱)</fn>
<res>執行結果<res/>
<plug/>
<tool_res/>
當前本地插件:
1.插件名稱:get_localtion_weather
描述:查詢某個地點天氣插件
功能:
- query_now_weather:
args:
location:string,必需的,查詢地點
need_humidity:boolean,非必需的,默認為false,是否返回濕度
圖中所示為 ChatBox
,其他的客戶端會對 <xx><xx/>
進行處理,顯示不出來