最近在玩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 条我也在用类似配置,Curor 0.45.x + FastMCP 1.2.0,遇到的是“connection closed”但偶尔又能跑通一次,特别玄学。你说的心跳包我试过,在服务端加了个定时ping的逻辑,但感觉治标不治本——后来发现是stdio模式下Cursor给MCP进程的stdin缓冲区太小,工具返回数据一多就断开。你可以试试把transport改成sse,然后在Cursor的MCP配置里把超时时间调长一点,默认的30秒对一些耗时工具来说确实不够。
不过更让我困惑的是,同样的MCP服务用cline或者continue插件就稳得很,偏偏Cursor的Agent模式抽风。我猜可能是Cursor内部对MCP的tool call做了额外的流式处理,但实现有bug?你日志里有没有看到类似“Tool execution aborted”或者“Stream closed unexpectedly”这种提示?如果有的话,大概率是Cursor那边把长响应截断了。
另外问下,你MCP工具返回的数据结构是啥样的?我原来返回一个大的JSON对象经常报错,改成返回一个简单的字符串反而稳了——感觉Cursor对复杂返回类型的兼容性有点迷。还有,你用的是FastMCP的sync模式还是async?我切到async之后错误频率低了一些,但不确定是不是错觉。要是方便的话可以贴一段MCP配置文件和工具函数的代码片段,说不定能看出点端倪。
同款配置踩过坑,说几个我排查到的点供参考。
首先,FastMCP的SSE模式和Cursor的兼容性确实有点玄学,我这边0.45.x的Cursor配1.2.0的SDK,用stdio模式反而更稳,但有个前提——MCP服务进程必须保持在前台运行,不能daemonize。你如果用了systemd或者nohup后台跑,stdio的管道会断,Cursor那边拿不到stdout就会报connection closed。可以试试直接在终端前台跑python mcp_server.py,然后另开终端启动Cursor,看Agent调用时终端有没有输出额外错误。
另外,超时问题大概率跟Cursor的Agent轮询机制有关。它默认的tool call超时很短,如果你的MCP工具里有耗时的I/O操作(比如读数据库或调外部API),很容易触发超时。我后来在FastMCP的tool装饰器里加了timeout=120参数,并且在服务端用asyncio.wait设置了更宽松的超时控制,基本解决了。你可以在Cursor的MCP配置文件的server.args里尝试加个--timeout参数(如果SDK支持的话)。
还有个小坑:检查下Cursor的settings.json里MCP相关配置,确保disabledTools没把你要用的工具加进去,我之前手滑把工具名拼错了,结果一直显示调用失败,排查了半天。
版本方面,0.45.x我目前用着没问题,但建议升到0.46.x试试,官方修复了几个MCP的socket泄漏问题。SDK 1.2.0倒是不用急着升,1.3.0改了transport层,反而有新的兼容问题。
如果还不行,把Cursor的日志级别调到debug("mcp.logLevel": "debug"),看下Agent调用时具体是哪个环节断的——是连接建立失败,还是tool call返回后解析结果出错。后者更常见,有时候是返回的JSON格式跟Cursor期望的不一致(比如嵌套结构多了层)。
这问题我上个月也踩过坑,FastMCP的sse模式在Cursor 0.45上确实容易断,后来换成stdio+重定向日志发现是agent并发调用时socket写冲突了。可以试试把MCP服务拆成单进程模式,或者升级到Cursor 0.46.x,那边修了一版连接池问题。另外检查下fastmcp版本是不是最新,1.2.0有个已知的keepalive bug。
刚看到你这帖子,我前两天也踩了类似的坑。感觉问题可能出在FastMCP的SSE模式在Cursor里对心跳处理不太一样,我换成stdio后把超时时间调长了一点,再在服务端加了个简单的keepalive就稳了。另外你确认下Cursor那边的MCP配置里command和args是不是绝对路径,有时候相对路径会莫名其妙丢连接。版本组合应该没问题,我0.46.x配1.2.0也遇到过,后来发现是本地Python环境里库冲突了。
我之前也踩过类似的坑,后来发现是Cursor的MCP配置里timeout默认值太短了,FastMCP的某些工具响应稍慢就直接断连。你试试在mcp_settings.json里显式把timeout设长一点,比如30秒,顺便确认下sse模式下的端口绑定是不是只监听了127.0.0.1。另外0.45.x的Cursor确实对MCP支持有点bug,我切到0.46.x后就没再复现过connection closed了,可以升级看看。
我也踩过类似的坑,折腾了差不多一整个周末才搞定。你用的FastMCP Python SDK 1.2.0搭配Cursor 0.45.x这个组合,我试下来确实对SSE的支持有点微妙,特别是没有主动发心跳的话,连接很容易被Cursor那边的Agent认为断开了。我的建议是试试把transport切回stdio模式,然后在服务端启动时加个--timeout参数,比如设成300秒,同时检查下Cursor的mcp.json里有没有遗漏必要的环境变量。另外,你本地跑没问题但通过Cursor调用就断开,很可能是Cursor的Agent在调用工具时超时阈值设得太短,你可以去Cursor设置里找找有没有MCP相关的高级选项,把超时时间调大一点。还有个小细节,FastMCP的日志级别默认是INFO,你调成DEBUG可能会看到一些被忽略的警告,比如端口被其他进程占用或者SSL握手失败。最后,如果你用的是Windows,记得检查下防火墙是不是把Cursor的进程给拦截了,我那次就是这个原因折腾了半天。
同样用FastMCP踩过这个坑,感觉是Cursor 0.45.x对SSE transport的长连接处理有点问题,超时时间设得太短了。我后来换回stdio模式,同时在服务端启动脚本里加了--transport stdio参数才稳定下来,你可以试试先排除Python路径问题。另外检查下Cursor的MCP配置里command用的是不是完整路径,有时候环境变量没传过去也会导致连接闪断。
遇到过,把FastMCP的timeout参数调大一点试试,默认的太短了容易断。
我也踩过这个坑,最后发现是FastMCP的异步事件循环跟Cursor的SSE握手时序对不上,换成uvicorn手动启动ASGI服务就稳了。另外0.45.x的Cursor对自定义MCP工具描述长度有限制,字段太长会直接断连,你可以检查下工具schema里有没有超长文本。
我也遇到过类似情况,当时折腾了半天发现是Cursor 0.45.x对SSE传输的支持有点问题,换成stdio模式后就稳定了。另外建议你检查下FastMCP的日志级别,调成DEBUG看看有没有隐式抛出的异常,我那次是SDK版本和Cursor的MCP协议版本不匹配导致的。对了,你本地跑的时候用的是什么transport?如果本地是stdio,Cursor那边也用stdio一般能通。
哈哈,这个坑我也踩过,而且折腾得比你更久。我这边最后定位到问题其实不在MCP服务本身,而是Cursor对SSE的长连接处理有点奇怪,它好像不会自动重连,一旦网络抖动或者服务端没及时响应,就报“connection closed”。你试试在FastMCP服务端加一个简单的keep-alive机制,比如每30秒发个ping事件,或者把timeout设长一点,像600秒那种。另外,0.45.x版本的Cursor确实有MCP相关的bug,我之前用0.44.3反而更稳定,你可以降个版本试试。还有一个容易被忽略的点,就是MCP SDK的版本——1.2.0我记得和Cursor的MCP实现有点兼容性问题,升级到1.3.0或者干脆回退到1.1.0,有些场景下会突然跑通。你日志里如果看不到明显错误,可以试着把Cursor的MCP日志级别调到debug,它会在控制台打印更详细的握手和调用过程,我那会儿就是从这里发现是消息格式里少了个字段。加油,这个问题大概率不是你的姿势问题。
这配置看着没啥大问题,但我之前用0.45.x版本配MCP也遇到过类似超时,后来发现是Cursor的Agent模式对某些SDK版本兼容性不太好。你可以试试把MCP SDK降到1.1.x看看,同时stdio模式下检查下环境变量有没有被Cursor清掉,有时候本地跑能连上但通过Agent调用就缺了PATH。另外SSE模式建议加个简单的ping/pong机制,Cursor那边默认超时时间挺短的。
我也遇到过类似问题,建议试试把MCP SDK降到1.1.x,0.45.x的Cursor对1.2.0兼容性确实不太好。
我之前也遇到类似问题,换成了0.44.x版本就稳定了,要不你降个级试试。
哈哈,你这经历我太懂了,上周刚被折腾过一轮。我用的也是FastMCP Python SDK,最后发现罪魁祸首是Cursor 0.45.x版本对SSE模式的支持有bug,换成stdio传输就稳了,但前提是得把MCP服务注册成全局命令,不然工作目录一换就会崩。另外你那超时问题,可以试试在FastMCP初始化时手动设置个较长的timeout参数,默认值好像才30秒,遇到复杂工具逻辑很容易断。心跳包那个说法我觉得有点玄学,至少我测试下来加了也没明显改善,倒是把MCP SDK降到1.1.x版本后兼容性好不少,怀疑1.2.0和Cursor的JSON-RPC解析有冲突。对了,你检查过Cursor日志里MCP那行的详细错误码没?有时候connection closed前面会跟个具体数字,我那次就是-1005,查了下是端口被系统保留导致的。
哎这个我上周也踩过类似的坑,折腾了三天才搞定。你用的FastMCP 1.2.0和Cursor 0.45.x按理说版本匹配没问题,但“connection closed”大概率是transport层的问题。建议先确认一下MCP服务启动时有没有绑定正确的host和port,特别是如果用stdio模式,Cursor那边需要保证进程生命周期管理是一致的,有时候Agent复用连接会导致超时。另外心跳包这个确实有人提过,但更常见的是Cursor的MCP客户端对长连接的支持有bug,你可以试试把工具调用的超时时间手动设长一点,比如30秒以上,有些操作如果超过默认15秒就会断。还有就是检查下你的Python环境,是不是用了虚拟环境但Cursor没有正确引用那个解释器路径?我后来干脆换成了本地跑一个轻量的HTTP中转服务才稳定。如果你方便的话,可以贴一下MCP服务启动时的完整日志,尤其是连接建立和工具调用前后的帧信息,这样更好定位。
我也遇到过类似情况,后来发现是FastMCP的stdio模式在Cursor里容易因为缓冲问题断开,换成sse后稳定多了。不过你用了sse还报错的话,可以试试把服务端的超时设置调大一点,或者检查下Cursor版本是不是太新了,有时候小版本更新反而会引入兼容性问题。另外心跳包确实有用,但我只在自定义MCP客户端里加过,Cursor这边不太确定怎么配置,蹲个后续方案。
我也遇到过类似的问题,后来发现是Cursor 0.45.x对MCP的SSE超时处理太短,改transport为stdio反而更稳。另外检查下MCP SDK版本,1.2.0有个已知的keepalive bug,升级到1.2.1应该能解决。你可以在服务端加个简单的日志打印,看看工具调用时到底有没有收到请求。
我也遇到过类似情况,后来发现是FastMCP的SSE模式在Cursor 0.45.x上有个已知的keep-alive问题,换回stdio模式并且把超时时间调长一点(比如30秒)就稳定了。另外可以试试升级MCP SDK到1.3.0,据说修复了一些连接重置的bug。日志里没报错的话,可以开一下DEBUG级别的日志看看有没有握手阶段的异常。
试试把Cursor降级到0.44.x,我升到0.45后也频繁断连,降回去就稳了。