news 2026/6/19 11:25:01

027、MCP 协议入门:架构设计与第一个 MCP Server

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
027、MCP 协议入门:架构设计与第一个 MCP Server

027、MCP 协议入门:架构设计与第一个 MCP Server

上周五凌晨两点,我盯着终端里一行诡异的报错发呆:

Error: Tool execution failed: Cannot read properties of undefined (reading 'schema')

Claude Code 调用我写的自定义工具时,schema 字段丢了。排查半天,发现是 MCP 协议里 tool 定义少了个inputSchema的嵌套层级。这种低级错误,放在白天可能一眼就看出,但凌晨的代码审查总是容易漏掉细节。MCP 协议看着简单,真写起来坑不少。

为什么需要 MCP

先说说背景。Claude Code 的能力扩展靠的是工具(Tool),但早期每个工具都得自己写 HTTP 接口、自己处理认证、自己定义参数格式。不同工具之间没有统一规范,Claude Code 调用时得针对每个工具写不同的适配代码。

MCP(Model Context Protocol)就是来解决这个问题的。它定义了一套标准协议,让 Claude Code 和外部工具之间能通过统一的格式通信。你可以把它理解成 AI 世界的“USB 接口”——不管背后是什么设备,插上就能用。

MCP 的核心架构分三层:

  • Transport Layer:负责数据传输,支持 stdio(本地进程通信)和 SSE(Server-Sent Events,远程通信)
  • Protocol Layer:定义消息格式、请求/响应模式、错误处理
  • Application Layer:具体的能力定义,比如 tool、resource、prompt

Claude Code 用的是 stdio 模式,启动一个子进程,通过标准输入输出交换 JSON 消息。远程场景用 SSE,但开发阶段用 stdio 调试更方便。

协议消息格式

MCP 的消息格式借鉴了 JSON-RPC 2.0,但做了扩展。每条消息必须包含jsonrpcmethodid三个字段:

{"jsonrpc":"2.0","method":"tools/call","id":"req-001","params":{"name":"get_weather","arguments":{"city":"北京"}}}

响应格式:

{"jsonrpc":"2.0","id":"req-001","result":{"content":[{"type":"text","text":"北京当前温度:22°C,晴"}]}}

注意content是个数组,可以返回多个内容块,支持 text、image、resource 等类型。这里踩过坑:如果只返回一个字符串,Claude Code 会报解析错误,必须包在数组里。

第一个 MCP Server

直接上代码。我用 Node.js 写一个最简单的 MCP Server,实现一个文件搜索工具。

// mcp-server.js// 别这样写:用 express 起 HTTP 服务,MCP 协议不认// 正确姿势:用 @modelcontextprotocol/sdkimport{Server}from'@modelcontextprotocol/sdk/server/index.js';import{StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';constserver=newServer({name:'file-search-server',version:'1.0.0'},{capabilities:{tools:{}// 声明支持工具能力}});// 定义工具列表server.setRequestHandler('tools/list',async()=>{return{tools:[{name:'search_files',description:'在指定目录搜索文件,支持通配符',inputSchema:{type:'object',properties:{pattern:{type:'string',description:'搜索模式,如 *.js 或 **/*.ts'},directory:{type:'string',description:'搜索目录,默认当前目录'}},required:['pattern']}}]};});// 处理工具调用server.setRequestHandler('tools/call',async(request)=>{// 这里踩过坑:request.params 才是参数,不是 request.argumentsconst{name,arguments:args}=request.params;if(name==='search_files'){const{pattern,directory='.'}=args;// 实际搜索逻辑,这里简化constresults=awaitsearchFiles(pattern,directory);return{content:[{type:'text',text:JSON.stringify(results,null,2)}]};}thrownewError(`Unknown tool:${name}`);});// 启动服务consttransport=newStdioServerTransport();awaitserver.connect(transport);

关键点:

  1. capabilities 必须声明:不声明 tools 能力,Claude Code 不会调用你的工具
  2. inputSchema 嵌套层级inputSchema是 tool 对象的属性,不是直接放在 tool 里。我凌晨踩的坑就是这个
  3. 请求处理区分tools/list返回工具列表,tools/call执行具体调用

在 Claude Code 中配置

