
你大約只需 15 分鐘,就能建構出一個 Claude 實際會呼叫的 MCP 伺服器。我們在 Node 20 和 Python 3.11 上進行了計時測試:一個透過 stdio 運作、能被 Claude Desktop 識別的 add 工具,初次建構花了 14 分鐘,而一旦熟悉流程後,不到 5 分鐘即可完成。本教學將分別使用 Python 的 FastMCP 2.x 與 TypeScript 的 @modelcontextprotocol/sdk 1.x 建構相同的伺服器兩次,讓你可以選擇適合的技術堆疊並直接複製實用程式碼。如果你想先了解架構與協定理論,請參考我們的 Model Context Protocol 概念指南;這裡我們專注於實作。
MCP 伺服器快速入門:你要建構什麼
MCP 伺服器是一個小型程式,它透過 Model Context Protocol 向 AI 用戶端(如 Claude、Cursor 或 VS Code)公開工具、資料和提示詞模板。你只需編寫一次伺服器,任何相容 MCP 的用戶端都能呼叫它。在本教學中,你將建構一個包含兩個工具(add 計算機和 fetch_url 輔助工具)的伺服器,在本地透過 stdio 運行、進行測試,並將其連接到真實的用戶端。
開始之前,以下是你需要準備的一切。
| 需求 | Python 路徑 | TypeScript 路徑 |
|---|---|---|
| 執行環境 | Python 3.10+(建議 3.11) | Node.js 20 LTS+ |
| 套件管理器 | uv(建議)或 pip | npm、pnpm 或 bun |
| SDK | mcp 1.x / FastMCP 2.x | @modelcontextprotocol/sdk 1.x |
| 用於測試的用戶端 | Claude Desktop、Claude Code 或 Cursor | 相同 |
| 測試工具 | npx @modelcontextprotocol/inspector | 相同 |
這兩種路徑產生的伺服器行為完全一致。請選擇你團隊目前使用的語言。如果沒有偏好,建議從 Python 開始,因為 FastMCP 能讓第一個伺服器的程式碼更簡潔。
MCP 伺服器實際上暴露了什麼?
在編寫程式碼之前,了解伺服器可以提供的三件事會很有幫助。MCP 伺服器暴露工具(模型可以呼叫的函式,例如「搜尋資料庫」)、資源(模型可以載入的唯讀資料,例如檔案或記錄)以及提示詞(可重複使用的提示詞模板)。你建構的大多數伺服器將以工具為主;資源和提示詞則是可選的。
MCP 伺服器定義: 一個遵循 Model Context Protocol 的程序,它宣傳一份工具、資源和提示詞清單,供 AI 用戶端在執行階段發現並呼叫。
用戶端(例如 Claude Desktop)扮演主機的角色。它啟動或連接到你的伺服器,詢問「你有什麼工具?」,然後在模型判斷某個工具有用時呼叫它們。你永遠不會在伺服器內部呼叫模型。流程是反向進行的。

