開發實戰 2026-06-16

從 0 開發
MCP Server

若你是全端工程師或 Agent 平台負責人,常被要求「讓 AI 能查內部 API、讀專案檔案」,卻只有零散的 curl 腳本而沒有可重用的整合層,本文正是為你而寫。你將用 Python 與 FastMCP 從環境建置一路做到 Tools / Resources / Prompts 全模組實作MCP 對照 Function Calling 決策表ChromaDB 向量知識庫實戰,以及五步 Mac 隔離開發驗收清單。全文含對照表、可跟做的程式片段與常見錯誤排查流程。

2026 從零開發 MCP Server 建構 AI 工具呼叫能力架構與 FastMCP 實戰示意

01 · 引言:AI 缺工具,MCP 補缺口

2026 年的 Agent 已能寫程式、做多步推理,但沒有外部工具仍是封閉系統:它讀不到你 Git 倉庫最新的 PR 狀態,無法代你執行 SELECT * FROM orders WHERE status='pending',也不能在 Slack 裡 @同事。傳統做法是每家模型宿主各自實作 Function Calling,每個 SaaS 又要為 Claude、GPT、Gemini 寫一套轉接器——整合成本隨 N×M 線性爆炸。

MCP(Model Context Protocol) 由 Anthropic 於 2024 年 11 月開源,定位是「大模型與外部世界的 USB-C 接頭」:你實作一個符合規範的 Server,Cursor、Claude Desktop、OpenClaw 等 Host 都能載入,無須重複寫膠水程式。若你已讀過站內 MCP 為何成為 AI 時代的 HTTP 協定,本文是它的動手版——從 pip install mcp 到 Docker 上線,全程可跟做。

文章結構:三大開發痛點MCP 架構與 JSON-RPC 生命週期對照 OpenAI FC / LangChain 決策表Hello World → Tools → Resources → Prompts 遞進實作HTTP+SSE 部署ChromaDB 知識庫實戰Mac 隔離開發驗收

02 · 三大開發痛點

1. 每家宿主一套工具方言。 OpenAI 的 tools 陣列、Anthropic 的 tool_use 區塊、Google 的 Function Declaration——Schema 欄位名、錯誤回傳格式各不相同。把同一個「查訂單」能力接到三個宿主,往往要寫三份包裝層。MCP 把工具註冊、能力描述、呼叫語意統一到 JSON-RPC,Write Once, Run Everywhere

2. 本地憑證與權限邊界模糊。 MCP Server 常需讀檔案系統、調內網 API、持有 OAuth Token。在主力筆電混裝十幾個 Server 與多款 IDE,一次誤設就可能把正式環境 Key 寫進測試 cron。需要可丟棄的沙箱環境先驗收再上線。

3. 除錯鏈路長、錯誤難定位。 從 Host 發起到 Server 執行,中間經過 Client 轉發、STDIO 管道或 HTTP 長連線——任何一環設定錯誤都表現為「工具不可用」或「Connection closed」。沒有 Inspector 與單元測試,排查往往靠猜。

03 · 什麼是 MCP:架構與演進

從 Function Calling 到 MCP 的三段演進

第一階段(2023):Function Calling。 OpenAI 在 GPT-4 中引入工具呼叫,模型輸出 JSON 指定函式名與參數,由應用層執行。問題是 Schema 嵌在 Prompt 或閉源 SDK,無法跨宿主重用

第二階段(2024 初):Plugins / Actions。 ChatGPT Plugins、GPT Actions 把 HTTP 端點包裝成工具,降低了接入門檻,但仍是宿主私有生態,且依賴 OpenAPI 靜態描述,Agent 無法在執行時動態發現新 Server。

第三階段(2024 11 月至今):MCP。 Anthropic 發布開放規範與參考 SDK,Host / Client / Server 三層解耦,10,000+ 社群 Server 在 18 個月內湧現,OpenAI、Google、Microsoft 於 2026 年全線跟進。

Client-Server 架構與三大能力

