MCP(https://github.com/modelcontextprotocol)
MCP(模型上下文協議) 是一種專為 基于LLM的工具調用外部工具而設計的協議 ,
本質上是 LLM ? 工具之間的RPC(遠程過程調用) 的一種安全且一致的處理方式,
是一種 輕量級的JSON-RPC標準 。
我是韓國人,不是中國人。但最近在韓國,如果不使用MCP,就會被認為是跟不上潮流的人,MCP非常火熱。我的博客雖然喜歡寫大多數人能享受的編程理論文章,但由于理論文章的資料整理與驗證需要耗費大量時間,再加上最近因為體力勞動沒有太多時間,并且考慮到概念理解上Python非常適合,因此我打算用Python的FastMCP快速實現一個MCP。
1.一般來說,MCP結構如下所示:
[用戶提示]
↓
[LLM]
↓
生成 "tool_call" (MCP)
↓ [
工具服務器執行(如FastMCP等)]
↓
生成MCP響應 → 傳遞給LLM
↓
LLM生成最終響應
2.MCP協議格式
實際上,MCP = JSON-RPC 2.0的子集
(即遵循JSON-RPC標準,但僅提供MCP特定的工具調用方式)
MCP字段 | 說明 |
---|---|
| "2.0"(固定值) |
| 要調用的工具名稱 |
| 傳遞給工具的參數(字典形式) |
| 調用標識符(自動遞增等) |
| 工具的執行結果 |
基本結構
{"jsonrpc": "2.0","id": 1,"method": "tool_name","params": {"argument1": "value1","argument2": 42}
}
2. 核心組成部分
1.?tool_call
(Claude → MCP服務器: 請求消息 )
當Claude判斷需要調用工具時,會向MCP服務器發送以下的JSON-RPC 2.0請求消息 。
// Claude -> MCP服務器 (請求示例)
{"jsonrpc": "2.0","id": 123, // 請求標識符(由Claude生成,與響應匹配)"method": "search_nature_articles", // 調用的工具(函數)名稱"params": { // 將傳遞給工具(函數)的參數(字典形式)"keyword": "quantum computing","max_results": 3 // 示例:附加參數}
}
2.?MCP Server
(本地或遠程工具執行器)
- Claude Desktop會在本地運行配置好的MCP服務器。
- 必須注冊
tool_name
(即method
字段值),并將其綁定到可執行函數。 - 在Python中,FastMCP可以輕松實現這一點。
@mcp.tool()
def search_nature_articles(keyword: str, max_results: int = 3): # 與params匹配...
3.?MCP Response
(MCP服務器 → Claude: 響應消息 )
- 工具(函數)在MCP服務器上執行后,其結果將以JSON-RPC 2.0響應消息 的形式返回給Claude。包括成功或失敗(錯誤)兩種情況。
// MCP服務器 -> Claude (成功響應示例)
{"jsonrpc": "2.0","id": 123, // 必須與請求消息中的id相同"result": "'quantum computing'相關論文3篇搜索結果:\n1. Title A...\n..." // 工具執行結果(字符串、數字、列表、對象等均可)
}
// MCP服務器 -> Claude (錯誤響應示例)
{"jsonrpc": "2.0","id": 123, // 與請求id相同(如果無法識別,也可以為null)"error": { // 發生錯誤時包含'error'對象而不是'result'"code": -32000, // 示例:服務器錯誤代碼"message": "Springer Nature API密鑰認證失敗" // 錯誤消息}
}
為什么需要MCP?
用表格總結如下:
問題 | MCP的解決方案 |
---|---|
LLM無法執行代碼 | 通過調用外部工具解決 |
結構化輸入/輸出困難 | 使用JSON-RPC實現一致的參數傳遞 |
工具錯誤處理困難 | 提供明確的錯誤響應 |
工具增多導致結構復雜 | 基于名稱的路由 + 分離的服務器架構解決 |
要素 | 內容 |
協議名稱 | MCP(模型上下文協議) |
技術基礎 | JSON-RPC 2.0 |
目標 | 讓LLM能夠安全地調用外部工具并接收響應 |
執行方式 | 在本地服務器或本地進程中運行MCP兼容服務器 |
典型實現 | FastMCP(Python),server-filesystem(JS) |
通信對象 | Claude Desktop / Claude API |
本文將指導如何快速在 VS Code 環境中設置開發 Claude MCP 系統的步驟。
這是使用 FastMCP 構建 MCP 服務器并運行基于 Python 的工具所需的配置。
FastMCP 是一個完整的 Claude 專用 MCP 工具服務器實現。
FastMCP (Python) 不直接打開端口
-
FastMCP 不會直接打開 TCP 套接字或 HTTP 服務器。
-
相反,它通過
stdio
(標準輸入輸出)與 Claude Desktop 進行通信 。 -
換句話說,Claude 內部會以
stdin/stdout
的方式啟動 MCP 進程來進行通信。
通常,許多示例中會有以下結構:
mcp_server.py
mcp_client.py
這種結構僅用于練習或調試 JSON-RPC 協議,但并不會與 Claude 實際集成(僅用于測試目的)。
因此,為了實現與 Claude 的實際集成,使用 FastMCP 是最簡單的方法之一。接下來我們將使用 FastMCP 實際構建一個 MCP。
總結
- FastMCP 是專為 Claude 設計的輕量級工具,避免了復雜的網絡設置。
- 它通過標準輸入輸出 (
stdin/stdout
) 與 Claude 桌面版通信。 - 使用 FastMCP 可以更高效地完成實際的 MCP 開發和集成。
1. 安裝 VS Code
-
訪問 https://code.visualstudio.com
-
下載并運行與操作系統對應的安裝文件。
2. 安裝 VS Code 及擴展
啟動 VS Code 后,在左側的擴展(Extensions)選項卡中搜索并安裝以下內容:
-
Python (
ms-python.python
) -
(可選)Pylance、IntelliCode(用于增強自動補全功能)
3. 創建并打開項目文件夾
- 在計算機上創建一個項目文件夾。在我的情況下,我將其命名為
PaperPort
。
4. 虛擬環境設置
- 在 VSCode 菜單中選擇 終端(Terminal) -> 新建終端(New Terminal),即可在 VS Code 內打開終端。
- 在終端中輸入以下命令,創建一個名為
.venv
的虛擬環境
python -m venv .venv
# 或者 python3 -m venv .venv (根據系統不同)
一定要用 '.venv' 嗎? : venv
模塊本身對虛擬環境文件夾的名稱沒有特別限制。你可以使用任何你想要的文件夾名稱 。不過,如果文件夾名稱前加了點(.),在 Linux 或 macOS 等 Unix 系統中會被視為隱藏文件夾,而 .venv
是一種常見的命名約定。
激活虛擬環境 : 創建虛擬環境后,你需要將其“激活”才能使用。根據終端類型不同,激活命令略有差異。
- Windows (PowerShell):
-
.\.venv\Scripts\Activate.ps1
- Windows (Command Prompt - cmd):
-
.\.venv\Scripts\activate.bat
- macOS / Linux (bash/zsh):
-
source .venv/bin/activate
實際上,查看
.venv
文件夾中的文件并執行相應的文件會更快。在我的情況下,生成了activate.bat
文件,因此我執行了該文件。5. 設置所需的庫
根據我對
fastmcp
示例的搜索結果,requests
庫也是必需的,因此可以一起安裝。創建
requirements.txt
文件: 將安裝的庫列表保存到文件中,這樣以后在其他環境中可以輕松地進行相同的設置,或者與他人共享。由于我的環境可能會有所不同,因此我會創建這個文件。使用
requirements.txt
安裝依賴的命令:pip install -r requirements.txt
6. 獲取 API 密鑰
- 創建一個
.env
文件。.env
是環境變量文件,用于連接實際的密鑰。 - 直接將密鑰寫入 Python 文件的方式存在安全問題。
6-1. Claude API 訪問方法
訪問 https://www.anthropic.com/api?。
創建密鑰。
由于我的密鑰是私人的,為了不展示,我特意創建了一個新賬戶。
訪問 https://dev.springernature.com/?并創建密鑰。
同樣,我的密鑰不會展示。
7. 編寫 MCP 工具代碼
- 在項目文件夾中創建一個以
.py
結尾的 Python 文件。 - 我們的目標是創建一個 Nature 論文搜索工具,因此命名為
tool_nature.py
。
from fastmcp import FastMCP
import requests
from urllib.parse import urlencode
import os
from dotenv import load_dotenv
import sys# 加載環境變量
load_dotenv()# 初始化 MCP 實例
mcp = FastMCP("Nature API Tool Server")# 定義常量
BASE_URL = "http://api.springernature.com/metadata/json"
API_KEY = os.getenv("NATURE_API_KEY")# 如果沒有 API 密鑰則立即退出
if not API_KEY:print("[FATAL] 環境變量 'NATURE_API_KEY' 未設置。", file=sys.stderr)raise RuntimeError("[CRITICAL] 環境變量 'NATURE_API_KEY' 未設置。請在 .env 或系統環境中注冊密鑰。")@mcp.tool()
def search_nature_articles(keyword: str, max_results: int = 3) -> str:"""使用 Nature(Open API)根據給定的關鍵字搜索論文標題和摘要。結果將以摘要形式返回。"""query_params = {"q": keyword,"api_key": API_KEY,"p": max_results}try:response = requests.get(f"{BASE_URL}?{urlencode(query_params)}")response.raise_for_status()data = response.json()records = data.get("records", [])if not records:return f"未找到關于 '{keyword}' 的結果。"output_lines = [f"\n 搜索結果: {keyword}"]for i, article in enumerate(records):title = article.get("title", "無標題")# 摘要類型安全處理abstract_raw = article.get("abstract", "無摘要")if isinstance(abstract_raw, dict):abstract = abstract_raw.get("p", "無摘要")else:abstract = abstract_rawurl_list = article.get("url", [])url = url_list[0].get("value") if url_list else "N/A"abstract_summary = (abstract[:400] + "...") if len(abstract) > 400 else abstractoutput_lines.append(f"\n{i+1}. {title}\n ? URL: {url}\n ? 摘要: {abstract_summary}")return "\n".join(output_lines)except requests.exceptions.RequestException as e:print(f"[ERROR] API 請求時發生錯誤: {e}", file=sys.stderr)return f"[ERROR] API 請求時發生錯誤: {e}"except Exception as e:print(f"[ERROR] 數據處理時發生錯誤: {e}", file=sys.stderr)return f"[ERROR] 數據處理時發生錯誤: {e}"# 啟動 MCP 服務器if __name__ == "__main__":# --------------------------------------------------------------------------# [重要] 下面的 print 語句中的 'http://localhost:3333' 地址相關說明:# 1. 該地址僅為示例,不是實際的 FastMCP 服務器訪問地址。# 2. 當使用 Claude Desktop 執行此腳本作為 MCP 服務器時,# ? ?FastMCP 不使用網絡端口(HTTP),# ? ?而是通過 stdio(標準輸入輸出)與 Claude Desktop 進行通信。# 3. 因此無法直接訪問 'http://localhost:3333'。# 4. 該地址僅供參考,假設將來使用 FastAPI 構建網絡服務器或擴展時,# ? ?可將其視為占位符或示例。# --------------------------------------------------------------------------print(" 正在啟動 Nature 工具服務器... http://localhost:3333")mcp.run()
7-1 ## .vscode/launch.json 示例(用于調試)
{"version": "0.2.0","configurations": [{"name": "運行 MCP 工具","type": "python","request": "launch","program": "${workspaceFolder}/tool_nature.py","envFile": "${workspaceFolder}/.env"}]
}
8. 配置 MCP 服務器
配置通過修改 claude_desktop_config.json
文件進行。
可以在以下路徑創建該文件:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json
- MacOS:
~/Library/Application Support/Claude/claude_desktop_config.json
或者: 點擊 Claude 桌面左上角菜單 - 文件 - 設置 - 開發者 - 編輯配置按鈕。
8-1. 手動注冊 MCP 服務器(修改配置文件 claude_desktop_config.json
)
Claude Desktop 可以通過配置文件手動注冊 MCP 服務器。
(示例是我的文件路徑。)
{"mcpServers": {"nature": {"command": "Python 路徑","args": ["py 文件所在的路徑"]}}
}
運行 tool_nature.py
?
9. 啟動
首先需要在 VSCode 中運行 py 腳本。
然后可以在 Claude 桌面開發者界面看到正在運行的狀態。
10. 現在可以做的事
摘要總結
Call tool search_nature_articles with keyword="感興趣的領域關鍵詞"
URL 返回
search_nature_articles(keyword="感興趣的領域關鍵詞")
獲取兩篇相關論文,并返回其摘要和 URL。
Bouns: 如果想在 "localhost:3333" 端口上通過 HTTP 接收請求,該怎么做?
這需要使用 FastAPI、Flask、aiohttp 等單獨啟動服務器 ,而不是使用 FastMCP
:
from fastapi import FastAPI
from fastmcp import MCPMiddlewareapp = FastAPI()
app.add_middleware(MCPMiddleware, tools=[...])# 這樣 FastAPI 就會在 http://localhost:3333 端口上監聽請求
→ 這種方式適用于使用 transport="sse"
的情況。
→ 當前的 FastMCP
默認不使用這種方式。
平時上傳的文章性質與以往有很大的不同,因此感到有些遺憾。
我的博客文章通常面向所有語言的使用者,但最近發表了一些針對特定語言的內容,對此我感到對欣賞本博客的所有讀者有些抱歉。
最近因為忙於工地工作,沒有時間撰寫理論性的文章。
對期待我的讀者們表示歉意。