這個方向至關重要。你的伺服器是被動的提供者。它等待用戶端連接,回應探索請求,並執行被呼叫的任何工具。保持這個心智模型,本教學的其餘部分就會變得清晰易懂。
如何在 Python 中建構 MCP 伺服器(逐步教學)
Python 是讓伺服器最快運行的路徑,因為 FastMCP 處理了協定的底層細節,並透過裝飾器將普通函式轉換為工具。以下內容均使用 官方 Python SDK。以下是四個步驟。
步驟 1:設定專案。 使用 uv,這現在是 MCP Python 專案的標準工具:
uv init mcp-demo
cd mcp-demo
uv add "mcp[cli]"如果你偏好 pip:python -m venv .venv && source .venv/bin/activate && pip install "mcp[cli]"。
步驟 2:編寫伺服器。 建立 server.py:
from mcp.server.fastmcp import FastMCP
import httpx
# Name shows up in the client's tool list
mcp = FastMCP("demo-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers and return the sum."""
return a + b
@mcp.tool()
async def fetch_url(url: str) -> str:
"""Fetch a URL and return the first 2000 characters of the body."""
async with httpx.AsyncClient(timeout=10) as client:
resp = await client.get(url)
return resp.text[:2000]
if __name__ == "__main__":
mcp.run() # defaults to stdio transport注意兩件事。文件字串(docstring)會成為模型閱讀的工具描述,所以要像撰寫指令一樣撰寫它。此外,類型提示(a: int)會自動成為輸入結構描述,因此 FastMCP 會為你產生 JSON Schema。
步驟 3:運行它。 mcp.run() 會在 stdio 上啟動伺服器,這是本地用戶端啟動所使用的傳輸層。在開發期間,你不會直接運行此命令;而是由用戶端啟動它。為了進行快速煙霧測試,請使用開發運行器:
uv run mcp dev server.py步驟 4:回傳乾淨的輸出。 這裡有一個值得標記的陷阱:回傳字串或類型化值,而不是你希望它能渲染的裸嵌套字典。我們將在生產環境章節中回頭說明原因,但簡短來說,模糊的回傳類型可能會在某些用戶端中被無聲地截斷。
這就是完整的 Python MCP 伺服器。兩個工具、真實的網路呼叫、自動結構描述。接下來,我們用 TypeScript 做同樣的事。
如何在 TypeScript 中建構 MCP 伺服器(逐步教學)
TypeScript 路徑直接使用 官方 TypeScript SDK 和 zod 進行輸入驗證。它比 FastMCP 稍微冗長一些,但類型系統非常出色,且能乾淨地部署到 Node 主機上。
步驟 1:設定專案。
mkdir mcp-demo && cd mcp-demo
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx步驟 2:編寫伺服器。 建立 server.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "demo-server", version: "1.0.0" });
server.tool(
"add",
"Add two numbers and return the sum.",
{ a: z.number(), b: z.number() },
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
}),
);
server.tool(
"fetch_url",
"Fetch a URL and return the first 2000 characters.",
{ url: z.string().url() },
async ({ url }) => {
const resp = await fetch(url);
const body = await resp.text();
return { content: [{ type: "text", text: body.slice(0, 2000) }] };
},
);
const transport = new StdioServerTransport();
await server.connect(transport);步驟 3:運行它。 開發期間:npx tsx server.ts。生產環境中,使用 tsc 編譯並用 Node 運行建置後的 .js 檔案。注意回傳結構:每個工具都回傳 { content: [{ type: "text", text: ... }] }。這個明確的 content 陣列相當於 Python 中「回傳乾淨字串」規則的 TypeScript 版本。SDK 需要類型化的內容區塊,而不是原始物件。
步驟 4:使用 zod 驗證輸入。 z.string().url() 結構描述會在你的處理程序運行之前拒絕不良輸入,這正是當模型產生參數時你所需要的。
相同的兩個工具,相同的行為,地道的 TypeScript 寫法。現在讓我們決定用戶端應如何連接你的伺服器。
stdio 與 Streamable HTTP:該使用哪種傳輸層?
MCP 伺服器透過兩種傳輸層之一進行通訊。stdio 將伺服器作為本地子程序運行,由用戶端啟動並透過標準輸入/輸出進行通訊。Streamable HTTP 將伺服器作為網路服務運行,用戶端透過 HTTP 連接。根據伺服器需要所在的位置來選擇。
| stdio | Streamable HTTP | |
|---|---|---|
| 運行位置 | 本地,由用戶端啟動 | 遠端或本地,作為 Web 服務 |
| 最適合 | 個人工具、開發、單機 | 共享伺服器、團隊、SaaS、雲端 |
| 認證 | 繼承使用者的機器權限 | 需要 OAuth 2.1 / Token 認證 |
| 設定成本 | 最低(只需一個命令) | 需要託管 + 端點 |
| 我們測量的開銷 | 每次呼叫約 8-12 毫秒(本地) | 每次呼叫約 40-70 毫秒(受網路限制) |

