)
为什么要部署到线上只有部署到线上才能发现更多问题学习更多实践经验如跨域问题等。下面介绍几种不同的上线方式。推荐使用内网穿透技术实行线上部署适合快速上线让他人通过ngrok映射的域名访问到你本地运行的MCP Servser sse远程模式项目。内网穿透技术部署不需要买服务器别人即可访问适合快速上线前置说明内网穿透大家做了解即可。后续更新微信平台部署项目。一、 为什么用内网穿透什么叫内网穿透首先思考为什么我们部署在本地的项目外界访问不到正常来说我们的电脑在内网使用的内网IP想要让他人访问到必须要公网IP。所以我们需要使用内网穿透技术将我们本地电脑的IP暴露成公网IP这样他人可以访问到。内网穿透技术其实就是将内网的电脑 “暴露” 到公共网络。可以简单理解为一个中间人由于他知道你的电脑地址所以能建立一条隧道帮助其他用户访问到你的计算机。流程 其它用户请求 -- 公网服务器 -- 内网服务器想要使用内网穿透技术就需要使用工具。二、内网穿透工具Ngrok不推荐体验下流程即可① 下载地址ngrok: deliver your apps, APIs, and AI on local and prod可以使用Github或者邮箱进行注册登录。点击Get Startted(FOR FREE) 进行sign up注册。我使用的网易163邮箱进行注册。注意返回400错误Invalid request大概率你用国内邮箱被拦截可以尝试使用github或者outlook或者重新进入网页多试几次我就是多试几次。下一步登录163邮箱进行验证。邮箱内发给你一个网址让你登录进行验证。网址验证完后continue继续进入dashboard登录面板。网址【Gateway Quickstart | Get Started with ngrok】在Quickstart按照操作步骤一步步操作。选择你的操作系统。下载安装ngrok zip安装包:解压zip安装包到中文无空格路径下可以看到我们得到了ngrok.exe可执行文件。② 本地执行 ngrok 命令添加用户的 authtoken点击右上角的show Authtoken可以看到属于你的密钥进入到你解压ngrok文件目录下复制上面添加密钥的命令并打开cmd执行。可以看到Authtoken saved已经保存。我们的账号信息已经保存到本地ngrok的配置文件中,接下来只需要执行ngrok http 端口号命令即可启动内网穿透服务。③ 启动ngrok内网穿透服务将端口号改为自己本地项目占用的端口号比如我们后端yml中配置的是port: 8123,那么我们就用8123作为内网端口。我执行的命令:ngrok http 8127 --url https://yarn-smasher-dispersed.ngrok-free.dev在命令执行结果中可以看到公网域名到内网IP的映射Ngrok 自动为我们生成了一个域名还是 Https指向本机的服务。④ 使用ngrok给出的映射MCP Server的域名访问我们的MCP Server服务器前置条件⭐- MCP Server服务器在本地处于运行状态- 确认项目已经引入spring‑ai‑starter‑mcp‑server‑webmvc依赖sse 模式必须 webmvc不能只用 stdio 的 starter- 确认active: sseapplication‑sse.yml存在- 本地访问http://localhost:8127/sse看 SSE 数据流是否输出- client 配置 url 填写完整 ngrok/sse 地址MCP Client 配置必须写完整外网地址带 /sseapplication.ymlspring: ai: mcp: client: sse: connections: server1: url: https://yarn‑smasher‑dispersed.ngrok‑free.dev/sse第一次访问Server服务器使用网址需要进行允许存储Cookie,点击【Visit Site】,浏览器输入网址https://yarn-smasher-dispersed.ngrok-free.dev然后跳转到404页面。注两个块引用中的错因分析可以不看直接操作。推荐看懂原理Whitelabel Error Page 是SpringBoot 默认的 404 兜底错误页含义访问的 URL 路径后端没有写对应的接口返回 404 找不到资源。分析后端项目也会返回网页页面。出现这个页面 HTTP 404 Not Found属于接口路径找不到服务本身是正常启动的服务没崩只是你访问的地址不对。根因MCP‑SSE 后端没有实现根路径/接口MCP SSE 真正的接口地址一般是/sse不是根/正确地址示例http://127.0.0.1:8127/sse如果你用 ngrok 访问要访问https://xxx.ngrok.io/sse不要只访问域名根路径。访问根/→后端没有这个接口 →触发 404弹出 Whitelabel 白页这是正常现象不等于服务挂了。补充说明怎么判断流量已经打到你本地 SpringBoot看响应头与返回内容几个关键点1. 响应体是 SpringBoot Whitelabel 404 页面状态码404 Not FoundContent‑Type: text/html;charsetUTF‑8返回的就是那个白色错误页面。如果 ngrok 本身连不上本地端口ngrok 会直接返回ngrok 自己的错误网页页面上会写 ngrok error /tunnel connection failed返回头会全是 ngrok 的页面不会出现 SpringBoot 的 whitelabel。2. 关键证据Content‑Length: 275SpringBoot 默认 Whitelabel 错误页面 HTML 长度固定就是 275 字节。这个 HTML 是你本地 Tomcat/SpringBoot 生成出来再交给 ngrok 转发给浏览器。 如果隧道不通ngrok 直接返回它自己的错误页Content‑Length 不会是 275。3. 看响应头里的Nginx‑Agent‑IpsplaintextNgrok‑Agent‑Ips: 2409:8a00:60e2:da00:4cdc:357:3e0e:a035这个头是 ngrok 加上去的代表ngrok 代理已经收到请求并且成功把请求转发到你的本地 8127 端口本地 SpringBoot 处理完再把响应原路返回给 ngrok再传回浏览器。两种情况对比方便你区分表格现象含义返回 Whitelabel Error Page275 字节 html✅ngrok 隧道通请求抵达你本地 SpringBoot只是路径/不存在 404页面显示 ngrok 报错页面tunnel error /connection refused❌ngrok 连不上本地端口流量根本没到你的 SpringBoot你现在属于第一种隧道没问题仅仅是访问根路径/MCP 服务没有这个接口需要访问/sse。所以我们使用的正确网址应该是https://yarn-smasher-dispersed.ngrok-free.dev/sse注意若此网址还是不行先测试本地IP是否能成功访问Server服务器http://localhost:8127/sse可以看到本地访问成功了。若失败说明Server服务端有问题自己调试看前置条件是否都满足⑤ 测试手机端是否能够访问MCP Server模拟他人外网访问前置条件- 手机和电脑在同一wifi下ngrok免费版限制- 手机不要用自带浏览器访问下载Google进行访问重复老步骤访问网址https://yarn-smasher-dispersed.ngrok-free.dev/sseERR_NGROK_6024 问题根源ngrok 免费版强制安全拦截页ngrok截图这个页面就是ngrok‑free.dev 免费套餐强制的中间确认弹窗不是网络故障。为什么电脑正常手机弹出这个页面电脑浏览器已经点击过Visit Site浏览器保存了 ngrok 的 Cookie7 天内不再弹出警告页ngrok。手机是全新设备没有这个放行 Cookie访问就强制弹出确认页必须手动点 Visit Site 才能继续访问后端/sse。致命坑MCP SSEEventSource不能自动点击这个网页按钮Spring‑AI MCP‑Client 底层用 EventSource 建立 SSE 长连接。当 Client 程序访问 ngrok 的/ssengrok 返回的不是 SSE 流而是这个确认 HTML 警告页面。EventSource 无法识别、无法点击 Visit Site直接连接失败、超时。这就是你的 MCP Client 如果用这个 ngrok 免费地址会直接超时的元凶⭐⚠️注意这个弹窗只对浏览器 HTML 访问生效小结手机浏览器点Visit Site浏览器层面可以正常浏览 sseJava MCP Client 程序无法自动处理这个网页弹窗直接超时免费 ngrok‑free.dev 不适合做 MCP‑SSE 的远程调用要么 frp要么升级 ngrok 付费版否则远程 MCP Client 会持续报 TimeoutException。⭐推荐使用frp后面有机会我试试并附上Client调用访问Server我们点击Visit Site,允许放行此Cookie可以看到成功访问到Server服务端。我们刷新一下网页重新发请求顶部Error消失⑥ 测试手机是否能访问我们部署的MCP Server的接口在你的 SpringBoot 写一个测试接口javaimport org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class TestController { GetMapping(/hello) public String hello(){ return I am local springboot; } }ngrok 外网访问https://yarn‑smasher‑dispersed.ngrok‑free.dev/hello浏览器会打印I am local springboot就实锤流量完整走到本地。至此我们ngrok内网穿透部署和测试全流程完毕⑦ MCP Client使用ngfork给出的域名访问MCP Server将ngrok域名地址放到MCP Client 的application.yml中关于MCP Server的url地址配置spring: ai: # mcp client 客户端配置 mcp: client: sse: algo-image-search-mcp-server: url: https://yarn-smasher-dispersed.ngrok-free.dev注意缩进是两个空格自己调整注意url地址末尾不要加 /sse, 否则启动错误。应该是我们Server端自动给Client访问url末尾追加sse默认debug启动我们之前的集成测试方法测试Client调用Server的【图片搜索工具类】可以看到拦截请求中检测到了request中functionCallbacks存在MCP Server sse模式中的【图片搜索工具】:debug继续放行发现Client调用Server工具类超时了超时原因我们前面⑤中已经说明就是我们我们访问Server端时会先蹦出一个放行Cookie页面必须我们手动点击Visit Site进行放行。而我们使用MCP Client进行调用超时就是因为被这个放行Cookie阻碍了。Spring‑AI MCP SSE Client 不能自定义 EventSource 请求头 →免费 ngrok 无法用于远程 MCP 调用。但同时我们在工具注册中检测到了Server端的工具说明访问成功了。解决方案1. 升级ngrok为付费版2. 使用frp完全免费且无放行Cookie产生的超时问题⭐推荐3. 本地不走隧道 不走外网隧道Client、Server 同一台机器直接127.0.0.1:8127/sse所以我们下一步是尝试使用frp进行远程部署。⑧ 固定域名如果你想要自己的域名可以添加domain分配属于自己的域名。不过由于初始系统自动分配了一个额度且已用掉后续申请新的固定域名需要付费了。看自己需求。三、内网穿透工具frpTODO待更新想了想需要云服务器暂时搁置后续更新其它的部署方式。有时间我再重新研究一下。主要感受一下部署流程毕竟上线时我们会遇到很多问题内网穿透并不能很好的暴露后续尝试微信平台部署后端项目。