写好的 MCP Server 需要在 Claude Code 的配置文件中注册。配置文件位置:

  • macOS/Linux:~/.claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json
{"mcpServers":{"file-search":{"command":"node","args":["/path/to/mcp-server.js"],"env":{"NODE_ENV":"production"}}}}

配置完重启 Claude Code,在对话中输入“搜索当前目录下所有 .md 文件”,Claude Code 会自动调用你的工具。

调试技巧

MCP Server 的调试比普通服务麻烦,因为走的是 stdio,没有 HTTP 请求可以抓包。我的调试三板斧:

  1. 日志重定向:把日志写到文件,不要往 stdout 打,否则会污染协议消息

    constfs=require('fs');constlog=fs.createWriteStream('/tmp/mcp-debug.log',{flags:'a'});log.write(`[${newDate().toISOString()}] 收到请求:${JSON.stringify(request)}\n`);
  2. 手动模拟请求:用 echo 命令模拟 Claude Code 的请求

    echo'{"jsonrpc":"2.0","method":"tools/list","id":"test-001"}'|nodemcp-server.js
  3. 检查返回格式:Claude Code 对返回格式要求严格,少个字段就报错。写个测试脚本验证所有工具调用的返回格式

常见坑点

  • 超时问题:MCP 协议默认超时 60 秒,长时间运行的任务要拆成异步 + 进度通知
  • 错误处理:工具执行出错要返回 error 对象,不是直接抛异常
  • 参数校验:Claude Code 传的参数可能不符合 schema,服务端要做防御性校验
  • 并发调用:Claude Code 可能同时调用多个工具,服务端要做好并发控制

个人经验

MCP 协议的设计思路很清晰——把 AI 和工具的交互标准化。但实际开发中,协议细节的坑不少。我的建议是:

先写一个最简单的工具(比如返回当前时间),跑通整个链路,再逐步加复杂逻辑。调试阶段用 stdio 模式,日志一定要写到文件。schema 定义要严格,Claude Code 的 LLM 有时候会脑补参数,服务端校验能拦住大部分问题。

另外,别想着一次把所有工具都写完。MCP 支持动态注册工具,可以先暴露两三个核心功能,跑起来再迭代。协议版本目前还在快速演进,保持 SDK 更新,关注 breaking changes。

下篇会讲 MCP 的进阶用法:如何实现流式响应、工具链编排、以及和现有 API 网关的集成方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 11:11:31

5分钟极速解锁网盘下载:开源直链工具完全指南

5分钟极速解锁网盘下载:开源直链工具完全指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅…

作者头像 李华
网站建设 2026/6/19 11:08:49

2026 项目管理工具全景应用指南

在大型技术团队中,最让人头疼的往往不是技术难题本身,而是协作流程的混乱。你是否经历过这样的场景:迭代计划会上大家热火朝天,一旦进入开发阶段,任务状态却像黑盒一样难以追踪;跨部门资源争夺时&#xff0…

作者头像 李华
网站建设 2026/6/19 11:08:09

《今日头条》Feed流接口逆向实战:Python爬虫全流程解析(含代码)

一、写在前面:为什么选择今日头条Feed流? 在移动互联网时代,信息流(Feed流)是绝大多数内容平台的核心分发模式。今日头条作为国内最早的个性化推荐引擎之一,其Feed流接口具有极高的研究价值: 推荐算法黑盒:通过接口参数可以窥探推荐逻辑的冰山一角; 反爬机制典型:集…

作者头像 李华
网站建设 2026/6/19 11:02:45

MCP49x2系列DAC芯片:从SPI接口到硬件设计的实战指南

1. 项目概述:为什么是MCP49x2系列DAC?在嵌入式系统里,数字世界和模拟世界的桥梁,DAC(数模转换器)绝对算得上核心部件之一。无论是驱动一个模拟仪表、生成一个特定波形,还是为音频系统提供信号&a…

作者头像 李华
网站建设 2026/6/19 11:00:15

从时序图到驱动函数:HT1622驱动断码屏的实战解析

1. 初识HT1622与断码屏 第一次拿到HT1622芯片和断码屏时,我完全不知道从何下手。芯片手册上密密麻麻的英文术语和复杂的时序图让人望而生畏,断码屏上那些神秘的引脚排列更是让人摸不着头脑。但经过几天的摸索,我发现只要抓住几个关键点&#…

作者头像 李华