最近在折腾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 条我也遇到过类似的坑,handshake failed在MCP里其实挺常见的,未必是配置本身的问题。你用的是vllm部署Qwen2.5-7B,这个组合我试过,关键点往往出在MCP server的Docker网络模式上——如果你客户端和server不在同一个bridge网络里,握手包会被docker的iptables规则拦截掉。另外,MCP协议版本确实有兼容性要求,Qwen2.5系列官方文档里提到需要MCP v0.3以上,但vllm的MCP插件默认可能还在用旧版schema,你得检查一下容器里启动时是否指定了—mcp-version参数。还有个小细节:Qwen2.5-7B的context_window官方推荐是32768,但MCP默认的max_tokens如果设得太高,vllm那边的prefill阶段会直接超时,导致握手阶段无响应。allow_origin一般不是必须的,除非你客户端是从浏览器发请求。建议你在docker run时加个—network host跑一次试试,排除网络隔离问题,同时确认MCP server日志里有没有“protocol mismatch”字样。
我也踩过这个坑,handshake failed多半是Docker网络模式的问题,试试把MCP server的network_mode设成host,或者检查下容器和宿主机之间的端口映射有没有漏掉。另外Qwen2.5-7B用vllm部署时,MCP的tool定义里如果带了中文或者特殊字符,客户端解析也会报错,可以先把tools清空再启动看看。还有个小细节,MCP协议对某些非标模型版本确实有兼容性门槛,建议直接用官方推荐的Qwen2.5-7B-Instruct版本。
同踩过这个坑,MCP握手失败八成是协议版本不匹配,vllm默认的OpenAI兼容接口和MCP那个标准请求格式有出入,建议换个支持MCP原生协议的后端试试。另外Docker网络模式检查下是不是host模式,我上次就是bridge映射端口导致服务端和客户端跨容器通信出问题。你Qwen2.5-7B用vllm跑的话,可以试试在MCP server配置里显式指定api_base路径,有时候自动发现会走错端点。
报handshake failed的话,大概率不是配置或方法问题,我猜是MCP server和vllm之间的协议版本没对上,尤其是用Docker跑的时候网络层容易出岔子。你可以试试在MCP server的启动参数里显式指定--host 0.0.0.0,或者检查一下Docker的端口映射是不是漏了宿主机的IP绑定。另外Qwen2.5-7B在vllm上需要设置--trust-remote-code,不然有些tokenizer会默默报错,这坑我踩过好几次。
遇到过类似问题,当时折腾了一整天发现是Docker网络模式的问题,MCP server默认绑定了localhost,但容器外连的时候得用bridge模式或者显式把端口映射出来才行。另外vllm和MCP的版本匹配确实挺坑的,建议检查一下你的vllm版本是不是低于0.6.0,老版本对MCP的API支持有bug。allow_origin那个一般不是必须的,除非你跨域调用了。不如先贴一下你的docker-compose或者run命令,看看网络配置对不对。
看到这个错误我也遇到过,折腾了两天才发现是Docker网络模式的问题。你这个用vllm跑Qwen2.5-7B的话,MCP server和vllm容器是不是在同一个网络里?如果跨了网段,handshake经常因为DNS解析失败。另外Qwen2.5的tokenizer和MCP协议默认的有些冲突,建议在server启动参数里显式指定--tokenizer-mode=slow试试。端口冲突大概率不是主因,但可以改用1024以上的随机端口再测一次。
我也遇到过,试试把MCP server和vllm都跑在宿主机上排查一下。
同踩过这个坑,vllm加docker的组合下,MCP默认的localhost和容器内部网络地址对不上容易握手失败。你试试把MCP server的host设成0.0.0.0,然后客户端连宿主机的映射端口,不要用默认的localhost。另外Qwen2.5-7B的tools调用格式和MCP的schema可能不完全对齐,你检查下模型返回的tool_call_id是不是缺失了,这个会导致handshake校验不通过。
同款问题折腾过,后来发现是vllm的--api-key参数没传对,MCP握手阶段需要显式把key带在请求头里。另外Docker跑MCP server时记得把host网络模式打开,默认bridge模式会导致端口映射错乱。你检查下客户端日志里有没有“401 Unauthorized”之类的信息,有的话八成就是鉴权问题。
试试把MCP server的host改成0.0.0.0,Docker默认localhost容易出握手问题。
可能是MCP server的Docker网络模式没设对,试试host模式或检查端口映射。
这个报错我也踩过坑,大概率不是配置问题,而是MCP协议版本和vllm的API接口没对齐。你试试在MCP server的启动参数里加上--api-base指向vllm的/v1/chat/completions,同时检查下Docker里MCP的版本是不是0.3.x以上的,旧版对Qwen2.5支持不太好。另外allow_origin那个可以设成*先排除跨域问题,我之前就是卡在这两步上。
可以看看MCP server的日志,可能是Docker网络模式没配置好导致握手失败。
你遇到的这个handshake failed报错,我折腾MCP初期也卡过好久,后来发现大概率是传输层的问题。vllm本身对MCP协议的支持其实不算原生,它主要走的是OpenAI兼容接口,而MCP server在Docker里默认绑的是localhost,容器内外网络隔离会导致客户端握手时找不到正确的socket。你试试把MCP server的host改成0.0.0.0,同时检查下Docker端口映射是不是真的把宿主端口透传进去了,有时候docker run没加-p或者端口写错会静默失败。另外Qwen2.5-7B的模型格式跟MCP的tool calling规范匹配度确实有坑,比如tools参数里如果用了strict模式,模型输出的function_call格式不对就会直接握手失败,可以暂时把tools里的strict设成false或者先注释掉所有tools配置,只保留纯文本对话看能不能连上。还有个小细节:MCP的context_window现在很多实现是硬编码了2048,你手动调大反而可能触发vllm的max_model_len校验,两边不一致也会握手失败,建议先保持默认值。如果还不行,贴一下MCP server的完整启动日志,重点看下SSL/TLS协商部分,有些镜像默认开了HTTPS但没配证书,客户端用HTTP连就会报handshake failed。
看到这个报错我第一反应是docker网络模式的问题,我之前用桥接模式也踩过类似的坑。MCP握手失败很多时候不是配置项本身的问题,而是容器和宿主机之间的通信链路没打通,尤其是vllm暴露的端口和MCP server预期的端口如果不在同一个网络命名空间里,连接就会直接失败。可以试试把docker网络改成host模式,或者明确指定--network=host,这样能省掉很多端口映射的麻烦。另外Qwen2.5-7B的tokenizer版本和MCP协议里的context_window参数确实有微妙关系,有些旧版vllm对动态batch和协议字段的兼容性不太好,建议把vllm升到0.6.3以上再看看。还有个小细节,MCP server的config里如果没显式设置--allow-origin,默认会拒绝跨域请求,你用curl测试时加个Origin头看看响应码,很多时候问题就出在这里。GitHub issue里有人提到用--trust-remote-code参数启动vllm也能缓解部分校验问题,但不确定你这个场景是否适用。总之先排查网络层,再核对协议版本,这两个最容易忽略。
握手失败这个错误我折腾过两次,最后发现是MCP server的Docker网络模式没跟vllm对齐,桥接模式下端口映射容易出问题,改成host模式直接跑就通了。另外Qwen2.5-7B的tools调用格式跟MCP默认配置有点小差异,你得在server端显式指定一下allowed_tools参数,不然协议握手阶段会卡在schema校验上。还有Ubuntu 22.04的防火墙默认可能屏蔽了Docker的UDP端口,检查下ufw规则。
老实说MCP这玩意儿目前坑确实不少,你这个报错我之前也遇到过。我当时是用ollama跑的模型,最后发现是Docker网络模式没配成host,容器里localhost指向的不对导致握手失败。另外Qwen2.5-7B用vllm的话,建议检查下MCP server的API endpoint是不是跟vllm的接口格式匹配,有些模型版本确实会对协议字段有要求。你试试把MCP server日志级别调到debug,看具体握手阶段哪一步断的,比瞎改config靠谱。
试试把MCP server的host设成0.0.0.0,docker网络模式换成host看看能不能通。
握手失败这个坑我也踩过,问题大概率出在MCP server的WebSocket端口没正确映射出来,Docker跑的时候记得把宿主机的端口和容器内部端口绑对。另外vllm默认的api_key验证可能跟MCP的握手流程有冲突,可以试试在启动参数里加个--disable-auth绕过看看。还有Qwen2.5-7B用vllm 0.6.0以上版本兼容性会好很多,我之前降级到0.5.x反而稳定了。
这个报错我也遇到过,折腾了两天才发现是MCP server的Docker网络模式没设对,默认bridge模式下容器内端口映射到宿主机会有问题,改成host模式或者检查一下docker-compose里的ports配置试试。另外vllm加载Qwen2.5时如果用了--enable-prefix-caching,跟MCP的握手阶段容易冲突,关掉就好了。你检查下server日志里有没有类似“protocol mismatch”的提示,那个比客户端报错更有参考价值。