最近在折腾MCP(Model Context Protocol)部署本地大模型,按照官方文档一步步来,但启动服务后客户端连接时总报“handshake failed”错误。我试了调整context_window大小和修改tools配置,还是不行。环境是Ubuntu 22.04,用vllm部署的Qwen2.5-7B,MCP server跑在Docker里。怀疑是不是模型版本和MCP协议版本不兼容?或者需要额外设置allow_origin?看GitHub issue里有人说是端口冲突,但我检查过了。求大佬指点一下,这玩意儿是不是有隐藏前提条件?先谢过!
MCP部署大模型时总是报错,是配置问题还是我方法不对?
全部回复
共 185 条看到你这个报错我太有共鸣了,之前折腾MCP时也被“handshake failed”折磨了两天。你提到vllm+Qwen2.5-7B这个组合,我怀疑问题可能出在Docker网络模式上——默认bridge模式下容器和宿主机通信有时会丢包或被防火墙拦截,试试把MCP server和客户端都放在同一个host网络里跑,或者显式映射端口到宿主机。另外,Qwen2.5-7B如果用vllm的openai-compatible接口,建议检查下MCP server里配置的base_url是不是写成了localhost,改成宿主机IP试试。allow_origin这个参数一般在跨域请求时才需要,本地开发通常不用管,除非你前端和server在不同容器里。还有个小坑:vllm的某些版本对stream=True的处理和MCP协议握手阶段有冲突,可以尝试在vllm启动参数里加上--disable-stream-outputs。建议你先用curl直接调vllm的/v1/chat/completions接口确认模型本身没问题,再一步步排查MCP的握手逻辑。
我最近也踩过这个坑,handshake failed大概率是MCP server的端口绑定和Docker网络模式没对齐。试试在docker run加个--network host,或者把vllm的API端口显式映射出来。另外Qwen2.5-7B的tokenizer配置里如果用了特殊token,可能和MCP协议要求的上下文格式冲突,建议用默认chat template跑一遍。
可能是docker网络模式没配host,vllm和MCP server跨容器通信容易出这个问题。
握手失败这个问题我折腾过一阵,最后发现是Docker网络模式的问题——默认bridge模式下MCP的ws端口映射容易出幺蛾子,改成host模式或者加个network: host就通了。另外vllm的api接口路径跟MCP默认的/v1/chat/completions可能对不上,你检查下server端配置里的endpoint是不是写成了/v1/completions。还有个小细节,如果启用了防火墙,记得把MCP用的那个端口放行。
我之前也遇到过handshake failed,后来发现是Docker网络模式的问题,默认bridge模式会导致MCP的WebSocket端口映射异常,换成host模式或者加--network=host就正常了。另外vllm和MCP的协议版本确实可能有坑,我用的Qwen2.5-7B-Instruct搭配MCP 0.3.0才稳定,你检查下两边版本号对不对得上。还有allow_origin这个我倒是没设,但如果你客户端不是localhost访问,建议加上试试。
试试把MCP server的host设成0.0.0.0,Docker里默认绑127.0.0.1容易出奇奇怪怪的问题。
我也遇到过类似的handshake failed,折腾了好久才发现是Docker网络模式的问题。你试试把MCP server的network_mode设成host,或者确保客户端能访问到容器映射的端口,有时候docker内部的localhost和外部对不上。另外vllm的API地址检查一下,别漏了/v1/chat/completions这个路径,我之前就是挂在这上面。
我之前也踩过这个坑,vllm加Docker的组合确实容易在握手阶段出问题。试试把MCP server的--host设成0.0.0.0,docker映射端口时别用127.0.0.1,我猜是容器内监听地址没放开。另外检查下vllm服务本身有没有绑定localhost,跨容器通信经常栽在这细节上。如果还不行,贴一下docker-compose或者启动命令的片段?光看error的话,allow_origin通常不会直接导致handshake failed。
老哥你这问题我折腾过好几回了,handshake failed八成不是配置问题,MCP协议对vllm的兼容性确实有点坑。Qwen2.5-7B的tokenizer在MCP初始化时会多塞一些特殊token,导致context_window实际可用值比设的小,你试试把max_tokens设成4096以下,别超过模型官方推荐值。另外vllm用Docker跑的话,记得把--host设成0.0.0.0,默认绑127.0.0.1会让MCP server握手时拿不到正确地址。allow_origin这事我踩过雷,如果你MCP server和客户端不在同一个容器网络里,得显式设成*或者你客户端的域名,不然跨域握手直接断。还有个小细节——vllm的api版本号,MCP有时候会校验这个,你检查下启动日志里有没有类似“unsupported api version”的警告。我最后是换了vllm 0.5.3固定版本才稳住的,你可以回退试试。
老哥你这个报错我太熟了,上周刚被handshake failed折磨了两天。我猜大概率不是配置问题,而是MCP server的WebSocket端口绑定和vllm那边的CORS策略没对上。我试过直接用vllm的API端口暴露给MCP,结果也是握手失败,后来发现MCP要求server必须明确设置--host 0.0.0.0并且用--port指定一个未被占用的端口,同时vllm那边如果开了--enable-auto-tools得检查下是否和MCP的tools定义冲突。另外你检查过Docker的网络模式没?如果你MCP server跑在bridge模式,vllm在宿主机上,那docker内部访问宿主机要用host.docker.internal而不是localhost,这个坑我踩过。还有Qwen2.5-7B的tokenizer版本,MCP的v0.1.9对qwen系列有个已知的兼容性补丁,你试试把mcp-server升级到最新版,或者干脆降到0.1.8看看。要是还不行,贴一下docker logs和vllm的启动参数,我帮你对着官方example逐行比对。
我之前也遇到过类似问题,后来换了方案。
试试把MCP server的host改成0.0.0.0,或者检查下Docker网络模式是不是bridge。
握手失败大概率是MCP server的端口没映射到宿主机,Docker跑的时候加个-p试试。
同遇到过handshake failed,大概率是MCP协议版本和vllm的API接口对不上,建议先确认一下vllm的openai兼容接口版本,Qwen2.5-7B有些旧版本需要显式指定--api-key参数。另外Docker里跑MCP server时记得把host设成0.0.0.0,否则容器外的客户端连不上,端口冲突倒不常见。你试试把MCP server的日志级别调到debug,看看握手阶段具体卡在哪一步,这样排查快很多。
检查下MCP server的Docker网络模式,改成host模式试试,我之前也是handshake failed。
vllm的mcp接口默认绑localhost,docker里得配network_mode=host才行。
检查下MCP server的Docker网络模式,用host模式试试,我上次也是handshake failed改这个就好了。
遇到过类似情况,后来发现是Docker网络配置的问题,MCP server和客户端不在同一个网络桥接里会导致handshake失败,可以试试用host模式或者指定network。另外vllm的API端口确认一下是不是暴露给MCP了,有时候默认绑定本地环回地址会坑人。还有个小细节,Qwen2.5-7B的chat template如果没正确设置,MCP解析tool call时也会莫名其妙报错,建议先切个简单模型排除下兼容性。
vllm的api端口和mcp的端口冲突过,试试把mcp的端口改到9000以上。
我也遇到过类似问题,折腾了好几天才找到原因。你试过把MCP server和vllm放在同一个网络命名空间里跑吗?Docker默认的bridge模式有时候会导致端口映射问题,虽然你检查过端口,但实际连接时可能走的还是内部地址。另外Qwen2.5-7B和MCP协议的握手确实有版本匹配要求,可以看看vllm的日志里有没有协议版本号,跟MCP server要求的对一下。