SSH Tools

Execute commands, manage files, and automate deployments on remote servers directly from Claude Desktop or your agent. Six MCP tools with a built-in safety tier system, auto-backup, and one-step rollback.

Requirements: SSH access to your server, private key stored in cloak_passport under a named key (e.g. my-server). No password auth — key-based only.

On this page

How it works — the tier system

Every SSH command is automatically classified into one of three tiers before execution. Read-only commands run instantly. Write or destructive commands require explicit approval via cloak_ssh_approve — this is enforced at the tool level, not by convention.

Tier 1 — Read

Auto-executes. No approval needed. Examples: ls, cat, ps, df, grep, curl GET

↑ Tier 2 — Write

Requires approval. Auto-backs up before running. Examples: writing files, installing packages, editing configs, curl POST

↑ Tier 3 — Destructive

Requires approval + creates rollback snapshot. Examples: rm, crontab edits, service restarts, DROP TABLE

After an approved write or destructive operation, cloak_ssh_approve returns a rollback_key. Pass this to cloak_ssh_rollback within the session to undo the entire operation.

Setup — storing your SSH key

SSH keys must be stored in cloak_passport before use. The key name you choose becomes the keyName parameter in every SSH tool call.

MCP — Claude Desktop
// Store your private key once
cloak_passport({
  action: "set",
  key: "my-server",
  value: "-----BEGIN RSA PRIVATE KEY-----\n..."
});

// Then use keyName in all SSH calls
cloak_ssh_exec({
  host: "your.server.ip",
  username: "ubuntu",
  keyName: "my-server",   // <-- references passport
  command: "uptime"
});

Never use keyPath: the keyPath parameter is not supported. Always use keyName to reference a key stored in the vault. Raw file paths are rejected.

Tool reference

Execute commands

cloak_ssh_exec
Read → auto
Write → needs approval
Execute a single command on a remote server. Read operations run immediately and return output. Write or destructive operations are queued, previewed, and return an approval_token — pass this to cloak_ssh_approve to execute.
hostrequiredRemote hostname or IP address
usernamerequiredSSH username (e.g. ubuntu, root)
commandrequiredShell command to execute
keyNamerecommendedName of key stored in cloak_passport
portoptionalSSH port — default 22
timeoutoptionalCommand timeout in ms — default 30000
Examples
// Read — executes immediately
cloak_ssh_exec({ host: "1.2.3.4", username: "ubuntu", keyName: "prod", command: "df -h" });

// Write — returns approval_token, does NOT run yet
cloak_ssh_exec({ host: "1.2.3.4", username: "ubuntu", keyName: "prod",
  command: "echo 'hello' > /var/www/html/index.html" });
// → { tier: "write", approval_token: "abc123", preview: {...} }

// Then approve it:
cloak_ssh_approve({ approval_token: "abc123", confirm: true });
cloak_ssh_approve
MCP
Approve and execute a queued write or destructive SSH operation. Automatically creates a backup before running, verifies the result, runs health checks (nginx, pm2), and returns a rollback_key for one-step undo.
approval_tokenrequiredToken returned by cloak_ssh_exec or cloak_ssh_plan
confirmrequiredMust be true — explicit confirmation gate
Returns
{
  approved: true,
  tier: "write",
  rollback_key: "rollback_1713900000_abc",   // use with cloak_ssh_rollback
  results: [
    { cmd: "...", success: true, stdout: "...", exit_code: 0 }
  ],
  health_checks: { nginx: "ok", pm2: "3 processes online" }
}

Multi-step plans

cloak_ssh_plan
Write → needs approval
Queue multiple SSH commands as a single atomic transaction. All steps are classified, previewed, and executed in order after a single approval. If any step fails, the plan aborts. Ideal for deployments, multi-file edits, or sequences that must succeed together.
hostrequiredRemote hostname or IP
usernamerequiredSSH username
stepsrequiredArray of shell command strings, executed in order
keyNamerecommendedPassport key name
labeloptionalHuman-readable name for this plan (shown in preview)
portoptionalSSH port — default 22
Example — deploy new site version
cloak_ssh_plan({
  host: "1.2.3.4",
  username: "ubuntu",
  keyName: "prod",
  label: "Deploy v2.1.0",
  steps: [
    "cd /var/www/myapp && git pull origin main",
    "npm install --production",
    "pm2 reload myapp",
    "sudo nginx -t && sudo nginx -s reload"
  ]
});
// Returns approval_token — call cloak_ssh_approve to execute all 4 steps

