Releases: raychao-oao/infra-mcp
Release list
v2.0.0 — Resource model: layer + roots replace path guessing
Why this release exists
A fleet-wide census found that 32 of 34 recorded data/config paths — and 6 of 6 stray static paths — pointed at directories that did not exist. The root cause was structural: registration guessed sub-paths for every service, but most services were never deployed by this server, so the guesses became fiction that purge offered to delete and audits reported as real. v2 removes the possibility of that class of record.
Breaking changes
- Schema:
service_deploymentscolumnsapp_path/static_path/data_path/config_path/log_pathare removed, replaced bylayer(standard/nonstandard),project_root,deploy_root,workspace_url, andpath_overrides(JSON). Sub-paths are derived from roots by convention via a single resolver; only deviations are stored. register_serviceis now allocation-only (standard layer): it assigns roots thatdeploy_serviceconsumes. The five old path parameters are gone.update_servicefield set changed accordingly;layeris updatable, and promoting a record tostandardre-validates all effective paths.
New
record_service(tool #42): registers services that already exist and were not deployed by this server. Zero defaults — unknown facts stay null instead of being invented. Deploy refuses these records; purge never deletes their directories.scripts/migrate_resource_model.py: two-phase migration (add+backfill while old code runs → drop after new code is live), dry-run by default, per-record report, re-run-safe, refuses to drop columns on an unmigrated DB.- Health check now probes the deployments table, so a schema/DB regression turns
/healthunhealthy and the auto-deploy rollback can actually catch it (previously it only probed port allocations and reported healthy on a broken schema). - Test suite from zero to 50 tests (pytest + pytest-asyncio), covering the model, path resolution, both registration modes, deploy/purge guards, and the migration script against fixture DBs.
Docs
docs/MCP-API.md (allocation-vs-recording model, full record_service section), docs/Data-Models.md (new schema), README tool count.
v1.1.0 — Audit tools that can be trusted
38 → 41 tools. The theme of this release is that the security tooling from v1.0.0 was not trustworthy, and a tool nobody trusts protects nothing.
The audit tools existed the whole time. They were ignored, and they had earned it: every service scored 0.0 because the Caddy config path was derived as {project}-{service}.caddy while real filenames follow the hostname, and check_listening_ports graded 0.0.0.0 as less severe than a Tailscale address. Six services sat reachable on a public IP for roughly three months behind that noise.
New tools
check_firewall— asks whether a host actually filters packets, not whether a firewall service claims to be enabled. Aufwpackage inrcstate leaves/etc/ufw/ufw.confsayingENABLED=yesandsystemctl is-enabled ufwansweringenabledwhile no filter exists at all. Checks liveiptables/ip6tablesrules, package states and persistence — IPv6 separately, because purging ufw can leave the v6 chain at policyACCEPTwhile v4 looks healthy.reconcile_ports— three-way drift check between what is listening, what is allocated, and what was released.update_service— correct a deployment record without touching a server. Records used to be editable only by opening the SQLite file, so in practice they were left wrong, and every tool that trusts them inherited the error.
Audit correctness
- Three outcomes, not two.
SECURE/VULNERABLE/UNVERIFIED. "I could not determine the bind address" is neither a clean bill of health nor a finding; the score is computed over what could actually be judged. - Locate, don't derive. Caddy sites are found by hostname, port and static root; systemd units by
WorkingDirectoryandExecStart. Real units are named after what they run, not after{project}-{service}. - Every service on record is audited, not only those marked
deployed— the exposed six were not among the two that filter had been passing. - Addresses are parsed, not string-matched. Loopback, Tailscale (
100.64.0.0/10,fd7a:115c:a1e0::/48), private and public ranges are graded by reachability. - Speed is a correctness property. One
ServerSnapshotper server instead of round trips per check: a fleet audit went from 3–4 minutes to about 11 seconds. A slow audit gets skipped exactly like a noisy one. - Deliberate states are no longer warnings: a reserved port with nothing listening, a service with no Caddy site, a static site with no backend port.
purge_service
- It had never once returned successfully. After marking a record purged it re-read it with a query that excludes purged rows, got
None, and raised — reportingPURGE_FAILEDfor work that had completed. The obvious responses to that message, retry or clean up by hand, are both wrong. - It could report success while the site was still serving. Caddy-removal and file-removal failures were dropped on the floor. Any failed step now yields
PURGE_INCOMPLETEnaming what was left behind. - Refuses to run when another live deployment shares the record's hostname, port or paths — a superseded record often still describes its successor's resources. Adds
dry_runandforce.
Also
register_serviceno longer invents paths. Astatic_pathon a service with no static files madedeploy_servicecreate/var/www/{project}/and symlink to it; a defaultedlog_pathpointed at a directory nothing creates. Docker services get no guessed paths at all.- Optional pull-based auto-deploy (
deploy/auto-update.sh+ systemd timer) with health check and automatic rollback. - Security: patched CVE-2026-48710 (Starlette BadHost), hardened the auth middleware.
ReadWritePathsin the sample unit now covers the trees the tools manage. WithProtectSystem=strict, a server whoseINFRA_LOCAL_SERVERnames itself could manage every host except its own — andsudodoes not help, since a read-only mount is read-only for root too.
Full changelog: v1.0.0...v1.1.0
v1.0.0 — Initial Public Release
Infrastructure MCP Server v1.0.0
First public release of infra-mcp — a Model Context Protocol server that gives AI agents a structured interface to infrastructure primitives.
What's included
35 MCP tools across 6 categories:
- Ports — allocate and release ports from a managed pool (3000–9999)
- Services — deploy, restart, stop, audit, and inspect services on VPS via SSH + systemd + Caddy
- Tunnels — register and manage Cloudflare Tunnels (per-server main tunnels)
- DNS — create, update, delete, and list Cloudflare DNS records
- Access — manage Cloudflare Access applications and policies
- Git — create, list, inspect, and delete Gitea repositories
Architecture:
- FastAPI + JSON-RPC 2.0 transport (MCP-compatible)
- SQLite resource database (ports, tunnels, deployments)
- Cloudflare Access + optional API key authentication
- Zero Trust deployment — server binds to
127.0.0.1, all traffic via Cloudflare Tunnel - SSH-based remote command execution with shell injection prevention
Security
This release includes a full security audit pass: shell injection prevention, input validation, safe Caddy/systemd config generation, and hardened JSON-RPC error handling.
Getting Started
See QUICKSTART.md and docs/MCP-Client-Setup.md.