經驗法則:在 stdio 上建構和測試,僅當有多人或多台機器需要該伺服器時,才切換到 Streamable HTTP。大多數伺服器永遠不需要離開 stdio。上面的 mcp.run() 和 StdioServerTransport() 呼叫已經是 stdio,所以你已準備好進行開發。
如何使用 Inspector 測試你的 MCP 伺服器
在將伺服器接入 Claude 之前,先使用 MCP Inspector 獨立測試它。這是一個瀏覽器 UI,可以連接到你的伺服器,列出其工具,並讓你手動呼叫它們。針對你的伺服器運行它:
# Python
npx @modelcontextprotocol/inspector uv run server.py
# TypeScript
npx @modelcontextprotocol/inspector npx tsx server.tsInspector 會開啟一個本地頁面,你可以在其中看到你的 add 和 fetch_url 工具,發起測試呼叫,並閱讀原始回應。這是 MCP 開發中最好的習慣。如果工具的結構描述格式錯誤或回傳值有誤,你會在幾秒鐘內在此處看到,而不是盯著 Claude 內的無聲失敗。我們曾透過这种方式發現了一個錯誤的輸入結構描述,否則這將導致透過用戶端進行完整的除錯往返。每次都要先在 Inspector 中測試。
如何將你的 MCP 伺服器連接到 Claude Desktop、Claude Code 和 Cursor
一旦 Inspector 測試通過,就將真實用戶端指向你的伺服器。每個用戶端都會讀取一個設定檔,告訴它如何透過 stdio 啟動你的伺服器。
Claude Desktop。 編輯 claude_desktop_config.json(在 macOS 上:~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"demo-server": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/mcp-demo", "run", "server.py"]
}
}
}重新啟動 Claude Desktop,你的工具將會出現在連接器圖示下。
Claude Code。 從你的專案中使用一個命令添加伺服器:claude mcp add demo-server -- uv run server.py。Claude Code 會將其儲存在你的專案設定中,並在啟動時載入。如果你也使用 hooks 來腳本化 Claude Code,我們的 Claude Code hooks 指南 與自訂 MCP 工具搭配使用效果极佳。
Cursor。 將相同的 mcpServers 區塊添加到專案根目錄下的 .cursor/mcp.json 中。其結構與 Claude Desktop 的相匹配。有關在 Claude Code 中運行的 MCP 伺服器的真實範例,請參閱我們如何將 Higgsfield 接入 Claude Code。
在每个設定中使用絕對路徑。相對路徑是伺服器無法啟動的最常見原因。
將 MCP 伺服器部署到生產環境(認證與託管)
當你的伺服器需要共享時,將其從 stdio 移至 Streamable HTTP,並添加三件事:認證、錯誤處理和主機。
- 認證。 根據 MCP 授權規範,遠端 MCP 伺服器必須使用 OAuth 2.1。對於內部工具,在 HTTP 端點上進行 bearer-token 檢查是務實的最低要求。切勿發布公開且未經認證的工具伺服器,因為運行 SQL 或訪問內部 API 的工具是一個即時攻擊面。
- 錯誤處理。 將工具主體包裝在 try/except(或 try/catch)中,並回傳類型化的錯誤訊息,而不是拋出異常。模型處理「查詢失敗,原因是...」的效果遠好於連接中斷。
- 託管。 任何能運行長期存在的 Node 或 Python 程序的平台均可:小型 VPS、Fly.io、Railway 或你自己基礎設施上的容器。保持程序溫暖,因為冷啟動會增加第一次工具呼叫的延遲。
- 併發與成本。 如果你的工具在下游呼叫 LLM 或付費 API,請在它前面放置一個閘道器。我們整理的 LLM 閘道器工具 涵蓋了速率限制和故障轉移,而 上下文工程工具 有助於防止工具輸出膨脹模型的上下文視窗。
對於 Python,將運行呼叫切換為 mcp.run(transport="streamable-http");對於 TypeScript,將 StdioServerTransport 替換為 SDK 的 StreamableHTTPServerTransport。工具定義完全不會改變——這正是傳輸層抽象化的意義所在。
我們在生產環境中發布 MCP 伺服器所學到的經驗
我們在 Techsy 內部使用了 MCP 伺服器,有些教訓只有在真實流量進入後才會顯現。以下是我們測量的數據以及遇到的陷阱。
我們發布的第一個伺服器是一個使用 FastMCP 2.x 和 Python mcp 1.x SDK 建構的唯讀 Postgres 查詢工具,後來為了比較而用 @modelcontextprotocol/sdk 1.x 重寫。在 2026 年的技術堆疊(Node 20、Python 3.11)上,本地 stdio 工具呼叫每次呼叫增加了約 8 到 12 毫秒 的傳輸開銷。一旦我們將同一個伺服器移至 VPS 上的 Streamable HTTP,每次呼叫的成本上升到 40 到 70 毫秒,這幾乎完全是網路往返而非協定成本。FastMCP 的程序冷啟動時間約為 300 毫秒,這就是為什麼我們讓生產環境的程序保持溫暖。
讓我們損失了大約兩個小時的陷阱是:一個回傳原始 Python 字典的工具在 Inspector 中渲染正常,但在 Claude Desktop 中回傳時被截斷。將回傳值包裝為類型化的文字字串立即解決了問題。這就是為什麼本教學在各處都回傳字串和 content 文字區塊,而不是嵌套物件。另一個立即見效的習慣是在觸碰用戶端設定之前,透過 npx @modelcontextprotocol/inspector 運行每個伺服器,這在 TypeScript 重寫過程中發現了一個格式錯誤的輸入結構描述,否則它會在 Cursor 中無聲地失敗。
| 我們使用的工具 | 版本 |
|---|---|
Python mcp SDK | 1.x |
| FastMCP | 2.x |
@modelcontextprotocol/sdk (TS) | 1.x |
| Node.js | 20 LTS |
| Inspector | @modelcontextprotocol/inspector (latest) |
如果你在考慮首先要將哪些工具建構到伺服器中,我們的 2026 年最佳 MCP 伺服器 列表是一個很好的靈感來源。
Techsy 如何進行 MCP 開發
在 Techsy,我們將 MCP 伺服器作為我們為客戶發布的 AI 代理系統的一部分,透過類型化工具層將代理連接到內部資料庫、CRM 和 API。我們的方法是從窄範圍開始(一個經過充分測試的 stdio 工具),在 Inspector 中驗證,然後僅當多個代理需要時才將其提升為經過認證的 HTTP 服務。當代理邏輯變得複雜時,我們會將自訂伺服器與 Claude Agent SDK 搭配使用。
這是誠實的版本:大多數團隊過度建構他們的第一個伺服器。在第一天,你很少需要 HTTP、OAuth 和十幾個工具。如果你希望有人幫你檢視 MCP 整合,獲取免費諮詢,我們會告訴你這是一個單一工具的 stdio 工作,還是真正需要基礎設施的東西。
常見問題
我應該用 Python 還是 TypeScript 建構我的 MCP 伺服器?
使用你團隊已經發布的語言。使用 FastMCP 的 Python 是獲得第一個運行伺服器的最短路徑,因為裝飾器可以將函式轉換為工具。使用官方 SDK 的 TypeScript 稍微冗長一些,但提供了出色的類型系統,并能乾淨地部署到 Node 主機。兩者產生的伺服器對用戶端而言行為完全一致。
我需要像 FastMCP 這樣的框架來建構 MCP 伺服器嗎?
不需要,但它很有幫助。FastMCP 隨附於官方 Python mcp SDK 中,並消除了大多數協定樣板程式碼。你可以使用較低階的 Server API 進行細粒度控制,但對於幾乎所有伺服器來說,FastMCP(Python)或 McpServer(TypeScript)都是正確的工具,且程式碼量少得多。
如何除錯無法運作的 MCP 伺服器?
首先透過 MCP Inspector 運行它:npx @modelcontextprotocol/inspector 後接你的運行命令。Inspector 會列出你的工具並讓你直接呼叫它們,因此你可以在責怪用戶端之前確認伺服器是否正常運作。如果 Inspector 正常但用戶端不正常,請檢查你的設定是否使用絕對路徑,以及你是否重新啟動了用戶端。
FastMCP 是 MCP 的官方部分嗎?
是的。FastMCP 作為高階伺服器介面捆綁在官方 Model Context Protocol Python SDK 中。你使用的 @mcp.tool() 裝飾器是建構 Python 伺服器的推薦方式,而不是第三方附加元件。
本地和遠端 MCP 伺服器有什麼區別?
本地伺服器在你的機器上透過 stdio 運行,由用戶端作為子程序啟動,最適合個人工具和開發。遠端伺服器作為 Web 服務透過 Streamable HTTP 運行,可由多個用戶端訪問,這需要 OAuth 2.1 認證。先建構本地版本,僅在需要共享時才轉向遠端。
我可以用哪些語言建構 MCP 伺服器?
Model Context Protocol 擁有適用於 Python、TypeScript、Java、Kotlin 和 C# 的官方 SDK,以及其他語言的社群 SDK。由於 MCP 是一種線路協定,任何能夠透過 stdio 或 HTTP 讀寫 JSON-RPC 的語言都可以實現伺服器,但官方 SDK 可以節省你這項工作。
MCP 伺服器是否適用於 ChatGPT 和 Gemini,還是僅適用於 Claude?
MCP 是一個開放標準,已被整個代理 AI 生態系統採用,包括 ChatGPT、Gemini、Cursor 和 VS Code Copilot。你建構的單一伺服器適用於任何相容的用戶端。你不需要為每個模型編寫單獨的整合,這正是該協定的意義所在。
建構一個可運作的 MCP 伺服器需要多長時間?
一旦安裝好執行環境,第一個包含一兩個工具並透過 stdio 運行的伺服器大約需要 15 分鐘。我們測量顯示,Node 20 上的初學者需要 14 分鐘,而重複建構則不到 5 分鐘。添加認證、HTTP 傳輸層和生產環境託管才是真正耗時的部分,而非伺服器本身。
關於作者
Mert Batur Gurbuz 是 Techsy.io 的共同創辦人,該團隊為 B2B 客戶發布 AI 代理、自動化系統以及語音/SDR 管道。他就讀於伯明罕大學,並撰寫關於 Techsy 團隊在生產環境中實際使用的 LLM 工具堆疊的文章。在 LinkedIn 上聯繫他。
Mert Batur Gurbuz,共同創辦人,Techsy.io,伯明罕大學