fix: correct tool count (596), default English dashboard, clean up stale references
- Tool count corrected: 589→596 (was missing 4 OAuth + 4 system config tools) - System tools: 17→24 (accurate count of @mcp.tool() functions) - Dashboard defaults to English; Farsi only via ?lang=fa query param - Updated across all files: README, CLAUDE.md, CONTRIBUTING, DOCKER_README, getting-started, CHANGELOG, endpoints config - Removed remaining Phase references from server.py startup log - Tests: 289 passing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@ After 2-month hiatus (Dec 2025 - Feb 2026), updated all dependencies and verifie
|
|||||||
- All 54 tests now pass (previously 5 were failing)
|
- All 54 tests now pass (previously 5 were failing)
|
||||||
|
|
||||||
#### Verified
|
#### Verified
|
||||||
- All 589 tools generate correctly
|
- All 596 tools generate correctly
|
||||||
- Middleware API stable (Middleware, MiddlewareContext, get_http_headers)
|
- Middleware API stable (Middleware, MiddlewareContext, get_http_headers)
|
||||||
- 30+ custom routes operational (dashboard + OAuth)
|
- 30+ custom routes operational (dashboard + OAuth)
|
||||||
- Multi-endpoint architecture functional
|
- Multi-endpoint architecture functional
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
**MCP Hub** — a Python MCP (Model Context Protocol) server that manages multiple self-hosted projects through a unified plugin architecture. Supports 9 plugin types (WordPress, WooCommerce, WordPress Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with ~589 tools total. The tool count stays constant regardless of how many sites are configured.
|
**MCP Hub** — a Python MCP (Model Context Protocol) server that manages multiple self-hosted services through a unified plugin architecture. Supports 9 plugin types (WordPress, WooCommerce, WordPress Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with 596 tools total. The tool count stays constant regardless of how many sites are configured.
|
||||||
|
|
||||||
## Quick Setup
|
## Quick Setup
|
||||||
|
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ Then register in `plugins/__init__.py` and add tests.
|
|||||||
```
|
```
|
||||||
core/ # Core system (auth, site manager, tool registry, dashboard)
|
core/ # Core system (auth, site manager, tool registry, dashboard)
|
||||||
plugins/ # Plugin system (9 plugins, each with handlers + schemas)
|
plugins/ # Plugin system (9 plugins, each with handlers + schemas)
|
||||||
templates/ # Jinja2 templates (dashboard + OAuth)
|
core/templates/ # Jinja2 templates (dashboard + OAuth)
|
||||||
tests/ # Test suite (289 tests)
|
tests/ # Test suite (290 tests)
|
||||||
scripts/ # Setup & deployment scripts
|
scripts/ # Setup & deployment scripts
|
||||||
docs/ # Documentation
|
docs/ # Documentation
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**The AI-native management hub for WordPress, WooCommerce, and self-hosted services.**
|
**The AI-native management hub for WordPress, WooCommerce, and self-hosted services.**
|
||||||
|
|
||||||
589 tools across 9 plugins. Connect your sites, stores, repos, and databases — manage them all through Claude, ChatGPT, Cursor, or any MCP client.
|
596 tools across 9 plugins. Connect your sites, stores, repos, and databases — manage them all through Claude, ChatGPT, Cursor, or any MCP client.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -11,7 +11,7 @@ Connect your sites, stores, repos, and databases — manage them all through Cla
|
|||||||
[](https://pypi.org/project/mcphub-server/)
|
[](https://pypi.org/project/mcphub-server/)
|
||||||
[](https://hub.docker.com/r/airano/mcphub)
|
[](https://hub.docker.com/r/airano/mcphub)
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
[](https://github.com/airano-ir/mcphub/actions/workflows/ci.yml)
|
[](https://github.com/airano-ir/mcphub/actions/workflows/ci.yml)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -46,7 +46,7 @@ MCP Hub is the first MCP server that lets you manage WordPress, WooCommerce, and
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 589 Tools Across 9 Plugins
|
## 596 Tools Across 9 Plugins
|
||||||
|
|
||||||
| Plugin | Tools | What You Can Do |
|
| Plugin | Tools | What You Can Do |
|
||||||
|--------|-------|-----------------|
|
|--------|-------|-----------------|
|
||||||
@@ -59,8 +59,8 @@ MCP Hub is the first MCP server that lets you manage WordPress, WooCommerce, and
|
|||||||
| **OpenPanel** | 73 | Events, funnels, profiles, dashboards, projects |
|
| **OpenPanel** | 73 | Events, funnels, profiles, dashboards, projects |
|
||||||
| **Appwrite** | 100 | Databases, auth, storage, functions, teams, messaging |
|
| **Appwrite** | 100 | Databases, auth, storage, functions, teams, messaging |
|
||||||
| **Directus** | 100 | Collections, items, users, files, flows, permissions |
|
| **Directus** | 100 | Collections, items, users, files, flows, permissions |
|
||||||
| **System** | 17 | Health monitoring, API keys, project discovery |
|
| **System** | 24 | Health monitoring, API keys, OAuth management, audit |
|
||||||
| **Total** | **589** | Constant count — scales to unlimited sites |
|
| **Total** | **596** | Constant count — scales to unlimited sites |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -224,8 +224,8 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
|
|||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
/mcp → Admin endpoint (all 589 tools)
|
/mcp → Admin endpoint (all 596 tools)
|
||||||
/system/mcp → System tools only (17 tools)
|
/system/mcp → System tools only (24 tools)
|
||||||
/wordpress/mcp → WordPress tools (67 tools)
|
/wordpress/mcp → WordPress tools (67 tools)
|
||||||
/woocommerce/mcp → WooCommerce tools (28 tools)
|
/woocommerce/mcp → WooCommerce tools (28 tools)
|
||||||
/gitea/mcp → Gitea tools (56 tools)
|
/gitea/mcp → Gitea tools (56 tools)
|
||||||
|
|||||||
@@ -157,15 +157,10 @@ DASHBOARD_TRANSLATIONS = {
|
|||||||
|
|
||||||
|
|
||||||
def detect_language(accept_language: str | None, query_lang: str | None = None) -> str:
|
def detect_language(accept_language: str | None, query_lang: str | None = None) -> str:
|
||||||
"""Detect language from Accept-Language header or query parameter."""
|
"""Detect language from query parameter. Default is English."""
|
||||||
if query_lang and query_lang in DASHBOARD_TRANSLATIONS:
|
if query_lang and query_lang in DASHBOARD_TRANSLATIONS:
|
||||||
return query_lang
|
return query_lang
|
||||||
|
|
||||||
if accept_language:
|
|
||||||
# Check for Persian/Farsi
|
|
||||||
if "fa" in accept_language.lower() or "fa-ir" in accept_language.lower():
|
|
||||||
return "fa"
|
|
||||||
|
|
||||||
return "en"
|
return "en"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ ENDPOINT_CONFIGS = {
|
|||||||
allowed_scopes={"admin"},
|
allowed_scopes={"admin"},
|
||||||
max_tools=400,
|
max_tools=400,
|
||||||
),
|
),
|
||||||
# System endpoint - system tools only (17 tools) - Phase X.3
|
# System endpoint - system tools only (24 tools)
|
||||||
# For API key management, OAuth, rate limiting without loading all plugins
|
# For API key management, OAuth, rate limiting without loading all plugins
|
||||||
EndpointType.SYSTEM: EndpointConfig(
|
EndpointType.SYSTEM: EndpointConfig(
|
||||||
path="/system",
|
path="/system",
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<div class="mt-6 text-center" {% if lang == 'fa' %}dir="rtl"{% endif %}>
|
<div class="mt-6 text-center" {% if lang == 'fa' %}dir="rtl"{% endif %}>
|
||||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
{{ t.need_help }}
|
{{ t.need_help }}
|
||||||
<a href="https://github.com/airano-ir/coolify-mcp-hub" class="text-purple-600 dark:text-purple-400 hover:underline">{{ t.documentation }}</a>
|
<a href="https://github.com/airano-ir/mcphub" class="text-purple-600 dark:text-purple-400 hover:underline">{{ t.documentation }}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ After starting (via Docker or locally), wait ~30 seconds for the server to initi
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl http://localhost:8000/health
|
curl http://localhost:8000/health
|
||||||
# Expected: {"status": "ok", "tools_loaded": 589, ...}
|
# Expected: {"status": "ok", "tools_loaded": 596, ...}
|
||||||
```
|
```
|
||||||
|
|
||||||
**2. Open the web dashboard:**
|
**2. Open the web dashboard:**
|
||||||
@@ -313,7 +313,7 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
|
|||||||
|
|
||||||
## Using MCP Tools
|
## Using MCP Tools
|
||||||
|
|
||||||
### 589 Tools Across 9 Plugins
|
### 596 Tools Across 9 Plugins
|
||||||
|
|
||||||
| Plugin | Tools | Env Prefix |
|
| Plugin | Tools | Env Prefix |
|
||||||
|--------|-------|------------|
|
|--------|-------|------------|
|
||||||
@@ -326,7 +326,7 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
|
|||||||
| OpenPanel | 73 | `OPENPANEL_` |
|
| OpenPanel | 73 | `OPENPANEL_` |
|
||||||
| Appwrite | 100 | `APPWRITE_` |
|
| Appwrite | 100 | `APPWRITE_` |
|
||||||
| Directus | 100 | `DIRECTUS_` |
|
| Directus | 100 | `DIRECTUS_` |
|
||||||
| System | 17 | (no config needed) |
|
| System | 24 | (no config needed) |
|
||||||
|
|
||||||
### Unified Tool Pattern
|
### Unified Tool Pattern
|
||||||
|
|
||||||
@@ -346,8 +346,8 @@ The `site` parameter accepts either a **site_id** (e.g., `site1`) or an **alias*
|
|||||||
Use specific endpoints to limit tool access:
|
Use specific endpoints to limit tool access:
|
||||||
|
|
||||||
```
|
```
|
||||||
/mcp → All 589 tools (Master API Key)
|
/mcp → All 596 tools (Master API Key)
|
||||||
/system/mcp → System tools only (17 tools)
|
/system/mcp → System tools only (24 tools)
|
||||||
/wordpress/mcp → WordPress tools (67 tools)
|
/wordpress/mcp → WordPress tools (67 tools)
|
||||||
/woocommerce/mcp → WooCommerce tools (28 tools)
|
/woocommerce/mcp → WooCommerce tools (28 tools)
|
||||||
/gitea/mcp → Gitea tools (56 tools)
|
/gitea/mcp → Gitea tools (56 tools)
|
||||||
@@ -448,7 +448,7 @@ The server auto-discovers all `WORDPRESS_*`, `WOOCOMMERCE_*`, `GITEA_*`, and oth
|
|||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
1. **Explore the full tool list**: See the [README](../README.md) for all 589 tools
|
1. **Explore the full tool list**: See the [README](../README.md) for all 596 tools
|
||||||
2. **Set up API keys**: [API Keys Guide](API_KEYS_GUIDE.md) for per-project access control
|
2. **Set up API keys**: [API Keys Guide](API_KEYS_GUIDE.md) for per-project access control
|
||||||
3. **Configure OAuth**: [OAuth Guide](OAUTH_GUIDE.md) for Claude/ChatGPT auto-registration
|
3. **Configure OAuth**: [OAuth Guide](OAUTH_GUIDE.md) for Claude/ChatGPT auto-registration
|
||||||
4. **Monitor health**: Use `check_all_projects_health` tool or visit the web dashboard
|
4. **Monitor health**: Use `check_all_projects_health` tool or visit the web dashboard
|
||||||
|
|||||||
32
server.py
32
server.py
@@ -1804,10 +1804,12 @@ def register_project_tools():
|
|||||||
|
|
||||||
logger.info("=" * 60)
|
logger.info("=" * 60)
|
||||||
|
|
||||||
# System tools count (health + rate limit + API keys):
|
# System tools count:
|
||||||
# - 10 system/health/rate limit tools
|
# - 10 health/monitoring/rate-limit tools
|
||||||
|
# - 4 system config tools (endpoints, system_info, audit_log, set_rate_limit_config)
|
||||||
# - 6 API key management tools
|
# - 6 API key management tools
|
||||||
system_tools_count = 16
|
# - 4 OAuth management tools
|
||||||
|
system_tools_count = 24
|
||||||
|
|
||||||
total_tools = tool_registry.get_count() + system_tools_count
|
total_tools = tool_registry.get_count() + system_tools_count
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -3338,7 +3340,7 @@ def create_system_mcp():
|
|||||||
"""
|
"""
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
|
||||||
system_instructions = """This is the System Management endpoint (17 tools).
|
system_instructions = """This is the System Management endpoint (24 tools).
|
||||||
|
|
||||||
Available tools:
|
Available tools:
|
||||||
• API Key Management: create, list, get_info, revoke, delete, rotate
|
• API Key Management: create, list, get_info, revoke, delete, rotate
|
||||||
@@ -3455,7 +3457,7 @@ Use get_endpoints() to see all available MCP endpoints."""
|
|||||||
requests_per_minute, requests_per_hour, requests_per_day
|
requests_per_minute, requests_per_hour, requests_per_day
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info("Created System endpoint with 17 tools")
|
logger.info("Created System endpoint with 24 tools")
|
||||||
return system_mcp
|
return system_mcp
|
||||||
|
|
||||||
|
|
||||||
@@ -4277,21 +4279,21 @@ def create_multi_endpoint_app(transport: str = "streamable-http"):
|
|||||||
app = Starlette(routes=routes, lifespan=combined_lifespan, middleware=middleware)
|
app = Starlette(routes=routes, lifespan=combined_lifespan, middleware=middleware)
|
||||||
|
|
||||||
logger.info("=" * 60)
|
logger.info("=" * 60)
|
||||||
logger.info("Multi-Endpoint Architecture (Phase K) Active")
|
logger.info("Multi-Endpoint Architecture Active")
|
||||||
logger.info("=" * 60)
|
logger.info("=" * 60)
|
||||||
logger.info("Dashboard: /dashboard") # Phase K
|
logger.info("Dashboard: /dashboard")
|
||||||
logger.info("Endpoints:")
|
logger.info("Endpoints:")
|
||||||
logger.info(" /mcp - Admin (all 589 tools)")
|
logger.info(f" /mcp - Admin (all {_total_tool_count} tools)")
|
||||||
logger.info(" /system/mcp - System (17 tools)")
|
logger.info(" /system/mcp - System (24 tools)")
|
||||||
logger.info(" /wordpress/mcp - WordPress Core (67 tools)")
|
logger.info(" /wordpress/mcp - WordPress Core (67 tools)")
|
||||||
logger.info(" /woocommerce/mcp - WooCommerce (28 tools)") # Phase D.1
|
logger.info(" /woocommerce/mcp - WooCommerce (28 tools)")
|
||||||
logger.info(" /wordpress-advanced/mcp - WordPress Advanced (22 tools)")
|
logger.info(" /wordpress-advanced/mcp - WordPress Advanced (22 tools)")
|
||||||
logger.info(" /gitea/mcp - Gitea (56 tools)")
|
logger.info(" /gitea/mcp - Gitea (56 tools)")
|
||||||
logger.info(" /n8n/mcp - n8n Automation (56 tools)") # Phase F
|
logger.info(" /n8n/mcp - n8n Automation (56 tools)")
|
||||||
logger.info(" /supabase/mcp - Supabase (70 tools)") # Phase G
|
logger.info(" /supabase/mcp - Supabase (70 tools)")
|
||||||
logger.info(" /openpanel/mcp - OpenPanel Analytics (73 tools)") # Phase H
|
logger.info(" /openpanel/mcp - OpenPanel Analytics (73 tools)")
|
||||||
logger.info(" /appwrite/mcp - Appwrite Backend (100 tools)") # Phase I
|
logger.info(" /appwrite/mcp - Appwrite Backend (100 tools)")
|
||||||
logger.info(" /directus/mcp - Directus CMS (100 tools)") # Phase J
|
logger.info(" /directus/mcp - Directus CMS (100 tools)")
|
||||||
|
|
||||||
# Log per-project endpoints
|
# Log per-project endpoints
|
||||||
if project_apps:
|
if project_apps:
|
||||||
|
|||||||
@@ -64,22 +64,18 @@ class TestPluginDisplayNames:
|
|||||||
|
|
||||||
|
|
||||||
class TestLanguageDetection:
|
class TestLanguageDetection:
|
||||||
"""Test language detection from headers and query params."""
|
"""Test language detection from query params (default English)."""
|
||||||
|
|
||||||
def test_default_english(self):
|
def test_default_english(self):
|
||||||
"""Should default to English."""
|
"""Should default to English."""
|
||||||
assert detect_language(None) == "en"
|
assert detect_language(None) == "en"
|
||||||
|
|
||||||
def test_detect_farsi_from_header(self):
|
def test_header_ignored(self):
|
||||||
"""Should detect Farsi from Accept-Language header."""
|
"""Accept-Language header should be ignored (always default to English)."""
|
||||||
assert detect_language("fa-IR,fa;q=0.9,en;q=0.8") == "fa"
|
assert detect_language("fa-IR,fa;q=0.9,en;q=0.8") == "en"
|
||||||
|
|
||||||
def test_detect_farsi_short(self):
|
def test_query_param_farsi(self):
|
||||||
"""Should detect 'fa' in Accept-Language."""
|
"""Should detect Farsi from explicit query parameter."""
|
||||||
assert detect_language("fa") == "fa"
|
|
||||||
|
|
||||||
def test_query_param_overrides_header(self):
|
|
||||||
"""Query parameter should override Accept-Language header."""
|
|
||||||
assert detect_language("en-US", query_lang="fa") == "fa"
|
assert detect_language("en-US", query_lang="fa") == "fa"
|
||||||
|
|
||||||
def test_query_param_english(self):
|
def test_query_param_english(self):
|
||||||
@@ -87,8 +83,8 @@ class TestLanguageDetection:
|
|||||||
assert detect_language("fa-IR", query_lang="en") == "en"
|
assert detect_language("fa-IR", query_lang="en") == "en"
|
||||||
|
|
||||||
def test_invalid_query_lang_ignored(self):
|
def test_invalid_query_lang_ignored(self):
|
||||||
"""Invalid query lang should be ignored, fall back to header."""
|
"""Invalid query lang should be ignored, default to English."""
|
||||||
assert detect_language("fa-IR", query_lang="de") == "fa"
|
assert detect_language("fa-IR", query_lang="de") == "en"
|
||||||
|
|
||||||
def test_english_header(self):
|
def test_english_header(self):
|
||||||
"""Should return English for English header."""
|
"""Should return English for English header."""
|
||||||
|
|||||||
Reference in New Issue
Block a user