尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

解密 MCP 协议:如何用 Node.js 从零手写一个本地文件读取 MCP 服务器

解密 MCP 协议:如何用 Node.js 从零手写一个本地文件读取 MCP 服务器
📅 发布时间:2026/7/5 2:55:08

解密 MCP 协议:如何用 Node.js 从零手写一个本地文件读取 MCP 服务器

  • 前言
  • 为什么需要 MCP?它解决了什么问题?
  • 开发准备
  • 核心实现:手写 `simple-read-mcp` 服务
    • 代码深度解析
  • 落地集成:接入 AI 研发环境
  • 总结

前言

在当下大语言模型(LLM)与 AI Agent 技术爆发的时代,AI 助手在编写代码、解答疑问时表现得越发成熟。然而,受限于自身的训练数据与运行沙箱,AI 在执行“实时任务”或“触达本地生态”时常显得无能为力——它既无法感知你的本地文件,也无法直接调用你的专属工具。

为了打破这种“认知沙箱”,Anthropic 推出了MCP(Model Context Protocol,模型上下文协议)。它统一了 AI 与外部数据源、工具之间的通信标准。

本文将跳过复杂的理论灌输,通过基于 Node.js 的原生开发视角,带你从零手写一个具备本地文件读取能力(File System Server)的 MCP 服务,并将其接入到现代化 AI IDE 中。读完本文,你不仅能掌握 MCP 的底层通信逻辑,更能亲手为你的 AI 助手装上一双触达本地系统的“手”。


为什么需要 MCP?它解决了什么问题?

在 MCP 出现之前,如果你想让 AI 读取本地项目结构或文件,通常需要通过 IDE 插件或是自定义脚本来硬编码拼凑 Prompt。这种模式存在两个核心痛点:

  1. 接口标准不一:每个应用、每个扩展都有自己的数据组织形式,开发迁移成本极高。
  2. 上下文孤立:大模型无法以结构化、可感知的方式确认自己是否拥有某种能力,难以进行精准的工具决策。

MCP 就像是 AI 时代的“USB 接口协议”。它定义了一个标准的 C/S(Client/Server)架构:

  • MCP Host / Client(宿主/客户端):例如集成了 AI 能力的开发工具(Trae、VS Code 或是 Claude Desktop)。它们负责接收用户的自然语言指令,并将指令翻译给 AI。
  • MCP Server(服务器):由开发者编写的独立服务,负责暴露具体的“工具(Tools)”或“资源(Resources)”。

当用户发出指令时,整体的工作流如下所示:

  1. 用户下达指令:在 AI 聊天框输入:“帮我看看本地config.json里写了什么”。
  2. 客户端与大模型决策:Host 接收 Prompt 传给 LLM,LLM 分析上下文发现需要读取文件,于是选中了注册在客户端内的read_file工具。
  3. 协议传输(Stdio 管道):客户端通过标准输入(stdin)向 MCP Server 发送一条 JSON-RPC 请求。
  4. 服务器执行:MCP Server 接收请求,调用底层的fs模块执行本地文件读取,并将结果通过标准输出(stdout)返回。
  5. 生成最终响应:客户端(Host)将读取到的文件上下文喂给 LLM,LLM 根据最新的完整数据生成最终回复返还给用户。

通过这一层标准化的封装,LLM 可以在不需要知道本地细节的情况下,安全、动态地调用各类本地或者云端服务。


开发准备

在开始动手之前,我们需要初始化一个 Node.js 项目并引入相关的依赖。这里主要依赖两个核心库:

  1. @modelcontextprotocol/sdk:官方提供的协议 SDK,帮助我们快捷实现符合 MCP 规范的底层通信与生命周期管理。
  2. zod:一个强类型 Schema 声明与验证库。由于 MCP 核心需要向 LLM 声明工具的输入参数格式,Zod 能够提供极简且严谨的校验能力,避免手写繁琐的 JSON Schema。

首先,在你的终端中执行如下命令进行依赖安装:

pnpmi zod @modelcontextprotocol/sdk

核心实现:手写simple-read-mcp服务

接下来,我们创建一个名为app.service.mjs(或者其他符合 ECMAScript Modules 规范的命名)的文件。以下是完整的核心代码实现:

import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{z}from"zod";importfsfrom'fs/promises';// 1. 实例化 MCP 服务端constserver=newMcpServer({name:'simple-read-mcp',version:'1.0.0'});// 2. 利用新版极简工具注册器注册 read_file 工具server.tool("read_file","读取指定路径的本地文件内容",{path:z.string().describe("文件的绝对或相对路径")// 校验参数是否为字符串,并提供描述供 LLM 理解},async({path})=>{try{// 执行本地异步文件读取constcontent=awaitfs.readFile(path,'utf-8');// 严格按照 MCP 规范返回 text 类型的上下文数据return{content:[{type:"text",text:content}]};}catch(err){// 容错处理:若文件不存在或无权限,返回 error 标识并附带错误原因return{isError:true,content:[{type:"text",text:`读取文件失败:${err.message}`}]};}});// 3. 异步启动函数,建立标准输入输出通信通道asyncfunctionmain(){consttransport=newStdioServerTransport();awaitserver.connect(transport);console.error("MCP read_file 服务已启动(stdio模式)");}main().catch(console.error);