Backups

cloak_ssh_backup
Read
Manually trigger a timestamped backup on the remote server. Auto-detects project directories if no paths are specified. Creates a .tar.gz archive with the current timestamp. Called automatically before every approved write operation — use this for manual snapshots before major changes.
hostrequiredRemote hostname or IP
usernamerequiredSSH username
keyNamerecommendedPassport key name
pathsoptionalArray of absolute paths to back up. Omit to auto-detect project directories.
Example
// Auto-detect and backup everything
cloak_ssh_backup({ host: "1.2.3.4", username: "ubuntu", keyName: "prod" });

// Backup specific paths
cloak_ssh_backup({
  host: "1.2.3.4",
  username: "ubuntu",
  keyName: "prod",
  paths: ["/var/www/myapp", "/etc/nginx"]
});

Rollback

cloak_ssh_rollback
Write
Roll back the last approved SSH operation to its pre-execution state. Uses the rollback_key returned by cloak_ssh_approve. Can also target a specific backup archive path as a fallback. Restores files from the auto-backup taken before the operation ran.
hostrequiredRemote hostname or IP
usernamerequiredSSH username
keyNamerecommendedPassport key name
rollback_keyrecommendedKey returned by cloak_ssh_approve — preferred method
backup_pathfallbackDirect path to a .tar.gz backup archive on the remote server
Example
// After an approved operation returns rollback_key:
const { rollback_key } = await cloak_ssh_approve({ approval_token: "abc", confirm: true });

// Something went wrong — undo it:
cloak_ssh_rollback({
  host: "1.2.3.4",
  username: "ubuntu",
  keyName: "prod",
  rollback_key  // restores from the auto-backup taken before the operation
});

Session handover

cloak_ssh_session_store
MCP
Store an end-of-session handover note to VEKTOR memory. Call once at the end of any session where you've made changes to a server — summarises what was done, what's pending, and any gotchas for the next session. Automatically surfaces via vektor_briefing at the start of the next session.
hostrequiredThe remote host operated on this session
summaryrequiredWhat was done, what is pending, any warnings for next session
tagsoptionalArray of tags for recall, e.g. ["deploy", "nginx", "prod"]
Example — end of session
cloak_ssh_session_store({
  host: "1.2.3.4",
  summary: `Deployed v2.1.0. Updated nginx config for new subdomain.
  PENDING: SSL cert renewal due in 14 days (run certbot renew).
  WARNING: pm2 process 'worker' has 200+ restarts — investigate memory leak.`,
  tags: ["deploy", "nginx", "ssl", "prod"]
});
// Next session: vektor_briefing() will surface this automatically

How-to guides

How to deploy a file change safely

The recommended pattern for any file edit: read first, edit with Python to avoid encoding issues, verify the change, then reload the service.

Safe file edit pattern
// 1. Read current file (auto-executes — read tier)
cloak_ssh_exec({ host, username, keyName,
  command: "cat /etc/nginx/sites-enabled/mysite" });

// 2. Edit via Python (handles line endings + encoding correctly)
// This is write tier — returns approval_token
cloak_ssh_exec({ host, username, keyName, command: `python3 -c "
content = open('/etc/nginx/sites-enabled/mysite').read()
content = content.replace('server_name old.com', 'server_name new.com')
open('/etc/nginx/sites-enabled/mysite', 'w').write(content)
print('Done')
"` });

// 3. Approve it
cloak_ssh_approve({ approval_token: "...", confirm: true });

// 4. Test + reload (two more write ops — plan them together)
cloak_ssh_plan({ host, username, keyName, label: "Test + reload nginx",
  steps: ["sudo nginx -t", "sudo nginx -s reload"] });

How to set up a new cron job

Add cron safely
// 1. Check existing crons (read)
cloak_ssh_exec({ host, username, keyName, command: "crontab -l" });

