{
  "markdown": "# Servonaut\n\n<!-- mcp-name: dev.servonaut/servonaut -->\n\n**Your servers. Your terminal. Your AI agent. One TUI.**\n\nManage AWS, Hetzner, OVH, and custom servers from one terminal — with a built-in AI assistant and MCP server.\n\n![Servonaut demo](docs/screenshots/demo.gif)\n\n## Quick Install\n\n**Linux / macOS:**\n\n```bash\ncurl -sSL https://raw.githubusercontent.com/zb-ss/servonaut/master/install.sh | bash\n```\n\n**Windows (PowerShell):**\n\n```powershell\nirm https://raw.githubusercontent.com/zb-ss/servonaut/master/install.ps1 | iex\n```\n\n**Or install directly via pipx / pip:**\n\n```bash\npipx install servonaut\n```\n\n**Manual install from source:**\n\n```bash\ngit clone https://github.com/zb-ss/servonaut.git\ncd servonaut\npipx install .\n```\n\n### Set up with an AI agent\n\nPrefer to let an AI agent do the whole thing? Paste this prompt into Claude Code, Cursor, or any coding assistant — it installs Servonaut, generates the config, and walks you through AWS / SSH / bastion / custom-server / AI-provider setup plus the MCP server.\n\n<details>\n<summary><b>Copy-paste setup prompt</b></summary>\n\n```\nInstall and configure Servonaut, a TUI for managing servers (AWS EC2, OVHcloud, Hetzner Cloud, and custom SSH servers).\n\n1. Install with all optional features: `pipx install 'servonaut[all]'`\n   (bundles the MCP server + OVH/Hetzner SDKs + keyring; AI log analysis needs no extra. Use plain `pipx install servonaut` for a minimal install.)\n2. Run `servonaut` once to generate ~/.servonaut/config.json\n3. (Optional) If I have a Servonaut account, run `servonaut login` to unlock the hosted features: Servonaut AI (chat with my fleet, no local API key), config sync across machines, Memory Sync, and proactive monitoring (Findings). Servonaut works fully offline against my own credentials if I skip this.\n4. Read ~/.servonaut/config.json and help me configure:\n   - AWS regions to scan (default scans all, set `regions` array to limit)\n   - Default SSH username (`default_username`, default \"ec2-user\")\n   - Cache TTL (`cache_ttl_seconds`, default 3600)\n   - Terminal emulator if not auto-detected (`terminal_emulator`)\n5. If I use bastion/jump hosts, help me set up `connection_profiles` and `connection_rules`\n6. If I have non-AWS servers, help me add them to `custom_servers`\n7. If I use OVHcloud or Hetzner Cloud, help me add the API credentials so those instances merge into the fleet\n8. For AI log analysis or chat with my own model (instead of Servonaut AI), help me configure `ai_provider` (openai/anthropic/gemini/ollama)\n   - Each provider has its own key field (`openai_api_key`, `anthropic_api_key`, `gemini_api_key`, `ollama_api_key`); local Ollama needs none\n   - Key fields support `$ENV_VAR` and `file:~/.secrets/key` syntax so secrets stay out of the config file\n9. Install the MCP server into my coding agent: `servonaut --mcp-install claude` (or `cursor`, `windsurf`, `opencode`, `vscode`, `codex`, `agy`, `gemini`, `all`)\n10. (Optional) To let AI agents/teammates reach this machine over the relay — and to run proactive Findings scans — start it with `servonaut connect`\n\nAfter setup, launch with `servonaut` and walk me through the key features, including the Findings inbox if I enabled the hosted features.\n```\n\n</details>\n\n## Screenshots\n\n<details>\n<summary><b>📸 More screenshots</b> — CloudWatch Top IPs, IP banning, AI chat, sidebar, instance list</summary>\n\n![Instance List](docs/screenshots/instances.png)\n*Instance list — AWS, Hetzner, OVH, and custom servers merged into one view*\n\n![Sidebar with full feature set](docs/screenshots/instances-sidebar.png)\n*Sidebar reveals Fleet Memory, Memory Sync, Secrets, Settings, and per-provider management for OVH and Hetzner*\n\n![AI Chat Assistant](docs/screenshots/instances-chat.png)\n*Built-in AI assistant with MCP server integration — chat with local providers or hosted Servonaut AI*\n\n![CloudWatch Logs Browser](docs/screenshots/cloudwatch.png)\n*CloudWatch log browsing with Top IPs analysis, geolocation, and abuse scoring*\n\n![IP Ban Manager](docs/screenshots/ip-ban-manager.png)\n*Ban/unban IPs via WAF, Security Groups, or NACLs with audit trail*\n\nAll screenshots and the launch video were recorded with `--demo` active, which replaces real IPs, ARNs, paths, and secrets with safe fake equivalents. See [docs/demo-mode.md](docs/demo-mode.md) for what is redacted and how to use it.\n\n</details>\n\n## Features\n\n*Badges: **Solo+** = included with paid Solo/Teams plans.*\n\n### Core & connectivity\n\n- **Interactive TUI** — mouse + keyboard, powered by [Textual](https://textual.textualize.io/).\n- **Multi-provider fleet** — AWS EC2, OVHcloud (dedicated / VPS / Public Cloud), Hetzner Cloud, and custom servers from any provider (DigitalOcean, on-prem, …) — listed and searchable in one view across all regions.\n- **Per-instance dashboard** — click a server for a Server Actions view: a **memory snapshot** (OS, disk, web stack, databases, runtimes, containers) plus an opt-in **live resource monitor** (`L` — CPU / RAM / load / disk / uptime, polled only while open).\n- **SSH & SCP** — one-key SSH in a new terminal window (auto-detected emulator); upload/download files and directories.\n- **Run remote commands** — overlay panel with real-time streaming output, history, and saved favorites.\n- **Remote file browser** — interactive file-tree navigation, inline in the dashboard or full-screen.\n- **Real-time log viewer** — stream logs via `tail -f` with pause, search, and log switching.\n- **Robust SSH** — bastion / jump-server (ProxyJump / ProxyCommand), keepalives on by default (tunable), per-host `extra_ssh_options` for legacy boxes, and key auto-discovery.\n\n### Cloud provider management\n\n- **OVHcloud** — `OVH → ⚙ Manage`: create / start / stop / reboot / delete (Cloud / VPS / dedicated), a region-first create wizard with API-backed pricing, plus DNS, IP blocks & failover IPs, snapshots, block storage, and billing.\n- **Hetzner Cloud** — `Hetzner → ⚙ Manage`: full lifecycle + project SSH-key registry, with an equivalent CLI (`servonaut hetzner …`). Auto-registers new servers. → [docs](docs/hetzner.md)\n\n### Observability & security\n\n- **Proactive monitoring — Findings** *(Solo+)* — cloud-side detectors surface fleet issues (disk, failed services, slow queries, credential-scanning cross-referenced with fail2ban, container health, TLS expiry, pending updates) as triageable cards, with **gated one-click remediation** (server-signed preview → human confirm → verb-allowlisted executor; block IP or renew a cert). → [guide](docs/proactive-monitoring.md)\n- **CloudWatch Logs browser** — log groups with Top-IPs analysis, IP geolocation, and AbuseIPDB lookups.\n- **CloudTrail browser** — AWS CloudTrail events with region / time / event / user filters.\n- **IP ban manager** — ban IPs via AWS WAF, Security Groups, or NACLs, with an audit trail.\n- **Keyword server scanning** — search file contents across instances.\n\n### AI\n\n- **Servonaut AI** *(Solo+)* — hosted AI gateway; chat with your fleet with no local API key. The model can tail logs, run commands (with confirmation), and triage incidents over the relay — credentials and SSH keys never leave the CLI. Quota inline / `servonaut ai quota`.\n- **Bring your own key** — OpenAI / Anthropic / Gemini / Ollama keys configured per-provider in Settings → AI Provider (local Ollama needs none). All coexist with Servonaut AI, switchable per-session.\n- **Built-in AI chat** — LLM assistant with tool-calling against your instances (the same MCP tool surface below).\n- **AI log analysis** — analyze logs with OpenAI, Anthropic, Gemini, or Ollama, with cost estimation.\n- **Voice** — dictate into the chat panel with `ctrl+t`, have replies read aloud, or go fully hands-free with conversation mode (`ctrl+n`): the mic stays open between turns and replies are spoken — with optional barge-in (headphones mode) to interrupt a reply by talking over it. Transcription and speech synthesis run entirely on your machine, so audio never leaves the workstation. Opt-in — nothing is downloaded until you enable it in Settings. → [docs](docs/voice.md)\n\n### Memory & secrets\n\n- **Server memory** — persistent per-server cache of OS / runtime / service / web-stack / log / database / container / git / disk facts; optional background fleet auto-scan. → [docs](docs/memory.md)\n- **Memory Sync** *(Solo+)* — end-to-end-encrypted backup of fleet memory to servonaut.dev (X25519 + AES-256-GCM, your passphrase), with drift detection, cross-device history, and optional auto-sync. `☁ Memory Sync` in the sidebar.\n- **Database credential vault** *(Solo+)* — scan a server for the DB credentials its apps already use, store the password in your secret vault under a per-site label, and let the `db_*` tools resolve it by name — no password in config or agent context. → [docs](docs/db-credential-vault.md)\n\n### Agents & automation (MCP)\n\n- **MCP server** — ~80 tools for Claude Code, Cursor, Windsurf, etc.: instance ops, AWS / Hetzner / OVH lifecycle, S3, log analysis & IP banning, Docker inspection, system-health probes, SSH-key CRUD, memory queries, and an authenticated REST proxy — behind a three-tier guard (`readonly` / `standard` / `dangerous`) with a JSONL audit trail. → [details below](#mcp-server-for-ai-agents)\n- **MCP relay** — `servonaut connect` (or TUI autostart) holds a Mercure SSE connection open so agents and team-mates can dispatch tool calls to this machine. Tokens never leave the CLI.\n- **Servonaut Cloud account** — optional `servonaut login` unlocks config sync across machines and the MCP relay.\n- **Config sync** — client-side-encrypted snapshots of your `config.json` synced via servonaut.dev, paired with a passphrase you control.\n\n### Convenience\n\n- **Instance caching** — stale-while-revalidate for fast startup.\n- **Auto-update** — startup check + one-click update (`servonaut --update`).\n- **Desktop shortcut** — `servonaut --install-desktop` (Linux/macOS).\n- **Fully configurable** — everything in `~/.servonaut/config.json`.\n\n## Prerequisites\n\n- Python 3.10+\n- AWS CLI configured (`~/.aws/credentials` and `~/.aws/config`)\n- SSH client (standard on Linux/macOS, OpenSSH on Windows)\n- `pipx` for isolated installation (recommended)\n\nYour AWS credentials need `ec2:DescribeInstances` and `ec2:DescribeRegions` permissions. Additional permissions needed for optional features:\n\n| Feature | Required Permissions |\n|---------|---------------------|\n| CloudTrail browser | `cloudtrail:LookupEvents` |\n| IP ban (WAF) | `wafv2:GetIPSet`, `wafv2:UpdateIPSet` |\n| IP ban (Security Groups) | `ec2:AuthorizeSecurityGroupIngress`, `ec2:RevokeSecurityGroupIngress`, `ec2:DescribeSecurityGroups` |\n| IP ban (NACLs) | `ec2:CreateNetworkAclEntry`, `ec2:DeleteNetworkAclEntry`, `ec2:DescribeNetworkAcls` |\n| CloudWatch Logs | `logs:DescribeLogGroups`, `logs:FilterLogEvents` |\n| OVHcloud (optional) | OVH API credentials — 3-key (application key / secret / consumer key) or OAuth2. Set up via `servonaut --setup-ovh` or in Settings. |\n\n## Getting Started\n\n```bash\nservonaut\n```\n\nThat's the whole interface. The TUI is the primary and recommended way to\nuse Servonaut — every feature (fleet view, SSH, remote commands, logs,\nIP banning, AI chat, server memory, provider management) is reachable from\nthe sidebar, with full mouse and keyboard support.\n\nA few flags you may want on day one:\n\n```bash\nservonaut --update                # Check for updates and upgrade\nservonaut --install-desktop       # Create desktop shortcut (Linux/macOS)\nservonaut --setup-ovh             # Guided OVHcloud credential setup\nservonaut --debug                 # Verbose logging to stderr\n```\n\n**Headless & automation:** every major feature also has a scriptable CLI\n(`servonaut connect`, `servonaut memory`, `servonaut ai`,\n`servonaut hetzner`, `servonaut secrets`) for CI runners, cron jobs, and\nboxes without an interactive session — see the\n[CLI Reference](docs/cli-reference.md). Wiring up an AI agent instead?\nJump to [MCP Server for AI Agents](#mcp-server-for-ai-agents).\n\n### Keyboard Shortcuts\n\n| Context | Key | Action |\n|---------|-----|--------|\n| Main Menu | `U` | Update Servonaut (when update available) |\n| Global | `Q` | Quit |\n| Global | `?` | Help screen |\n| Global | `Escape` | Go back / close |\n| Global | `Ctrl+P` | Command palette — \"Go to …\" jumps to any sidebar section from the keyboard |\n| Instance List | `/` | Focus search |\n| Instance List | `R` | Force-refresh from AWS |\n| Instance List | `S` | SSH to selected instance |\n| Instance List | `B` | Browse remote files |\n| Instance List | `C` | Run command overlay |\n| Instance List | `T` | SCP transfer |\n| Instance List | `Y` | Copy IP to clipboard |\n| Server Actions | `L` | Toggle the live resource monitor |\n| Server Actions | `1`–`8` | Run the numbered action (Browse, Command, SSH, …) |\n| Server Actions | `Esc` | Close inline view, or go back |\n| Global | `F2` | Toggle AI chat panel |\n| Anywhere | Mouse drag | Select text (auto-copies to clipboard) |\n| Anywhere | `Ctrl+C` | Copy selected text |\n| Command Overlay | `Ctrl+C` | Stop running command |\n| Command Overlay | `Ctrl+R` | Command picker (saved + recent) |\n| Command Overlay | `Ctrl+S` | Save command to favorites |\n| Command Overlay | `Up/Down` | Command history |\n| Log Viewer | `P` | Pause/resume streaming |\n| Log Viewer | `C` | Clear output |\n| Log Viewer | `F` | Find/search in output |\n| Log Viewer | `L` | Switch log file |\n\n### What You Can Do\n\nThe TUI opens to a unified instance list (AWS + OVH + Hetzner + custom servers in one searchable table). The collapsible left sidebar groups everything else by purpose:\n\n**Core**\n- **📋 Instances** — search and SSH the unified fleet\n- **💻 Custom Servers** — add / edit / remove non-AWS servers (DigitalOcean, on-prem, etc.)\n- **🔑 SSH Keys** — configure default and per-instance keys\n\n**Logs & Security**\n- **📊 CloudWatch** — browse AWS log groups with Top IPs analysis, action filter (All/Allowed/Blocked), IP geolocation, AbuseIPDB lookup\n- **🔒 IP Ban Manager** — ban IPs via WAF, Security Groups, or NACLs\n- **🔍 CloudTrail** — audit AWS API activity with filters\n\n**Tools**\n- **🧠 Fleet Memory** — scan / refresh / inspect the AI-queryable fact cache, with an optional scheduled background auto-scan (bulk scans run in the background and survive leaving the panel)\n- **☁ Memory Sync** — encrypted backup of fleet memory across devices (Solo+)\n- **🛡 Findings** — proactive-monitoring inbox: scan, review, and triage server-detected issues fleet-wide (Solo+; Free shows an upgrade card)\n- **🔄 Sync Config** — encrypted config snapshots (Solo+)\n- **🔧 Settings** — configuration, scan rules, AI provider, AbuseIPDB key\n\n**OVH** (visible when configured)\n- **⚙ Manage** — table of OVH instances with state-aware lifecycle toolbar (Create / Start / Stop / Reboot / Delete)\n- **🔑 SSH Keys** — project-level SSH key registry (the one the create wizard injects from)\n- DNS Zones · IP Management · Block Storage · Billing\n\n**Hetzner** (visible when configured)\n- **⚙ Manage** — table of Hetzner servers with full lifecycle toolbar (Create / Power on / Shutdown / Reboot / Delete)\n- **🔑 SSH Keys** — Hetzner Cloud project SSH key registry\n\n**Account**\n- Login · Teams · Bug Reports\n\n**Server Actions** — clicking any instance row opens a per-instance dashboard: the detail pane shows the server's identity, a memory snapshot, and an opt-in live resource monitor (`L`), and the action rail covers:\n\n- Browse Files (inline) · Run Command · SSH Connect · SCP Transfer\n- View Scan Results · View Logs (`tail -f`) · AI Analysis · Findings (`F`)\n- Ban IP · Manage/Verify SSH Ref\n\nThe **SSH Ref** editor pairs with a Bitwarden vault — pick an SSH key from a list instead of pasting a UUID, or import keys straight from `~/.ssh` (passphrase-protected included), so a machine with no local keys can still connect. The TUI, CLI, and MCP agents all resolve the key from your vault at connect time *(Solo+)*. → [docs](docs/bitwarden-ssh.md)\n\nCommand history persists across sessions — `Ctrl+R` to search history and saved commands, `Ctrl+S` to save favorites.\n\n### Instance Caching\n\n| Scenario | Behavior |\n|----------|----------|\n| First launch (no cache) | Fetches from AWS with progress indicator |\n| Restart within TTL (default 1h) | Instant load from cache |\n| Restart after TTL | Shows stale data immediately, refreshes in background |\n| Press `R` | Force-refresh from AWS |\n\n### Configuration\n\nAll configuration lives in `~/.servonaut/config.json`, created automatically on first run.\n\nSee [Configuration Guide](docs/configuration.md) for the full reference including connection profiles, custom servers, scan rules, and match conditions.\n\n**SSH keepalives:** all connections send keepalives by default so long or idle agent-driven sessions don't get dropped. Tune globally via the `ssh` block in `config.json` (`server_alive_interval`, `server_alive_count_max`, `tcp_keepalive`, `connect_timeout`).\n\n**Legacy / special-case SSH hosts:** connection profiles and custom servers both accept an `extra_ssh_options` array that appends arbitrary `-o KEY=VALUE` flags per host — use it to talk to ancient OpenSSH boxes (`HostKeyAlgorithms=+ssh-rsa`), override keepalives, or set connect timeouts without weakening your global SSH defaults. See [Per-host SSH tuning](docs/configuration.md#per-host-ssh-tuning).\n\n**Secrets:** API keys in `config.json` support `$ENV_VAR` and `file:~/.secrets/key` syntax so the config file stays secret-free. You can also create `~/.secrets/servonaut.env` with `KEY=value` pairs — loaded automatically on startup.\n\n### Optional Dependencies\n\n```bash\n# MCP server for AI agents\npipx inject servonaut mcp\n# or: pip install 'servonaut[mcp]'\n\n# Hetzner Cloud / OVHcloud provider SDKs\npip install 'servonaut[hetzner]'\npip install 'servonaut[ovh]'\n\n# Voice — all processed locally, nothing sent to a speech service\npip install 'servonaut[voice]'            # voice input, batch engine\npip install 'servonaut[voice-streaming]'  # voice input, live text as you speak\npip install 'servonaut[voice-output]'     # spoken replies / conversation mode\n\n# Install everything\npip install 'servonaut[all]'\n```\n\nVoice also needs the PortAudio system library (`sudo apt install\nlibportaudio2`, `brew install portaudio`) and one-time model downloads,\nboth surfaced in Settings → AI → Voice Input. See\n[docs/voice.md](docs/voice.md).\n\nAI log analysis (OpenAI, Anthropic, Gemini, Ollama) needs no extra install —\n`httpx` ships as a base dependency.\n\n### MCP Server for AI Agents\n\n> This section is for wiring up AI agents (Claude Code, Cursor, Windsurf, …) —\n> not day-to-day interactive use. If you're a human operating your fleet,\n> the TUI above is the recommended interface.\n\nServonaut includes an integrated MCP server that exposes tools to AI agents like Claude Code:\n\n```bash\n# Auto-install into a coding agent\nservonaut --mcp-install claude     # Claude Code\nservonaut --mcp-install cursor     # Cursor\nservonaut --mcp-install windsurf   # Windsurf\nservonaut --mcp-install opencode   # OpenCode\nservonaut --mcp-install vscode     # VS Code Copilot\nservonaut --mcp-install codex      # Codex CLI\nservonaut --mcp-install agy        # Antigravity CLI\nservonaut --mcp-install gemini     # Gemini CLI\nservonaut --mcp-install all        # All of the above\n\n# Run MCP server manually (stdio transport)\nservonaut --mcp\n```\n\nRe-running an installer updates only Servonaut's launch command and required\nenvironment forwarding. Other MCP servers and user-owned settings such as\ntimeouts, trust, tool filters, and custom environment entries are preserved.\nSecret values are never copied into agent configuration: supported clients use\nreferences, variable-name allowlists, or inherited environment to supply\nSSH/Bitwarden state, AWS credentials, Servonaut endpoints, and `$ENV_VAR`\nreferences found in the local Servonaut config. Invalid agent JSON is refused\ninstead of overwritten, and config writes are atomic without replacing\nsymlinked dotfiles.\n\nSSH-backed MCP tools first use the configured local or vault key. If that key\ncannot authenticate and `SSH_AUTH_SOCK` was forwarded, Servonaut retries once\nusing the agent without forcing the configured identity. Authentication\nfailures are returned and audited as failures, never as successful tool calls.\n\n#### Agent-only / headless install\n\nYou don't need the TUI to use Servonaut as an agent toolbox. The MCP server\nruns fully headless — `servonaut --mcp` never loads the terminal UI (this is\nenforced by a regression test), so you can install it on a server or CI box\npurely as an MCP backend for your coding agent:\n\n```bash\npipx install 'servonaut[mcp]'\nservonaut --mcp-install claude   # or cursor, windsurf, opencode, vscode, codex, agy, gemini, all\n```\n\nConfigure credentials and servers the same way as a TUI install (\n`~/.servonaut/config.json`, `$ENV_VAR` / `file:` secret syntax — see\n[Configuration Guide](docs/configuration.md)). For Servonaut Cloud features\n(relay, config sync, hosted AI), `servonaut login` runs the device-flow\nsign-in fully headless — approve from a browser on any device. Everything an\nagent does goes through the same guard levels and is logged to\n`~/.servonaut/mcp_audit.jsonl`.\n\n**SSH keys from Bitwarden (no keys on the box).** If your instances have a\n[Bitwarden SSH ref](docs/bitwarden-ssh.md) saved, the SSH-backed tools\n(`run_command`, `get_logs`, `transfer_file`, …) resolve the private key from\nyour vault at connect time instead of needing it in `~/.ssh` — so an agent on a\nfresh server or CI box can connect with no local keys at all. Because a headless\nprocess can't prompt for your master password, unlock the vault once and export\nthe session into the environment the MCP server (or `servonaut connect`) runs\nin:\n\n```bash\nexport BW_SESSION=$(bw unlock --raw)   # unlock once; stays valid until you `bw lock` or the shell exits\nservonaut --mcp                         # child inherits BW_SESSION\n```\n\nThe key is written to a private, `0600` temporary file only for the duration of\neach command and deleted immediately after. If the vault is locked or `bw` isn't\ninstalled, the tools fall back to local keys — a working local setup is never\naffected.\n\n**Available tools:**\n\n| Category | Tools |\n|----------|-------|\n| Instance ops | `list_instances`, `check_status`, `get_server_info`, `run_command`, `get_logs`, `transfer_file` |\n| AWS observability & security | `cloudwatch_list_log_groups`, `cloudwatch_get_log_events`, `cloudwatch_top_ips`, `cloudtrail_lookup_events`, `ip_ban_list_configs`, `ip_ban_list_banned`, `ip_ban_set` |\n| Server memory | `get_server_memory`, `list_server_memories`, `build_server_memory`, `refresh_server_memory` |\n| Session / backend | `whoami`, `api_request` |\n| Relay | `relay_status`, `relay_reconnect`, `mcp_tool_call` |\n| Hetzner Cloud | `hetzner_list_servers`, `hetzner_list_server_types`, `hetzner_list_ssh_keys`, `hetzner_create_ssh_key`, `hetzner_delete_ssh_key`, `hetzner_create_server`, `hetzner_delete_server`, `hetzner_power_on`, `hetzner_power_off`, `hetzner_shutdown`, `hetzner_reboot` |\n| OVHcloud | `ovh_monitoring`, `ovh_list_ips`, `ovh_firewall_rules`, `ovh_ssh_keys`, `ovh_snapshots`, `ovh_dns_records`, `ovh_billing`, `ovh_invoices`, `ovh_create_instance`, `ovh_delete_instance`, `ovh_start_instance`, `ovh_stop_instance`, `ovh_reboot_instance` |\n| AWS EC2 | `aws_list_regions`, `aws_list_amis`, `aws_list_instance_types`, `aws_list_key_pairs`, `aws_list_subnets`, `aws_list_security_groups`, `aws_start_instance`, `aws_stop_instance`, `aws_reboot_instance`, `aws_terminate_instance`, `aws_run_instances` |\n| S3 / Object Storage | `s3_list_buckets`, `s3_list_objects`, `s3_download_object`, `s3_create_bucket`, `s3_delete_bucket`, `s3_upload_object`, `s3_delete_object`, `s3_copy_object`, `s3_move_object`, `s3_generate_presigned_url` |\n\nThe tool list is filtered to what's actually usable: OVH and Hetzner tools appear only when those providers are configured, the `ip_ban_*` tools only when at least one IP-ban target is defined, and the `*_server_memory*` tools only when the memory subsystem is enabled. CloudWatch/CloudTrail and the core instance tools are always available (AWS is the base provider).\n\n- `cloudwatch_top_ips` parses WAF/ALB structured logs to rank client IPs with allowed/blocked counts — pair it with `cloudtrail_lookup_events` to corroborate, then `ip_ban_set` to block via WAF, a security group, or a NACL.\n- `whoami` returns session metadata — the OAuth bearer is never exposed.\n- `api_request` lets an agent make authenticated REST calls against servonaut.dev with automatic 401 refresh and a CLI-side rate limit (30/min). The bearer stays on the CLI.\n- `mcp_tool_call` wraps a JSON-RPC 2.0 `tools/call` envelope against the hosted MCP at `mcp.servonaut.dev` — used for premium tools when your plan includes them.\n- `get_server_memory(id)` returns the cached fact snapshot — agents call this BEFORE any SSH round-trip so they answer most OS / runtime / service questions without `run_command`. Pass `format='context_block'` to get back a `<CONTEXT>` envelope for direct prompt injection.\n\n**Guard levels:** `readonly` (list/status/introspection only — includes CloudWatch/CloudTrail and `ip_ban_list_*` queries), `standard` (read + safe commands + authenticated REST + power management — start / stop / reboot / shutdown + S3 download), `dangerous` (everything, including `create_server` / `delete_server` / `transfer_file` / `ip_ban_set` / `aws_terminate_instance` / `aws_run_instances` / S3 mutations (`s3_create_bucket`, `s3_delete_bucket`, `s3_upload_object`, `s3_delete_object`, `s3_copy_object`, `s3_move_object`, `s3_generate_presigned_url`)). Dangerous shell commands (`rm -rf`, `shutdown`, `reboot`, etc.) are always blocked regardless of guard level. Mutating tools carry an explicit \"confirm with the user before calling\" cue in their descriptions; the top-level MCP instructions document the three-step protocol (summarise → state args → wait for affirmative reply). All operations are logged to `~/.servonaut/mcp_audit.jsonl`.\n\n## Servonaut Cloud account\n\nOptional — Servonaut works fully offline against your own AWS / OVH\ncredentials. Signing in at [servonaut.dev](https://servonaut.dev) unlocks:\n\n- **Config sync** — push/pull an encrypted snapshot of your\n  `config.json` between machines. The passphrase never leaves your\n  client; the server only sees ciphertext. Sidebar entry `🔄 Sync\n  Config` opens the snapshot manager directly (Pull Latest / Push New\n  / Restore / Rename / Delete).\n- **MCP relay** — a Mercure SSE channel that lets AI agents and\n  team-mates dispatch MCP tool calls to this machine. While the relay\n  is connected, `https://servonaut.dev/account` reports your CLI as\n  online, and hosted agents can reach it.\n- **Memory Sync (Solo+)** — encrypted fleet memory backup with drift\n  detection. Open the `☁ Memory Sync` sidebar entry, click *Unlock\n  Memory Sync*, and enter a passphrase. The same screen handles\n  first-time enrolment AND post-restart unlock — your private key is\n  wrapped with the passphrase locally, so the server never sees it.\n  After unlock, click *Sync now* to push every cached server's memory\n  modules as encrypted envelopes, or flip on **auto-sync** to drain the\n  queue in the background so the server-side copy (and weekly digests)\n  stay current. Unlock **survives restarts**: tick *Remember on this\n  device* to silently re-unlock from your OS keychain on the next launch\n  (re-prompted after 30 days, or *Forget on this device* to clear it). If\n  you decline, Memory Sync stays dormant until you next open a memory\n  section. Per-feature settings (digest cadence, Mercure push, AI consent)\n  live at the bottom of the Settings panel and are stored on your\n  servonaut.dev account.\n\nSign in from the TUI's Account / Login screen. After a successful\ndevice-flow authentication, the TUI auto-starts an in-process relay\nlistener and the sidebar indicator flips to `● connected`.\n\nThe listener is tied to the TUI window — closing the TUI drops the\nconnection after ~60 s. For always-on reachability (CI runners,\nheadless boxes), use `servonaut connect --bg` instead; the CLI and\nTUI cooperate over `~/.servonaut/relay.lock` so they can't run at the\nsame time. The TUI shows `external listener (PID N)` when a `--bg`\nlistener is holding the connection.\n\n```bash\nservonaut connect                 # Foreground relay (Ctrl+C to stop)\nservonaut connect --bg            # Detach; writes ~/.servonaut/relay.pid\nservonaut connect --status        # Local + backend view with divergence warning\nservonaut connect --stop          # SIGTERM the background listener\nservonaut connect --reconnect     # Heal a stale SSE socket (stop+start)\nservonaut connect --force-bg      # Take over from a TUI's in-process listener\n```\n\nSee [CLI Reference → servonaut connect](docs/cli-reference.md) for full flags.\n\nTokens are stored at `~/.servonaut/auth.json` with mode `0600`, written\natomically via tmp + `os.replace()`. If an older build left the file\nworld-readable, the next run auto-fixes it.\n\n## Proactive monitoring — Findings (Solo+)\n\nServer-side detectors scan your fleet for problems and post each one as a\ntriageable **finding card**: severity, description, evidence, and\nremediation options. Detection runs in the Servonaut cloud; this client\nonly runs **read-only** probes over your relay connection and renders the\nresults — nothing is analysed or decided locally.\n\n- **Fleet inbox / per-instance** — `🛡 Findings` in the sidebar for the\n  whole fleet, `F` on any server for that instance.\n- **Scan now** (`s`) — dispatches read-only probes over the relay\n  (`servonaut connect` or the TUI autostart must be running); inapplicable\n  detectors report the reason instead of failing silently.\n- **Triage** — acknowledge (`a`), resolve (`r`), or suppress (`x`); status\n  syncs server-side.\n- **Gated one-click remediation** — automatable fixes run only on an\n  explicit click, from a **server-signed preview**, through a\n  **verb-allowlisted executor** (typed confirmation for state changes,\n  dry-run first, fully audited). Fixes today: block a source IP (AWS\n  WAF / Security Group / NACL, or the box's own firewall —\n  nftables / ufw / firewalld) and renew a TLS certificate.\n\n**[→ Full guide: docs/proactive-monitoring.md](docs/proactive-monitoring.md)** —\ndetectors, the detection/probe/remediation model, and the safety &\nprivacy design. Included with Solo and Teams (monitored-instance\nallowance); Free shows an upgrade card.\n\n## Secrets management (Solo+)\n\nCentralise SSH keys + other named secrets behind a pluggable provider\nbackend. Day-to-day this is invisible: once configured, SSH key\nresolution checks your provider automatically on every connect — you\nkeep clicking *SSH* in the TUI and it just works. The commands below\nare one-time setup. MVP supports two backends:\n\n- **LocalProvider** — keys live in `~/.servonaut/secrets.json`\n  (mode 0600, atomic write, same trust model as `auth.json`). Always\n  available on Solo and Teams plans.\n- **BitwardenProvider (`bws`)** — keys live in your team's Bitwarden\n  Secrets Manager project. Team admin configures the project from\n  `https://servonaut.dev/account/teams/<slug>/secrets`; CLI fetches\n  the metadata and reads/writes through the local `bws` binary using\n  your own access token. The token never leaves your machine —\n  servonaut.dev only stores the project ID and the name of the env\n  var holding the token.\n\nTo use Bitwarden as your team's backend:\n\n```bash\n# 1. Install the bws CLI (one-time)\nservonaut secrets install bws         # macOS: brew · Linux: cargo\n# Windows / other → prints upstream install URL.\n\n# 2. Mint a BWS access token (https://bitwarden.com/help/personal-access-tokens/)\n#    and export it\nexport BWS_ACCESS_TOKEN=<your-token>\n\n# 3. Verify wiring\nservonaut secrets status              # shows plan, entitlement, active provider\n\n# That's it — SSH key resolution now checks Bitwarden first, ~/.ssh as\n# fallback. Push a key into BWS with `bws secret create`:\nbws secret create \"$(basename ~/.ssh/prod-server)\" \\\n                  \"$(cat ~/.ssh/prod-server)\" \\\n                  --project-id <project-uuid-from-status>\n```\n\nKey resolution order on every SSH connect:\n1. Active provider (Bitwarden, if configured) looked up by key name.\n2. `~/.ssh` discovery (existing patterns + fuzzy match).\n3. The path stored in `config.json::instance_keys[<id>]` or\n   `config.default_key`.\n\nFree-tier users get the legacy `~/.ssh`-only flow with zero behaviour\nchange. Provider-supplied keys land in `~/.servonaut/keys/<name>` at\nmode 0600.\n\nThreat-model + design notes are pinned in the codebase via inline\ndocstrings on `services/secret_provider.py`,\n`services/bitwarden_provider.py`, and\n`services/secret_provider_resolver.py`.\n\n### Database credential vault\n\nThe same secret store also backs a **database credential vault**: scan a server\nfor the DB credentials its apps already use — `.env` / `DATABASE_URL` (including\n`DATABASE_URL_PROD` / `_STAGING` variants), `wp-config.php`, `configuration.php`,\nMagento `env.php`, and `docker-compose` `environment:` blocks, with a read-only\n`sudo -n` fallback so root-owned files and containerized stacks are covered.\nStore the password under a per-site label and the `db_processlist` /\n`db_top_queries` tools resolve it by name — the password never lands in your\nconfig or in an AI agent's context. A **Secrets → DB coverage** view lists which\ninstances are covered per site, with in-place label and remove.\n[Full docs](docs/db-credential-vault.md)\n\n## Development\n\n```bash\n# Run directly (primary dev workflow)\nPYTHONPATH=src python3 -m servonaut.main\n\n# Run with debug logging\nPYTHONPATH=src python3 -m servonaut.main --debug\n\n# Install editable\npip install -e .\n\n# Update pipx installation after changes\npipx install . --force\n```\n\n```bash\n# Run tests\npip install -e \".[test]\"\npytest\n```\n\nSee [Architecture](docs/architecture.md) for codebase structure and design patterns.\n\n## Troubleshooting\n\nSee [Troubleshooting Guide](docs/troubleshooting.md) for help with SSH connections, bastion hosts, key management, and AWS credentials.\n\n## Runtime Files\n\nAll runtime files are under `~/.servonaut/`:\n\n| File | Purpose |\n|------|---------|\n| `config.json` | Main configuration |\n| `cache.json` | Cached instance list (AWS + merged OVH) |\n| `auth.json` | OAuth tokens for servonaut.dev, mode `0600`, atomic writes |\n| `keywords.json` | Scan results store |\n| `command_history.json` | Saved commands and command history |\n| `ip_ban_audit.json` | IP ban audit trail |\n| `mcp_audit.jsonl` | MCP server audit trail |\n| `relay.pid` | Background `servonaut connect --bg` PID (when running) |\n| `relay.lock` | Advisory flock shared between the TUI's in-process listener and `--bg`, carries `{pid, mode, acquired_at}` |\n| `memory/` | Server-memory store: `<provider>/<instance_id>/<module>.json` per probed server, plus `index.json` |\n| `memory/sync_queue.jsonl` | Pre-encryption envelopes waiting to be pushed to servonaut.dev. Replayed on next bootstrap; deleted after a successful drain. Only present while Memory Sync has unsent work. |\n| `logs/servonaut.log` | Application log |\n| `logs/relay.log` | Relay lifecycle events (one JSON line per event, secrets redacted) |\n\n## Logging\n\nLogs are always written to `~/.servonaut/logs/servonaut.log`. Use `--debug` for verbose stderr output.\n\nWhen SSH fails, the terminal window stays open showing the error and exit code.\n\n## Listed on\n\n[![servonaut MCP server](https://glama.ai/mcp/servers/zb-ss/servonaut/badges/card.svg)](https://glama.ai/mcp/servers/zb-ss/servonaut)\n\nAlso published to the official [MCP Registry](https://registry.modelcontextprotocol.io) as `dev.servonaut/servonaut`.\n\n## License\n\nThis project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.\n",
  "bytes": 35798,
  "sha": "2743c84c9a942a44b58301e4fee48131f92fdd0e498ce383651a4e4a5eeb1738",
  "repo_slug": "zb-ss/servonaut",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_servonaut_servonaut_3e95db67/readme"
}