┌─────────────────────────────────────────────────────────────┐
│  Host(Cursor / Claude Desktop / OpenClaw)                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │ MCP Client  │  │ MCP Client  │  │ MCP Client  │          │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘          │
└─────────┼────────────────┼────────────────┼─────────────────┘
          │ JSON-RPC       │ JSON-RPC       │ JSON-RPC
          ▼                ▼                ▼
   ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
   │ MCP Server A │ │ MCP Server B │ │ MCP Server C │
   │ Tools        │ │ Resources    │ │ Prompts      │
   │ Resources    │ │ Tools        │ │ Tools        │
   └──────────────┘ └──────────────┘ └──────────────┘
  • Tools(工具):模型可主動呼叫的函式,如 read_filequery_databasesend_http_request。帶 JSON Schema 輸入描述,回傳結構化或文字結果。
  • Resources(資源):模型可被動讀取的上下文,如設定檔、日誌片段、資料庫 schema 快照。透過 URI 識別(file:///project/README.md),由 Client 按需拉取。
  • Prompts(提示範本):預置的多輪對話範本,如「程式碼審查」「SQL 生成」,Host 可一鍵注入,減少重複 Prompt 工程。

JSON-RPC 2.0 與傳輸層

所有 MCP 訊息統一為 JSON-RPC 2.0。常見方法包括 initializetools/listtools/callresources/listresources/readprompts/listprompts/get

// 連線生命週期:initialize → initialized → 業務呼叫 → 關閉

// 1. Client 發起握手
{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "cursor", "version": "1.0" } } }

// 2. Server 回應能力集
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} }, "serverInfo": { "name": "my-server", "version": "0.1.0" } } }

// 3. 呼叫工具
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
  "params": { "name": "say_hello", "arguments": { "name": "MacDate" } } }

傳輸層兩種主流模式:STDIO(Host 以子程序拉起 Server,stdin/stdout 傳 JSON-RPC,適合本地開發)與 HTTP + SSE(遠端 Server、多租戶閘道,Client 透過 SSE 收 Server 推送)。2026 年規範還引入了 Streamable HTTP,進一步簡化雙向串流通訊。

04 · MCP vs OpenAI FC vs LangChain 對照表

選型時常見疑問:「我已有 OpenAI Function Calling,還要 MCP 嗎?」「LangChain Tool 夠不夠用?」下表從架構師視角對照三者:

維度 OpenAI Function Calling LangChain Tools MCP
定位 單模型宿主內建能力 Python 框架層工具抽象 跨宿主開放協定
發現機制 靜態 Schema 嵌入請求 程式碼內註冊,執行時列舉 執行時 tools/list(機讀)
跨 Host 重用 僅 OpenAI API / ChatGPT 需重寫各宿主轉接器 一次實作,多 Host 載入
Resources / Prompts 無原生支援 透過 Retriever / Template 模擬 協定級一等公民
傳輸 HTTP API 內嵌 程序內呼叫 STDIO / HTTP+SSE / Streamable HTTP
生態規模(2026 中) 宿主私有 數千 PyPI 整合 10,000+ Server
適用場景 純 OpenAI 棧快速驗證 自研 Agent 框架內編排 多 Host、企業 Catalog、長期維護

硬核數據快照: 採用 MCP 統一工具層的團隊,報告整合成本下降 38%–55%;同一 Server 接到 Cursor 與 Claude Desktop 的重複開發工作量減少約 70%;公網掃描顯示未授權暴露的 MCP Server 約 1,000+——部署前必須在隔離環境驗收權限邊界。

05 · 開發環境建置

Python vs TypeScript 選型

官方 SDK 涵蓋 Python(mcp)TypeScript(@modelcontextprotocol/sdk)。Python 側 FastMCP 裝飾器語法簡潔,適合資料工程與 AI 腳本;TypeScript 適合 Node 生態與前端團隊。本文以 Python + FastMCP 為主,TS 讀者可對照 SDK 文件平移概念。

虛擬環境與專案結構

mkdir my-mcp-server && cd my-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" pydantic httpx chromadb

建議目錄結構:

my-mcp-server/
├── server.py # FastMCP 入口
├── tools/ # 各工具模組
│ ├── calculator.py
│ ├── filesystem.py
│ ├── http_client.py
│ ├── database.py
│ └── datetime_tool.py
├── resources/ # Resource 處理器
├── prompts/ # Prompt 範本
├── tests/ # pytest 單元測試
├── pyproject.toml
└── Dockerfile

MCP Inspector、Cursor 與 Claude Desktop

MCP Inspector 是官方除錯 UI,可獨立連線 STDIO 或 HTTP Server,視覺化 tools/listtools/call

npx @modelcontextprotocol/inspector python server.py

Cursor~/.cursor/mcp.json(或專案級 .cursor/mcp.json)註冊 Server。Claude Desktop 使用 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)。二者格式類似,下文 Hello World 節給出完整範例。

06 · Hello World:第一個 MCP Server

用 FastMCP 實作最小可執行 Server,包含一個 say_hello 工具:

# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-server")

@mcp.tool()
def say_hello(name: str = "World") -> str:
    """向指定名稱打招呼。"""
    return f"Hello, {name}! MCP Server is running."

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

本地啟動與 Inspector 驗證:

python server.py
# 另開終端機
npx @modelcontextprotocol/inspector python server.py

在 Inspector 中點擊 ConnectList Tools → 呼叫 say_hello 並傳入 {"name": "MacDate"},應回傳問候語。

Cursor 設定範例

// ~/.cursor/mcp.json
{
  "mcpServers": {
    "hello-server": {
      "command": "/path/to/my-mcp-server/.venv/bin/python",
      "args": ["/path/to/my-mcp-server/server.py"]
    }
  }
}

Claude Desktop 設定結構相同,路徑改為上述 macOS 設定檔。重啟 Host 後,在對話中應能看到 say_hello 工具可用。

07 · Tools:五種典型工具實作

Tool 結構與 Pydantic 輸入驗證

FastMCP 用 Python 型別註解自動產生 JSON Schema。複雜參數可用 Pydantic BaseModel

from pydantic import BaseModel, Field

class CalcInput(BaseModel):
    expression: str = Field(description="數學運算式,如 2+3*4")

@mcp.tool()
def calculator(input: CalcInput) -> str:
    """安全計算器,僅允許數字與四則運算。"""
    import re
    if not re.match(r'^[\d\s+\-*/().]+$', input.expression):
        raise ValueError("非法字元")
    return str(eval(input.expression))

五種工具一覽

工具名 用途 關鍵實作
calculator 安全四則運算 正則白名單 + eval 沙箱
read_file 讀取工作區檔案 路徑正規化 + 根目錄約束
http_get 代理 HTTP 請求 httpx 非同步 + 逾時/網域白名單
query_db 唯讀 SQL 查詢 sqlite3 / asyncpg + 參數化
current_time 回傳指定時區時間 zoneinfo + ISO 8601 格式

檔案工具範例

from pathlib import Path

WORKSPACE = Path("/safe/workspace").resolve()

@mcp.tool()
def read_file(path: str) -> str:
    """讀取工作區內檔案內容。"""
    target = (WORKSPACE / path).resolve()
    if not str(target).startswith(str(WORKSPACE)):
        raise ValueError("路徑越界")
    return target.read_text(encoding="utf-8")

非同步工具與錯誤處理

IO 密集型工具應使用 async def,FastMCP 會自動排程:

@mcp.tool()
async def http_get(url: str) -> str:
    """GET 請求,5 秒逾時。"""
    import httpx
    async with httpx.AsyncClient(timeout=5.0) as client:
        try:
            resp = await client.get(url)
            resp.raise_for_status()
            return resp.text[:8000]
        except httpx.HTTPError as e:
            return f"HTTP 錯誤: {e}"

錯誤應回傳可讀文字而非裸拋例外(除非參數驗證失敗),便於模型在對話中向使用者解釋並重試。

08 · Resources:唯讀上下文

Resource vs Tool 的分工

Tool 是模型主動決策呼叫的動作(副作用:寫檔案、發 HTTP、改資料庫)。Resource 是模型按需讀取的上下文(無副作用:設定檔、schema 文件、日誌 tail)。Host 可在對話開始時預拉 Resource,減少 Token 浪費。

URI Scheme 與靜態/動態 Resource

  • 靜態 Resource:固定 URI,如 config://app/settings.json,內容相對固定。
  • 動態 Resource:URI 帶參數或使用 Resource Template,如 log://app/{date},內容隨請求變化。
  • 檔案系統 Server:官方 @modelcontextprotocol/server-filesystem 將目錄對應為 file:// Resource,適合唯讀暴露專案文件。
@mcp.resource("config://app/settings")
def get_settings() -> str:
    """回傳應用設定 JSON。"""
    import json
    return json.dumps({"env": "production", "debug": False})

@mcp.resource("schema://db/{table_name}")
def get_table_schema(table_name: str) -> str:
    """動態回傳指定表的 DDL。"""
    return f"CREATE TABLE {table_name} (...);"

09 · Prompts:可重用對話範本

Prompts 讓 Host 一鍵注入多輪對話結構,減少重複 Prompt 工程。與 Cursor 的 Agent Skill 互補:Skill 編排「何時用什麼能力」,MCP Prompt 提供「標準對話骨架」。

