Preflight MCP服务器-开发人员指南
本文件适用于 开发Preflight的开发人员. 它解释了如何添加新的MCP工具、接线服务并遵循项目约定。
如果你是MCP的新手:把这个项目想象成 用于人工智能的后端API.
______________________________________________________________________
心理模型
- 这 人工智能 是客户端(通过MCP/stdio)
- MCP工具 是控制器
- HTTP路由 是控制器
- 服务 包含业务逻辑
- 适配器 处理I/O(数据库、文件)
经验法则:
控制器协调。\ 服务计算。\ 适配器与外界对话。
______________________________________________________________________
目录职责
tools/ → MCP controllers (AI-facing)
services/ → Business logic (shared)
adapters/ → Data access / external systems
schemas/ → Validation & contracts (Zod)
utils/ → Shared helpers (envelope, etc.)什么不该做
- ❌ 不要直接在工具或路由中获取数据
- ❌ 不要从MCP工具返回原始对象
- ❌ 不要将MCP逻辑放入服务中
- ❌ 不要在MCP和HTTP之间复制业务逻辑
______________________________________________________________________
体系结构概述
MCP Client ──▶ tools/*.tool.js ──▶ services/*.service.js ──▶ adapters/*- MCP工具和HTTP路由 共享相同的服务
- 服务是可重用和可测试的
- 传输(MCP vs HTTP)只是一个实现细节
______________________________________________________________________
添加新的MCP工具
例子: system.dateTime
1.创建工具文件
tools/system.tool.js2.注册工具
// tools/system.tool.js
import { z } from "zod";
import { ok, fail } from "../utils/index.js";
import { systemService } from "../services/system.service.js";
export const registerSystemTools = (server) => {
server.tool(
"system.dateTime",
{ timezone: z.string().optional() },
systemDateTime,
);
};3.出口自 tools/index.js
import { registerSystemTools } from "./system.tool.js";
export const registerAllTools = (server) => {
registerSystemTools(server);
};就是这样。人工智能现在可以呼叫 system.dateTime.
______________________________________________________________________
写作服务
服务包括 纯域逻辑 并且由MCP工具和HTTP路由共享。
// services/system.service.js
export const systemDateTime = async ({ timezone }) => {
try {
const tz = timezone ?? "UTC";
const now = new Date();
const parts = new Intl.DateTimeFormat("en-CA", {
timeZone: tz,
dateStyle: "short",
timeStyle: "medium",
hour12: false,
}).formatToParts(now);
const get = (type) => parts.find((p) => p.type === type)?.value;
const date = `${get("year")}-${get("month")}-${get("day")}`;
const time = `${get("hour")}:${get("minute")}:${get("second")}`;
return ok({
dateTime: `${date}T${time}`,
date,
time,
timezone: tz,
});
} catch (error) {
return fail(error);
}
};规则:
- 无MCP导入
- 无快递进口
- 没有Zod
- 没有信封
服务必须在任何地方都是可重用的。
______________________________________________________________________
返回响应(MCP)
所有MCP工具必须返回MCP兼容的信封。
import { ok, fail } from "../utils/index.js";
return ok({ result: "value" });切勿从工具中归还原始物品。
______________________________________________________________________
错误处理模式
- 验证边界处的输入(工具/路线)
- 捕捉控制器中的错误
- 返回安全、面向用户的消息
不要从MCP工具抛出未捕获的错误。
______________________________________________________________________
本地开发
MCP服务器
npm run start笔记:
- MCP使用stdio
- 重新启动会中断客户端连接
- 重新启动后重新连接客户端
调试提示
- 如果没有出现工具,请检查
tools/index.js - 如果结果为空,请检查MCP包络形状(
ok,data,meta) - 使用MCP检查器检查工具和响应
npm run mcp:inspect______________________________________________________________________
设计原则
- 保持控制器精简
- 保持服务纯粹
- 跨传输共享逻辑
- 清楚地命名MCP工具
- 在utils中集中处理协议怪癖
______________________________________________________________________
提交前检查表
- \[\]工具文件名
*.tool.js - \[\]工具已在中注册
tools/index.js - \[\]服务文件名
*.service.js - \[\]MCP重用的服务
- \[\]MCP不导入外部工具
- \[\]MCP工具没有原始退货
