最近在玩Cursor的Agent模式,想着把MCP服务接上去试试,结果折腾了两天……服务端用的是FastMCP的Python SDK,本地跑没问题,但通过Cursor的MCP配置连上后,Agent一调用工具就报“connection closed”或超时。我试过改transport为stdio和sse,也检查了端口没冲突,日志里看不出明显错误。网上搜了一圈,有人说要加心跳包,有人说Cursor的MCP实现还不稳定。有没有大佬遇到过类似情况?还是说MCP和Cursor的版本匹配有问题?我用的Cursor 0.45.x,MCP SDK 1.2.0。求指点,感谢!
MCP对接Cursor后,Agent总是调用失败,是我配置姿势不对吗?
全部回复
共 152 条我上周也踩过类似的坑,最后发现是Cursor那边的MCP客户端对超时时间卡得很死,FastMCP默认的响应速度一慢就直接掐断连接。你可以试试在初始化服务的时候把shutdown_timeout和request_timeout调大点,另外确认下SDK版本跟Cursor内置的MCP协议版本是否兼容,我升到1.3.0之后就没再报过connection closed了。
还有个细节,Cursor的Agent模式如果开了流式输出,可能会跟SSE传输方式冲突,我后来换成stdio反而稳定了。你日志里没错误但连接断,大概率是客户端主动断的,可以抓包看下是不是有RST包。要是还不行,可以试试在工具函数里加个简单的重试装饰器,至少能让Agent多试几次。
这问题我上个月也踩过,FastMCP配Cursor死活连不上,后来发现是SDK版本太新,Cursor那边的MCP客户端对某些协议字段兼容性有问题。建议你试试把FastMCP锁到0.11.x,然后transport强制用stdio,别让Cursor自动探测。另外检查下是不是有代理或VPN在中间捣乱,我那次就是全局代理把本地socket流量给劫了。
我最近也踩过类似的坑,不过我是用TypeScript SDK接的,现象一模一样。后来发现问题是FastMCP默认的stdio模式在Cursor里对启动路径和环境变量特别敏感,尤其是你用虚拟环境跑Python的话,Cursor那边可能没继承到正确的Python解释器路径,导致服务起了一半就崩了。你可以试试在MCP配置里把command写成绝对路径,比如直接指向venv里的python,然后再加个--host参数指定回环地址,我这么改完就稳定多了。另外版本匹配这块,Cursor 0.45.x对MCP协议支持确实有点老,你SDK 1.2.0可能默认用了新的协议特性,比如initialized消息的时序要求更严格,建议先降到0.9.x试试。还有个野路子,就是给服务端加个简单的日志重定向到文件,别只靠Cursor的日志面板,这样能看到Python那边真正的报错,我之前就是发现是异步事件循环没跑起来。心跳包那个说法我也试过,但治标不治本,关键还是握手阶段的问题。你要是方便的话,把MCP配置文件和启动命令贴出来,我帮你看看哪里的参数不匹配。
巧了,我上周刚踩完这个坑,跟你配置几乎一样,最后发现是FastMCP的SSE模式跟Cursor的握手方式不兼容。Cursor那边对SSE的endpoint路径有硬性要求,默认的/sse可能没问题,但如果你用了自定义路径或者加了鉴权头,它就会静默断开,日志里啥都不显示。我换回stdio模式后,又把MCP SDK降到0.9.x版本,问题就消失了,怀疑是1.2.0版本的心跳机制跟Cursor的Agent循环冲突了。
另外你确认下Cursor设置里的MCP超时时间,默认好像是30秒,但Agent在思考复杂任务时经常超过这个阈值,尤其是本地模型推理慢的时候,直接给你掐断连接。可以在config文件里把timeout调大到120秒试试,虽然官方UI没开放这个选项,但手动编辑json是有效的。
还有个容易忽略的点,如果你同时开了多个MCP server,Cursor的并发连接数可能不够用,导致后面的请求排队超时。我那次就是同时挂了GitHub和本地文件服务,结果Agent一调用就崩,关掉一个立刻就好了。你试试只保留一个MCP服务,排除干扰项。
版本匹配的话,0.45.x确实偏老,我后来升级到0.47.1,对MCP的支持明显稳定了,至少不会再出现“connection closed”这种裸报错。建议你直接升到最新版,然后SDK用官方示例里的fastmcp版本,别追新,稳定优先。如果还不行,把Cursor的日志级别调成debug,它会打出每次调用的详细握手过程,比服务端日志有用多了。
我跟你一样卡在这,后来降到0.42.x版本加短超时就稳了,你可以试试。
SDK换1.0.4试试,我之前升到新版也老断连,降级后立竿见影。
我之前也被这个坑过,后来发现是FastMCP的SSE模式和Cursor的兼容性有问题,换成stdio瞬间就稳了。你试试把服务端启动命令改成带--transport stdio参数,然后在Cursor里配置成command模式,别用URL。另外心跳包那个说法我试过,加个heartbeat: 30确实能缓解超时,但根本原因还是版本不匹配,Cursor 0.45.x对MCP协议的支持还比较老,建议升级到0.46以上。
我0.46之前也这样,换0.46.x后稳定多了,建议先升个级试试。
之前遇到过,把FastMCP的keepalive设成true,再调大超时时间基本就解决了。
我上周也踩过这个坑,最后发现是FastMCP的SSE模式在Cursor里对keep-alive处理有问题,换回stdio再给每个工具调用加个超时重试逻辑就稳了。另外你Cursor 0.45.x配MCP SDK 1.2.0的话,建议试试把SDK降到1.1.x,我记得有issue说1.2.0的握手协议变化导致连接容易被Cursor主动断开。还有个小细节,本地跑没问题但Cursor里挂,看看是不是没给Agent设置足够长的tool call超时时间,默认几秒很容易触发。
遇到过一模一样的坑,最后发现是FastMCP的SSE模式跟Cursor的兼容性有问题,换成streamable-http传输就稳了。另外你试试把Cursor的MCP超时时间调大点,默认那个值对复杂工具调用确实太紧了。还有个小细节,本地跑没问题不代表Cursor环境没问题,检查下环境变量是不是没传过去,我上次就是PATH里少了Python路径导致连接被掐断。
我之前也卡在这块儿,后来发现主要是Cursor那边对MCP的调用超时设置太短了,FastMCP默认的响应逻辑容易撞上这个限制。你可以试试在服务端把streamable_http的ping间隔调小一点,或者干脆用streamable_http(不是sse)再配个nginx反代,比直接暴露端口稳很多。另外0.45.x确实有点老,我升到0.48之后就没怎么出过connection closed了,SDK那边倒不用太纠结版本。
我之前也卡在这块儿,后来发现是FastMCP的SDK版本和Cursor那边的MCP协议握手对不上,特别是那个initialize请求的响应体,建议先抓包看下具体报错。另外0.45.x这版对SSE支持确实有点迷,我换成streamable-http模式就稳了,你可以试试。心跳包那个说法我也见过,但感觉不是主因,更像是Cursor自己连接池回收太激进导致的。如果还不行,试试把MCP服务端加个超时重连逻辑,至少能缓解偶发断连。
我也踩过类似的坑,后来发现是FastMCP的SSE模式和Cursor的兼容性问题,换成streamable-http那个新协议就稳了。另外你检查下Cursor那边MCP配置里的超时时间,默认好像只有5秒,本地跑没问题但跨进程就很容易卡在握手阶段。还有个小细节,如果用的是Python 3.12+,试试把SDK降到1.1.x,有次更新后连接池行为变了导致间歇性断连。
你试试把Cursor更新到最新版,0.45.x的MCP客户端确实有bug,我升到0.47后就没再掉过线。
我跟你一样踩过这个坑,后来发现多半是FastMCP的SSE模式跟Cursor的握手逻辑对不上,尤其你用的SDK版本还偏新。建议试试把transport切回stdio,然后确保你的Python环境路径在Cursor里配的是绝对路径,别用相对路径。另外0.45.x这个版本确实对MCP支持有点迷,我换了0.46.x的Beta版就稳定多了,你可以先降级SDK到1.0.x看看。心跳包那个说法我也见过,但感觉治标不治本,不如直接看Cursor的日志文件,路径一般在~/Library/Logs/Cursor下,里面会有更具体的报错。
我之前也踩过这个坑,折腾了差不多一晚上。后来发现大概率不是配置姿势问题,而是Cursor对MCP的stdio模式支持确实有bug,尤其是0.45这个版本,连接池管理做得比较糙,Agent并发调用一多就容易把管道搞崩。我后来改成sse模式,然后服务端加了点重试逻辑,情况好了不少,但偶尔还是会超时,感觉是Cursor那边对工具响应时间卡得很死。你用的FastMCP 1.2.0应该没问题,不过我建议你试试把服务端的日志级别调到DEBUG,看看是不是在收到请求后,Cursor那边主动断开的,如果是,那基本就是客户端的问题了。还有个偏方,就是给每个工具调用前加个几十毫秒的延迟,虽然很蠢,但有时候还真能绕过这个坑,可能是Cursor的某个竞态条件。另外你可以检查下本地的代理软件,有时候系统代理会把localhost的流量也劫持了,导致连接被重置,这个特别隐蔽。我后来是直接把Cursor的代理设置改成不代理本地地址才彻底解决的,你可以先试试这个,成本最低。
我之前也踩过这个坑,后来发现是FastMCP的SSE模式和Cursor的Agent兼容性有问题,换成stdio后稳定多了。你试试把transport改成stdio,然后确保Cursor里MCP的command和args填对,别用默认的http地址。另外版本上,Cursor 0.45确实对MCP支持还比较糙,建议升到0.46.x以上,SDK那边1.2.0也可以试试降级到1.1.x,我这边这么弄之后基本没再掉线。还有个偏方,如果你用的是本地服务,启动命令里加个--no-browser或者环境变量设个超时时间,有时候是握手太慢被掐断的。
这版本组合我试过,问题多半出在FastMCP的stdio模式上,Cursor对子进程的生命周期管理挺激进的,空闲一会儿就给你掐了。建议把transport换成sse,然后服务端加个简单的定时ping保活,另外看看Cursor的日志输出级别有没有更详细的选项,有时候错误被吞了。我之前是升到MCP SDK 1.3.x才稳定下来,但也不能保证,毕竟Cursor这边更新太勤快了。
这配置问题我太有同感了,之前也被折腾得够呛。你用的FastMCP 1.2.0配Cursor 0.45.x,这个组合我试过,大概率不是版本匹配的问题,而是transport模式在客户端和服务端之间没对齐。我后来把服务端改成用sse模式,并且特意在FastMCP里设置了更短的响应超时和重连机制,才稳定下来。另外你说的“connection closed”,我怀疑是Cursor侧的MCP客户端对长连接的空闲管理太激进,它默认可能几十秒没消息就掐断,你试着手动在服务端加个定时器,每15秒发个ping或者注释,保持连接活跃,比单纯改transport更有效。还有个小坑,如果你本地跑的时候是直接python xxx.py,但Cursor是通过npx或者绝对路径去启动,那环境变量和cwd可能不一样,导致SDK找不到某些配置,建议把启动命令写成绝对路径加--log-level debug,把输出重定向到文件,看看到底是服务端崩了还是客户端主动断的。我最后就是靠这个日志定位到是FastMCP内部某个异步任务异常退出,但没打印traceback,你查查这个方向。
遇到过类似的,不过我是用TypeScript SDK接的。你试试把Cursor和MCP服务都升级到最新版,0.45.x那会儿确实有已知的连接池问题,后来某个小版本修了。另外检查下FastMCP的日志级别,把debug打开,看看是不是服务端主动断的,还是Cursor那边超时。心跳这个说法我觉得不太靠谱,MCP协议本身没这个机制,更像是SDK版本兼容问题。
我前几天也卡在这上面了,不过后来发现是FastMCP版本太新,跟Cursor的MCP客户端握手协议对不上,降级到0.9.x就稳了。你那个1.2.0可能也有类似兼容问题,不妨试试锁版本,另外stdio模式记得别加什么超时设置,让Cursor自己管理进程生命周期。还有,日志看不出错不代表没报错,可以开debug模式看看MCP那边的stderr输出,我之前就是在那儿找到线索的。