5条Prompt实战:从零构建MCP Server,让AI助手安全调用本地工具 📅 发布时间:2026/8/22 13:04:04 👁 浏览次数: 1. 先搞清楚 MCP Server 是什么以及为什么需要它如果你最近在关注 AI 辅助编程尤其是使用 Cursor 这类工具可能会频繁听到MCP Server这个词。它听起来很技术但核心要解决的问题其实很直接让 AI 助手比如 Cursor 里的 AI 模型能够安全、可控地访问和使用你本地的工具、数据或服务。简单来说你可以把 MCP Server 理解为一个“翻译官”或“适配器”。AI 模型本身无法直接操作你的文件系统、数据库或调用某个本地 API。MCP Server 就负责定义一套标准接口告诉 AI“你可以通过我用这些特定的‘工具’Tools或‘资源’Resources来做事。” 然后当你在 Cursor 里对 AI 说“帮我把当前目录下的所有 .ts 文件整理到一个列表里”时AI 就能通过你写的 MCP Server调用一个“读取目录”的工具来完成这个任务。所以这个实战教程的价值在于它教你如何从零开始用几条清晰的Prompt来引导 AI比如 Claude 或 GPT-4快速搭建一个能实际工作的 MCP Server。这比单纯看文档要高效得多因为文档往往告诉你“是什么”而 Prompt 工程则直接引导你“怎么做”并在这个过程中让你理解背后的原理。最适合看这篇教程的人正在使用 Cursor、Claude Desktop 等支持 MCP 协议的 AI 编程工具的开发者。希望扩展 AI 助手能力让其能安全接入自己内部工具、私有 API 或特定数据源的团队。对 TypeScript/Node.js 有基本了解想学习如何将 AI 能力与现有工作流结合的工程师。最关键的一点通过这个教程你获得的不是仅仅一个服务器代码而是一套“用 Prompt 驱动复杂开发任务”的方法论。你会发现写好 Prompt 让 AI 帮你写代码比自己从头吭哧吭哧写要快得多而且 AI 还能帮你考虑一些你可能会忽略的边界情况。2. 动手前的环境与概念准备在开始跟着 Prompt 搭建之前你需要确保环境就绪并理解几个关键概念这样 AI 生成的代码你才能看得懂、改得了。2.1 核心环境配置Node.js 环境MCP Server 标准实现目前主要基于 Node.js。你需要安装Node.js 18或更高版本。可以在终端运行node -v和npm -v来确认。TypeScript教程和社区示例大量使用 TypeScript因为它能提供更好的类型安全和开发体验。确保已全局安装 TypeScriptnpm install -g typescript。代码编辑器/IDE强烈推荐使用Cursor或VS Code。本教程的 Prompt 思路在 Cursor 中实践效果最佳因为它深度集成了 AI 能力。如果你用 VS Code需要安装相应的 AI 插件如 Continue、Claude for VS Code 等。MCP 基础包你需要安装modelcontextprotocol/sdk这个官方 SDK。这是构建任何 MCP Server 的基石。2.2 必须理解的三个核心概念在给 AI 下 Prompt 前你自己得先明白要让 AI 做什么。MCP 协议主要围绕这三个概念展开Server服务器就是你将要构建的这个程序。它启动后会通过标准输入输出stdio或 HTTP 等方式等待 AI 客户端如 Cursor的连接和指令。Tools工具这是 Server 向 AI 暴露的核心能力。每个 Tool 都有一个名字、描述、输入参数定义JSON Schema和一个执行函数。例如一个read_file工具参数是file_path执行函数就是读取该路径文件并返回内容。AI 只能调用你明确声明和提供的 Tools。Resources资源你可以理解为一种只读的“数据源”。AI 可以通过 URI 来请求read这些资源的内容但不能修改。例如你可以将本地一个配置文件、一个数据库查询结果封装成 Resource 供 AI 参考。为什么先理解这些因为你的 Prompt 需要清晰地告诉 AI“请帮我创建一个 MCP Server它需要提供 A、B、C 这几个 Tools以及 X、Y 这几个 Resources。” 如果你自己都搞不清要什么AI 生成的代码就会偏离目标。2.3 项目初始化打开你的终端创建一个新的目录并初始化项目mkdir my-first-mcp-server cd my-first-mcp-server npm init -y然后安装核心依赖npm install modelcontextprotocol/sdk npm install -D typescript types/node tsx在package.json中添加一个启动脚本{ scripts: { dev: tsx watch src/index.ts, build: tsc, start: node dist/index.js } }创建tsconfig.json文件{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, outDir: ./dist, rootDir: ./src, strict: true, esModuleInterop: true, skipLibCheck: true, forceConsistentCasingInFileNames: true }, include: [src/**/*], exclude: [node_modules] }最后创建源代码目录和入口文件mkdir src touch src/index.ts现在你的基础开发环境就准备好了。接下来就是利用 Prompt 的力量让 AI 帮你填充src/index.ts的内容。3. 五条核心 Prompt 实战拆解下面这五条 Prompt 是一个循序渐进的构建指南。我建议你在 Cursor 里新建一个 Chat并将对话上下文关联到当前项目然后一条一条地喂给 AI比如 Claude 3.5 Sonnet 或 GPT-4。3.1 Prompt 1创建服务器骨架与基础工具你的输入Prompt“我将使用modelcontextprotocol/sdk构建一个 MCP Server。请先为我创建一个最基本的服务器骨架。这个服务器需要通过 stdio 传输。同时请先实现一个最简单的工具叫做get_server_info当被调用时返回一个简单的 JSON 对象包含服务器名称name和当前时间戳timestamp。请确保代码使用 TypeScript并包含必要的注释。”AI 会做什么及输出要点AI 会生成src/index.ts的初始内容。它会导入Server类和相关类型。创建一个Server实例。使用server.setRequestHandler来定义tools/list和tools/call的处理逻辑。在tools/list中返回get_server_info工具的定义包括名称、描述和参数 schema——本例无参数。在tools/call中处理对get_server_info的调用执行函数并返回结果。最后启动服务器监听 stdio。你需要检查和理解的地方工具定义看get_server_info工具的inputSchema是否为{ type: “object”, properties: {} }这表示它不需要输入参数。结果返回看tools/call处理函数中是否正确返回{ content: [{ type: “text”, text: JSON.stringify({ name: “My First MCP Server”, timestamp: Date.now() }) }] }。MCP 协议要求返回的内容是特定格式的数组。启动方式最后应该是server.connect(stdio).then(() console.error(‘MCP Server running…’));。注意是console.error因为 stdout 要留给协议通信。实测感跑通这个最简单的工具至关重要。它能验证你的环境、依赖和基础通信链路是否正常。先别急着加复杂功能。3.2 Prompt 2添加一个实用的文件读取工具你的输入Prompt“很好。现在请为这个服务器添加一个新的工具叫做read_file。这个工具应该接受一个字符串参数file_path描述是‘读取指定路径的文本文件内容’。在tools/call中实现其逻辑使用 Node.js 的fs/promises读取文件并以文本形式返回内容。请妥善处理错误例如文件不存在时返回一个用户友好的错误信息。同时更新tools/list的返回包含这个新工具。”AI 会做什么及输出要点AI 会修改代码主要更新两个部分tools/list处理器在返回的列表中添加第二个工具定义。inputSchema会包含file_path参数类型为string。tools/call处理器添加一个if (request.params.name “read_file”)的分支。在这个分支里使用await readFile(request.params.arguments?.file_path, ‘utf-8’)并将结果包装返回。它应该用try…catch包裹在catch中返回错误信息。你需要检查和理解的地方参数验证AI 生成的代码可能不会深入验证file_path是否为空或是否为绝对路径。这是一个潜在的改进点但对于第一个版本能处理基本错误即可。错误格式MCP 协议中工具调用错误应该通过返回{ content: […], isError: true }来标示。检查 AI 是否正确地设置了isError: true。导入语句确保文件顶部正确添加了import { readFile } from ‘fs/promises’;。边界感这个工具很强大但也危险。它允许 AI 读取你文件系统上的任何文件在进程权限内。在实际生产用途中你必须严格限制可访问的路径范围比如限制在项目目录内。这里为了学习我们先保持其通用性但心里要有这根弦。3.3 Prompt 3实现资源Resources列表与读取你的输入Prompt“现在我想引入 Resources 的概念。请让服务器在初始化时扫描当前项目目录下的所有.md文件并将它们作为 Resources 公布。每个 Resource 的 URI 可以设为file://${filePath}。同时请实现resources/list和resources/read请求处理器。resources/list返回这些 .md 文件的列表包含 URI 和名称。resources/read则根据请求的 URI 读取对应的 .md 文件内容并返回。”AI 会做什么及输出要点这是一个关键升级AI 需要添加readdir导入用于扫描目录。在服务器启动时或在一个函数中获取当前目录下所有.md文件列表并缓存起来。实现server.setRequestHandler对resources/list的处理返回一个Resources列表每个元素包含uri和name可以用文件名。实现resources/read的处理解析请求中的uri提取文件路径然后读取文件内容返回。同样需要错误处理。你需要检查和理解的地方路径处理AI 生成的 URI 可能类似file://${path.join(__dirname, ‘..’, file)}。确保这个路径解析是正确的并且resources/read时能反向解析出来。初始扫描时机代码可能在服务器启动时同步扫描这对于小目录没问题。如果文件很多要考虑异步初始化或懒加载。MIME 类型在resources/read返回时可以指定mimeType: “text/markdown”。检查 AI 是否添加了这个细节这有助于客户端更好地处理内容。避坑感这里最容易出问题的是 URI 的格式和解析。如果resources/list返回的 URI 和resources/read请求的 URI 对不上就会读不到文件。第一次实现后一定要让 AI 客户端如 Cursor去请求一下资源列表看是否能正确显示。3.4 Prompt 4连接 Cursor 并进行集成测试你的输入Prompt“服务器代码看起来差不多了。现在请指导我如何将这个 MCP Server 连接到 Cursor IDE 中进行测试。我需要修改 Cursor 的哪些配置请给出具体的配置步骤和示例。另外请在我们的服务器代码中添加必要的日志输出以便在调试时能看到连接和请求过程。”AI 会做什么及输出要点AI 会提供两种主要的连接方式指导通过 Cursor 设置界面推荐给初学者指导你打开 Cursor Settings - MCP Servers - Add New Server。配置方式选择 “Command”然后填入运行命令例如node /absolute/path/to/your/project/dist/index.js。你需要先运行npm run build生成dist目录。通过配置文件cursor/mcp.jsonAI 会告诉你可以在项目根目录或用户全局目录创建这个文件内容类似{ “mcpServers”: { “my-local-server”: { “command”: “node”, “args”: [“dist/index.js”], “cwd”: “/absolute/path/to/your/project” } } }同时AI 会在服务器代码的关键位置如连接建立、收到list/call/read请求时添加console.error日志方便你观察通信流程。你需要检查和理解的地方命令路径确保配置中的路径是绝对路径。相对路径在 Cursor 的上下文中可能无法正确解析。构建与运行记住每次修改src/index.ts后需要重新运行npm run build来编译 TypeScript或者直接使用tsx在开发时运行源码配置命令为npx tsx src/index.ts。日志观察连接 Cursor 后你需要打开 Cursor 的“开发者工具”或查看其日志输出位置不同平台不同才能看到你服务器通过console.error打印的日志。这是排查连接问题的关键。实测感这一步是“临门一脚”。很多人在此卡住。最常见的问题是路径不对、命令执行权限问题或者端口/stdio 冲突。如果连接失败首先检查 Cursor 的错误日志然后回到终端手动运行你的服务器命令看是否能正常启动且不报错。3.5 Prompt 5功能增强与错误处理优化你的输入Prompt“我们已经有了一个可工作的原型。现在请帮我进行以下增强和优化安全性修改read_file工具将其访问范围限制在当前项目目录即process.cwd()及其子目录下防止路径遍历攻击。健壮性为所有工具调用和资源读取添加更全面的错误处理。不仅处理文件不存在还要处理无权限、读取错误等情况返回结构化的错误信息。可扩展性将工具和资源的定义与处理逻辑拆分成独立的模块或类让index.ts主文件只负责服务器初始化和路由。请展示一个简单的重构思路。”AI 会做什么及输出要点这条 Prompt 引导 AI 从“能跑”到“好用、安全”。路径安全AI 会引入path模块在read_file和resources/read中使用path.resolve和path.relative来判断请求路径是否在项目根目录内。如果..试图跳出范围则拒绝请求。错误处理AI 会创建统一的错误处理函数或是在每个try…catch中更细致地判断错误类型instanceof Error检查code属性如’ENOENT’,’EACCES’并返回更具描述性的错误文本。代码重构AI 可能会建议创建tools.ts和resources.ts文件。tools.ts导出所有工具的定义Tool对象和对应的执行函数。resources.ts管理资源列表和读取逻辑。然后在index.ts中导入并注册它们。这使得添加新工具变得非常容易。你需要检查和理解的地方安全边界检查路径检查逻辑是否严密。最简单的办法是const resolvedPath path.resolve(projectRoot, requestedPath); if (!resolvedPath.startsWith(projectRoot path.sep)) { throw new Error(‘Access denied’); }。错误信息有用性返回给 AI 的错误信息应该能指导用户或 AI 本身下一步该做什么。例如“文件不存在”比“读取错误”更好。重构的清晰度重构后的代码应该更易读。如果 AI 的重构让你感到更混乱可以要求它用更简单的方式或者先不进行这一步保持原有结构。经验注入到这一步你已经拥有了一个功能相对完整、有一定安全意识的 MCP Server。这个过程的核心收获不是代码本身而是你通过精心设计的 Prompt像项目经理一样分阶段、有重点地引导 AI 完成了从骨架到血肉再到安全加固的整个开发流程。这比单纯复制粘贴代码要深刻得多。4. 在 Cursor 中实际使用与效果验证服务器搭建好并成功连接到 Cursor 后怎么验证它真的在工作4.1 验证工具调用在 Cursor 的 Chat 界面中直接输入“请调用get_server_info工具。”Cursor 的 AI 应该识别到你连接的 MCP Server 提供了这个工具并自动调用它。你会在回复中看到类似{“name”: “My First MCP Server”, “timestamp”: 172…}的结果。同样尝试“读取README.md文件的内容。” AI 应该会调用read_file工具并返回文件内容。如果失败怎么办AI 说“找不到工具”检查 Cursor 的 MCP Server 配置是否正确服务器进程是否在运行。查看 Cursor 日志确认握手和工具列表交换是否成功。调用出错查看你的服务器日志console.error输出的内容通常会有详细的错误堆栈。常见问题包括路径错误、权限不足、代码逻辑 bug。4.2 验证资源访问在 Chat 中输入“列出所有可用的资源。” 或者更自然地说“你有什么可参考的文档吗”AI 应该会调用resources/list并返回你项目里所有.md文件的列表。你可以接着说“请给我看看xxx.md的内容。” AI 会调用resources/read并返回该文件内容。资源与工具的区别体验你会发现AI 在“思考”时对 Resources 和 Tools 的使用方式略有不同。Tools 是 AI 主动“使用”的“能力”而 Resources 更像是 AI 可以“查阅”的“资料库”。在设计你的 Server 时可以根据这个特性来规划功能。4.3 更复杂的场景测试尝试一些组合指令观察 AI 如何利用你的 Server“帮我把src目录下所有.ts文件的文件名列出来。”这可能需要你新增一个list_directory工具或者 AI 组合多次read_file不更好的方式是新增工具。你可以用 Prompt 让 AI 帮你添加这个工具。“根据requirements.md里的描述帮我规划一下项目结构。”AI 会先读取该资源获取上下文然后再进行回答。这就是 MCP 的强大之处你扩展了 AI 的感知和行动边界。它不再局限于对话历史而是能实时、安全地与你本地环境交互。5. 排查清单当你的 MCP Server 不工作时按照以下顺序检查能解决 95% 的问题基础运行检查在项目目录下能否直接运行node dist/index.js或npx tsx src/index.ts并看到“MCP Server running…”日志且进程不退出如果启动失败根据终端报错解决通常是语法错误、依赖缺失。Cursor 连接配置检查配置中使用的命令和路径是否能在终端中独立执行成功Cursor 的 MCP Server 配置页面该 Server 的状态是否是 “Connected” 或 “Ready”如果是 “Error”点击查看详情。检查 Cursor 的日志Help - Toggle Developer Tools 打开控制台或在日志文件中查找。协议通信检查在你的服务器代码中是否在关键步骤连接成功、收到请求添加了日志查看这些日志是否被打印。如果根本没收到tools/list请求说明连接或握手可能有问题。如果收到了list请求但没收到call请求可能是 AI 认为工具不适用当前问题或者工具描述不够清晰。工具/资源逻辑检查当 AI 调用工具失败时服务器返回的错误信息是什么是否遵循了 MCP 的错误格式isError: true手动模拟调用你可以在代码中临时写一个测试脚本来调用你的工具函数看逻辑是否正确。路径问题所有文件路径都处理成绝对路径了吗路径权限对吗依赖与版本检查modelcontextprotocol/sdk的版本是否与 Cursor 兼容查看 Cursor 文档或社区了解其兼容的协议版本。Node.js 版本是否满足要求一个很常见的坑你的服务器代码使用了 ES Module (import/export)但package.json中没有设置“type”: “module”或者启动命令不对。确保你的环境一致。使用tsx通常能避免很多模块问题。6. 下一步从玩具到生产力的思考通过这 5 条 Prompt你已经走完了从零到一的闭环。接下来可以考虑如何让它真正产生价值连接内部系统将 MCP Server 作为桥梁让 AI 能安全查询公司内部数据库只读、调用内部 API如创建 JIRA 工单、查询 CI/CD 状态、读取监控图表。关键是做好权限控制和审计。封装复杂工作流比如一个“部署预览”工具AI 调用后Server 后端执行一系列 Git、Docker、kubectl 命令最后将预览 URL 返回给 AI。这比让 AI 去生成一堆命令再让你复制粘贴要可靠得多。动态资源Resources 不一定非要是文件。它可以是一个动态生成的报告比如“当前线上错误最多的 5 个服务”Server 每次收到resources/read请求时实时调用内部系统获取数据并生成 Markdown 返回。权限模型实现一个简单的权限模型不同的工具/资源对不同用户或不同上下文项目可见。这需要 Server 能识别调用上下文MCP 协议支持部分元数据传递。最后一点经验Prompt Engineering 对于开发 MCP Server 来说其价值在于快速原型设计和逻辑描述。一旦核心流程跑通后续的优化、测试、安全加固和部署仍然需要你扎实的工程能力。不要指望单靠 Prompt 就能得到一个完美的生产级应用但它绝对是帮你跨越“从想到做”这个鸿沟的超级杠杆。现在你可以试着用同样的方法去让 AI 帮你实现上面任何一个进阶想法了。