用 Python 開發 MCP 服務很簡單,完整案例拿走不謝!
模型上下文協議 MCP 是一種開放協議,旨在標準化 AI 應用程序與外部數據源和工具的連接方式。其核心目標在於簡化大型語言模型 LLM 與各種上下文和工具的集成,從而解決將多種 LLM 與多種工具相集成的複雜性問題。
但你有沒有想過,自己動手打造一個 MCP 服務呢?想象一下,親手設計一個智能工具,無論是處理數據、調用外部 API,還是生成自定義報告。這種創造力和掌控力的體驗,會不會更香呢?
MCP 本身是一個通用的協議,設計上是爲了跨語言和跨平臺的,因此可以使用各種語言來編寫服務,比如常用的 Node.js
。但如果不熟悉 Web 開發,也想自己寫一寫呢?Python 自然是不二之選。只是 MCP 具體的協議挺複雜的,很難快速上手。
不過,現在好了,因爲有了 FastMCP,它是一個 Python 軟件開發工具包 (SDK),專門設計用於簡化構建 MCP 服務的過程。它提供了一個高級且符合 Python 語言習慣的接口,用於定義工具、資源和提示。FastMCP 的核心優勢在於其能夠幫助開發者更輕鬆地創建符合 MCP 規範的服務,而無需深入瞭解底層的協議細節。
但值得注意的是,你看網上代碼會涉及兩個 FastMCP 包,其中一個是,
https://github.com/jlowin/fastmcp
另一個則是官方的,
https://github.com/modelcontextprotocol/python-sdk
這兩個什麼關係呢?其實是官方收編了上面第一個包,但官方集成的是 fastmcp 的 v1.0 版本。然而,jlowin 繼續開發 fastmcp,還發布了 v2.0 版本,其中包含代理和客戶端採樣等新功能。
使用的話這兩個都可以,先看第一個的安裝和導入,
pip install fastmcp
from fastmcp import FastMCP
官方的安裝和導入如下所示,
pip install mcp
from mcp.server.fastmcp import FastMCP
本文使用官方 Python SDK 裏的 FastMCP 來構建自己的 MCP 服務。
我們先來看一個最簡單的例子。
./demo/server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Demo 🚀")
@mcp.tool()
def add_2_numbers(a: int, b: int) -> int:
"""兩個數字相加"""
return a + b
if __name__ == "__main__":
mcp.run(transport='stdio')
這個例子展示瞭如何使用 FastMCP 庫來創建一個簡單的 MCP 服務器,它提供一個基本的工具(工具名:add_2_numbers
),用於兩個數字相加。這是一個非常簡單的入門示例,適合理解 MCP 服務器的工作原理和 FastMCP 的基本用法。
-
首先,從
mcp.server.fastmcp
模塊中導入了 FastMCP 類。接着,創建了一個 FastMCP 類的實例,命名爲 mcp。FastMCP 是服務器的核心類,它負責管理工具、資源和通信。參數「Demo 🚀」是服務器的名稱,用於標識這個 MCP 服務器。 -
然後,
@mcp.tool()
是一個裝飾器(decorator
),它告訴 FastMCP 將add_2_numbers
函數註冊爲一個可供客戶端調用的工具。文檔字符串("""兩個數字相加"""):這是函數的描述,客戶端(如MCP Inspector
)會顯示這個描述,幫助用戶理解工具的功能。 -
這個工具可以被外部客戶端調用,例如通過 MCP 協議發送請求,傳入兩個整數 a 和 b,服務器會返回它們的和。例如,如果客戶端調用
add_2_numbers(3, 5)
,服務器會返回 8。 -
mcp.run(transport='stdio')
啓動 MCP 服務器,進入監聽狀態,等待客戶端的連接和請求。transport='stdio'
指定了通信方式爲標準輸入輸出(Standard I/O
)。這意味着服務器通過命令行的標準輸入(stdin)和標準輸出(stdout)與客戶端通信,適合本地開發和測試。如果需要遠程通信,可以更改爲其他傳輸方式(如'sse'
,Server-Sent Events
)。
運行效果:
運行 python ./demo/server.py
,服務器會啓動並監聽 stdio。任何支持 MCP 協議的客戶端(例如 MCP Inspector
或 Claude Desktop
)都可以連接到它,調用 add_2_numbers
工具。
比如,可以通過 MCP Inspector
測試一下這個工具。
% mcp dev ./demo/server.py
Need to install the following packages:
@modelcontextprotocol/inspector@0.8.2
Ok to proceed? (y) y
瀏覽器中打開 http://127.0.0.1:6274
,可以測試一下上面這個 mcp 服務裏提供的 tool。
這個 mcp 過於簡單,咱們就不安裝來用了。下面我們手擼一個稍微複雜一點的 mcp 服務,並安裝上真正使用起來。
記賬 mcp 服務
我們基於 MCP 開發了一個輕量級(玩具級)記賬服務 Money Track MCP
,旨在幫助用戶管理和跟蹤財務數據。該服務利用 Python 和 FastMCP
框架,提供了三種核心功能類型(工具、資源和提示),爲用戶提供一個靈活、高效的解決方案來記錄收入和支出、查詢賬戶狀態以及生成格式化的財務報告。
項目雖小,但涉及環境變量的設置和讀取,用戶數據的存儲等多個方面,對於開發更強大服務來說是一個不錯的基礎。完整代碼的地址見文末。
核心功能
-
工具 (
@tool
):
服務提供了一個名爲record_transaction
的工具,允許用戶動態輸入當天的收入和支出,如「今天賺了 500 元,花了 250 元」。工具會自動更新累積的總收入、總支出,並計算當前餘額。這些數據持久化存儲在用戶指定的文件中,確保數據不會丟失。 -
資源 (
@resource
):
通過get_account_status
資源,用戶可以安全地檢索當前賬戶的最新狀態,包括總收入、總支出和餘額。資源數據存儲在 JSON 文件中,文件路徑可以由用戶通過環境變量或配置文件自定義,默認位於./accounting_data/accounting_data.json
。 -
提示 (
@prompt
):
format_account_report
提示負責將賬戶狀態格式化爲易讀的報告。
技術架構
-
框架:基於
FastMCP
,一個高效的 Python 庫,簡化了 MCP 服務器的開發。 -
存儲:數據保存在 JSON 文件中,支持用戶自定義存儲路徑(如通過環境變量
ACCOUNTING_WORKING_DIR
或配置文件)。 -
通信:默認使用標準輸入輸出 (
stdio
) 傳輸協議,方便本地開發和測試。 -
日誌:支持
INFO
和DEBUG
級別的日誌記錄,幫助開發者監控服務運行狀態和調試問題。
使用場景
MoneyTrack MCP
適用於多種場景,包括但不限於:
-
個人財務管理:個人用戶可以通過客戶端記錄日常收支,並隨時查看餘額。
-
企業 / 團隊記賬:小型企業或團隊可以集成此服務到更大的財務系統中,快速統計現金流。
-
教育與開發示例:開發者可以作爲 MCP 服務的學習示例,瞭解工具、資源和提示的協同工作。
具體代碼如下,
# ./src/server.py
from mcp.server.fastmcp import FastMCP
import os
import json
from typing import Dict, Optional
import logging
# 配置日誌
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 從環境變量或默認值獲取工作目錄
DEFAULT_WORKING_DIR = "~/accounting_data"
WORKING_DIR = os.getenv("ACCOUNTING_WORKING_DIR", DEFAULT_WORKING_DIR)
# 確保目錄存在
os.makedirs(WORKING_DIR, exist_ok=True)
# 數據文件路徑
DATA_FILE = os.path.join(WORKING_DIR, "accounting_data.json")
# 初始數據(如果文件不存在)
INITIAL_DATA = {
"total_income": 0,
"total_expense": 0,
"balance": 0
}
def load_data() -> Dict:
"""從文件中加載數據,如果文件不存在則創建默認數據"""
try:
if os.path.exists(DATA_FILE):
with open(DATA_FILE, "r", encoding="utf-8") as f:
return json.load(f)
else:
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(INITIAL_DATA, f, indent=4)
return INITIAL_DATA
except Exception as e:
logger.error(f"Failed to load data: {str(e)}")
return INITIAL_DATA
def save_data(data: Dict) -> None:
"""將數據保存到文件"""
try:
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
except Exception as e:
logger.error(f"Failed to save data: {str(e)}")
# 創建 MCP 服務器
mcp = FastMCP("money-track-mcp", log_level="ERROR")
# 工具:記錄收入和支出
@mcp.tool()
def record_transaction(income: Optional[int] = 0, expense: Optional[int] = 0) -> Dict:
"""記錄今天的收入和支出,更新賬戶餘額"""
ifnot isinstance(income, (int, float)) ornot isinstance(expense, (int, float)):
return {"error": "Income and expense must be numbers"}
data = load_data()
data["total_income"] += income
data["total_expense"] += expense
data["balance"] = data["total_income"] - data["total_expense"]
save_data(data)
return {
"message": "Transaction recorded successfully",
"total_income": data["total_income"],
"total_expense": data["total_expense"],
"balance": data["balance"]
}
# 資源:獲取當前賬戶狀態
@mcp.resource("accounting://status")
def get_account_status() -> Dict:
"""獲取當前賬戶的收入、支出和餘額"""
data = load_data()
return {
"total_income": data["total_income"],
"total_expense": data["total_expense"],
"balance": data["balance"]
}
# 提示:格式化賬戶報告
@mcp.prompt()
def format_account_report(status: Dict) -> str:
"""格式化賬戶狀態爲易讀的報告"""
returnf"""
=== 賬戶報告 ===
總收入: ${status["total_income"]:.2f}
總支出: ${status["total_expense"]:.2f}
當前餘額: ${status["balance"]:.2f}
================
"""
def run_server():
"""運行 MCP 服務器"""
print("=== Money Track MCP 服務啓動 ===")
logging.info("Money Track MCP 服務啓動")
print(f"當前工作目錄: {os.getcwd()}")
mcp.run(transport='stdio')
安裝和運行
git clone https://github.com/mathinml/mcp_money_track.git
cd mcp_money_track
pip install mcp
pip install .
打開你喜歡的 mcp 客戶端,比如 Cline
,Roo Code
, Cursor
等等。mcp 配置文件中請參考如下設置,
"money-track-mcp": {
"command": "/opt/anaconda3/bin/python",
"args": [
"-m",
"mcp_money_track"
],
"env": {
"ACCOUNTING_WORKING_DIR": "/Users/xyz/account"
}
},
環境變量 "ACCOUNTING_WORKING_DIR"
是用於設置賬本的保存目錄。
1、Cline
點擊 Approve 以後,
再次輸入:我今天收入才 500 元,花掉了 1500 元。
沒多說啥,它自動領會要記賬啦,請看結果。
打開保存目錄裏的賬本看一看,
2、Roo Code
然後在另一個客戶端裏試試,VS Code + 插件 Roo Code。
換套說辭,咱不提記賬不記賬,只跟它說:我想買個電腦,1 萬元左右,看看我的餘額還夠嗎?
點擊 Approve,如果覺得每次要點太煩人,也可以在 Auto-approve 裏設定總是允許。
餘額不夠啦,誰打賞一點讓我湊個整唄。
3、Cherry Studio
在 Cherry Studio 裏設置也是類似的,如圖。
然後,在聊天界面一定要在 MCP 服務器裏選中這個服務。
大模型這裏我們選用 OpenRoute 提供的免費 Gemini 2.5 Pro,
也還行,速度上感覺比前面兩個慢一丟丟。
好了,通過這個例子,應該已經明白如何使用 Python 來寫一個簡單但完整的 mcp 服務。
代碼:https://github.com/mathinml/mcp_money_track
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/g_A43tlarARXcWrcf8Hx-g