1. localhost 只对你可用,而不是对 ChatGPT
先从本模块最容易引发认知错位的地方说起。你在浏览器里打开 http://localhost:3000,一切工作正常:Next.js 很开心,小部件成功渲染。 看起来顺理成章:“既然我有一个 URL,那就把它给 ChatGPT 吧。”
问题在于,localhost 并不是“我这台机器在互联网中的神奇域名”。 这是一个特殊名称,它总是指向发起请求的那台机器本身(运行浏览器或客户端的那台)。 你的笔记本是在向自己发请求。OpenAI 的服务器(运行 ChatGPT 的地方)当然也能访问 localhost……但那是它们自己的 localhost——在数据中心内部。 而你的 Next.js 则老老实实地被家庭路由器、NAT,甚至可能还有公司 VPN 隔在里面。
本讲我们将:
- 弄清楚为什么 localhost 对 ChatGPT 不可达;
- 通过 cloudflared 把 localhost:3000 暴露到公共 URL 的 HTTPS 隧道;
- 把该 URL 接入 ChatGPT 的 Dev Mode;
- 通过一个对小部件的简单改动验证“代码 → 隧道 → ChatGPT”的链路,并讨论常见踩坑点。
由此有两个简单结论:
- ChatGPT 不知道你的笔记本在哪儿。
- 即便知道,它也无法直接连到你的机器——入站连接被阻断。
此外,ChatGPT 原则上只使用公共的 HTTPS 入口(endpoint): 需要正规域名与 TLS 证书。出于安全考虑,OpenAI 的服务器不会访问任意未加密的 HTTP 地址, 因此必须是带有效证书的 HTTPS 域名。单纯把 http://我的公网IP:3000 暴露出去——已经不行了。
因此我们需要一个中介——一个服务,它能够:
- 运行在互联网上并提供正规的 HTTPS 域名;
- 能把来自该域名的请求安全地转发到你的 localhost:3000。
这就是 HTTPS 隧道。
2. 什么是 HTTPS 隧道:直观模型
撇开术语不谈,隧道就是一个服务,它给你一个临时(或长期)的公共 URL,并把该 URL 上的所有请求转发到你的本地端口。 在网络术语里,这本质上是一个反向代理(reverse proxy),由你这边主动保持到云端的出站连接。
一个直观类比:你被关在门后(家庭路由器),而隧道就像门外的快递员,举着一块牌子“所有信件到我这儿”, 然后通过后门通道不时进来把信件亲手交给你。
请求路径大致如下:
sequenceDiagram
participant ChatGPT as ChatGPT(云端)
participant Tunnel as HTTPS 隧道
(Cloudflare / ngrok)
participant Dev as 你的开发服务器
(localhost:3000)
ChatGPT->>Tunnel: 对 https://xyz.trycloudflare.com 发起 HTTPS 请求
Tunnel->>Dev: 对 http://localhost:3000 发起 HTTP 请求
Dev-->>Tunnel: Next.js 响应
Tunnel-->>ChatGPT: HTTPS 响应
几个关键点。
首先,你才是与隧道服务建立连接的一方。 工具(cloudflared、ngrok 等)会自行向云端发起出站连接。 即便在 NAT/防火墙之后,这几乎总是被允许的。
其次,隧道服务会给你带有效证书的 HTTPS 域名,因此无需手动部署自签名 TLS。
第三,对 ChatGPT 而言,你的 App 就是一个拥有 HTTPS 域名的普通 Web 服务。它并不知道后面的流量会被转发到某人的笔记本上。
3. 有哪些隧道方案,以及本课程的选择
在 Web 开发生态中,这类需求有若干常用方案:
- ngrok —— 经典之作,长期是“把本地服务暴露到公网”的事实标准。
- Cloudflare Tunnel(cloudflared)—— Cloudflare 提供的现代免费方案,甚至无需注册就能获得 *.trycloudflare.com 域名;也可以绑定你自己的域名。
- LocalTunnel —— 魔法最少,纯 npm 包,会给出一个临时的 HTTPS URL,例如 https://something.loca.lt。
它们都解决同一件事:为本地服务器提供一个 ChatGPT 可用的公共 HTTPS 域名。
为避免分散注意力,本课程将以 Cloudflare Tunnel(配合 cloudflared)作为“主力工具”。 理由很简单:快速上手、无需注册即可打通、提供正规 HTTPS、且一条命令即可启动。
当然,如果你已经是 ngrok 的重度用户——也没问题。命令略有不同,但理念完全一致: 把 ngrok http 3000 换成 cloudflared tunnel --url http://localhost:3000 即可。
为了更直观地比较,我们用一张小表归纳一下这些工具。
| 工具 | 需要注册? | URL 格式 | 主要优点 | 主要缺点 |
|---|---|---|---|---|
| Cloudflare Tunnel | 否 | |
上手快,正规 HTTPS | 每次启动 URL 都会变化 |
| ngrok | 是 | |
文档与生态庞大 | 免费 URL 同样会变化 |
| LocalTunnel | 否 | |
通过 npm 安装,几乎没有“魔法” | 域名不太稳定,功能较少 |
本讲我们聚焦于Cloudflare Tunnel 的“快速一次性隧道”模式。 这足以让你的 Next.js 通过 Dev Mode 与 ChatGPT“连上朋友”。
4. 先确认本地 Next.js 正在运行
在把服务通过隧道暴露出去之前,要先确认本地服务器确实在工作。 否则你可能一直在排查隧道问题,而真实原因只是 Next.js 根本没启动。
标准流程回顾:
# 在包含 Apps SDK 模板的项目根目录
npm install # 如果还没执行过
npm run dev # 启动 Next.js 的开发服务器
默认情况下,Next.js 16 会监听 http://localhost:3000(如果端口未被占用)。 终端中会看到类似输出:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
在浏览器中打开 http://localhost:3000,确认模板页面能正常显示。 这是你的“本地实验室”。如果这里就不工作(构建错误、TypeScript 报错、端口占用), 请先修好这些问题,再谈隧道。
5. 启动 Cloudflare Tunnel:从 localhost 到公共 HTTPS
接下来进入高光时刻——让任何人(包括 ChatGPT)都能通过一个 HTTPS URL 打开你的 Next.js。
安装 cloudflared
安装方式取决于操作系统。macOS 上最简单的是通过 Homebrew:
brew install cloudflare/cloudflare/cloudflared
在 Windows 和 Linux 上,可以下载现成的二进制文件,或按 Cloudflare 文档建议使用包管理器 (链接见本模块的补充材料)。
用下面的命令验证是否安装成功:
cloudflared --version
如果提示找不到该命令,请检查 PATH 或重启终端。
快速一次性隧道
我们的目标是一个最小可用的隧道:无需账号、域名或复杂配置。 为此,cloudflared 提供了 quick tunnel 模式,它会给出 trycloudflare.com 域名下的 URL。
在另外一个终端里(此时 npm run dev 已经在跑)执行:
cloudflared tunnel --url http://localhost:3000
记住一个简单规则:外部用 HTTPS,内部用 HTTP。 cloudflared 会在外部为你提供 HTTPS 域名,但连接你的 localhost:3000 时用的是普通 HTTP。
稍等片刻,日志里会出现类似内容:
INF +-------------------------------------------------------------+
INF | Your quick Tunnel has been created! |
INF | https://giftgenius-1234.trycloudflare.com |
INF +-------------------------------------------------------------+
这个 https://giftgenius-1234.trycloudflare.com 就是你的本地应用在互联网上的新公共地址。 隧道接收该域名上的 HTTPS 请求,并将其转发到 http://localhost:3000。
有两点务必注意。
首先,运行 cloudflared 的终端必须保持打开,只要你还需要这个隧道。 一旦关闭终端(或按下 Ctrl+C),隧道就会停止,URL 也会失效。
其次,每次启动 quick tunnel,URL 可能都会变化。对我们的教学开发而言这没问题: 本模块的目标只是让 ChatGPT 能通过任意可用的 HTTPS 地址访问你的本地 Next.js。 但这意味着你有时需要在 ChatGPT 的 Dev Mode 里更新 URL。 在第 7 模块我们会再回到隧道话题,配置一个稳定的开发域名,避免频繁更换地址。
像普通网站一样检查隧道
在接入 ChatGPT 之前,先确认隧道确实能从互联网打开。
- 在浏览器中打开你得到的 https://...trycloudflare.com。
- 你应该能看到与 http://localhost:3000 相同的界面。
- 在运行 npm run dev 的控制台里会出现新请求——说明 Next.js 确实在响应外部访问。
如果打不开或出现错误,请先排查:
- npm run dev 是否在运行。
- 启动隧道时本地 URL 是否写对(应为 http://localhost:3000,不要用 https://,也不要写成端口 3001)。
- 是否有东西阻断了出站连接(较少见,但在严格的企业网络里可能发生)。
6. 把该 URL 接入 ChatGPT 的 Dev Mode
现在我们已经具备了串起整条链路的一切:
ChatGPT(云端) → 你的 HTTPS 隧道 → 本地 Next.js。
关于 Dev Mode 的界面你在上一讲已经见过,这里我们重复同样流程,但这次换成 真实的 HTTPS URL,而不是理论上的地址。
在 ChatGPT 里的基本步骤如下。
先在浏览器里打开 ChatGPT,进入开发者相关的区域(通常类似 “Developer”、“Apps”、“My apps”——具体名称可能随 UI 更新而变化)。
创建一个新应用,或者编辑你已经创建过的开发应用。
在需要填写 App URL 的字段中,填入隧道的根地址,例如:
https://giftgenius-1234.trycloudflare.com/mcp
入口是我们的 /route/mcp.ts。ChatGPT 在连接时会从这里开始,再获取所需的全部信息。 如果你的模板 README 指定了别的路径(例如有多个应用),则以 README 为准;在本课程里,默认为“隧道根 URL + /mcp”。
保存应用配置。此时 ChatGPT 会通过隧道向你的应用发出若干请求:
- 读取 App 的清单(元数据、工具等)。
- 检查 MCP 入口是否可用。
- 获取所有 tools 与资源列表。
- 缓存所有小部件的 HTML 代码(!)
如果一切正常,你会在 Dev‑Apps 列表中看到你的应用。如果某处出错(清单无效、服务器无响应、隧道已断), ChatGPT 会显示类似 “App unavailable” 的错误。
注意:ChatGPT 会使用同一个隧道 HTTPS URL 来访问 MCP(工具调用) 和 小部件及静态资源。下一节我们分别解释这两种角色。
7. 请求现在如何流转:你的隧道的两种角色
务必清楚ChatGPT 是如何使用这个 URL 的。 在 Apps SDK 的架构中,有两类主要入口:MCP 端点与 UI 小部件。
简化后的链路如下:
flowchart LR
ChatGPT["ChatGPT(模型)"]
subgraph Internet
Tunnel[HTTPS 隧道
giftgenius-1234.trycloudflare.com]
end
Local["Next.js 开发服务器 http://localhost:3000"]
ChatGPT -- HTTP(S) 请求到 /mcp --> Tunnel
ChatGPT -- 加载 iframe /widget --> Tunnel
Tunnel --> Local
隧道实际上承担两种主要角色:
- 角色 1:MCP 端点(工具)。 当模型决定调用某个工具(tool)时,会对 MCP 端点发起 HTTP POST (在模板中,这是 Next.js 的 app/mcp/route.ts 路由),域名仍是同一个隧道域名。
- 角色 2:UI 小部件与静态资源。 当模型决定展示一个小部件时,它会嵌入指向你 URL 的 iframe(通常是 /widget, 或清单中指定的路径),加载同样经过隧道。
因此隧道并非“只为某一类用途”,而是通往你本地 App 的唯一大门:UI、MCP、静态资源,都通过同一个公共 HTTPS 域名。
8. 动手实践:验证“代码 → 隧道 → ChatGPT”的链路
为了确保不是“纸上谈兵”,请完成以下最小实践。
首先运行 npm run dev, 确认 http://localhost:3000 能在浏览器中打开。
其次运行 cloudflared tunnel --url http://localhost:3000 获取公共 HTTPS URL。 在另一台设备或另一款浏览器(比如手机使用移动网络)中访问该地址——这样你能确定请求确实经过了互联网,而不是仅在本机循环。
然后打开 ChatGPT,进入 Dev Mode,确认你的 App 已连接到这个 URL。 在 ChatGPT 的对话框中选择你的 App,开始对话,看看 ChatGPT 是否会插入小部件并加载你的 UI。
为了直观看到这就是你的代码,可以对小部件做个非常简单的改动,比如修改标题:
// app/widget/page.tsx(示例)
'use client';
export default function GiftGeniusWidget() {
return <h1>GiftGenius 通过隧道 🚇</h1>;
}
保存文件后:
- 等待 Next.js 完成 fast refresh;
- 回到你在 ChatGPT 中添加应用的地方并刷新;
- 在 ChatGPT 中打开/刷新与该 App 的会话;
- 向 ChatGPT 发送一个新请求,要求它展示你的小部件;
- 确认新的标题文本已经在 ChatGPT 内部显示出来。
这就是“真相时刻”:你刚刚在本机修改了代码,而该改动通过隧道反映到了 ChatGPT 的云端界面中。
9. 关于安全性与“你到底暴露了什么”
任何隧道都不是玩具,而是真实的公共入口通向你的机器。 在我们的教学场景中,我们仅转发 localhost:3000(Next.js 应用所在端口)。 在以下条件下,这相对安全:
- 该端口没有被用于其他用途;
- 你没有把“怪兽应用”塞在一起,比如内置数据库管理、phpMyAdmin 以及其它一堆 demo 服务。
一些重要的实践守则:
隧道是开发工具,而非生产托管。我们有意只在 Dev Mode 使用它, 并不面向真实用户,更不会用于收款等严肃场景。
请不要在同一个端口(3000)上运行任何管理面板、无密码数据库等敏感服务。 只要你通过隧道转发了这个端口,所有在该端口上响应的内容就对外网可见。
不要随意把你的 trycloudflare.com URL 四处传播。是的,在你做教学项目时, 别人主动来扫描它的概率不高;但“把开发服务器链接随手乱丢”的习惯,一旦到了生产环境就会埋下大隐患。
后续在讲到 Vercel 与生产环境时,我们会使用正规的托管与稳定域名,并具备生产级安全; 隧道会继续作为纯开发工具存在。
10. 本地运行与隧道的常见错误
现在我们已经有了本地 Next.js、可用的 HTTPS 隧道,以及在 ChatGPT 中接入的 Dev Mode。最后列出几类几乎人人都会遇到的常见错误,以及如何快速定位。
错误 №1:试图在 ChatGPT 中直接使用 http://localhost:3000。
一些新手会把这个 URL 直接复制到 Dev Mode 配置里,然后惊讶于 ChatGPT 提示无法访问 App。 再次提醒:localhost 对发起请求的一方来说意味着“我自己”。对 ChatGPT 来说,那是 OpenAI 的服务器,而不是你的笔记本。 你这边通常也看不到任何日志,因为请求根本到不了你的机器。
错误 №2:隧道指向了不存在或错误的端口。
常见场景:你曾经在 3000 端口跑过 npm run dev,后来服务已经停止,但你在另一个终端习惯性地启动 cloudflared tunnel --url http://localhost:3000。Cloudflare 会给你一个漂亮的 HTTPS 域名,但打开后报错。 诊断很简单:本地服务器没活着。请总是先在浏览器中检查 http://localhost:3000, 再开启隧道。
错误 №3:启动隧道时把 http:// 与 https:// 搞混。
隧道会在外部提供 HTTPS,但连接本地服务器必须使用 HTTP,例如 http://localhost:3000。若尝试写成 https://localhost:3000,经常会导致内部 TLS 相关的莫名错误,或者直接不可达。记住规则:外部 HTTPS,内部 HTTP。
错误 №4:在 ChatGPT 中测试时不小心关掉了运行隧道的终端。
这也是经典问题:一切配置妥当,App 在 ChatGPT 中运行良好,但你不小心关掉了 cloudflared 的终端。十分钟后回到 ChatGPT——看到 “App unavailable”。 原因很简单:URL 还在 App 设置里,但隧道本身已经停了。请牢记: 只要你在 Dev Mode 里测试 App,隧道所在的终端就必须保持运行。
错误 №5:重启隧道后使用了新 URL,却没在 ChatGPT 中更新。
在 quick tunnel 模式下,Cloudflare 每次都会给一个新的 *.trycloudflare.com。 如果你停止并重新启动了 cloudflared,而 ChatGPT 里还是旧的 URL, 它就会继续访问旧地址,结果要么超时要么命中他人的服务。每当隧道 URL 变化,请及时更新 Dev Mode 设置。 稍后我们会讲如何弄一个稳定的开发域名,省得追着 URL 跑。
错误 №6:把多余或危险的服务一起暴露到了同一端口。
有时为了图省事,开发者会在 3000 端口上同时运行 Next.js 与各种“辅助服务”: 调试面板、没有授权的实验性 API 等。一旦你通过隧道暴露了这个端口,这些东西也一并对外可见。 在教学项目中也许问题不大,但在真实项目里,这种习惯会显著提升泄漏与入侵的风险。 务必牢记:只要某个服务在隧道指定的端口上响应,它就对互联网敞开。
GO TO FULL VERSION