最近在玩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客户端对stdio进程的启动参数要求比较严格,FastMCP默认会带些额外输出导致握手失败,你试试在启动命令里显式加上--no-print之类的参数。另外0.45.x这个版本确实对SSE支持不太好,建议直接换streamable-http试下,虽然文档少但稳定性高不少。对了,你FastMCP用的什么版本?我升级到2.x以后就没再报connection closed了。
调了两天最后发现不是传输方式的问题,是FastMCP的日志输出会污染stdio通道,Cursor那边一读到非协议内容就断连,把日志重定向到文件就好了。你可以试试在启动命令后面加个2>mcp.log,看是不是这个原因。版本匹配的话,我这边0.46.x配SDK 1.2.0是正常的,不过具体还得看你的系统环境。
我猜可能是你那个工具的响应时间太长了,Cursor的Agent默认等待超时设得比较短,尤其是调用一些慢的数据库查询时特别容易触发。你可以在MCP server的配置里加个timeout字段,或者把工具改造成异步返回。另外检查下Cursor的日志文件,有时具体错误会藏在~/.cursor/logs里,界面上的日志太笼统了。
我之前也卡在这,后来把
我上周也踩过这个坑,后来发现是FastMCP的SDK版本和Cursor内置的MCP客户端握手协议对不上,你试试把SDK降到0.9.x看看。另外SSE模式记得在服务端显式设置CORS头,Cursor那边有时候预检请求没过就会直接掐断连接。还有个小细节,如果本地跑是好的,检查一下Cursor的MCP配置里环境变量是不是没带全,尤其是PATH和PYTHONPATH。
我前阵子也踩过类似的坑,最后发现是FastMCP版本和Cursor的MCP客户端握手协议不兼容,你试试把SDK降到1.0.x或者干脆用官方examples里的旧写法,别用最新特性。另外如果用的是SSE,Cursor那边对event-stream的缓冲处理挺迷的,建议直接换回stdio然后给命令加个--no-warnings参数,我这么弄完就没再掉过线。你日志里有没有出现“Unexpected end of JSON input”之类的?有的话基本就是版本问题了。
我之前用0.44版配FastMCP也这样,后来发现是Cursor的MCP配置里环境变量没继承全,尤其是PATH和PYTHONPATH,导致SDK内部某些子进程起不来。你可以试试在mcp配置的env字段里手动把PATH写全,再给个超时时间比如60s,别用默认的。另外0.45.x的Agent模式对MCP工具并发调用有限制,如果工具内部有sleep或者嵌套调用,很容易触发超时,先简化成同步单步骤试试。
你这情况我怀疑是心跳包的问题,Cursor的MCP客户端空闲几秒后会自动断开连接,但FastMCP的默认心跳间隔是30秒,两边对不上。我解决的笨办法是在每个工具函数开头加个print或者写个log,强制产生IO活动,这样连接就不会被
这配置看着没啥毛病,八成是Cursor那边对长连接处理有bug,试试把工具返回数据改小点。
同款配置踩过坑,最后发现是Cursor的MCP客户端对stdio模式支持有bug,切到sse后加个--port参数反而稳了。另外你的FastMCP版本最好和Cursor的MCP协议版本对齐,0.45.x好像只支持到老版本协议,试试把SDK降到1.0.x或者升级Cursor到最新版。日志里没错误不代表没问题,建议在工具函数入口打点日志,看请求到底有没有到服务端。我这边还遇到过因为环境变量没传导致连接被重置的情况,你可以检查下Cursor启动MCP时的工作目录。
看到你这个版本组合我大概知道啥问题了,0.45.x的Cursor对MCP的stdio支持确实有bug,我上个月也踩过这坑。后来我把FastMCP降到0.9.x,然后强制用sse模式并且把超时时间调到120秒才勉强稳定下来。你试试在MCP配置里加个"connectionTimeout"和"requestTimeout"参数,另外确认下Cursor是不是在后台把Python进程给杀了。实在不行就换个思路,用Remote MCP Server的方式跑,别直接让Cursor拉起本地服务。
我上周也被这个坑过,最后发现是FastMCP的SSE模式在Cursor里默认超时时间太短,你试试在服务端启动时把timeout参数调大点,或者干脆用streamable-http的transport,那个稳定很多。另外确认下Cursor的MCP配置里有没有自动加上了什么多余的headers,我之前就是被这个搞的。版本的话0.45.x应该没问题,我这边0.46也正常跑。
我上周也踩过这个坑,最后发现是Cursor的MCP客户端对stdio模式下的进程存活检测太激进,稍微慢一点就掐连接。你试试在FastMCP初始化时把shutdown_timeout调大点,或者干脆用streamable-http transport,比SSE稳不少。另外0.45.x对MCP协议版本支持确实有点迷,我升到0.46.x之后就没再复现过connection closed了,你可以先排除下版本因素。
别光盯着端口和日志,Cursor那个MCP配置界面里有个“health check”超时设置,默认5秒,FastMCP启动如果加载了太多工具或者有网络请求就会超时。我直接把超时改成30秒就好了,另外记得把Cursor和MCP SDK都升到最新版,老版本之间协议握手确实有兼容问题。
我怀疑是你本地跑的时候没走代理,但Cursor内部会强制走它的网络层,导致SSE的长连接被中间件掐断。你可以试试把服务端改成监听127.0.0.1而不是localhost,我换了之后就没再报过超时。还有,FastMCP 1.2.0有个已知bug,工具响应体太大时会被截断,建议给每个工具返回前加个压缩。
我上周也踩过这个坑,最后发现是FastMCP版本和Cursor的MCP协议握手方式不太兼容,尤其是sse模式下,Cursor那边对endpoint路径的处理跟SDK默认生成的不一样。你可以试试手动指定一下sse的path,或者干脆降到MCP SDK 1.1.x看看,我换了之后就没再报connection closed了。另外,如果是stdio模式,确认下Cursor是不是真的把环境变量传过去了,有时候代理工具会吞掉这些。
这配置折腾两天太真实了,我上次也是卡在transport上,换成sse加个重连逻辑立马好了。
建议试试把Cursor降回0.44,这版本MCP兼容性确实有点迷,我升完也老断。
这问题我上个月也踩过,后来发现是Cursor的MCP客户端对stdio模式下进程退出处理有bug,FastMCP那边一空闲就自动断。你可以试试在FastMCP启动参数里加个keepalive,或者干脆用streamable-http模式,我换了之后基本稳定了。另外0.45.x版本对MCP的支持确实有点老,升级到最新版可能也有帮助。
这问题我上周刚踩完坑,跟你配置关系不大,大概率是Cursor对MCP的keep-alive处理有bug。你可以试试把服务端的读超时调大一点,比如设成300秒,然后客户端那边别用默认的health check。另外0.45.x这版对SSE的支持确实有点迷,我换回0.43.x就稳了,你可以降级试试。
我最近也踩过类似的坑,不过我是把MCP挂在Claude Desktop上用的,情况跟你不太一样。但有个点你可以试试看,就是FastMCP的SDK版本和Cursor内置的MCP client实现之间可能存在协议版本兼容问题,尤其是streamable HTTP这个新特性,老版本的SDK默认走的是SSE,但Cursor那边可能已经默认用streamable了,两边握手失败就会出现你这种连接被重置的情况。你试试把FastMCP显式指定为sse transport,并且把endpoint路径改成/sse,别用默认的/message,有些实现会对路径很敏感。另外,超时问题我怀疑是Cursor的Agent在调用工具时,如果工具执行时间超过它的内部阈值(比如30秒),它就直接掐断连接了,你可以把工具函数里加个快速返回的测试逻辑,先确认是不是执行耗时导致的。还有,日志里没错误不代表没有,你试试在FastMCP服务端加个全局异常捕获,把traceback打到文件里,有时候Cursor吞掉了错误细节。版本的话,我用的Cursor 0.46.x,MCP SDK 1.3.0,感觉0.45的MCP集成确实有不少bug,更新一下可能也有帮助。
我遇到过一次,SSE模式必须配心跳,不然Cursor那边空闲几秒就断,你试试加个ping间隔。
我也卡过这问题,最后发现是FastMCP版本太新,降到1.0.1就稳了,你可以试试。
我之前也卡在这块好几天,最后发现是FastMCP的SSE模式和Cursor的keep-alive机制不太对付,换成streamable http那个新版transport就稳了。你SDK都1.2了,要不试试把服务端也升到最新,然后配置里明确指定一下端点路径?另外如果用的是stdio,确认下Cursor启动Agent时的环境变量有没有继承完整,有时候PATH缺东西也会导致连接秒断。
刚看了眼你版本,Cursor 0.45.x配MCP 1.2.0理论上没大问题,但“connection closed”八成跟超时有关。我这边是把服务端响应时间调短,然后给Agent的system prompt里加了句“工具调用需在5秒内返回”,居然就好了,感觉是Cursor对长连接有隐式限制,你可以拿短任务试试水。
我倒觉得不是配置姿势问题,是Cursor那边对MCP请求有并发限制,你连续调用几个工具就会触发风控式断连。解决办法很土,在FastMCP里加个全局锁,把工具调用串行化,顺便把日志级别开到DEBUG,看看到底是客户端主动断还是服务端崩了,我赌是前者。
我跟你几乎一模一样的配置,也是FastMCP配Cursor 0.45.x,折腾三天最后发现是Cursor那边对SSE的keep-alive处理有问题,换个思路直接用streamable-http试试,新版SDK支持这个transport,稳定很多。另外你本地跑没问题但Cursor连不上,大概率不是端口问题,而是Cursor进程的代理或防火墙拦截了长连接,查下系统日志有没有被静默丢弃的TCP包。我后来干脆放弃在Cursor里调MCP,写个中间层脚本封装成普通HTTP接口给Agent用,反而省心。你SDK版本其实不算旧,但建议升到1.2.1以上,有个已知的connection close bug修复了。
这版本组合大概率是SDK和Cursor不兼容,建议试试降级到1.0.x或者直接换本地代理转发。
这问题我上周刚踩过,大概率是Cursor对SSE传输的兼容性有坑,建议试试把transport改成streamable-http,FastMCP新版支持这个。另外检查下Cursor的MCP超时设置,默认10秒太短,FastMCP启动时如果加载了太多工具容易卡住,手动调长到30秒试试。我之前也是0.45.x,升级到0.46之后明显稳定了,你可以先排除下版本因素。
之前调试MCP的时候也踩过类似的坑,不过我这边是Claude Desktop,症状几乎一模一样。后来发现问题是FastMCP的stdio模式下,Cursor启动子进程的方式和它默认的编码/缓冲策略对不上,尤其是Windows环境下特别容易触发connection closed。你试试在FastMCP初始化时显式指定encoding='utf-8',然后给transport加个超时参数,比如transport="stdio", timeout=30,有些版本默认超时太短,Agent思考一久连接就被掐了。另外心跳包不是必须的,但如果你用的是SSE,建议把服务端的ping间隔调短到15秒以内,Cursor那边对空闲连接的处理比较激进。版本上,Cursor 0.45.x确实有已知的MCP兼容问题,官方论坛有人反馈升级到0.46.3后稳定很多,你可以先升个级试试。还有一个偏门但有效的办法:别直接让Cursor连FastMCP,中间套一层代理,比如用mcp-proxy转发一下,能绕开某些握手细节的bug。日志没有明显错误不代表没问题,你可以把环境变量MCP_DEBUG=true开起来,会输出协议层的完整交互,定位到具体是哪一步断的。
这问题我上周刚踩过一模一样的坑,也是FastMCP配Cursor,折腾到半夜差点砸电脑。你试试把MCP SDK降到1.0.x看看,我换回1.0.9之后瞬间稳了,感觉1.2.0和Cursor 0.45.x的握手协议有点兼容性问题,尤其是SSE模式下特别明显。另外心跳包那个说法我觉得有道理,但与其自己加,不如直接在FastMCP服务端把keepalive间隔设成25秒,Cursor那边的空闲超时好像卡在30秒,稍微错开一点就能避开坑。还有个细节,如果你用的是stdio,检查下Cursor是不是用绝对路径启动的Python环境,我一开始用虚拟环境里的python,结果它连的是系统全局的,日志里完全看不出来。最后建议把日志级别调到DEBUG,Cursor的MCP日志面板里能看到更详细的报错,比服务端日志有用多了。要是还不行就试试用remote方式连,别用stdio,Cursor对子进程的生命周期管理有点激进,动不动就杀进程。