从零构建 Node.js MCP Server —— 让 AI 读写你的文件系统
概要
上一篇文章介绍了如何用 Spring AI 构建 Java 版的 MCP Server。但 MCP 远不止 Java——它的官方 SDK 支持 TypeScript/Python/Kotlin,生态非常活跃。
本文将用 Node.js + TypeScript 从零搭建一个 MCP Server,并介绍如何将 AI 对话数据从 Elasticsearch 迁移到 MySQL 的数据管道设计。两个项目结合起来,展示了一条完整的 "AI 工具开发 + AI 数据工程" 链路。
MCP 官方工具:Filesystem Server
MCP 官方提供了开箱即用的文件系统 Server:
{
"dependencies": {
"@modelcontextprotocol/create-server": "^0.3.1",
"@modelcontextprotocol/server-filesystem": "^2025.3.28"
}
}
只需要在 AI 客户端配置中添加:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
}
}
}
配置完成后,AI 助手就能在你的指定目录中读文件、写文件、搜索文件——相当于给了 AI 一个受限的文件浏览器。
自定义 MCP Server:Disk Analyzer
官方工具虽然方便,但真实场景下往往需要自定义逻辑。以 "磁盘分析器" 为例:
// 基本结构
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "disk-analyzer",
version: "0.1.0",
}, {
capabilities: {
resources: {}, // 暴露数据给 AI 读取
tools: {}, // 暴露函数给 AI 调用
prompts: {} // 暴露提示词模板
}
});
// TODO: 注册 tools, resources, prompts
const transport = new StdioServerTransport();
await server.connect(transport);
一个 MCP Server 可以暴露三种能力:
| 能力 | 说明 | 示例 |
|---|---|---|
| Resources | 让 AI 读取结构化数据 | 磁盘使用报告、文件大小列表 |
| Tools | 让 AI 执行操作 | 删除临时文件、扫描大文件 |
| Prompts | 预定义的提示词模板 | "分析 C 盘空间并给出清理建议" |
开发与调试
MCP Server 通过标准输入输出(stdio)与客户端通信,调试不太直观。官方提供了 MCP Inspector:
npm run inspector
# 或直接使用
npx @modelcontextprotocol/inspector build/index.js
Inspector 会在浏览器中打开一个交互界面,可以:
- 查看 Server 提供的所有 tools/resources/prompts
- 手动构造请求测试每个能力
- 查看完整的请求/响应 JSON
AI 数据管道:ES → MySQL 迁移
另一个实用的场景是:AI 的对话历史存在 Elasticsearch 中,需要迁移到 MySQL 做持久化存储。我写了一个 Python 脚本处理这个迁移:
# 读取 ES 导出的 JSON
with open('input.json', 'r', encoding='utf-8') as f:
data = json.load(f)
messages = data['hits']['hits']
# 按会话 ID 分组
conversations = defaultdict(list)
for hit in messages:
conv_id = hit['_source']['metadata']['conversationId']
conversations[conv_id].append(hit)
# 生成 MySQL INSERT 语句
for conv_id, msgs in conversations.items():
title = extract_title(msgs) # 取第一条 USER 消息截断为标题
timestamps = [get_timestamp(m) for m in msgs]
sql = f"INSERT INTO chat_conversation (id, title, create_time) VALUES ..."
处理的数据结构:
{
"_source": {
"metadata": {
"conversationId": "1758640633392",
"messageType": "USER",
"timestamp": 1767051787364,
"jiacn": "oH2zD1PUPvspic..."
},
"content": "我要做一个水浒传题材的小游戏..."
}
}
输出两个 SQL 文件:
insert_conversations.sql—— 会话记录insert_messages.sql—— 消息记录(含序号、时间戳、metadata JSON)
脚本的关键设计点:
| 设计 | 实现 | 原因 |
|---|---|---|
| 会话自动提取标题 | 取第一条 USER 消息前 50 字符 | 用户第一句话通常是主题 |
| timestamp 容错 | metadata.timestamp → sort → now() | ES 字段可能缺失 |
| SQL 注入防护 | 单引号转义 '',反斜杠转义 \\ | 用户输入可能含特殊字符 |
| 消息顺序保留 | message_order 字段 | 保持对话的时间线 |
小结
这篇文章覆盖了两个方向:
- MCP Server 开发——Node.js SDK 让构建自定义 AI 工具变得简单,官方 Filesystem Server 开箱即用,自定义 Tool 只需要继承 SDK 标准接口
- AI 数据工程——ES 到 MySQL 的迁移脚本展示了如何用 Python 处理 AI 对话的结构化数据,类似的思路可以用于日志清洗、数据归档、多数据源汇聚
MCP 生态系统正在快速增长,现在入局正是好时机。
Disk Analyzer 源码见
D:\workspace\project\mcp-server\disk-analyzer\,ES 迁移脚本见D:\workspace\project\python-script\trans_es_to_mysql\。