proxy-aiops 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. proxy_aiops-0.1.0/.github/workflows/mcp-publish.yml +55 -0
  2. proxy_aiops-0.1.0/.github/workflows/publish.yml +26 -0
  3. proxy_aiops-0.1.0/.gitignore +8 -0
  4. proxy_aiops-0.1.0/CHANGELOG.md +68 -0
  5. proxy_aiops-0.1.0/LICENSE +21 -0
  6. proxy_aiops-0.1.0/PKG-INFO +213 -0
  7. proxy_aiops-0.1.0/README.md +197 -0
  8. proxy_aiops-0.1.0/RELEASE_NOTES.md +61 -0
  9. proxy_aiops-0.1.0/SECURITY.md +96 -0
  10. proxy_aiops-0.1.0/mcp_server/__init__.py +1 -0
  11. proxy_aiops-0.1.0/mcp_server/_shared.py +108 -0
  12. proxy_aiops-0.1.0/mcp_server/server.py +40 -0
  13. proxy_aiops-0.1.0/mcp_server/tools/__init__.py +1 -0
  14. proxy_aiops-0.1.0/mcp_server/tools/analysis.py +170 -0
  15. proxy_aiops-0.1.0/mcp_server/tools/certs.py +29 -0
  16. proxy_aiops-0.1.0/mcp_server/tools/configread.py +50 -0
  17. proxy_aiops-0.1.0/mcp_server/tools/routes.py +52 -0
  18. proxy_aiops-0.1.0/mcp_server/tools/services.py +74 -0
  19. proxy_aiops-0.1.0/mcp_server/tools/status.py +47 -0
  20. proxy_aiops-0.1.0/mcp_server/tools/traffic.py +36 -0
  21. proxy_aiops-0.1.0/mcp_server/tools/undo.py +121 -0
  22. proxy_aiops-0.1.0/mcp_server/tools/writes.py +265 -0
  23. proxy_aiops-0.1.0/proxy_aiops/__init__.py +14 -0
  24. proxy_aiops-0.1.0/proxy_aiops/cli/__init__.py +5 -0
  25. proxy_aiops-0.1.0/proxy_aiops/cli/_common.py +78 -0
  26. proxy_aiops-0.1.0/proxy_aiops/cli/_root.py +68 -0
  27. proxy_aiops-0.1.0/proxy_aiops/cli/analyze.py +81 -0
  28. proxy_aiops-0.1.0/proxy_aiops/cli/certs.py +43 -0
  29. proxy_aiops-0.1.0/proxy_aiops/cli/configcmd.py +107 -0
  30. proxy_aiops-0.1.0/proxy_aiops/cli/doctor.py +21 -0
  31. proxy_aiops-0.1.0/proxy_aiops/cli/init.py +166 -0
  32. proxy_aiops-0.1.0/proxy_aiops/cli/overview.py +16 -0
  33. proxy_aiops-0.1.0/proxy_aiops/cli/routes.py +59 -0
  34. proxy_aiops-0.1.0/proxy_aiops/cli/secret.py +105 -0
  35. proxy_aiops-0.1.0/proxy_aiops/cli/server.py +74 -0
  36. proxy_aiops-0.1.0/proxy_aiops/cli/services.py +54 -0
  37. proxy_aiops-0.1.0/proxy_aiops/cli/undo.py +62 -0
  38. proxy_aiops-0.1.0/proxy_aiops/config.py +174 -0
  39. proxy_aiops-0.1.0/proxy_aiops/connection.py +189 -0
  40. proxy_aiops-0.1.0/proxy_aiops/doctor.py +97 -0
  41. proxy_aiops-0.1.0/proxy_aiops/governance/__init__.py +40 -0
  42. proxy_aiops-0.1.0/proxy_aiops/governance/audit.py +377 -0
  43. proxy_aiops-0.1.0/proxy_aiops/governance/budget.py +225 -0
  44. proxy_aiops-0.1.0/proxy_aiops/governance/decorators.py +482 -0
  45. proxy_aiops-0.1.0/proxy_aiops/governance/paths.py +23 -0
  46. proxy_aiops-0.1.0/proxy_aiops/governance/patterns.py +378 -0
  47. proxy_aiops-0.1.0/proxy_aiops/governance/policy.py +430 -0
  48. proxy_aiops-0.1.0/proxy_aiops/governance/sanitize.py +45 -0
  49. proxy_aiops-0.1.0/proxy_aiops/governance/undo.py +218 -0
  50. proxy_aiops-0.1.0/proxy_aiops/ops/__init__.py +2 -0
  51. proxy_aiops-0.1.0/proxy_aiops/ops/_util.py +86 -0
  52. proxy_aiops-0.1.0/proxy_aiops/ops/analysis.py +469 -0
  53. proxy_aiops-0.1.0/proxy_aiops/ops/certs.py +146 -0
  54. proxy_aiops-0.1.0/proxy_aiops/ops/configread.py +94 -0
  55. proxy_aiops-0.1.0/proxy_aiops/ops/overview.py +55 -0
  56. proxy_aiops-0.1.0/proxy_aiops/ops/routes.py +209 -0
  57. proxy_aiops-0.1.0/proxy_aiops/ops/services.py +304 -0
  58. proxy_aiops-0.1.0/proxy_aiops/ops/status.py +73 -0
  59. proxy_aiops-0.1.0/proxy_aiops/ops/traffic.py +178 -0
  60. proxy_aiops-0.1.0/proxy_aiops/ops/writes.py +174 -0
  61. proxy_aiops-0.1.0/proxy_aiops/platform.py +371 -0
  62. proxy_aiops-0.1.0/proxy_aiops/secretstore.py +304 -0
  63. proxy_aiops-0.1.0/pyproject.toml +60 -0
  64. proxy_aiops-0.1.0/server.json +21 -0
  65. proxy_aiops-0.1.0/skills/proxy-aiops/SKILL.md +159 -0
  66. proxy_aiops-0.1.0/skills/proxy-aiops/references/capabilities.md +86 -0
  67. proxy_aiops-0.1.0/skills/proxy-aiops/references/cli-reference.md +79 -0
  68. proxy_aiops-0.1.0/skills/proxy-aiops/references/setup-guide.md +99 -0
  69. proxy_aiops-0.1.0/smithery.yaml +9 -0
  70. proxy_aiops-0.1.0/tests/conftest.py +34 -0
  71. proxy_aiops-0.1.0/tests/test_analysis.py +224 -0
  72. proxy_aiops-0.1.0/tests/test_cli_writes.py +143 -0
  73. proxy_aiops-0.1.0/tests/test_doctor.py +215 -0
  74. proxy_aiops-0.1.0/tests/test_governance_persistence.py +187 -0
  75. proxy_aiops-0.1.0/tests/test_init.py +171 -0
  76. proxy_aiops-0.1.0/tests/test_platform.py +220 -0
  77. proxy_aiops-0.1.0/tests/test_reads.py +408 -0
  78. proxy_aiops-0.1.0/tests/test_secretstore.py +99 -0
  79. proxy_aiops-0.1.0/tests/test_smoke.py +137 -0
  80. proxy_aiops-0.1.0/tests/test_undo_executor.py +138 -0
  81. proxy_aiops-0.1.0/tests/test_writes.py +340 -0
  82. proxy_aiops-0.1.0/uv.lock +1121 -0
