Add 3 new Coolify plugin handlers (37 new tools, 67 total): - projects.py: 8 tools (CRUD projects + environments) - databases.py: 16 tools (CRUD, lifecycle, 6 DB types, backups) - services.py: 13 tools (CRUD, lifecycle, env vars) 734 tests passing. Total platform tools: 633. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
212 lines
9.1 KiB
Markdown
212 lines
9.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**MCP Hub** — a Python MCP (Model Context Protocol) server that manages multiple self-hosted services through a unified plugin architecture. Supports 10 plugin types (WordPress, WooCommerce, WordPress Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus, Coolify) with 633 tools total. The tool count stays constant regardless of how many sites are configured.
|
|
|
|
## Quick Setup
|
|
|
|
```bash
|
|
cp env.example .env # Copy and fill in credentials
|
|
pip install -e ".[dev]" # Install with dev deps
|
|
python server.py # Run (stdio) or:
|
|
python server.py --transport streamable-http --port 8000 # Run (HTTP)
|
|
```
|
|
|
|
## Build & Development Commands
|
|
|
|
```bash
|
|
# Install with dev dependencies
|
|
pip install -e ".[dev]"
|
|
|
|
# Run server (stdio transport for Claude Desktop)
|
|
python server.py
|
|
|
|
# Run server (HTTP transport for testing)
|
|
python server.py --transport streamable-http --port 8000
|
|
|
|
# Run all tests
|
|
pytest
|
|
|
|
# Run single test file
|
|
pytest tests/test_api_keys.py
|
|
|
|
# Run by marker (unit, integration, security, slow)
|
|
pytest -m unit
|
|
pytest -m "not slow"
|
|
|
|
# Tests with coverage
|
|
pytest --cov --cov-report=html
|
|
|
|
# Format code
|
|
black .
|
|
|
|
# Lint
|
|
ruff check .
|
|
ruff check --fix .
|
|
|
|
# Type check
|
|
mypy .
|
|
|
|
# Docker build and run
|
|
docker build -t mcphub .
|
|
docker-compose up -d
|
|
```
|
|
|
|
## Code Quality Configuration
|
|
|
|
All configured in `pyproject.toml`:
|
|
- **Black**: line-length=100, target py311
|
|
- **Ruff**: strict rules (E, W, F, I, N, D, UP, B, C4, SIM, TCH, PTH), Google-style docstrings
|
|
- **mypy**: Python 3.11, strict equality, check_untyped_defs=true
|
|
- **pytest**: asyncio_mode="auto", testpaths=["tests"], markers: slow, integration, unit, security
|
|
|
|
## Architecture
|
|
|
|
### Root Directory Overview
|
|
|
|
```
|
|
├── server.py # Primary entry point
|
|
├── core/ # Layer 1: Core system modules
|
|
├── plugins/ # Layer 2: Plugin system (9 plugins)
|
|
├── core/templates/ # Jinja2 templates (dashboard + OAuth)
|
|
├── tests/ # Organized test suite
|
|
├── scripts/ # Setup & deployment scripts
|
|
├── wordpress-plugin/ # Companion WP plugins (PHP)
|
|
├── docs/ # Extensive documentation
|
|
├── pyproject.toml # All tool configs (black, ruff, mypy, pytest)
|
|
├── docker-compose.yaml # Docker composition
|
|
└── env.example # Environment variable template
|
|
```
|
|
|
|
### Three-Layer Clean Architecture ("Option B")
|
|
|
|
```
|
|
Layer 1: Core System (core/) — Auth, site discovery, tool registry, health, rate limiting
|
|
Layer 2: Plugin System (plugins/) — 9 plugin types, each with handlers + schemas
|
|
Layer 3: API & Web UI (server.py + core/dashboard/) — FastMCP server, Starlette routes, dashboard
|
|
```
|
|
|
|
### Entry Points
|
|
|
|
- **`server.py`** (~3500 lines) — Primary entry point. Handles FastMCP server, Starlette routes, middleware, plugins.
|
|
### Multi-Endpoint Architecture
|
|
|
|
```
|
|
/mcp → Admin (all tools, Master API Key required)
|
|
/system/mcp → System tools only
|
|
/{plugin_type}/mcp → Plugin-specific tools (wordpress, gitea, n8n, etc.)
|
|
/project/{alias_or_id}/mcp → Per-project endpoint (auto-injects site parameter)
|
|
```
|
|
|
|
Implemented in `core/endpoints/` — EndpointConfig, MCPEndpointFactory, EndpointRegistry.
|
|
|
|
### Plugin System
|
|
|
|
All plugins extend `BasePlugin` (in `plugins/base.py`). Registration happens in `plugins/__init__.py` via `PluginRegistry`.
|
|
|
|
Each plugin follows this structure:
|
|
```
|
|
plugins/{name}/
|
|
├── plugin.py # Main class extending BasePlugin
|
|
├── client.py # REST API client for the service
|
|
├── handlers/ # Feature-specific handlers (posts.py, orders.py, etc.)
|
|
└── schemas/ # Pydantic models for validation
|
|
```
|
|
|
|
**Registered plugins**: wordpress, woocommerce, wordpress_advanced, gitea, n8n, supabase, openpanel, appwrite, directus, coolify
|
|
|
|
**Plugin visibility** (Track F.1): Public users only see plugins listed in `ENABLED_PLUGINS` env var (default: `wordpress,woocommerce,supabase`). Admin sees all. Controlled by `core/plugin_visibility.py`.
|
|
|
|
### Tool Generation
|
|
|
|
Tools are dynamically generated at startup from plugin specifications:
|
|
1. `ToolGenerator` creates unified tools with a `site` parameter injected
|
|
2. Tools are registered in `ToolRegistry` and exposed via FastMCP
|
|
|
|
Unified tool pattern: `wordpress_create_post(site="myblog", title="Hello")` — the `site` parameter accepts either a site_id or alias.
|
|
|
|
### Site Configuration
|
|
|
|
Sites are managed via the web dashboard and stored in SQLite (DB-based).
|
|
User sites are encrypted with AES-256-GCM and accessed via `core/site_api.py` + `core/database.py`.
|
|
`SiteManager` (`core/site_manager.py`) provides registration and lookup infrastructure for tool generation.
|
|
|
|
### Key Core Modules
|
|
|
|
| Module | Purpose |
|
|
|--------|---------|
|
|
| `core/auth.py` | Master API key validation, request authentication |
|
|
| `core/api_keys.py` | Per-project API keys with scopes (read/write/admin) |
|
|
| `core/site_manager.py` | Type-safe site config registration and lookup |
|
|
| `core/tool_registry.py` | Central tool definitions and lookup |
|
|
| `core/tool_generator.py` | Dynamic unified tool creation with site injection |
|
|
| `core/health.py` | Health monitoring, metrics, alerts |
|
|
| `core/rate_limiter.py` | Token bucket rate limiting (60/min, 1000/hr, 10k/day) |
|
|
| `core/audit_log.py` | GDPR-compliant JSON audit logging |
|
|
| `core/oauth/` | OAuth 2.1 with PKCE (RFC 8414, 7591, 7636) |
|
|
| `core/dashboard/routes.py` | Web UI dashboard (login, projects, API keys, health, audit) |
|
|
| `core/endpoints/` | Multi-endpoint architecture (factory, registry, config) |
|
|
| `core/plugin_visibility.py` | Plugin enable/disable for public vs admin users |
|
|
| `core/user_auth.py` | OAuth Social Login (GitHub + Google) |
|
|
| `core/user_endpoints.py` | Per-user MCP endpoints (`/u/{user_id}/{alias}/mcp`) |
|
|
| `core/site_api.py` | User site CRUD, connection testing, credential encryption |
|
|
| `core/user_keys.py` | User API key management (bcrypt, `mhu_` prefix) |
|
|
| `core/database.py` | SQLite backend (aiosqlite, WAL mode, migrations) |
|
|
| `core/encryption.py` | AES-256-GCM credential encryption |
|
|
|
|
### User System (Track E)
|
|
|
|
OAuth Social Login (GitHub + Google) via `core/user_auth.py`. Users register, add sites, get personal MCP endpoints at `/u/{user_id}/{alias}/mcp`. Per-user API keys with `mhu_` prefix (bcrypt-hashed). Credentials encrypted with AES-256-GCM in SQLite.
|
|
|
|
### Dashboard
|
|
|
|
Web UI at the server root, built with Starlette + Jinja2 + HTMX + Tailwind CSS. Supports EN/FA i18n (`core/i18n.py`).
|
|
|
|
**Admin pages**: Login, Home, Projects, API Keys, OAuth Clients, Audit Logs, Health, Settings.
|
|
**User pages**: Login (OAuth), Home, My Sites (list/add/edit/test/delete), Connect (API keys + config snippets + OAuth clients), Profile.
|
|
|
|
## Commit Style
|
|
|
|
```
|
|
<type>(<scope>): <description>
|
|
```
|
|
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
|
|
|
|
## Live Instances
|
|
|
|
- **Platform**: `mcp.example.com` — Live MCP Hub with OAuth login
|
|
- **Blog**: `blog.example.com` — WordPress test site + project blog
|
|
- **Deployment**: Coolify / Docker Compose, port 8000
|
|
|
|
## Current Development (Track F)
|
|
|
|
v4 development cycle with 15 phases. See `docs/ROADMAP.md` (Track F) and `.claude/plans/structured-popping-adleman.md` for full plan.
|
|
|
|
**Active plugins for public users**: WordPress, WooCommerce, Supabase, OpenPanel, Gitea (configurable via `ENABLED_PLUGINS` env var)
|
|
|
|
## Gotchas
|
|
|
|
- Test files exist in both `tests/` (proper) and root directory (legacy `test_*.py`). Run `pytest tests/` for organized tests only.
|
|
- `wordpress-plugin/` contains companion WP plugins (openpanel, airano-mcp-seo-bridge) — these are PHP, not Python
|
|
- `env.example` has "FUTURE" labels for Supabase/Gitea but both are fully implemented
|
|
- 5 plugins are tested for public use: WordPress, WooCommerce, Supabase, OpenPanel, Gitea. Others are admin-only or disabled.
|
|
- OAuth Clients (Client ID/Secret) are for MCP endpoint auth, NOT the same as GitHub/Google dashboard login
|
|
- All sites stored in SQLite (`core/database.py`), managed via web dashboard
|
|
- Dashboard templates live in `core/templates/` (included in pip package as `package_data`)
|
|
- `ruff` config uses top-level `select` key in pyproject.toml (not `[tool.ruff.lint]` nested format)
|
|
- The `scripts/` directory has platform-specific setup scripts: `setup.sh` (Linux/Mac), `setup.ps1` (Windows)
|
|
|
|
## Deployment Notes
|
|
|
|
- **Coolify**: Docker Compose build pack, port 8000, health check `GET /health`
|
|
- Must listen on `0.0.0.0` (not localhost)
|
|
- Docker socket mount required for WP-CLI tools: `/var/run/docker.sock:/var/run/docker.sock:ro`
|
|
- Persistent volumes: `mcp-data` (API keys, OAuth), `mcp-logs` (audit, health)
|
|
- Required env vars: `MASTER_API_KEY`, `OAUTH_JWT_SECRET_KEY`, `OAUTH_BASE_URL`
|
|
- OAuth env vars: `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `PUBLIC_URL`
|
|
- User limits: `MAX_SITES_PER_USER=10`, `USER_RATE_LIMIT_PER_MIN=30`, `USER_RATE_LIMIT_PER_HR=500`
|
|
- Plugin visibility: `ENABLED_PLUGINS=wordpress,woocommerce,supabase,openpanel,gitea` (default)
|