@mcp.prompt()
def code_review_prompt(language: str = "Python") -> str:
    """產生程式碼審查 Prompt 範本。"""
    return f"""你是一位資深 {language} 程式碼審查專家。請按以下結構審查使用者提交的程式碼:
1. 安全漏洞(SQL 注入、路徑遍歷、金鑰硬編碼)
2. 效能問題(N+1 查詢、阻塞 IO)
3. 可讀性與命名
4. 測試覆蓋建議
請用繁體中文輸出,每條發現附行號與修復建議。"""

多輪 Prompt 可透過回傳多條 Message 實作:FastMCP 支援 list[PromptMessage],第一條設 system 角色,後續設 user 角色,Host 按序注入對話歷史。

10 · HTTP 傳輸與安全

STDIO vs HTTP+SSE 對照

維度 STDIO HTTP + SSE Streamable HTTP(2026)
部署位置 本地子程序 遠端伺服器 / 容器 遠端,單端點雙向流
多 Client 共享 每 Host 獨立程序 多 Client 連同一 Server 同左,連線管理更簡
認證 程序級(誰啟動誰負責) Bearer Token / mTLS / OAuth 同 HTTP+SSE
適用場景 桌面 Host、敏感本地工具 企業內網、SaaS 閘道 新部署首選
負載平衡 不適用 需工作階段黏著 改進中

HTTP Server 啟動範例(FastMCP):

# 正式環境用 uvicorn 或 mcp 內建 HTTP 模式
mcp run server.py --transport streamable-http --port 8080

安全要點: 公網暴露的 MCP Server 必須啟用認證(Bearer Token 或 OAuth 2.1);工具層實施網域白名單、路徑沙箱、SQL 唯讀;稽核日誌記錄每次 tools/call 的參數與呼叫方。2026 年掃描顯示 1,000+ 未授權 Server 裸奔——切勿把內網 API Key 直接寫進無鑑權的 HTTP Server。

11 · 除錯測試與常見錯誤

MCP Inspector 工作流程

  1. Connect:選擇 STDIO 命令或 HTTP URL,確認 initialize 握手成功。
  2. List Tools / Resources / Prompts:核對能力集與 JSON Schema 是否符合預期。
  3. Call Tool:手動傳入參數,觀察回傳與錯誤訊息。
  4. Notifications:若 Server 支援進度推送,在此面板查看。
  5. Export Log:匯出 JSON-RPC transcript 供團隊複盤。

pytest 單元測試範例

# tests/test_tools.py
import pytest
from server import calculator

def test_calculator_basic():
    from server import CalcInput
    result = calculator(CalcInput(expression="2+3*4"))
    assert result == "14"

def test_calculator_rejects_injection():
    with pytest.raises(ValueError):
        calculator(CalcInput(expression="__import__('os')"))

常見錯誤對照表

現象 可能原因 排查步驟
Host 看不到工具 設定路徑錯誤、Python 非 venv 檢查 mcp.json 絕對路徑;Inspector 先驗證
Connection closed Server 啟動崩潰、stderr 污染 stdout 單獨執行 python server.py 看 traceback
tools/call 逾時 同步阻塞 IO、無逾時設定 改 async + httpx timeout;資料庫加 statement_timeout
HTTP 401 Token 缺失或過期 核對 Authorization 標頭;輪替 Key
Schema 驗證失敗 Pydantic 欄位名與模型輸出不符 Inspector 查看 tools/list 的 inputSchema

12 · 生產部署

Docker 打包

# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY . .
EXPOSE 8080
CMD ["mcp", "run", "server.py", "--transport", "streamable-http", "--port", "8080"]

雲端平台選型

  • Railway / Render:零設定容器部署,適合 MVP 與 PoC,按用量計費。
  • AWS Lambda / Google Cloud Run:無伺服器,冷啟動需優化 Server 體積;Cloud Run 支援 SSE 長連線較友善。
  • VPS(DigitalOcean / Hetzner):完全控制,適合 mTLS 內網閘道;需自建監控與日誌。

監控與版本化:serverInfo.version 中語意化版本(SemVer);接入 Prometheus 或雲端 APM 記錄 tools/call 延遲 P99;灰度發布時新舊 Server 並行註冊到 Host Catalog,對照錯誤率後再切換。

13 · 知識庫實戰:ChromaDB / Qdrant

企業 Agent 最常見的 MCP Server 場景是向量知識庫:把內部文件 embedding 後供模型檢索。以下以 ChromaDB 為例(Qdrant 介面類似,換用戶端即可)。

import chromadb
from chromadb.utils import embedding_functions

