將 Node.js REST API 改造為 AI 就緒的 MCP 服務器
瞭解如何將 Node.js REST API 升級為 AI 就緒的模型上下文協議(MCP)服務器,以支持智能的、由智能體驅動的交互能力。
大型語言模型(LLM)與智能體 AI 的發展,要求應用程序暴露能力的方式發生根本性轉變。傳統 REST API 專為軟件對軟件通信設計,需要開發者閲讀文檔並編寫自定義集成代碼。而模型上下文協議(MCP)作為一種開放標準,通過創建統一的機器可讀接口解決了這一問題,使 AI 智能體能夠動態發現並與之交互。
本文提供了一份全面指南,介紹如何使用官方 TypeScript SDK 將現有 Node.js REST API 轉換為 MCP 服務器,重點解析轉換帶來的架構變化及解鎖的關鍵應用場景。
一、範式轉變:從 REST 到 MCP
REST API 的設計通常以人類開發者為核心,通過 HTTP 動詞、路徑變量和特定的請求/響應格式優化資源管理(CRUD 操作)。
相比之下,MCP 模型以 AI 為優先設計理念:
| 維度 | 傳統 REST API | AI 優先 MCP 服務器 |
|---|---|---|
| 主要使用者 | 人類開發者、客户端應用 | AI 智能體、LLM、AI 驅動的 IDE |
| 接口形式 | HTTP 動詞、路徑、查詢參數、自定義請求體 | 標準化 JSON-RPC 消息(工具、資源、提示詞) |
| 發現方式 | 通過 OpenAPI/Swagger 文檔手動發現 | 通過 list_tools()或 list_resources()協議動態發現 |
| 功能特性 | 細粒度、原子化端點(如 GET /users/{id}) | 高層級、語義化操作(如 manage_user_profile) |
這種轉換並非直接移植,而是一種抽象過程:用 MCP 層包裹現有的 Node.js 業務邏輯,將標準化的 MCP 調用轉換為 API 可理解的 REST 請求。
二、步驟 1:搭建 Node.js MCP 環境
官方模型上下文協議 TypeScript SDK 是實現這一轉換的核心工具。
(一)初始化項目並安裝依賴
假設已創建基礎 Node.js 項目(v18 及以上版本),需安裝 MCP SDK、請求驗證工具(如 Zod)以及用於與現有 REST API 交互的 HTTP 客户端(如 axios 或 node-fetch)。
npm init -y
npm install @modelcontextprotocol/sdk zod node-fetch
npm install -D typescript @types/node ts-node
(二)實例化 MCP 服務器
創建文件(如 mcp-server.ts),用於設置服務器實例和傳輸層——本地測試可使用 StdioServerTransport,遠程部署可使用 StreamableHttpServerTransport。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 實例化核心MCP服務器
const server = new McpServer({
name: "MyNodeAPIServer",
version: "1.0.0",
capabilities: { tools: {}, resources: {}, prompts: {} }, // 初始為空,後續註冊工具和資源
});
// 傳輸層負責與LLM客户端的通信
const transport = new StdioServerTransport();
async function startServer() {
// [工具和資源註冊代碼將在此處添加]
await server.connect(transport);
console.log("MCP服務器已在標準輸入輸出流上運行...");
}
startServer().catch(console.error);
三、步驟 2:設計並定義 MCP 工具
這是最關鍵的步驟。無需盲目暴露所有 REST 端點,而應將功能整合為高層級、適合智能體使用的“工具(Tools)”和“資源(Resources)”。
(一)設計適合 LLM 的工具
LLM 在處理語義化、基於意圖的工具時表現更優,而非細粒度的底層 API 調用。
- 不推薦(REST 導向):get_user_by_id(通過 ID 獲取用户)、update_user_name(更新用户名)、update_user_email(更新用户郵箱)
- 推薦(MCP 導向):manage_user_profile(userId, newName, newEmail)(管理用户檔案)
MCP 工具處理器應協調多個必要的 REST 調用,以完成單個高層級操作。
(二)實現工具處理器
每個工具需包含描述性名稱、面向 LLM 的詳細自然語言描述,以及使用 Zod 定義的結構化輸入/輸出 schema。
// 定義工具輸入參數的schema
const UpdateUserSchema = z.object({
userId: z.string().describe("待更新用户的唯一ID。"),
newEmail: z.string().email().optional().describe("用户的新郵箱地址(可選)。"),
newSubscriptionPlan: z.enum(['basic', 'premium', 'pro']).optional().describe("待應用的新訂閲計劃(可選,值為basic/premium/pro)。"),
});
// 註冊MCP工具
server.registerTool(
"manage_subscription", // 工具唯一標識
{
title: "管理用户訂閲及檔案", // 工具標題
description: "更新用户郵箱地址和/或修改其訂閲計劃,需傳入用户ID。", // 工具描述(供LLM理解功能)
argsSchema: UpdateUserSchema, // 輸入參數校驗schema
outputSchema: z.object({ // 輸出結果schema
status: z.string(), // 操作狀態(如Success/Error)
updatedFields: z.array(z.string()), // 已更新的字段列表
}),
},
async (args) => { // 工具處理邏輯
const { userId, newEmail, newSubscriptionPlan } = args;
const updatedFields: string[] = [];
// --- REST API調用編排 ---
const REST_API_BASE = process.env.REST_API_URL; // 從環境變量獲取原REST API地址
if (newEmail) {
// 1. 調用REST API更新郵箱
await fetch(`${REST_API_BASE}/users/${userId}/email`, {
method: 'PUT',
body: JSON.stringify({ email: newEmail }),
headers: { 'Content-Type': 'application/json' },
});
updatedFields.push('email');
}
if (newSubscriptionPlan) {
// 2. 調用REST API更新訂閲計劃
await fetch(`${REST_API_BASE}/billing/${userId}/plan`, {
method: 'POST',
body: JSON.stringify({ plan: newSubscriptionPlan }),
headers: { 'Content-Type': 'application/json' },
});
updatedFields.push('subscriptionPlan');
}
// 返回結構化結果(供LLM解析)
return {
status: "Success",
updatedFields: updatedFields.length > 0 ? updatedFields : ["未執行任何修改。"],
};
}
);
(三)創建用於提供上下文的資源
對於提供上下文的簡單 GET 請求(只讀數據),可使用 ResourceTemplates(資源模板)。這使 LLM 能夠了解可用數據,無需實際調用工具。
server.registerResource(
"product_catalog_item", // 資源唯一標識
{
title: "產品目錄項", // 資源標題
description: "產品目錄中的單個商品信息,包含價格、庫存和描述。", // 資源描述
uriTemplate: "api://my-node-api-mcp/products/{productId}", // 資源URI模板(包含參數佔位符)
dataSchema: z.object({ // 數據結構schema
id: z.string(), // 商品ID
name: z.string(), // 商品名稱
price: z.number(), // 商品價格
description: z.string(), // 商品描述
}),
},
async (uri) => { // 資源數據獲取邏輯
// 從URI中解析productId
const productId = uri.split('/').pop();
// 調用REST API獲取商品數據:GET /products/{productId}
const response = await fetch(`${process.env.REST_API_URL}/products/${productId}`);
return await response.json();
}
);
四、步驟 3:實現安全與錯誤處理
向自主智能體暴露能力時,安全性至關重要。
(一)認證集成
MCP 服務器充當代理角色,其內部 HTTP 客户端需處理原 REST API 的認證邏輯。通常需從環境變量中安全加載 API 密鑰或 OAuth 令牌,並在工具處理器的 fetch/axios 調用中,將其包含在 Authorization 請求頭中。
(二)健壯的錯誤響應
AI 智能體依賴結構化輸出來判斷操作成敗。處理器必須捕獲 REST API 返回的 HTTP 錯誤,並將其轉換為清晰、結構化的 MCP 錯誤響應。
- 不推薦:直接拋出原始 HTTP 404 錯誤。
- 推薦:返回結構化 MCP 輸出,如
{ status: "Error", message: "數據庫中未找到ID為123的用户。" }
五、MCP 解鎖的關鍵應用場景
轉換為 MCP 是一項戰略性舉措,可支持新型 AI 驅動應用的開發。
(一)AI 驅動的開發工具(“Cursor”場景)
許多現代 AI IDE 和代碼助手(如 Cursor、GitHub Copilot)利用 MCP 實現 AI 與本地開發環境或內部服務的交互。
- 場景:開發者詢問 AI:“為新的用户管理模塊運行集成測試。”
- MCP 工具:
run_npm_script(scriptName: string)(執行 NPM 腳本) - Node.js API 邏輯:工具在用户明確授權後,安全執行
npm run test:user-management等 shell 命令。
(二)智能客户支持自動化
將核心 CRM(客户關係管理)、庫存或計費 API 封裝為 MCP 工具,提供給內部 AI 智能體使用。
- 場景:客服人員詢問 AI:“客户 Alice 的訂單狀態如何?能否為其應用 10%的折扣?”
- MCP 工具 1(資源):
get_customer_order_history(customerId)(獲取客户訂單歷史) - MCP 工具 2(工具):
apply_discount_to_order(orderId, percentage)(為訂單應用折扣) - 優勢:AI 自主串聯多個調用,自動獲取數據並執行操作,無需人工干預。
(三)動態工作流與微服務編排
MCP 服務器可作為抽象層部署在複雜的微服務架構之上,使 LLM 能通過單個語義化命令編排多步驟複雜工作流。
- 場景:LLM 收到指令:“為 Jane Doe 處理新客户入職流程。”
- MCP 工具:
onboard_new_customer(name, email)(新客户入職) - 編排邏輯:工具處理器內部調用用户微服務(REST POST)、計費服務(REST POST)和郵件服務(REST POST),確保整個業務流程正確完成。這使 LLM 集成更簡單,且對後端複雜度具備彈性。
六、結語:標準化 AI 集成的未來
將 Node.js REST API 改造為支持 MCP 的服務器,是為自主 AI 智能體時代適配應用的前瞻性投資。雖然簡單包裹所有端點是良好的起點,但 MCP 的真正價值在於主動整合功能——設計反映用户意圖而非 API 結構的高層級語義化工具。這一過程將 API 從靜態的數據交換服務,轉變為動態的、可被 AI 調用的能力集合,大幅提升其在智能體生態系統中的實用性。