隨着大型語言模型(LLM)和代理 AI 的快速發展,應用程序展示其功能的方式亟待從根本上變革。傳統的 REST API 專為軟件與軟件之間的通信設計,開發人員需閲讀大量文檔並編寫自定義集成代碼才能使用。而模型上下文協議(MCP) 作為一種開放標準,通過創建統一的、機器可讀的界面,讓 AI 代理能夠動態發現並與之交互,成功解決了這一痛點。
本文將提供一份全面指南,介紹如何使用官方 TypeScript SDK 將現有的 Node.js REST API 轉換為 MCP 服務器,並重點剖析此次轉換所帶來的架構變革及關鍵應用場景。
一、範式轉變:從 REST 到 MCP
REST API 在設計之初主要面向人類開發人員,圍繞資源管理(CRUD 操作)進行優化,依賴 HTTP 謂詞、路徑變量及特定的請求 / 響應格式實現功能。
與之不同,MCP 模型秉持 “人工智能優先” 的理念,二者在核心特性上存在顯著差異,具體對比如下表所示:
| 對比維度 | REST API(傳統模式) | MCP 服務器(AI 優先模式) |
|---|---|---|
| 主要使用者 | 人類開發人員、客户端應用程序 | AI 代理、LLM、AI 驅動的 IDE |
| 接口形式 | HTTP 動詞、路徑、查詢參數、自定義正文 | 標準化的 JSON-RPC 消息(工具、資源、提示) |
| 功能發現方式 | 通過 OpenAPI/Swagger 文檔手動查閲 | 通過 list_tools() 或 list_resources() 協議動態發現 |
| 功能設計 | 細粒度的原子化端點(如 GET /users/{id}) | 高級語義化操作(如 manage_user_profile) |
需要注意的是,REST 到 MCP 的轉換並非簡單的端口遷移,而是一次抽象升級。我們可以通過 MCP 層包裝現有的 Node.js 業務邏輯,將標準化的 MCP 調用轉換為 REST API 能夠理解的請求,從而實現功能適配。
二、第 1 步:搭建 Node.js MCP 環境
官方的模型上下文協議 TypeScript SDK 是完成此次轉換的核心工具,以下是具體的環境搭建步驟:
1. 初始化項目並安裝依賴
假設我們已擁有一個基礎的 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
2. 實例化 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 服務器已在標準 I/O 上運行...");
}
startServer().catch(console.error);
三、第 2 步:規劃並定義 MCP 工具
這是轉換過程中最關鍵的一步。我們不能盲目地將每個 REST 端點直接暴露,而應將功能規劃為高級、適配代理的工具和資源。
1. 設計適配 LLM 的工具
LLM 對語義化、基於意圖的工具的適配性,遠優於細粒度的低級 API 調用。
- 不合理(以 REST 為核心) :設計
get_user_by_id、update_user_name、update_user_email等細分接口; - 合理(以 MCP 為核心) :設計
manage_user_profile(userId, newName, newEmail)這樣的高級語義化操作接口。
MCP 工具處理程序需協調多個必要的 REST 調用,以完成單個高級操作。
2. 實現工具處理程序
每個工具都需要具備描述性名稱、面向 LLM 的完整自然語言描述,以及基於 Zod 的結構化輸入 / 輸出模式。
示例代碼如下:
// 定義工具輸入參數的模式
const UpdateUserSchema = z.object({
userId: z.string().describe("需要更新信息的用户的唯一 ID。"),
newEmail: z.string().email().optional().describe("用户的新電子郵箱地址。"),
newSubscriptionPlan: z.enum(['basic', 'premium', 'pro']).optional().describe("需要為用户應用的新訂閲計劃。"),
});
server.registerTool(
"manage_subscription",
{
title: "管理用户訂閲與個人資料",
description: "更新用户的電子郵箱地址和/或更改其訂閲計劃,操作需提供用户 ID。",
argsSchema: UpdateUserSchema,
outputSchema: z.object({
status: z.string(),
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;
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 : ["未進行任何更改。"],
};
}
);
3. 為上下文創建資源
對於僅提供上下文(只讀數據)的簡單 GET 請求,可使用 ResourceTemplates。這種方式能讓 LLM 瞭解可用的數據信息,無需額外調用工具。
示例代碼如下:
server.registerResource(
"product_catalog_item",
{
title: "產品目錄項",
description: "產品目錄中的單個產品信息,包含價格、庫存和產品描述。",
uriTemplate: "api://my-node-api-mcp/products/{productId}",
dataSchema: z.object({
id: z.string(),
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 步:實現安全與錯誤處理
向自主代理開放功能時,安全性至關重要。同時,為了確保 AI 代理能準確判斷操作結果,還需設計完善的錯誤處理機制。
1. 身份驗證集成
MCP 服務器在此過程中扮演代理角色,其內部的 HTTP 客户端必須處理原始 REST API 的身份驗證。通常的做法是:從環境變量中安全加載 API 密鑰或 OAuth 令牌,並在工具處理程序的 fetch 或 axios 調用中,將這些憑證包含在 Authorization 標頭裏。
2. 穩健的錯誤響應
AI 代理依賴結構化輸出來判斷操作的成功或失敗。因此,工具處理程序必須捕獲 REST API 返回的 HTTP 錯誤,並將其轉換為清晰、結構化的 MCP 錯誤響應。
- 不合理:直接拋出原始的 HTTP 404 錯誤;
- 合理:返回結構化響應,如
{ status: "Error", message: "在數據庫中未找到 ID 為 123 的用户" }。
五、MCP 解鎖的關鍵應用場景
將 REST API 轉換為 MCP 服務器是一項具有戰略意義的舉措,它能賦能新型人工智能驅動的應用程序,以下是幾個典型場景:
1. AI 驅動的開發者工具(“光標” 場景)
如今,許多現代 AI IDE 和代碼助手(如 Cursor、GitHub Copilot)都採用 MCP 協議,讓 AI 能夠與本地開發環境或內部服務進行交互。
場景示例:開發人員向 AI 詢問 “為新的用户管理模塊運行集成測試”;
MCP 工具支撐:調用 run_npm_script(scriptName: string) 工具;
Node.js API 邏輯:該工具在獲得用户明確批准後,安全執行 shell 命令(如 npm run test:user-management),完成集成測試任務。
2. 智能客户支持自動化
將核心的 CRM(客户關係管理)、庫存管理或賬單管理 API 作為 MCP 工具,開放給內部 AI 代理使用。
場景示例:客服人員向 AI 詢問 “客户 Alice 的訂單狀態如何?我們能否為她的訂單應用 10% 的折扣?”;
MCP 工具支撐:
- 調用資源工具
get_customer_order_history(customerId),獲取 Alice 的訂單歷史; -
調用操作工具
apply_discount_to_order(orderId, percentage),為指定訂單應用折扣;優勢:AI 可自動串聯多個工具調用,完成數據獲取與操作執行,無需人工手動干預。
3. 動態工作流與微服務編排
MCP 服務器可作為龐大微服務架構的抽象層,讓 LLM 能夠通過單個語義化命令,編排複雜的多步驟工作流。
場景示例:LLM 收到指令 “處理 Jane Doe 的新客户入職流程”;
MCP 工具支撐:調用 onboard_new_customer(姓名、電子郵件) 工具;
編排邏輯:該工具的處理程序在內部依次調用用户微服務(REST POST)、計費服務(REST POST)和郵件服務(REST POST),確保整個新客户入職的業務流程完整、正確執行。這種方式不僅讓 LLM 集成變得簡單,還能靈活適配後端架構的複雜性。
六、結論:標準化 AI 集成的未來
將 Node.js REST API 轉換為支持 MCP 的服務器,是一項面向未來的投資,能讓應用程序更好地適應自主 AI 代理時代的需求。
雖然簡單包裝每個 REST 端點是一個不錯的起點,但 MCP 的真正價值需要通過主動規劃來實現 —— 即設計反映用户意圖而非 API 結構的高級語義化工具。這一過程能將 API 從靜態的數據交換服務,轉變為動態的、可被 AI 調用的 “技能集合”,從而大幅提升其在代理生態系統中的實用性,為應用程序的智能化升級奠定堅實基礎。
- 作者: 拉克希米·納拉亞納·拉薩萊
- 源文地址:https://dzone.com/articles/transform-nodejs-rest-api-to-mcp-s...