↓推薦關注↓
2024年底,Anthropic釋出了 MCP協議。Anthropic就是釋出了Claude系列模型的公司(現在gpt基礎模型不更新還退步,claude真的很棒)
除去官方的各種美化和包裝,這到底是什麼?我大膽說一說:這其實是另一種形式的
Function Calling
一、簡單解釋 Function Calling
大模型可以看作在一個封閉的“盒子”裡,無法即時獲取外部資訊。為了讓大模型獲取外部資料,我們可以提供一些“方法”,例如:
方法:獲取天氣需要傳入的引數:經度、緯度返回結果:空氣質量、溫度、溼度...
在提問時,我們攜帶一個方法列表,裡面寫著各種方法。大模型決定呼叫某個方法時,會輸出方法名和引數;該方法在本地執行,並將結果返回給大模型。
二、快速開始
簡介
模型上下文協議 (MCP) 是一種開放協議,可實現 LLM 應用與外部資料來源和工具之間的無縫整合。
GitHub地址(https://github.com/modelcontextprotocol](https://github.com/modelcontextprotocol)
在此處我們還是跳開這些枯燥的理論,直接上手官方案例(有條件的小夥伴可以親自試試!)
我是Mac環境、Python語言(TS也支援)
(一)安裝包管理器 – uv
執行以下命令安裝 uv:
curl -LsSf https://astral.sh/uv/install.sh | sh
提示:安裝後需重啟終端。如果環境變數寫入失敗,手動修改~/.zshrc
:export PATH="$HOME/.local/bin:$PATH"
吐槽:官方居然選了個剛釋出不久的依賴管理工具 uv,坑點一堆。我後續探索下給換成poetry版本的吧
(二)初始化專案
以下是完整步驟:
# 建立專案uv init weathercd weather# 建立虛擬環境uv venvsource .venv/bin/activate# 安裝依賴uv add mcp httpx# 刪除示例檔案rm hello.py# 建立檔案mkdir -p src/weathertouch src/weather/__init__.pytouch src/weather/server.py
(三)編寫程式碼
1. 修改 pyproject.toml
在
pyproject.toml
尾部新增以下內容:[build-system]requires = [ "hatchling",]build-backend = "hatchling.build"[project.scripts]weather = "weather:main"
2. 編寫 __init__.py
檔案路徑:
src/weather/__init__.py
from . import serverimport asynciodefmain():"""Main entry point for the package.""" asyncio.run(server.main())# Optionally expose other important items at package level__all__ = ['main', 'server']
3. 編寫 server.py
檔案路徑:
src/weather/server.py
from typing import Anyimport asyncioimport httpxfrom mcp.server.models import InitializationOptionsimport mcp.types as typesfrom mcp.server import NotificationOptions, Serverimport mcp.server.stdioNWS_API_BASE = "https://api.weather.gov"USER_AGENT = "weather-app/1.0"server = Server("weather")@server.list_tools()asyncdefhandle_list_tools() -> list[types.Tool]:return [ types.Tool( name="get-alerts", description="Get weather alerts for a state", inputSchema={"type": "object","properties": {"state": {"type": "string","description": "Two-letter state code (e.g. CA, NY)", }, },"required": ["state"], }, ), types.Tool( name="get-forecast", description="Get weather forecast for a location", inputSchema={"type": "object","properties": {"latitude": {"type": "number","description": "Latitude of the location", },"longitude": {"type": "number","description": "Longitude of the location", }, },"required": ["latitude", "longitude"], }, ), ]@server.call_tool()asyncdefhandle_call_tool( name: str, arguments: dict | None) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:ifnot arguments:raise ValueError("Missing arguments")if name == "get-alerts":return [ types.TextContent( type="text", text="氣溫38,溼度60%" ) ]elif name == "get-forecast":return [types.TextContent( type="text", text="氣溫18,溼度10%" )]else:raise ValueError(f"Unknown tool: {name}")asyncdefmain():asyncwith 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
三、使用 Claude for Desktop 測試
第二章我們就完成了程式碼部分,接下來就要看效果
我前面說:MCP 是 Function Calling 的另一種實現。因此需要一個大模型主動呼叫。這裡我們使用 Claude for Desktop,它可以作為測試客戶端(不是唯一的,你也可以用vscode搭建一個客戶端)
Claude for Desktop 下載連結(https://claude.ai/download)
修改配置檔案
將第二章寫的服務註冊到 Claude for Desktop:
vim ~/Library/Application Support/Claude/claude_desktop_config.json
新增如下內容:
{"mcpServers": {"weather": {"command": "uv", //缺少環境變數的話可以寫絕對路徑"args": ["--directory","/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",# 目錄記得改"run","weather" ] } }}
儲存後,重啟 Claude for Desktop。
測試 MCP 工具
重新開啟 Claude 後,點選工具欄中的錘子圖示:


基於可以看到我們實現的工具了:


輸入問題,即可看到 Claude 呼叫本地服務並返回答案:


四、原理解讀
(一)過程分析
-
我們向 Claude 提問; -
Claude 分析可用工具並決定呼叫某個工具; -
客戶端(Claude for Desktop)透過 MCP 協議呼叫工具; -
結果返回給 Claude; -
Claude 根據結果生成答案。
(二)程式碼核心
程式碼的核心功能集中在以下兩部分:
# 列出工具,供 LLM 選擇@server.list_tools()asyncdefhandle_list_tools() -> list[types.Tool]:# 執行方法,解析並處理 LLM 呼叫請求@server.call_tool()asyncdefhandle_call_tool( name: str, arguments: dict | None) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
注: 示例程式碼中handle_call_tool
返回固定回覆,是因為原版呼叫美國國家氣象資料局 API,配置較麻煩。實際使用時,可替換為真實 API。
更多問題可參考官方 故障排除文件(https://modelcontextprotocol.io/quickstart#troubleshooting)。
那麼到這兒其實就基本能看明白了,後續深入會視情況再推進。