infra-mcp
by esp4ce
README.md
<div align="center">
# infra-mcp
[](https://pypi.org/project/infra-mcp/)
[](https://glama.ai/mcp/servers/esp4ce/infra-mcp)
[](LICENSE)
*Read-only MCP access to on-prem Linux VMs and PostgreSQL databases over SSH.*
```
agent ──stdio──▶ infra-mcp ──SSH──▶ VMs (journald · log files)
└──▶ DBs (read-only PostgreSQL)
```
</div>
---
An agent can check service health, retrieve bounded logs, inspect DB state, and explore table schemas — without terminal access. Every remote operation is allowlist-gated and written to an append-only audit log.
## Install
```bash
uv tool install infra-mcp
# or
pip install infra-mcp
```
## Configure
Copy `infra-mcp.yaml.example` to `~/.infra-mcp/infra-mcp.yaml` and edit it.
```bash
# Generate a starter config from ~/.ssh/config
infra-mcp generate-config -o ~/.infra-mcp/infra-mcp.yaml
# Create the read-only PostgreSQL role(s)
infra-mcp setup
# Check VM reachability
infra-mcp test
# Refresh discovered services, log dirs, and databases (updates config in place)
infra-mcp discover --in-place
```
Override the config path with `--config` or `INFRA_MCP_CONFIG`.
## Run
```bash
infra-mcp run
```
Register as a **stdio** MCP server in your client (Claude Code, Cursor, …) with command `infra-mcp run`.
## Updates
`infra-mcp` checks PyPI for a newer release once a day and, when one exists, prints a
one-line hint to stderr telling you how to upgrade:
```bash
uv tool upgrade infra-mcp # or: pip install --upgrade infra-mcp
```
The check runs in the background, never blocks startup, and never touches stdout. Print
the installed version with `infra-mcp --version`. Disable the check entirely by setting
`INFRA_MCP_NO_UPDATE_CHECK=1`.
## Tools
### VM & services
| Tool | Purpose |
|------|---------|
| `list_vms` | All VMs with reachability and watched services |
| `get_infra_overview` | Service states + DB health for one VM in a single call |
| `get_service_status` | systemd state, uptime, last 5 log lines |
| `get_service_logs` | Bounded journald logs, filtered by severity |
| `get_log_file` | Last N lines of an allowed log file, optional grep |
### Databases
| Tool | Purpose |
|------|---------|
| `get_db_status` | Connection counts, waiting locks, long-running query count |
| `query_db` | Bounded caller-supplied `SELECT` |
| `list_tables` | Tables in a database (schema + name), capped at 200 |
| `describe_table` | Columns, types, primary key, foreign keys for one table |
### Meta
| Tool | Purpose |
|------|---------|
| `get_audit_log` | Recent entries from the local audit log |
All output is bounded server-side (200 log lines, 100 DB rows, 200 tables/columns max). Truncation is always flagged with a `-- TRUNCATED:` marker. `list_tables` and `describe_table` cache results in memory (TTL: `schema_cache_ttl_hours`, default 24 h); pass `refresh: true` to force a live re-read.
## Security model
- SSH commands and systemd services are checked against a per-VM allowlist before any network call.
- All DB queries run as a read-only role inside a `READ ONLY` transaction.
- Log file paths are resolved against a per-VM directory allowlist (`..` traversal blocked).
- Every remote operation is appended to a local JSONL audit log.
TDQS
A4/5.0
Scored across 10 tools
Disambiguation5/5
Each tool targets a distinct resource or action: tables (list, describe, query), VMs (list, overview), services (status, logs), logs (file, service), database health, audit log. No overlap in purpose.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern (describe_table, get_audit_log, list_vms, etc.), making it easy to infer functionality.
Tool Count5/5
10 tools is appropriate for infrastructure diagnostics, covering VMs, databases, services, logs, and audit without being excessive or sparse.
Completeness5/5
The tool set provides complete coverage for read-only infrastructure diagnosis: discovering VMs, checking health, exploring database schemas, querying data, and retrieving logs. No obvious gaps for its diagnostic purpose.
Maintenance
ActivityInactive
ResponsivenessNo issues