forked from HomeLab/unraid-mcp
- bd init: Dolt-backed issue tracker, prefix unraid-mcp-<hash> - .lavra/config/project-setup.md: python stack, 4 review agents - .lavra/config/codebase-profile.md: stack/arch/conventions profile - .gitignore: add lavra session-state and beads entries - CLAUDE.md: beads workflow integration block Co-Authored-By: Claude <noreply@anthropic.com>
90 lines
3.9 KiB
Markdown
90 lines
3.9 KiB
Markdown
# Codebase Profile
|
|
Generated by /project-setup on 2026-03-27
|
|
|
|
## Stack & Integrations
|
|
**Language & Runtime**
|
|
- Python 3.12+ (min requirement), supports 3.13
|
|
- Build system: Hatchling 1.25.0+, package manager: uv
|
|
|
|
**Core Frameworks**
|
|
- FastMCP 3.0.0+: MCP server framework
|
|
- FastAPI 0.115.0+, Uvicorn 0.35.0+: ASGI layer
|
|
- Pydantic: validation/serialization
|
|
|
|
**API & Communication**
|
|
- httpx 0.28.1+: async HTTP client for GraphQL queries
|
|
- websockets 15.0.1+: WebSocket client for real-time subscriptions
|
|
- graphql-core 3.2.0+: GraphQL query validation (dev dep)
|
|
|
|
**Configuration**
|
|
- python-dotenv 1.1.1+: env var management
|
|
- rich 14.1.0+: terminal output/logging
|
|
|
|
**Testing**
|
|
- pytest 8.4.2+, pytest-asyncio 1.2.0+, pytest-cov 7.0.0+
|
|
- respx 0.22.0+: httpx request mocking
|
|
- hypothesis 6.151.9+: property-based testing
|
|
|
|
**Quality**
|
|
- ruff 0.12.8+: lint/format; ty 0.0.15+: type checking
|
|
|
|
**External Dependencies**
|
|
- Unraid GraphQL API (primary backend via httpx)
|
|
- WebSocket subscriptions to Unraid server (persistent connections)
|
|
- Supports custom CA certs (UNRAID_VERIFY_SSL)
|
|
|
|
**Entry Points**
|
|
- CLI: `unraid-mcp-server` / `unraid` bin scripts
|
|
- 1 primary MCP tool: `unraid` (15 domains, ~108 subactions)
|
|
- 2 diagnostic tools: `diagnose_subscriptions`, `test_subscription_query`
|
|
- 10 live snapshot MCP resources under `unraid://` namespace
|
|
|
|
## Architecture & Structure
|
|
```
|
|
unraid_mcp/
|
|
├── core/ # GraphQL client, exceptions, types, guards
|
|
├── config/ # Settings, logging, env validation
|
|
├── tools/ # Consolidated unraid tool (15 action domains)
|
|
├── subscriptions/ # WebSocket manager, resources, diagnostics
|
|
├── main.py # Entry point with shutdown cleanup
|
|
└── server.py # FastMCP init + 5-layer middleware chain
|
|
```
|
|
|
|
**server.py**: FastMCP init with middleware: logging → error_handling → rate_limiting → response_limiting → caching. Registers all tools/resources at import.
|
|
|
|
**tools/unraid.py**: Single consolidated tool (~1900 lines). 15 actions dispatch to domain handlers. Destructive actions require `confirm=True`.
|
|
|
|
**core/client.py**: GraphQL HTTP client (httpx-based) with sensitive key redaction, request/response logging, timeout management, credentials elicitation.
|
|
|
|
**config/settings.py**: Env var parsing for API URL, credentials, host/port, SSL, timeouts, log level, transport.
|
|
|
|
**subscriptions/manager.py**: Singleton SubscriptionManager for WebSocket lifecycle and real-time streaming.
|
|
|
|
**Data Flow**: `unraid(action, subaction)` → domain handler → GraphQL query → httpx → Unraid API → response
|
|
|
|
**Patterns**:
|
|
- Consolidated single-tool MCP (action+subaction multiplexing)
|
|
- Singleton SubscriptionManager for WebSocket lifecycle
|
|
- Middleware chain (logging wraps all; caching disabled for mutations)
|
|
- Elicitation flow for first-run credential setup
|
|
|
|
## Conventions & Testing
|
|
**Test Framework**: pytest with asyncio auto mode; `make_tool_fn` helper in conftest for tool extraction from FastMCP.
|
|
|
|
**Test Layout**:
|
|
- Root: domain unit tests (test_array.py, test_docker.py, etc.)
|
|
- tests/safety/: destructive action guard audits
|
|
- tests/schema/: GraphQL query validation
|
|
- tests/http_layer/: respx-based HTTP mocking
|
|
- tests/contract/: response structure contracts
|
|
- tests/property/: hypothesis property-based tests
|
|
- tests/integration/: WebSocket subscription lifecycle (slow, mock WS)
|
|
|
|
**Key Patching Rule**: Patch at `unraid_mcp.tools.unraid.make_graphql_request` (tool module level), NOT core module.
|
|
|
|
**Naming**: `Test{Feature}` classes, async `test_*` methods, `_DOMAIN_QUERIES` dicts, `register_{domain}_tool()` functions.
|
|
|
|
**CI**: uv-based: lint (ruff) → typecheck (ty) → test (pytest) → version-sync → audit. Coverage 80% with branch coverage. Version sync enforces pyproject.toml ↔ .claude-plugin/plugin.json consistency.
|
|
|
|
**Ruff config**: line length 100, ignores D1xx/D2xx/D7xx (docstring), S101 (assert in tests).
|