An MCP token is your account password with an API attached. Hand it to an agent and you have a user that never gets tired, reads every web page you point it at, and does exactly what the last instruction in its context said. Most of the time that is what you want. This page is about the rest of the time.
Everything below was checked against the live server on the date at the top: the tool list comes from tools/list on https://mcp.eqvps.com/mcp, the limits from the API itself. If you are new to the server, start with connecting an MCP client and API tokens, then come back.
Threat model: what actually goes wrong
Three things, in the order we see them:
- The agent misunderstands. "Clean up the test box" becomes a reinstall of the wrong server. No malice, just a model filling a gap in the instruction.
- Prompt injection. The agent reads text you did not write (a README, a support reply, a scraped page) and that text tells it to do something. If the agent holds a full-rights token, the injected instruction does too.
- The token leaks. It ends up in a shell history, a public repo, a shared MCP config or a log line.
The MCP server checks that the token is valid and that the server belongs to that account (or is delegated to it). It does not know what you meant. Every guardrail below works on one question: how much damage is possible when the instruction is wrong?
Every MCP tool, by risk tier
A customer token sees 45 tools (MCP server 1.6.0). A reseller token (rk_…) sees a separate set of 30 reseller tools and none of these, so the endpoint has 75 in total. Your client receives only its own set from tools/list.
This page sorts the tools by risk. For each tool's parameters and example calls, see the parameter reference; every tool in one line, including the 30 reseller tools, is in the complete list.
We do not ship MCP tool annotations (readOnlyHint, destructiveHint) yet, so your client cannot sort these by itself. Use the tiers below to set approvals by hand.
Tier 0 — public, no token (5)
| Tool | What it does |
|---|---|
get_started | The whole flow in one response: which tools to call, in which order |
list_plans | Plans, prices, OS images |
sandbox_pricing | Sandbox tariffs |
register_account | Creates a new account and returns its token |
login | Email + password → token |
Tier 1 — account read, no side effects (15)
| Tool | What it does | Watch out |
|---|---|---|
whoami | Account id, name, email | |
get_balance | Prepaid balance | |
list_vps | Active, provisioning and suspended servers | |
get_vps_status | Status, specs, access details | With reveal: true it returns the root password |
get_vps_metrics | CPU, memory, network, disk over time | |
get_upgrade_options | Plans this server can switch to in place | |
list_delegations | Who you gave access to | |
list_delegated_to_me | Servers others delegated to you | |
list_tickets | Your support tickets | |
get_ticket | One ticket with its thread | Ticket text is untrusted input for the agent |
list_sandboxes | Your sandboxes | |
get_sandbox | One sandbox and its usage | |
get_task | Output of a background task | |
download_file | Reads a small file from a sandbox | |
get_download_url | Short-lived link to one sandbox file | Anyone with the link can download until it expires |
Tier 2 — changes state, spends nothing (17)
| Tool | What it does | Watch out |
|---|---|---|
power_vps | start / stop / reboot | A stop is a stop: services go down |
set_hostname | Renames the server | Changes the value confirm checks against |
undo_cancel | Removes a scheduled end-of-period cancellation | |
refresh_token | New token, old one revoked at once | Update any static config afterwards |
set_password | Sets the account password if none exists | Whoever holds the token can set it first |
topup_balance | Creates a top-up invoice + crypto checkout link | Paying it needs a wallet |
pay_invoice | Checkout link for an unpaid invoice | Same |
accept_delegation | Accepts an invitation | |
revoke_delegation | Ends a delegation | |
create_ticket / reply_ticket / close_ticket | Support tickets | The agent writes to support in your name |
run_code / exec_command | Runs code inside a sandbox | Sandbox only, not on your VPS |
kill_task | Stops a sandbox background task | |
upload_file / get_upload_url | Puts a file into a sandbox |
Tier 3 — spends money, destroys data or grants access (8)
| Tool | What it does | Server-side check |
|---|---|---|
order_vps | Orders a server, paid from balance | Balance short → unpaid invoice, nothing charged |
change_plan | In-place plan change, difference charged from balance | confirm: true; balance short → 402 |
create_sandbox | Starts a billed sandbox | Empty balance → 402 |
reinstall_vps | Wipes the disk and installs a new OS | confirm = exact hostname or DELETE; 4 calls/min |
reset_password | New root password, old one stops working | confirm = hostname or DELETE; 6 calls/min |
cancel_service | end_of_period (default, undoable) or immediate (destroys the server now) | immediate needs confirm = hostname |
kill_sandbox | Deletes a sandbox and its files | none |
delegate_service | Gives another person operator access to a server | Owner only; they must accept |
Tool-set changelog
| Date | Server version | Change | Risk impact |
|---|---|---|---|
| 2026-10-03 | 1.6.0 | refresh_token added; tokens live 1 year by default | Tier 2 |
| 2026-10-03 | 1.5.0 | undo_cancel, get_upgrade_options, change_plan | change_plan spends balance → tier 3 |
| 2026-10-03 | 1.1.0 | 13 sandbox tools | create_sandbox spends, kill_sandbox destroys → tier 3 |
The running version is public: curl -s https://mcp.eqvps.com/healthz. When it moves, this table moves with it.
The balance is the spending cap
EQVPS is prepaid. There is no card on file, no credit line and no overdraft, so the most an agent can ever spend is what sits on the balance. Three tools spend: order_vps, change_plan and create_sandbox. Renewals of your existing servers come out of the same balance.
The agent can create money requests, but not pay them. topup_balance and pay_invoice return a crypto checkout link, and a link does nothing without a wallet behind it. There is no withdrawal endpoint either: money on the balance can buy services in your account and cannot be sent out. Refunds from an immediate cancellation also go back to the balance.
One caveat, and it is a real one. If you keep the balance very low to cap the agent, your own renewals start failing and servers go into grace. Our rule of thumb: one renewal cycle of what you already run, plus the budget of the agent's current job. The agent budget guide walks through sizing it. And if you give the agent its own funded wallet, that wallet becomes a second ceiling you have to watch.
Least privilege: there is no read-only token (yet)
Straight answer: every customer token has the same rights as the account in the dashboard. Token names and lifetimes are configurable; scopes are not.
The narrowest thing available today is delegation. You give the agent its own account, with zero balance, and delegate one server to it:
delegate_service { "service_id": "EQ-XXXX", "email": "agent@yourdomain.com", "expires_days": 30 }
Same thing over REST:
curl -s -X POST "https://api.eqvps.com/api/v1/eqvps/services/EQ-XXXX/delegations" \
-H "Authorization: Bearer $EQVPS_TOKEN" -H "Content-Type: application/json" \
-d '{"email":"agent@yourdomain.com","expires_days":30}'
The invitation has to be accepted while signed in as that email (accept_delegation), and expires_days can be 1 to 365. Step by step with screenshots: delegate access and access in the docs.
| A delegated account can | A delegated account cannot |
|---|---|
| See status, metrics and history of that one server | See your other servers, balance or invoices |
| Start, stop, reboot | Cancel, renew or change the plan |
| Set the hostname and reverse DNS | Buy add-ons or IPs |
| Reset the root password | Open the web console |
| Reinstall the OS | Delegate the server to anyone else |
Note the last two rows on the left. A delegate cannot spend your money, but it can wipe that server. Turn on backups for any server an agent can reinstall.
Token hygiene
One token per agent, with a name. Create it in Dashboard → Settings → API tokens for agents, or:
curl -s -X POST "https://api.eqvps.com/api/v1/eqvps/auth/tokens" \
-H "Authorization: Bearer $EQVPS_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"backup-agent","expires_in_days":90}'
The token is shown once. Lifetime is 1 to 1825 days, 365 if you do not set it. For agents we would pick 90.
Keep it in a file only you can read, not in the repo, not in the prompt, not in a shell variable you paste around:
mkdir -p ~/.config/eqvps && chmod 700 ~/.config/eqvps
( umask 077; read -rsp 'EQVPS token: ' T; echo; printf 'EQVPS_TOKEN=%s\n' "$T" > ~/.config/eqvps/agent.env )
ls -l ~/.config/eqvps/agent.env # expect -rw-------
Then load it in the agent's service with EnvironmentFile= (systemd) or set -a; . ~/.config/eqvps/agent.env; set +a.
Rotate before expiry. The refresh_token tool, or POST /auth/tokens/{id}/refresh, issues a new token with the same name and revokes the old one immediately. If your MCP client has the token hard-coded in its config, update it right after, or the next session gets a 401.
Check who is using what: GET /auth/tokens lists every token with its name, expiry and last_used_at. A token you do not recognise, or one used after you switched the agent off, is your signal.
If a token leaks
In this order:
- Revoke it. Dashboard → Settings → API tokens for agents → Revoke, or
curl -s -X DELETE -H "Authorization: Bearer $EQVPS_TOKEN" https://api.eqvps.com/api/v1/eqvps/auth/tokens/<id>. It stops working on the next request. - Look for new tokens you did not create, and revoke them too.
- Check the damage surface: each server's Service history, your invoices and balance, and
list_delegationsfor access you did not grant. - Rotate root passwords on every server that token could see.
get_vps_statuswithreveal: truehands out the root password, so a leaked token is a leaked root password. Check~/.ssh/authorized_keyswhile you are there. - Close the password door. If your account never had a password, whoever held the token could have set one with
set_password. Sign in with an email code and change it.
Prevention for step 5 is cheap: set an account password yourself now, and set_password returns 409 for everyone after you.
Human in the loop
What the server enforces:
reinstall_vps,reset_passwordandcancel_servicewithtype: immediateneedconfirmequal to the exact hostname (DELETEalso works for reinstall and reset).change_planneedsconfirm: true.- Cancellation defaults to
end_of_period: the server keeps running to the end of the paid period, andundo_cancelreverses it. - Rate limits per account: reinstall 4/min, password reset 6/min, power 20/min, orders 20/min. Enough to stop a loop from doing it fifty times, not enough to stop one bad call.
Be clear about what confirm is. It stops an agent from acting on "clean it up". It does not stop an attacker, because the hostname is one get_vps_status call away. The real approval step lives in your MCP client. Most clients can ask before each tool call; let tiers 0 and 1 run freely and make tier 3 always ask. In clients with per-tool permissions, such as Claude Code's settings.json (server registered as eqvps):
{
"permissions": {
"ask": ["mcp__eqvps__order_vps", "mcp__eqvps__change_plan", "mcp__eqvps__create_sandbox", "mcp__eqvps__reset_password", "mcp__eqvps__delegate_service"],
"deny": ["mcp__eqvps__reinstall_vps", "mcp__eqvps__cancel_service", "mcp__eqvps__kill_sandbox"]
}
}
Add a line to the agent's instructions as well. It is not a security control on its own, but it cuts the misunderstanding cases:
Never call reinstall_vps, reset_password, cancel_service (type=immediate), change_plan,
order_vps, create_sandbox, kill_sandbox or delegate_service unless the human has typed
the target server's hostname in this conversation for that specific action.
If the agent signs in by email code instead of holding a long-lived token, see agent login over MCP.
Audit: what you can see afterwards
- Token list (
GET /auth/tokens, or Settings → API tokens for agents): name, created, expires,last_used_at. This is why naming tokens per agent matters. - Service history (dashboard, server page): power actions, reinstalls, password resets, plan changes, payments, each with a time and an actor: you, support or automatic. It does not tell you which token or delegate acted, only that it came from your side.
- Invoices and balance: every charge and refund.
list_delegations: who has access to what, and until when.
That gap in Service history is the honest limit of server-side audit today. If you need to know which agent did what, log every tool call with its arguments (minus secrets) on the agent's side.
The setup we would use
For an agent that manages one production server:
- A separate account for the agent, zero balance, the server delegated with
expires_days: 90. - Your owner token stays with you, not in any agent config.
- Backups on that server, because a delegate can reinstall.
- Tier 3 tools on "ask" or "deny" in the client.
- The agent's token in a
600file, refreshed before it expires.
For an agent that has to order servers or run sandboxes, delegation is not enough, since it needs a balance. There the balance is your cap: fund it per job, name the token, and read last_used_at once a week. If a read-only token would change how you deploy agents, tell us in support: that kind of feedback decides what we build next.
Comments
No comments yet. Be the first.