代码深度解析

很多开发者在接触 MCP 时,容易被繁琐的协议细节劝退。上面的代码利用了新版官方 SDK 的高层抽象,非常优雅地完成了功能实现。我们来重点拆解它的几个关键设计:

  • new McpServer(...):初始化 MCP 服务的实例。服务名(name)和版本(version)会在 Client 与 Server 建立连接时进行握手交换,便于客户端识别和管理。
  • server.tool(...)内的 Schema 声明:这是 MCP 的精髓所在。我们不需要用复杂的 JSON 格式去写定义,而是直接传入read_file的名字、功能的自然语言描述,以及一个 Zod 对象{ path: z.string().describe(...) }。大模型就是通过这些“描述文字(Description)”来感知这个工具有什么用、需要什么参数的。当大模型决定调用时,Zod 会在底层自动拦截并校验入参是否合法。
  • 返回值结构体:MCP 协议规定了 Server 返回给大模型的上下文格式。必须符合{ content: [{ type: "text", text: ... }] }的数组嵌套结构。如果中途发生异常(例如无权限、路径不存在),则需提供isError: true标记,告知大模型执行失败,以便大模型在后续对话中进行调整或向用户报错。
  • StdioServerTransport与console.error的设计妙处:
    在主函数main中,我们采用了 Stdio(标准输入输出)进程管道进行通信。这意味着客户端与服务器之间传递 JSON-RPC 数据是通过process.stdin和process.stdout完成的。
    因此,服务器代码中绝对不能出现普通的console.log。因为任何console.log都会污染stdout管道,导致客户端解析 JSON 报错。这就解释了为什么代码中提示服务启动的日志必须使用console.error输出——因为stderr不会影响主通信管道,它是安全的日志输出通道。

落地集成:接入 AI 研发环境

编写完代码后,如何让我们的 AI 编辑器(如 Trae / VS Code 等)用上这个工具呢?

我们可以通过编辑编辑器支持的 MCP 配置文件(通常位于项目根目录的.trae/mcp.json或全局配置中)来导入该服务。配置的核心逻辑是告诉 Host 如何用 Node 启动我们写好的脚本:

{"mcpServers":{"simple-read-mcp":{"command":"node","args":["/你的项目绝对路径/app.service.mjs"],"disabled":false}}}

配置完成后,打开编辑器的 MCP 管理面板,你会看到如图所示的界面:

当看到simple-read-mcp显示为启用状态且带有绿色对勾时,说明宿主客户端已经成功通过 Stdio 管道拉起了我们的 Node.js 进程,并完成了能力握手。

现在,你可以在聊天对话框或者 Agent 模式下直接对 AI 说:“帮我分析一下系统里根目录下的package.json”。AI 将在后台自动识别并调用read_file工具,读取内容并给出专业的解答。


总结

MCP 协议的出现,在 LLM 与本地物理世界之间架起了一座标准化的桥梁。通过本文的实践,我们仅用了不到 40 行的 Node.js 代码,就实现了一个安全、规范的本地文件读取服务器。

在实际的生产实践中,你可以基于此架构进行更广阔的扩展:

  • 安全性控制:在read_file中加入沙箱路径校验,防止 AI 被提示词攻击(Prompt Injection)进而读取系统敏感文件(如.env或~/.ssh)。
  • 多功能集成:在同一个McpServer实例上,通过server.tool继续挂载数据库查询、外部 API 联动、自动化编译等更多工具。

掌握 MCP,就是掌握了让 AI Agent 走向务实落地的钥匙。希望这篇文章能帮你顺利开启自定义 AI 工具库的大门!

相关新闻

  • Dify vs. Coze:从SaaS到私有化部署,掌握AI应用开发自主权
  • 小从不知名wordpress开发者推荐
  • Transformer(一):为什么是需要Transformer?

最新新闻

  • STM32F373VC与TPS65263的多电压域电源管理方案
  • SysML v2革命:如何用新一代建模语言破解复杂系统设计难题?
  • 告别命令行恐惧:3分钟学会用Crontab UI可视化管理Linux定时任务
  • GeWe 开发指南:微信朋友圈自动发布与定时运营系统实现
  • 如何用JavaQuestPlayer三步搞定QSP游戏开发:终极Java游戏引擎指南
  • Translation-Agent安全实践:10个技巧保护API密钥与数据隐私

日新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号