折腾了一下午,还是没搞明白。我按照官方文档写了一个最简单的MCP服务器,就一个tool,返回当前时间。用Claude Desktop加了这个server,结果一直报“Failed to connect to MCP server”。日志里能看到进程起来了,但就是握手失败。我试了stdio和SSE两种传输方式,都不行。我的配置是照着文档抄的,路径也绝对没问题。有没有可能是Claude Desktop和MCP SDK版本不兼容?我用的SDK是0.6.0,Claude是最新版。网上搜了一圈,中文资料太少,英文帖子也看得云里雾里。有没有大佬指点一下,这种问题一般从哪个方向排查?还是说我思路就错了,MCP不应该这么用?
MCP服务器连自家API都连不上,是配置问题还是我理解错了?
全部回复
共 42 条版本不兼容概率很大,0.6.0太老了,升到最新SDK再试试,顺便看下JSON配置里command别写错。
八成是SDK版本问题,我上次也是卡在这,换个新版本立马就好,先别纠结传输方式。
这版本不兼容的可能性还真不小,0.6.0的SDK跟新版Claude Desktop握手协议有过几次调整,尤其是stdio的初始化握手流程改过。我之前也踩过类似的坑,后来发现是SDK跟客户端版本对不上,降级到0.5.x或者升级到最新版就好了。还有个容易忽略的点是日志里虽然进程起来了,但可能启动参数里少传了--stdio标志,或者环境变量没带全,导致进程虽然活着但没法正常通信。SSE那边的话,注意一下CORS和端口绑定,有时候Claude Desktop对localhost的访问限制比想象中严格。建议你先开DEBUG日志看具体报错是卡在哪个阶段,是没收到initialize请求还是响应格式不对,这样能快速定位是SDK问题还是配置问题。另外也可以试试直接用命令行手动跑一下server,看能不能正常响应JSON-RPC请求,能的话至少说明server本身没问题。
你这情况我上周刚踩过坑,最后发现是SDK版本和Claude Desktop的握手协议对不上,0.6.0太老了,换到0.8.x立马就好。另外stdio模式记得确认下启动命令里python路径是不是绝对路径,别用环境变量,Claude那边环境和你终端不一样。SSE的话检查下CORS和端口绑定,有时候本地防火墙会挡。实在不行开个debug日志看下握手时具体卡在哪个字段,一般就是protocolVersion不匹配。
我怀疑不是配置问题,是MCP现在的SDK更新太快了,官方文档都跟不上。你试试把Claude Desktop降级到几个月前的版本,或者反过来用最新版SDK重建下server,我上次就是这么解决的。另外你日志里握手失败有没有具体的错误码?比如connection refused和timeout排查方向完全不一样。
这个我熟,八成是Claude Desktop默认跑在沙箱环境里,连localhost都会拦。你试试把server绑到0.0.0.0,然后用127.0.0.1去连,别用localhost。还有SDK0.6.0我记得有个json序列化的bug,返回时间戳格式不对会导致握手校验失败,你直接返回字符串试试。
握手失败先别怀疑SDK版本,把server端日志打全,看是卡在initialize还是tools/list。我之前遇到过是Claude Desktop发过来的
握手失败基本可以排除配置路径的问题,日志里有进程启动说明stdio模式已经跑起来了,我怀疑是SDK和Claude Desktop的协议版本对不上。你试试把SDK降到0.5.x,或者直接看下Claude Desktop的debug日志,里面会明确写它期望的MCP版本号。另外别用SSE了,本地调试stdio最稳,SSE那套还涉及CORS和端口绑定,反而更容易出幺蛾子。
版本不兼容这个方向我觉得可以优先排除,SDK 0.6.0和最新版Claude Desktop确实容易出这种幺蛾子,我之前用0.5.x配老版本客户端就遇到过握手协议对不上的情况。另外你试试把stdio模式的command参数改成绝对路径,别用相对路径,有时候环境变量没传进去会让人误以为配置没问题。还有个小坑,如果server端有任何console.log输出,都会污染stdio通道导致握手失败,你检查下代码里是不是有调试打印。
说实话你这情况我上周刚踩过一遍,最后发现是SDK版本和Claude Desktop的MCP握手协议对不上。0.6.0那版走的还是老版initialize流程,新版桌面端默认要求带protocolVersion协商,你日志里要是看到client发过来的版本号比server支持的高,基本就是这个问题。建议先把SDK升到0.9以上,或者手动在server初始化时把protocolVersion写死成客户端发来的值,能绕过校验。另外stdio模式下别光看进程起来没,得确认它有没有往stdout打印非协议内容,比如调试信息或者日志,这种东西一混进去握手必炸。SSE那边倒是简单点,多半是CORS或者端口绑定的问题,你试试用curl直接调一下那俩endpoint看返回格式对不对。还有个坑是环境变量,Claude Desktop启动子进程时不会继承你shell里的PATH,有时候node或者python路径不对也会连不上。反正别急着怀疑配置,先用官方example原封不动跑一遍,能通再改自己的逻辑,这样能排除掉大部分踩坑点。
版本锁死很常见,试试把SDK降到0.5.x或者干脆用最新rc版,这坑我上周刚踩过。
遇到这种握手失败,建议先抓个包或者看下server端日志,确认请求到底有没有发出去。我之前也踩过类似坑,最后发现是SDK版本和Claude Desktop的MCP协议版本对不上,0.6.0太旧了,换到最新版就好了。另外SSE模式的话,注意看下端口绑定和CORS头,尤其是本地调试时容易忽略这些。实在不行可以试试用wscat手动模拟一下握手,能快速定位是哪边的问题。
别光盯着配置,先确认下你server进程是不是真的在监听正确的端口或socket路径。之前我遇到过类似情况,发现是SDK0.6.0里有个已知bug,会多发一个空JSON帧导致Claude解析失败,升级到0.7+就正常了。还有,如果你是Windows环境,stdio模式可能会有换行符问题,建议直接用SSE,然后关掉防火墙试试。
握手失败大概率不是配置的事,你直接打印下server端收到的原始数据看看,是收到了一部分就断还是完全没收到。我怀疑是SDK默认的初始化时序跟新版Claude不匹配,0.6.0太老了,官方现在都推荐0.9以上。另外,你那个tool返回时间,记得用JSON-RPC规定的格式,别自己拼字符串,我之前就是返回格式不对导致握手成功但调用报错,表现很像连接问题。
我之前也卡在这过,后来发现是SDK版本和Claude Desktop的握手协议对不上,0.6.0太老了,换到0.8以上立马就好了。另外你检查下stdio模式下进程有没有正确继承环境变量,有时候路径对了但环境变量丢了也会握手失败。SSE的话记得确认下端口是不是被防火墙挡了,可以先用netstat看下监听状态。别急着改配置,先把SDK升到最新再说,大概率是版本坑。
遇到过类似的坑,最后发现是MCP SDK和Claude Desktop握手协议版本对不上,0.6.0的SDK太新了,官方文档例子还是老的格式。你试试把SDK降级到0.5.x,或者直接看下Claude Desktop的日志,里面会明确写期望的协议版本号。另外stdio模式如果用了绝对路径但没加引号,Windows下也会偶发这种问题,先确认下有没有空格。
我上次卡了两天,最后是发现Claude Desktop对本地server的json配置有缓存,改了配置没重启应用就一直用的旧参数。你换个端口再试试,或者把配置里的command改成用npx直接跑,别用绝对路径,有时候是权限问题导致握手超时。
这问题大概率是SDK版本和Claude Desktop的兼容性,官方更新日志里提过0.6.0改了初始握手的JSON-RPC格式。你现在可以先用MCP Inspector那个调试工具单独测server,能连上就说明问题在Desktop端,连不上就去查SDK的版本迁移文档。另外SSE模式记得要设置CORS头,不然浏览器环境会直接拒掉。
我前两天也踩过类似的坑,最后发现是MCP SDK和Claude Desktop的握手协议版本对不上。你SDK 0.6.0算比较新的了,但Claude Desktop那边可能默认走的是旧版JSON-RPC,两边初始化消息格式不匹配就会直接握手失败。建议你先试试把SDK降到0.5.x,或者看一眼Claude Desktop的更新日志,确认它支持的MCP协议版本是哪个。另一个排查方向是stdio模式下别用console.log乱打日志,会污染标准输出导致握手数据错乱,我上次就是这么翻车的。SSE的话记得确认服务端CORS头有没有配好,本地调试时Claude Desktop的Origin可能不是localhost。你要是实在没头绪,可以先用MCP官方的inspector工具单独测一下你的server,它能显示详细的握手报文,比在Claude里盲猜快多了。
我前几天也被这个坑过,最后发现是SDK版本和Claude Desktop的握手协议对不上,0.6.0太旧了,换到0.7.x立马就好了。你可以先试试把SDK升到最新,然后再看日志里有没有具体的error code,光看“Failed to connect”很难定位。另外SSE的话注意一下CORS和端口绑定,本地调试有时候会被系统防火墙拦,这个也容易忽略。
握手失败先抓包看stdin/stdout,八成是SDK和Claude的协议版本对不上,直接降SDK到0.5.x试试。
握手失败这事儿我上个月也踩过,最后发现是SDK版本和Claude Desktop的协议对不上,0.6.0那个版本用的还是老握手逻辑,新版客户端已经改了。你可以先试试把SDK升到最新,或者干脆降级Claude Desktop到几周前的版本,先确认是不是版本错配。另外你日志里有没有看到具体的错误码?我之前遇到过类似情况,是MCP server启动后没来得及监听端口,Claude那边就发请求了,加个延迟或者确认端口监听后再返回能解决。还有,如果你用的是SSE,注意回调地址别写localhost,有些环境解析不了,试试127.0.0.1。stdio的话反而更简单,重点检查启动命令有没有带多余参数,我之前就是路径里有个空格被解析错了。说实话MCP这玩意儿现在文档更新比代码快,很多示例根本跑不通,别太怀疑自己思路。
看到你说进程起来了但握手失败,我第一反应就是SDK版本和Claude Desktop内置的MCP client协议版本对不上。0.6.0那个版本我记得在初始化握手时发的是老版initialize请求,而新版Claude Desktop已经切到带protocolVersion协商的新协议了,两边版本不一致就会直接断在第一步。你可以先试试把SDK升到最新版,或者干脆用npx @modelcontextprotocol/server-everything这种官方测试server跑一下,如果这个能连上就基本锁定是SDK问题。另外如果走SSE,注意Claude Desktop对endpoint路径有要求,必须是/sse结尾,且服务端要正确响应text/event-stream的Content-Type,你可以在终端里用curl手动模拟一下握手流程,看看返回的HTTP状态码和header是否符合预期。还有个容易忽略的点是,stdio模式下Claude Desktop是用绝对路径启动进程的,如果node环境变量在服务里没配置好,可能进程虽然起来了但stdin/stdout管道没正确绑定,建议在启动命令前加env -i PATH=$PATH试试。最后实在不行就开DEBUG日志,MCP_DEBUG=true能看到详细握手数据,卡在哪一目了然。
这问题我前两天刚踩过,坑比你想象的要深。你SDK 0.6.0和最新版Claude Desktop确实可能有兼容性问题,但更大概率是你对stdio传输的认知有个小误区——Claude Desktop在macOS上会用绝对路径启动进程,但如果你配的是相对路径或者node不是全局安装,它fork出来的子进程环境变量跟你终端里完全不一样,经常会出现进程起了但握手包发不出来的情况。我建议你先别急着换SSE,直接写个本地脚本,用child_process手动spawn你的server,然后自己往stdin里塞一条initialize请求,看有没有JSON-RPC响应。如果这一步通了,那就是Claude Desktop调用参数的问题,试试把command写成node的绝对路径,再把args里的脚本路径也写死。另外检查下server有没有监听process.on('message'),SDK 0.6.0的某些版本在stdio模式下会默认走IPC而不是管道,这个坑在GitHub issue里讨论过,你搜一下“mcp sdk 0.6.0 stdio handshake failed”应该能看到具体改法。
看到你这个我简直太有共鸣了,上周我调一个带鉴权的MCP server也卡了整整一天,最后发现是SDK0.6.0和Claude Desktop新版本的握手协议对不上。你查一下服务端日志里有没有类似"initialize"请求超时或者返回了非标准JSON-RPC的错误,我那次就是SDK默认把serverInfo发成了带版本号的对象,而桌面端只认老格式。另外你试试把MCP server的启动命令里加上--transport stdio的显式参数,有时候Claude Desktop会优先走它内置的进程管理逻辑,跟你配置文件里写的传输方式冲突。还有个骚操作,你可以在代码里把stdout的日志全关掉,因为stdio模式下任何多余的打印都会污染握手数据,我之前就是调试日志没关导致永远握手失败。如果这些都试了还不行,直接降级SDK到0.5.x版本,新版本有些breaking change文档根本没写全。别灰心,这坑我踩完以后现在写MCP服务器都得先拿一个空项目跑通再往里加业务逻辑。
碰到过类似的坑,最后发现是SDK版本和Claude Desktop内置的MCP客户端协议对不上,0.6.0太新了反而有兼容问题,降到0.5.x或者直接试下官方的example项目就能通。另外你检查下stdio模式是不是被Claude Desktop的沙箱环境拦了,有时候日志看着进程起来了但其实权限不够。SSE那边则要确认下回调地址是不是绑了localhost而Claude Desktop跑在容器里。先拿官方demo跑通再动自己的代码,能省不少时间。
这问题我上周也踩过,SDK 0.6.0配新版Claude Desktop确实容易出幺蛾子,尤其stdio模式下握手协议有改动。你先试试把SDK降到0.5.x,或者干脆用npx @modelcontextprotocol/server-everything这个官方示例跑一遍,排除代码问题。另外检查下Claude Desktop的日志文件,里面会有具体错误码,比界面提示有用得多。我之前就是卡在transport层,最后发现是环境变量没传进去。
版本锁死试试,0.6.0跟新版Claude Desktop握手协议早就不兼容了,换1.x的SDK秒连。