client = chromadb.PersistentClient(path="./chroma_data")
ef = embedding_functions.DefaultEmbeddingFunction()
collection = client.get_or_create_collection("docs", embedding_function=ef)

@mcp.tool()
def index_document(doc_id: str, text: str) -> str:
    """寫入文件到向量庫。"""
    collection.upsert(ids=[doc_id], documents=[text])
    return f"已索引: {doc_id}"

@mcp.tool()
def search_knowledge(query: str, top_k: int = 5) -> str:
    """語意檢索知識庫。"""
    results = collection.query(query_texts=[query], n_results=top_k)
    docs = results["documents"][0]
    return "\n---\n".join(docs or ["無結果"])

Embedding 模型可選 OpenAI text-embedding-3-small(1536 維)或本地 sentence-transformers。ChromaDB 預設使用 all-MiniLM-L6-v2(384 維),單條 512 token 切片是常見實務;索引 10 萬頁文件約需 2–4 GB 磁碟與 8 GB 記憶體。正式環境建議 Qdrant 叢集 + 副本,ChromaDB 適合單機 PoC。

14 · 生態與學習路徑

推薦社群 Server

  • @modelcontextprotocol/server-filesystem — 檔案讀寫與 Resource
  • @modelcontextprotocol/server-postgres — 唯讀 SQL 查詢
  • @modelcontextprotocol/server-slack — Slack 訊息與頻道
  • @modelcontextprotocol/server-github — Issue / PR / 程式碼搜尋
  • mcp-server-fetch — HTTP 抓取與 HTML 轉 Markdown

2026 趨勢與學習路徑

趨勢: Streamable HTTP 取代純 SSE 成為新部署預設;OAuth 2.1 裝置流進入主流 Host;企業 Catalog 與 Server 簽章/稽核成為合規標配;MCP 與 A2A(Agent-to-Agent)在同一棧分層共存。

建議學習路徑(約 2 週):

  1. 閱讀 MCP 協定架構解析,理解 Host / Client / Server 三層。
  2. 跟做本文 Hello World → Tools 五件套,Inspector 驗收。
  3. 接入 Cursor,跑通真實業務場景(讀 README + 查庫 + HTTP)。
  4. 實作 ChromaDB 知識庫 Server,對照檢索準確率。
  5. Docker + HTTP 部署到 Railway,設定 Bearer 認證。
  6. 在隔離 Mac 節點做 Catalog 彩排,寫入 ADR 後推進正式環境。

15 · 結語:在隔離 Mac 上練熟再上線

雖然你可以在 Windows WSL、Linux 容器或主力 Mac 上直接開發 MCP Server,但主力機混裝 OAuth、正式 API Key 與多款 Host 全域設定,一次誤設就可能讓 tools/call 在背景 cron 裡存取內網;WSL 檔案系統權限與 macOS Seatbelt 沙箱體驗也不等價。公網掃描已發現 1,000+ 未授權暴露的 Server——在污染正式憑證之前,用隔離環境驗證「哪些 Server 值得進白名單」是更穩健的工程紀律。

MCP 讓你寫一次 Server、多 Host 重用,但開發體驗同樣重要:Cursor 與 Claude Desktop 的 MCP 設定路徑、STDIO 子程序行為、Keychain 憑證儲存都是 macOS 原生體驗。若你需要可稽核的「多 Server × 多 Host 對照實測」證據,又與 Xcode / Apple 工具鏈同週期協作,在獨立 macOS 租用節點完成 1–3 天 MCP 開發彩排再推進企業 Catalog,通常比直接在辦公筆電上疊裝 Server 更輕、比裸容器更接近真實桌面 Host 行為。

五步 Mac 隔離 MCP 開發驗收(HowTo)

  1. 租用隔離 macOS:Mac mini M4 起,SSH 接入;本地使用者、Apple ID 與 OAuth 與主力機完全隔離。套餐見 M 系列算力定價
  2. 部署開發環境:安裝 Python 3.12、Node(Inspector)、Cursor;建立獨立 venv,不共享主力機 ~/.config
  3. 並行開發多個 Server:在同一節點實作 Hello World、Tools 五件套與 ChromaDB 知識庫,Inspector 匯出 tools/list 快照。
  4. Cursor / Claude Desktop 聯調:註冊 STDIO Server,跑固定任務包(讀檔案、查庫、語意檢索),記錄延遲與越權攔截。
  5. 匯出 ADR 並釋放:將 Server 白名單、OAuth 範圍與資料分級寫入架構決策記錄,吊銷測試 Key、退租擦碟。