diff --git a/skills/saiop-infrastructure/saiop-mcp-servers/SKILL.md b/skills/saiop-infrastructure/saiop-mcp-servers/SKILL.md new file mode 100644 index 0000000..daf9d22 --- /dev/null +++ b/skills/saiop-infrastructure/saiop-mcp-servers/SKILL.md @@ -0,0 +1,70 @@ +--- +name: saiop-mcp-servers +description: "MCP server setup for SAIOP (git, postgres read-only, docker read-only) — least-privilege patterns and what was deliberately NOT wired up." +version: 1.0.0 +author: Claude Code (SAIOP ops session) +license: MIT +platforms: [linux] +prerequisites: + env_vars: [MCP_POSTGRES_READONLY_PASSWORD] + commands: [uvx] +metadata: + hermes: + tags: [SAIOP, MCP, security, least-privilege, postgres, docker, git] +--- + +# MCP servers on SAIOP (Phase 6.3) + +## When to use + +Adding or auditing MCP tool access for Hermes (Deployment Guide §6.3). + +## What's wired up and why + +- **git-mcp** (`uvx mcp-server-git -r /opt/ai-stack`) — all 12 tools enabled + (including commit/branch/checkout). Low risk: git is naturally revertible, + no host-level escalation path. +- **postgres-mcp** (`uvx postgres-mcp --access-mode restricted`) — a + dedicated `mcp_readonly` Postgres role exists (SELECT-only, granted on + `saiop` + `netbox` DBs specifically, not the other app DBs). **Two + independent enforcement layers**: the role itself can't write (verified: + `DELETE` returns `permission denied`), and `--access-mode restricted` + blocks non-SELECT statements at the app layer too. Connection string goes + through the `DATABASE_URI` env var (checked the package source — + `os.environ.get("DATABASE_URI", args.database_url)`), not a CLI arg, + since CLI args are visible to any local user via `ps aux`. +- **docker-mcp** (`uvx docker-mcp`) — **the npm/pip package itself has no + read-only mode.** It exposes `create-container` and `deploy-compose` + (full write/deploy) alongside `get-logs`/`list-containers`. Restricted via + Hermes's own `tools: {include: [...]}` allow-list in `config.yaml` to + just the two read-only tools — same enforcement mechanism already + field-verified for the Telegram platform-toolset restriction (a real + destructive command was confirmed blocked at the tool layer, not just + configured). **Do not change this to "all tools" without a deliberate + decision** — full Docker access would directly undermine the project's + core containment design (the `hermes` Linux user is deliberately denied + `docker compose`/restart-docker capability via scoped sudoers; an + unrestricted docker-mcp would hand that back through a side door). + +## What was deliberately NOT wired up + +- **SSH MCP** — no second system exists in this environment that needs SSH + access beyond the VM Hermes already runs on. The one genuinely sensitive + SSH target (the Proxmox hypervisor) is the project's hardest boundary — + don't wire SSH MCP access to it without the operator directly involved in + scoping exactly what it can reach. +- **pfSense/MikroTik MCP** — no real device credentials exist in this + environment to configure them safely. Needs the operator to provide + scoped, read-only-by-default credentials first. + +## Useful commands + +```bash +hermes mcp list # see all servers + tool-count summary +hermes mcp test # verify a server connects and discover its tools +``` + +`hermes mcp add` has an interactive curses-based tool picker with no clean +non-interactive path — for a scripted/repeatable setup, hand-edit +`mcp_servers:` in `config.yaml` directly instead (schema: +`{command, args, env, enabled, tools: {include: [...]}}`).