Node.js REST 升级 MCP 服务器,让 AI 代理成为你的开发助手

207 阅读8分钟

随着大型语言模型(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_idupdate_user_nameupdate_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 updatedFieldsstring[] = [];

      

       // --- 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 令牌,并在工具处理程序的 fetchaxios 调用中,将这些凭证包含在 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 工具支撑

  1. 调用资源工具 get_customer_order_history(customerId),获取 Alice 的订单历史;

  2. 调用操作工具 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 调用的 “技能集合”,从而大幅提升其在代理生态系统中的实用性,为应用程序的智能化升级奠定坚实基础。