SynapseWire

從零打造 MCP Server:Python 實戰教學(2026 完整版)

手把手教你用 Python 建構 Model Context Protocol 伺服器,讓 AI Agent 串接真實世界的 API。從專案初始化到生產部署一次搞定。

作者: SynapseWire 編輯部 發布於:
終端機畫面顯示 MCP Server 程式碼,搭配 Python 標誌與 API 連線示意圖

Model Context Protocol(MCP)已經成為 AI Agent 與外部工具和資料來源溝通的標準協定。如果你正在使用 Claude Code 或 Cursor 這類 AI 編碼助手,你其實已經在使用 MCP 了——只不過你可能沒察覺。每當你的助手讀取檔案、搜尋網頁或查詢資料庫時,底層很可能就是透過 MCP Server 在運作。

自己動手寫一個 MCP Server,比你想像的簡單得多。這篇教學會帶你從零開始,用 Python 建一個完整可運作的 MCP Server,串接真實世界的 API,在本機跑起來,最後用 MCP Inspector 做測試。讀完之後,你會有足够的理解去為任何需要的 API 打造專屬的 MCP Server。

MCP 到底是什麼(以及為什麼重要)

MCP 是一套協定,用來定義 AI Agent 如何與外部工具溝通。你可以把它想成 AI 的 USB 埻:你不需要為每個 AI 框架寫客製化的整合程式,只要建好一個 MCP Server,就能與所有支援 MCP 的用戶端配合使用。

在 MCP 出現之前,如果你想讓 AI Agent 存取資料庫,你需要為每個 AI 框架各寫一套整合程式。OpenAI 需要一套、Anthropic 需要一套、Google 又需要一套。MCP 把這些統一了。你只要建一次 Server,到哪裡都能用。

架構很簡單。MCP Server 暴露三種東西:工具(tools,AI 可以呼叫的函數)、資源(resources,AI 可以讀取的資料)、以及提示(prompts,常見查詢的模板)。用戶端(你的 AI 助手)在執行時自動發現這些功能,按需使用。

這個分離很重要,因為它讓 AI 的邏輯與工具的邏輯各自獨立。AI 決定要幹嘛,MCP Server 決定怎麼做。兩邊不需要知道對方的細節。

專案設定

建立一個新目錄,設定 Python 專案:

mkdir mcp-weather-server
cd mcp-weather-server
python3 -m venv .venv
source .venv/bin/activate

安裝 MCP Python SDK:

pip install mcp

SDK 處理了所有協定層面的細節。你只需要用 Python 裝飾器定義你的工具和資源,SDK 會負責序列化、傳輸和錯誤處理。

建立主伺服器檔案:

touch server.py

專案結構就是這麼精簡。MCP Server 刻意設計得輕量。協定負責複雜度,你的程式碼只負責定義 Server 能做什麼。

建構伺服器

這是一個完整的 MCP Server,提供天氣資料查詢功能:

import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather-server")

NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-mcp-server/1.0"

async def make_nws_request(url: str) -> dict | None:
    """向 NWS API 發出請求,附帶正確的 headers。"""
    headers = {
        "User-Agent": USER_AGENT,
        "Accept": "application/geo+json",
    }
    async with httpx.AsyncClient() as client:
        response = await client.get(url, headers=headers, timeout=30.0)
        response.raise_for_status()
        return response.json()

def format_alert(feature: dict) -> str:
    """將天氣警報格式化為可讀文字。"""
    props = feature["properties"]
    return (
        f"事件:{props.get('event', '未知')}\n"
        f"區域:{props.get('areaDesc', '未知')}\n"
        f"嚴重程度:{props.get('severity', '未知')}\n"
        f"描述:{props.get('description', '無描述')}\n"
    )

@mcp.tool()
async def get_alerts(state: str) -> str:
    """取得美國某州的即時天氣警報。

    Args:
        state: 美國州的兩字母縮寫(例如 CA、NY、TX)
    """
    url = f"{NWS_API_BASE}/alerts?area={state}"
    data = await make_nws_request(url)

    if not data or not data.get("features"):
        return "此州目前沒有活躍的天氣警報。"

    alerts = [format_alert(f) for f in data["features"][:5]]
    return f"找到 {len(data['features'])} 筆警報,顯示前 5 筆:\n\n" + "\n---\n".join(alerts)

@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
    """取得指定位置的天氣預報。

    Args:
        latitude: 位置的緯度
        longitude: 位置的經度
    """
    points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
    points_data = await make_nws_request(points_url)

    if not points_data:
        return "無法取得此位置的預報資料。"

    forecast_url = points_data["properties"]["forecast"]
    forecast_data = await make_nws_request(forecast_url)

    if not forecast_data:
        return "無法取得預報。"

    periods = forecast_data["properties"]["periods"][:5]
    forecasts = []
    for period in periods:
        forecasts.append(
            f"{period['name']}{period['detailedForecast']}"
        )
    return "\n\n".join(forecasts)

if __name__ == "__main__":
    mcp.run()

這個 Server 暴露了兩個工具。第一個接收美國州的縮寫,回傳即時天氣警報。第二個接收經緯度座標,回傳五天預報。兩個都使用美國國家氣象局的 API,免費且無需 API Key。

關鍵模式是 @mcp.tool() 裝飾器。你寫一個帶有型別提示和 docstring 的 Python 函數,裝飾器就會把它註冊為 MCP 工具。docstring 變成 AI Agent 看到的工具描述,型別提示變成參數的 schema。AI 靠這些資訊來決定何時以及如何呼叫你的工具。

本地執行與測試

以 stdio 模式啟動伺服器(本地開發的預設模式):

python server.py

伺服器會啟動並在標準輸入/輸出上等待連線。這是大多數 MCP Server 在開發階段的運作方式。用戶端透過 stdin 傳送 JSON-RPC 訊息,伺服器透過 stdout 回應。

