Remote MCP Rate Limit And Audit Export Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: Add session-scoped remote MCP/SSE rate limiting and append-only audit JSONL export.
Architecture: Add a focused zaxy.remote_security module with fixed-window rate limiting and audit export. Wire it into the existing SSE authorization path so stdio behavior remains unchanged.
Tech Stack: Python 3.11, Starlette request handlers, Typer/Pydantic settings, pytest, ruff.
---
Task 1: Remote Security Module
Files:
- Create:
src/zaxy/remote_security.py - Create:
tests/test_remote_security.py
- [ ] Step 1: Write failing tests
Add tests for SessionRateLimiter allowing two requests and denying the third, resetting after the time window, AuditEventExporter writing compact JSONL without secrets, and disabled exporter no-op behavior.
- [ ] Step 2: Run red test
Run: pytest --no-cov tests/test_remote_security.py -q
Expected: fail because zaxy.remote_security does not exist.
- [ ] Step 3: Implement module
Add RateLimitDecision, SessionRateLimiter, RemoteAuditEvent, and AuditEventExporter. Use injected clock functions for deterministic tests.
- [ ] Step 4: Run green test
Run: pytest --no-cov tests/test_remote_security.py -q
Expected: pass.
Task 2: Config And Metrics
Files:
- Modify:
src/zaxy/config.py - Modify:
src/zaxy/metrics.py - Modify:
tests/test_config.py - Modify:
tests/test_metrics.py
- [ ] Step 1: Write failing tests
Assert default settings expose enabled rate limiting, default request/window values, disabled audit export, and default audit path. Assert metrics collector exposes a record_rate_limit_denial(session_id) no-op-safe method.
- [ ] Step 2: Run red tests
Run: pytest --no-cov tests/test_config.py tests/test_metrics.py -q
Expected: fail because settings and metric method are missing.
- [ ] Step 3: Implement config and metric additions
Add fields and metric counter without changing production auth validation.
- [ ] Step 4: Run green tests
Run: pytest --no-cov tests/test_config.py tests/test_metrics.py -q
Expected: pass.
Task 3: MCP SSE Wiring
Files:
- Modify:
src/zaxy/mcp_server.py - Modify:
tests/test_mcp.py
- [ ] Step 1: Write failing tests
Add direct tests around a request guard helper that returns session IDs for allowed requests, raises rate-limit errors on excess session requests, and audits auth-denied, allowed, and rate-limited outcomes.
- [ ] Step 2: Run red tests
Run: pytest --no-cov tests/test_mcp.py -q
Expected: fail because the request guard helper does not exist.
- [ ] Step 3: Implement request guard
Add a small helper around MCPTransportAuth, SessionRateLimiter, AuditEventExporter, and settings. Wire /sse and /messages/ through it.
- [ ] Step 4: Run green tests
Run: pytest --no-cov tests/test_mcp.py tests/test_remote_security.py -q
Expected: pass.
Task 4: Docs And Roadmap
Files:
- Modify:
docs/security.md - Modify:
docs/runbook.md - Modify:
docs/configuration.md - Modify:
AGENTS.md
- [ ] Step 1: Document settings and behavior
Describe session-first rate limiting, audit JSONL export, no secret capture, and process-local limitations.
- [ ] Step 2: Verify
Run:
ruff check src/zaxy/remote_security.py src/zaxy/mcp_server.py src/zaxy/config.py src/zaxy/metrics.py tests/test_remote_security.py tests/test_mcp.py tests/test_config.py tests/test_metrics.py
pytest --no-cov tests/test_remote_security.py tests/test_mcp.py tests/test_config.py tests/test_metrics.py tests/test_docs_site.py -q
pytest --no-cov -m "not integration"
Expected: all checks pass.