Serverless Agent Forwarding for SSH
通过 SFTP 在 VS Code 中直接浏览和编辑远程文件,并通过 SSH 打开远程终端, 无需在服务器安装 VS Code Server。开启 Agent 转发后,VS Code Agent 与 桌面版 Agent(Codex、Claude Code 等)可通过 MCP 直接读写、搜索远程文件, 并通过 SSH 执行远程命令。适用于内网环境、禁止端口转发的远程服务器。
功能
- 使用
safs://虚拟工作区直接显示远程目录。 - 浏览、打开、保存、新建、重命名和删除远程文件及目录。
- 密码或私钥认证;配置密码可通过主口令加密。
- SFTP 连接池、断线重试、元数据缓存和远程文件轮询。
- 从当前远程文件或工作区打开相同目录下的 SSH 终端。
- 每个远程配置记住最后切换的目录,重新打开时恢复工作区和终端目录。
- 远程文件夹侧栏显示连接状态,可打开、断开或删除配置。
- GitHub Copilot Language Model Tools 和本机 MCP 服务可直接列出、读取、写入、 搜索远程文件,并通过 SSH 执行远程命令。
使用
安装
code --install-extension safs-serverless-agent-forwarding-1.1.1.vsix
添加 SSH 配置并打开远程文件夹
- 运行
SAFS: 添加 SSH 配置。 - 输入配置名称、
user@host,并选择密码或私钥认证。 - 运行
SAFS: 打开远程文件夹,选择刚添加的配置;也可以在左侧活动栏的 SAFS 视图(远程文件夹)中点击连接项上的“打开远程文件夹”按钮。 - 远程目录以
safs://虚拟工作区打开,直接在资源管理器中编辑远程文件。 - 使用
SAFS: 断开 SFTP 连接关闭连接(或点击连接项上的“断开连接”按钮)。
打开远程终端
远程终端通过 SSH 建立,不需要在服务器安装 VS Code Server。
- 在命令面板运行
SAFS: 打开远程终端。 - 或在 SAFS 视图的远程文件夹连接项上点击“打开远程终端”按钮。
- 终端会在当前远程目录打开:有打开的远程文件时使用其所在目录,否则使用
挂载根目录(或上次记住的目录)。终端名称形如
SSH: <配置名> — <相对路径>。 - 配置
remote_terminal: "open"时,打开远程文件夹后会自动连接终端。
打开远程目录
- 在命令面板运行
SAFS: 打开远程目录。 - 输入挂载根目录内的路径,或从补全列表选择候选目录后回车,会在新窗口中打开 该目录(只能打开挂载根目录内真实存在的目录);当前窗口保持不变,两个窗口 各自的 Agent 转发/MCP 独立绑定各自目录。
- 每个远程配置会记住最后切换的目录;重新打开远程文件夹时,工作区和终端 都会恢复到该目录。
启用 Agent 转发
Agent 可以是 VS Code 扩展(Copilot Chat、Codex 等),也可以是桌面 App
(Codex CLI、Claude Code 等),但必须和运行 SAFS 的 VS Code 处于同一个
操作系统平台:MCP 地址是仅回环可访问的 127.0.0.1,跨机器或跨系统无法
连接。
- 先在 SAFS 视图的远程文件夹连接项上点击“启用 Agent 转发”按钮(或右键菜单
中选择同一命令)。扩展会为检测到的 Agent CLI(默认
codex和claude, 可用safs.agentForwardingAgents扩展,如pi)安装或更新名为safs的固定 HTTP MCP。 - 验证注册:打开 Agent 并输入
/mcp(或打开其 MCP 管理界面),看到safs条目即表示 MCP 注册成功。Agent 若是 VS Code 扩展,直接在新窗口的 Agent 会话中确认即可。 - 再运行
SAFS: 打开远程文件夹进入远程目录(或点击连接项上的“打开远程 文件夹”按钮)。打开前扩展会先启动固定 HTTP 路由并注册 Agent;新窗口会 启动该窗口的动态端口服务,Agent 会话通过resolve_workspace_execution自动绑定当前远程窗口,之后工具调用无需指定mountName。 - 重启 Agent 并新建对话(首次安装、更新或移除 MCP 后都需要)。
- 之后 Agent 可直接使用远程工具:VS Code Agent 的
#safsList、#safsRead、#safsWrite、#safsSearch、#safsRun,或 MCP 工具resolve_workspace_execution、list_remote_folders、remote_list、remote_read、remote_write、remote_search、run_remote_command。 - 关闭转发:点击连接项上的“关闭 Agent 转发”。只有最后一个启用挂载也被
关闭后,扩展才会执行
mcp remove。
多个远程窗口
- 同时打开多个远程窗口时,所有窗口共用同一个固定 HTTP MCP 入口;窗口之间 通过固定端口选举一个 Router Leader,Leader 关闭后其他窗口自动接管。
- 省略
mountName的工具调用绑定到当前获得焦点且状态最新的窗口;显式传入mountName时选择对应的活动挂载。 - 每个窗口的动态端口服务只能访问自己绑定的挂载,不能通过请求参数跨窗口 访问其他挂载。
确认 Agent 会话绑定哪个远程
- 会话开始时先调用
resolve_workspace_execution:返回 JSON 中的mountName(以及name、remoteRoot、host、focused)就是当前 绑定。MCP 指令要求每个会话先调用它,并复用返回的mountName保持绑定 稳定。 - 也可调用
current_remote_workspace直接查看当前获得焦点的活动远程 文件夹,或用list_remote_folders查看所有已开启转发的活动挂载。 - 省略
mountName时,路由器按“获得焦点的窗口优先、其次最近更新”选择: 哪个远程窗口处于焦点就绑定哪个;都没有焦点时绑定最近交互的窗口。 - VS Code 侧可运行
SAFS: 显示状态在输出面板查看各挂载的连接状态。
配置
所有平台统一使用 ~/.safs/config.json。
{
"encrypt_passwords": true,
"hosts": [
{
"name": "dev",
"ip": "10.0.0.2",
"user": "alice",
"port": 22,
"private_key_path": "~/.ssh/id_ed25519"
}
],
"mounts": [
{
"name": "project",
"host": "dev",
"remote_path": "/srv/project",
"remote_terminal": "open"
}
]
}
顶层 mounts 数组定义 SFTP 远程文件夹;远程目录不会挂载到本地文件系统。
Agent 工具
VS Code Agent 可使用:
#safsList#safsRead#safsWrite#safsSearch#safsRun
扩展还在 127.0.0.1 上提供令牌保护的 Streamable HTTP MCP 服务,工具包括
resolve_workspace_execution、list_remote_folders、remote_list、remote_read、remote_write、
remote_search 和 run_remote_command。
Agent 在执行工作区操作前通过 resolve_workspace_execution 识别当前 SFTP 虚拟工作区。
开启转发后,文件工具可省略 mountName 并自动绑定当前工作区。所有远程文件访问
都通过 SFTP 工具完成,构建、测试、Git 和系统检查通过 SSH 远程命令完成;工具被
限制在已开启转发的 remote_path 内。Agent 路由和使用约束由固定 MCP 服务统一管理,扩展
不会在远端创建或读取 Agent 指引文件。
统一 Agent MCP(Codex / Claude Code)
每个开启 Agent 转发的远程 VS Code 窗口会启动独立的动态端口 MCP。扩展为 Codex 和
Claude Code 注册同一个由扩展进程托管的固定 Streamable HTTP MCP 路由器,并在每次工具
调用时找到目标窗口的最新动态端口。Agent 不再启动 STDIO 路由子进程,因此不会继承
safs 虚拟工作区 cwd。省略 mountName 时使用
当前获得焦点且状态最新的窗口;显式提供 mountName 时选择对应的活动挂载。窗口服务只能
访问其绑定挂载,不能通过请求参数跨窗口访问。
某些 Agent 扩展仍会把虚拟 URI 的 POSIX 路径当成本机 cwd 并在启动时调用
lstat 或创建 Git watcher。开启 Agent 转发时,扩展会在用户级扩展存储中创建空的
占位目录,并在第一个不存在的本机路径段建立 Windows Junction 或 Linux/macOS
目录符号链接。该目录不包含或同步远程文件,只用于让 Agent 完成本机启动。扩展不会
覆盖已存在的本机路径;如果父目录权限不允许创建链接,会在输出面板中报告。
窗口发现、目标选择、动态端口路由、断线判断、挂载校验和远程工具说明全部由扩展内置的
HTTP 路由器完成,不安装 Codex 插件、Skill 或 hooks。多个 VS Code 窗口通过固定端口选出
一个 Router Leader;Leader 关闭后,其他窗口会自动接管。MCP instructions
会要求 Agent 对 safs 工作区只使用远程
工具;由于 MCP 无法拦截客户端自身的本地工具,该约束依赖 Agent 遵循工具说明。
“启用 Agent 转发”会先为检测到的 Codex 和 Claude Code 安装或更新名为
safs 的固定 HTTP MCP;如果当前已打开该远程目录,还会立即启动该窗口的
动态端口 MCP 服务。关闭某个挂载的 Agent 转发会停止该窗口服务;只有最后一个已启用挂载
也被关闭后,扩展才会执行 mcp remove。首次安装、更新或移除 MCP 后请重启 Agent 并
新建对话。
扩展会生成鉴权令牌并自动执行等价于以下形式的配置:
codex mcp add safs --url 'http://127.0.0.1:9848/mcp?token=<generated-token>'
claude mcp add --transport http --scope user safs 'http://127.0.0.1:9848/mcp?token=<generated-token>'
如果未安装 Agent CLI,可在 VS Code 命令面板执行
SAFS: 复制桌面版 Agent MCP 地址,然后在桌面版
Settings > MCP servers 中添加名为 safs 的
Streamable HTTP 服务器并粘贴该地址。地址包含鉴权令牌,不要共享或
提交到仓库。
安装后重启 Agent 并新建对话。VS Code 扩展必须保持运行,并为相应挂载开启“Agent 转发”。断开 SFTP
不会关闭 Agent 转发偏好,重连相同挂载后 MCP 会发现新端口。如果同时打开多个远程窗口,
省略 mountName 的工具调用使用当前获得焦点且状态最新的窗口。设置
safs.agentMcpPort 应保持为默认值 0;固定入口端口由
safs.agentHttpRouterPort 控制,默认是 9848。如果该端口被其他程序占用,
扩展会拒绝连接并提示更换端口,不会误连到未知服务。
限制
- 本地命令行程序不能直接访问
safs://文件。 - 只支持
file://工作区的第三方 VS Code 扩展可能无法使用。 - SFTP 没有原生文件变更通知,扩展使用定时轮询检测外部修改。
- 目标服务器只提供旧式主机密钥(
ssh-rsa/ssh-dss,OpenSSH 8.8+ 默认禁用)时, 扩展会在所有连接路径(系统ssh、WSL bridge、内置 SFTP/终端)自动重新启用这些算法。 - 服务器只接受
keyboard-interactive认证(如 NSG/公司网关)时,SFTP 与终端路径 都会用配置的密码自动应答交互式提示。 - 内置终端被服务器拒绝 pty/shell(如 NSG 网关设备)时,会自动改用系统
ssh重连。 - 部分 NSG/网关按客户端标识白名单放行(MobaXterm 用 PuTTY 标识可以连,ssh2js 被拒)。
插件默认把 SFTP/内置终端的客户端标识伪装为
OpenSSH_9.6,可用设置safs.sshClientIdent改为PuTTY_Release_0.78等。 - 服务器没有 SFTP 子系统(如老版本 OpenSSH 未装 sftp-server 的 NSG 网关)时,
远程文件夹会自动降级到 SCP/exec 传输(与 MobaXterm 文件浏览器同机制),
文件树、读写、搜索与 Agent MCP 工具均可继续使用。列目录/路径解析优先使用
GNU 命令(
find -printf/readlink -f),BSD/macOS/Solaris 等非 GNU 服务器 会自动回退到ls/pwd解析。 - WSL 的
vpn: true配置复用wsl-vpn-ssh-bridge的 Windows TCP 中继; 使用该模式前需要安装 bridge。vpn: false时 SFTP 直接连接目标地址。
设置
safs.terminalFollowsActiveFile:开启远程终端时跟随当前打开的远程文件所在目录(默认false)safs.configPathsafs.reuseSshConnectionsafs.sftp.cacheTtlsafs.sftp.watchIntervalsafs.agentMcpPortsafs.agentHttpRouterPortsafs.agentForwardingAgents:选择启用 MCP 转发的 Agent,默认codex和claude。配置值直接使用 Agent 的 CLI 命令名(如codex、claude、pi),支持任意 CLI。扩展优先从PATH查找支持mcp指令的 CLI, 找不到时再从对应的 VS Code Agent 扩展安装路径查找内置 CLI;检测到 CLI 不支持mcp子命令时会跳过并提示。pi通过内置处理器注册:把 SAFS 地址写入 pi-mcp-extension 的配置文件(~/.pi/agent/mcp.json),无需pi mcp add。 使用pi需要先在 pi 中安装pi-mcp-extension(pi install npm:pi-mcp-extension), 并在启用转发后重启 pi 会话以加载工具。safs.highRiskCommandPatterns:Agent 通过 MCP 请求远程命令时的高危匹配规则(正则数组), 默认包含递归删除、磁盘/分区/文件系统操作、关机重启、管道执行远程脚本,以及sudo/su/doas/pkexec/runas、setuid/setgid、账号管理、visudo/sudoers等提权操作。命中即按safs.highRiskCommandAction处理;设为[]可关闭拦截。匹配会忽略引号内的内容,避免搜索 “sudo” 这类关键词时误伤。safs.highRiskCommandAction:deny(默认)直接拒绝高危命令并记录日志;confirm则每次 执行前弹窗让用户确认。