十分钟搭一个 MCP 服务器:TypeScript 与 Python 双版本实战教程
【免费下载链接】skillsPublic repository for Agent Skills项目地址: https://gitcode.com/GitHub_Trending/skills3/skills
想让 AI 替你查仓库、发消息、拉数据,光靠提示词不够,它得有一把"钥匙"——这就是 MCP 服务器。这篇 MCP 教程按最短路径讲如何构建 MCP 服务器:TypeScript 和 Python 各给一份最小可运行代码,十分钟跑通。
什么时候你需要一个 MCP 服务器
两个场景。一是让 AI 查 GitHub 上的 issue:直接提问,它只能按"记忆"回答,数据是旧的;把 API 包成 MCP 服务器,它就能实时调接口拿真数据。二是让 AI 往 Slack 发通知、把工单同步到 Jira。这类"替 AI 动手操作外部服务"的需求,就是 MCP 服务器的价值所在。
选型先做:TypeScript 还是 Python
结论先行:团队主力是 Node,就用 TypeScript 写 MCP 服务器;想最快出活、已有 Python 服务,就选 Python。两边协议完全一致,工具命名和返回格式对齐即可,随时能换。
| 维度 | TypeScript | Python(FastMCP) |
|---|---|---|
| 类型安全 | 强,Zod 运行时校验,坏参数当场拦截 | 中,Pydantic 校验,类型提示可选 |
| 开发速度 | 中,要配 tsconfig 和编译步骤 | 快,函数加个装饰器就注册好了 |
| 生态依赖 | Node 生态,官方 SDK 维护,发 npm 包顺手 | httpx 等成熟 HTTP 库,数据工具链齐全 |
十分钟跑通:初始化、注册工具、本地验证
第 1 步,初始化。TypeScript:建目录,npm init -y,装上 @modelcontextprotocol/sdk 和 zod,配好 tsconfig 就能写代码。Python:一行pip install fastmcp,传输层和注册逻辑框架全包了。
第 2 步,注册第一个工具。工具 = 名字 + 描述 + 输入规则 + 实现,其中描述是 AI 决定"什么时候用我"的依据,务必写清楚。TypeScript 版:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; const server = new McpServer({ name: "demo", version: "1.0.0" }); // 描述是 AI 选择工具的依据,别写"工具1"这种废话 server.registerTool("get_time", { description: "获取当前时间", inputSchema: {} }, async () => ({ content: [{ type: "text", text: new Date().toISOString() }] })); await server.connect(new StdioServerTransport()); // stdio 传输:本地调试走它Python 版更短,docstring 自动变成描述:
from fastmcp import FastMCP from datetime import datetime mcp = FastMCP("demo") @mcp.tool() async def get_time() -> str: """获取当前时间,docstring 自动变成工具描述""" return datetime.now().isoformat() mcp.run() # 默认 stdio 传输,本地调试直接可用第 3 步,本地验证。两种语言都先走 stdio:用 MCP Inspector 连上你的进程,确认 get_time 出现在工具列表里,手动调用一次,返回当前时间就算跑通。TypeScript 用npx @modelcontextprotocol/inspector拉起,Python 直接fastmcp dev main.py就有 Web 调试页。
让工具说"人话":输入校验与返回格式
为什么必须校验?因为传参的是 AI,不是人。它照着描述猜参数,猜错了如果直接打到下游服务,你拿到一个 500,它也只会再猜一次。在校验层拦住、返回一句人话,它下一次就传对了:
// 校验即文档:约束写清楚,AI 才知道该传什么 const schema = z.object({ repo: z.string().min(2, "仓库名至少 2 个字符"), limit: z.number().int().max(50).default(20), // 兜底,防 AI 一次拉太多 });返回格式有两类读者。给人看的用 Markdown:标题、列表,一屏读完;给程序对接的用 JSON:字段稳定、可解析。一个工具只选一种主格式,列表类工具建议用 Markdown,别混着来。
踩坑预警 ⚠️:错误、分页、超时
坑一:AI 看不懂你的报错。现象:下游挂了,AI 只收到"Error: 500",然后傻重试。原因:把 HTTP 原始状态码直接透传了。怎么办:捕获后翻译成可操作的话——"仓库不存在,请检查名字拼写"、"请求太频繁,稍后再试",404、限流、网络错误分开处理。
坑二:列表工具一调就卡。现象:大仓库查一次,内存飙升或直接超时。原因:一次把上千条全返回了。怎么办:默认每页 20–50 条,响应里带上 has_more 和 next_offset,让 AI 自己翻页。
坑三:偶尔卡死几十秒。现象:多数时候正常,偶尔挂起很久。原因:HTTP 客户端没设超时,上游慢的时候连接被无限占住。怎么办:显式设 5–10 秒超时,超时统一返回"上游服务响应超时,请稍后重试"。
上线:从本机 stdio 到远程 HTTP
stdio 适合本地单客户端:AI 客户端拉起你的进程,用完即走,调试方便。多人共享或跨机器访问,就得切到 HTTP。TypeScript 里把 StdioServerTransport 换成 StreamableHTTPServerTransport 并监听端口;Python 里给 FastMCP 指定 host、port 并声明 http 传输。切换时记住两点:进程不再由客户端拉起,你得自己管好生命周期;多了一个网络边界,至少加个 token 鉴权。
下一步
到这里,一个能跑、能验、能上线的 MCP 服务器就齐了。别停在 get_time:挑你最熟的一个 API,把真实工具、错误翻译、分页补齐,再用 MCP Inspector 跑几轮真实提问,看 AI 用着顺不顺手。仓库里的 mcp-builder 技能带现成的评估流程,可以照着出一组测试题。
【免费下载链接】skillsPublic repository for Agent Skills项目地址: https://gitcode.com/GitHub_Trending/skills3/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考