I let Claude Code deploy, restart, and roll back apps on my own production servers. Given how that sentence usually ends for people, I want to explain exactly what's actually happening under it, not just assert it's safe.
The part everyone gets right to be suspicious of
Giving a language model direct, unsupervised access to infrastructure is a bad idea in general. It can misread an instruction, hallucinate a target, or just be prompted into doing something destructive by content it reads along the way (a malicious README, a poisoned commit message). None of that is hypothetical. So the design question isn't "should an AI touch my servers" - it's "what has to be true before that's an acceptable risk."
Here's what's actually true of DeployOS's MCP server, because I built it and can point at the code:
It runs on my machine, not the server
There's no deployos-agent process on any of my VPS boxes, and there never was one. The MCP server is a small binary that ships next to the desktop app, runs locally over stdio, and talks to my servers the same way the GUI does: plain SSH, using the credentials already sitting in my OS keychain. If Claude Code wants to know what's running, it's asking a process on my laptop, which then SSHes out - the same trust boundary as me typing the command myself.
That matters because the alternative (a scoped user living permanently on the server, waiting for instructions from some cloud service) is a bigger attack surface by construction: it's always-on, it's reachable from outside my network, and compromising it compromises the server directly. Mine only exists while my laptop is open and Claude Code has asked it to do something.
Read access and write access are different toggles, in the literal sense
Fifteen tools are always available the moment MCP is turned on: list apps, list servers, pull logs, run the diagnostic, check metrics. None of them can change anything. Env var names are readable so an assistant can check whether DATABASE_URL is set; the value is never returned by any tool, full stop - I audited every read tool for this specifically before shipping, because "trust me" isn't a security control.
Every tool that can actually change something - deploy, restart, scale, roll back, touch a database, tear down - is a separate, individually-toggled, off-by-default setting. Turning on "restart" doesn't turn on "tear down." I didn't build a single "AI access: on/off" switch on purpose; a blanket toggle either has to be too permissive or too restrictive to be useful, and per-tool is the only version of this that's actually honest about the tradeoffs.
Destructive actions ask first - literally, not as a suggestion
Tearing down an app, scaling one to zero, restarting anything I've tagged critical, or removing a cron job doesn't happen the instant Claude Code calls the tool. It drops a request, and the desktop app - which runs as a real, visible window separate from the headless MCP process - shows me exactly what's about to happen in plain English before it runs. No response in two minutes and it's treated as "no." Nothing executes on a maybe.
I can turn this off per-tool if it gets in my way once I trust the workflow. It's on by default because the first time you find out an AI assistant did something destructive shouldn't be after the fact.
Every write is logged, locally, forever queryable
Every tool call that actually changes something gets a row in a local audit log: what tool, what it targeted, a short rendering of the arguments (never a secret value - set_env_var logs the key it changed, never what it set it to), whether it succeeded, how long it took. It's a table in a JSON file on my disk. It goes nowhere. I can filter it, search it, or export it to CSV if I ever need to answer "what did the AI actually do to my infrastructure this week" - and I've used it exactly that way, out of curiosity more than concern.
And there's a single kill switch
If I want AI access to stop touching anything right now, without hunting down which of the write toggles were on, there's one switch: Pause AI access. It denies every write tool instantly, read access keeps working. I built this because "turn off the twelve things I turned on" is a bad emergency procedure.
What I'm not claiming
This isn't a sandboxed execution environment. It's not a policy engine that understands the difference between a safe change and a risky one beyond the handful of actions that always ask first. If you give write access to something and don't read the confirmation prompt, that's on you. I built the parts that make "safe by default, and checkable after the fact" actually true - not the parts that would require this to be a much bigger, much later product before I'd ship anything at all.
I'd rather ship the honest, narrower version of this now than the broader version that doesn't exist yet.