从 0 到 1 构建 MCP Server:一个 FDE 的工程实践

MCP 的价值不是“又多了一个协议”,而是让企业已有系统能以标准方式暴露给 AI 客户端调用。对 FDE 来说,它是把客户内部能力接入 Agent 工作流的基础件。

事实说明
参考来源
Model Context Protocol 官方站点MCP GitHub 组织@modelcontextprotocol/sdk npm 页面
判断边界
MCP 生态和传输规范仍在快速演进。本文适合作为工程入门和选型参考,生产接入前应重新核对当前 SDK 版本、客户端支持范围和安全要求。

为什么 FDE 要关心 MCP

客户现场最常见的问题不是“AI 不会回答”,而是“AI 拿不到正确系统里的数据,也不能安全地执行动作”。MCP 把工具、资源和提示词模板用统一协议暴露出来,让 Claude、Cursor、内部 Agent 或其他客户端可以用一致的方式调用。

MCP 对 AI 生态的意义,类似 USB-C 对硬件的意义:统一接口,降低集成成本,让能力可以自由流通。

先把概念搞清楚

Tools
可被 AI 主动调用的函数,例如查询订单、创建工单、发送通知。多数业务集成从 Tools 开始。
Resources
可读取的数据源,例如文件、日志、知识库条目。适合提供上下文,不应产生副作用。
Prompts
预置提示词模板,用标准方式触发某类工作流。客户端支持度不同,生产前要验证。

Transport 选哪个

方式适用场景注意事项
STDIO本地工具、CLI、开发调试stdout 是协议通道,日志请走 stderr 或文件。
Streamable HTTP远程服务、团队共享、生产部署要补齐鉴权、限流、审计和错误处理。

一个最小 TypeScript Server

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "ticket-server", version: "1.0.0" });

server.tool(
  "get_ticket",
  "根据工单 ID 查询标题、状态和负责人",
  { ticketId: z.string().describe("工单唯一 ID,例如 TICKET-1234") },
  async ({ ticketId }) => ({
    content: [{ type: "text", text: JSON.stringify({ ticketId, status: "open" }) }]
  })
);

await server.connect(new StdioServerTransport());

真实踩坑

  1. 工具描述含糊,AI 会误调用。描述要写清楚“什么时候用”和“参数格式”。
  2. 工具职责过宽,AI 很容易传错参数。一个工具最好只做一件事。
  3. 错误返回不清楚,Agent 会继续错误重试。错误也要结构化返回。
  4. 生产部署不能只跑通 demo,要补鉴权、审计、超时、限流和敏感字段脱敏。

MCP 不难,难的是把已有系统的能力设计成 AI 能稳定理解、稳定调用、失败可恢复的工具。FDE 的价值就在这里:不是把协议跑起来,而是把业务能力接进可靠的工作流。

欢迎通过邮件和我交流:shaoyanyan91@163.com