Every setup I found for letting an AI agent work on a server asked for one of two things. Either I paste a private key somewhere the agent can read it, or I install a daemon on the box and leave it running. I wasn't willing to do the first and didn't want to maintain the second, so for about a year I just didn't use agents for ops work. I'd have one open in a window, describing a problem to it, then type the commands myself.
What eventually bothered me about that: I already have an authenticated SSH session open. It's sitting in the file manager I use every day, connected, host key verified, ready. The agent doesn't need credentials. It needs that session, and it should have to ask me before it touches it.
That's the Agent Bridge in Faro, the SFTP/SSH client I maintain. I'd been using it for read-only things, mostly tailing logs and diffing config between staging and prod. Last week I pointed it at something with more consequences: two brand new DigitalOcean droplets, one prompt, install a full server control panel on both.
Two minutes, no narration. Faro and ServerKit are both MIT if you want to follow along.
What the agent could actually see
The Bridge is an HTTP endpoint that speaks MCP. It binds to 127.0.0.1 on a random port, requires a bearer token generated fresh each launch, and serves nothing to anything that isn't already on the machine. Connecting an agent is one command:
claude mcp add --transport http faro http://127.0.0.1:<port>/mcp \
--header "Authorization: Bearer <token>"
From there the agent gets 25 tools. faro_exec is the one people react to, but most of the useful work is faro_list_dir, faro_read_file, faro_search, faro_tail, faro_diff — inspection, not mutation. Being able to say "read the nginx config on both boxes and tell me what's different" turns out to be worth more day to day than remote execution.
Three things stand between a tool call and my server. Sessions are opted in one at a time, so a saved connection I haven't granted access to isn't in the list the agent receives; it can't act on a box it can't see. Anything with side effects raises a prompt in the Faro window showing the exact command, and the call blocks until I answer or it times out after two minutes. And every call, approved or denied, lands in a running activity log.
None of that involves the agent holding a secret. It talks to localhost. Faro holds the SSH session, and nothing gets installed on the remote side, which is the part I care about most across a fleet.
The prompt
This is the entire thing I typed:
Install ServerKit on serverkit-test-server-1 and serverkit-test-server-2
in parallel using faro-cli: curl -fsSL https://serverkit.ai/install.sh | bash
Return me the 2 admin URLs.
No IPs, no usernames, no key paths. Two names, the same ones I saved in Faro months ago.
That works because of faro-cli, a standalone binary that talks to the same Bridge the GUI is running. It reads the URL and token out of Faro's local discovery file, so a script never handles either one:
faro-cli agent sessions
# → serverkit-test-server-1 sftp 159.223.187.83
# → serverkit-test-server-2 sftp 157.230.230.92
faro-cli agent exec serverkit-test-server-1 'hostname'
Commands that arrive this way still hit the approval gate and still show up in the console. The CLI is a different door into the same room, not a way around the lock.
Why two servers
One server would have been an easier demo and a less honest one. Everything interesting about fleet work starts at two: the second box is where drift begins, where you paste the wrong IP, where you do six steps correctly and forget the seventh.
So I set them up deliberately differently. serverkit-test-server-1 uses an SSH key. serverkit-test-server-2 uses the root password DigitalOcean emails you. Both end up as ordinary entries in the same connection list, and by the time the agent sees them the difference has stopped mattering. It got two names and treated them identically.
It listed the fleet, fired at both profiles, and two install streams ran side by side. About a minute each. Then it handed back two URLs, I opened both, and there were two working panels on hardware that had been empty when I started recording.
What I don't like about it
Approval fatigue is the real problem, and I don't think I've solved it. Watching an installer means clicking approve over and over, and clicking approve over and over is training yourself to stop reading. There are relaxed policies — allow-all, auto-approve read-only operations, auto-approve commands matched as safe and read-only — stored per profile so they survive a restart. Each one is a security decision, and I'd rather people make it deliberately at the start than drift into it around the fortieth prompt.
The more uncomfortable limitation: approval covers the command, not what the command does. I approved curl … | bash. Whatever that script did afterward was between me and my trust in that URL. The Bridge removes credential exposure and the remote daemon. It does not remove judgment, and I'd be suspicious of anyone claiming otherwise about a tool in this category.
Beyond that: it's localhost-only by design, which suits an operator at a desk and does nothing for CI. The desktop builds are unsigned because I don't have an Apple or Windows certificate yet, so every OS objects the first time you launch. And both droplets in the video were throwaways, destroyed afterward.
Try it
Faro is a desktop client for SFTP, FTP, SSH, S3-compatible storage, WebDAV and a handful of clouds, written in Rust on Tauri 2: github.com/jhd3197/faro. ServerKit is the panel it installed, self-hosted, one command:
curl -fsSL https://serverkit.ai/install.sh | bash
Both MIT, both free, neither one phones home.
The open question I keep changing my mind about is where auto-approval should stop. Read-only inspection is clearly fine. apt install feels fine until the day it isn't. If you've given an agent this kind of access, I'd like to know where you drew the line, because I'm about to ship defaults and I'd rather not invent them alone.
Top comments (0)