// 2. Backup + add new entry (plan = single approval gate)
cloak_ssh_plan({ host, username, keyName, label: "Add cron job",
  steps: [
    "crontab -l > /tmp/cron.bak",    // backup first
    "(crontab -l; echo '0 9 * * 1 cd /app && node post.js >> /app/cron.log 2>&1') | crontab -",
    "crontab -l"                      // verify
  ]
});

How to check server health

Health check — all read tier, all auto-execute
cloak_ssh_exec({ host, username, keyName,
  command: "echo '=DISK=' && df -h && echo '=MEM=' && free -h && echo '=PM2=' && pm2 list && echo '=NGINX=' && sudo nginx -t 2>&1 && echo '=UPTIME=' && uptime" });

How to run a deployment from scratch

Full deploy plan
cloak_ssh_plan({
  host, username, keyName,
  label: "Full deploy — v3.0.0",
  steps: [
    // Backup first
    "tar -czf /tmp/backup-$(date +%s).tar.gz /var/www/myapp",
    // Pull latest
    "cd /var/www/myapp && git pull origin main",
    // Install deps
    "cd /var/www/myapp && npm install --production",
    // Run migrations
    "cd /var/www/myapp && node migrate.js",
    // Reload app
    "pm2 reload myapp",
    // Test + reload nginx
    "sudo nginx -t && sudo nginx -s reload",
    // Verify
    "pm2 list && curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/health"
  ]
});

Common issues & fixes

Tool execution failed — no output, no error

Usually means the SSH connection itself failed before the command ran. Check: (1) Is keyName correct — does that key exist in cloak_passport? Verify with cloak_passport({ action: "get", key: "your-key-name" }). (2) Is port 22 open on the server? Try nc -zv your.host 22. (3) Is the username correct? Common mistake: using root when the server requires ubuntu.

403 / Permission denied on write operations

The command ran but the process doesn't have write permission on the target path. Solutions: (1) Prefix with sudo if the user has sudo rights. (2) Check ownership: ls -la /path/to/file. (3) For nginx/system files, use sudo tee instead of direct redirects: echo 'content' | sudo tee /etc/nginx/conf.d/mysite.conf.

SSH command timed out after 90s

The command is taking too long — usually a long-running process, npm install on slow connection, or a hung process. Solutions: (1) Increase timeout: timeout: 120000. (2) For very long ops, run via nohup ... & and check the log file separately. (3) For npm installs, use npm install --prefer-offline if packages are cached.

Backup failed before write operation

The auto-backup runs before every approved write. If it fails (usually disk space or permission issue), the write operation still proceeds but without a rollback snapshot. Check disk space: df -h. If /tmp is full, clear it: rm -rf /tmp/*.tar.gz. The backup timeout is 90s — very large directories may need paths specified in cloak_ssh_backup to target only what matters.

cloak_ssh_plan — one step failed, rest didn't run

By design — plans abort on first failure (on_fail: "abort"). Check the results array in the response to see which step failed and its stderr. Fix the failing command, then re-run the plan from that step. If you need steps to continue despite failures, split into separate cloak_ssh_exec calls.

cloak_ssh_session_store — Float32Array alignment error

Known issue: a corrupted embedding vector in the VEKTOR DB causes this after turbo_quant_compress has been run. Fix: SSH to your machine running VEKTOR and run node fix-db.js from the SDK directory. This is a local SDK issue, not a server issue — the session note is lost but the SSH tools continue working.

rollback_key is null — can't undo

The rollback key is only returned when the auto-backup succeeds before the operation. If backup failed (disk space, timeout), rollback_key will be null. In this case, check /tmp/ for any .tar.gz files from around the time of the operation and pass that path as backup_path to cloak_ssh_rollback instead.

nginx health check always shows "configuration file test failed"

This appears in health checks after every approved operation. It is a known VPS configuration issue where nginx test runs without root privileges and cannot read SSL cert keys. It does not affect nginx actually running. Verify nginx is serving correctly with: curl -s -o /dev/null -w "%{http_code}" https://yourdomain.com. If that returns 200, nginx is fine.

← Cloak overview Memory Intelligence →