web-gpt-file-save
Allows ChatGPT/OpenAI to save files, generated images, and attachments from conversations to a local macOS project directory via MCP tools like save_file and get_project_context.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@web-gpt-file-savesave the file I just uploaded to my project directory"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
web-gpt-file-save
中文 | English
一个独立的 MCP 服务,用于把 ChatGPT 对话中的附件、生成文件和图片可靠地保存到 macOS 本地项目目录。
ChatGPT 对话文件
-> 临时或固定公网 HTTPS MCP 地址
-> 本 MCP 服务(Streamable HTTP)
-> OAuth 2.0 authorization code + PKCE
-> openai/fileParams
-> save_file(import_file 保留为兼容别名)
-> ChatGPT 临时 download_url
-> DNS 校验 + 连接 IP 固定
-> FILE_SAVE_ROOT/<destination 或原文件名>当前实现
save_file是主要工具名,描述覆盖“保存 / 导出 / 下载 / 复制 / 持久化”等常见用户意图。import_file保留为兼容别名,避免已有客户端在迁移过程中失效。get_project_context是零参数项目定位工具:需要本地项目路径时应先调用它,不要让用户在每个新对话里重复输入绝对路径。show_config也要求 OAuth 授权;公网匿名调用不会获得本地文件系统路径。项目根目录由部署时的
FILE_SAVE_ROOT一次性配置;对话中的save_file只使用相对路径,destination还可以直接省略。两个工具都通过
_meta["openai/fileParams"]声明顶层file参数。destination可省略;默认使用 ChatGPT 提供的原文件名,没有文件名时使用安全化后的file_id。写入路径限制在
FILE_SAVE_ROOT下,并防护路径穿越、父目录符号链接和目标符号链接。下载限制 HTTPS(测试时可显式允许 loopback HTTP)、重定向次数、最大文件大小和超时。
DNS 解析结果会先检查私网/保留地址;实际网络连接使用已经校验的 IP,避免解析校验后再次 DNS 查询造成 rebinding 窗口。
OAuth client 和未过期 access token 原子持久化到本地状态文件,正常服务重启不会无故丢失授权。
覆盖写入使用临时文件 + rename,降低部分写入风险。
成功和失败保存操作会输出结构化本地审计日志,但不会记录临时
download_url。
环境要求
Node.js 20+(当前环境使用 Node 22)
npm
如果需要公网稳定接入:Cloudflare Named Tunnel 或其他固定 HTTPS 反向代理
这台 Mac 的非交互 shell 可能需要:
export PATH=/opt/homebrew/bin:$PATH安装与验证
npm install
npm test测试包含五层:
settings-smoke:验证本地设置持久化、0600权限、项目根目录复用以及 Quick/Stable 配置分离。security-smoke:验证私网/保留地址阻断、DNS 混合结果拒绝和一次解析后的固定地址。importer-smoke:验证真实本地 HTTP fixture 下载、SHA-256、自动文件名、覆盖写入、路径穿越和重复写入防护。protocol-smoke:验证save_file、import_file、get_project_context、受保护的show_config、openai/fileParams和 OAuth challenge。oauth-smoke:验证动态 client 注册、PKCE-S256、token exchange、token 持久化重载和授权 MCP 调用。
本地开发运行
npm run build
MCP_AUTH_PASSWORD='replace-with-a-long-local-password' \
MCP_ALLOW_INSECURE_HTTP=1 \
MCP_PUBLIC_BASE_URL='http://127.0.0.1:8765' \
FILE_SAVE_ROOT="$PWD/imports" \
npm start本地 MCP 地址为 http://127.0.0.1:8765/mcp。
ChatGPT 文件参数
工具描述包含:
_meta: {
"openai/fileParams": ["file"],
}ChatGPT 调用时会提供类似:
{
"file": {
"download_url": "https://...",
"file_id": "file_...",
"mime_type": "image/png",
"file_name": "hero.png"
},
"destination": "assets/hero.png",
"overwrite": false
}mime_type、file_name 和 destination 都可以缺省。destination 缺省时,save_file 会自动推导安全文件名。
运行配置
MCP_PUBLIC_BASE_URL:当前这次服务对外使用的 HTTPS base URL;Quick 模式自动生成,Stable 模式从本地设置读取。MCP_AUTH_PASSWORD:本地单用户 OAuth 授权密码,至少 12 字符。MCP_HOST:监听地址,Tunnel 场景建议127.0.0.1。MCP_PORT:监听端口,默认8765。MCP_QUICK_PORT/ 本地设置quickPort:Quick 模式端口,默认8765。MCP_STABLE_PORT/ 本地设置stablePort:Stable 模式端口,默认8878。FILE_SAVE_ROOT:允许写入的唯一文件系统根目录。这是服务部署时一次性设置,不是每次对话都要用户提供的参数。
ChatGPT 可通过零参数
get_project_context获取已配置路径。
MCP_STATE_FILE:OAuth 状态文件,默认.web-gpt-file-save/oauth-state.json。MCP_MAX_FILE_BYTES:最大下载大小,默认 25 MiB。MCP_DOWNLOAD_TIMEOUT_MS:单次下载超时,默认 30000 ms。MCP_ACCESS_TOKEN_TTL_SECONDS:access token 生命周期,默认 3600 秒。
公网使用:Quick 临时域名和 Stable 固定域名都支持
两种模式都会使用同一个本地项目根目录、同一套 save_file / get_project_context 工具和同一个本地设置文件。区别只在公网入口的生命周期。
模式 | 启动命令 | 公网地址 | 适合场景 | ChatGPT 连接行为 |
Quick 临时域名 |
| 随机 | Demo、临时测试、换机器快速验证 | URL 变化后需要更新/重连并重新授权 |
Stable 固定域名 |
| 自己的固定 HTTPS hostname | 日常长期使用 | hostname 不变时可持续复用连接;正常重启可恢复未过期 token |
0. 两种模式共用:第一次只配置一次本地设置
先安装依赖:
npm install然后初始化本地设置:
npm run configure这会创建:
.web-gpt-file-save/settings.json文件权限为 0600,并且整个 .web-gpt-file-save/ 已被 Git 忽略。第一次初始化会:
默认把当前项目目录保存为本地项目根目录;
自动生成并保存一个可重复使用的 OAuth 授权密码;
默认把 Named Tunnel 名称设为
web-gpt-file-save;OAuth 状态默认保存在
.web-gpt-file-save/oauth-state.json。Quick 默认使用本地端口
8765,Stable 默认使用8878,因此两种模式可以同时保留运行而不抢端口。
如果文件需要保存到另一个本地项目,只需要配置一次:
npm run configure -- --save-root /Users/you/Documents/my-project以后 ChatGPT 不需要再问这个绝对路径。需要查看路径时,模型应调用零参数:
get_project_context()需要查看 OAuth 授权密码时:
npm run auth:showA. Quick 模式:临时随机域名,一条命令启动
适合:快速验证、临时使用、Demo,以及不想先配置 DNS/域名的场景。
先确认本机有 cloudflared:
cloudflared --versionmacOS 如未安装,可使用 Homebrew 安装:
brew install cloudflared启动:
npm run quick这个命令会自动完成:
编译项目;
启动 Cloudflare Quick Tunnel;
自动读取随机
https://<random>.trycloudflare.com地址;把这个地址注入
MCP_PUBLIC_BASE_URL;使用已经保存的项目根目录和 OAuth 密码启动 MCP 服务;
在终端打印可以直接填写到 ChatGPT 的
/mcpURL。
终端会看到类似:
=== web-gpt-file-save: QUICK MODE ===
ChatGPT MCP URL: https://xxxx.trycloudflare.com/mcp
OAuth password: ...
Local project root: /Users/you/Documents/my-project然后在 ChatGPT 中:
新增或编辑开发者模式 MCP App;
MCP URL 填终端打印的
https://xxxx.trycloudflare.com/mcp;完成 OAuth 时输入终端打印的密码;
之后直接说“保存这个文件”“保存刚生成的图片”即可;不需要再次提供本地绝对路径。
停止时按 Ctrl+C,脚本会同时停止本地 MCP 服务和 Quick Tunnel。
Quick 模式的重要行为: 随机 URL 在下次启动时可能改变。OAuth token 绑定具体 resource URL,因此 URL 改变后,旧 ChatGPT 连接可能显示工具不可用;这时把 MCP App 更新到新的 /mcp URL 并重新授权即可。本地设置、保存根目录和文件不会因此丢失。
B. Stable 模式:固定域名,日常长期使用
适合:希望 ChatGPT MCP 地址长期不变化、机器重启后仍继续使用的场景。
固定模式第一次需要先准备一个 Cloudflare Named Tunnel 和自己的 hostname。示例使用:
https://files.example.com如果这台机器已经有用过的 Named Tunnel + 固定域名,可以直接复用,不需要重新创建 Tunnel。只要把已有 hostname 和 tunnel name 写入本项目配置即可;如果没有单独的 YAML 配置文件,npm run stable 会自动把该 Named Tunnel 转发到当前本地 MCP 端口。
第一步,登录并创建 Tunnel:
cloudflared tunnel login
cloudflared tunnel create web-gpt-file-save
cloudflared tunnel route dns web-gpt-file-save files.example.com第二步,复制示例配置:
cp deploy/cloudflared/config.example.yml ~/.cloudflared/web-gpt-file-save.yml编辑这个私有文件,把下面三项替换成真实值:
<TUNNEL-UUID>/Users/<username>/.cloudflared/<TUNNEL-UUID>.jsonfiles.example.com
第三步,把固定域名和 Tunnel 信息保存到本项目的本地设置里,只做一次:
npm run configure -- \
--stable-url https://files.example.com \
--tunnel-name web-gpt-file-save \
--cloudflared-config ~/.cloudflared/web-gpt-file-save.yml复用本机已有 Named Tunnel、且没有单独 YAML 时,可以更简单:
npm run configure -- \
--stable-url https://existing-host.example.com \
--tunnel-name existing-tunnel-name此时不需要 --cloudflared-config。
第四步,日常启动只需要:
npm run stable这个命令会自动:
编译项目;
运行 Stable 模式 preflight;
使用已保存的项目根目录和 OAuth 密码启动本地 MCP;
等待本地
/healthz正常;启动配置好的 Cloudflare Named Tunnel;
打印固定的 ChatGPT MCP URL。
在 ChatGPT 中固定配置:
https://files.example.com/mcp首次使用这个固定 hostname 时完成一次 OAuth 授权。之后只要 hostname 不变,普通服务重启会从 MCP_STATE_FILE 恢复已注册 client 和未过期 token,不需要因为本地进程重启而重新配置 URL。
可以单独检查 Stable 配置而不启动服务:
npm run preflight:stable固定域名服务启动后,还可以从公网完整验证 OAuth(动态注册、PKCE、授权、token、授权后的 MCP 调用):
P1_PUBLIC_BASE_URL='https://files.example.com' \
P1_AUTH_PASSWORD="$(npm run --silent auth:show)" \
npm run test:public:auth该命令不会打印 OAuth 密码。
旧命令 npm run preflight:production 和 npm run start:production 继续保留,方便使用自定义反向代理而不是由本项目启动 Named Tunnel。
Quick 与 Stable 如何共存和切换
两种模式都保留,互不删除配置。
默认共用
.web-gpt-file-save/settings.json、项目根目录、OAuth 授权密码和 OAuth 状态文件。可以在 ChatGPT 里分别保留两个 MCP App,例如“File Save Quick”和“File Save Stable”。
Quick 默认使用
8765,Stable 默认使用8878,因此两种模式可以同时运行;也可以通过--quick-port/--stable-port修改。从 Quick URL 切到 Stable hostname,或者反过来,属于不同 OAuth resource;需要针对那个 URL 单独授权一次。
Stable hostname 不变时,不会出现 Quick Tunnel 随机 URL 变化导致的“工具突然不可调用”。
常用操作
修改本地项目根目录,只需执行一次并重启当前模式:
npm run configure -- --save-root /Users/you/Documents/another-project修改固定域名:
npm run configure -- --stable-url https://new-files.example.com修改 Named Tunnel 名称:
npm run configure -- --tunnel-name another-tunnel修改 Quick / Stable 本地端口:
npm run configure -- --quick-port 8765 --stable-port 8878查看当前本地设置摘要:
npm run configure查看 OAuth 密码:
npm run auth:show本地健康检查:
# Quick
curl http://127.0.0.1:8765/healthz
# Stable
curl http://127.0.0.1:8878/healthz“工具突然不可调用”时优先检查
Quick 模式:看当前终端打印的
trycloudflare.com/mcp是否和 ChatGPT App 中保存的 URL 一致。Stable 模式:确认
npm run stable仍在运行,并检查 Named Tunnel 的 hostname / DNS 没有改变。确认本地健康检查
/healthz正常。如果公网 URL 改过,重新连接并授权,因为 OAuth token 会校验 resource URL。
本地项目路径不需要重新输入;授权后调用
get_project_context()即可读取当前配置。
更完整的部署说明也保留在 docs/DEPLOYMENT.md。
已验证状态
P0/P1 已验证:
MCP Streamable HTTP 服务和 OAuth 流程;
ChatGPT
openai/fileParams注入;ChatGPT host file 保存到本地;
用户上传附件保存;
ChatGPT 对话中生成图片保存;
文件大小、内容和 SHA-256 本地验证。
复用本机既有 Cloudflare Named Tunnel / 固定 hostname 的公网
/healthz、OAuth metadata、MCPlistTools、openai/fileParams和 OAuth challenge 验证。
详细历史测试记录见 docs/P1_INDEPENDENT_MCP_TEST.md。
Phase 2 当前状态:
save_file成为主工具,import_file保留兼容。destination可省略并自动推导。增加零参数
get_project_context,新对话无需重复询问本地绝对路径。下载大小和超时可配置。
下载后重新检查目标路径,覆盖写入使用临时文件 rename。
OAuth client/token 本地持久化。
结构化保存审计事件。
DNS 私网/保留地址检查和连接 IP 固定,收紧 DNS rebinding 窗口。
提供固定 HTTPS / Named Tunnel 的生产预检和配置模板。
Quick Tunnel 保留为一键临时模式,Stable Named Tunnel 保留为一键长期模式。
验证可直接复用本机已有 Named Tunnel + 固定 hostname,无需重新创建域名或 YAML 配置。
已绑定并验证实际固定 hostname / Named Tunnel;真实 ChatGPT 重连后使用
save_file保存 host file,并在 Mac 上独立校验字节数、内容和 SHA-256。按部署需要增加 MIME allowlist、速率限制和项目级写入策略。
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP connector that lets ChatGPT list, search, and run your Apple Shortcuts via a local Mac agent
Share one project context across ChatGPT, Claude, Telegram and any MCP client.
- mcpOAuthai.butlerbrain
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
MCP-native notes and memory for ChatGPT, Claude, and other AI tools.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables ChatGPT to inspect and edit local projects through a secure MCP interface, offering workspace management, file operations, git integration, and safe command execution.5MIT
- AlicenseAqualityBmaintenanceConnects ChatGPT to a local developer workspace through MCP, enabling bounded repository analysis, file and image inspection, direct edits, command verification, and Git-aware review.22MIT
- FlicenseNot gradedqualityBmaintenanceEnables ChatGPT web, desktop, and computer use to access and automate a Mac via 228 MCP tools, including local files, Git, processes, macOS native automation, browser control, and durable goal continuation.5 npm-
- AlicenseNot gradedqualityAmaintenanceEnables ChatGPT on Windows to securely access codebases, Git, terminals, language servers, debuggers, SQLite, local HTTP services, adaptive project memory, engineering skills, checkpoints, audit logs, and sandboxed command execution through MCP tools.MIT