最近在折腾MCP(模型上下文协议),想把本地部署的Qwen2.5接进Claude Desktop当工具用。我按教程写了个最简单的stdio server,用Python的mcp库起的,模型走的是Ollama的API。现在问题是:Claude那边一调用工具就报“connection timed out”,但我在终端里直接跑server脚本,curl一下Ollama的接口是通的,延迟也就几十毫秒。
MCP服务器连本地大模型总是超时,是配置问题还是我姿势不对?
全部回复
共 14 条我之前也栽在过这个坑里,大概率不是Ollama的问题,而是stdio server那边没有正确把请求转发出去。你试试把server脚本里的stdin/stdout缓冲关掉,或者用--no-buffer跑一下,还有就是确认Claude Desktop的MCP配置里command路径是不是写全了,有时候它找不到python环境也会超时。
另外你curl测的是HTTP,但MCP走的是子进程管道,两边网络栈完全不一样,不能直接类比。建议在server代码里加个日志打点,看看Claude的请求到底有没有进到你的脚本里,如果连日志都没输出,那八成是MCP握手阶段就断了。
我之前把Ollama的host从localhost改成127.0.0.1,再把server的timeout调大到30秒,莫名就好了,你试试这两个方向。
我猜大概率是stdio server的握手方式跟Claude Desktop那边不兼容,尤其是超时时间设得太短了。Ollama虽然响应快,但MCP初始化时要先做能力协商,这步如果卡住就会直接掐断连接。你可以试试把server的启动日志打到文件里,看看是卡在transport层还是tool调用层,另外确认下Claude Desktop的node版本和Python环境是不是匹配,我之前遇到过类似问题就是环境变量没传进去。
我刚开始搞MCP也踩过这个坑,大概率不是Ollama的问题,而是stdio server的启动方式不对。Claude Desktop调用的时候会拿它自己的环境变量去跑你的Python脚本,如果你用了venv或者conda,路径对不上就很容易超时。你试试在配置里写死python的绝对路径,或者先确认下server有没有真的被拉起,我那时候就是卡在这。另外也可以看看日志,MCP的stderr输出有时候会直接吞掉,但错误信息其实都写在里面。
我之前也踩过类似的坑,问题大概率不在Ollama,而是stdio server的启动方式或超时设置。Claude Desktop调MCP时对进程启动和响应时间很敏感,你试试在server代码里显式把超时调大点,比如socketTimeout设成60秒。另外确认下是不是用了异步循环,有时候没正确跑起事件循环也会导致连接挂起。我之前就是卡在asyncio的run_until_complete上,改成同步等待就好了。
大概率是stdio进程没起来或环境变量不对,试试用绝对路径跑server,别用相对路径。
你这延迟几十毫秒还超时,先查下Ollama的host是不是绑了127.0.0.1,换个端口或者走localhost试试。
我之前也踩过类似的坑,后来发现不是Ollama的问题,而是stdio server的启动方式不对。Claude Desktop连本地MCP时,如果server进程没在它预期的环境变量里跑起来,超时太正常了,你试试把server路径写成绝对路径,然后用python -m mcp.cli的方式启动。另外检查下Ollama的host是不是绑定了127.0.0.1,有时候默认监听localhost但IPv6解析会绕一圈,延迟看着低但连接就是卡住。
我之前也踩过类似的坑,大概率不是Ollama的问题,而是stdio server的启动方式不对。Claude Desktop调MCP时对进程生命周期管得很严,你试试把server脚本用绝对路径写进配置,别用相对路径。另外看看是不是Python缓冲导致的,加个-u参数强制无缓冲输出,有时候超时是握手时输出卡住了。
我之前用npx起的node server就没这问题,但你用Python的话,得确认mcp库版本跟Claude Desktop的兼容性,新版协议握手超时阈值好像变短了。如果还不行,把server的stderr重定向到文件,看下有没有报错被吞了。
我之前也踩过这个坑,大概率不是Ollama的问题,而是stdio server和Claude Desktop之间握手超时了。你试试把server的启动日志打出来,看看Claude那边有没有真的把请求发过来,有时候是环境变量或者Python路径不对导致子进程起不来。另外,Ollama的API虽然通,但MCP server默认可能没配好模型名,Qwen2.5在Ollama里的tag要写全,比如qwen2.5:latest,不然模型加载慢也会拖到超时。
还有个思路,既然curl能通,你可以在server里把Ollama的调用改成异步或者加长超时时间,mcp库默认的timeout挺短的,尤其是第一次加载模型要好几秒,很容易触发。实在不行换个思路,用HTTP模式的MCP server试试,别死磕stdio,Claude Desktop对本地进程的启动和通信限制挺多的,我之前就是这么解决的。
遇到过类似情况,最后发现是stdio server的启动方式问题。Claude Desktop调用MCP时,如果server进程没在它预期的环境变量里找到Ollama的host配置,连接就会一直挂着直到超时。你终端里能通是因为shell环境带了OLLAMA_HOST,但Claude Desktop启动的子进程可能没继承这个变量,试试在server代码里显式指定Ollama的base_url,别依赖系统环境。
另外有个细节容易忽略——stdio模式下MCP的握手是同步的,如果你的server在初始化时去调Ollama的模型列表或者embedding接口,而Ollama那边恰好还在加载模型(首次请求要等好几秒),整个握手就会卡住,Claude那边看起来就是timeout。可以在server启动时先异步预热一下模型,或者把Ollama的keep_alive设长一点。
还有种可能是你server的日志输出混进了stdout。MCP的stdio通信严格走stdin/stdout,如果你print了调试信息到stdout,Claude解析协议时会把垃圾数据当消息头,直接导致连接中断或超时。用logging写到stderr或者文件里,别用print。
如果上面都排除了,检查下Claude Desktop的MCP配置里server启动命令是不是用了绝对路径。有时候它工作目录不是你想的那样,相对路径找不到Python模块也会静默失败,表现为超时而不是报错。我上次就是栽在venv的python路径上,直接用绝对路径的python解释器就好了。
我之前也卡在这过,后来发现是stdio server的启动方式有问题。Claude Desktop那边对子进程的环境变量要求挺严格,Ollama的host或者端口如果没显式传进去,它可能默认连了个不存在的地址。你试试在server代码里硬编码Ollama的base_url,别依赖系统环境变量。
另外超时也可能跟MCP的初始化握手有关,有些版本要求server在特定时间内发ready信号,你那个Python库如果没用对transport类型(比如用的http但声明成stdio),会一直卡着。建议把server的日志输出到文件里,看看Claude那边到底有没有把请求发过来。
还有个土办法,先用mcp dev这个调试工具跑一下,它能模拟客户端的调用,比直接接Claude好排查多了。我上次就是这么定位到是参数传递类型不匹配,Qwen2.5的tool calling格式和MCP的不完全兼容,得自己转一层。
我之前也踩过类似的坑,问题多半不在Ollama本身,而是stdio server和Claude Desktop的进程生命周期对不上。你试试在server启动后加个延迟或者心跳输出,有时候Claude那边等不到初始化完成就发请求了,直接超时。另外检查下Ollama的host是不是绑定在127.0.0.1,如果Claude Desktop跑在沙箱环境里,可能访问不到这个地址。还有个小细节,Python的mcp库版本太新的话,有些默认参数会变,你看看有没有把transport_type明确设成stdio。我之前换成用sse模式就稳定多了,虽然配置繁琐点,但至少不会莫名其妙断连。
我之前也卡在这过,后来发现是stdio server的启动路径问题,Claude Desktop调用时用的工作目录和终端不一样,导致它找不到Ollama的环境变量。你试试在server脚本里硬编码Ollama的host和port,别用默认的localhost,有时候IPv6解析会坑你。另外检查下Claude Desktop的权限设置,macOS上它可能被沙盒限制了网络访问,这个最容易忽略。
我之前也踩过类似的坑,多半不是Ollama的问题,而是Claude Desktop那边对stdio server的启动和心跳超时判断太严格了。你试试把MCP配置里的command参数改成用python -m mcp_server这种绝对路径,或者检查下子进程有没有因为环境变量缺失直接崩了。另外,如果server启动时要加载模型配置,可能会超过Claude默认的几秒超时窗口,可以试试在server代码里先把模型预热好再监听。我之前是把Ollama的keep_alive设成-1,然后延迟就消失了,你可以参考下。
我之前也踩过这个坑,八成是Claude Desktop启动server时用的环境变量跟你终端里不一样,Ollama的host或者代理没传进去。你可以在server脚本开头把环境变量打印到日志里,对比一下就知道差在哪了。另外stdio模式下别往stdout写任何调试信息,会污染协议导致超时,日志一律写stderr。