最近刚上手MCP,想用Cursor搭个本地服务器试水,结果折腾了两天。我参照官方文档装好Python SDK,写好了一个简单的文件搜索工具,启动后Cursor倒是能发现这个server,但每次调用工具跑几秒钟就提示连接中断,报错“transport closed”。我试过换端口、关防火墙,甚至还重启了电脑,问题依旧。是不是MCP的传输协议对本地socket有什么特殊要求?还是我代码里异步处理写错了?感觉网上资料太零散了,求大佬指点一个稳定的入门配置。
MCP服务器连Cursor老是断联,是我姿势不对吗?
全部回复
共 148 条大概率是stdio传输模式下没保持事件循环常驻,试试把server跑成sse模式或者检查下asyncio任务有没有被GC回收。
我之前也踩过这坑,把心跳间隔调短点,或者干脆用官方那个fastmcp库封装下,断联问题基本就消失了。
八成是stdio传输模式下子进程退出导致cursor把连接关了,试试把server跑成sse模式再连。
我之前也卡这好久,后来发现是代码里asyncio循环没保住,换个线程跑就好了。
这问题我上周刚踩过,八成不是协议问题,而是Cursor那边MCP客户端默认的超时时间太短了。你试试在server启动时把日志级别调成DEBUG,看看是不是工具执行超过5秒就被掐断了,文件搜索如果扫大目录很容易触发。另外检查下你的异步函数有没有正确返回结果,transport closed经常是因为服务端抛了未捕获异常导致进程退出。稳定点的话可以先不用stdio,改成SSE模式连本地端口,那个断联概率低很多。
我刚开始用MCP的时候也踩过这个坑,transport closed大概率不是姿势问题,而是stdio管道缓冲惹的祸。Cursor对子进程的stdout/stderr处理挺敏感,你试试在启动命令里加个PYTHONUNBUFFERED=1,或者把日志重定向到文件,别让它往标准输出打。另外异步那块,如果用了asyncio记得确保event loop在子线程里跑,不然容易跟主进程的IO循环打架。我后来换成用sse模式连本地就稳多了,虽然配置麻烦点但至少不会动不动断。你可以先拿官方那个echo示例跑通再往上加业务逻辑。
大概率是stdio模式下stdout被日志污染了,要么把日志全走stderr,要么换个streamable http传输试试。
我上次也卡这,最后发现是asyncio循环和线程混用导致的,建议把server跑在独立事件循环里再挂到Cursor上。
我之前也踩过这坑,多半不是协议问题,是本地server的event loop没跑对,尤其用FastAPI或asyncio的时候,很容易和MCP的stdio传输冲突。你可以试试把server改成同步阻塞模式跑,或者用官方推荐的mcp.server.stdio入口,别自己包装asyncio。另外检查下Cursor那边的MCP配置,超时时间默认可能太短,调长到30秒以上试试。
我之前也踩过这个坑,后来发现多半不是协议问题,而是SDK版本和Cursor自带MCP客户端不兼容导致的。你试试把Python SDK降到0.9.x,或者直接用官方推荐的stdio传输方式,别用sse。另外异步任务里记得给工具调用加个超时处理,不然长时间没返回也会被判定断开。我换成这个组合后基本没再断过。
如果你没改过代码,可以先确认下启动MCP server时是不是用了守护进程模式,Cursor有时连不上是因为进程提前退了。我之前用nohup跑服务就经常断,改成前台运行反而稳定。还有个小细节,工具函数里别用全局变量存状态,多线程下容易出问题。
我遇到过类似的,最后发现是Python环境里asyncio事件循环和Cursor的Jupyter内核冲突了。你可以试试把server跑在单独的虚拟环境里,然后通过绝对路径启动,别用系统默认Python。另外检查下是不是有代理软件在拦截本地socket,我之前就是Clash导致transport closed,关了就正常了。
我之前也踩过这个坑,后来发现多半是MCP的stdio传输模式跟Cursor的进程生命周期没对上,尤其是你代码里如果用了异步任务但没保持事件循环常驻,很容易跑几秒就被判定断开。建议先试试把server改成用sse模式跑在HTTP端口上,或者检查一下你的工具函数里有没有在返回前就退出循环的写法。另外可以开个debug日志看下断联前有没有收到shutdown请求,这比瞎猜端口和防火墙靠谱多了。
我之前也踩过这个坑,折腾半天发现多半是MCP server那边的超时设置太短了,工具处理稍微慢点连接就被掐了。你试试在启动server时把传输超时参数调大,或者检查下是不是用了同步阻塞的代码,搞得事件循环卡住了。另外,Cursor对本地socket的路径长度和权限也挺敏感,换个更短的临时目录试试运气。要是还不行,直接看server端的日志,比瞎猜靠谱多了。
我之前也遇到过一模一样的“transport closed”,多半不是姿势问题,是MCP那个stdio传输在Cursor里对超时特别敏感。你试试把工具函数里那些耗时操作改成真正的异步,别用同步阻塞,另外检查下是不是有print输出混进了stdout,这玩意儿会直接搞坏协议。实在不行就换个思路,用streamable HTTP模式,比本地socket稳很多。
我之前也踩过这个坑,后来发现多半是stdio传输模式下子进程没等响应就退出了,试试在代码里给server加个显式的事件循环保持存活,或者用sse模式替代。另外Cursor的MCP客户端版本更新挺勤的,老版本对超时和重连的处理有bug,先升级到最新版再排查。你那个异步处理如果用的asyncio,注意别在工具函数里开新loop,直接复用主循环就行。最后实在不行就开个debug日志看下是服务端主动关的还是客户端断的,定位会快很多。
你这大概率是异步任务没hold住,试试把server跑成同步模式或者加个keepalive心跳。
八成是server端没配stdio的keepalive,Cursor那边闲置几秒就掐了。你试试把超时参数调大点。
这问题我当初也踩过,大概率不是姿势问题,是MCP那个stdio传输在Cursor里对进程生命周期管理太敏感了。你那个“跑几秒才断”的现象,我猜是Python SDK默认的异步事件循环跟Cursor的调用超时机制冲突了,尤其如果你用了asyncio.create_task但没保持loop常驻,很容易触发transport closed。建议先别急着怀疑防火墙,直接试试把server端改成同步模式,或者用jsonrpc那个显式的消息循环模板,网上那些简化版教程坑很多。另外,你本地是不是开了VPN或者代理?有时候系统代理会劫持localhost的socket连接,这个比防火墙隐蔽多了,我上次就是被Clash搞的。还有个调试技巧,你可以在server启动时加--debug日志,看断连前有没有收到shutdown请求,如果有,那就是Cursor主动掐的,得去调MCP配置里的超时参数。最后实在不行,换个思路用SSE模式挂到本地端口上,虽然麻烦点,但稳定性比stdio好不少。
八成是stdio传输模式下子进程退出把管道带崩了,试试把server端日志重定向到文件,看看是不是异步任务没保持事件循环存活。
我之前也遇到这问题,后来发现是SDK版本和Cursor内置的不匹配,直接锁死版本号基本能解决。
我前两天也踩过这个坑,后来发现大概率不是协议问题,而是你那个文件搜索工具里如果有阻塞操作,SDK默认的异步循环会被卡住,导致心跳超时被判定为transport closed。你可以试试在工具函数里把耗时操作丢给asyncio.to_thread跑,或者直接用streamablehttp模式看看,本地stdio对超时特别敏感。另外如果用了代理,记得把localhost加到NO_PROXY里,这玩意能让你莫名其妙断得怀疑人生。
我之前也卡在这,多半是stdio的buffer问题,把server里logging输出关掉或重定向到文件试试。
transport closed大概率是异步循环里没加keepalive,你检查下心跳配置。
这问题我上周刚踩过一模一样的坑,折腾到凌晨三点才缓过来。你那个“transport closed”大概率不是协议的问题,而是MCP的stdio传输模式下,Python进程的stdout被污染了。我猜你是不是在代码里加了print调试?一旦print输出到stdout,JSON-RPC的消息流就会被破坏,Cursor那边读到非法的数据包就直接掐断连接了。解决办法很简单,把调试信息全部改成stderr输出,或者用logging模块定向到文件,另外确认一下你的异步事件循环有没有正确调用asyncio.run(),别在回调里再建新loop。还有个隐蔽的坑是Windows下Python的asyncio子进程兼容性差,如果你用了subprocess,记得把ProactorEventLoop换成SelectorEventLoop。我之前就是这么修好的,建议你先跑一遍官方examples里的echo server,排除代码问题再往上加逻辑。
我之前也卡在这过,后来发现多半是异步循环里没处理好,MCP对stdin/stdout的通信时序挺敏感的,工具跑太久或者日志打到stdout都会把连接搞挂。建议你试试把server端改成同步模式,或者给工具调用加个超时,先排除是不是长时间运行导致的。另外可以开debug日志看下具体是哪个环节断的,别光盯着transport closed这个笼统报错。
这问题我上周刚踩完坑,折腾到半夜才搞明白。你那个transport closed大概率不是端口或防火墙的事,我试到最后发现是Python SDK版本和Cursor内置的MCP客户端不兼容,尤其如果你用的是新版SDK但Cursor没更新,两边握手协议对不上就会这样。建议你先锁死SDK版本,别用最新版,我换回0.9.x之后就稳了。另外你那个文件搜索工具如果是同步阻塞式的,调用时卡住几秒也会触发超时断开,得把IO操作丢到线程池里跑,确保工具函数能立刻返回。还有个冷门点:本地socket路径别用默认的/tmp下的,换个用户目录下的长路径,有时候权限或清理机制会悄悄干掉连接。我最后是把stdio传输换成SSE模式才彻底解决的,虽然配置麻烦点但稳定得多,你可以试试。要是还不行,去MCP的GitHub issues里搜“cursor transport closed”,有个老哥贴了完整的调试日志,照着改准没错。