mcpField
R
relay-remotify-mcp

relay-remotify-mcp

本地服务
github.com/onlsol开发工具33 周前更新

关于 relay-remotify-mcp

本地 MCP 服务通过 remotify.run 中继,让兼容的宿主向远程计算机发送 Shell 命令。支持逐条审批或自动执行,并提供会话恢复工具。

主要功能

  1. 01运行远程 Shell 命令
  2. 02逐条审批或选择自动执行
  3. 03创建并查看远程会话
  4. 04恢复卡住的中继会话

适用场景

  1. 01从 MCP 宿主在远程计算机运行命令
  2. 02要求每条远程命令执行前审批
  3. 03中继会话卡住后恢复工作

MCP 相关

向 MCP 客户端提供 `remote_exec`、`remote_session_info` 和 `remote_session_reset` 工具。命令经 remotify.run 中继发送给远程监听器。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"onlsol-relay-remotify": {
"command": "npx",
"args": [
"-y",
"remotify-mcp"
],
"env": {
"REMOTIFY_URL": "<REMOTIFY_URL>",
"REMOTIFY_KEY": "<REMOTIFY_KEY>"
}
}
}
}
启动命令npx -y remotify-mcp
需要配置的环境变量
REMOTIFY_URLRelay to talk to. Override to point at a self-hosted instance.
REMOTIFY_KEY密钥Reuse an existing session key instead of creating a new one on startup.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmremotify-mcp0.6.2

工具

3

收录的工具列表 · 更新于 3 周前

参数类型必填说明
commandstring是要在远程机器上执行的 Shell 命令

详细介绍

remotify-mcp

MCP 服务为任何兼容 MCP 的宿主提供 remote_exec 工具,并由 remotify.run 中继服务提供支持。

在你的机器上运行;中继服务零成本。

安装

大多数用户无需安装——以下 MCP 宿主都会通过 npx 启动它:

npx -y remotify-mcp@latest

或者克隆此仓库,并在 mcp/ 中运行 npm install,以便自行修改。

接入 MCP 宿主

以下每个宿主都会启动相同的命令;区别仅在于配置文件。如果宿主未能发现该服务,请查阅其文档,了解它从何处读取 MCP 配置。

Claude Code
claude mcp add -s user remotify -- npx -y remotify-mcp@latest

-s user 会将其注册到所有工作目录,而不只是你运行命令时所在的目录。claude mcp list 会显示它;在会话中输入 /mcp 可以查看实时状态和公开的工具。

Codex CLI

~/.codex/config.toml:

[mcp_servers.remotify]
command = "npx"
args    = ["-y", "remotify-mcp@latest"]
OpenCode V2
opencode mcp add remotify --global -- npx -y remotify-mcp@latest

需要安装 Node.js 18+,并使用 npx。--global 会将服务注册到 ~/.config/opencode/opencode.jsonc 中的所有项目;省略此参数则只为当前项目注册。无需账户、API 密钥或全局安装 npm。

使用 opencode mcp list 或在 OpenCode 中输入 /mcps 检查连接。让 OpenCode 调用 remote_session_info 并显示两条连接命令,然后将选定的一条粘贴到远程端。监督模式会在每条命令执行前请求批准;自动模式则无需批准即可执行。

如需使用可自托管的中继服务,请在 mcp.servers 下的服务条目中添加 environment(OpenCode V2 使用 environment,而非 env):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "remotify": {
        "type": "local",
        "command": ["npx", "-y", "remotify-mcp@latest"],
        "environment": {
          "REMOTIFY_URL": "https://remotify.example.com"
        }
      }
    }
  }
}
Cursor

为所有项目配置 ~/.cursor/mcp.json,或为单个项目配置 .cursor/mcp.json:

{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }

之后重启 Cursor。

Windsurf

~/.codeium/windsurf/mcp_config.json,格式相同:

