My AI client can provision real servers now — over Krova Cloud's MCP server. The reason I sleep: scoped keys, a sandbox space, unreachable boxes, and a legible bill. Setup, guardrails, and the threat model inside.
I typed a sentence into my AI client: "stand up a 2-CPU box with Docker for the staging API, call it staging-api." It provisioned a real server, verified the boot, and reported back — SSH ready, no public ports exposed. Ten seconds of magic, then the feeling you're supposed to have: what did I just hand an LLM the ability to do?
The answer is the whole point of this post. Spoiler: it's not "trust the model." It's architecture.
The setup
Krova Cloud ships an MCP server, so Claude/Cursor/any MCP client can drive the API in plain English. Config is the standard shape:
{
"mcpServers": {
"krova": {
"command": "npx",
"args": ["-y", "@krovacloud/mcp"],
"env": {
"KROVA_API_KEY": "kro_sandbox_...",
"KROVA_SPACE_ID": "space_..."
}
}
}
}
Two gotchas the docs call out, both worth knowing before you debug ghosts:
- The space ID is the step everyone misses. The key authenticates you but doesn't say which space; without KROVA_SPACE_ID the server starts happily and then every call fails with "No spaceId provided." It's in your dashboard URL.
- Verify it's actually connected. Ask it to list your Cubes. Real Cubes with status and hourly cost = connected. A vague essay about what Krova is = the model answering from memory; check the MCP status panel, don't rephrase.
The guardrails (the reason I sleep)
- Sandbox space, its own key. Keys are scoped to a single space and carry your permissions there. The assistant lives in a space that holds nothing precious — per the docs' own advice, "use a separate space for anything experimental, so the key cannot reach production Cubes at all." Prod is managed by me, slowly, with my own hands.
- Approval prompts stay on. The tool surface includes delete_cube, restore_cube, delete_domain — an agent that can create can also remove. I read what a call will do before allowing it. The prompt is a feature, not friction.
- Machines with no address. Every Cube the assistant can create is a Firecracker microVM with no public IP by default — private NAT'd network, default-deny inbound. A rogue box is isolated and unreachable, not a fresh attack surface.
- An enumerable, cheap blast radius. One nightly audit answers "what is it running right now?":
krova context use sandbox # contexts = kubectl-style profiles per space
krova list --json \
| jq -r '.[] | select(.state=="running") | "\(.name)\t\(.createdAt)"'
# forgotten box? one word:
krova cubes delete staging-api-2
Billing is by the minute, so worst case is a forgotten box costing the price of a coffee — visible in one list, deleted in one word.
The wrong question
We keep asking "can we trust the model?" No. Not fully, not ever. Models misread; prompts inject; docs lie.
The right question: what's the worst thing this key can do? Mine can spin up isolated microVMs with no public address, in a sandbox space, billed by the minute, visible in one sentence. I haven't made the AI careful. I've made carelessness survivable.
The AI doesn't make the infrastructure safe. The infrastructure makes AI access safe.
The honest part
- Prompt injection is real. A malicious page my assistant reads could instruct it to provision nonsense or delete things in its space. The layers absorb it: scoped key, sandbox space, approvals, unreachable boxes. Four imperfect layers multiplying into something sleepable.
- The key is a credential. It acts as you in that space. Config file, never a repo; one key per machine; revoke the ones you're not using — deletion takes effect immediately.
- It won't do ops for you. The assistant provisions; backups, patching and restore drills are still mine. Isolation is the platform's job, operations remain the owner's.
The tool didn't change. The blast radius did.
The same assistant that's terrifying with AdministratorAccess and a production VPS is harmless with a scoped key and disposable, unreachable boxes. Give it a library card, not a master key.
Top comments (1)
The line I would underline is the one about making carelessness survivable rather than making the model careful. That is the same move as designing for recoverability instead of designing for correctness, and it holds up much better under load.
One place I would push: the approval prompt is carrying more weight in this design than the other three layers, and it is the only one that degrades with use. Scoped keys, private networking and per-minute billing behave the same on day 200 as on day one. The prompt depends on you reading it properly every time, and the failure mode is not that you stop caring. It is that after the fortieth create approval, the difference between a normal one and a strange one stops registering. I have watched review quality decay that way on ordinary pull requests, long before agents were in the picture.
What has worked better for me is making the boring approvals disappear so the unusual ones stand out. Auto-allow the calls that are provably reversible and cheap, and reserve the prompt for the ones that are not, like delete_domain. Have you thought about splitting the tool surface that way, or does the sandbox isolation make you comfortable letting the whole surface run unattended?