@@ -0,0 +1,55 @@
1
+ name: mcp-publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ permissions:
9
+ id-token: write
10
+ contents: read
11
+
12
+ jobs:
13
+ publish-mcp:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - name: Wait for PyPI
18
+ # The release event also triggers the PyPI publish workflow; the MCP
19
+ # registry validates that the package version exists on PyPI, so poll
20
+ # until it has propagated (every 15s, up to 10 minutes).
21
+ run: |
22
+ python3 - <<'EOF'
23
+ import json
24
+ import sys
25
+ import time
26
+ import urllib.error
27
+ import urllib.request
28
+
29
+ with open("server.json", encoding="utf-8") as f:
30
+ package = json.load(f)["packages"][0]
31
+ name, version = package["identifier"], package["version"]
32
+ url = f"https://pypi.org/pypi/{name}/{version}/json"
33
+ deadline = time.monotonic() + 600
34
+ while True:
35
+ try:
36
+ with urllib.request.urlopen(url, timeout=10):
37
+ print(f"{name}=={version} is available on PyPI.")
38
+ sys.exit(0)
39
+ except (urllib.error.URLError, OSError) as exc:
40
+ print(f"{name}=={version} not on PyPI yet ({exc}); "
41
+ "retrying in 15s...")
42
+ if time.monotonic() >= deadline:
43
+ sys.exit(f"Timed out after 10 minutes waiting for "
44
+ f"{name}=={version} to appear on PyPI. "
45
+ "Check the PyPI publish workflow, then re-run "
46
+ "this workflow via workflow_dispatch.")
47
+ time.sleep(15)
48
+ EOF
49
+ - name: Install mcp-publisher
50
+ run: |
51
+ curl -sL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
52
+ - name: Login to MCP Registry (GitHub OIDC)
53
+ run: ./mcp-publisher login github-oidc
54
+ - name: Publish server.json
55
+ run: ./mcp-publisher publish
@@ -0,0 +1,26 @@
1
+ name: Publish to PyPI
2
+
3
+ # Trusted Publishing (OIDC) — publishes from GitHub's runners with no API token,
4
+ # sidestepping the local-IP / account new-project rate limit. Configure a matching
5
+ # "trusted publisher" for this package on PyPI (see the repo release notes).
6
+ on:
7
+ release:
8
+ types: [published]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ publish:
16
+ runs-on: ubuntu-latest
17
+ permissions:
18
+ id-token: write # required for PyPI Trusted Publishing (OIDC)
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Set up uv
22
+ uses: astral-sh/setup-uv@v5
23
+ - name: Build sdist + wheel
24
+ run: uv build
25
+ - name: Publish to PyPI (Trusted Publishing)
26
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ dist/
3
+ __pycache__/
4
+ *.pyc
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ *.egg-info/
8
+ .coverage
@@ -0,0 +1,68 @@
1
+ # Changelog
2
+
3
+ All notable changes to proxy-aiops are documented here. This project adheres
4
+ to [Semantic Versioning](https://semver.org/).
5
+
6
+ ## v0.1.0 — 2026-07-17
7
+
8
+ Initial preview release: governed AI-ops for **Traefik**, **Caddy** and
9
+ **HAProxy** reverse proxies / load balancers, with a bundled governance
10
+ harness. One MCP server spans all three platforms via a per-target `platform`
11
+ field; an explicit support matrix raises teaching errors for ops a platform
12
+ cannot do (never a silent no-op).
13
+ **Mock-validated only — not yet verified against a live proxy.**
14
+
15
+ ### Added
16
+
17
+ - **26 MCP tools** (21 read, 5 write), every one wrapped with the bundled
18
+ `@governed_tool` harness (audit, policy, token/runaway budget, undo,
19
+ risk-tiers):
20
+ - **Status (read)** — `proxy_overview`, `version_info`, `list_entrypoints`.
21
+ - **Routes (read)** — `list_routes` (normalised hosts/paths across
22
+ platforms), `route_detail`, `find_route` (static host/path match).
23
+ - **Services (read)** — `list_services`, `service_detail`, `list_upstreams`
24
+ (server-level up/down/maint/drain + check info), `upstream_detail`,
25
+ `list_middlewares`.
26
+ - **Certificates (read)** — `list_certificates` (TLS domain inventory +
27
+ optional bounded live handshake probe).
28
+ - **Traffic (read)** — `traffic_stats`, `error_counters` (traefik /metrics
29
+ text parsed per status code; haproxy Data Plane stats per class).
30
+ - **Config (read)** — `config_snapshot`, `search_config`, `get_config_value`.
31
+ - **Flagship analyses (read)** — `backend_health_rca`, `cert_expiry_sweep`,
32
+ `error_rate_rca`, `route_conflict_analysis` — transparent heuristics that
33
+ report their numbers, not a black-box verdict.
34
+ - **Writes** — caddy `set_config_value` (med, prior subtree captured →
35
+ undo restores it), `delete_config_path` (**high**, subtree captured → undo
36
+ re-creates it), `load_config` (**high**, full prior config snapshotted →
37
+ undo re-loads it); haproxy `set_server_state` (med, ready/drain/maint,
38
+ undo restores prior admin state), `set_server_weight` (med, undo restores
39
+ prior weight). Every write takes a `dry_run` preview; high-risk writes
40
+ require an approver.
41
+ - **Platform abstraction with a support matrix** — a name-keyed registry maps
42
+ each target's `platform` (`traefik` / `caddy` / `haproxy`) to its auth style
43
+ + REST resource paths, and unsupported ops raise **teaching errors**:
44
+ traefik writes point at its providers, haproxy config edits point at the
45
+ runtime writes, caddy error counters point at access logs.
46
+ - **Encrypted secret store** — the haproxy Data Plane API password (required)
47
+ or an optional Basic-auth credential for traefik/caddy is stored encrypted
48
+ in `~/.proxy-aiops/secrets.enc` (Fernet + scrypt); never plaintext on disk.
49
+ Traefik/caddy targets without a secret are treated as unauthenticated
50
+ localhost endpoints. Legacy `PROXY_<TARGET>_SECRET` env var honoured as a
51
+ fallback.
52
+ - **CLI** (`proxy-aiops`) — `init` platform-picking wizard (TLS-verify default
53
+ ON, seeds a starter rules.yaml with the dual-control high-risk tier),
54
+ `overview`, `routes list/show/find`, `services list/show/upstreams`,
55
+ `analyze health/errors/conflicts`, `certs --sweep`,
56
+ `config snapshot/search/get/set/delete` and `server state/weight`
57
+ (dry-run + double-confirm, executed through the governed twins so CLI writes
58
+ are audited + undo-recorded), `secret` management, and a `doctor`
59
+ connectivity check (health/info probe per platform).
60
+
61
+ ### Known limitations
62
+
63
+ - Preview / mock-only: Traefik, Caddy and HAProxy responses are mocked and
64
+ need live verification; the modelled REST paths especially (the haproxy
65
+ runtime-server weight write in particular).
66
+ - haproxy host/path routing lives in haproxy.cfg ACLs and is not statically
67
+ analysed; `route_conflict_analysis` covers dead-backend detection there.
68
+ - **Missing a capability? Open an issue or PR** — contributions welcome.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wei <zhouwei008@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,213 @@
1
+ Metadata-Version: 2.4
2
+ Name: proxy-aiops
3
+ Version: 0.1.0
4
+ Summary: Governed AI-ops for Traefik + Caddy + HAProxy reverse proxies / load balancers: routes, services, upstream health, TLS cert expiry sweep, 5xx error-rate RCA, route conflict analysis, and governed writes (caddy config, haproxy server state/weight) with a built-in governance harness (audit, budget, undo, risk tiers)
5
+ Author-email: wei <zhouwei008@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: cryptography>=42.0
10
+ Requires-Dist: httpx<1.0,>=0.27
11
+ Requires-Dist: mcp[cli]<2.0,>=1.10
12
+ Requires-Dist: pyyaml<7.0,>=6.0
13
+ Requires-Dist: rich<16.0,>=13.0
14
+ Requires-Dist: typer<1.0,>=0.12
15
+ Description-Content-Type: text/markdown
16
+
17
+ <!-- mcp-name: io.github.AIops-tools/proxy-aiops -->
18
+
19
+ # Proxy AIops (preview)
20
+
21
+ Governed, audited AI-ops for **Traefik**, **Caddy** and **HAProxy** reverse proxies / load balancers — for AI agents (via MCP) and humans (via CLI).
22
+
23
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by Traefik Labs, the Caddy project, HAProxy Technologies, or the HAProxy project.** Traefik, Caddy and HAProxy are trademarks of their respective owners. MIT licensed.
24
+
25
+ proxy-aiops speaks to three proxy platforms behind one MCP server — **Traefik**
26
+ (its API under `/api/...`, metrics-text counters via `/metrics`), **Caddy** (the
27
+ admin API, default `localhost:2019`) and **HAProxy** (the Data Plane API v2 under
28
+ `/v2/...`, HTTP Basic auth) — with the **same tools working on all three**. Each
29
+ target in the config names its own `platform`; a name-keyed platform registry
30
+ selects the API shape (auth + resource paths), and an explicit **support matrix**
31
+ raises teaching errors for ops a platform genuinely cannot do — e.g. Traefik
32
+ writes point you at its providers (file, container labels, orchestrator CRDs), never
33
+ a silent no-op.
34
+
35
+ Every tool runs through a **built-in governance harness** (vendored, zero external
36
+ dependency): audit log, token/call budget with runaway circuit-breaker, graduated
37
+ risk-tier approval, undo-token recording, and output sanitisation.
38
+
39
+ ## Why this exists
40
+
41
+ - **One server, three proxies** — Traefik, Caddy and HAProxy in a mixed edge,
42
+ spoken to through identical tool names. Adding another proxy later is a new
43
+ platform descriptor, not a rewrite.
44
+ - **Read the whole edge** — version, entrypoints/listeners, routes (routers /
45
+ caddy routes / frontends) with parsed hosts+paths, services and server-level
46
+ upstream health, middlewares, TLS domain inventory, traffic/error counters,
47
+ and the live config tree (snapshot + search).
48
+ - **Flagship RCA analyses** — transparent heuristics that show their numbers,
49
+ never a black-box verdict: `backend_health_rca` (down upstreams → cause class
50
+ L4/L6/L7/DNS/maint + action), `cert_expiry_sweep` (days-to-expiry buckets +
51
+ per-platform renewal hints), `error_rate_rca` (5xx share vs the fleet
52
+ baseline, dominant code → 502/503/504/500 cause), and
53
+ `route_conflict_analysis` (shadowed routes, dead routes, redirect loops).
54
+ - **Governed writes** — caddy config `set` / `delete` / full `load` (the prior
55
+ subtree/config is fetched first, so the recorded undo replays a real restore)
56
+ and haproxy runtime server `state` (ready/drain/maint) and `weight` (undo
57
+ restores the prior value) — all with `dry_run` previews; delete/load are
58
+ **risk=high** behind an approver gate.
59
+
60
+ ## Tool inventory (26 tools)
61
+
62
+ | Domain | Tools | # | Kind |
63
+ |--------|-------|:-:|------|
64
+ | **Status** | `proxy_overview`, `version_info`, `list_entrypoints` | 3 | read |
65
+ | **Routes** | `list_routes`, `route_detail`, `find_route` | 3 | read |
66
+ | **Services** | `list_services`, `service_detail`, `list_upstreams`, `upstream_detail`, `list_middlewares` | 5 | read |
67
+ | **Certificates** | `list_certificates` | 1 | read |
68
+ | **Traffic** | `traffic_stats`, `error_counters` | 2 | read |
69
+ | **Config** | `config_snapshot`, `search_config`, `get_config_value` | 3 | read |
70
+ | **Flagship analyses** | `backend_health_rca`, `cert_expiry_sweep`, `error_rate_rca`, `route_conflict_analysis` | 4 | read |
71
+ | **Writes (caddy)** | `set_config_value` | 1 | write (**med**) |
72
+ | **Writes (caddy)** | `delete_config_path`, `load_config` | 2 | write (**high**) |
73
+ | **Writes (haproxy)** | `set_server_state`, `set_server_weight` | 2 | write (**med**) |
74
+
75
+ Reversible writes record an inverse **undo descriptor** built from the real fetched
76
+ before-state (`set_config_value` restores the prior subtree; `delete_config_path`
77
+ re-creates it; `load_config` re-loads the snapshotted config; server state/weight
78
+ restore the prior value). The undo params match each tool's own signature, so the
79
+ descriptor replays as-is.
80
+
81
+ ### Per-platform support matrix
82
+
83
+ | Capability | traefik | caddy | haproxy |
84
+ |------------|:-------:|:-----:|:-------:|
85
+ | Routes / services / upstream health | ✅ | ✅ | ✅ |
86
+ | Middlewares list | ✅ | teaching note (inline handlers) | teaching note (haproxy.cfg) |
87
+ | TLS cert inventory + expiry sweep | ✅ | ✅ | teaching note (.pem files) |
88
+ | Error counters / error-rate RCA | ✅ (/metrics) | teaching note (no per-route counters) | ✅ (stats) |
89
+ | Config snapshot / search | ✅ (rawdata, read-only) | ✅ | teaching note |
90
+ | Config writes | teaching error → edit the **provider** | ✅ (the write surface) | teaching error → runtime writes |
91
+ | Runtime server state / weight | teaching error → provider | teaching error → config tree | ✅ |
92
+
93
+ Unsupported combinations **raise a teaching error that says what to use instead**
94
+ — never a silent empty result.
95
+
96
+ ## Install
97
+
98
+ ```bash
99
+ uv tool install proxy-aiops # or: pipx install proxy-aiops
100
+ ```
101
+
102
+ ## Quick start
103
+
104
+ ```bash
105
+ proxy-aiops init # wizard: pick platform (traefik/caddy/haproxy) + optional encrypted secret
106
+ proxy-aiops doctor # verify config, secrets, and connectivity
107
+ proxy-aiops overview # one-shot: version + route/service counts + upstream health
108
+ proxy-aiops routes list # normalised route table
109
+ proxy-aiops services upstreams # server-level upstream health
110
+ proxy-aiops analyze health # backend/upstream health RCA
111
+ proxy-aiops analyze errors # 5xx error-rate RCA
112
+ proxy-aiops analyze conflicts # shadowed/dead routes, redirect loops
113
+ proxy-aiops certs --sweep # TLS cert expiry sweep (traefik/caddy)
114
+ proxy-aiops server state app web1 drain --dry-run # governed haproxy write preview
115
+ proxy-aiops config set apps/http/servers/srv0 '{"listen":[":8080"]}' --dry-run
116
+ ```
117
+
118
+ Run the MCP server (stdio) for an agent:
119
+
120
+ ```bash
121
+ proxy-aiops mcp # or: proxy-aiops-mcp
122
+ ```
123
+
124
+ ### MCP client config
125
+
126
+ ```json
127
+ {
128
+ "mcpServers": {
129
+ "proxy-aiops": {
130
+ "command": "uvx",
131
+ "args": ["--from", "proxy-aiops", "proxy-aiops-mcp"],
132
+ "env": { "PROXY_AIOPS_MASTER_PASSWORD": "your-master-password" }
133
+ }
134
+ }
135
+ }
136
+ ```
137
+
138
+ > **Env-block caveat**: the `env` block is only needed when a credential is
139
+ > stored (haproxy always; traefik/caddy only behind Basic auth). MCP clients do
140
+ > **not** inherit your shell profile — set `PROXY_AIOPS_MASTER_PASSWORD` (and
141
+ > `PROXY_AIOPS_CONFIG` / `PROXY_AIOPS_HOME` if you relocated them) explicitly in
142
+ > the client config, or the server cannot unlock `secrets.enc`.
143
+
144
+ ## Configuration
145
+
146
+ `~/.proxy-aiops/config.yaml` (non-secret connection details only):
147
+
148
+ ```yaml
149
+ targets:
150
+ - name: edge1
151
+ platform: traefik # traefik | caddy | haproxy
152
+ base_url: http://192.0.2.10:8080
153
+ verify_ssl: true
154
+ - name: caddy1
155
+ platform: caddy
156
+ base_url: http://127.0.0.1:2019
157
+ - name: lb1
158
+ platform: haproxy
159
+ base_url: http://192.0.2.20:5555
160
+ username: dpapi # Data Plane API user
161
+ ```
162
+
163
+ The **secret** — the HAProxy Data Plane API password, or an optional Basic-auth
164
+ password in front of Traefik/Caddy — is stored **encrypted** in
165
+ `~/.proxy-aiops/secrets.enc` (Fernet + scrypt-derived key), never plaintext on
166
+ disk. Traefik and Caddy commonly run unauthenticated on localhost, so their
167
+ secret is **optional** (like a local socket); HAProxy's is required. Set it with
168
+ `proxy-aiops secret set <target>` or the `init` wizard. The store is unlocked by
169
+ a master password from `PROXY_AIOPS_MASTER_PASSWORD` (non-interactive/MCP/CI) or
170
+ an interactive prompt (CLI on a TTY). A legacy plaintext env var
171
+ `PROXY_<TARGET>_SECRET` is honoured as a fallback (migrate with
172
+ `proxy-aiops secret migrate`).
173
+
174
+ ## Governance
175
+
176
+ Every MCP tool is wrapped by `@governed_tool`:
177
+
178
+ - **Audit** — every call is logged to `~/.proxy-aiops/audit.db` (tool, params with
179
+ secrets redacted, status, duration, risk tier, approver, rationale).
180
+ - **Budget / runaway guard** — per-process token/call caps and a repeat-call circuit
181
+ breaker (`PROXY_MAX_TOOL_CALLS`, `PROXY_RUNAWAY_MAX`, …).
182
+ - **Graduated risk tiers — secure by default** — with no
183
+ `~/.proxy-aiops/rules.yaml`, high-risk writes (`delete_config_path`,
184
+ `load_config`) require an approver: set `PROXY_AUDIT_APPROVED_BY` (and
185
+ `PROXY_AUDIT_RATIONALE`) before they will run. `init` seeds a starter
186
+ rules.yaml; an operator-authored rules file is honoured as-is.
187
+ - **Undo recording** — reversible writes record an inverse descriptor to
188
+ `~/.proxy-aiops/undo.db` from the fetched before-state (recording only; an
189
+ external orchestrator executes it). Undo params match the target tool's own
190
+ signature, so the descriptor replays as-is.
191
+ - **Sanitisation** — all proxy-returned text is bounded + control-character
192
+ sanitised before it reaches the agent.
193
+
194
+ ## Preview status
195
+
196
+ - **Platforms**: Traefik (API + /metrics), Caddy (admin API), HAProxy (Data Plane
197
+ API v2).
198
+ - **Preview — mock-validated only. Not run against a live proxy.** All behaviour is
199
+ validated against mocked JSON/metrics responses; the concrete REST paths are
200
+ modelled from each project's public API and need live verification. All three
201
+ platforms are free and self-hostable (a small container-compose lab with
202
+ traefik + caddy + haproxy/dataplaneapi is a one-evening setup), so
203
+ `proxy-aiops doctor` — a health/info probe per platform — is the fastest
204
+ live check.
205
+ - **Routing note**: this tool operates reverse proxies / load balancers. Do NOT
206
+ use it for firewall rules — use firewall-aiops.
207
+ - **Missing a capability?** Open an issue or PR at
208
+ [github.com/AIops-tools/Proxy-AIops](https://github.com/AIops-tools/Proxy-AIops)
209
+ — contributions and feedback welcome.
210
+
211
+ ## License
212
+
213
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,197 @@
1
+ <!-- mcp-name: io.github.AIops-tools/proxy-aiops -->
2
+
3
+ # Proxy AIops (preview)
4
+
5
+ Governed, audited AI-ops for **Traefik**, **Caddy** and **HAProxy** reverse proxies / load balancers — for AI agents (via MCP) and humans (via CLI).
6
+
7
+ > **Disclaimer**: Community-maintained open-source project. **Not affiliated with, endorsed by, or sponsored by Traefik Labs, the Caddy project, HAProxy Technologies, or the HAProxy project.** Traefik, Caddy and HAProxy are trademarks of their respective owners. MIT licensed.
8
+
9
+ proxy-aiops speaks to three proxy platforms behind one MCP server — **Traefik**
10
+ (its API under `/api/...`, metrics-text counters via `/metrics`), **Caddy** (the
11
+ admin API, default `localhost:2019`) and **HAProxy** (the Data Plane API v2 under
12
+ `/v2/...`, HTTP Basic auth) — with the **same tools working on all three**. Each
13
+ target in the config names its own `platform`; a name-keyed platform registry
14
+ selects the API shape (auth + resource paths), and an explicit **support matrix**
15
+ raises teaching errors for ops a platform genuinely cannot do — e.g. Traefik
16
+ writes point you at its providers (file, container labels, orchestrator CRDs), never
17
+ a silent no-op.
18
+
19
+ Every tool runs through a **built-in governance harness** (vendored, zero external
20
+ dependency): audit log, token/call budget with runaway circuit-breaker, graduated
21
+ risk-tier approval, undo-token recording, and output sanitisation.
22
+
23
+ ## Why this exists
24
+
25
+ - **One server, three proxies** — Traefik, Caddy and HAProxy in a mixed edge,
26
+ spoken to through identical tool names. Adding another proxy later is a new
27
+ platform descriptor, not a rewrite.
28
+ - **Read the whole edge** — version, entrypoints/listeners, routes (routers /
29
+ caddy routes / frontends) with parsed hosts+paths, services and server-level
30
+ upstream health, middlewares, TLS domain inventory, traffic/error counters,
31
+ and the live config tree (snapshot + search).
32
+ - **Flagship RCA analyses** — transparent heuristics that show their numbers,
33
+ never a black-box verdict: `backend_health_rca` (down upstreams → cause class
34
+ L4/L6/L7/DNS/maint + action), `cert_expiry_sweep` (days-to-expiry buckets +
35
+ per-platform renewal hints), `error_rate_rca` (5xx share vs the fleet
36
+ baseline, dominant code → 502/503/504/500 cause), and
37
+ `route_conflict_analysis` (shadowed routes, dead routes, redirect loops).
38
+ - **Governed writes** — caddy config `set` / `delete` / full `load` (the prior
39
+ subtree/config is fetched first, so the recorded undo replays a real restore)
40
+ and haproxy runtime server `state` (ready/drain/maint) and `weight` (undo
41
+ restores the prior value) — all with `dry_run` previews; delete/load are
42
+ **risk=high** behind an approver gate.
43
+
44
+ ## Tool inventory (26 tools)
45
+
46
+ | Domain | Tools | # | Kind |
47
+ |--------|-------|:-:|------|
48
+ | **Status** | `proxy_overview`, `version_info`, `list_entrypoints` | 3 | read |
49
+ | **Routes** | `list_routes`, `route_detail`, `find_route` | 3 | read |
50
+ | **Services** | `list_services`, `service_detail`, `list_upstreams`, `upstream_detail`, `list_middlewares` | 5 | read |
51
+ | **Certificates** | `list_certificates` | 1 | read |
52
+ | **Traffic** | `traffic_stats`, `error_counters` | 2 | read |
53
+ | **Config** | `config_snapshot`, `search_config`, `get_config_value` | 3 | read |
54
+ | **Flagship analyses** | `backend_health_rca`, `cert_expiry_sweep`, `error_rate_rca`, `route_conflict_analysis` | 4 | read |
55
+ | **Writes (caddy)** | `set_config_value` | 1 | write (**med**) |
56
+ | **Writes (caddy)** | `delete_config_path`, `load_config` | 2 | write (**high**) |
57
+ | **Writes (haproxy)** | `set_server_state`, `set_server_weight` | 2 | write (**med**) |
58
+
59
+ Reversible writes record an inverse **undo descriptor** built from the real fetched
60
+ before-state (`set_config_value` restores the prior subtree; `delete_config_path`
61
+ re-creates it; `load_config` re-loads the snapshotted config; server state/weight
62
+ restore the prior value). The undo params match each tool's own signature, so the
63
+ descriptor replays as-is.
64
+
65
+ ### Per-platform support matrix
66
+
67
+ | Capability | traefik | caddy | haproxy |
68
+ |------------|:-------:|:-----:|:-------:|
69
+ | Routes / services / upstream health | ✅ | ✅ | ✅ |
70
+ | Middlewares list | ✅ | teaching note (inline handlers) | teaching note (haproxy.cfg) |
71
+ | TLS cert inventory + expiry sweep | ✅ | ✅ | teaching note (.pem files) |
72
+ | Error counters / error-rate RCA | ✅ (/metrics) | teaching note (no per-route counters) | ✅ (stats) |
73
+ | Config snapshot / search | ✅ (rawdata, read-only) | ✅ | teaching note |
74
+ | Config writes | teaching error → edit the **provider** | ✅ (the write surface) | teaching error → runtime writes |
75
+ | Runtime server state / weight | teaching error → provider | teaching error → config tree | ✅ |
76
+
77
+ Unsupported combinations **raise a teaching error that says what to use instead**
78
+ — never a silent empty result.
79
+
80
+ ## Install
81
+
82
+ ```bash
83
+ uv tool install proxy-aiops # or: pipx install proxy-aiops
84
+ ```
85
+
86
+ ## Quick start
87
+
88
+ ```bash
89
+ proxy-aiops init # wizard: pick platform (traefik/caddy/haproxy) + optional encrypted secret
90
+ proxy-aiops doctor # verify config, secrets, and connectivity
91
+ proxy-aiops overview # one-shot: version + route/service counts + upstream health
92
+ proxy-aiops routes list # normalised route table
93
+ proxy-aiops services upstreams # server-level upstream health
94
+ proxy-aiops analyze health # backend/upstream health RCA
95
+ proxy-aiops analyze errors # 5xx error-rate RCA
96
+ proxy-aiops analyze conflicts # shadowed/dead routes, redirect loops
97
+ proxy-aiops certs --sweep # TLS cert expiry sweep (traefik/caddy)
98
+ proxy-aiops server state app web1 drain --dry-run # governed haproxy write preview
99
+ proxy-aiops config set apps/http/servers/srv0 '{"listen":[":8080"]}' --dry-run
100
+ ```
101
+
102
+ Run the MCP server (stdio) for an agent:
103
+
104
+ ```bash
105
+ proxy-aiops mcp # or: proxy-aiops-mcp
106
+ ```
107
+
108
+ ### MCP client config
109
+
110
+ ```json
111
+ {
112
+ "mcpServers": {
113
+ "proxy-aiops": {
114
+ "command": "uvx",
115
+ "args": ["--from", "proxy-aiops", "proxy-aiops-mcp"],
116
+ "env": { "PROXY_AIOPS_MASTER_PASSWORD": "your-master-password" }
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ > **Env-block caveat**: the `env` block is only needed when a credential is
123
+ > stored (haproxy always; traefik/caddy only behind Basic auth). MCP clients do
124
+ > **not** inherit your shell profile — set `PROXY_AIOPS_MASTER_PASSWORD` (and
125
+ > `PROXY_AIOPS_CONFIG` / `PROXY_AIOPS_HOME` if you relocated them) explicitly in
126
+ > the client config, or the server cannot unlock `secrets.enc`.
127
+
128
+ ## Configuration
129
+
130
+ `~/.proxy-aiops/config.yaml` (non-secret connection details only):
131
+
132
+ ```yaml
133
+ targets:
134
+ - name: edge1
135
+ platform: traefik # traefik | caddy | haproxy
136
+ base_url: http://192.0.2.10:8080
137
+ verify_ssl: true
138
+ - name: caddy1
139
+ platform: caddy
140
+ base_url: http://127.0.0.1:2019
141
+ - name: lb1
142
+ platform: haproxy
143
+ base_url: http://192.0.2.20:5555
144
+ username: dpapi # Data Plane API user
145
+ ```
146
+
147
+ The **secret** — the HAProxy Data Plane API password, or an optional Basic-auth
148
+ password in front of Traefik/Caddy — is stored **encrypted** in
149
+ `~/.proxy-aiops/secrets.enc` (Fernet + scrypt-derived key), never plaintext on
150
+ disk. Traefik and Caddy commonly run unauthenticated on localhost, so their
151
+ secret is **optional** (like a local socket); HAProxy's is required. Set it with
152
+ `proxy-aiops secret set <target>` or the `init` wizard. The store is unlocked by
153
+ a master password from `PROXY_AIOPS_MASTER_PASSWORD` (non-interactive/MCP/CI) or
154
+ an interactive prompt (CLI on a TTY). A legacy plaintext env var
155
+ `PROXY_<TARGET>_SECRET` is honoured as a fallback (migrate with
156
+ `proxy-aiops secret migrate`).
157
+
158
+ ## Governance
159
+
160
+ Every MCP tool is wrapped by `@governed_tool`:
161
+
162
+ - **Audit** — every call is logged to `~/.proxy-aiops/audit.db` (tool, params with
163
+ secrets redacted, status, duration, risk tier, approver, rationale).
164
+ - **Budget / runaway guard** — per-process token/call caps and a repeat-call circuit
165
+ breaker (`PROXY_MAX_TOOL_CALLS`, `PROXY_RUNAWAY_MAX`, …).
166
+ - **Graduated risk tiers — secure by default** — with no
167
+ `~/.proxy-aiops/rules.yaml`, high-risk writes (`delete_config_path`,
168
+ `load_config`) require an approver: set `PROXY_AUDIT_APPROVED_BY` (and
169
+ `PROXY_AUDIT_RATIONALE`) before they will run. `init` seeds a starter
170
+ rules.yaml; an operator-authored rules file is honoured as-is.
171
+ - **Undo recording** — reversible writes record an inverse descriptor to
172
+ `~/.proxy-aiops/undo.db` from the fetched before-state (recording only; an
173
+ external orchestrator executes it). Undo params match the target tool's own
174
+ signature, so the descriptor replays as-is.
175
+ - **Sanitisation** — all proxy-returned text is bounded + control-character
176
+ sanitised before it reaches the agent.
177
+
178
+ ## Preview status
179
+
180
+ - **Platforms**: Traefik (API + /metrics), Caddy (admin API), HAProxy (Data Plane
181
+ API v2).
182
+ - **Preview — mock-validated only. Not run against a live proxy.** All behaviour is
183
+ validated against mocked JSON/metrics responses; the concrete REST paths are
184
+ modelled from each project's public API and need live verification. All three
185
+ platforms are free and self-hostable (a small container-compose lab with
186
+ traefik + caddy + haproxy/dataplaneapi is a one-evening setup), so
187
+ `proxy-aiops doctor` — a health/info probe per platform — is the fastest
188
+ live check.
189
+ - **Routing note**: this tool operates reverse proxies / load balancers. Do NOT
190
+ use it for firewall rules — use firewall-aiops.
191
+ - **Missing a capability?** Open an issue or PR at
192
+ [github.com/AIops-tools/Proxy-AIops](https://github.com/AIops-tools/Proxy-AIops)
193
+ — contributions and feedback welcome.
194
+
195
+ ## License
196
+
197
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,61 @@
1
+ # Proxy AIops v0.1.0 — preview
2
+
3
+ Governed AI-ops for **Traefik**, **Caddy** and **HAProxy** reverse proxies /
4
+ load balancers for AI agents, with a built-in governance harness (audit,
5
+ policy, token/runaway budget, undo-token recording, graduated risk tiers) and
6
+ an encrypted credential store. Standalone — no external skill-family
7
+ dependency. One MCP server spans all three platforms: a per-target `platform`
8
+ field selects the API shape, and the same 26 tools work on Traefik (API +
9
+ `/metrics`), Caddy (admin API) and HAProxy (Data Plane API v2, HTTP Basic).
10
+
11
+ > **Not affiliated with, endorsed by, or sponsored by Traefik Labs, the Caddy
12
+ > project, HAProxy Technologies, or the HAProxy project.** Traefik, Caddy and
13
+ > HAProxy are trademarks of their respective owners.
14
+
15
+ > **Preview / mock-only.** All behaviour is validated against mocked JSON /
16
+ > metrics-text responses; it has **not** been run against a live proxy. The
17
+ > concrete REST paths are modelled from each project's public API and need
18
+ > live verification. All three platforms are free/self-hostable, so a small
19
+ > lab is the easiest live check — `proxy-aiops doctor` is the fastest.
20
+
21
+ ## Highlights
22
+
23
+ - **26 MCP tools** (21 read, 5 write), every one wrapped with `@governed_tool`:
24
+ - **Status** — `proxy_overview`, `version_info`, `list_entrypoints`.
25
+ - **Routes** — `list_routes` (hosts/paths normalised across platforms),
26
+ `route_detail`, `find_route`.
27
+ - **Services** — `list_services`, `service_detail`, `list_upstreams`,
28
+ `upstream_detail`, `list_middlewares`.
29
+ - **Certificates** — `list_certificates` (+ bounded live expiry probe).
30
+ - **Traffic** — `traffic_stats`, `error_counters`.
31
+ - **Config** — `config_snapshot`, `search_config`, `get_config_value`.
32
+ - **Writes** — caddy `set_config_value` / `delete_config_path` /
33
+ `load_config` (prior config captured → replayable undo), haproxy
34
+ `set_server_state` (ready/drain/maint) / `set_server_weight` (undo
35
+ restores the prior value). High-risk writes gate on an approver.
36
+ - **Flagship analyses** (transparent heuristics that show their numbers):
37
+ - `backend_health_rca` — down upstreams per service with the failure class
38
+ (connection refused / L4 timeout / TLS / L7 check / DNS / maint) + action.
39
+ - `cert_expiry_sweep` — days-to-expiry buckets (expired / critical /
40
+ warning / ok) + per-platform renewal hints.
41
+ - `error_rate_rca` — per-service 5xx share vs the fleet baseline; the
42
+ dominant code maps to a cause (503 no-upstream / 502 conn-fail /
43
+ 504 timeout / 500 app error).
44
+ - `route_conflict_analysis` — shadowed routes, dead routes (service missing
45
+ or zero servers up), redirect loops.
46
+ - **Support matrix with teaching errors** — ops a platform cannot do fail fast
47
+ with what to use instead (traefik writes → its providers; caddy counters →
48
+ access logs; haproxy certs → the .pem pipeline). Never a silent no-op.
49
+ - **Governance** — audit to `~/.proxy-aiops/audit.db`, budget/runaway guard,
50
+ secure-by-default approver gate for high-risk writes, undo descriptors built
51
+ from the real fetched before-state (replayable as-is), output sanitisation.
52
+
53
+ ## Install
54
+
55
+ ```bash
56
+ uv tool install proxy-aiops
57
+ proxy-aiops init && proxy-aiops doctor
58
+ ```
59
+
60
+ Routing note: this tool operates reverse proxies / load balancers. Do NOT use
61
+ it for firewall rules — use firewall-aiops.