外部 Agent · MCPExternal Agents · MCP
macOS 2.0.0 起,Shellby 可以作为一个 MCP 服务运行,把你已配好的主机开放给桌面上的 AI 编程工具——claude-code、codex,以及任何支持 MCP 的客户端。它们不必再知道你的密码、私钥和跳板机怎么配,只需要说「在 prod-db 上跑这条命令」。当前开放的能力全部只读。
它解决什么问题
AI 编程工具在本地写代码,部署与排障却要上服务器。以前只有两条路:把 SSH 私钥交给它(从此它能对你的服务器做任何事),或者你自己开终端来回搬运输出。Shellby 提供第三条路:
| 直接让 agent 用 ssh | 经 Shellby MCP | |
|---|---|---|
| 凭证 | 得把密码 / 私钥交给它 | 凭证不出 Shellby,agent 只见主机名 |
| 危险命令 | 没有任何护栏 | 本地分类器判定,会改动系统的命令一律拒绝 |
| 跳板机 / 隧道 / Mosh 兼容 | 得自己拼参数 | 复用既有主机配置与已打开的会话 |
| 留痕 | 无 | 每次调用记入审计日志 |
前提
- macOS,Shellby 2.0.0 或更新版本。iPhone / iPad 上没有 MCP 服务——桌面上的编程工具才是消费方,且 iOS 的后台限制会让本地服务随时被挂起。
- Shellby 必须在运行。服务住在 App 进程里,退出 App 即停止。我们有意不做后台常驻:一个能触达你全部服务器的进程,不该无人看管地跑在后台。
- 一个支持 MCP(Streamable HTTP 传输)的客户端。已实测:claude-code、codex。
开启与接入
- 开启服务——设置 ▸ 外部 Agent,打开「开放给外部 Agent」。状态会变为「运行中 · 端口 xxxxx」。端口首次随机选定后固定下来,客户端配一次即可长期使用。
- 复制接入命令——同一页的「接入命令」区已按客户端给出完整命令行,点「复制」即可,无需手拼。
- 在终端里执行——粘贴运行。之后在 claude-code 里让它「看看 prod-web-01 上 nginx 最近的错误日志」,它会自己调用 Shellby 的工具。
两家客户端的鉴权形态不同,命令也不同:
# claude-code:令牌可直接写进 header
claude mcp add shellby --transport http http://127.0.0.1:<端口>/mcp \
--header "Authorization: Bearer <令牌>"
# codex:只认环境变量名,所以是两行
export SHELLBY_MCP_TOKEN=<令牌>
codex mcp add shellby --url http://127.0.0.1:<端口>/mcp \
--bearer-token-env-var SHELLBY_MCP_TOKEN
export 只对当前终端有效,要长期生效需写进 ~/.zshrc。注意这样令牌就落在了一个明文文件里——这是 codex 的形态决定的,请自行权衡。开放了哪些能力
| 工具 | 做什么 | 限制 |
|---|---|---|
list_hosts | 列出已配置的主机:id、名称、地址、端口、用户名、标签 | 不含任何凭证 |
run_command | 在指定主机上执行一条 shell 命令,返回退出码与输出 | 仅放行只读命令;超时默认 30 秒、最长 300 秒;输出上限 64 KB,超出截断并标注 |
read_file | 经 SFTP 读远程文件 | 只接受绝对路径;默认 64 KB、最多 256 KB |
get_metrics | 取一次资源快照:CPU、内存、磁盘、负载、占用最高的进程 | 仅 Linux 远端 |
工具的 host 参数填 list_hosts 返回的名称或 id 均可。执行时优先复用你已经打开的会话,其次才新建连接——所以你正在 Shellby 里连着的机器,agent 查起来几乎是零等待。
哪些会被拒绝
会改动系统状态的命令——安装、重启服务、写文件、删除、重定向到系统路径——一律拒绝,并把原因返回给 agent。判定由 Shellby 的本地命令分类器做出,与 App 内 AI Agent 用的是同一套;模型自己怎么描述这条命令不参与判定。你在 AI 设置里配置的黑名单同样对外部 agent 生效;白名单不生效——那是你为 App 内 AI 做的放宽,不会悄悄扩散到外部工具。
几条实际会碰到的规则:
- 用
&&串起多条不相关的命令,整条按其中最危险的一段判定,可能整体被拒——工具描述已提醒模型「写成可独立审阅的单条」。 - 把命令塞进
bash -c、管道到 shell、用重定向写文件——这些绕法都会被识别为非只读。 - 没有任何绕过分类器的「直通」工具。这是有意的:一旦存在,外部 agent 一定会优先用它,所有护栏当场失效。
安全边界
- 只监听本机(127.0.0.1),并拒绝来自网页的跨源请求,防 DNS rebinding。
- 每次请求校验访问令牌(Bearer token)。令牌存在系统钥匙串,不落明文文件;同机其它程序拿不到令牌就无法调用。
- 凭证不出 App。工具入参只接受主机名,密码、私钥、口令一律不出现在 MCP 报文里。
- 输出先脱敏。命令输出与文件内容返回前,按你的 AI 脱敏设置经本地脱敏(与 AI Agent 同一套规则)——因为外部 agent 会把它们发给自己的模型服务商。
- 令牌可随时重置——旧令牌立即作废,已配置的客户端需要用新命令重新添加。
审计日志
每次调用记一行:时间、来源客户端、工具名、目标主机、命令摘要、结果(退出码或失败原因)。设置 ▸ 外部 Agent 里可查看、复制与清空。不记录命令输出——里面可能含敏感数据,且体量不可控。日志只存在本机,不参与同步。
常见问题
agent 说「无法连接」?
先确认 Shellby 正在运行且开关是开着的;再对一下接入命令里的端口与设置页显示的是否一致(重置令牌后端口不变,但令牌要换)。
能让它重启服务、改配置吗?
目前不能——本版只开放只读能力。带审批卡的变更命令与文件写入(与 App 内 AI Agent 同样的 diff 预览)在计划中,会在后续版本里逐步开放。
多个客户端能同时接入吗?
可以,它们共用同一个端口与令牌。审计日志里的「来源」一列可区分是哪个客户端发起的调用。
需要 Pro 吗?
不需要。这个功能消耗的是你自己在 claude-code / codex 里的 AI 额度,Shellby 只提供通道。
From macOS 2.0.0, Shellby can run as an MCP server that exposes the hosts you have already configured to AI coding tools on your desktop — claude-code, codex, and any other MCP client. They no longer need your passwords, private keys or jump-host setup; they just say “run this on prod-db”. Everything exposed today is read-only.
The problem it solves
AI coding tools write code locally, but deploys and debugging happen on servers. Until now you had two options: hand the tool your SSH key (after which it can do anything to your servers), or open a terminal yourself and ferry output back and forth. Shellby adds a third:
| Letting the agent run ssh | Through Shellby MCP | |
|---|---|---|
| Credentials | You hand over passwords / keys | Never leave Shellby; the agent sees host names only |
| Dangerous commands | No guardrails at all | A local classifier decides; anything that changes the system is refused |
| Jump hosts / tunnels / Mosh-compatible | The agent must assemble the arguments | Reuses existing host config and open sessions |
| Traceability | None | Every call in an audit log |
Requirements
- macOS, Shellby 2.0.0 or later. There is no MCP server on iPhone / iPad — the consumers are desktop coding tools, and iOS background limits would suspend a local service at any moment.
- Shellby must be running. The server lives inside the app process and stops when the app quits. There is deliberately no background daemon: a process that can reach all of your servers should not sit unattended in the background.
- An MCP client that speaks Streamable HTTP. Tested with claude-code and codex.
Turn it on and connect
- Enable the server — Settings ▸ External Agents, switch on “Expose to external agents”. The status changes to “Running · port xxxxx”. The port is picked at random the first time and then kept, so clients are configured once.
- Copy the connection command — the “Connection commands” block on the same page has a complete command line per client; hit Copy.
- Run it in your terminal. Then ask claude-code to “check the recent nginx error log on prod-web-01” and it will call Shellby's tools by itself.
The two clients authenticate differently, so the commands differ:
# claude-code: the token can go straight into a header
claude mcp add shellby --transport http http://127.0.0.1:<port>/mcp \
--header "Authorization: Bearer <token>"
# codex: only accepts an environment variable name, hence two lines
export SHELLBY_MCP_TOKEN=<token>
codex mcp add shellby --url http://127.0.0.1:<port>/mcp \
--bearer-token-env-var SHELLBY_MCP_TOKEN
export line for codex only lasts for the current terminal; put it in ~/.zshrc to make it permanent. That does leave the token in a plaintext file — a consequence of how codex works, so weigh it yourself.What is exposed
| Tool | What it does | Limits |
|---|---|---|
list_hosts | Lists configured hosts: id, name, address, port, username, tags | No credentials whatsoever |
run_command | Runs one shell command on a host; returns exit code and output | Read-only commands only; timeout 30 s by default, 300 s max; output capped at 64 KB, truncated and flagged beyond that |
read_file | Reads a remote file over SFTP | Absolute paths only; 64 KB by default, 256 KB max |
get_metrics | One resource snapshot: CPU, memory, disks, load, top processes | Linux hosts only |
The host argument accepts either the name or the id returned by list_hosts. Calls reuse a session you already have open before opening a new connection — so a machine you are connected to in Shellby answers the agent almost instantly.
What gets refused
Anything that would change system state — installing, restarting services, writing files, deleting, redirecting into system paths — is refused, and the reason is returned to the agent. The decision is made by Shellby's local command classifier, the same one the built-in AI Agent uses; how the model describes the command plays no part. Your deny list from the AI settings applies to external agents too; your allow list does not — that is a relaxation you made for the in-app AI, and it is not quietly extended to outside tools.
Rules you will actually run into:
- Chaining unrelated commands with
&&makes the whole line inherit its most dangerous part, so it may be refused as a whole — the tool description already tells the model to “write commands as single, independently reviewable lines”. - Wrapping a command in
bash -c, piping into a shell, or writing files via redirection are all recognised as non-read-only. - There is no “raw ssh” tool that bypasses the classifier. Deliberately: if one existed, the agent would always prefer it and every guardrail would be moot.
Security boundary
- Loopback only (127.0.0.1); cross-origin requests from web pages are rejected to defeat DNS rebinding.
- A bearer token is checked on every request. The token lives in the system Keychain, never in a plaintext file; other programs on the same Mac cannot call the service without it.
- Credentials never leave the app. Tool arguments accept host names only; passwords, private keys and passphrases never appear in MCP messages.
- Output is redacted first. Command output and file contents pass through the same local redaction as the AI Agent (following your AI redaction setting) before they are returned — the external agent will forward them to its own model provider.
- The token can be reset at any time — the old one is invalidated immediately, and configured clients must be re-added with the new command.
Audit log
Every call is recorded as one line: time, client, tool, target host, command summary, result (exit code or failure reason). View, copy and clear it under Settings ▸ External Agents. Command output is not recorded — it may contain sensitive data and its size is unbounded. The log stays on this Mac and is not synced.
FAQ
The agent says it cannot connect?
Check that Shellby is running and the switch is on, then compare the port in your connection command with the one shown in Settings (resetting the token keeps the port but changes the token).
Can it restart services or edit config?
Not yet — this release exposes read-only capabilities only. Mutating commands behind an approval card, and file writes with the same diff preview the in-app AI Agent uses, are planned for later releases.
Can several clients connect at once?
Yes; they share the port and token. The “client” column in the audit log tells them apart.
Does it need Pro?
No. The feature spends your own AI quota in claude-code / codex; Shellby only provides the channel.