queue-aiops 0.1.0__tar.gz → 0.2.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.
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/CHANGELOG.md +5 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/PKG-INFO +61 -12
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/README.md +60 -11
- queue_aiops-0.2.0/RELEASE_NOTES.md +48 -0
- queue_aiops-0.2.0/docs/VERIFICATION.md +200 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/_shared.py +1 -1
- queue_aiops-0.2.0/mcp_server/server.py +76 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/rabbit_reads.py +16 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/redis_reads.py +12 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/undo.py +13 -2
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/pyproject.toml +1 -1
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/rabbit_cmds.py +28 -4
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/redis_cmds.py +14 -2
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/__init__.py +5 -1
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/decorators.py +12 -0
- queue_aiops-0.2.0/queue_aiops/governance/readonly.py +49 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/sanitize.py +25 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/_util.py +17 -1
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/analysis.py +13 -10
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/rabbit_reads.py +45 -24
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/redis_reads.py +45 -17
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/writes.py +8 -8
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/server.json +3 -3
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/skills/queue-aiops/SKILL.md +106 -37
- queue_aiops-0.2.0/skills/queue-aiops/references/agent-guardrails.md +109 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/skills/queue-aiops/references/capabilities.md +8 -1
- queue_aiops-0.2.0/tests/test_cli_rabbit_writes.py +164 -0
- queue_aiops-0.2.0/tests/test_cli_reads.py +249 -0
- queue_aiops-0.2.0/tests/test_cli_secret.py +111 -0
- queue_aiops-0.2.0/tests/test_connection.py +241 -0
- queue_aiops-0.2.0/tests/test_gov_audit.py +292 -0
- queue_aiops-0.2.0/tests/test_gov_decorators.py +452 -0
- queue_aiops-0.2.0/tests/test_gov_patterns.py +417 -0
- queue_aiops-0.2.0/tests/test_gov_policy.py +415 -0
- queue_aiops-0.2.0/tests/test_mcp_reads.py +211 -0
- queue_aiops-0.2.0/tests/test_optional_fields.py +184 -0
- queue_aiops-0.2.0/tests/test_readonly.py +142 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_reads.py +2 -1
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/uv.lock +1 -1
- queue_aiops-0.1.0/RELEASE_NOTES.md +0 -33
- queue_aiops-0.1.0/mcp_server/server.py +0 -38
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/.github/workflows/mcp-publish.yml +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/.github/workflows/publish.yml +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/.gitignore +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/LICENSE +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/SECURITY.md +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/__init__.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/__init__.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/analysis.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/overview.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/mcp_server/tools/writes.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/__init__.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/__init__.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/_common.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/_root.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/analyze.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/doctor.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/init.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/overview.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/secret.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/cli/undo.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/config.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/connection.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/doctor.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/audit.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/budget.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/paths.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/patterns.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/policy.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/governance/undo.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/__init__.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/ops/overview.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/platform.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/queue_aiops/secretstore.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/skills/queue-aiops/references/cli-reference.md +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/skills/queue-aiops/references/setup-guide.md +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/smithery.yaml +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/conftest.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/fakes.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_analysis.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_cli_writes.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_doctor.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_governance_persistence.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_init.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_platform.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_secretstore.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_smoke.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_undo_executor.py +0 -0
- {queue_aiops-0.1.0 → queue_aiops-0.2.0}/tests/test_writes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: queue-aiops
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Governed AI-ops for redis + rabbitmq: memory-pressure/latency/queue-backlog/connection-churn RCAs, slowlog and SCAN-budgeted big-key sampling, queues/policies/nodes, and governed writes (config set, client kill, purge/delete queue, policies) with a built-in governance harness (audit, budget, undo, risk tiers)
|
|
5
5
|
Author-email: wei <zhouwei008@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -15,7 +15,9 @@ Requires-Dist: rich<16.0,>=13.0
|
|
|
15
15
|
Requires-Dist: typer<1.0,>=0.12
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
<!-- mcp-name: io.github.AIops-tools/queue-aiops -->
|
|
19
|
+
|
|
20
|
+
# Queue AIops
|
|
19
21
|
|
|
20
22
|
**Governed AI-ops for redis + rabbitmq.** queue-aiops is for the team running
|
|
21
23
|
their own cache and message broker — a redis that "suddenly eats memory", a
|
|
@@ -31,9 +33,10 @@ by the built-in governance harness.
|
|
|
31
33
|
> with, endorsed by, or sponsored by the Redis or RabbitMQ projects or their
|
|
32
34
|
> respective owners.** Redis and RabbitMQ are trademarks of their respective owners.
|
|
33
35
|
>
|
|
34
|
-
> **
|
|
35
|
-
> redis and rabbitmq are free/self-hostable (one lab container
|
|
36
|
-
> check is easy — `queue-aiops doctor` is the fastest
|
|
36
|
+
> **Verification**: behaviour is covered by a mock-based test suite; not yet validated
|
|
37
|
+
> against live brokers. Both redis and rabbitmq are free/self-hostable (one lab container
|
|
38
|
+
> or package install each), so a lab check is easy — `queue-aiops doctor` is the fastest
|
|
39
|
+
> live probe, and [docs/VERIFICATION.md](docs/VERIFICATION.md) is the checklist.
|
|
37
40
|
|
|
38
41
|
## Quick start
|
|
39
42
|
|
|
@@ -56,6 +59,46 @@ queue-aiops redis bigkeys # SCAN-budgeted big-key sample (never KEYS *)
|
|
|
56
59
|
queue-aiops rabbitmq queues # deepest backlog first
|
|
57
60
|
```
|
|
58
61
|
|
|
62
|
+
## Security: read-only mode
|
|
63
|
+
|
|
64
|
+
This tool is meant to be handed to an AI agent, so its safety story is enforced
|
|
65
|
+
by the server rather than requested in a prompt:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
export QUEUE_READ_ONLY=1
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
With that set, the **8 write tools are never registered**. An MCP client
|
|
72
|
+
lists **20 tools instead of 28** — the writes are not hidden, not
|
|
73
|
+
gated behind a flag, and not merely refused when called. They are absent from
|
|
74
|
+
the session. A model cannot invoke a tool it was never offered, and cannot be
|
|
75
|
+
argued into one.
|
|
76
|
+
|
|
77
|
+
That distinction is the whole point. A tool that exists but refuses still invites
|
|
78
|
+
retry loops and "I'll describe the call instead" behaviour from smaller models,
|
|
79
|
+
and it leaves a reviewer trusting a promise. An absent tool is a fact you can
|
|
80
|
+
check: connect, list the tools, and see that the writes are not there.
|
|
81
|
+
|
|
82
|
+
Enforcement is two layers deep, so the switch cannot be sidestepped by changing
|
|
83
|
+
entry point:
|
|
84
|
+
|
|
85
|
+
| Layer | What it does | Covers |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `@governed_tool` harness | refuses every non-read operation outright | MCP, CLI, and in-process callers |
|
|
88
|
+
| MCP registration | write tools are removed from `list_tools()` | anything speaking MCP |
|
|
89
|
+
|
|
90
|
+
Read operations are unaffected, and every call is still audited to
|
|
91
|
+
`~/.queue-aiops/audit.db`.
|
|
92
|
+
|
|
93
|
+
> The read/write split is derived from each tool's declared `risk_level`, and a
|
|
94
|
+
> test asserts that this never disagrees with the `[READ]`/`[WRITE]` tag in the
|
|
95
|
+
> tool's own documentation — so a write can't quietly present itself as a read.
|
|
96
|
+
|
|
97
|
+
Running a smaller / local model? See
|
|
98
|
+
[agent-guardrails.md](skills/queue-aiops/references/agent-guardrails.md) — it lists
|
|
99
|
+
the guardrails this tool now enforces for you (so you don't spend prompt budget
|
|
100
|
+
restating them) and gives a ready-made system prompt for what's left.
|
|
101
|
+
|
|
59
102
|
## Support scope
|
|
60
103
|
|
|
61
104
|
| Platform | Protocol | Coverage |
|
|
@@ -63,7 +106,7 @@ queue-aiops rabbitmq queues # deepest backlog first
|
|
|
63
106
|
| **redis** (5.x–7.x wire protocol via `redis` Python client) | RESP, password optional, TLS optional | INFO (server/memory/clients/stats/persistence/keyspace), SLOWLOG, CLIENT LIST/KILL, CONFIG GET/SET, MEMORY STATS/USAGE, SCAN-budgeted big-key sampling, DBSIZE, PING |
|
|
64
107
|
| **rabbitmq** (management plugin HTTP API) | HTTP(S), Basic auth | /api/overview, /api/queues (+ per-vhost, detail, purge, declare, delete), /api/connections, /api/channels, /api/consumers, /api/policies (get/set/delete), /api/nodes |
|
|
65
108
|
|
|
66
|
-
**
|
|
109
|
+
**28 MCP tools** — 20 reads (incl. 4 flagship RCAs) + 8 governed writes.
|
|
67
110
|
|
|
68
111
|
| Group | Tools | R/W |
|
|
69
112
|
|-------|-------|:---:|
|
|
@@ -73,6 +116,7 @@ queue-aiops rabbitmq queues # deepest backlog first
|
|
|
73
116
|
| Flagship RCAs | redis_memory_pressure_rca, redis_latency_rca, rabbitmq_queue_backlog_rca, connection_churn_analysis | read |
|
|
74
117
|
| Writes (medium) | redis_config_set, redis_kill_client, declare_queue, set_policy, delete_policy | write |
|
|
75
118
|
| Writes (**high**) | purge_queue, delete_queue | write |
|
|
119
|
+
| Undo | undo_list, undo_apply | read / write |
|
|
76
120
|
|
|
77
121
|
The four RCAs are transparent heuristics that report their numbers — thresholds
|
|
78
122
|
are named constants, every finding carries its evidence, never a black-box
|
|
@@ -148,12 +192,17 @@ queue-aiops analyze memory|latency|backlog|churn
|
|
|
148
192
|
|
|
149
193
|
## Verification status
|
|
150
194
|
|
|
151
|
-
|
|
152
|
-
broker needed)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
195
|
+
**Mock-validated; not yet run against live brokers.** The full test suite runs against
|
|
196
|
+
mocked clients (no live broker needed): every module imports, every MCP tool carries the
|
|
197
|
+
governance marker, the four flagship RCAs are unit-tested against synthetic telemetry,
|
|
198
|
+
and reversible writes are asserted to record the correct inverse undo descriptor. The
|
|
199
|
+
REST paths and `INFO` field names are modelled from the public docs of both platforms
|
|
200
|
+
and have not been exercised against a real broker.
|
|
201
|
+
|
|
202
|
+
Both platforms are trivially self-hostable, so `queue-aiops doctor` against a local lab
|
|
203
|
+
redis instance / rabbitmq broker (management plugin enabled) is the quickest live check.
|
|
204
|
+
[docs/VERIFICATION.md](docs/VERIFICATION.md) is the full checklist a live run must
|
|
205
|
+
satisfy.
|
|
157
206
|
|
|
158
207
|
## Contributing
|
|
159
208
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- mcp-name: io.github.AIops-tools/queue-aiops -->
|
|
2
|
+
|
|
3
|
+
# Queue AIops
|
|
2
4
|
|
|
3
5
|
**Governed AI-ops for redis + rabbitmq.** queue-aiops is for the team running
|
|
4
6
|
their own cache and message broker — a redis that "suddenly eats memory", a
|
|
@@ -14,9 +16,10 @@ by the built-in governance harness.
|
|
|
14
16
|
> with, endorsed by, or sponsored by the Redis or RabbitMQ projects or their
|
|
15
17
|
> respective owners.** Redis and RabbitMQ are trademarks of their respective owners.
|
|
16
18
|
>
|
|
17
|
-
> **
|
|
18
|
-
> redis and rabbitmq are free/self-hostable (one lab container
|
|
19
|
-
> check is easy — `queue-aiops doctor` is the fastest
|
|
19
|
+
> **Verification**: behaviour is covered by a mock-based test suite; not yet validated
|
|
20
|
+
> against live brokers. Both redis and rabbitmq are free/self-hostable (one lab container
|
|
21
|
+
> or package install each), so a lab check is easy — `queue-aiops doctor` is the fastest
|
|
22
|
+
> live probe, and [docs/VERIFICATION.md](docs/VERIFICATION.md) is the checklist.
|
|
20
23
|
|
|
21
24
|
## Quick start
|
|
22
25
|
|
|
@@ -39,6 +42,46 @@ queue-aiops redis bigkeys # SCAN-budgeted big-key sample (never KEYS *)
|
|
|
39
42
|
queue-aiops rabbitmq queues # deepest backlog first
|
|
40
43
|
```
|
|
41
44
|
|
|
45
|
+
## Security: read-only mode
|
|
46
|
+
|
|
47
|
+
This tool is meant to be handed to an AI agent, so its safety story is enforced
|
|
48
|
+
by the server rather than requested in a prompt:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
export QUEUE_READ_ONLY=1
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
With that set, the **8 write tools are never registered**. An MCP client
|
|
55
|
+
lists **20 tools instead of 28** — the writes are not hidden, not
|
|
56
|
+
gated behind a flag, and not merely refused when called. They are absent from
|
|
57
|
+
the session. A model cannot invoke a tool it was never offered, and cannot be
|
|
58
|
+
argued into one.
|
|
59
|
+
|
|
60
|
+
That distinction is the whole point. A tool that exists but refuses still invites
|
|
61
|
+
retry loops and "I'll describe the call instead" behaviour from smaller models,
|
|
62
|
+
and it leaves a reviewer trusting a promise. An absent tool is a fact you can
|
|
63
|
+
check: connect, list the tools, and see that the writes are not there.
|
|
64
|
+
|
|
65
|
+
Enforcement is two layers deep, so the switch cannot be sidestepped by changing
|
|
66
|
+
entry point:
|
|
67
|
+
|
|
68
|
+
| Layer | What it does | Covers |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `@governed_tool` harness | refuses every non-read operation outright | MCP, CLI, and in-process callers |
|
|
71
|
+
| MCP registration | write tools are removed from `list_tools()` | anything speaking MCP |
|
|
72
|
+
|
|
73
|
+
Read operations are unaffected, and every call is still audited to
|
|
74
|
+
`~/.queue-aiops/audit.db`.
|
|
75
|
+
|
|
76
|
+
> The read/write split is derived from each tool's declared `risk_level`, and a
|
|
77
|
+
> test asserts that this never disagrees with the `[READ]`/`[WRITE]` tag in the
|
|
78
|
+
> tool's own documentation — so a write can't quietly present itself as a read.
|
|
79
|
+
|
|
80
|
+
Running a smaller / local model? See
|
|
81
|
+
[agent-guardrails.md](skills/queue-aiops/references/agent-guardrails.md) — it lists
|
|
82
|
+
the guardrails this tool now enforces for you (so you don't spend prompt budget
|
|
83
|
+
restating them) and gives a ready-made system prompt for what's left.
|
|
84
|
+
|
|
42
85
|
## Support scope
|
|
43
86
|
|
|
44
87
|
| Platform | Protocol | Coverage |
|
|
@@ -46,7 +89,7 @@ queue-aiops rabbitmq queues # deepest backlog first
|
|
|
46
89
|
| **redis** (5.x–7.x wire protocol via `redis` Python client) | RESP, password optional, TLS optional | INFO (server/memory/clients/stats/persistence/keyspace), SLOWLOG, CLIENT LIST/KILL, CONFIG GET/SET, MEMORY STATS/USAGE, SCAN-budgeted big-key sampling, DBSIZE, PING |
|
|
47
90
|
| **rabbitmq** (management plugin HTTP API) | HTTP(S), Basic auth | /api/overview, /api/queues (+ per-vhost, detail, purge, declare, delete), /api/connections, /api/channels, /api/consumers, /api/policies (get/set/delete), /api/nodes |
|
|
48
91
|
|
|
49
|
-
**
|
|
92
|
+
**28 MCP tools** — 20 reads (incl. 4 flagship RCAs) + 8 governed writes.
|
|
50
93
|
|
|
51
94
|
| Group | Tools | R/W |
|
|
52
95
|
|-------|-------|:---:|
|
|
@@ -56,6 +99,7 @@ queue-aiops rabbitmq queues # deepest backlog first
|
|
|
56
99
|
| Flagship RCAs | redis_memory_pressure_rca, redis_latency_rca, rabbitmq_queue_backlog_rca, connection_churn_analysis | read |
|
|
57
100
|
| Writes (medium) | redis_config_set, redis_kill_client, declare_queue, set_policy, delete_policy | write |
|
|
58
101
|
| Writes (**high**) | purge_queue, delete_queue | write |
|
|
102
|
+
| Undo | undo_list, undo_apply | read / write |
|
|
59
103
|
|
|
60
104
|
The four RCAs are transparent heuristics that report their numbers — thresholds
|
|
61
105
|
are named constants, every finding carries its evidence, never a black-box
|
|
@@ -131,12 +175,17 @@ queue-aiops analyze memory|latency|backlog|churn
|
|
|
131
175
|
|
|
132
176
|
## Verification status
|
|
133
177
|
|
|
134
|
-
|
|
135
|
-
broker needed)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
178
|
+
**Mock-validated; not yet run against live brokers.** The full test suite runs against
|
|
179
|
+
mocked clients (no live broker needed): every module imports, every MCP tool carries the
|
|
180
|
+
governance marker, the four flagship RCAs are unit-tested against synthetic telemetry,
|
|
181
|
+
and reversible writes are asserted to record the correct inverse undo descriptor. The
|
|
182
|
+
REST paths and `INFO` field names are modelled from the public docs of both platforms
|
|
183
|
+
and have not been exercised against a real broker.
|
|
184
|
+
|
|
185
|
+
Both platforms are trivially self-hostable, so `queue-aiops doctor` against a local lab
|
|
186
|
+
redis instance / rabbitmq broker (management plugin enabled) is the quickest live check.
|
|
187
|
+
[docs/VERIFICATION.md](docs/VERIFICATION.md) is the full checklist a live run must
|
|
188
|
+
satisfy.
|
|
140
189
|
|
|
141
190
|
## Contributing
|
|
142
191
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Release notes — queue-aiops 0.2.0
|
|
2
|
+
|
|
3
|
+
Previous release: 0.1.1.
|
|
4
|
+
|
|
5
|
+
## Headline: read-only mode
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
export QUEUE_READ_ONLY=1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
With this set the **8 write tools are never registered** — an MCP
|
|
12
|
+
client lists **20 tools instead of 28**. The writes are not hidden
|
|
13
|
+
behind a flag and not merely refused on call: they are absent from the session,
|
|
14
|
+
so a model cannot invoke one and cannot be argued into one. For a reviewer this
|
|
15
|
+
is checkable rather than promised — connect, list the tools, and the writes are
|
|
16
|
+
not there.
|
|
17
|
+
|
|
18
|
+
Enforcement is two layers deep: the `@governed_tool` harness refuses every
|
|
19
|
+
non-read operation (covering the CLI and in-process callers too), and the MCP
|
|
20
|
+
server removes write tools from `list_tools()`. Changing entry point does not
|
|
21
|
+
get around it.
|
|
22
|
+
|
|
23
|
+
## BREAKING — return shapes changed
|
|
24
|
+
|
|
25
|
+
This release changes payloads that callers may be parsing. Both changes exist
|
|
26
|
+
to stop a result from misrepresenting itself:
|
|
27
|
+
|
|
28
|
+
1. **Absent fields are now `null`, not `""`.** A missing value and an empty value
|
|
29
|
+
were previously indistinguishable, which invited consumers to invent the
|
|
30
|
+
difference. Keys are still always present — only the value may be null.
|
|
31
|
+
2. **Anything with a `limit` now returns an envelope** —
|
|
32
|
+
`{"<items>": [...], "returned": N, "limit": L, "truncated": bool}`. Truncation is
|
|
33
|
+
*measured* (one extra row is fetched), never inferred from the page happening to
|
|
34
|
+
be full. Where a genuine pre-cap total is knowable it is reported as `total`;
|
|
35
|
+
where it isn't, `total` is deliberately omitted rather than echoing `returned`.
|
|
36
|
+
|
|
37
|
+
## Also in this release
|
|
38
|
+
|
|
39
|
+
- **`docs/VERIFICATION.md`** — what the mock suite actually guarantees, a live
|
|
40
|
+
verification checklist, and the criteria for claiming this tool verified.
|
|
41
|
+
- **`skills/queue-aiops/references/agent-guardrails.md`** — for driving this tool with a
|
|
42
|
+
smaller / local model: which guardrails are now enforced for you, and a
|
|
43
|
+
ready-made system prompt for the rest.
|
|
44
|
+
- Expanded operator playbooks in the skill documentation.
|
|
45
|
+
- The advertised tool count now matches what an MCP client actually lists
|
|
46
|
+
(it includes `undo_list` / `undo_apply`), and a release gate keeps it honest.
|
|
47
|
+
- The `(preview)` label has been dropped. It never meant unreleased; verification
|
|
48
|
+
status now lives in `docs/VERIFICATION.md` where it can be specific.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Live verification — redis / rabbitmq
|
|
2
|
+
|
|
3
|
+
`queue-aiops` is exercised by a **mock-only** test suite (`uv run pytest`, no real
|
|
4
|
+
broker). It has **not** yet been validated end-to-end against a live redis instance or
|
|
5
|
+
rabbitmq broker. This document says exactly what the mock suite already guarantees, and
|
|
6
|
+
what a live run has to prove before anyone may describe this tool as verified against a
|
|
7
|
+
real broker.
|
|
8
|
+
|
|
9
|
+
It is deliberately checklist-shaped so the result is reproducible and auditable — not a
|
|
10
|
+
subjective "seems fine".
|
|
11
|
+
|
|
12
|
+
## What the mock suite already guarantees
|
|
13
|
+
|
|
14
|
+
- Every module imports; the CLI builds; **all 28 MCP tools** carry the `@governed_tool`
|
|
15
|
+
harness marker (`tests/test_smoke.py`, which also asserts the tool count and that
|
|
16
|
+
`__version__` matches `pyproject.toml`).
|
|
17
|
+
- The four flagship analyses (`redis_memory_pressure_rca`, `redis_latency_rca`,
|
|
18
|
+
`rabbitmq_queue_backlog_rca`, `connection_churn_analysis`) are unit-tested against
|
|
19
|
+
synthetic telemetry: each cause classification fires on the right signal
|
|
20
|
+
(noeviction-near-limit vs active eviction vs fragmentation vs swapping; O(N) command
|
|
21
|
+
patterns and fork/AOF stalls; no-consumers vs unacked pile-up vs rate deficit),
|
|
22
|
+
findings cite the measured number, and partial/missing fields do not crash.
|
|
23
|
+
- The **platform registry** resolves each tool to the correct redis (RESP, via the
|
|
24
|
+
`redis` Python client) or rabbitmq (management HTTP API, HTTP Basic) shape.
|
|
25
|
+
- **Safety invariants** are tested: the redis surface is a typed command **allow-list**
|
|
26
|
+
with no generic passthrough; big-key sampling is `SCAN`-based under a hard budget and
|
|
27
|
+
**never** issues `KEYS *`; and rabbitmq path segments (queue/policy names, and the
|
|
28
|
+
default vhost `/` → `%2F`) are percent-encoded centrally.
|
|
29
|
+
- Reversible writes record a faithful **inverse** undo descriptor built from a fetched
|
|
30
|
+
before-state (`redis_config_set` restores the prior value from `CONFIG GET`;
|
|
31
|
+
`set_policy` / `delete_policy` restore the captured definition; `declare_queue`'s undo
|
|
32
|
+
deletes it only when newly created). `purge_queue` declares **no** undo;
|
|
33
|
+
`delete_queue`'s undo re-declares the captured definition and the tests assert that
|
|
34
|
+
**messages are not claimed to be restored**.
|
|
35
|
+
- Governance persistence is tested against a real on-disk SQLite audit DB: calls land as
|
|
36
|
+
rows, failures record `status=error` and no undo, and the secure-by-default approver
|
|
37
|
+
gate refuses high-risk ops when no `rules.yaml` exists.
|
|
38
|
+
|
|
39
|
+
What it does **not** guarantee: that the concrete `INFO` field names, `SLOWLOG` entry
|
|
40
|
+
shape, and rabbitmq management-API JSON match a real broker build. Those are modelled
|
|
41
|
+
from each project's public documentation and are the **largest verification debt in this
|
|
42
|
+
repo** — `INFO` field names in particular have shifted across redis 5/6/7.
|
|
43
|
+
|
|
44
|
+
## Prerequisites for a live run
|
|
45
|
+
|
|
46
|
+
Both platforms are free and trivially containerised:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
docker run -d --name redis-verify -p 6379:6379 redis:7 \
|
|
50
|
+
redis-server --maxmemory 128mb --maxmemory-policy noeviction
|
|
51
|
+
docker run -d --name rabbit-verify -p 5672:5672 -p 15672:15672 rabbitmq:3-management
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The rabbitmq **management plugin** must be enabled (the `-management` image does this),
|
|
55
|
+
and the API user needs the `monitoring` or `management` tag.
|
|
56
|
+
|
|
57
|
+
Use a **throwaway broker with throwaway data**. The checklist purges and deletes queues,
|
|
58
|
+
kills clients, and changes the running config — `purge_queue` destroys real messages and
|
|
59
|
+
records **no undo**. Never point it at a broker carrying traffic you care about.
|
|
60
|
+
|
|
61
|
+
Set the lab up so the reads have something to find:
|
|
62
|
+
|
|
63
|
+
- Fill redis past 80% of a small `maxmemory` and leave the policy at `noeviction`, so the
|
|
64
|
+
most dangerous finding is reachable.
|
|
65
|
+
- Create a few deliberately oversized keys (a large hash and a large list).
|
|
66
|
+
- Run some `KEYS`/`SMEMBERS` calls so the SLOWLOG has genuine O(N) entries.
|
|
67
|
+
- On rabbitmq, create three queues: one with **no consumer** and messages published, one
|
|
68
|
+
with a consumer that **never acks**, and one healthy — the three backlog causes.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv tool install queue-aiops
|
|
72
|
+
queue-aiops init # wizard: pick platform, optional encrypted secret
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Record the exact versions tested (e.g. "redis 7.4, rabbitmq 3.13") — a tick is only
|
|
76
|
+
meaningful with the build it was ticked against.
|
|
77
|
+
|
|
78
|
+
## Verification checklist
|
|
79
|
+
|
|
80
|
+
Tick every box, **per platform**. A box that cannot be ticked is a verification gap —
|
|
81
|
+
record it, do not silently pass.
|
|
82
|
+
|
|
83
|
+
### 1. Connectivity (the fastest live gate)
|
|
84
|
+
- [ ] `queue-aiops doctor` → green on each target: config parsed, secret store unlocks,
|
|
85
|
+
and a real `PING` / `/api/overview` returns.
|
|
86
|
+
- [ ] `queue-aiops doctor --skip-auth` → passes offline (config/secret checks only).
|
|
87
|
+
- [ ] An **auth-less** lab redis connects with no stored secret (this is a supported
|
|
88
|
+
configuration and a common mock-vs-reality divergence).
|
|
89
|
+
- [ ] One config spanning both platforms works with `--target` switching.
|
|
90
|
+
|
|
91
|
+
### 2. Reads return real, well-shaped data
|
|
92
|
+
- [ ] `queue-aiops overview` → real version/role, memory posture, client counts, ops/sec,
|
|
93
|
+
hit rate and key count (redis); version, queue/message totals, connection/channel/
|
|
94
|
+
consumer counts and node alarms (rabbitmq). Confirm a **partial** failure degrades
|
|
95
|
+
into the `errors` list rather than failing the whole call.
|
|
96
|
+
- [ ] `queue-aiops redis info` / `redis memory` → fields match `redis-cli INFO`
|
|
97
|
+
**on each of redis 6 and 7**, since field names have moved between versions.
|
|
98
|
+
- [ ] `queue-aiops redis clients` → matches `CLIENT LIST`; `redis keyspace` matches
|
|
99
|
+
`DBSIZE` per database.
|
|
100
|
+
- [ ] `queue-aiops redis slowlog --limit 50` → matches `SLOWLOG GET`, with timings
|
|
101
|
+
parsed correctly.
|
|
102
|
+
- [ ] `queue-aiops redis config-get maxmemory*` → glob patterns work and match
|
|
103
|
+
`CONFIG GET`.
|
|
104
|
+
- [ ] `queue-aiops redis bigkeys --count 500` → finds the oversized keys you planted, and
|
|
105
|
+
reports a **coverage %** consistent with the keyspace size. Confirm with
|
|
106
|
+
`MONITOR` or the slowlog that it issued `SCAN`, **never** `KEYS *` — this is the
|
|
107
|
+
single most important safety check in the file.
|
|
108
|
+
- [ ] `queue-aiops rabbitmq queues` / `queue <name>` / `connections` / `channels` /
|
|
109
|
+
`policies` / `nodes` → match the management UI, including ready-vs-unacked splits.
|
|
110
|
+
- [ ] A queue and a policy whose **names need percent-encoding** (a `/`, a space, a `%`)
|
|
111
|
+
are read correctly, and the default vhost `/` resolves as `%2F`.
|
|
112
|
+
|
|
113
|
+
### 3. The analyses are right, not just non-crashing
|
|
114
|
+
- [ ] With redis near `maxmemory` under `noeviction`,
|
|
115
|
+
`queue-aiops analyze memory --used-pct 85` raises the **noeviction-near-limit**
|
|
116
|
+
finding and cites the real used/max numbers. Switch to `allkeys-lru`, drive
|
|
117
|
+
evictions, and confirm the finding changes to active eviction.
|
|
118
|
+
- [ ] Fragmentation vs swapping are distinguished correctly (do not accept "flagged
|
|
119
|
+
something" — check it names the right one).
|
|
120
|
+
- [ ] `queue-aiops analyze latency --slow-us 10000` digests the planted O(N) entries by
|
|
121
|
+
**command pattern** and suggests the incremental variant (`KEYS` → `SCAN`).
|
|
122
|
+
- [ ] Trigger a background save on a large dataset; the fork/AOF stall signal appears.
|
|
123
|
+
- [ ] `queue-aiops analyze backlog --top 20` classifies each of your three planted
|
|
124
|
+
queues correctly: **no consumers**, **unacked pile-up**, and healthy.
|
|
125
|
+
- [ ] Drive the node past its memory watermark; the alarm is reported as blocking **all**
|
|
126
|
+
publishers, and outranks the per-queue findings.
|
|
127
|
+
- [ ] `queue-aiops analyze churn` on both platforms pins reconnect churn to the right
|
|
128
|
+
client source.
|
|
129
|
+
|
|
130
|
+
### 4. A reversible write + its undo (governance closes the loop)
|
|
131
|
+
- [ ] `queue-aiops redis config-set maxmemory-policy allkeys-lru --dry-run` → prints the
|
|
132
|
+
call, `CONFIG GET` shows the value unchanged.
|
|
133
|
+
- [ ] `queue-aiops redis config-set maxmemory-policy allkeys-lru` → the running config
|
|
134
|
+
changes, the result carries an `_undo_id`, and a row lands in
|
|
135
|
+
`~/.queue-aiops/audit.db`.
|
|
136
|
+
- [ ] `queue-aiops undo list` shows it; `undo apply <id>` restores the **prior** policy —
|
|
137
|
+
verify starting from a non-default value, where a naive undo would wrongly set
|
|
138
|
+
`noeviction`.
|
|
139
|
+
- [ ] `queue-aiops rabbitmq set-policy <name> <pattern> '{"max-length":1000}'` over an
|
|
140
|
+
**existing** policy, then `undo apply` → the prior definition returns intact (not
|
|
141
|
+
a deletion).
|
|
142
|
+
- [ ] `queue-aiops rabbitmq declare-queue <new> --dry-run` then for real, then
|
|
143
|
+
`undo apply` → the newly created queue is deleted. Repeat against a queue that
|
|
144
|
+
**already existed**: the undo must **not** delete it.
|
|
145
|
+
|
|
146
|
+
### 5. Irreversible / asymmetric writes behave as declared
|
|
147
|
+
- [ ] `queue-aiops rabbitmq purge <queue> --dry-run` → reports the message count about to
|
|
148
|
+
be destroyed; the real run destroys exactly that many and records **no** undo.
|
|
149
|
+
- [ ] `queue-aiops rabbitmq delete-queue <queue>` on a queue **with messages**, then
|
|
150
|
+
`undo apply` → the queue is re-declared with the right durable/auto-delete flags,
|
|
151
|
+
and the **messages are gone**. Confirm the tool never claimed otherwise.
|
|
152
|
+
- [ ] `queue-aiops redis kill-client --addr <ip:port>` drops that connection, records no
|
|
153
|
+
undo, and is audited.
|
|
154
|
+
|
|
155
|
+
### 6. Governance actually gates
|
|
156
|
+
- [ ] With no `~/.queue-aiops/rules.yaml`, `purge_queue` and `delete_queue` are
|
|
157
|
+
**refused** unless `QUEUE_AUDIT_APPROVED_BY` is set (secure-by-default); with it
|
|
158
|
+
plus `QUEUE_AUDIT_RATIONALE`, both appear in the audit row.
|
|
159
|
+
- [ ] A tight poll loop trips the runaway budget guard rather than hammering the broker.
|
|
160
|
+
- [ ] A failed call (nonexistent queue) is audited `status=error` and records no undo.
|
|
161
|
+
- [ ] Attempting a redis command outside the typed allow-list is rejected **before** the
|
|
162
|
+
client sends anything — confirm against the live server that nothing executes.
|
|
163
|
+
|
|
164
|
+
### 7. Cleanup
|
|
165
|
+
- [ ] Restore every config value you changed, delete the throwaway queues and policies,
|
|
166
|
+
and flush the lab redis.
|
|
167
|
+
- [ ] `queue-aiops overview` matches the baseline you captured before starting.
|
|
168
|
+
- [ ] Skim `~/.queue-aiops/audit.db` — every write is there with the right risk tier.
|
|
169
|
+
|
|
170
|
+
## Criteria to consider it live-verified
|
|
171
|
+
|
|
172
|
+
All of the following must hold:
|
|
173
|
+
|
|
174
|
+
1. Every box above is ticked against **both** a real redis and a real rabbitmq, with the
|
|
175
|
+
exact builds recorded (e.g. "redis 7.4 + rabbitmq 3.13"), and the redis reads
|
|
176
|
+
re-checked on at least **two major redis versions** given the `INFO` field drift.
|
|
177
|
+
2. Every field-name or API-shape mismatch found is **fixed and covered by a regression
|
|
178
|
+
test**, so the mock suite would now catch it.
|
|
179
|
+
3. Section 4 passed, including the asymmetric `declare_queue` case (undo must delete only
|
|
180
|
+
a queue it created). Recording an undo descriptor is not the same as the undo
|
|
181
|
+
working, and this product line has shipped broken undo pairs before.
|
|
182
|
+
4. The big-key sampler was confirmed **live** to issue `SCAN` under budget and never
|
|
183
|
+
`KEYS *` — a mock cannot prove this, and getting it wrong stalls a production redis.
|
|
184
|
+
5. The run is written up in the release notes / product-line memory with the date and
|
|
185
|
+
package version, matching how the line records its other live-verified tools.
|
|
186
|
+
|
|
187
|
+
Until then, this repo says only what is true: mock-validated, live-unverified. Claiming
|
|
188
|
+
otherwise would break that promise.
|
|
189
|
+
|
|
190
|
+
## Notes for maintainers
|
|
191
|
+
|
|
192
|
+
- `queue-aiops doctor` is the single fastest live entry point; start there.
|
|
193
|
+
- Weight the run toward **redis `INFO` field names** and **rabbitmq percent-encoded path
|
|
194
|
+
segments** — those are the two places the mocks are least able to model.
|
|
195
|
+
- Managed cloud queue services (ElastiCache, Amazon MQ, CloudAMQP, …) are a **separate**
|
|
196
|
+
verification target: wire-compatible reads may work, but `CONFIG SET` and
|
|
197
|
+
`CLIENT KILL` are commonly restricted. Do not infer managed support from a self-hosted
|
|
198
|
+
run.
|
|
199
|
+
- Add this tool's result to the product-line verification ledger once green, so the
|
|
200
|
+
central "verification debt" list stays accurate.
|
|
@@ -75,7 +75,7 @@ def tool_errors(shape: str = "dict") -> Callable:
|
|
|
75
75
|
mcp = FastMCP(
|
|
76
76
|
"queue-aiops",
|
|
77
77
|
instructions=(
|
|
78
|
-
"Queue/cache broker operations
|
|
78
|
+
"Queue/cache broker operations over redis and rabbitmq: for a "
|
|
79
79
|
"redis target — server/memory/keyspace reads, clients, slowlog, config, "
|
|
80
80
|
"and a SCAN-budgeted big-key sample (never KEYS *); for a rabbitmq "
|
|
81
81
|
"target — management-API overview, queues, connections, channels, "
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""MCP server wrapping queue-aiops operations (stdio transport).
|
|
2
|
+
|
|
3
|
+
Thin adapter layer: each ``@mcp.tool()`` function (in ``mcp_server/tools/``)
|
|
4
|
+
delegates to the ``queue_aiops`` ops package and is wrapped with the
|
|
5
|
+
queue-aiops ``@governed_tool`` harness (audit / budget / undo / risk-tier).
|
|
6
|
+
|
|
7
|
+
Standalone, self-governed broker operations over redis and rabbitmq:
|
|
8
|
+
redis server/memory/clients/slowlog/config/keyspace/big-key reads, rabbitmq
|
|
9
|
+
overview/queues/connections/channels/policies/node reads, four flagship
|
|
10
|
+
analyses, and governed writes (redis config set + client kill; rabbitmq queue
|
|
11
|
+
purge/delete/declare and policy set/delete).
|
|
12
|
+
|
|
13
|
+
Source: https://github.com/AIops-tools/Queue-AIops
|
|
14
|
+
License: MIT
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
|
|
19
|
+
from mcp_server._shared import _safe_error, mcp, tool_errors
|
|
20
|
+
|
|
21
|
+
# Importing the tool modules registers every @mcp.tool() onto the shared
|
|
22
|
+
# `mcp` instance. Order does not matter; each module is self-contained.
|
|
23
|
+
from mcp_server.tools import ( # noqa: F401 — side effects
|
|
24
|
+
analysis,
|
|
25
|
+
overview,
|
|
26
|
+
rabbit_reads,
|
|
27
|
+
redis_reads,
|
|
28
|
+
undo,
|
|
29
|
+
writes,
|
|
30
|
+
)
|
|
31
|
+
from queue_aiops.governance import READ_ONLY_ENV, is_read_only
|
|
32
|
+
|
|
33
|
+
__all__ = ["mcp", "main", "_safe_error", "tool_errors", "apply_read_only"]
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def apply_read_only() -> list[str]:
|
|
39
|
+
"""Unregister every write tool when read-only mode is on.
|
|
40
|
+
|
|
41
|
+
The ``@governed_tool`` harness already refuses writes in this mode, so this
|
|
42
|
+
is a second layer — and the one that matters for smaller local models:
|
|
43
|
+
a tool absent from ``list_tools()`` cannot be hallucinated into a call,
|
|
44
|
+
whereas a tool that exists but refuses invites retry loops. It also gives a
|
|
45
|
+
compliance reviewer something checkable — the write tools are simply not
|
|
46
|
+
exposed.
|
|
47
|
+
|
|
48
|
+
``risk_level == "low"`` is the read/write discriminator; a smoke test
|
|
49
|
+
asserts it stays in agreement with each tool's ``[READ]``/``[WRITE]``
|
|
50
|
+
docstring tag so the two can never drift apart silently.
|
|
51
|
+
|
|
52
|
+
Returns the names that were removed (empty when not in read-only mode).
|
|
53
|
+
"""
|
|
54
|
+
if not is_read_only():
|
|
55
|
+
return []
|
|
56
|
+
registry = mcp._tool_manager._tools
|
|
57
|
+
dropped = [
|
|
58
|
+
name
|
|
59
|
+
for name, tool in registry.items()
|
|
60
|
+
if getattr(getattr(tool, "fn", None), "_risk_level", "low") != "low"
|
|
61
|
+
]
|
|
62
|
+
for name in dropped:
|
|
63
|
+
del registry[name]
|
|
64
|
+
if dropped:
|
|
65
|
+
logger.info(
|
|
66
|
+
"%s is set — read-only mode: %d write tool(s) not exposed",
|
|
67
|
+
READ_ONLY_ENV, len(dropped),
|
|
68
|
+
)
|
|
69
|
+
return dropped
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> None:
|
|
73
|
+
"""Run the MCP server over stdio."""
|
|
74
|
+
logging.basicConfig(level=logging.INFO)
|
|
75
|
+
apply_read_only()
|
|
76
|
+
mcp.run(transport="stdio")
|
|
@@ -28,6 +28,10 @@ def list_queues(vhost: Optional[str] = None, target: Optional[str] = None) -> di
|
|
|
28
28
|
Args:
|
|
29
29
|
vhost: Restrict to one vhost (the default vhost is '/'); omit for all.
|
|
30
30
|
target: rabbitmq target name from config; omit for the default.
|
|
31
|
+
|
|
32
|
+
Returns an envelope: {"queues": [...], "returned": N, "limit": L,
|
|
33
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
34
|
+
returned — do not treat this as the complete set.
|
|
31
35
|
"""
|
|
32
36
|
return ops.list_queues(_get_connection(target), vhost)
|
|
33
37
|
|
|
@@ -54,6 +58,10 @@ def list_connections(target: Optional[str] = None) -> dict:
|
|
|
54
58
|
|
|
55
59
|
Args:
|
|
56
60
|
target: rabbitmq target name from config; omit for the default.
|
|
61
|
+
|
|
62
|
+
Returns an envelope: {"connections": [...], "returned": N, "limit": L,
|
|
63
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
64
|
+
returned — do not treat this as the complete set.
|
|
57
65
|
"""
|
|
58
66
|
return ops.list_connections(_get_connection(target))
|
|
59
67
|
|
|
@@ -66,6 +74,10 @@ def list_channels(target: Optional[str] = None) -> dict:
|
|
|
66
74
|
|
|
67
75
|
Args:
|
|
68
76
|
target: rabbitmq target name from config; omit for the default.
|
|
77
|
+
|
|
78
|
+
Returns an envelope: {"channels": [...], "returned": N, "limit": L,
|
|
79
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
80
|
+
returned — do not treat this as the complete set.
|
|
69
81
|
"""
|
|
70
82
|
return ops.list_channels(_get_connection(target))
|
|
71
83
|
|
|
@@ -79,6 +91,10 @@ def list_policies(vhost: Optional[str] = None, target: Optional[str] = None) ->
|
|
|
79
91
|
Args:
|
|
80
92
|
vhost: Restrict to one vhost (the default vhost is '/'); omit for all.
|
|
81
93
|
target: rabbitmq target name from config; omit for the default.
|
|
94
|
+
|
|
95
|
+
Returns an envelope: {"policies": [...], "returned": N, "limit": L,
|
|
96
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
97
|
+
returned — do not treat this as the complete set.
|
|
82
98
|
"""
|
|
83
99
|
return ops.list_policies(_get_connection(target), vhost)
|
|
84
100
|
|
|
@@ -39,6 +39,10 @@ def redis_clients(target: Optional[str] = None) -> dict:
|
|
|
39
39
|
|
|
40
40
|
Args:
|
|
41
41
|
target: redis target name from config; omit for the default.
|
|
42
|
+
|
|
43
|
+
Returns an envelope: {"clients": [...], "returned": N, "limit": L,
|
|
44
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
45
|
+
returned — do not treat this as the complete set.
|
|
42
46
|
"""
|
|
43
47
|
return ops.list_clients(_get_connection(target))
|
|
44
48
|
|
|
@@ -52,6 +56,10 @@ def redis_slowlog(count: int = 128, target: Optional[str] = None) -> dict:
|
|
|
52
56
|
Args:
|
|
53
57
|
count: Max entries to pull (capped at 128).
|
|
54
58
|
target: redis target name from config; omit for the default.
|
|
59
|
+
|
|
60
|
+
Returns an envelope: {"entries": [...], "returned": N, "limit": L,
|
|
61
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
62
|
+
returned — do not treat this as the complete set.
|
|
55
63
|
"""
|
|
56
64
|
return ops.slowlog(_get_connection(target), count)
|
|
57
65
|
|
|
@@ -94,5 +102,9 @@ def redis_big_keys(top: int = 20, target: Optional[str] = None) -> dict:
|
|
|
94
102
|
Args:
|
|
95
103
|
top: How many key rows to return, largest first (default 20).
|
|
96
104
|
target: redis target name from config; omit for the default.
|
|
105
|
+
|
|
106
|
+
Returns an envelope: {"topKeys": [...], "returned": N, "limit": L,
|
|
107
|
+
"truncated": bool}. When "truncated" is true there is more than was
|
|
108
|
+
returned — do not treat this as the complete set.
|
|
97
109
|
"""
|
|
98
110
|
return ops.big_key_sample(_get_connection(target), top)
|