Node.js TypeScript 构建企业级 MCP Server 全流程指南1. 为什么选择 MCP 协议进行 AI 工具开发在当今 AI 应用开发领域Model Context ProtocolMCP正在成为连接大语言模型与外部工具的事实标准协议。与传统的 API 调用方式相比MCP 提供了更标准化、更安全的交互方式协议标准化统一了不同工具间的调用规范安全隔离通过 STDIO/SSE 模式实现沙箱环境开发友好提供完善的 TypeScript SDK 支持生态丰富已有数百个开源 MCP Server 实现对于 Node.js 开发者而言使用 TypeScript 开发 MCP Server 具有显著优势类型安全保证工具定义的准确性完善的异步处理机制适合 AI 场景丰富的 npm 生态可快速集成各类服务编译检查能在早期发现接口定义问题// 典型 MCP Server 类型定义示例 interface McpServerConfig { name: string; version: string; capabilities: { tools?: Recordstring, ToolDefinition; resources?: ResourceRegistry; }; }2. 开发环境准备与项目初始化2.1 基础环境配置推荐使用以下工具链组合工具推荐版本作用Node.js18.x LTS运行时环境TypeScript5.0类型检查与编译pnpm8.x包管理更快更节省空间VS Code最新版开发IDEDocker Desktop4.25容器化部署环境验证命令# 检查Node.js版本 node -v # 检查pnpm安装 pnpm -v # 检查TypeScript tsc --version2.2 项目初始化步骤创建项目目录并初始化mkdir mcp-email-server cd mcp-email-server pnpm init安装 TypeScript 及相关依赖pnpm add -D typescript types/node npx tsc --init修改tsconfig.json关键配置{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true } }添加基础项目结构├── src │ ├── index.ts # 入口文件 │ └── types.ts # 类型定义 ├── test # 测试目录 ├── .env.example # 环境变量示例 └── package.json3. MCP Server 核心实现3.1 安装 MCP SDK 依赖pnpm add modelcontextprotocol/sdk dotenv pnpm add -D types/node modelcontextprotocol/types3.2 基础服务器框架#!/usr/bin/env node import { Server } from modelcontextprotocol/sdk/server; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio; import { ListToolsRequestSchema } from modelcontextprotocol/sdk/types; import dotenv from dotenv; // 加载环境变量 dotenv.config(); const server new Server( { name: email-mcp-server, version: 1.0.0, }, { capabilities: { tools: {}, }, } ); // 必须实现的工具列表接口 server.setRequestHandler(ListToolsRequestSchema, async () { return { tools: [ { name: send-email, description: 发送HTML格式邮件支持附件, inputSchema: { type: object, properties: { to: { type: string, description: 收件人地址多个用逗号分隔 }, subject: { type: string, description: 邮件主题 }, html: { type: string, description: HTML内容 }, attachments: { type: array, items: { type: object, properties: { filename: { type: string }, content: { type: string, format: binary }, }, }, }, }, required: [to, subject], }, }, ], }; }); async function bootstrap() { const transport new StdioServerTransport(); await server.connect(transport); console.error([MCP Server] 服务已启动); } bootstrap().catch((err) { console.error([MCP Server] 启动失败:, err); process.exit(1); });3.3 邮件发送功能实现安装 nodemailer 依赖pnpm add nodemailer types/nodemailer扩展工具处理逻辑import { CallToolRequestSchema } from modelcontextprotocol/sdk/types; import nodemailer from nodemailer; // 配置邮件传输器 const transporter nodemailer.createTransport({ host: process.env.SMTP_HOST, port: parseInt(process.env.SMTP_PORT || 465), secure: true, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD, }, }); server.setRequestHandler(CallToolRequestSchema, async (request) { try { const { name, arguments: args } request.params; if (name send-email) { const mailOptions { from: AI助理 ${process.env.SMTP_USER}, to: args.to, subject: args.subject, html: args.html, attachments: args.attachments, }; const info await transporter.sendMail(mailOptions); return { success: true, data: { messageId: info.messageId, accepted: info.accepted, } }; } return { success: false, error: 未知工具: ${name} }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 未知错误 }; } });4. Cherry Studio 集成指南4.1 环境准备Cherry Studio 对运行环境有特殊要求必须安装的运行时Bun (替代Node.js)uv (Python包管理)推荐安装方式# 使用bun安装uv bun install -g uv4.2 配置对接在Cherry Studio中添加MCP Server的配置示例{ mcpServers: { email-service: { command: bun, args: [run, start], env: { SMTP_HOST: smtp.example.com, SMTP_PORT: 465, SMTP_USER: youremail.com, SMTP_PASSWORD: your-password } } } }4.3 常见集成问题解决问题1连接超时解决方案检查Cherry Studio和Server是否在同一网络确认防火墙未阻止进程通信问题2工具列表不显示解决方案确保实现了ListToolsRequestSchema处理器检查工具定义的JSON Schema是否符合规范问题3权限不足解决方案为Server进程配置适当的文件系统权限在Docker中运行时正确映射卷5. 高级功能与生产环境部署5.1 邮件模板管理实现动态模板加载功能import fs from fs/promises; import path from path; async function loadTemplate(templateName: string, variables: Recordstring, string) { const templatePath path.join(__dirname, templates, ${templateName}.html); let content await fs.readFile(templatePath, utf-8); // 替换变量 for (const [key, value] of Object.entries(variables)) { content content.replace(new RegExp({{${key}}}, g), value); } return content; }5.2 Docker 容器化部署创建DockerfileFROM node:18-alpine WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN corepack enable pnpm install COPY . . RUN pnpm build ENV NODE_ENVproduction CMD [node, dist/index.js]构建并运行docker build -t mcp-email-server . docker run -d --name email-server \ -e SMTP_HOSTsmtp.example.com \ -e SMTP_USERyouremail.com \ -e SMTP_PASSWORDyour-password \ -p 3000:3000 \ mcp-email-server5.3 性能优化建议连接池配置const transporter nodemailer.createTransport({ pool: true, maxConnections: 5, maxMessages: 100, // ...其他配置 });日志监控import winston from winston; const logger winston.createLogger({ level: info, format: winston.format.json(), transports: [ new winston.transports.File({ filename: error.log, level: error }), new winston.transports.File({ filename: combined.log }), ], }); // 在工具调用中添加日志 server.setRequestHandler(CallToolRequestSchema, async (req) { logger.info(工具调用: ${req.params.name}, { timestamp: new Date(), arguments: req.params.arguments }); // ...处理逻辑 });6. 安全最佳实践6.1 敏感信息管理推荐方案使用dotenv管理环境变量生产环境使用 Vault 或 AWS Secrets Manager永远不要将凭据硬编码在代码中.env 文件示例# SMTP 配置 SMTP_HOSTsmtp.example.com SMTP_PORT465 SMTP_USERserviceexample.com SMTP_PASSWORDyour-strong-password # 加密密钥 JWT_SECRETyour-random-secret6.2 输入验证强化import { z } from zod; const emailSchema z.object({ to: z.string().email().or(z.string().regex(/^[^][^]\.[^](,[^][^]\.[^])*$/)), subject: z.string().min(1).max(100), html: z.string().optional(), attachments: z.array( z.object({ filename: z.string(), content: z.string(), }) ).optional(), }); server.setRequestHandler(CallToolRequestSchema, async (req) { try { const validated emailSchema.parse(req.params.arguments); // ...处理逻辑 } catch (err) { return { success: false, error: 输入验证失败 }; } });6.3 速率限制使用express-rate-limit实现基础防护import rateLimit from express-rate-limit; const limiter rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 每个IP限制100次请求 }); // 在HTTP服务中应用(如果暴露HTTP接口) app.use(limiter);7. 测试与调试技巧7.1 单元测试配置安装测试依赖pnpm add -D vitest vitest/coverage-v8 happy-dom示例测试代码import { describe, it, expect } from vitest; import { validateEmailInput } from ../src/validator; describe(邮件输入验证, () { it(应接受有效的单个邮箱, () { const input { to: testexample.com, subject: 测试 }; expect(validateEmailInput(input)).toBeTruthy(); }); it(应拒绝无效的主题, () { const input { to: testexample.com, subject: }; expect(() validateEmailInput(input)).toThrow(); }); });7.2 集成测试方案使用node-mocks-http模拟 MCP 协议交互import { MockMcpTransport } from ./mocks; import { server } from ../src; describe(MCP 协议测试, () { it(应正确返回工具列表, async () { const transport new MockMcpTransport(); await server.connect(transport); const response await transport.request({ type: ListToolsRequest, params: {}, }); expect(response.tools).toBeInstanceOf(Array); expect(response.tools[0].name).toBe(send-email); }); });7.3 调试技巧VS Code 调试配置{ version: 0.2.0, configurations: [ { type: node, request: launch, name: 调试 MCP Server, skipFiles: [node_internals/**], program: ${workspaceFolder}/src/index.ts, preLaunchTask: tsc: build, outFiles: [${workspaceFolder}/dist/**/*.js], env: { SMTP_HOST: localhost, SMTP_USER: testexample.com } } ] }协议分析工具使用 Wireshark 分析 STDIO 通信开发中间件记录协议消息8. 项目优化与扩展方向8.1 性能监控集成import Prometheus from prom-client; const httpRequestDuration new Prometheus.Histogram({ name: http_request_duration_seconds, help: Duration of HTTP requests in seconds, labelNames: [method, route, code], buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10], }); // 在工具调用中记录指标 server.setRequestHandler(CallToolRequestSchema, async (req) { const end httpRequestDuration.startTimer(); try { // ...处理逻辑 end({ method: MCP, route: req.params.name, code: 200 }); } catch (err) { end({ method: MCP, route: req.params.name, code: 500 }); throw err; } });8.2 插件系统设计实现可扩展的插件架构interface EmailPlugin { name: string; beforeSend?(mail: MailOptions): PromiseMailOptions; afterSend?(result: SendMailResult): Promisevoid; } class PluginManager { private plugins: EmailPlugin[] []; register(plugin: EmailPlugin) { this.plugins.push(plugin); } async applyBeforeSendHooks(mail: MailOptions) { for (const plugin of this.plugins) { if (plugin.beforeSend) { mail await plugin.beforeSend(mail); } } return mail; } }8.3 多协议支持扩展支持 HTTP 和 WebSocketimport { HttpServerTransport } from modelcontextprotocol/sdk/server/http; import express from express; const app express(); app.use(express.json()); const httpTransport new HttpServerTransport({ app }); server.connect(httpTransport).then(() { app.listen(3000, () { console.log(HTTP服务已启动在端口3000); }); });9. 实际业务场景案例9.1 电商订单通知// 订单确认邮件模板 const orderConfirmationTemplate (order: Order) !DOCTYPE html html head style .order-table { width: 100%; border-collapse: collapse; } .order-table th, .order-table td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } /style /head body h2您的订单 #${order.id} 已确认/h2 table classorder-table ${order.items.map(item tr td${item.name}/td td${item.quantity} × ¥${item.price}/td td¥${item.quantity * item.price}/td /tr ).join()} /table p总计: ¥${order.total}/p /body /html ; // 在工具调用中使用 server.setRequestHandler(CallToolRequestSchema, async (req) { if (req.params.name send-order-confirmation) { const html orderConfirmationTemplate(req.params.arguments.order); return transporter.sendMail({ to: req.params.arguments.email, subject: 订单确认: #${req.params.arguments.order.id}, html, }); } });9.2 用户注册验证// 生成验证链接 function generateVerificationLink(userId: string, token: string) { return https://example.com/verify?userId${userId}token${token}; } // 发送验证邮件 server.setRequestHandler(CallToolRequestSchema, async (req) { if (req.params.name send-verification-email) { const link generateVerificationLink( req.params.arguments.userId, req.params.arguments.token ); return transporter.sendMail({ to: req.params.arguments.email, subject: 请验证您的邮箱, html: 请点击链接完成验证: a href${link}${link}/a, }); } });10. 持续维护与更新策略10.1 版本管理建议采用语义化版本控制MAJOR不兼容的API修改MINOR向下兼容的功能新增PATCH向下兼容的问题修正package.json 示例{ name: mcp-email-server, version: 1.0.0, engines: { node: 18.0.0 }, scripts: { release:major: npm version major, release:minor: npm version minor, release:patch: npm version patch } }10.2 变更日志规范保持CHANGELOG.md文件记录# 变更日志 ## [1.1.0] - 2025-03-15 ### 新增 - 支持邮件模板系统 - 添加插件架构基础 ### 修复 - 解决附件编码问题 - 修正SMTP连接池泄漏 ## [1.0.0] - 2025-01-10 ### 初始版本 - 基础邮件发送功能 - MCP协议标准实现10.3 依赖更新策略使用npm outdated定期检查过时依赖为生产环境锁定依赖版本pnpm install --save-exact packageversion使用 Dependabot 或 Renovate 自动化更新11. 社区资源与学习路径11.1 推荐学习资源官方文档MCP 协议规范Cherry Studio 开发者指南开源项目MCP 示例仓库Awesome MCP视频教程MCP 全栈开发系列课程Cherry Studio 官方频道11.2 常见问题速查表问题现象可能原因解决方案工具调用超时网络问题/处理时间过长增加超时设置/优化处理逻辑附件无法正常显示编码问题/大小限制检查Base64编码/分片处理Cherry Studio 连接失败环境变量缺失/版本不兼容检查.env文件/更新SDK版本邮件进入垃圾箱SPF/DKIM未配置完善域名验证记录高并发下连接断开资源不足/连接泄漏优化连接池配置/增加监控11.3 进阶学习方向协议层深入理解 MCP 协议设计原理研究二进制协议优化方案安全领域实现端到端加密通信开发审计日志系统性能优化引入 Rust 扩展关键路径实现水平扩展架构生态扩展开发可视化配置界面创建模板市场12. 项目完整配置参考12.1 生产环境配置示例.env.production:# SMTP 配置 SMTP_HOSTsmtp.mailservice.com SMTP_PORT465 SMTP_USERno-replyyourdomain.com SMTP_PASSWORDyour-strong-password # 性能调优 CONNECTION_POOL_MAX10 CONNECTION_TIMEOUT30000 # 安全设置 RATE_LIMIT100 ALLOWED_DOMAINSyourdomain.com12.2 开发脚本集package.json片段{ scripts: { build: tsc, start: node dist/index.js, dev: ts-node-dev --respawn src/index.ts, test: vitest, coverage: vitest run --coverage, lint: eslint . --ext .ts, format: prettier --write ., docker:build: docker build -t mcp-email-server ., docker:run: docker run -p 3000:3000 --env-file .env mcp-email-server } }12.3 完整技术栈类别技术选型运行时Node.js 18 TypeScript 5协议实现modelcontextprotocol/sdk邮件服务nodemailer测试框架vitest happy-dom代码质量ESLint Prettier部署方式Docker Kubernetes监控系统Prometheus Grafana日志管理Winston ELK
Node.js + TypeScript 搭建 MCP Server 保姆级教程(含 Cherry Studio 集成避坑指南)
Node.js TypeScript 构建企业级 MCP Server 全流程指南1. 为什么选择 MCP 协议进行 AI 工具开发在当今 AI 应用开发领域Model Context ProtocolMCP正在成为连接大语言模型与外部工具的事实标准协议。与传统的 API 调用方式相比MCP 提供了更标准化、更安全的交互方式协议标准化统一了不同工具间的调用规范安全隔离通过 STDIO/SSE 模式实现沙箱环境开发友好提供完善的 TypeScript SDK 支持生态丰富已有数百个开源 MCP Server 实现对于 Node.js 开发者而言使用 TypeScript 开发 MCP Server 具有显著优势类型安全保证工具定义的准确性完善的异步处理机制适合 AI 场景丰富的 npm 生态可快速集成各类服务编译检查能在早期发现接口定义问题// 典型 MCP Server 类型定义示例 interface McpServerConfig { name: string; version: string; capabilities: { tools?: Recordstring, ToolDefinition; resources?: ResourceRegistry; }; }2. 开发环境准备与项目初始化2.1 基础环境配置推荐使用以下工具链组合工具推荐版本作用Node.js18.x LTS运行时环境TypeScript5.0类型检查与编译pnpm8.x包管理更快更节省空间VS Code最新版开发IDEDocker Desktop4.25容器化部署环境验证命令# 检查Node.js版本 node -v # 检查pnpm安装 pnpm -v # 检查TypeScript tsc --version2.2 项目初始化步骤创建项目目录并初始化mkdir mcp-email-server cd mcp-email-server pnpm init安装 TypeScript 及相关依赖pnpm add -D typescript types/node npx tsc --init修改tsconfig.json关键配置{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true } }添加基础项目结构├── src │ ├── index.ts # 入口文件 │ └── types.ts # 类型定义 ├── test # 测试目录 ├── .env.example # 环境变量示例 └── package.json3. MCP Server 核心实现3.1 安装 MCP SDK 依赖pnpm add modelcontextprotocol/sdk dotenv pnpm add -D types/node modelcontextprotocol/types3.2 基础服务器框架#!/usr/bin/env node import { Server } from modelcontextprotocol/sdk/server; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio; import { ListToolsRequestSchema } from modelcontextprotocol/sdk/types; import dotenv from dotenv; // 加载环境变量 dotenv.config(); const server new Server( { name: email-mcp-server, version: 1.0.0, }, { capabilities: { tools: {}, }, } ); // 必须实现的工具列表接口 server.setRequestHandler(ListToolsRequestSchema, async () { return { tools: [ { name: send-email, description: 发送HTML格式邮件支持附件, inputSchema: { type: object, properties: { to: { type: string, description: 收件人地址多个用逗号分隔 }, subject: { type: string, description: 邮件主题 }, html: { type: string, description: HTML内容 }, attachments: { type: array, items: { type: object, properties: { filename: { type: string }, content: { type: string, format: binary }, }, }, }, }, required: [to, subject], }, }, ], }; }); async function bootstrap() { const transport new StdioServerTransport(); await server.connect(transport); console.error([MCP Server] 服务已启动); } bootstrap().catch((err) { console.error([MCP Server] 启动失败:, err); process.exit(1); });3.3 邮件发送功能实现安装 nodemailer 依赖pnpm add nodemailer types/nodemailer扩展工具处理逻辑import { CallToolRequestSchema } from modelcontextprotocol/sdk/types; import nodemailer from nodemailer; // 配置邮件传输器 const transporter nodemailer.createTransport({ host: process.env.SMTP_HOST, port: parseInt(process.env.SMTP_PORT || 465), secure: true, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD, }, }); server.setRequestHandler(CallToolRequestSchema, async (request) { try { const { name, arguments: args } request.params; if (name send-email) { const mailOptions { from: AI助理 ${process.env.SMTP_USER}, to: args.to, subject: args.subject, html: args.html, attachments: args.attachments, }; const info await transporter.sendMail(mailOptions); return { success: true, data: { messageId: info.messageId, accepted: info.accepted, } }; } return { success: false, error: 未知工具: ${name} }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 未知错误 }; } });4. Cherry Studio 集成指南4.1 环境准备Cherry Studio 对运行环境有特殊要求必须安装的运行时Bun (替代Node.js)uv (Python包管理)推荐安装方式# 使用bun安装uv bun install -g uv4.2 配置对接在Cherry Studio中添加MCP Server的配置示例{ mcpServers: { email-service: { command: bun, args: [run, start], env: { SMTP_HOST: smtp.example.com, SMTP_PORT: 465, SMTP_USER: youremail.com, SMTP_PASSWORD: your-password } } } }4.3 常见集成问题解决问题1连接超时解决方案检查Cherry Studio和Server是否在同一网络确认防火墙未阻止进程通信问题2工具列表不显示解决方案确保实现了ListToolsRequestSchema处理器检查工具定义的JSON Schema是否符合规范问题3权限不足解决方案为Server进程配置适当的文件系统权限在Docker中运行时正确映射卷5. 高级功能与生产环境部署5.1 邮件模板管理实现动态模板加载功能import fs from fs/promises; import path from path; async function loadTemplate(templateName: string, variables: Recordstring, string) { const templatePath path.join(__dirname, templates, ${templateName}.html); let content await fs.readFile(templatePath, utf-8); // 替换变量 for (const [key, value] of Object.entries(variables)) { content content.replace(new RegExp({{${key}}}, g), value); } return content; }5.2 Docker 容器化部署创建DockerfileFROM node:18-alpine WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN corepack enable pnpm install COPY . . RUN pnpm build ENV NODE_ENVproduction CMD [node, dist/index.js]构建并运行docker build -t mcp-email-server . docker run -d --name email-server \ -e SMTP_HOSTsmtp.example.com \ -e SMTP_USERyouremail.com \ -e SMTP_PASSWORDyour-password \ -p 3000:3000 \ mcp-email-server5.3 性能优化建议连接池配置const transporter nodemailer.createTransport({ pool: true, maxConnections: 5, maxMessages: 100, // ...其他配置 });日志监控import winston from winston; const logger winston.createLogger({ level: info, format: winston.format.json(), transports: [ new winston.transports.File({ filename: error.log, level: error }), new winston.transports.File({ filename: combined.log }), ], }); // 在工具调用中添加日志 server.setRequestHandler(CallToolRequestSchema, async (req) { logger.info(工具调用: ${req.params.name}, { timestamp: new Date(), arguments: req.params.arguments }); // ...处理逻辑 });6. 安全最佳实践6.1 敏感信息管理推荐方案使用dotenv管理环境变量生产环境使用 Vault 或 AWS Secrets Manager永远不要将凭据硬编码在代码中.env 文件示例# SMTP 配置 SMTP_HOSTsmtp.example.com SMTP_PORT465 SMTP_USERserviceexample.com SMTP_PASSWORDyour-strong-password # 加密密钥 JWT_SECRETyour-random-secret6.2 输入验证强化import { z } from zod; const emailSchema z.object({ to: z.string().email().or(z.string().regex(/^[^][^]\.[^](,[^][^]\.[^])*$/)), subject: z.string().min(1).max(100), html: z.string().optional(), attachments: z.array( z.object({ filename: z.string(), content: z.string(), }) ).optional(), }); server.setRequestHandler(CallToolRequestSchema, async (req) { try { const validated emailSchema.parse(req.params.arguments); // ...处理逻辑 } catch (err) { return { success: false, error: 输入验证失败 }; } });6.3 速率限制使用express-rate-limit实现基础防护import rateLimit from express-rate-limit; const limiter rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 每个IP限制100次请求 }); // 在HTTP服务中应用(如果暴露HTTP接口) app.use(limiter);7. 测试与调试技巧7.1 单元测试配置安装测试依赖pnpm add -D vitest vitest/coverage-v8 happy-dom示例测试代码import { describe, it, expect } from vitest; import { validateEmailInput } from ../src/validator; describe(邮件输入验证, () { it(应接受有效的单个邮箱, () { const input { to: testexample.com, subject: 测试 }; expect(validateEmailInput(input)).toBeTruthy(); }); it(应拒绝无效的主题, () { const input { to: testexample.com, subject: }; expect(() validateEmailInput(input)).toThrow(); }); });7.2 集成测试方案使用node-mocks-http模拟 MCP 协议交互import { MockMcpTransport } from ./mocks; import { server } from ../src; describe(MCP 协议测试, () { it(应正确返回工具列表, async () { const transport new MockMcpTransport(); await server.connect(transport); const response await transport.request({ type: ListToolsRequest, params: {}, }); expect(response.tools).toBeInstanceOf(Array); expect(response.tools[0].name).toBe(send-email); }); });7.3 调试技巧VS Code 调试配置{ version: 0.2.0, configurations: [ { type: node, request: launch, name: 调试 MCP Server, skipFiles: [node_internals/**], program: ${workspaceFolder}/src/index.ts, preLaunchTask: tsc: build, outFiles: [${workspaceFolder}/dist/**/*.js], env: { SMTP_HOST: localhost, SMTP_USER: testexample.com } } ] }协议分析工具使用 Wireshark 分析 STDIO 通信开发中间件记录协议消息8. 项目优化与扩展方向8.1 性能监控集成import Prometheus from prom-client; const httpRequestDuration new Prometheus.Histogram({ name: http_request_duration_seconds, help: Duration of HTTP requests in seconds, labelNames: [method, route, code], buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10], }); // 在工具调用中记录指标 server.setRequestHandler(CallToolRequestSchema, async (req) { const end httpRequestDuration.startTimer(); try { // ...处理逻辑 end({ method: MCP, route: req.params.name, code: 200 }); } catch (err) { end({ method: MCP, route: req.params.name, code: 500 }); throw err; } });8.2 插件系统设计实现可扩展的插件架构interface EmailPlugin { name: string; beforeSend?(mail: MailOptions): PromiseMailOptions; afterSend?(result: SendMailResult): Promisevoid; } class PluginManager { private plugins: EmailPlugin[] []; register(plugin: EmailPlugin) { this.plugins.push(plugin); } async applyBeforeSendHooks(mail: MailOptions) { for (const plugin of this.plugins) { if (plugin.beforeSend) { mail await plugin.beforeSend(mail); } } return mail; } }8.3 多协议支持扩展支持 HTTP 和 WebSocketimport { HttpServerTransport } from modelcontextprotocol/sdk/server/http; import express from express; const app express(); app.use(express.json()); const httpTransport new HttpServerTransport({ app }); server.connect(httpTransport).then(() { app.listen(3000, () { console.log(HTTP服务已启动在端口3000); }); });9. 实际业务场景案例9.1 电商订单通知// 订单确认邮件模板 const orderConfirmationTemplate (order: Order) !DOCTYPE html html head style .order-table { width: 100%; border-collapse: collapse; } .order-table th, .order-table td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } /style /head body h2您的订单 #${order.id} 已确认/h2 table classorder-table ${order.items.map(item tr td${item.name}/td td${item.quantity} × ¥${item.price}/td td¥${item.quantity * item.price}/td /tr ).join()} /table p总计: ¥${order.total}/p /body /html ; // 在工具调用中使用 server.setRequestHandler(CallToolRequestSchema, async (req) { if (req.params.name send-order-confirmation) { const html orderConfirmationTemplate(req.params.arguments.order); return transporter.sendMail({ to: req.params.arguments.email, subject: 订单确认: #${req.params.arguments.order.id}, html, }); } });9.2 用户注册验证// 生成验证链接 function generateVerificationLink(userId: string, token: string) { return https://example.com/verify?userId${userId}token${token}; } // 发送验证邮件 server.setRequestHandler(CallToolRequestSchema, async (req) { if (req.params.name send-verification-email) { const link generateVerificationLink( req.params.arguments.userId, req.params.arguments.token ); return transporter.sendMail({ to: req.params.arguments.email, subject: 请验证您的邮箱, html: 请点击链接完成验证: a href${link}${link}/a, }); } });10. 持续维护与更新策略10.1 版本管理建议采用语义化版本控制MAJOR不兼容的API修改MINOR向下兼容的功能新增PATCH向下兼容的问题修正package.json 示例{ name: mcp-email-server, version: 1.0.0, engines: { node: 18.0.0 }, scripts: { release:major: npm version major, release:minor: npm version minor, release:patch: npm version patch } }10.2 变更日志规范保持CHANGELOG.md文件记录# 变更日志 ## [1.1.0] - 2025-03-15 ### 新增 - 支持邮件模板系统 - 添加插件架构基础 ### 修复 - 解决附件编码问题 - 修正SMTP连接池泄漏 ## [1.0.0] - 2025-01-10 ### 初始版本 - 基础邮件发送功能 - MCP协议标准实现10.3 依赖更新策略使用npm outdated定期检查过时依赖为生产环境锁定依赖版本pnpm install --save-exact packageversion使用 Dependabot 或 Renovate 自动化更新11. 社区资源与学习路径11.1 推荐学习资源官方文档MCP 协议规范Cherry Studio 开发者指南开源项目MCP 示例仓库Awesome MCP视频教程MCP 全栈开发系列课程Cherry Studio 官方频道11.2 常见问题速查表问题现象可能原因解决方案工具调用超时网络问题/处理时间过长增加超时设置/优化处理逻辑附件无法正常显示编码问题/大小限制检查Base64编码/分片处理Cherry Studio 连接失败环境变量缺失/版本不兼容检查.env文件/更新SDK版本邮件进入垃圾箱SPF/DKIM未配置完善域名验证记录高并发下连接断开资源不足/连接泄漏优化连接池配置/增加监控11.3 进阶学习方向协议层深入理解 MCP 协议设计原理研究二进制协议优化方案安全领域实现端到端加密通信开发审计日志系统性能优化引入 Rust 扩展关键路径实现水平扩展架构生态扩展开发可视化配置界面创建模板市场12. 项目完整配置参考12.1 生产环境配置示例.env.production:# SMTP 配置 SMTP_HOSTsmtp.mailservice.com SMTP_PORT465 SMTP_USERno-replyyourdomain.com SMTP_PASSWORDyour-strong-password # 性能调优 CONNECTION_POOL_MAX10 CONNECTION_TIMEOUT30000 # 安全设置 RATE_LIMIT100 ALLOWED_DOMAINSyourdomain.com12.2 开发脚本集package.json片段{ scripts: { build: tsc, start: node dist/index.js, dev: ts-node-dev --respawn src/index.ts, test: vitest, coverage: vitest run --coverage, lint: eslint . --ext .ts, format: prettier --write ., docker:build: docker build -t mcp-email-server ., docker:run: docker run -p 3000:3000 --env-file .env mcp-email-server } }12.3 完整技术栈类别技术选型运行时Node.js 18 TypeScript 5协议实现modelcontextprotocol/sdk邮件服务nodemailer测试框架vitest happy-dom代码质量ESLint Prettier部署方式Docker Kubernetes监控系统Prometheus Grafana日志管理Winston ELK