要測試它,你需要一個 MCP 用戶端。最簡單的選項是 MCP Inspector,一個基於瀏覽器的除錯工具:

npx @modelcontextprotocol/inspector python server.py

Inspector 會在瀏覽器中開啟,讓你瀏覽伺服器的工具、送出測試請求,並查看原始的 JSON-RPC 訊息。這是驗證伺服器是否正常運作的最快方式。

你也可以把它連接到 Claude Desktop,在 claude_desktop_config.json 中加入:

{
  "mcpServers": {
    "weather": {
      "command": "python",
      "args": ["/path/to/server.py"]
    }
  }
}

連線之後,Claude 就能在使用者詢問天氣時自動呼叫你的天氣工具。AI 負責決策,你的 Server 負責 API 呼叫。

加入資源和提示

工具不是 MCP Server 能暴露的唯一東西。資源提供 AI 可以讀取的資料,提示提供常見查詢的模板。

在你的 Server 中加入一個資源:

@mcp.resource("weather://alerts/stats")
async def get_alert_stats() -> str:
    """回傳目前警報的統計摘要。"""
    data = await make_nws_request(f"{NWS_API_BASE}/alerts?status=actual")
    if not data:
        return "無法取得資料。"

    features = data.get("features", [])
    severities = {}
    for f in features:
        sev = f["properties"].get("severity", "未知")
        severities[sev] = severities.get(sev, 0) + 1

    stats = "\n".join(f"  {k}{v}" for k, v in severities.items())
    return f"目前活躍警報總數:{len(features)}\n按嚴重程度分類:\n{stats}"

資源的運作方式與工具類似,但唯讀。AI 可以在沒有使用者明確授權的情況下存取它們,這讓它們非常適合提供上下文資訊,例如摘要、統計數據或設定資料。

加入一個提示模板:

@mcp.prompt()
def weather_report(state: str) -> str:
    """產生天氣報告的提示模板。"""
    return f"""分析 {state} 目前的天氣狀況。

1. 使用 get_alerts 工具檢查即時天氣警報
2. 取得該州三大城市的天氣預報
3. 彙整整體天氣概況
4. 重點標示任何嚴重天氣風險

報告格式要求:分段清楚,附帶可執行的建議。"""

提示是幫助使用者快速上手常見任務的模板。當使用者選擇一個提示時,AI 會收到模板文字,然後用你的工具來填入具體細節。

生產環境部署

本地 stdio 模式適合開發,但正式部署需要 HTTP 傳輸。MCP 支援 Server-Sent Events(SSE)用於遠端伺服器。

修改你的伺服器以支援 HTTP:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather-server")

# ... 你的工具和資源 ...

if __name__ == "__main__":
    import sys
    if "--sse" in sys.argv:
        mcp.run(transport="sse")
    else:
        mcp.run()

以 SSE 模式啟動:

python server.py --sse

伺服器現在會在 HTTP port 8000 上監聽。遠端的 MCP 用戶端可以透過你的伺服器 URL 連線。在正式環境中,建議在前面加上反向代理(nginx 或 Caddy),並啟用 HTTPS 和身份驗證。

需要容器化部署的話,加入一個 Dockerfile:

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY server.py .
EXPOSE 8000
CMD ["python", "server.py", "--sse"]

建構並執行:

docker build -t mcp-weather .
docker run -p 8000:8000 mcp-weather

錯誤處理與最佳實踐

MCP Server 必須優雅地處理錯誤。AI Agent 應該永遠收到有用的回應,即使出問題了也一樣。

工具一定要回傳字串回應,即使發生錯誤也不要例外。絕對不要讓例外傳播到用戶端。應該要捕捉錯誤,回傳描述性的訊息:

@mcp.tool()
async def safe_get_forecast(latitude: float, longitude: float) -> str:
    """帶錯誤處理的天氣預報查詢。"""
    try:
        points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
        points_data = await make_nws_request(points_url)
        if not points_data:
            return "錯誤:找不到這些座標的預報資料。請確認緯度和經度是有效的美國位置。"
        # ... 其餘邏輯
    except httpx.TimeoutException:
        return "錯誤:天氣服務回應較慢,請稍後再試。"
    except Exception as e:
        return f"錯誤:取得預報資料時發生意外問題。詳情:{str(e)}"

其他最佳實踐:

  • 工具描述要精確但簡潔。AI 靠這些來決定要呼叫哪個工具。
  • 所有參數都要使用型別提示。MCP SDK 用這些來產生參數 schema。
  • 外部 API 呼叫要設定合理的逾時時間。AI Agent 不應該無限等待。
  • 伺服器端要記錄錯誤以便除錯,但回傳給用戶端的訊息要是使用者友善的。
  • 要版本控制你的伺服器。在伺服器名稱中加入版本號,方便用戶端追蹤更新。

接下來可以做什麼

這篇教學涵蓋了用 Python 建構 MCP Server 的基礎。相同的模式適用於任何 API:資料庫查詢、檔案系統存取、外部服務整合,或客製化的商業邏輯。

MCP 生態系正在快速成長。modelcontextprotocol.io 上的官方 registry 已經列出數百個社群 Server。如果需要靈感,可以看看其他人如何為 GitHub、Slack、PostgreSQL 或 Google Drive 打造 Server。

MCP 真正的威力在於可組合性。一旦你有了 Server,任何支援 MCP 的 AI Agent 都能使用它。你不是在為某一個 AI 框架寫程式,你是在為所有框架寫程式。

從一個小而有用的工具開始。讓它跑起來,然後再加更多。協定會處理剩下的事。

分享文章

留言評論

0 則評論

暫無評論,搶先發表你的看法吧!

相關文章