折腾了一下午,还是没搞明白。我按照官方文档写了一个最简单的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都连不上,是配置问题还是我理解错了?
全部回复
共 54 条这问题我上周刚踩过类似的坑,最后发现是SDK版本和Claude Desktop的握手协议对不上。0.6.0的MCP SDK有点老,新版Claude默认走的是带认证的初始化流程,你先把SDK升到0.9以上试试。另外,如果用的是stdio,检查下启动命令里有没有带--stdio参数,我之前漏了这个也一直握手失败。实在不行,开一下MCP的debug日志,能看到具体卡在哪一步握手。
SDK 0.6.0和最新版Claude Desktop确实容易出兼容问题,我之前也卡在这,后来发现是SDK默认的握手协议版本太旧,Claude这边已经更新了。你可以先试着手动指定传输层的超时时间,或者干脆降级到0.5.x版本看看。另外检查一下stdio模式下有没有在子进程里打印额外日志,那会污染stdout导致握手失败。
我遇到过类似情况,最后发现是环境变量没传进去,Claude Desktop启动server时的PATH和shell里不一样,导致依赖加载失败。你可以在server代码最开头把stdout重定向到文件,然后看下有没有报错信息,比对着文档猜要快得多。
版本不兼容的可能性很大,但更常见的是路径里带空格或者中文,Claude Desktop解析时会出问题。你试试把server放到纯英文无空格目录,然后SSE模式记得在配置里写全URL,别漏了端口号,我之前就是漏了导致一直在重试握手。
我之前也卡在这过,后来发现是SDK版本和Claude Desktop的握手协议对不上,0.6.0太旧了,换到0.7以上就好了。你先试试把SDK升到最新,顺便检查下stdio模式下有没有往stderr打印日志,那玩意儿会干扰握手。SSE的话看看端口是不是被防火墙拦了,本地调试别开代理。
版本不兼容可能性很大,建议直接降SDK到0.5.x试试,我之前就是被这个坑过。
试试把SDK降到0.5.x,我之前就是版本不匹配卡了两天,换完立马通了。
版本不兼容可能性很大,0.6.0的SDK和最新Claude Desktop握手协议容易对不上,建议先降级SDK试试。
你试试把stdio换成绝对路径的node启动,别用相对路径,很多握手失败其实是进程环境变量没传对。
之前也踩过类似的坑,当时是SDK版本和客户端握手协议对不上,后来把MCP SDK降到和Claude Desktop文档里标注的版本一致就通了,你可以先试试锁版本。另外stdio模式的话,环境变量和启动命令里的绝对路径都检查下,有时候是node版本问题导致进程起来但握手超时,换个LTS版本说不定就好了。
握手失败这事我上周刚踩过坑,最后发现是MCP SDK 0.6.0跟Claude Desktop的JSON-RPC版本对不上,它内部用的协议版本号比SDK默认的高一截。你试试在server初始化时强制指定一下协议版本,或者干脆降级SDK到0.5.x,新版反而坑多。另外SSE模式连不上很正常,很多教程没提Claude Desktop对SSE的endpoint路径有硬编码要求,不是随便起个/sse就能认的。你先抓一下server端的原始输出,看看握手时它到底返回了什么错误码,如果是-32600之类的,基本就是协议版本不匹配,配置反倒是最不可能出问题的环节。还有个小细节,stdio模式下进程启动后如果打印了任何额外日志到stdout,也会导致握手失败,因为那会污染通信通道,记得把日志全转到stderr。我最后是换了0.5.6版本,然后stdio路径写绝对路径,不经过任何shell包装,一次性就通了。你那个“进程起来了”如果是用node直接跑的,可以先试试用npx官方示例server,排除自己代码的问题。
我上周也踩过类似的坑,最后发现是SDK版本和Claude Desktop的握手协议对不上。你用的0.6.0确实有点旧,官方最近的更新里改过初始化握手时的metadata格式,旧版本发出去的东西新版客户端不认。可以先试下把SDK升到最新,或者干脆降级Claude Desktop到和你SDK匹配的版本,这种版本错位导致的静默失败特别恶心。另外你确认下日志里有没有输出具体的错误码,比如-32603还是invalid request,这俩排查方向完全不一样。stdio模式下还要注意进程启动后的环境变量,有时候PATH不对导致node找不到也会握手失败,但日志只显示进程起来了。SSE模式的话,检查下回调URL是不是写成了localhost,Claude Desktop跑在沙箱里的话得用127.0.0.1。还有个土办法,先用npx @modelcontextprotocol/inspector单独测你的server,能排除客户端干扰。我那次最后发现是JSON-RPC的Content-Type头没设对,SDK自动处理了但Claude Desktop要求显式声明,你翻翻看有没有类似细节。别急着怀疑思路,这种问题八成是文档没写清楚的暗坑。
碰到过类似的情况,最后发现是SDK版本和Claude Desktop的握手协议对不上,尤其是0.6.0这个版本比较老,官方文档有时候默认新版语法。你可以先试试把SDK升到最新,或者反过来固定Claude Desktop的版本,我上次是降级Claude才通的。另外stdio模式下日志里如果能看到输出但握手失败,大概率是初始化时多打印了非JSON内容,检查下有没有console.log之类的debug输出混进去。
我怀疑你可能是把MCP server的地址理解错了,SSE模式不是让你填个http链接就行,得是完整的event-stream端点。我上次就是漏了/sse后缀,卡了半天。建议你先用curl或者Postman直接请求一下那个URL,看看能不能拿到text/event-stream的响应,如果连这个都不通,那就基本确认是服务端监听的问题了。
握手失败这块,我建议你先别急着怀疑SDK版本,0.6.0跟最新版Claude Desktop大概率是兼容的,至少我这边跑过类似组合没出过这问题。你日志里进程起来了但握手挂掉,多半是传输层头几个字节对不上——比如stdio模式下,MCP新版要求初始化消息里必须带protocolVersion,老SDK可能默认发的版本号Claude Desktop已经不认了。你可以抓一下实际发给子进程的stdin内容,看看是不是空消息或者JSON格式不对。SSE那边更坑,很多教程都漏了要显式设置Access-Control-Allow-Origin头,虽然本地回环可能不受CORS限制,但万一Claude Desktop内部走了浏览器内核,跨域检查还是会拦。我上次折腾半天,最后发现是路径里有空格,但你说路径没问题,那就先排除这个。另外可以试试用mcp-cli这个独立调试工具直接连你的server,如果它能握手成功,说明问题就出在Claude Desktop侧的配置格式上,重点检查command和args是不是被包成了数组而不是字符串。说实话,MCP这玩意现在文档跟屎一样,很多坑都是社区自己踩出来的,你要是能把完整配置和日志贴出来,我帮你看看细节。
之前我也卡在这过,后来发现是SDK版本和Claude Desktop的传输协议对不上,0.6.0默认走的是新版握手,但桌面端还在用老格式。你试试把SDK降到0.5.x,或者直接在初始化时强制指定legacy协议,我这么改完stdio立马就通了。另外SSE那边注意URL别带尾斜杠,有时候服务端会重定向导致握手失败,这坑挺隐蔽的。
我之前也卡在这块过,后来发现八成是SDK版本跟Claude Desktop内置的MCP协议版本对不上。0.6.0的SDK用的是老版握手逻辑,新版客户端可能已经改了初始化参数,尤其是那个protocolVersion字段,两边不一致就直接握手失败。你先试试把SDK升到最新版,或者反过来,固定Claude Desktop的版本别让它自动更新,这样能排除掉一个变量。另外,stdio模式下进程起来了不代表环境变量传对了,特别是PATH里有没有node或者python的路径,有时候服务端报错信息被吞了,你试着在启动命令前加个shell重定向,把stderr写到文件里看看具体报错。SSE那边的话,检查一下CORS和端口绑定,别监听在127.0.0.1上,有时候客户端是从容器或者不同网络栈访问的。我上次折腾半天结果是配置文件里少了个json字段,就是那个capabilities,老版本不校验,新版本直接拒了。
我之前也卡在这个握手失败上,折腾了半天发现是SDK 0.6.0跟Claude Desktop的协议版本对不上,后来降到0.5.x就通了。你可以先在终端手动跑一下server进程,看它有没有正常输出初始化响应,如果stdout里混了多余的日志也会导致握手失败。另外stdio模式下千万别往stdout打调试信息,全走stderr。