{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
Claude Desktop

macOS 上的 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 上的 %APPDATA%\Claude\claude_desktop_config.json:

{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }

之后重启应用。

Gemini CLI

~/.gemini/settings.json:

{ "mcpServers": { "remotify": { "command": "npx", "args": ["-y", "remotify-mcp@latest"] } } }
其他宿主

Continue、Cline、Roo Code、Zed、VS Code 内置的 MCP 功能及其他宿主,都支持在各自文档说明的文件中使用相同的 command 和 args 配对。将代码片段放进去即可完成配置。

指向可自托管的中继服务

默认情况下,此服务会连接公共中继服务 https://relay.remotify.run。如需使用自己的实例,请在宿主配置中添加一个环境变量(environment 字段可参考上面的 OpenCode V2 示例):

"env": { "REMOTIFY_URL": "https://remotify.example.com" }
宿主需要呈现的内容

连接命令以普通文本内容块的形式随工具结果返回,因为这是上述所有宿主都会原样传递给模型的唯一内容。本服务不依赖任何特定宿主机制:无论是 Claude Code 钩子、notifications/progress 或 notifications/message,还是 MCP 资源、引导式请求,均不依赖。下文介绍的钩子和桌面通知只是对支持它们的宿主提供的额外功能,绝不是唯一途径。

环境

变量默认值含义
REMOTIFY_URLhttps://relay.remotify.run要连接的 Relay。可覆盖此值以指向你的自托管实例。
REMOTIFY_KEY(未设置)启动时重用现有会话密钥,而不是创建新密钥。
REMOTIFY_CHUNK_MS5000每次调用的阻塞时长预算;超出后,工具会返回 [pending] 并要求助手继续循环。
REMOTIFY_MAX_CHUNKS24工具放弃前连续返回无进展的 [pending] 的上限。命令在远程端确实处于执行中的时间会返还,不计入此上限,因此不会把长时间运行的任务误判为监听器无响应。
REMOTIFY_POLL_MS500针对 Relay 的 /api/session/<key>/status 探测的内部轮询间隔。
REMOTIFY_RESULT_TIMEOUT_MS30000GET /result-{key} 长轮询的单次获取超时时间。
REMOTIFY_QUICK_TIMEOUT_MS10000快速状态、推送和会话 HTTP 调用的超时时间。
REMOTIFY_MAX_INFLIGHT_MS1800000命令处于“执行中”状态的绝对最长等待时间,用于防止监听器在命令执行过程中退出。超过此上限后,也会自动清除由先前已退出的会话遗留的过期执行中标记,以便运行新命令。
REMOTIFY_STALE_GRACE_S30过期执行中的快速处理宽限时间:如果监听器的心跳时间比执行中状态的开始时间晚超过此秒数,就能确定该执行中命令的执行器已退出,系统会立即清除卡住的状态,而不是等待 REMOTIFY_MAX_INFLIGHT_MS 耗尽。

暴露的工具

  • remote_exec(command) — 将 command 推送到 Relay,等待监听器 执行,然后以纯文本形式返回合并后的 stdout 和 stderr。
  • remote_session_info() — 首先提供两条可直接复制粘贴的单行命令 (受监管模式和自动模式),并用一句话说明各自的作用,然后提供会话 JSON:密钥、URL 和 TTL。此调用会按需创建会话,足以向用户提供连接 监听器所需的全部信息。
  • remote_session_reset({rotate?}) — 用于恢复的应急入口。默认情况下: 原地清除卡住的 Relay 状态(排队的命令/结果及执行中标记);密钥和已连接的 监听器仍可继续使用。{"rotate": true}:清除当前会话并生成全新的密钥 (用户必须重新粘贴新的单行命令)。通常无需使用——remote_exec 会自动 恢复(见下文)。

卡住会话的自动恢复

如果监听器在执行命令期间被强制终止,来不及通知中继(例如使用 kill -9、关闭终端或主机重启),会话过去就会卡住:每条新命令都会针对当前会话从未发出的命令返回 [busy],唯一的解决办法是手动发送一个虚拟结果并重新加载 MCP。现在,这种状态会自动清除:

  • **中继端:**任何监听器重新连接并轮询任务时,中继都会立即检测到孤立的执行中标记,清除该标记,并为正在等待的对象排队一个合成的 [remotify: ...] 结果。
  • **MCP 端:**新命令触发忙碌保护机制时,如果有确凿证据表明标记已过期(监听器心跳时间晚于接收任务的时间,且超过 REMOTIFY_STALE_GRACE_S),或标记时间超过 REMOTIFY_MAX_INFLIGHT_MS,MCP 就会自行重置会话状态(POST /api/session/{key}/reset;对于较旧的中继,则会回退到手动清除),然后继续执行新命令,并在响应前加上 [recovered]。

真正耗时较长的命令不会受到影响:监听器正在执行命令时,心跳时间不可能晚于接收任务的时间,因此在达到 REMOTIFY_MAX_INFLIGHT_MS 之前不会清除状态。

有一种卡住情况无法自动清除:监听器在命令执行期间死亡(心跳冻结在接收任务时,无法与真正的长时间运行区分开),且未超过执行中时限。此时需要用户重新连接运行器才能恢复,因此 [busy] 响应中会包含可粘贴的一行命令,并告知助手转发这些命令——重新连接会触发上述中继端的自动修复。

由中继提供的消息措辞

remote_exec 返回给助手的每条运行时字符串([pending]、[busy]、[recovered]、可粘贴的一行命令等)都由模板表生成。中继可以在会话负载中(mcp_messages.templates,维护于中继代码库的 php/app/mcp-messages.json)为任意部分键提供替换模板,因此措辞改进只需部署中继即可发布,并会在下次会话时传递给每个客户端——包括缓存已过期的安装——无需发布 npm 版本。对于较旧的中继和离线故障情形,软件包仍内置了完整模板表作为回退。

不会由中继提供的内容:工具名称、架构和描述。主机和用户会根据这些内容授予权限;它们只会通过带版本号的 npm 发布进行更改。

remote_exec 如何处理监听器缺失的情况

MCP 服务没有渠道在工具调用期间向用户显示文本(Claude Code、Cursor 等不会在工具调用期间渲染来自 MCP 服务的 notifications/progress 或 notifications/message)。虽然可以使用引导对话框,但当前客户端无法在服务端将其关闭,导致过期提示词留在聊天中。

当前设计还受到第二个限制:助手在工具调用之间写入的文本也不一定会可靠显示。Claude Code 会将其折叠成一行“已总结”的占位文本,其他主机则会截断或隐藏这类文本。因此,助手即使“转发这些一行命令,然后继续轮询”,操作人员也看不到任何可粘贴的内容。主机唯一会完整显示的文本,是助手本轮发言的最终消息。

因此,remote_exec 会区分两种 [pending] 情况:

  1. 如果这是首次调用,则创建会话;随后将命令推送到中继队列中,无论接下来发生什么。
  2. 会话中的第一条命令,且监听器从未轮询过:工具会立即作答,完全不等待。在用户粘贴一行运行命令之前,没有任何东西能取走命令,而且用户还没看到运行命令,因此等待只会白白耗费时间。响应会包含一个 [pending],其中带有两条粘贴用单行命令(受监督模式和自动模式),并告知助手停止、结束本轮,并在最终消息中用围栏代码块原样给出这两行。命令会继续留在队列中。用户粘贴一条单行命令后,监听器会取走并运行它;用户下一次发消息时,助手会使用相同参数再次调用 remote_exec 并获取输出。服务端会在不同轮次间保留状态,因此命令不会重新入队,也不会执行两次。
  3. 否则,工具会轮询约 5 秒(REMOTIFY_CHUNK_MS)。如果监听器在这段时间内取走命令,工具会等待结果并返回。大多数调用都会在此处完成。
  4. 后续调用时仍没有监听器:返回同样包含两条命令的 [pending]。每次没有监听器的 [pending]、死掉的监听器导致的 [busy] 卡住状态、会话续期以及放弃时的错误中都会重复提供这两条命令,这样,即使助手曾经无视过停止要求,下次响应中仍会再次看到它们。
  5. 监听器在线(有新鲜心跳),但尚未确认取走命令:工具会返回一个不含单行命令的 [pending],并要求用相同参数静默重试,只有在连续约 10 次响应后才会放弃。一旦中继确认命令正在执行(cmd_in_flight),响应就会切换为 [in-flight],且完全没有重试次数上限。
  6. 中继无法连接,而不是缺少监听器:如果一次状态探测都未能成功,响应会明确说明这一点,而不是让用户去粘贴一条与故障无关的命令。完全无法连接的中继(DNS、连接被拒绝、超时),以及返回 426 的已退役端点,都会各自显示一条消息,说明相应 URL 和需要更改的内容。

每个 [pending] 都会重申这条硬性规则:绝不能退而使用 ssh、scp 或任何其他传输方式,也绝不能尝试自行启动监听器。运维人员选择 remotify,正是因为不希望任何 Agent 获得 shell 访问权限;助手若绕过缺失的监听器,就违背了产品的设计初衷。

REMOTIFY_MAX_CHUNKS(默认值为 24)是服务端对无进展等待次数设定的内部上限。命令在远程端确实处于执行中的时间会返还,不计入上限,因此长时间运行的任务(mongodump、restic、缓慢的部署)绝不会被误判为监听器已失效。只有在持续无进展的重试耗尽取件预算,或会话因自身空闲 TTL 到期时(以先发生者为准),排队中的命令才会自动从中继中移除。

用户看到的实际效果是:“正在调用 remotify……”持续几秒,然后显示命令输出(如果监听器已经启动),或由助手显示一条简短的最终消息,其中包含要粘贴到远程端的两条单行命令。没有对话框,也没有遗留的 UI 提示;监听器一连接,排队中的命令就会运行,用户下一次发消息时即可获取输出。

不依赖模型的操作员可见性

上面的每条指令都位于工具结果中,模型可以忽略它:转述工具调用之间的内容(由宿主折叠)、只转述其中一条,或者完全不转述,并继续轮询一个没人知道如何启动的监听器。有两种机制可以确保操作员看到这些内容,不受模型行为影响。

桌面通知和剪贴板。MCP 服务运行在操作员自己的机器上。创建会话时,以及每次响应只能通过操作员粘贴一行内容来结束时(无监听器 [pending]、监听器已失效 [busy]、无监听器时放弃),都会弹出桌面通知,显示两条单行命令,并将受监督模式的命令复制到剪贴板;每个会话每分钟最多触发一次。Linux 使用 notify-send(或 kdialog)和 wl-copy / xclip / xsel;macOS 使用 osascript 和 pbcopy;Windows 使用 msg 和 clip。所有操作都尽力而为,缺少工具时静默处理,因此无头机器不会受到影响。

变量默认值作用
REMOTIFY_NOTIFY1设为 0 可禁用桌面通知
REMOTIFY_CLIPBOARD1设为 0 可禁用剪贴板复制
REMOTIFY_NOTIFY_THROTTLE_MS60000同一会话两次通知之间的最短间隔

Claude Code 钩子。remotify-mcp --claude-hook 从 stdin 读取 PostToolUse 钩子载荷;如果工具结果中包含连接用的单行命令,就会返回 systemMessage,由 Claude Code 在终端中直接打印,因此即使模型什么也没说,操作员也能看到这些命令。将以下内容添加到 .claude/settings.json(项目级)或 ~/.claude/settings.json(用户级):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "mcp__remotify__.*",
        "hooks": [
          { "type": "command", "command": "npx -y remotify-mcp@latest --claude-hook" }
        ]
      }
    ]
  }
}

典型的首次运行流程

  1. MCP 宿主启动此服务。此时不会发生任何事情——启动时不会创建会话。首次调用 remote_exec 或 remote_session_info 时会延迟创建会话,并将会话信息打印到 stderr:
    remotify: new session a1b2...
      on remote (supervised): curl -fsSL 'https://relay.remotify.run/r/a1b2...' | bash
      on remote (auto):       curl -fsSL 'https://relay.remotify.run/r/a1b2...?mode=auto' | bash
    
  2. 首次调用 remote_exec 会触发会话创建。此时还没有监听器:工具会立即返回 [pending],不会等待;助手会在本轮结束时,将两条粘贴用的单行命令(受监督模式和自动模式)作为最终消息发出。
  3. 你在远程端粘贴其中一条(受监督模式会针对每条命令提示 y/N;自动模式会立即运行每条命令)。监听器连接后,会运行排队的命令。
  4. 你回复(任何内容,例如“已连接”)。助手会使用相同参数再次调用 remote_exec,并返回输出。从此以后,监听器运行时,调用会在约 0.5-2 秒内完成。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。