Initial commit: MCP Hub Community Edition v3.0.0
Community edition generated from private repo via sync pipeline. Includes 9 plugins (WordPress, WooCommerce, WP Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with ~587 tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
585
docs/API_KEYS_GUIDE.md
Normal file
585
docs/API_KEYS_GUIDE.md
Normal file
@@ -0,0 +1,585 @@
|
||||
# 🔐 API Keys Management Guide
|
||||
|
||||
Complete guide for managing API keys in MCP Hub.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Key Types](#key-types)
|
||||
- [Scopes & Permissions](#scopes--permissions)
|
||||
- [Creating Keys](#creating-keys)
|
||||
- [Managing Keys](#managing-keys)
|
||||
- [Best Practices](#best-practices)
|
||||
- [Examples](#examples)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
MCP Hub supports two types of API keys for authentication:
|
||||
|
||||
1. **Master API Key** - Full access to all operations and projects
|
||||
2. **Per-Project API Keys** - Scoped access with granular permissions
|
||||
|
||||
Per-project keys provide:
|
||||
- ✅ **Project-level isolation** - Limit access to specific projects
|
||||
- ✅ **Scope-based permissions** - Control read/write/admin operations
|
||||
- ✅ **Expiration support** - Automatic key rotation
|
||||
- ✅ **Usage tracking** - Monitor key usage and last access
|
||||
- ✅ **Audit trail** - All key operations are logged
|
||||
- ✅ **Easy rotation** - Rotate all keys for a project with one command
|
||||
|
||||
---
|
||||
|
||||
## Key Types
|
||||
|
||||
### Master API Key
|
||||
|
||||
- **Source**: `MASTER_API_KEY` environment variable
|
||||
- **Access Level**: Full admin access to all projects
|
||||
- **Use Case**: Server administration, initial setup
|
||||
- **Lifetime**: Permanent (until manually changed)
|
||||
- **Format**: Any string (recommended: 32+ characters)
|
||||
|
||||
**Example**:
|
||||
```bash
|
||||
MASTER_API_KEY=your_secure_master_key_here
|
||||
```
|
||||
|
||||
### Per-Project API Keys
|
||||
|
||||
- **Storage**: JSON file (`data/api_keys.json`)
|
||||
- **Access Level**: Configurable per key (read/write/admin)
|
||||
- **Use Case**: Application integration, team access, CI/CD
|
||||
- **Lifetime**: Optional expiration (days)
|
||||
- **Format**: `cmp_` prefix + random string
|
||||
|
||||
**Example**:
|
||||
```
|
||||
cmp_AQECAHhoZXJlIGlzIGEgcmFuZG9tIGtleQ
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scopes & Permissions
|
||||
|
||||
### Read Scope
|
||||
|
||||
**Per-Project Keys** (`project_id` specific):
|
||||
- ✅ List and get operations for assigned project
|
||||
- ✅ Read WordPress content (posts, pages, comments, media)
|
||||
- ✅ Read WooCommerce data (products, orders, customers)
|
||||
- ✅ Read taxonomies, menus, and settings
|
||||
- ❌ Cannot access system tools (requires global key)
|
||||
- ❌ Cannot create, update, or delete
|
||||
|
||||
**Tools Allowed**:
|
||||
- `wordpress_list_posts`, `wordpress_get_post`
|
||||
- `wordpress_list_products`, `wordpress_get_product`
|
||||
- `wordpress_list_orders`, `wordpress_get_order`
|
||||
- All WordPress/WooCommerce `get_*` and `list_*` tools
|
||||
|
||||
**Global Keys** (`project_id="*"`):
|
||||
- ✅ All per-project permissions for ALL projects
|
||||
- ✅ System tools: `list_projects`, `get_project_info`
|
||||
- ✅ Monitoring: `check_all_projects_health`, `get_system_metrics`
|
||||
- ✅ Rate limits: `get_rate_limit_stats`
|
||||
- ✅ API Keys: `manage_api_keys_list` (read-only)
|
||||
|
||||
**Use Cases**:
|
||||
- **Per-Project**: Client access to their specific site
|
||||
- **Global**: Admin dashboards, monitoring, analytics
|
||||
|
||||
### Write Scope
|
||||
|
||||
**Per-Project Keys**:
|
||||
- ✅ All read operations for assigned project
|
||||
- ✅ Create, update, delete content
|
||||
- ✅ Upload and modify media
|
||||
- ✅ Manage products, orders, customers
|
||||
- ❌ Cannot access system tools (requires global key)
|
||||
- ❌ Cannot manage API keys or system settings
|
||||
|
||||
**Tools Allowed**:
|
||||
- All read scope tools for the project, plus:
|
||||
- `wordpress_create_post`, `wordpress_update_post`, `wordpress_delete_post`
|
||||
- `wordpress_create_product`, `wordpress_update_product`
|
||||
- `wordpress_create_order`, `wordpress_update_order_status`
|
||||
- `wordpress_upload_media_from_url`
|
||||
- All `create_*`, `update_*`, `delete_*` tools for the project
|
||||
|
||||
**Global Keys** (`project_id="*"`):
|
||||
- ✅ All per-project permissions for ALL projects
|
||||
- ✅ System tools access (read-only)
|
||||
|
||||
**Use Cases**:
|
||||
- **Per-Project**: Client content management for their site
|
||||
- **Global**: Multi-site management, automated publishing
|
||||
|
||||
### Admin Scope
|
||||
|
||||
**Per-Project Keys**:
|
||||
- ✅ All read and write operations for assigned project
|
||||
- ✅ Advanced WordPress management (WP-CLI tools)
|
||||
- ✅ Database operations (check, optimize, export)
|
||||
- ❌ Cannot access system tools (requires global key)
|
||||
- ❌ Cannot manage API keys (requires global key)
|
||||
|
||||
**Global Keys** (`project_id="*"`):
|
||||
- ✅ All per-project permissions for ALL projects
|
||||
- ✅ Full system access: `manage_api_keys_*`, `reset_rate_limit`
|
||||
- ✅ System monitoring and administration
|
||||
- ✅ Health metrics export
|
||||
|
||||
**Tools Allowed**:
|
||||
- All read and write scope tools, plus:
|
||||
- `manage_api_keys_*` tools (global keys only)
|
||||
- `reset_rate_limit` (global keys only)
|
||||
- `export_health_metrics`
|
||||
- WP-CLI tools: `wp_cache_flush`, `wp_db_optimize`, etc.
|
||||
|
||||
**Use Cases**:
|
||||
- **Per-Project**: Full site administration for specific client
|
||||
- **Global**: Platform administration, multi-tenant management
|
||||
- System maintenance
|
||||
|
||||
---
|
||||
|
||||
## Creating Keys
|
||||
|
||||
### Basic Key Creation
|
||||
|
||||
Create a read-only key for a specific project:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site1",
|
||||
scope="read"
|
||||
)
|
||||
|
||||
# Save the key - it won't be shown again!
|
||||
api_key = result["key"] # cmp_...
|
||||
key_id = result["key_id"] # key_...
|
||||
```
|
||||
|
||||
### Key with Description
|
||||
|
||||
Add a description for better organization:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site1",
|
||||
scope="write",
|
||||
description="CI/CD pipeline key for automated deployments"
|
||||
)
|
||||
```
|
||||
|
||||
### Expiring Key
|
||||
|
||||
Create a temporary key that expires after 30 days:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site2",
|
||||
scope="read",
|
||||
expires_in_days=30,
|
||||
description="Temporary access for contractor"
|
||||
)
|
||||
```
|
||||
|
||||
### Global Key
|
||||
|
||||
Create a key that works for all projects:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_create(
|
||||
project_id="*", # All projects
|
||||
scope="admin",
|
||||
description="Backup admin key"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Managing Keys
|
||||
|
||||
### List All Keys
|
||||
|
||||
```python
|
||||
result = manage_api_keys_list()
|
||||
|
||||
print(f"Total keys: {result['total']}")
|
||||
for key in result['keys']:
|
||||
print(f"- {key['key_id']}: {key['project_id']} ({key['scope']})")
|
||||
```
|
||||
|
||||
### List Keys for Specific Project
|
||||
|
||||
```python
|
||||
result = manage_api_keys_list(
|
||||
project_id="wordpress_site1"
|
||||
)
|
||||
```
|
||||
|
||||
### Include Revoked Keys
|
||||
|
||||
```python
|
||||
result = manage_api_keys_list(
|
||||
include_revoked=True
|
||||
)
|
||||
```
|
||||
|
||||
### Get Key Information
|
||||
|
||||
```python
|
||||
result = manage_api_keys_get_info(
|
||||
key_id="key_abc123"
|
||||
)
|
||||
|
||||
if result['success']:
|
||||
key_info = result['key']
|
||||
print(f"Project: {key_info['project_id']}")
|
||||
print(f"Scope: {key_info['scope']}")
|
||||
print(f"Created: {key_info['created_at']}")
|
||||
print(f"Last used: {key_info['last_used_at']}")
|
||||
print(f"Usage count: {key_info['usage_count']}")
|
||||
print(f"Valid: {key_info['valid']}")
|
||||
```
|
||||
|
||||
### Revoke a Key
|
||||
|
||||
Soft delete (can view in history):
|
||||
|
||||
```python
|
||||
result = manage_api_keys_revoke(
|
||||
key_id="key_abc123"
|
||||
)
|
||||
```
|
||||
|
||||
### Delete a Key
|
||||
|
||||
Permanent deletion:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_delete(
|
||||
key_id="key_abc123"
|
||||
)
|
||||
```
|
||||
|
||||
### Rotate All Project Keys
|
||||
|
||||
Create new keys and revoke old ones:
|
||||
|
||||
```python
|
||||
result = manage_api_keys_rotate(
|
||||
project_id="wordpress_site1"
|
||||
)
|
||||
|
||||
# Save the new keys!
|
||||
for new_key in result['new_keys']:
|
||||
print(f"New key: {new_key['key']}")
|
||||
print(f"Scope: {new_key['scope']}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use Principle of Least Privilege
|
||||
|
||||
**❌ Don't**:
|
||||
```python
|
||||
# Giving admin access when read is enough
|
||||
manage_api_keys_create("wordpress_site1", scope="admin")
|
||||
```
|
||||
|
||||
**✅ Do**:
|
||||
```python
|
||||
# Use minimal required scope
|
||||
manage_api_keys_create("wordpress_site1", scope="read")
|
||||
```
|
||||
|
||||
### 2. Set Expiration for Temporary Access
|
||||
|
||||
**❌ Don't**:
|
||||
```python
|
||||
# Permanent key for temporary contractor
|
||||
manage_api_keys_create("wordpress_site1", scope="write")
|
||||
```
|
||||
|
||||
**✅ Do**:
|
||||
```python
|
||||
# Expiring key for contractor
|
||||
manage_api_keys_create(
|
||||
"wordpress_site1",
|
||||
scope="write",
|
||||
expires_in_days=90,
|
||||
description="Q4 contractor access"
|
||||
)
|
||||
```
|
||||
|
||||
### 3. Use Descriptive Names
|
||||
|
||||
**❌ Don't**:
|
||||
```python
|
||||
manage_api_keys_create("wordpress_site1", "write")
|
||||
```
|
||||
|
||||
**✅ Do**:
|
||||
```python
|
||||
manage_api_keys_create(
|
||||
"wordpress_site1",
|
||||
scope="write",
|
||||
description="Production deployment key for CI/CD pipeline"
|
||||
)
|
||||
```
|
||||
|
||||
### 4. Regular Key Rotation
|
||||
|
||||
Rotate keys quarterly or after team changes:
|
||||
|
||||
```python
|
||||
# Every 3 months
|
||||
result = manage_api_keys_rotate("wordpress_site1")
|
||||
|
||||
# Update all integrations with new keys
|
||||
for key in result['new_keys']:
|
||||
# Update CI/CD, monitoring tools, etc.
|
||||
update_integration(key['key'])
|
||||
```
|
||||
|
||||
### 5. Monitor Key Usage
|
||||
|
||||
```python
|
||||
# Check if keys are being used
|
||||
result = manage_api_keys_list()
|
||||
|
||||
for key in result['keys']:
|
||||
if key['usage_count'] == 0:
|
||||
print(f"Warning: Key {key['key_id']} has never been used")
|
||||
|
||||
if key['last_used_at']:
|
||||
# Check if key hasn't been used in 30+ days
|
||||
# Consider revoking inactive keys
|
||||
pass
|
||||
```
|
||||
|
||||
### 6. Revoke Compromised Keys Immediately
|
||||
|
||||
```python
|
||||
# If a key is compromised
|
||||
manage_api_keys_revoke("key_compromised")
|
||||
|
||||
# Create a new key
|
||||
new_key = manage_api_keys_create(
|
||||
"wordpress_site1",
|
||||
scope="write",
|
||||
description="Replacement for compromised key"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: CI/CD Pipeline
|
||||
|
||||
```python
|
||||
# 1. Create a write-scoped key for CI/CD
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site1",
|
||||
scope="write",
|
||||
description="GitHub Actions deployment key"
|
||||
)
|
||||
|
||||
ci_key = result['key']
|
||||
|
||||
# 2. Add to GitHub Secrets as MCP_API_KEY
|
||||
|
||||
# 3. Use in workflow:
|
||||
# headers = {"Authorization": f"Bearer {os.getenv('MCP_API_KEY')}"}
|
||||
```
|
||||
|
||||
### Example 2: Monitoring Dashboard
|
||||
|
||||
```python
|
||||
# Create read-only key for monitoring
|
||||
result = manage_api_keys_create(
|
||||
project_id="*", # All projects
|
||||
scope="read",
|
||||
description="Grafana monitoring dashboard"
|
||||
)
|
||||
|
||||
monitoring_key = result['key']
|
||||
|
||||
# Use for health checks, metrics collection
|
||||
```
|
||||
|
||||
### Example 3: Team Member Access
|
||||
|
||||
```python
|
||||
# Create keys for team members
|
||||
team_keys = {}
|
||||
|
||||
for member in ["alice", "bob", "charlie"]:
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site1",
|
||||
scope="write",
|
||||
description=f"Key for {member}"
|
||||
)
|
||||
team_keys[member] = result['key']
|
||||
|
||||
# Distribute keys securely (1Password, etc.)
|
||||
```
|
||||
|
||||
### Example 4: Temporary Contractor Access
|
||||
|
||||
```python
|
||||
# 90-day expiring key for contractor
|
||||
result = manage_api_keys_create(
|
||||
project_id="wordpress_site2",
|
||||
scope="read",
|
||||
expires_in_days=90,
|
||||
description="Contractor access - expires Q1 2026"
|
||||
)
|
||||
|
||||
contractor_key = result['key']
|
||||
|
||||
# Key automatically becomes invalid after 90 days
|
||||
```
|
||||
|
||||
### Example 5: Key Rotation Schedule
|
||||
|
||||
```python
|
||||
# Quarterly rotation script
|
||||
import schedule
|
||||
|
||||
def rotate_all_projects():
|
||||
projects = ["wordpress_site1", "wordpress_site2", "wordpress_site3"]
|
||||
|
||||
for project in projects:
|
||||
result = manage_api_keys_rotate(project)
|
||||
print(f"Rotated {result['rotated_count']} keys for {project}")
|
||||
|
||||
# Email new keys to team
|
||||
notify_team(project, result['new_keys'])
|
||||
|
||||
# Run every 90 days
|
||||
schedule.every(90).days.do(rotate_all_projects)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Key Not Working
|
||||
|
||||
**Problem**: API key returns "Authentication failed"
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check if key is revoked:
|
||||
```python
|
||||
info = manage_api_keys_get_info("key_abc123")
|
||||
if info['key']['revoked']:
|
||||
print("Key has been revoked")
|
||||
```
|
||||
|
||||
2. Check if key expired:
|
||||
```python
|
||||
if info['key']['expired']:
|
||||
print("Key has expired")
|
||||
```
|
||||
|
||||
3. Verify scope matches operation:
|
||||
```python
|
||||
# Read-only key cannot write
|
||||
if info['key']['scope'] == 'read':
|
||||
print("Cannot use read key for write operations")
|
||||
```
|
||||
|
||||
### Key Not Found
|
||||
|
||||
**Problem**: "Key not found: key_abc123"
|
||||
|
||||
**Solution**: List all keys to find correct ID:
|
||||
```python
|
||||
result = manage_api_keys_list(include_revoked=True)
|
||||
for key in result['keys']:
|
||||
print(f"{key['key_id']}: {key['description']}")
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
|
||||
**Problem**: "Insufficient scope"
|
||||
|
||||
**Solution**: Check required scope for operation:
|
||||
```python
|
||||
# Operation requires 'write' but key has 'read'
|
||||
# Create new key with correct scope:
|
||||
manage_api_keys_create(project_id="site1", scope="write")
|
||||
```
|
||||
|
||||
### Storage File Issues
|
||||
|
||||
**Problem**: "Failed to load keys" or "Failed to save keys"
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. Check file permissions:
|
||||
```bash
|
||||
ls -l data/api_keys.json
|
||||
chmod 600 data/api_keys.json # Read/write for owner only
|
||||
```
|
||||
|
||||
2. Check directory exists:
|
||||
```bash
|
||||
mkdir -p data
|
||||
```
|
||||
|
||||
3. Validate JSON format:
|
||||
```bash
|
||||
python -m json.tool data/api_keys.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Storage Security
|
||||
|
||||
- API keys are stored as SHA256 hashes
|
||||
- Only the key hash is saved, not the actual key
|
||||
- Storage file should have restricted permissions (600)
|
||||
- Consider encrypting the storage file at rest
|
||||
|
||||
### Network Security
|
||||
|
||||
- Always use HTTPS for API requests
|
||||
- Never log API keys in plain text
|
||||
- Use secure channels to distribute keys (1Password, Vault)
|
||||
|
||||
### Audit & Compliance
|
||||
|
||||
- All key operations are logged in audit.log
|
||||
- Track key usage via `usage_count` and `last_used_at`
|
||||
- Regular review of active keys
|
||||
- Compliance with GDPR, SOC 2, ISO 27001
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Authentication Guide](AUTH_GUIDE.md)
|
||||
- [Security Policy](../SECURITY.md)
|
||||
- [Audit Logging](AUDIT_LOGGING.md)
|
||||
- [Rate Limiting](RATE_LIMITING.md)
|
||||
|
||||
---
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Last Updated**: 2025-11-11
|
||||
**Maintained by**: Airano (https://mcphub.dev)
|
||||
721
docs/GITEA_GUIDE.md
Normal file
721
docs/GITEA_GUIDE.md
Normal file
@@ -0,0 +1,721 @@
|
||||
# 🦊 Gitea Plugin Guide
|
||||
|
||||
**Complete guide for Gitea integration in MCP Hub**
|
||||
|
||||
Version: 1.0.0 (Phase C)
|
||||
Last Updated: 2025-11-19
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Features](#features)
|
||||
- [Installation](#installation)
|
||||
- [Configuration](#configuration)
|
||||
- [Tool Categories](#tool-categories)
|
||||
- [Usage Examples](#usage-examples)
|
||||
- [OAuth Integration](#oauth-integration)
|
||||
- [API Reference](#api-reference)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
The Gitea Plugin provides comprehensive Git repository management through Gitea's REST API. It enables AI assistants (like Claude) to manage repositories, issues, pull requests, and more directly from ChatGPT or other MCP-enabled clients.
|
||||
|
||||
### What is Gitea?
|
||||
|
||||
Gitea is a lightweight, self-hosted Git service similar to GitHub/GitLab. It provides:
|
||||
- Git repository hosting
|
||||
- Issue tracking
|
||||
- Pull requests
|
||||
- Code review
|
||||
- Webhooks
|
||||
- Organizations and teams
|
||||
|
||||
### Why This Plugin?
|
||||
|
||||
✅ **Git Workflow Automation** - Manage repositories from ChatGPT
|
||||
✅ **CI/CD Integration** - Trigger deployments with PR merges
|
||||
✅ **Issue Management** - AI-assisted issue triaging and responses
|
||||
✅ **Code Review** - Automated PR reviews and suggestions
|
||||
✅ **OAuth Support** - Seamless ChatGPT integration
|
||||
✅ **Multi-Site** - Manage multiple Gitea instances
|
||||
|
||||
---
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### 📦 Repository Management (15 Tools)
|
||||
|
||||
- **CRUD Operations**: Create, read, update, delete repositories
|
||||
- **Branch Management**: List, create, delete branches
|
||||
- **Tag Management**: Create and manage tags
|
||||
- **File Operations**: Read, create, update files in repository
|
||||
|
||||
### 🐛 Issue Tracking (12 Tools)
|
||||
|
||||
- **Issue Management**: Create, update, close, reopen issues
|
||||
- **Labels**: Create and manage issue labels
|
||||
- **Milestones**: Track project milestones
|
||||
- **Comments**: Add comments to issues
|
||||
|
||||
### 🔀 Pull Requests (15 Tools)
|
||||
|
||||
- **PR Operations**: Create, update, merge pull requests
|
||||
- **Code Review**: Review PRs, request changes, approve
|
||||
- **PR Details**: View commits, files, diff
|
||||
- **Reviewers**: Request reviewers for PRs
|
||||
|
||||
### 👥 User & Organization (8 Tools)
|
||||
|
||||
- **User Management**: Get user info, list repositories
|
||||
- **Organizations**: Manage organizations and teams
|
||||
- **Teams**: List team members
|
||||
- **Search**: Search for users
|
||||
|
||||
### 🔗 Webhooks (5 Tools)
|
||||
|
||||
- **Webhook Setup**: Create, list, delete webhooks
|
||||
- **Event Configuration**: Configure webhook events
|
||||
- **Testing**: Test webhook delivery
|
||||
|
||||
**Total: 55 Tools**
|
||||
|
||||
---
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Gitea instance (self-hosted or managed)
|
||||
- Gitea personal access token OR OAuth setup
|
||||
- MCP Hub installed
|
||||
|
||||
### 1. Enable Gitea Plugin
|
||||
|
||||
The Gitea plugin is built-in. No additional installation needed.
|
||||
|
||||
### 2. Configure Environment
|
||||
|
||||
Edit `.env` file:
|
||||
|
||||
```bash
|
||||
# Site 1 - Token Authentication
|
||||
GITEA_SITE1_URL=https://gitea.mcphub.dev
|
||||
GITEA_SITE1_TOKEN=your_personal_access_token_here
|
||||
GITEA_SITE1_ALIAS=mygitea
|
||||
|
||||
# Site 2 - OAuth Authentication (for ChatGPT)
|
||||
GITEA_SITE2_URL=https://git.company.com
|
||||
GITEA_SITE2_OAUTH_ENABLED=true
|
||||
GITEA_SITE2_ALIAS=workgit
|
||||
```
|
||||
|
||||
### 3. Generate Personal Access Token
|
||||
|
||||
#### In Gitea:
|
||||
|
||||
1. Log in to your Gitea instance
|
||||
2. Go to **Settings → Applications**
|
||||
3. Click **Generate New Token**
|
||||
4. Enter token name: `MCP Server`
|
||||
5. Select permissions:
|
||||
- ✅ **repo** (all) - Full repository access
|
||||
- ✅ **write:org** - Manage organizations
|
||||
- ✅ **read:user** - Read user information
|
||||
- ✅ **write:issue** - Create/edit issues and PRs
|
||||
6. Click **Generate Token**
|
||||
7. **Copy the token** (shown only once!)
|
||||
8. Add to `.env` as `GITEA_SITE1_TOKEN`
|
||||
|
||||
### 4. Restart Server
|
||||
|
||||
```bash
|
||||
# If running locally
|
||||
python server.py
|
||||
|
||||
# If running in Docker
|
||||
docker-compose restart
|
||||
|
||||
# If deployed in Coolify
|
||||
# Restart the service from Coolify dashboard
|
||||
```
|
||||
|
||||
### 5. Verify Installation
|
||||
|
||||
Check server logs for:
|
||||
|
||||
```
|
||||
✅ Gitea plugin loaded: gitea_site1 (mygitea)
|
||||
```
|
||||
|
||||
Or use health check tool:
|
||||
|
||||
```
|
||||
check_project_health(project_id="gitea_site1")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `GITEA_SITEX_URL` | ✅ Yes | - | Gitea instance URL |
|
||||
| `GITEA_SITEX_TOKEN` | ⚠️ Conditional | - | Personal access token (required if not using OAuth) |
|
||||
| `GITEA_SITEX_ALIAS` | ❌ No | - | Friendly site name |
|
||||
| `GITEA_SITEX_OAUTH_ENABLED` | ❌ No | `false` | Enable OAuth instead of token |
|
||||
|
||||
### Multiple Sites
|
||||
|
||||
You can configure unlimited Gitea instances:
|
||||
|
||||
```bash
|
||||
# Personal Gitea
|
||||
GITEA_SITE1_URL=https://gitea.mcphub.dev
|
||||
GITEA_SITE1_TOKEN=token1
|
||||
GITEA_SITE1_ALIAS=personal
|
||||
|
||||
# Work Gitea
|
||||
GITEA_SITE2_URL=https://git.company.com
|
||||
GITEA_SITE2_TOKEN=token2
|
||||
GITEA_SITE2_ALIAS=work
|
||||
|
||||
# Client Gitea
|
||||
GITEA_SITE3_URL=https://git.client.com
|
||||
GITEA_SITE3_TOKEN=token3
|
||||
GITEA_SITE3_ALIAS=client
|
||||
```
|
||||
|
||||
### OAuth vs Token Authentication
|
||||
|
||||
#### Token Authentication (Recommended for Scripts)
|
||||
|
||||
✅ **Pros:**
|
||||
- Simple setup
|
||||
- No user interaction needed
|
||||
- Suitable for automation
|
||||
|
||||
❌ **Cons:**
|
||||
- Tokens can expire
|
||||
- Manual renewal needed
|
||||
- Less secure if leaked
|
||||
|
||||
#### OAuth Authentication (Recommended for ChatGPT)
|
||||
|
||||
✅ **Pros:**
|
||||
- User-approved access
|
||||
- More secure
|
||||
- Automatic token refresh
|
||||
- Better for third-party apps
|
||||
|
||||
❌ **Cons:**
|
||||
- Requires OAuth setup
|
||||
- More complex configuration
|
||||
|
||||
---
|
||||
|
||||
## 🧰 Tool Categories
|
||||
|
||||
### 1. Repository Tools
|
||||
|
||||
#### List Repositories
|
||||
```
|
||||
gitea_list_repositories(site, owner?, type?, page?, limit?)
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
# List all my repositories
|
||||
gitea_list_repositories(site="mygitea")
|
||||
|
||||
# List user's repositories
|
||||
gitea_list_repositories(site="mygitea", owner="username")
|
||||
```
|
||||
|
||||
#### Create Repository
|
||||
```
|
||||
gitea_create_repository(site, name, description?, private?, auto_init?)
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
gitea_create_repository(
|
||||
site="mygitea",
|
||||
name="awesome-project",
|
||||
description="My awesome project",
|
||||
private=False,
|
||||
auto_init=True
|
||||
)
|
||||
```
|
||||
|
||||
#### Manage Branches
|
||||
```
|
||||
gitea_list_branches(site, owner, repo)
|
||||
gitea_create_branch(site, owner, repo, new_branch_name, old_branch_name?)
|
||||
gitea_delete_branch(site, owner, repo, branch)
|
||||
```
|
||||
|
||||
#### File Operations
|
||||
```
|
||||
gitea_get_file(site, owner, repo, path, ref?)
|
||||
gitea_create_file(site, owner, repo, path, content, message)
|
||||
gitea_update_file(site, owner, repo, path, content, sha, message)
|
||||
```
|
||||
|
||||
### 2. Issue Tools
|
||||
|
||||
#### Manage Issues
|
||||
```
|
||||
gitea_list_issues(site, owner, repo, state?, labels?, q?)
|
||||
gitea_create_issue(site, owner, repo, title, body?, labels?)
|
||||
gitea_update_issue(site, owner, repo, issue_number, ...)
|
||||
gitea_close_issue(site, owner, repo, issue_number)
|
||||
```
|
||||
|
||||
#### Labels & Milestones
|
||||
```
|
||||
gitea_list_labels(site, owner, repo)
|
||||
gitea_create_label(site, owner, repo, name, color, description?)
|
||||
gitea_list_milestones(site, owner, repo, state?)
|
||||
gitea_create_milestone(site, owner, repo, title, due_on?)
|
||||
```
|
||||
|
||||
### 3. Pull Request Tools
|
||||
|
||||
#### Manage PRs
|
||||
```
|
||||
gitea_create_pull_request(site, owner, repo, title, head, base, body?)
|
||||
gitea_merge_pull_request(site, owner, repo, pr_number, method?)
|
||||
gitea_list_pr_commits(site, owner, repo, pr_number)
|
||||
gitea_list_pr_files(site, owner, repo, pr_number)
|
||||
```
|
||||
|
||||
#### Code Review
|
||||
```
|
||||
gitea_create_pr_review(site, owner, repo, pr_number, event, body?)
|
||||
gitea_request_pr_reviewers(site, owner, repo, pr_number, reviewers)
|
||||
```
|
||||
|
||||
### 4. User & Organization Tools
|
||||
|
||||
```
|
||||
gitea_get_user(site, username)
|
||||
gitea_list_user_repos(site, username)
|
||||
gitea_list_organizations(site)
|
||||
gitea_list_org_teams(site, org)
|
||||
```
|
||||
|
||||
### 5. Webhook Tools
|
||||
|
||||
```
|
||||
gitea_list_webhooks(site, owner, repo)
|
||||
gitea_create_webhook(site, owner, repo, url, events)
|
||||
gitea_test_webhook(site, owner, repo, webhook_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Usage Examples
|
||||
|
||||
### Example 1: Create a Repository
|
||||
|
||||
```
|
||||
# Create a new repository with README
|
||||
gitea_create_repository(
|
||||
site="mygitea",
|
||||
name="my-new-project",
|
||||
description="A new project for testing",
|
||||
private=False,
|
||||
auto_init=True,
|
||||
license="MIT"
|
||||
)
|
||||
```
|
||||
|
||||
### Example 2: Create an Issue
|
||||
|
||||
```
|
||||
# Create an issue
|
||||
gitea_create_issue(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
title="Bug: Login not working",
|
||||
body="## Description\n\nUsers cannot log in after the latest update.\n\n## Steps to Reproduce\n1. Go to login page\n2. Enter credentials\n3. Click login\n\n## Expected\nShould log in successfully\n\n## Actual\nError message displayed",
|
||||
labels=[1, 3] # bug, high-priority
|
||||
)
|
||||
```
|
||||
|
||||
### Example 3: Create a Pull Request
|
||||
|
||||
```
|
||||
# Create feature branch
|
||||
gitea_create_branch(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
new_branch_name="feature/user-authentication",
|
||||
old_branch_name="main"
|
||||
)
|
||||
|
||||
# Make changes to files
|
||||
gitea_update_file(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
path="src/auth.js",
|
||||
content="// Updated authentication code\n...",
|
||||
sha="abc123",
|
||||
message="Add OAuth support",
|
||||
branch="feature/user-authentication"
|
||||
)
|
||||
|
||||
# Create pull request
|
||||
gitea_create_pull_request(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
title="Add OAuth Authentication",
|
||||
head="feature/user-authentication",
|
||||
base="main",
|
||||
body="This PR adds OAuth support for Google and GitHub authentication."
|
||||
)
|
||||
```
|
||||
|
||||
### Example 4: Review and Merge PR
|
||||
|
||||
```
|
||||
# List open PRs
|
||||
gitea_list_pull_requests(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
state="open"
|
||||
)
|
||||
|
||||
# Review the PR
|
||||
gitea_create_pr_review(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
pr_number=5,
|
||||
event="APPROVED",
|
||||
body="LGTM! Great work on the OAuth implementation."
|
||||
)
|
||||
|
||||
# Merge the PR
|
||||
gitea_merge_pull_request(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
pr_number=5,
|
||||
method="squash",
|
||||
delete_branch_after_merge=True
|
||||
)
|
||||
```
|
||||
|
||||
### Example 5: Setup Webhook for CI/CD
|
||||
|
||||
```
|
||||
# Create webhook for Coolify deployment
|
||||
gitea_create_webhook(
|
||||
site="mygitea",
|
||||
owner="myuser",
|
||||
repo="my-project",
|
||||
url="https://coolify.example.com/webhooks/deploy",
|
||||
events=["push", "pull_request"],
|
||||
content_type="json",
|
||||
secret="webhook_secret_here"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 OAuth Integration
|
||||
|
||||
### Setup OAuth for ChatGPT
|
||||
|
||||
#### 1. Configure Server
|
||||
|
||||
In `.env`:
|
||||
```bash
|
||||
# Enable OAuth for Gitea site
|
||||
GITEA_SITE1_URL=https://gitea.mcphub.dev
|
||||
GITEA_SITE1_OAUTH_ENABLED=true
|
||||
GITEA_SITE1_ALIAS=mygitea
|
||||
|
||||
# OAuth settings (if not already set)
|
||||
OAUTH_JWT_SECRET_KEY=your_jwt_secret_here
|
||||
OAUTH_AUTH_MODE=trusted_domains
|
||||
OAUTH_TRUSTED_DOMAINS=chatgpt.com,chat.openai.com,openai.com
|
||||
```
|
||||
|
||||
#### 2. Create GPT Action
|
||||
|
||||
In ChatGPT GPTs:
|
||||
|
||||
1. Go to **Configure → Actions**
|
||||
2. Click **Create new action**
|
||||
3. Import OpenAPI schema from: `https://your-server.com/.well-known/oauth-authorization-server`
|
||||
4. Set OAuth:
|
||||
- **Client ID**: Auto-registered via dynamic registration
|
||||
- **Authorization URL**: `https://your-server.com/oauth/authorize`
|
||||
- **Token URL**: `https://your-server.com/oauth/token`
|
||||
|
||||
#### 3. Use from ChatGPT
|
||||
|
||||
```
|
||||
User: "Create a new repository called 'test-repo' in my Gitea"
|
||||
|
||||
Claude: Sure! I'll create a new repository.
|
||||
[Calls gitea_create_repository with OAuth token]
|
||||
```
|
||||
|
||||
### API Key with OAuth
|
||||
|
||||
For additional security, you can require API Keys even with OAuth:
|
||||
|
||||
```bash
|
||||
OAUTH_AUTH_MODE=required
|
||||
```
|
||||
|
||||
Then users must provide API Key in authorization URL:
|
||||
```
|
||||
/oauth/authorize?client_id=xxx&...&api_key=cmp_your_key_here
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 API Reference
|
||||
|
||||
### Tool Naming Convention
|
||||
|
||||
All Gitea tools follow this pattern:
|
||||
```
|
||||
gitea_<action>_<resource>(site, ...params)
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `gitea_create_repository`
|
||||
- `gitea_list_issues`
|
||||
- `gitea_merge_pull_request`
|
||||
|
||||
### Common Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `site` | string | ✅ | Site ID or alias (e.g., "mygitea") |
|
||||
| `owner` | string | ✅ | Repository owner username/org |
|
||||
| `repo` | string | ✅ | Repository name |
|
||||
| `page` | integer | ❌ | Page number (default: 1) |
|
||||
| `limit` | integer | ❌ | Items per page (default: 30, max: 100) |
|
||||
|
||||
### Response Format
|
||||
|
||||
All tools return consistent response format:
|
||||
|
||||
**Success:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Operation completed",
|
||||
"data": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
**Error:**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Error description",
|
||||
"code": "ERROR_CODE"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. "Authentication failed"
|
||||
|
||||
**Cause**: Invalid or expired token
|
||||
|
||||
**Solution**:
|
||||
- Regenerate personal access token in Gitea
|
||||
- Update `GITEA_SITEX_TOKEN` in `.env`
|
||||
- Restart server
|
||||
|
||||
#### 2. "Repository not found"
|
||||
|
||||
**Cause**: Incorrect owner or repo name
|
||||
|
||||
**Solution**:
|
||||
- Verify repository exists in Gitea
|
||||
- Check spelling of owner/repo
|
||||
- Ensure user has access to repository
|
||||
|
||||
#### 3. "Permission denied"
|
||||
|
||||
**Cause**: Token lacks required permissions
|
||||
|
||||
**Solution**:
|
||||
- Regenerate token with correct permissions:
|
||||
- `repo` (all)
|
||||
- `write:org`
|
||||
- `read:user`
|
||||
- `write:issue`
|
||||
|
||||
#### 4. "Webhook creation failed"
|
||||
|
||||
**Cause**: Invalid webhook URL or insufficient permissions
|
||||
|
||||
**Solution**:
|
||||
- Verify webhook URL is accessible
|
||||
- Ensure user has admin access to repository
|
||||
- Check webhook events are valid
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
LOG_LEVEL=DEBUG
|
||||
```
|
||||
|
||||
Check logs:
|
||||
```bash
|
||||
tail -f logs/audit.log | jq
|
||||
```
|
||||
|
||||
### Health Check
|
||||
|
||||
Test Gitea connectivity:
|
||||
|
||||
```
|
||||
check_project_health(project_id="gitea_site1")
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"healthy": true,
|
||||
"message": "Gitea instance is accessible"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Best Practices
|
||||
|
||||
### 1. Security
|
||||
|
||||
- ✅ Use **personal access tokens** with minimal required permissions
|
||||
- ✅ Enable **OAuth** for third-party access (ChatGPT)
|
||||
- ✅ Rotate tokens regularly
|
||||
- ✅ Use **private repositories** for sensitive code
|
||||
- ✅ Enable **webhook secrets** for webhook security
|
||||
- ✅ Use **per-project API keys** instead of master key
|
||||
|
||||
### 2. Git Workflow
|
||||
|
||||
- ✅ Create **feature branches** for new features
|
||||
- ✅ Use **pull requests** for code review
|
||||
- ✅ Add **meaningful commit messages**
|
||||
- ✅ Use **labels** for issue categorization
|
||||
- ✅ Set **milestones** for project planning
|
||||
- ✅ **Squash merge** to keep history clean
|
||||
|
||||
### 3. Automation
|
||||
|
||||
- ✅ Setup **webhooks** for CI/CD integration
|
||||
- ✅ Auto-close issues when PR is merged
|
||||
- ✅ Use **labels** to trigger automation
|
||||
- ✅ Create **templates** for issues and PRs
|
||||
|
||||
### 4. Performance
|
||||
|
||||
- ✅ Use **pagination** for large result sets
|
||||
- ✅ Cache repository information when possible
|
||||
- ✅ Use **search** instead of listing all items
|
||||
- ✅ Batch operations when possible
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Use Cases
|
||||
|
||||
### 1. Automated Issue Triage
|
||||
|
||||
```
|
||||
# AI assistant automatically:
|
||||
1. Lists open issues
|
||||
2. Analyzes issue content
|
||||
3. Adds appropriate labels
|
||||
4. Assigns to team members
|
||||
5. Sets milestone
|
||||
```
|
||||
|
||||
### 2. AI Code Review
|
||||
|
||||
```
|
||||
# AI assistant reviews PRs:
|
||||
1. Lists open PRs
|
||||
2. Gets PR diff
|
||||
3. Analyzes code changes
|
||||
4. Adds review comments
|
||||
5. Approves or requests changes
|
||||
```
|
||||
|
||||
### 3. Automated Releases
|
||||
|
||||
```
|
||||
# Create release workflow:
|
||||
1. Create release branch
|
||||
2. Update version numbers
|
||||
3. Generate changelog
|
||||
4. Create pull request
|
||||
5. After merge: create tag and release
|
||||
```
|
||||
|
||||
### 4. Documentation Updates
|
||||
|
||||
```
|
||||
# Keep docs in sync:
|
||||
1. Detect code changes
|
||||
2. Update corresponding documentation
|
||||
3. Create PR for doc updates
|
||||
4. Request review from maintainers
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📖 Related Documentation
|
||||
|
||||
- [OAuth Guide](OAUTH_GUIDE.md) - Complete OAuth 2.1 setup
|
||||
- [API Keys Guide](API_KEYS_USAGE.md) - API key management
|
||||
- [Gitea API Docs](https://docs.gitea.io/en-us/api-usage/) - Official Gitea API
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
### Need Help?
|
||||
|
||||
- 📧 **Email**: hello@mcphub.dev
|
||||
- 🐛 **Issues**: [GitHub Issues](https://github.com/airano-ir/mcphub/issues)
|
||||
- 📚 **Docs**: [Full Documentation](../README.md)
|
||||
|
||||
### Contributing
|
||||
|
||||
Contributions welcome! See [CONTRIBUTING.md](../CONTRIBUTING.md)
|
||||
|
||||
---
|
||||
|
||||
**Version**: 3.0.0
|
||||
344
docs/MULTI_ENDPOINT_GUIDE.md
Normal file
344
docs/MULTI_ENDPOINT_GUIDE.md
Normal file
@@ -0,0 +1,344 @@
|
||||
# Multi-Endpoint Architecture Guide
|
||||
|
||||
> Solving the Tool Visibility Problem
|
||||
|
||||
---
|
||||
|
||||
## The Problem
|
||||
|
||||
### Before (Single Endpoint)
|
||||
```
|
||||
Client connects to /mcp
|
||||
↓
|
||||
Sees ALL 188 tools
|
||||
↓
|
||||
API key for site4 can see:
|
||||
- ✅ WordPress tools (but for all sites!)
|
||||
- ❌ Gitea tools (shouldn't see)
|
||||
- ❌ System tools (shouldn't see)
|
||||
- ❌ API key management (security risk!)
|
||||
```
|
||||
|
||||
### Issue
|
||||
- Users saw tools they couldn't use
|
||||
- Wasted AI context on irrelevant tools
|
||||
- Security concern: tool enumeration
|
||||
- Confusing UX
|
||||
|
||||
---
|
||||
|
||||
## The Solution
|
||||
|
||||
### After (Multi-Endpoint)
|
||||
```
|
||||
Client connects to /mcp/wordpress
|
||||
↓
|
||||
Sees ONLY 92 WordPress tools
|
||||
↓
|
||||
Clean, focused, secure
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Overview
|
||||
|
||||
| Endpoint | Tools | Requires | Use Case |
|
||||
|----------|-------|----------|----------|
|
||||
| `/mcp` | 188 | Master Key | Admin operations |
|
||||
| `/mcp/wordpress` | 92 | API Key | WordPress management |
|
||||
| `/mcp/wordpress-advanced` | 22 | Admin Key | DB/Bulk/System ops |
|
||||
| `/mcp/gitea` | 55 | API Key | Git management |
|
||||
| `/mcp/project/{id}` | Varies | Project Key | Single project |
|
||||
|
||||
---
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### For Existing Users
|
||||
|
||||
**Before (v1.x)**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"coolify": {
|
||||
"url": "https://mcp.example.com/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer cmp_xxx"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After (v2.0)**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"wordpress": {
|
||||
"url": "https://mcp.example.com/mcp/wordpress",
|
||||
"headers": {
|
||||
"Authorization": "Bearer cmp_xxx"
|
||||
}
|
||||
},
|
||||
"gitea": {
|
||||
"url": "https://mcp.example.com/mcp/gitea",
|
||||
"headers": {
|
||||
"Authorization": "Bearer cmp_yyy"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Benefits After Migration
|
||||
- Faster tool discovery
|
||||
- Less AI context used
|
||||
- Better security
|
||||
- Clearer access control
|
||||
|
||||
---
|
||||
|
||||
## API Key Configuration
|
||||
|
||||
### Creating WordPress-Only Key
|
||||
```bash
|
||||
# Using admin endpoint with Master Key
|
||||
curl -X POST https://mcp.example.com/mcp \
|
||||
-H "Authorization: Bearer sk-master-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"tool": "manage_api_keys_create",
|
||||
"arguments": {
|
||||
"project_id": "wordpress_site1",
|
||||
"scope": "write",
|
||||
"name": "Site1 Editor"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Key Scopes
|
||||
|
||||
| Scope | Permissions |
|
||||
|-------|-------------|
|
||||
| `read` | Read-only operations |
|
||||
| `write` | Read + create/update |
|
||||
| `admin` | Full access + system tools |
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Details
|
||||
|
||||
### `/mcp` - Admin Endpoint
|
||||
|
||||
**Access**: Master API Key (`sk-*`) only
|
||||
|
||||
**Tools**: All 188 tools including:
|
||||
- WordPress Core (92)
|
||||
- WordPress Advanced (22)
|
||||
- Gitea (55)
|
||||
- System tools (19)
|
||||
- API key management
|
||||
- OAuth management
|
||||
|
||||
**Use Cases**:
|
||||
- Initial setup
|
||||
- Creating API keys
|
||||
- System monitoring
|
||||
- OAuth client management
|
||||
|
||||
---
|
||||
|
||||
### `/mcp/wordpress` - WordPress Endpoint
|
||||
|
||||
**Access**: Any valid API key
|
||||
|
||||
**Tools**: 92 WordPress tools
|
||||
- Posts & Pages
|
||||
- Media
|
||||
- Taxonomy
|
||||
- Comments
|
||||
- Users
|
||||
- WooCommerce
|
||||
- SEO
|
||||
|
||||
**Blacklisted Tools**:
|
||||
- `manage_api_keys_*`
|
||||
- `oauth_*`
|
||||
- System tools
|
||||
|
||||
**Use Cases**:
|
||||
- Content management
|
||||
- WooCommerce operations
|
||||
- SEO management
|
||||
|
||||
---
|
||||
|
||||
### `/mcp/wordpress-advanced` - Advanced WordPress Endpoint
|
||||
|
||||
**Access**: Admin scope required
|
||||
|
||||
**Tools**: 22 advanced tools
|
||||
- Database operations
|
||||
- Bulk operations
|
||||
- System operations
|
||||
|
||||
**Use Cases**:
|
||||
- Database backup/restore
|
||||
- Bulk content updates
|
||||
- System maintenance
|
||||
|
||||
---
|
||||
|
||||
### `/mcp/gitea` - Gitea Endpoint
|
||||
|
||||
**Access**: Any valid API key (with gitea project)
|
||||
|
||||
**Tools**: 55 Gitea tools
|
||||
- Repository management
|
||||
- Issue tracking
|
||||
- Pull requests
|
||||
- Webhooks
|
||||
|
||||
**Use Cases**:
|
||||
- Git operations
|
||||
- Issue management
|
||||
- PR reviews
|
||||
|
||||
---
|
||||
|
||||
### `/mcp/project/{id}` - Project Endpoint
|
||||
|
||||
**Access**: API key matching project_id
|
||||
|
||||
**Tools**: Plugin tools filtered to single project
|
||||
|
||||
**Example**: `/mcp/project/wordpress_site1`
|
||||
- Only WordPress tools
|
||||
- Site parameter auto-set to `site1`
|
||||
|
||||
**Use Cases**:
|
||||
- Single-site management
|
||||
- Restricted access per client
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Tool Blacklisting
|
||||
|
||||
System and admin tools are blacklisted from non-admin endpoints:
|
||||
```python
|
||||
tool_blacklist = {
|
||||
"manage_api_keys_create",
|
||||
"manage_api_keys_delete",
|
||||
"manage_api_keys_rotate",
|
||||
"oauth_register_client",
|
||||
"oauth_revoke_client",
|
||||
}
|
||||
```
|
||||
|
||||
### API Key Validation
|
||||
|
||||
Each endpoint validates:
|
||||
1. Token format and validity
|
||||
2. Scope requirements
|
||||
3. Plugin type matching
|
||||
4. Tool-level access
|
||||
|
||||
### Audit Logging
|
||||
|
||||
All tool calls are logged with:
|
||||
- Endpoint path
|
||||
- Tool name
|
||||
- API key ID
|
||||
- Timestamp
|
||||
- Success/failure
|
||||
|
||||
---
|
||||
|
||||
## Running the Server
|
||||
|
||||
### Development
|
||||
```bash
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run multi-endpoint server
|
||||
python server_multi.py --port 8000
|
||||
```
|
||||
|
||||
### Production (Docker)
|
||||
```bash
|
||||
# Build
|
||||
docker-compose build
|
||||
|
||||
# Run
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
```bash
|
||||
# Required
|
||||
MASTER_API_KEY=sk-your-secure-key
|
||||
|
||||
# WordPress
|
||||
WORDPRESS_SITE1_URL=https://example.com
|
||||
WORDPRESS_SITE1_USERNAME=admin
|
||||
WORDPRESS_SITE1_PASSWORD=app_password
|
||||
|
||||
# Gitea
|
||||
GITEA_SITE1_URL=https://gitea.example.com
|
||||
GITEA_SITE1_TOKEN=your-token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Endpoints
|
||||
|
||||
### Check Available Endpoints
|
||||
```bash
|
||||
curl http://localhost:8000/endpoints
|
||||
```
|
||||
|
||||
### Check Health
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
### Test WordPress Endpoint
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/mcp/wordpress \
|
||||
-H "Authorization: Bearer cmp_xxx" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tool": "wordpress_list_posts", "arguments": {"site": "site1"}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Endpoint requires master API key"
|
||||
- Use `/mcp` endpoint with Master Key for admin operations
|
||||
- Or use appropriate plugin endpoint with project API key
|
||||
|
||||
### "API key cannot access this endpoint"
|
||||
- API key project_id must match endpoint plugin type
|
||||
- Example: `wordpress_site1` key works on `/mcp/wordpress`, not `/mcp/gitea`
|
||||
|
||||
### "Access denied to tool"
|
||||
- Tool may be blacklisted for this endpoint
|
||||
- Check if admin scope is required
|
||||
|
||||
---
|
||||
|
||||
## Future Improvements
|
||||
|
||||
- [ ] Per-project endpoints (`/mcp/project/{id}`)
|
||||
- [ ] Dynamic endpoint creation
|
||||
- [ ] Custom tool whitelists
|
||||
- [ ] Endpoint-level rate limiting
|
||||
- [ ] Endpoint usage analytics
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-11-24
|
||||
1025
docs/OAUTH_GUIDE.md
Normal file
1025
docs/OAUTH_GUIDE.md
Normal file
File diff suppressed because it is too large
Load Diff
1131
docs/appwrite-plugin-design.md
Normal file
1131
docs/appwrite-plugin-design.md
Normal file
File diff suppressed because it is too large
Load Diff
1420
docs/directus-plugin-design.md
Normal file
1420
docs/directus-plugin-design.md
Normal file
File diff suppressed because it is too large
Load Diff
448
docs/getting-started.md
Normal file
448
docs/getting-started.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# 🚀 Getting Started with MCP Hub
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Prerequisites](#prerequisites)
|
||||
2. [Installation](#installation)
|
||||
3. [Configuration](#configuration)
|
||||
4. [Running the Server](#running-the-server)
|
||||
5. [Testing Your Setup](#testing-your-setup)
|
||||
6. [Using MCP Tools](#using-mcp-tools)
|
||||
7. [Docker Deployment](#docker-deployment)
|
||||
8. [Coolify Deployment](#coolify-deployment)
|
||||
9. [Next Steps](#next-steps)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following installed:
|
||||
|
||||
### Required
|
||||
|
||||
- **Python 3.11+**: [Download Python](https://www.python.org/downloads/)
|
||||
- **Git**: [Download Git](https://git-scm.com/downloads)
|
||||
|
||||
### Optional (for Docker deployment)
|
||||
|
||||
- **Docker**: [Download Docker Desktop](https://www.docker.com/products/docker-desktop)
|
||||
- **Docker Compose**: Included with Docker Desktop
|
||||
|
||||
### WordPress Requirements
|
||||
|
||||
For each WordPress site you want to manage:
|
||||
|
||||
- WordPress 5.0+
|
||||
- **Application Passwords** enabled (WordPress 5.6+)
|
||||
- **WooCommerce** 3.0+ (if using WooCommerce tools)
|
||||
- **Rank Math** or **Yoast SEO** (if using SEO tools)
|
||||
- HTTPS enabled (recommended)
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### Option 1: Automated Setup (Recommended)
|
||||
|
||||
#### Linux/Mac
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/mcphub/mcphub.git
|
||||
cd mcphub
|
||||
|
||||
# Run setup script
|
||||
chmod +x scripts/setup.sh
|
||||
./scripts/setup.sh
|
||||
```
|
||||
|
||||
#### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
# Clone the repository
|
||||
git clone https://github.com/mcphub/mcphub.git
|
||||
cd mcphub
|
||||
|
||||
# Run setup script
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
|
||||
.\scripts\setup.ps1
|
||||
```
|
||||
|
||||
### Option 2: Manual Setup
|
||||
|
||||
```bash
|
||||
# 1. Clone repository
|
||||
git clone https://github.com/mcphub/mcphub.git
|
||||
cd mcphub
|
||||
|
||||
# 2. Create virtual environment
|
||||
python3 -m venv venv
|
||||
|
||||
# 3. Activate virtual environment
|
||||
# Linux/Mac:
|
||||
source venv/bin/activate
|
||||
# Windows:
|
||||
.\venv\Scripts\Activate.ps1
|
||||
|
||||
# 4. Install dependencies
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 5. Copy environment template
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Step 1: Generate WordPress Application Passwords
|
||||
|
||||
For each WordPress site:
|
||||
|
||||
1. Log in to WordPress admin
|
||||
2. Navigate to: **Users → Your Profile**
|
||||
3. Scroll to **Application Passwords** section
|
||||
4. Enter name: `MCP Server`
|
||||
5. Click **Add New Application Password**
|
||||
6. Copy the generated password (format: `xxxx xxxx xxxx xxxx xxxx xxxx`)
|
||||
|
||||
**Important**: Save this password immediately. You cannot retrieve it later.
|
||||
|
||||
### Step 2: Generate WooCommerce API Keys
|
||||
|
||||
If using WooCommerce tools:
|
||||
|
||||
1. Go to: **WooCommerce → Settings → Advanced → REST API**
|
||||
2. Click **Add Key**
|
||||
3. Fill in:
|
||||
- **Description**: `MCP Server`
|
||||
- **User**: Select admin user
|
||||
- **Permissions**: `Read/Write`
|
||||
4. Click **Generate API Key**
|
||||
5. Copy **Consumer Key** and **Consumer Secret**
|
||||
|
||||
### Step 3: Configure Environment Variables
|
||||
|
||||
Edit `.env` file:
|
||||
|
||||
```bash
|
||||
# Basic Configuration
|
||||
MCP_SERVER_NAME=mcphub
|
||||
MCP_SERVER_VERSION=1.0.0
|
||||
|
||||
# Site 1 - Main WordPress Site
|
||||
WORDPRESS_SITE1_URL=https://example.com
|
||||
WORDPRESS_SITE1_USERNAME=admin
|
||||
WORDPRESS_SITE1_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
WORDPRESS_SITE1_WC_CONSUMER_KEY=ck_xxxxxxxxxxxxx
|
||||
WORDPRESS_SITE1_WC_CONSUMER_SECRET=cs_xxxxxxxxxxxxx
|
||||
WORDPRESS_SITE1_ALIAS=mainsite
|
||||
|
||||
# Site 2 - E-commerce Site (Optional)
|
||||
WORDPRESS_SITE2_URL=https://shop.example.com
|
||||
WORDPRESS_SITE2_USERNAME=admin
|
||||
WORDPRESS_SITE2_APP_PASSWORD=yyyy yyyy yyyy yyyy yyyy yyyy
|
||||
WORDPRESS_SITE2_WC_CONSUMER_KEY=ck_yyyyyyyyyyyyy
|
||||
WORDPRESS_SITE2_WC_CONSUMER_SECRET=cs_yyyyyyyyyyyyy
|
||||
WORDPRESS_SITE2_ALIAS=shop
|
||||
|
||||
# Site 3 - Blog Site (Optional)
|
||||
WORDPRESS_SITE3_URL=https://blog.example.com
|
||||
WORDPRESS_SITE3_USERNAME=admin
|
||||
WORDPRESS_SITE3_APP_PASSWORD=zzzz zzzz zzzz zzzz zzzz zzzz
|
||||
WORDPRESS_SITE3_ALIAS=blog
|
||||
|
||||
# Rate Limiting (Optional)
|
||||
RATE_LIMIT_PER_MINUTE=60
|
||||
RATE_LIMIT_PER_HOUR=1000
|
||||
RATE_LIMIT_PER_DAY=10000
|
||||
|
||||
# Logging (Optional)
|
||||
LOG_LEVEL=INFO
|
||||
```
|
||||
|
||||
### Configuration Tips
|
||||
|
||||
- **Site Aliases**: Use friendly names like `mainsite`, `shop`, or `blog`
|
||||
- **Minimal WooCommerce**: Only configure WooCommerce keys if you need e-commerce tools
|
||||
- **Testing**: Start with one site, verify it works, then add more
|
||||
- **Security**: Never commit `.env` file to git
|
||||
|
||||
---
|
||||
|
||||
## Running the Server
|
||||
|
||||
### Development Mode
|
||||
|
||||
```bash
|
||||
# Activate virtual environment (if not already active)
|
||||
source venv/bin/activate # Linux/Mac
|
||||
.\venv\Scripts\Activate.ps1 # Windows
|
||||
|
||||
# Run server
|
||||
python src/main.py
|
||||
|
||||
# Or use the dev script
|
||||
./scripts/dev.sh # Linux/Mac
|
||||
```
|
||||
|
||||
### Verify Server is Running
|
||||
|
||||
Check logs for:
|
||||
|
||||
```
|
||||
INFO: MCP Server initialized
|
||||
INFO: Registered 390 tools
|
||||
INFO: Server ready
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Your Setup
|
||||
|
||||
### Quick Health Check
|
||||
|
||||
Run the test script:
|
||||
|
||||
```bash
|
||||
./scripts/test.sh quick
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov
|
||||
|
||||
# Run specific test
|
||||
pytest tests/test_wordpress_plugin.py
|
||||
```
|
||||
|
||||
### Verify Tool Registration
|
||||
|
||||
Check that tools are registered:
|
||||
|
||||
```bash
|
||||
python -c "
|
||||
from src.main import app
|
||||
tools = app.list_tools()
|
||||
print(f'Total tools: {len(tools)}')
|
||||
"
|
||||
```
|
||||
|
||||
Expected output: `Total tools: 390` (for 3 configured sites)
|
||||
|
||||
---
|
||||
|
||||
## Using MCP Tools
|
||||
|
||||
### Tool Naming Convention
|
||||
|
||||
#### Per-Site Tools (Legacy)
|
||||
```
|
||||
wordpress_{site}_action
|
||||
```
|
||||
Examples:
|
||||
- `wordpress_site1_list_posts`
|
||||
- `wordpress_site2_get_product`
|
||||
- `wordpress_site3_create_page`
|
||||
|
||||
#### Unified Tools (Recommended)
|
||||
```
|
||||
wordpress_action(site="site_id", ...)
|
||||
```
|
||||
Examples:
|
||||
- `wordpress_list_posts(site="site1")`
|
||||
- `wordpress_get_product(site="shop", product_id=123)`
|
||||
- `wordpress_create_page(site="blog", title="Hello", content="...")`
|
||||
|
||||
### Using Site Aliases
|
||||
|
||||
If you configured `WORDPRESS_SITE2_ALIAS=shop`:
|
||||
|
||||
```python
|
||||
# Both work the same
|
||||
wordpress_list_products(site="site2")
|
||||
wordpress_list_products(site="shop")
|
||||
```
|
||||
|
||||
### Example: List Posts
|
||||
|
||||
**Using Per-Site Tools**:
|
||||
```python
|
||||
result = wordpress_site1_list_posts(per_page=10, status="publish")
|
||||
```
|
||||
|
||||
**Using Unified Tools**:
|
||||
```python
|
||||
result = wordpress_list_posts(site="mainsite", per_page=10, status="publish")
|
||||
```
|
||||
|
||||
### Example: Create Product
|
||||
|
||||
```python
|
||||
result = wordpress_create_product(
|
||||
site="shop",
|
||||
name="New Product",
|
||||
type="simple",
|
||||
regular_price="29.99",
|
||||
description="Product description",
|
||||
status="publish"
|
||||
)
|
||||
```
|
||||
|
||||
### Example: Update Page
|
||||
|
||||
```python
|
||||
result = wordpress_update_page(
|
||||
site="blog",
|
||||
page_id=42,
|
||||
title="Updated Title",
|
||||
content="<p>Updated content</p>",
|
||||
status="publish"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
### Quick Start
|
||||
|
||||
```bash
|
||||
# Deploy with Docker
|
||||
./scripts/deploy.sh
|
||||
|
||||
# Or manually
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Docker Commands
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
|
||||
# Restart
|
||||
docker compose restart
|
||||
|
||||
# Stop
|
||||
docker compose down
|
||||
|
||||
# Rebuild
|
||||
docker compose up --build -d
|
||||
```
|
||||
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
# Check container health
|
||||
docker compose ps
|
||||
|
||||
# Test API endpoint
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coolify Deployment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Coolify instance running
|
||||
- Docker registry access (optional)
|
||||
|
||||
### Step 1: Create New Resource
|
||||
|
||||
1. Log in to Coolify dashboard
|
||||
2. Click **+ New Resource**
|
||||
3. Select **Docker Compose**
|
||||
|
||||
### Step 2: Configure Repository
|
||||
|
||||
1. **Git Repository**: `https://github.com/mcphub/mcphub.git`
|
||||
2. **Branch**: `main`
|
||||
3. **Build Pack**: `Docker Compose`
|
||||
|
||||
### Step 3: Configure Environment Variables
|
||||
|
||||
Add all required environment variables from `.env.example`:
|
||||
|
||||
```
|
||||
WORDPRESS_SITE1_URL=https://example.com
|
||||
WORDPRESS_SITE1_USERNAME=admin
|
||||
WORDPRESS_SITE1_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
...
|
||||
```
|
||||
|
||||
### Step 4: Configure Health Check
|
||||
|
||||
- **Path**: `/health`
|
||||
- **Port**: `8000`
|
||||
- **Interval**: `30s`
|
||||
- **Timeout**: `10s`
|
||||
- **Retries**: `3`
|
||||
|
||||
### Step 5: Deploy
|
||||
|
||||
1. Click **Deploy**
|
||||
2. Wait for build to complete
|
||||
3. Check logs for successful startup
|
||||
|
||||
### Coolify-Specific Configuration
|
||||
|
||||
Add to `docker-compose.yml` if needed:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mcp-server:
|
||||
labels:
|
||||
- "coolify.managed=true"
|
||||
- "coolify.port=8000"
|
||||
- "coolify.health_check=/health"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
### 1. Explore Available Tools
|
||||
|
||||
Check the [README](../README.md) for complete tool listing.
|
||||
|
||||
### 2. Configure Monitoring
|
||||
|
||||
- View health metrics: Use `check_all_projects_health` tool
|
||||
- Check rate limits: Use `get_rate_limit_stats` tool
|
||||
- Review audit logs: `tail -f logs/audit.log`
|
||||
|
||||
### 3. Customize Configuration
|
||||
|
||||
- Adjust rate limits in `.env`
|
||||
- Configure log levels
|
||||
- Add more WordPress sites
|
||||
|
||||
### 4. Read Documentation
|
||||
|
||||
- [Troubleshooting Guide](troubleshooting.md)
|
||||
- [Security Policy](../SECURITY.md)
|
||||
- [Contributing Guide](../CONTRIBUTING.md)
|
||||
|
||||
### 5. Join Community
|
||||
|
||||
- **Repository**: [github.com/mcphub/mcphub](https://github.com/mcphub/mcphub)
|
||||
- **Contact**: hello@mcphub.dev
|
||||
- **Website**: [mcphub.dev](https://mcphub.dev)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
669
docs/n8n-plugin-design.md
Normal file
669
docs/n8n-plugin-design.md
Normal file
@@ -0,0 +1,669 @@
|
||||
# n8n Automation Plugin Design
|
||||
|
||||
> **Phase I: n8n Automation Plugin**
|
||||
> **Priority**: High (Upgraded from Medium)
|
||||
> **Estimated Tools**: 55-60
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The n8n plugin provides comprehensive automation workflow management through n8n's REST API. This enables AI assistants to create, manage, execute, and monitor automation workflows programmatically.
|
||||
|
||||
### Key Capabilities
|
||||
- Complete workflow lifecycle management (CRUD + activate/deactivate/execute)
|
||||
- Execution monitoring and history
|
||||
- Credential management for third-party integrations
|
||||
- Project and user management (Enterprise/Pro features)
|
||||
- Environment variables management
|
||||
- Security audit and source control integration
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Plugin Structure
|
||||
|
||||
```
|
||||
plugins/n8n/
|
||||
├── __init__.py
|
||||
├── plugin.py # N8nPlugin class
|
||||
├── client.py # N8nClient (REST API communication)
|
||||
└── handlers/
|
||||
├── __init__.py
|
||||
├── workflows.py # Workflow management (14 tools)
|
||||
├── executions.py # Execution monitoring (8 tools)
|
||||
├── credentials.py # Credential management (8 tools)
|
||||
├── tags.py # Tag management (6 tools)
|
||||
├── users.py # User management (6 tools)
|
||||
├── projects.py # Project management (8 tools)
|
||||
├── variables.py # Variable management (6 tools)
|
||||
└── system.py # Audit & Source Control (4 tools)
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
n8n uses API Key authentication via `X-N8N-API-KEY` header.
|
||||
|
||||
```python
|
||||
# Environment Variables
|
||||
N8N_SITE1_URL=https://n8n.example.com
|
||||
N8N_SITE1_API_KEY=your-api-key
|
||||
N8N_SITE1_ALIAS=myautomation # Optional friendly name
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tool Specifications (55-60 Tools)
|
||||
|
||||
### 1. Workflows Handler (14 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_workflows` | GET | read | List all workflows with filters (active, tags, name) |
|
||||
| `get_workflow` | GET | read | Get workflow details by ID |
|
||||
| `create_workflow` | POST | write | Create new workflow from JSON definition |
|
||||
| `update_workflow` | PUT | write | Update existing workflow |
|
||||
| `delete_workflow` | DELETE | admin | Delete a workflow |
|
||||
| `activate_workflow` | POST | write | Activate a workflow |
|
||||
| `deactivate_workflow` | POST | write | Deactivate a workflow |
|
||||
| `execute_workflow` | POST | write | Manually execute a workflow |
|
||||
| `execute_workflow_with_data` | POST | write | Execute with custom input data |
|
||||
| `duplicate_workflow` | POST | write | Duplicate an existing workflow |
|
||||
| `export_workflow` | GET | read | Export workflow as JSON |
|
||||
| `import_workflow` | POST | write | Import workflow from JSON |
|
||||
| `get_workflow_tags` | GET | read | Get tags assigned to a workflow |
|
||||
| `set_workflow_tags` | PUT | write | Assign tags to a workflow |
|
||||
|
||||
#### Tool Specification Example
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "list_workflows",
|
||||
"method_name": "list_workflows",
|
||||
"description": "List all n8n workflows with optional filters. Returns workflow ID, name, active status, and metadata.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"active": {
|
||||
"type": "boolean",
|
||||
"description": "Filter by active/inactive status"
|
||||
},
|
||||
"tags": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Filter by tag name(s), comma-separated"
|
||||
},
|
||||
"name": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Filter by workflow name (partial match)"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum workflows to return",
|
||||
"default": 50,
|
||||
"minimum": 1,
|
||||
"maximum": 250
|
||||
},
|
||||
"cursor": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Pagination cursor for next page"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "execute_workflow",
|
||||
"method_name": "execute_workflow",
|
||||
"description": "Manually execute a workflow and return execution ID. Use get_execution to check status.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"workflow_id": {
|
||||
"type": "string",
|
||||
"description": "Workflow ID to execute",
|
||||
"minLength": 1
|
||||
},
|
||||
"wait": {
|
||||
"type": "boolean",
|
||||
"description": "Wait for execution to complete (max 5 minutes)",
|
||||
"default": False
|
||||
}
|
||||
},
|
||||
"required": ["workflow_id"]
|
||||
},
|
||||
"scope": "write"
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "execute_workflow_with_data",
|
||||
"method_name": "execute_workflow_with_data",
|
||||
"description": "Execute workflow with custom input data. Useful for workflows with webhook/manual triggers.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"workflow_id": {
|
||||
"type": "string",
|
||||
"description": "Workflow ID to execute",
|
||||
"minLength": 1
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Input data to pass to workflow trigger node"
|
||||
},
|
||||
"wait": {
|
||||
"type": "boolean",
|
||||
"description": "Wait for execution to complete",
|
||||
"default": False
|
||||
}
|
||||
},
|
||||
"required": ["workflow_id", "data"]
|
||||
},
|
||||
"scope": "write"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Executions Handler (8 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_executions` | GET | read | List workflow executions with filters |
|
||||
| `get_execution` | GET | read | Get execution details and data |
|
||||
| `delete_execution` | DELETE | write | Delete a single execution |
|
||||
| `delete_executions` | DELETE | write | Bulk delete executions |
|
||||
| `stop_execution` | POST | write | Stop a running execution |
|
||||
| `retry_execution` | POST | write | Retry a failed execution |
|
||||
| `get_execution_data` | GET | read | Get full execution data including node outputs |
|
||||
| `wait_for_execution` | GET | read | Poll until execution completes |
|
||||
|
||||
#### Tool Specification Examples
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "list_executions",
|
||||
"method_name": "list_executions",
|
||||
"description": "List workflow executions with filters by status, workflow, date range. Returns execution history.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"workflow_id": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Filter by workflow ID"
|
||||
},
|
||||
"status": {
|
||||
"anyOf": [{"type": "string", "enum": ["success", "error", "waiting", "running", "new"]}, {"type": "null"}],
|
||||
"description": "Filter by execution status"
|
||||
},
|
||||
"include_data": {
|
||||
"type": "boolean",
|
||||
"description": "Include full execution data",
|
||||
"default": False
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum results",
|
||||
"default": 20,
|
||||
"minimum": 1,
|
||||
"maximum": 250
|
||||
},
|
||||
"cursor": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Pagination cursor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "get_execution",
|
||||
"method_name": "get_execution",
|
||||
"description": "Get detailed information about a specific execution including status, timing, and optionally full data.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"execution_id": {
|
||||
"type": "string",
|
||||
"description": "Execution ID",
|
||||
"minLength": 1
|
||||
},
|
||||
"include_data": {
|
||||
"type": "boolean",
|
||||
"description": "Include full node execution data",
|
||||
"default": True
|
||||
}
|
||||
},
|
||||
"required": ["execution_id"]
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Credentials Handler (8 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_credentials` | GET | read | List all credentials (without sensitive data) |
|
||||
| `get_credential` | GET | read | Get credential metadata |
|
||||
| `create_credential` | POST | admin | Create new credential |
|
||||
| `update_credential` | PUT | admin | Update credential |
|
||||
| `delete_credential` | DELETE | admin | Delete a credential |
|
||||
| `get_credential_schema` | GET | read | Get schema for credential type |
|
||||
| `list_credential_types` | GET | read | List available credential types |
|
||||
| `transfer_credential` | POST | admin | Transfer credential to another project |
|
||||
|
||||
#### Tool Specification Examples
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "list_credentials",
|
||||
"method_name": "list_credentials",
|
||||
"description": "List all stored credentials. Returns metadata only (no sensitive values).",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Maximum results",
|
||||
"default": 100,
|
||||
"minimum": 1,
|
||||
"maximum": 250
|
||||
},
|
||||
"cursor": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Pagination cursor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
{
|
||||
"name": "create_credential",
|
||||
"method_name": "create_credential",
|
||||
"description": "Create a new credential for use in workflows. Use get_credential_schema to see required fields.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Credential display name",
|
||||
"minLength": 1
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Credential type (e.g., 'githubApi', 'slackApi')",
|
||||
"minLength": 1
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Credential data matching the schema for this type"
|
||||
}
|
||||
},
|
||||
"required": ["name", "type", "data"]
|
||||
},
|
||||
"scope": "admin"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Tags Handler (6 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_tags` | GET | read | List all tags |
|
||||
| `get_tag` | GET | read | Get tag details |
|
||||
| `create_tag` | POST | write | Create a new tag |
|
||||
| `update_tag` | PUT | write | Update tag name |
|
||||
| `delete_tag` | DELETE | write | Delete a tag |
|
||||
| `delete_tags` | DELETE | write | Bulk delete tags |
|
||||
|
||||
---
|
||||
|
||||
### 5. Users Handler (6 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_users` | GET | admin | List all users |
|
||||
| `get_user` | GET | admin | Get user details |
|
||||
| `create_user` | POST | admin | Invite/create new user |
|
||||
| `delete_user` | DELETE | admin | Delete a user |
|
||||
| `change_user_role` | PUT | admin | Change user's global role |
|
||||
| `get_current_user` | GET | read | Get current authenticated user |
|
||||
|
||||
---
|
||||
|
||||
### 6. Projects Handler (8 tools) - Enterprise/Pro
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_projects` | GET | read | List all projects |
|
||||
| `get_project` | GET | read | Get project details |
|
||||
| `create_project` | POST | admin | Create a new project |
|
||||
| `update_project` | PUT | admin | Update project metadata |
|
||||
| `delete_project` | DELETE | admin | Delete a project |
|
||||
| `add_project_users` | POST | admin | Add users to project with roles |
|
||||
| `change_project_user_role` | PUT | admin | Change user's role in project |
|
||||
| `remove_project_user` | DELETE | admin | Remove user from project |
|
||||
|
||||
---
|
||||
|
||||
### 7. Variables Handler (6 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_variables` | GET | read | List all environment variables |
|
||||
| `get_variable` | GET | read | Get variable value by key |
|
||||
| `create_variable` | POST | admin | Create new variable |
|
||||
| `update_variable` | PUT | admin | Update variable value |
|
||||
| `delete_variable` | DELETE | admin | Delete a variable |
|
||||
| `set_variables` | POST | admin | Bulk set multiple variables |
|
||||
|
||||
---
|
||||
|
||||
### 8. System Handler (4 tools)
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `run_security_audit` | POST | admin | Run security audit on instance |
|
||||
| `source_control_pull` | POST | admin | Pull workflows from Git repository |
|
||||
| `get_instance_info` | GET | read | Get n8n instance version and status |
|
||||
| `health_check` | GET | read | Check n8n instance health |
|
||||
|
||||
---
|
||||
|
||||
## API Client Design
|
||||
|
||||
### N8nClient Class
|
||||
|
||||
```python
|
||||
class N8nClient:
|
||||
"""
|
||||
n8n REST API client for HTTP communication.
|
||||
|
||||
Handles authentication, request formatting, and error handling
|
||||
for all n8n API endpoints.
|
||||
"""
|
||||
|
||||
def __init__(self, site_url: str, api_key: str):
|
||||
"""
|
||||
Initialize n8n API client.
|
||||
|
||||
Args:
|
||||
site_url: n8n instance URL (e.g., https://n8n.example.com)
|
||||
api_key: n8n API key for authentication
|
||||
"""
|
||||
self.site_url = site_url.rstrip('/')
|
||||
self.api_base = f"{self.site_url}/api/v1"
|
||||
self.api_key = api_key
|
||||
|
||||
def _get_headers(self) -> Dict[str, str]:
|
||||
"""Get request headers with API key authentication."""
|
||||
return {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"X-N8N-API-KEY": self.api_key
|
||||
}
|
||||
|
||||
async def request(
|
||||
self,
|
||||
method: str,
|
||||
endpoint: str,
|
||||
params: Optional[Dict] = None,
|
||||
json_data: Optional[Dict] = None
|
||||
) -> Any:
|
||||
"""Make authenticated request to n8n REST API."""
|
||||
# Implementation similar to GiteaClient
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Reference
|
||||
|
||||
### Base URL
|
||||
```
|
||||
{N8N_URL}/api/v1
|
||||
```
|
||||
|
||||
### Workflows
|
||||
```
|
||||
GET /workflows - List workflows
|
||||
POST /workflows - Create workflow
|
||||
GET /workflows/{id} - Get workflow
|
||||
PUT /workflows/{id} - Update workflow
|
||||
DELETE /workflows/{id} - Delete workflow
|
||||
POST /workflows/{id}/activate - Activate workflow
|
||||
POST /workflows/{id}/deactivate - Deactivate workflow
|
||||
POST /workflows/{id}/run - Execute workflow
|
||||
```
|
||||
|
||||
### Executions
|
||||
```
|
||||
GET /executions - List executions
|
||||
GET /executions/{id} - Get execution
|
||||
DELETE /executions/{id} - Delete execution
|
||||
```
|
||||
|
||||
### Credentials
|
||||
```
|
||||
GET /credentials - List credentials
|
||||
POST /credentials - Create credential
|
||||
GET /credentials/{id} - Get credential
|
||||
DELETE /credentials/{id} - Delete credential
|
||||
GET /credentials/schema/{type} - Get credential schema
|
||||
POST /credentials/{id}/transfer - Transfer credential
|
||||
```
|
||||
|
||||
### Tags
|
||||
```
|
||||
GET /tags - List tags
|
||||
POST /tags - Create tag
|
||||
GET /tags/{id} - Get tag
|
||||
PUT /tags/{id} - Update tag
|
||||
DELETE /tags/{id} - Delete tag
|
||||
```
|
||||
|
||||
### Users
|
||||
```
|
||||
GET /users - List users
|
||||
POST /users - Create/invite user
|
||||
GET /users/{id} - Get user
|
||||
DELETE /users/{id} - Delete user
|
||||
PATCH /users/{id}/role - Change user role
|
||||
```
|
||||
|
||||
### Projects (Enterprise/Pro)
|
||||
```
|
||||
GET /projects - List projects
|
||||
POST /projects - Create project
|
||||
GET /projects/{id} - Get project
|
||||
PUT /projects/{id} - Update project
|
||||
DELETE /projects/{id} - Delete project
|
||||
POST /projects/{id}/users - Add users to project
|
||||
```
|
||||
|
||||
### Variables
|
||||
```
|
||||
GET /variables - List variables
|
||||
POST /variables - Create variable
|
||||
GET /variables/{key} - Get variable
|
||||
PUT /variables/{key} - Update variable
|
||||
DELETE /variables/{key} - Delete variable
|
||||
```
|
||||
|
||||
### System
|
||||
```
|
||||
POST /audit - Run security audit
|
||||
POST /source-control/pull - Pull from Git
|
||||
GET /health - Health check
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-Endpoint Integration
|
||||
|
||||
### Endpoint Configuration
|
||||
|
||||
```python
|
||||
# core/endpoints/config.py
|
||||
ENDPOINT_CONFIGS = {
|
||||
# ... existing configs ...
|
||||
|
||||
"n8n": EndpointConfig(
|
||||
path="/n8n/mcp",
|
||||
name="n8n Automation",
|
||||
plugin_types=["n8n"],
|
||||
description="Workflow automation management",
|
||||
tools_count=55
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Per-Project Endpoint
|
||||
|
||||
```
|
||||
/project/{alias}/mcp - Site-specific n8n endpoint
|
||||
/project/myautomation/mcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
```bash
|
||||
# Single n8n instance
|
||||
N8N_SITE1_URL=https://n8n.example.com
|
||||
N8N_SITE1_API_KEY=your-api-key-here
|
||||
N8N_SITE1_ALIAS=automation
|
||||
|
||||
# Multiple instances
|
||||
N8N_SITE2_URL=https://n8n-staging.example.com
|
||||
N8N_SITE2_API_KEY=staging-api-key
|
||||
N8N_SITE2_ALIAS=automation-staging
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Workflow Management
|
||||
```
|
||||
User: "Create a new workflow that sends Slack notifications when a GitHub issue is created"
|
||||
|
||||
AI Assistant:
|
||||
1. create_workflow with workflow JSON definition
|
||||
2. activate_workflow to enable it
|
||||
3. list_credentials to verify Slack/GitHub credentials exist
|
||||
```
|
||||
|
||||
### 2. Execution Monitoring
|
||||
```
|
||||
User: "Show me failed executions from the last 24 hours"
|
||||
|
||||
AI Assistant:
|
||||
1. list_executions with status="error" filter
|
||||
2. get_execution for each to see error details
|
||||
3. Provide summary and suggestions
|
||||
```
|
||||
|
||||
### 3. Credential Management
|
||||
```
|
||||
User: "Set up new API credentials for OpenAI"
|
||||
|
||||
AI Assistant:
|
||||
1. get_credential_schema for "openAiApi" type
|
||||
2. create_credential with required fields
|
||||
3. Confirm credential is ready for use
|
||||
```
|
||||
|
||||
### 4. Security Audit
|
||||
```
|
||||
User: "Run a security audit on our n8n instance"
|
||||
|
||||
AI Assistant:
|
||||
1. run_security_audit
|
||||
2. Parse and summarize findings
|
||||
3. Provide recommendations
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Priority
|
||||
|
||||
### Phase 1 (Core - Must Have)
|
||||
1. Workflows handler (14 tools)
|
||||
2. Executions handler (8 tools)
|
||||
3. Client implementation
|
||||
4. Plugin class
|
||||
|
||||
### Phase 2 (Extended - Should Have)
|
||||
1. Credentials handler (8 tools)
|
||||
2. Tags handler (6 tools)
|
||||
3. Variables handler (6 tools)
|
||||
|
||||
### Phase 3 (Advanced - Nice to Have)
|
||||
1. Users handler (6 tools)
|
||||
2. Projects handler (8 tools)
|
||||
3. System handler (4 tools)
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **API Key Protection**: Store API keys securely, never log them
|
||||
2. **Credential Handling**: Never expose credential values in responses
|
||||
3. **Scope Enforcement**: Admin-level tools require admin scope
|
||||
4. **Rate Limiting**: Respect n8n API rate limits
|
||||
5. **Audit Logging**: Log all write/admin operations
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
1. **Unit Tests**: Test each handler function independently
|
||||
2. **Integration Tests**: Test against a local n8n instance
|
||||
3. **Mock Tests**: Use mocked API responses for CI/CD
|
||||
|
||||
---
|
||||
|
||||
## Documentation Links
|
||||
|
||||
- [n8n Public REST API](https://docs.n8n.io/api/)
|
||||
- [n8n API Reference](https://docs.n8n.io/api/api-reference/)
|
||||
- [n8n Authentication](https://docs.n8n.io/api/authentication/)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Category | Tools | Priority |
|
||||
|----------|-------|----------|
|
||||
| Workflows | 14 | Phase 1 |
|
||||
| Executions | 8 | Phase 1 |
|
||||
| Credentials | 8 | Phase 2 |
|
||||
| Tags | 6 | Phase 2 |
|
||||
| Variables | 6 | Phase 2 |
|
||||
| Users | 6 | Phase 3 |
|
||||
| Projects | 8 | Phase 3 |
|
||||
| System | 4 | Phase 3 |
|
||||
| **Total** | **60** | - |
|
||||
|
||||
---
|
||||
|
||||
**Created**: 2025-11-27
|
||||
**Author**: AI Assistant
|
||||
**Status**: Design Document - Awaiting Implementation
|
||||
922
docs/openpanel-plugin-design.md
Normal file
922
docs/openpanel-plugin-design.md
Normal file
@@ -0,0 +1,922 @@
|
||||
# OpenPanel Plugin Design - Phase H
|
||||
|
||||
> **MCP Plugin for OpenPanel Analytics Management (Self-Hosted)**
|
||||
|
||||
**Version**: v1.0.0 (Design)
|
||||
**Priority**: Highest
|
||||
**Estimated Tools**: 72-78
|
||||
|
||||
---
|
||||
|
||||
## Why OpenPanel over Plausible?
|
||||
|
||||
### Comparison Summary
|
||||
|
||||
| Feature | Plausible | OpenPanel | Winner |
|
||||
|---------|-----------|-----------|--------|
|
||||
| Web Analytics | Yes | Yes | Tie |
|
||||
| Product Analytics | No | Yes (Funnels, Cohorts) | OpenPanel |
|
||||
| User Profiles | No | Yes | OpenPanel |
|
||||
| A/B Testing | No | Yes | OpenPanel |
|
||||
| Retention Analysis | No | Yes | OpenPanel |
|
||||
| Session Recording | No | Yes | OpenPanel |
|
||||
| Multi-platform | Web only | Web, Mobile, Server | OpenPanel |
|
||||
| API Completeness | Stats API only | Track + Export + Management | OpenPanel |
|
||||
| Custom Dashboards | Limited | Full flexibility | OpenPanel |
|
||||
| Self-Hosted | Yes | Yes | Tie |
|
||||
| Privacy (GDPR) | Yes | Yes | Tie |
|
||||
|
||||
**Decision**: **OpenPanel** - More comprehensive analytics with Product Analytics features that Plausible lacks.
|
||||
|
||||
### Key OpenPanel Advantages
|
||||
|
||||
1. **Product Analytics** - Funnels, cohorts, user profiles, retention
|
||||
2. **A/B Testing** - Built-in variant testing
|
||||
3. **Multi-platform** - Web, iOS, Android, Server-side SDKs
|
||||
4. **Comprehensive API** - Track, Export, and Management APIs
|
||||
5. **Custom Dashboards** - Flexible chart creation
|
||||
6. **Self-Hosted on Coolify** - Full data control
|
||||
|
||||
Sources:
|
||||
- [OpenPanel](https://openpanel.dev/)
|
||||
- [OpenPanel GitHub](https://github.com/Openpanel-dev/openpanel)
|
||||
- [Coolify OpenPanel Docs](https://coolify.io/docs/services/openpanel)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Plugin for managing **OpenPanel Self-Hosted** instances deployed on Coolify.
|
||||
|
||||
### Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ OpenPanel Self-Hosted Architecture │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ OpenPanel Stack │ │
|
||||
│ ├─────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ │
|
||||
│ │ Next.js Dashboard (:3000) │ │
|
||||
│ │ └── tRPC API (internal management) │ │
|
||||
│ │ │ │
|
||||
│ │ Fastify Event API (:3333) │ │
|
||||
│ │ └── /track - Event ingestion │ │
|
||||
│ │ └── /export - Data export │ │
|
||||
│ │ │ │
|
||||
│ │ PostgreSQL - Metadata & config │ │
|
||||
│ │ ClickHouse - Event storage (high-volume) │ │
|
||||
│ │ Redis - Cache, pub/sub, queues │ │
|
||||
│ │ BullMQ - Job processing │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
### API Authentication
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ OpenPanel Authentication │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Required Headers: │
|
||||
│ ├── openpanel-client-id: YOUR_CLIENT_ID │
|
||||
│ └── openpanel-client-secret: YOUR_CLIENT_SECRET │
|
||||
│ │
|
||||
│ Client Modes: │
|
||||
│ ├── write - Can send events (tracking) │
|
||||
│ ├── read - Can read data (export) │
|
||||
│ └── root - Full access (management + read + write) │
|
||||
│ │
|
||||
│ For Self-Hosted: Create clients via Dashboard or API │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# OpenPanel Self-Hosted Instance (Required)
|
||||
OPENPANEL_SITE1_URL=https://analytics.example.com
|
||||
OPENPANEL_SITE1_CLIENT_ID=your-client-id
|
||||
OPENPANEL_SITE1_CLIENT_SECRET=your-client-secret
|
||||
OPENPANEL_SITE1_PROJECT_ID=your-project-id # Required for Export/Read APIs
|
||||
OPENPANEL_SITE1_ALIAS=myanalytics
|
||||
|
||||
# Optional: Multiple Instances
|
||||
OPENPANEL_SITE2_URL=https://analytics-staging.example.com
|
||||
OPENPANEL_SITE2_CLIENT_ID=client-id-staging
|
||||
OPENPANEL_SITE2_CLIENT_SECRET=client-secret-staging
|
||||
OPENPANEL_SITE2_PROJECT_ID=staging-project-id
|
||||
OPENPANEL_SITE2_ALIAS=staging
|
||||
```
|
||||
|
||||
**Finding Your Project ID:**
|
||||
1. Log in to your OpenPanel Dashboard
|
||||
2. Go to Project Settings
|
||||
3. Copy the Project ID
|
||||
|
||||
**Note:**
|
||||
- `CLIENT_ID` and `CLIENT_SECRET` are used for authentication
|
||||
- `PROJECT_ID` is required for Export/Read APIs (get_event_count, export_events, etc.)
|
||||
- Track APIs (identify_user, track_event) work without PROJECT_ID
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Track API (Fastify - /api)
|
||||
|
||||
Primary endpoint for event ingestion:
|
||||
|
||||
```
|
||||
POST /track
|
||||
Headers:
|
||||
openpanel-client-id: YOUR_CLIENT_ID
|
||||
openpanel-client-secret: YOUR_CLIENT_SECRET
|
||||
x-client-ip: CLIENT_IP (optional, for geo)
|
||||
user-agent: USER_AGENT (optional, for device info)
|
||||
```
|
||||
|
||||
**Operation Types:**
|
||||
|
||||
| Type | Description | Use Case |
|
||||
|------|-------------|----------|
|
||||
| `track` | Track custom event | Page view, button click, purchase |
|
||||
| `identify` | Identify user | Set user profile properties |
|
||||
| `increment` | Increment property | Visit count, purchase count |
|
||||
| `decrement` | Decrement property | Credits used, inventory |
|
||||
| `alias` | Alias profile ID | Link anonymous to authenticated |
|
||||
|
||||
### Export API (Fastify - /export)
|
||||
|
||||
```
|
||||
GET /export/events
|
||||
- Retrieve raw event data
|
||||
- Filters: projectId, profileId, event, start, end
|
||||
- Pagination: page, limit
|
||||
- Includes: profile, meta
|
||||
|
||||
GET /export/charts
|
||||
- Retrieve aggregated chart data
|
||||
- Events with breakdowns
|
||||
- Intervals: minute, hour, day, week, month
|
||||
- Ranges: 30min, today, 7d, 30d, 6m, 12m, etc.
|
||||
```
|
||||
|
||||
### Dashboard tRPC API (Next.js - /api/trpc)
|
||||
|
||||
Internal API for dashboard management:
|
||||
|
||||
```
|
||||
Projects:
|
||||
- project.list, project.get, project.create, project.update, project.delete
|
||||
|
||||
Dashboards:
|
||||
- dashboard.list, dashboard.get, dashboard.create, dashboard.update, dashboard.delete
|
||||
|
||||
Charts:
|
||||
- chart.create, chart.update, chart.delete
|
||||
|
||||
Clients:
|
||||
- client.list, client.create, client.delete, client.regenerate
|
||||
|
||||
Funnels:
|
||||
- funnel.list, funnel.get, funnel.create, funnel.update, funnel.delete
|
||||
|
||||
Reports:
|
||||
- report.overview, report.retention, report.paths
|
||||
|
||||
Users/Profiles:
|
||||
- profile.list, profile.get, profile.events
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugin Architecture
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
plugins/openpanel/
|
||||
├── __init__.py # Export: OpenPanelPlugin, OpenPanelClient
|
||||
├── plugin.py # Main OpenPanelPlugin class
|
||||
├── client.py # OpenPanelClient (unified client)
|
||||
└── handlers/
|
||||
├── __init__.py
|
||||
├── events.py # Event tracking (10 tools)
|
||||
├── export.py # Data export (10 tools)
|
||||
├── projects.py # Project management (8 tools)
|
||||
├── dashboards.py # Dashboard management (10 tools)
|
||||
├── funnels.py # Funnel analytics (8 tools)
|
||||
├── profiles.py # User profiles (8 tools)
|
||||
├── clients.py # API client management (6 tools)
|
||||
├── reports.py # Analytics reports (8 tools)
|
||||
└── system.py # Health & stats (6 tools)
|
||||
```
|
||||
|
||||
### Client Architecture
|
||||
|
||||
```python
|
||||
class OpenPanelClient:
|
||||
"""
|
||||
Unified client for OpenPanel Self-Hosted APIs
|
||||
|
||||
Handles both Track/Export API (Fastify) and
|
||||
Dashboard tRPC API (Next.js) where available.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str, # e.g., https://analytics.example.com
|
||||
client_id: str, # Client ID for authentication
|
||||
client_secret: str, # Client Secret for authentication
|
||||
):
|
||||
self.base_url = base_url.rstrip('/')
|
||||
self.api_url = f"{self.base_url}/api"
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
|
||||
def _get_headers(self, include_ip: str = None) -> Dict[str, str]:
|
||||
"""Get authentication headers"""
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"openpanel-client-id": self.client_id,
|
||||
"openpanel-client-secret": self.client_secret
|
||||
}
|
||||
if include_ip:
|
||||
headers["x-client-ip"] = include_ip
|
||||
return headers
|
||||
|
||||
async def track(
|
||||
self,
|
||||
event_type: str,
|
||||
payload: Dict[str, Any],
|
||||
client_ip: str = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Send tracking request to /track endpoint"""
|
||||
...
|
||||
|
||||
async def export_events(
|
||||
self,
|
||||
project_id: str,
|
||||
**filters
|
||||
) -> Dict[str, Any]:
|
||||
"""Export events from /export/events"""
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tool Categories
|
||||
|
||||
### 1. Events Handler (10 tools)
|
||||
|
||||
Event tracking and ingestion operations.
|
||||
|
||||
| Tool | Type | Scope | Description |
|
||||
|------|------|-------|-------------|
|
||||
| `track_event` | track | write | Track custom event with properties |
|
||||
| `track_page_view` | track | write | Track page view event |
|
||||
| `track_screen_view` | track | write | Track screen view (mobile) |
|
||||
| `identify_user` | identify | write | Identify user with profile data |
|
||||
| `set_user_properties` | identify | write | Update user properties |
|
||||
| `increment_property` | increment | write | Increment numeric property |
|
||||
| `decrement_property` | decrement | write | Decrement numeric property |
|
||||
| `alias_user` | alias | write | Link two profile IDs |
|
||||
| `track_revenue` | track | write | Track revenue/purchase event |
|
||||
| `track_batch` | track | write | Track multiple events in batch |
|
||||
|
||||
```python
|
||||
# Example: track_event
|
||||
{
|
||||
"name": "track_event",
|
||||
"method_name": "track_event",
|
||||
"description": "Track a custom event with properties. Events can have any custom properties.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Event name (e.g., 'button_clicked', 'purchase_completed')"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"description": "Custom properties for the event"
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "User/profile ID to associate with event"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Event timestamp (ISO 8601, defaults to now)"
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
},
|
||||
"scope": "write"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Export Handler (10 tools)
|
||||
|
||||
Data export and retrieval operations.
|
||||
|
||||
| Tool | Type | Scope | Description |
|
||||
|------|------|-------|-------------|
|
||||
| `export_events` | GET | read | Export raw event data |
|
||||
| `export_events_csv` | GET | read | Export events as CSV |
|
||||
| `export_chart_data` | GET | read | Export aggregated chart data |
|
||||
| `get_event_count` | GET | read | Get event counts with filters |
|
||||
| `get_unique_users` | GET | read | Get unique user count |
|
||||
| `get_page_views` | GET | read | Get page view statistics |
|
||||
| `get_top_pages` | GET | read | Get top pages by views |
|
||||
| `get_top_referrers` | GET | read | Get top traffic sources |
|
||||
| `get_geo_data` | GET | read | Get geographic distribution |
|
||||
| `get_device_data` | GET | read | Get device/browser breakdown |
|
||||
|
||||
```python
|
||||
# Example: export_events
|
||||
{
|
||||
"name": "export_events",
|
||||
"method_name": "export_events",
|
||||
"description": "Export raw event data with filters and pagination",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {
|
||||
"type": "string",
|
||||
"description": "Project ID to export from"
|
||||
},
|
||||
"event": {
|
||||
"anyOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}],
|
||||
"description": "Event name(s) to filter"
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "Filter by user/profile ID"
|
||||
},
|
||||
"start": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "Start date (YYYY-MM-DD)"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"description": "End date (YYYY-MM-DD)"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"default": 50,
|
||||
"maximum": 1000
|
||||
},
|
||||
"page": {
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
},
|
||||
"includes": {
|
||||
"type": "array",
|
||||
"items": {"type": "string", "enum": ["profile", "meta"]},
|
||||
"description": "Additional data to include"
|
||||
}
|
||||
},
|
||||
"required": ["project_id"]
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Projects Handler (8 tools)
|
||||
|
||||
Project management operations.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_projects` | GET | read | List all projects |
|
||||
| `get_project` | GET | read | Get project details |
|
||||
| `create_project` | POST | admin | Create new project |
|
||||
| `update_project` | PUT | admin | Update project settings |
|
||||
| `delete_project` | DELETE | admin | Delete project |
|
||||
| `get_project_stats` | GET | read | Get project statistics |
|
||||
| `get_project_settings` | GET | read | Get project configuration |
|
||||
| `update_project_settings` | PUT | admin | Update project configuration |
|
||||
|
||||
### 4. Dashboards Handler (10 tools)
|
||||
|
||||
Dashboard and chart management.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_dashboards` | GET | read | List all dashboards |
|
||||
| `get_dashboard` | GET | read | Get dashboard with charts |
|
||||
| `create_dashboard` | POST | write | Create new dashboard |
|
||||
| `update_dashboard` | PUT | write | Update dashboard |
|
||||
| `delete_dashboard` | DELETE | write | Delete dashboard |
|
||||
| `add_chart` | POST | write | Add chart to dashboard |
|
||||
| `update_chart` | PUT | write | Update chart configuration |
|
||||
| `delete_chart` | DELETE | write | Remove chart from dashboard |
|
||||
| `duplicate_dashboard` | POST | write | Clone existing dashboard |
|
||||
| `share_dashboard` | POST | write | Generate shareable link |
|
||||
|
||||
### 5. Funnels Handler (8 tools)
|
||||
|
||||
Funnel analysis operations.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_funnels` | GET | read | List all funnels |
|
||||
| `get_funnel` | GET | read | Get funnel with conversion data |
|
||||
| `create_funnel` | POST | write | Create new funnel |
|
||||
| `update_funnel` | PUT | write | Update funnel steps |
|
||||
| `delete_funnel` | DELETE | write | Delete funnel |
|
||||
| `get_funnel_conversion` | GET | read | Get conversion rates |
|
||||
| `get_funnel_breakdown` | GET | read | Get breakdown by segment |
|
||||
| `compare_funnels` | GET | read | Compare multiple funnels |
|
||||
|
||||
```python
|
||||
# Example: create_funnel
|
||||
{
|
||||
"name": "create_funnel",
|
||||
"method_name": "create_funnel",
|
||||
"description": "Create a funnel to track user journey through steps",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": {
|
||||
"type": "string",
|
||||
"description": "Project ID"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Funnel name"
|
||||
},
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"event": {"type": "string"},
|
||||
"filters": {"type": "array"}
|
||||
},
|
||||
"required": ["name", "event"]
|
||||
},
|
||||
"description": "Funnel steps (events in sequence)",
|
||||
"minItems": 2
|
||||
},
|
||||
"window_days": {
|
||||
"type": "integer",
|
||||
"default": 14,
|
||||
"description": "Conversion window in days"
|
||||
}
|
||||
},
|
||||
"required": ["project_id", "name", "steps"]
|
||||
},
|
||||
"scope": "write"
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Profiles Handler (8 tools)
|
||||
|
||||
User profile management.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_profiles` | GET | read | List user profiles |
|
||||
| `get_profile` | GET | read | Get profile details |
|
||||
| `search_profiles` | GET | read | Search profiles by property |
|
||||
| `get_profile_events` | GET | read | Get events for profile |
|
||||
| `get_profile_sessions` | GET | read | Get sessions for profile |
|
||||
| `delete_profile` | DELETE | admin | Delete profile data (GDPR) |
|
||||
| `merge_profiles` | POST | admin | Merge duplicate profiles |
|
||||
| `export_profile_data` | GET | read | Export all profile data (GDPR) |
|
||||
|
||||
### 7. Clients Handler (6 tools)
|
||||
|
||||
API client/key management.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_clients` | GET | read | List API clients |
|
||||
| `get_client` | GET | read | Get client details |
|
||||
| `create_client` | POST | admin | Create new API client |
|
||||
| `delete_client` | DELETE | admin | Delete API client |
|
||||
| `regenerate_secret` | POST | admin | Regenerate client secret |
|
||||
| `update_client_mode` | PUT | admin | Update client permissions |
|
||||
|
||||
### 8. Reports Handler (8 tools)
|
||||
|
||||
Analytics and reporting.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `get_overview_report` | GET | read | Get overview statistics |
|
||||
| `get_retention_report` | GET | read | Get retention analysis |
|
||||
| `get_cohort_report` | GET | read | Get cohort analysis |
|
||||
| `get_paths_report` | GET | read | Get user flow paths |
|
||||
| `get_realtime_stats` | GET | read | Get real-time visitors |
|
||||
| `get_ab_test_results` | GET | read | Get A/B test results |
|
||||
| `create_report` | POST | write | Create scheduled report |
|
||||
| `export_report` | GET | read | Export report as PDF/CSV |
|
||||
|
||||
### 9. System Handler (6 tools)
|
||||
|
||||
System health and management.
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `health_check` | GET | read | Check service health |
|
||||
| `get_instance_info` | GET | read | Get instance information |
|
||||
| `get_usage_stats` | GET | read | Get usage statistics |
|
||||
| `get_storage_stats` | GET | read | Get storage usage (ClickHouse) |
|
||||
| `test_connection` | GET | read | Test API connection |
|
||||
| `get_rate_limit_status` | GET | read | Check rate limit status |
|
||||
|
||||
---
|
||||
|
||||
## Tool Summary
|
||||
|
||||
| Handler | Tools | Description |
|
||||
|---------|-------|-------------|
|
||||
| Events | 10 | Event tracking & ingestion |
|
||||
| Export | 10 | Data export & retrieval |
|
||||
| Projects | 8 | Project management |
|
||||
| Dashboards | 10 | Dashboard & chart management |
|
||||
| Funnels | 8 | Funnel analysis |
|
||||
| Profiles | 8 | User profile management |
|
||||
| Clients | 6 | API client management |
|
||||
| Reports | 8 | Analytics & reporting |
|
||||
| System | 6 | Health & instance info |
|
||||
| **Total** | **74** | |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase H.1: Core (Required)
|
||||
|
||||
**Goal**: Basic event tracking and data export
|
||||
|
||||
1. **OpenPanelPlugin** class
|
||||
2. **OpenPanelClient** (unified)
|
||||
3. **Events Handler** (10 tools)
|
||||
4. **Export Handler** (10 tools)
|
||||
5. **System Handler** (6 tools)
|
||||
|
||||
**Tools**: 26
|
||||
|
||||
### Phase H.2: Analytics (Recommended)
|
||||
|
||||
**Goal**: Advanced analytics features
|
||||
|
||||
1. **Reports Handler** (8 tools)
|
||||
2. **Funnels Handler** (8 tools)
|
||||
3. **Profiles Handler** (8 tools)
|
||||
|
||||
**Tools**: 24 (Total: 50)
|
||||
|
||||
### Phase H.3: Management (Complete)
|
||||
|
||||
**Goal**: Full dashboard and project management
|
||||
|
||||
1. **Projects Handler** (8 tools)
|
||||
2. **Dashboards Handler** (10 tools)
|
||||
3. **Clients Handler** (6 tools)
|
||||
|
||||
**Tools**: 24 (Total: 74)
|
||||
|
||||
---
|
||||
|
||||
## Export API Reference
|
||||
|
||||
### Event Segmentation Types
|
||||
|
||||
| Segment | Description |
|
||||
|---------|-------------|
|
||||
| `event` | Count total events |
|
||||
| `user` | Count unique users |
|
||||
| `session` | Count unique sessions |
|
||||
| `user_average` | Average per user |
|
||||
| `one_event_per_user` | First event per user |
|
||||
| `property_sum` | Sum of property values |
|
||||
| `property_average` | Average of property values |
|
||||
| `property_min` | Minimum property value |
|
||||
| `property_max` | Maximum property value |
|
||||
|
||||
### Filter Operators
|
||||
|
||||
| Operator | Description |
|
||||
|----------|-------------|
|
||||
| `is` | Exact match |
|
||||
| `isNot` | Not equal |
|
||||
| `contains` | Contains substring |
|
||||
| `doesNotContain` | Does not contain |
|
||||
| `startsWith` | Starts with |
|
||||
| `endsWith` | Ends with |
|
||||
| `regex` | Regular expression |
|
||||
| `isNull` | Is null/undefined |
|
||||
| `isNotNull` | Is not null |
|
||||
|
||||
### Breakdown Dimensions
|
||||
|
||||
| Dimension | Description |
|
||||
|-----------|-------------|
|
||||
| `country` | Country |
|
||||
| `region` | Region/State |
|
||||
| `city` | City |
|
||||
| `device` | Device type |
|
||||
| `browser` | Browser name |
|
||||
| `os` | Operating system |
|
||||
| `referrer` | Traffic source |
|
||||
| `path` | Page path |
|
||||
|
||||
### Date Ranges
|
||||
|
||||
```
|
||||
30min, lastHour, today, yesterday
|
||||
7d, 30d, 6m, 12m
|
||||
monthToDate, lastMonth
|
||||
yearToDate, lastYear
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### HTTP Status Codes
|
||||
|
||||
| Code | Description | Action |
|
||||
|------|-------------|--------|
|
||||
| 200 | Success | Return data |
|
||||
| 400 | Bad Request | Validate input |
|
||||
| 401 | Unauthorized | Check credentials |
|
||||
| 403 | Forbidden | Check client mode |
|
||||
| 404 | Not Found | Resource doesn't exist |
|
||||
| 429 | Rate Limited | Implement backoff |
|
||||
| 500 | Server Error | Retry with backoff |
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
```
|
||||
Limit: 100 requests per 10 seconds per client
|
||||
Backoff: Exponential (1s, 2s, 4s, 8s...)
|
||||
|
||||
Headers:
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 95
|
||||
X-RateLimit-Reset: 1699999999
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Client Secret Protection
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Client Security │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ write mode client: │
|
||||
│ ├── Can send events only │
|
||||
│ ├── Cannot read data │
|
||||
│ └── Safe for client-side (with domain restrictions) │
|
||||
│ │
|
||||
│ read mode client: │
|
||||
│ ├── Can export data │
|
||||
│ ├── Cannot send events │
|
||||
│ └── Server-side only │
|
||||
│ │
|
||||
│ root mode client: │
|
||||
│ ├── Full access │
|
||||
│ ├── Can manage projects, clients │
|
||||
│ └── ⚠️ Server-side only - Never expose! │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Use appropriate client mode** - write for tracking, read for export
|
||||
2. **Never expose root clients** - Server-side only
|
||||
3. **Implement rate limiting** - Respect API limits
|
||||
4. **GDPR compliance** - Use profile deletion tools
|
||||
5. **Audit data exports** - Log who exports what
|
||||
|
||||
---
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Track Event
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "track_event",
|
||||
"args": {
|
||||
"site": "myanalytics",
|
||||
"name": "purchase_completed",
|
||||
"properties": {
|
||||
"product_id": "prod_123",
|
||||
"amount": 99.99,
|
||||
"currency": "USD",
|
||||
"category": "electronics"
|
||||
},
|
||||
"profile_id": "user_456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Identify User
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "identify_user",
|
||||
"args": {
|
||||
"site": "myanalytics",
|
||||
"profile_id": "user_456",
|
||||
"properties": {
|
||||
"firstName": "John",
|
||||
"lastName": "Doe",
|
||||
"email": "john@example.com",
|
||||
"plan": "premium",
|
||||
"company": "Acme Inc"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Export Events
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "export_events",
|
||||
"args": {
|
||||
"site": "myanalytics",
|
||||
"project_id": "proj_abc",
|
||||
"event": "purchase_completed",
|
||||
"start": "2025-11-01",
|
||||
"end": "2025-11-30",
|
||||
"limit": 100,
|
||||
"includes": ["profile"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create Funnel
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "create_funnel",
|
||||
"args": {
|
||||
"site": "myanalytics",
|
||||
"project_id": "proj_abc",
|
||||
"name": "Checkout Flow",
|
||||
"steps": [
|
||||
{"name": "View Product", "event": "product_viewed"},
|
||||
{"name": "Add to Cart", "event": "cart_added"},
|
||||
{"name": "Start Checkout", "event": "checkout_started"},
|
||||
{"name": "Complete Purchase", "event": "purchase_completed"}
|
||||
],
|
||||
"window_days": 7
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Retention Report
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "get_retention_report",
|
||||
"args": {
|
||||
"site": "myanalytics",
|
||||
"project_id": "proj_abc",
|
||||
"start_event": "signup_completed",
|
||||
"return_event": "app_opened",
|
||||
"period": "week",
|
||||
"cohorts": 12
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coolify Deployment Notes
|
||||
|
||||
### OpenPanel Services
|
||||
|
||||
```yaml
|
||||
# OpenPanel services in Coolify
|
||||
services:
|
||||
dashboard: # Next.js - port 3000
|
||||
api: # Fastify Event API - port 3333
|
||||
worker: # BullMQ worker
|
||||
postgres: # PostgreSQL - metadata
|
||||
clickhouse: # ClickHouse - events
|
||||
redis: # Redis - cache/queue
|
||||
```
|
||||
|
||||
### Environment Variables (Coolify)
|
||||
|
||||
```bash
|
||||
# Required
|
||||
NEXT_PUBLIC_DASHBOARD_URL=https://analytics.example.com
|
||||
DATABASE_URL=postgresql://...
|
||||
CLICKHOUSE_URL=http://clickhouse:8123
|
||||
REDIS_URL=redis://redis:6379
|
||||
|
||||
# Optional
|
||||
RESEND_API_KEY=re_...
|
||||
OPENAI_API_KEY=sk-... # For AI features
|
||||
ANTHROPIC_API_KEY=sk-...
|
||||
```
|
||||
|
||||
### Finding Credentials
|
||||
|
||||
1. **URL**: Coolify Dashboard → Project → OpenPanel → Domain
|
||||
2. **Client ID/Secret**: OpenPanel Dashboard → Settings → Clients
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Registration
|
||||
|
||||
### Endpoint Config
|
||||
|
||||
```python
|
||||
# core/endpoints/config.py
|
||||
|
||||
EndpointType.OPENPANEL: EndpointConfig(
|
||||
path="/openpanel",
|
||||
name="OpenPanel Analytics",
|
||||
description="OpenPanel product analytics management (events, funnels, dashboards)",
|
||||
endpoint_type=EndpointType.OPENPANEL,
|
||||
plugin_types=["openpanel"],
|
||||
require_master_key=False,
|
||||
allowed_scopes={"read", "write", "admin"},
|
||||
tool_blacklist={
|
||||
"manage_api_keys_create",
|
||||
"manage_api_keys_delete",
|
||||
"oauth_register_client",
|
||||
"oauth_revoke_client",
|
||||
},
|
||||
max_tools=80,
|
||||
),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- [ ] OpenPanelClient authentication
|
||||
- [ ] Track API operations (track, identify, increment)
|
||||
- [ ] Export API operations (events, charts)
|
||||
- [ ] Error handling for all endpoints
|
||||
- [ ] Rate limiting behavior
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- [ ] Track event and verify in export
|
||||
- [ ] Create funnel and get conversion data
|
||||
- [ ] Create dashboard with charts
|
||||
- [ ] Profile identification and merging
|
||||
- [ ] GDPR data export and deletion
|
||||
|
||||
---
|
||||
|
||||
## Comparison with Other Plugins
|
||||
|
||||
| Aspect | Supabase | n8n | OpenPanel |
|
||||
|--------|----------|-----|-----------|
|
||||
| Primary Focus | Database/Backend | Automation | Analytics |
|
||||
| Auth Method | JWT Keys | API Key | Client ID/Secret |
|
||||
| Main APIs | PostgREST, GoTrue | REST API | Track, Export |
|
||||
| Tools | 70 | 56 | 74 |
|
||||
| Phases | 3 | 1 | 3 |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OpenPanel Documentation](https://openpanel.dev/docs)
|
||||
- [OpenPanel GitHub](https://github.com/Openpanel-dev/openpanel)
|
||||
- [Track API Reference](https://openpanel.dev/docs/api/track)
|
||||
- [Export API Reference](https://openpanel.dev/docs/api/export)
|
||||
- [Coolify OpenPanel](https://coolify.io/docs/services/openpanel)
|
||||
|
||||
---
|
||||
|
||||
**Created**: 2025-11-30
|
||||
**Author**: Claude AI Assistant
|
||||
**Status**: Design Phase
|
||||
721
docs/supabase-plugin-design.md
Normal file
721
docs/supabase-plugin-design.md
Normal file
@@ -0,0 +1,721 @@
|
||||
# Supabase Plugin Design - Phase G
|
||||
|
||||
> **MCP Plugin برای مدیریت Supabase Self-Hosted روی Coolify**
|
||||
|
||||
**Version**: v1.1.0 (طراحی - Self-Hosted)
|
||||
**Priority**: High
|
||||
**Estimated Tools**: 70-75
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
پلاگین Supabase برای مدیریت **Supabase Self-Hosted** روی Coolify طراحی شده است.
|
||||
|
||||
### تفاوت Self-Hosted با Cloud
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Supabase Self-Hosted vs Cloud │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ✅ موجود در Self-Hosted: │
|
||||
│ ├── Database API (PostgREST) - /rest/v1/ │
|
||||
│ ├── Auth API (GoTrue) - /auth/v1/ │
|
||||
│ ├── Storage API - /storage/v1/ │
|
||||
│ ├── Edge Functions - /functions/v1/ │
|
||||
│ ├── postgres-meta (DB Admin) - /pg/ │
|
||||
│ └── Realtime - /realtime/v1/ (WebSocket) │
|
||||
│ │
|
||||
│ ❌ فقط در Cloud: │
|
||||
│ ├── Management API (api.supabase.com) │
|
||||
│ ├── Projects & Organizations │
|
||||
│ ├── Database Branches │
|
||||
│ ├── Platform Analytics │
|
||||
│ └── Secrets Management (platform-level) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**نکته مهم**: در Self-Hosted، هر instance یک پروژه است. Management API وجود ندارد.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
### سطح واحد احراز هویت
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Supabase Self-Hosted Auth │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ API Keys (JWT-based): │
|
||||
│ ├── anon_key │
|
||||
│ │ ├── Public/client-safe │
|
||||
│ │ ├── Protected by RLS policies │
|
||||
│ │ └── role: "anon" in JWT │
|
||||
│ │ │
|
||||
│ └── service_role_key │
|
||||
│ ├── ⚠️ SERVER-ONLY - Never expose! │
|
||||
│ ├── Bypasses ALL RLS policies │
|
||||
│ └── role: "service_role" in JWT │
|
||||
│ │
|
||||
│ All keys signed with JWT_SECRET from .env │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Supabase Self-Hosted Instance (Required)
|
||||
SUPABASE_SITE1_URL=https://supabase.example.com
|
||||
SUPABASE_SITE1_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
SUPABASE_SITE1_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
SUPABASE_SITE1_ALIAS=mysupabase
|
||||
|
||||
# Optional: Direct database access for postgres-meta
|
||||
SUPABASE_SITE1_DB_HOST=db.supabase.example.com
|
||||
SUPABASE_SITE1_DB_PORT=5432
|
||||
SUPABASE_SITE1_DB_NAME=postgres
|
||||
SUPABASE_SITE1_DB_USER=postgres
|
||||
SUPABASE_SITE1_DB_PASSWORD=your-db-password
|
||||
|
||||
# Multiple Instances
|
||||
SUPABASE_SITE2_URL=https://supabase-staging.example.com
|
||||
SUPABASE_SITE2_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
SUPABASE_SITE2_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
SUPABASE_SITE2_ALIAS=staging
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints (Kong Gateway)
|
||||
|
||||
تمام API ها از طریق Kong API Gateway (پورت 8000) در دسترس هستند:
|
||||
|
||||
```
|
||||
Base URL: https://supabase.example.com (یا http://localhost:8000)
|
||||
|
||||
Database (PostgREST):
|
||||
GET/POST/PATCH/DELETE /rest/v1/{table}
|
||||
POST /rest/v1/rpc/{function}
|
||||
|
||||
Auth (GoTrue):
|
||||
POST /auth/v1/signup
|
||||
POST /auth/v1/token
|
||||
GET /auth/v1/user
|
||||
POST /auth/v1/admin/users
|
||||
...
|
||||
|
||||
Storage:
|
||||
GET/POST/DELETE /storage/v1/bucket
|
||||
GET/POST/DELETE /storage/v1/object/{bucket}/{path}
|
||||
...
|
||||
|
||||
Edge Functions:
|
||||
POST /functions/v1/{function_name}
|
||||
|
||||
postgres-meta (Admin):
|
||||
GET /pg/tables
|
||||
GET /pg/columns
|
||||
GET /pg/policies
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
plugins/supabase/
|
||||
├── __init__.py # Export: SupabasePlugin, SupabaseClient
|
||||
├── plugin.py # کلاس اصلی SupabasePlugin
|
||||
├── client.py # SupabaseClient (unified client)
|
||||
└── handlers/
|
||||
├── __init__.py
|
||||
├── database.py # Database operations (18 tools)
|
||||
├── auth.py # User management (14 tools)
|
||||
├── storage.py # File management (12 tools)
|
||||
├── functions.py # Edge Functions (8 tools)
|
||||
├── admin.py # postgres-meta admin (12 tools)
|
||||
└── system.py # Health & info (6 tools)
|
||||
```
|
||||
|
||||
### Client Architecture
|
||||
|
||||
```python
|
||||
class SupabaseClient:
|
||||
"""
|
||||
Unified client for Supabase Self-Hosted APIs
|
||||
|
||||
All requests go through Kong gateway on single base URL.
|
||||
"""
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str, # e.g., https://supabase.example.com
|
||||
anon_key: str, # For public/RLS-protected operations
|
||||
service_role_key: str, # For admin operations (bypasses RLS)
|
||||
):
|
||||
self.base_url = base_url.rstrip('/')
|
||||
self.anon_key = anon_key
|
||||
self.service_role_key = service_role_key
|
||||
|
||||
async def request(
|
||||
self,
|
||||
method: str,
|
||||
endpoint: str,
|
||||
use_service_role: bool = False,
|
||||
**kwargs
|
||||
) -> Any:
|
||||
"""Make authenticated request to Supabase API"""
|
||||
key = self.service_role_key if use_service_role else self.anon_key
|
||||
headers = {
|
||||
"apikey": key,
|
||||
"Authorization": f"Bearer {key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
url = f"{self.base_url}{endpoint}"
|
||||
# ... request logic
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tool Categories
|
||||
|
||||
### 1. Database Handler (18 tools)
|
||||
|
||||
عملیات CRUD روی دیتابیس PostgreSQL از طریق PostgREST
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_tables` | GET | read | لیست جداول (via postgres-meta) |
|
||||
| `get_table_schema` | GET | read | ساختار جدول |
|
||||
| `query_table` | GET | read | کوئری SELECT با فیلتر |
|
||||
| `insert_rows` | POST | write | درج رکوردها |
|
||||
| `update_rows` | PATCH | write | بهروزرسانی رکوردها |
|
||||
| `upsert_rows` | POST | write | درج/بهروزرسانی |
|
||||
| `delete_rows` | DELETE | write | حذف رکوردها |
|
||||
| `execute_rpc` | POST | write | اجرای stored procedure |
|
||||
| `count_rows` | GET | read | شمارش رکوردها |
|
||||
| `get_row_by_id` | GET | read | دریافت یک رکورد با ID |
|
||||
| `bulk_insert` | POST | write | درج دستهای |
|
||||
| `bulk_update` | PATCH | write | بهروزرسانی دستهای |
|
||||
| `bulk_delete` | DELETE | write | حذف دستهای |
|
||||
| `search_text` | GET | read | جستجوی Full-text |
|
||||
| `get_foreign_tables` | GET | read | جداول مرتبط |
|
||||
| `execute_sql` | POST | admin | اجرای SQL مستقیم (via postgres-meta) |
|
||||
| `create_table` | POST | admin | ایجاد جدول جدید |
|
||||
| `drop_table` | DELETE | admin | حذف جدول |
|
||||
|
||||
```python
|
||||
# Query Table Example
|
||||
{
|
||||
"name": "supabase_query_table",
|
||||
"description": "Query data from a Supabase table with filters and pagination",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"site": {
|
||||
"type": "string",
|
||||
"description": "Supabase instance alias or site ID"
|
||||
},
|
||||
"table": {
|
||||
"type": "string",
|
||||
"description": "Table name"
|
||||
},
|
||||
"select": {
|
||||
"type": "string",
|
||||
"description": "Columns to select (e.g., 'id,name,email' or '*')",
|
||||
"default": "*"
|
||||
},
|
||||
"filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"column": {"type": "string"},
|
||||
"operator": {
|
||||
"type": "string",
|
||||
"enum": ["eq", "neq", "gt", "gte", "lt", "lte",
|
||||
"like", "ilike", "in", "is", "cs", "cd"]
|
||||
},
|
||||
"value": {}
|
||||
}
|
||||
},
|
||||
"description": "PostgREST filter conditions"
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Order by (e.g., 'created_at.desc')"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"default": 100,
|
||||
"maximum": 1000
|
||||
},
|
||||
"offset": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"required": ["table"]
|
||||
},
|
||||
"scope": "read"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Auth Handler (14 tools)
|
||||
|
||||
مدیریت کاربران از طریق GoTrue Admin API
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_users` | GET | admin | لیست کاربران |
|
||||
| `get_user` | GET | read | جزئیات کاربر |
|
||||
| `create_user` | POST | admin | ایجاد کاربر |
|
||||
| `update_user` | PUT | admin | بهروزرسانی کاربر |
|
||||
| `delete_user` | DELETE | admin | حذف کاربر |
|
||||
| `invite_user` | POST | admin | ارسال دعوتنامه |
|
||||
| `generate_link` | POST | admin | تولید magic/recovery link |
|
||||
| `ban_user` | PUT | admin | مسدود کردن کاربر |
|
||||
| `unban_user` | PUT | admin | رفع مسدودیت |
|
||||
| `list_factors` | GET | read | لیست MFA factors |
|
||||
| `delete_factor` | DELETE | admin | حذف MFA factor |
|
||||
| `get_audit_logs` | GET | read | لاگهای auth |
|
||||
| `verify_otp` | POST | write | تایید OTP |
|
||||
| `resend_otp` | POST | write | ارسال مجدد OTP |
|
||||
|
||||
```python
|
||||
# Create User Example
|
||||
{
|
||||
"name": "supabase_create_user",
|
||||
"description": "Create a new user in Supabase Auth",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"site": {"type": "string"},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"minLength": 6
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "Phone number (E.164 format)"
|
||||
},
|
||||
"email_confirm": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Auto-confirm email"
|
||||
},
|
||||
"user_metadata": {
|
||||
"type": "object",
|
||||
"description": "Custom user metadata"
|
||||
},
|
||||
"app_metadata": {
|
||||
"type": "object",
|
||||
"description": "App-specific metadata"
|
||||
}
|
||||
},
|
||||
"required": ["email", "password"]
|
||||
},
|
||||
"scope": "admin"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Storage Handler (12 tools)
|
||||
|
||||
مدیریت فایلها و bucket ها
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_buckets` | GET | read | لیست bucket ها |
|
||||
| `get_bucket` | GET | read | جزئیات bucket |
|
||||
| `create_bucket` | POST | admin | ایجاد bucket |
|
||||
| `update_bucket` | PUT | admin | بهروزرسانی bucket |
|
||||
| `delete_bucket` | DELETE | admin | حذف bucket |
|
||||
| `empty_bucket` | POST | admin | خالی کردن bucket |
|
||||
| `list_files` | GET | read | لیست فایلها در مسیر |
|
||||
| `upload_file` | POST | write | آپلود فایل |
|
||||
| `download_file` | GET | read | دانلود فایل (base64) |
|
||||
| `delete_files` | DELETE | write | حذف فایلها |
|
||||
| `move_file` | POST | write | انتقال/تغییر نام فایل |
|
||||
| `get_public_url` | GET | read | دریافت URL عمومی |
|
||||
|
||||
### 4. Functions Handler (8 tools)
|
||||
|
||||
مدیریت و اجرای Edge Functions
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_functions` | GET | read | لیست functions موجود |
|
||||
| `invoke_function` | POST | write | اجرای function |
|
||||
| `invoke_function_get` | GET | read | اجرای function با GET |
|
||||
| `get_function_body` | GET | read | دریافت کد function |
|
||||
| `deploy_function` | POST | admin | deploy function جدید |
|
||||
| `delete_function` | DELETE | admin | حذف function |
|
||||
| `get_function_logs` | GET | read | لاگهای اخیر |
|
||||
| `update_function_secrets` | PATCH | admin | تنظیم secrets |
|
||||
|
||||
**نکته**: در Self-Hosted، functions در `volumes/functions/` ذخیره میشوند.
|
||||
|
||||
### 5. Admin Handler (12 tools)
|
||||
|
||||
عملیات مدیریتی دیتابیس از طریق postgres-meta
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `list_schemas` | GET | read | لیست schemas |
|
||||
| `list_extensions` | GET | read | لیست extensions |
|
||||
| `enable_extension` | POST | admin | فعالسازی extension |
|
||||
| `disable_extension` | DELETE | admin | غیرفعالسازی extension |
|
||||
| `list_policies` | GET | read | لیست RLS policies |
|
||||
| `create_policy` | POST | admin | ایجاد RLS policy |
|
||||
| `update_policy` | PATCH | admin | بهروزرسانی policy |
|
||||
| `delete_policy` | DELETE | admin | حذف policy |
|
||||
| `list_roles` | GET | read | لیست database roles |
|
||||
| `list_triggers` | GET | read | لیست triggers |
|
||||
| `list_functions_db` | GET | read | لیست DB functions |
|
||||
| `get_database_size` | GET | read | سایز دیتابیس |
|
||||
|
||||
### 6. System Handler (6 tools)
|
||||
|
||||
سلامت و اطلاعات سیستم
|
||||
|
||||
| Tool | Method | Scope | Description |
|
||||
|------|--------|-------|-------------|
|
||||
| `health_check` | GET | read | بررسی سلامت |
|
||||
| `get_config` | GET | read | تنظیمات فعلی |
|
||||
| `get_version` | GET | read | نسخه سرویسها |
|
||||
| `test_connection` | GET | read | تست اتصال |
|
||||
| `get_stats` | GET | read | آمار سرویسها |
|
||||
| `ping` | GET | read | Ping ساده |
|
||||
|
||||
---
|
||||
|
||||
## Tool Summary
|
||||
|
||||
| Handler | Tools | Description |
|
||||
|---------|-------|-------------|
|
||||
| Database | 18 | PostgREST CRUD + SQL |
|
||||
| Auth | 14 | GoTrue user management |
|
||||
| Storage | 12 | File & bucket management |
|
||||
| Functions | 8 | Edge Functions |
|
||||
| Admin | 12 | postgres-meta DB admin |
|
||||
| System | 6 | Health & info |
|
||||
| **Total** | **70** | |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase G.1: Core (Required)
|
||||
|
||||
**هدف**: دسترسی اولیه به Supabase Self-Hosted
|
||||
|
||||
1. **SupabasePlugin** class
|
||||
2. **SupabaseClient** (unified)
|
||||
3. **Database Handler** (18 tools)
|
||||
4. **System Handler** (6 tools)
|
||||
|
||||
**ابزارها**: 24
|
||||
|
||||
### Phase G.2: Auth & Storage (Recommended)
|
||||
|
||||
**هدف**: مدیریت کاربران و فایلها
|
||||
|
||||
1. **Auth Handler** (14 tools)
|
||||
2. **Storage Handler** (12 tools)
|
||||
|
||||
**ابزارها**: 26 (جمع: 50)
|
||||
|
||||
### Phase G.3: Advanced (Complete)
|
||||
|
||||
**هدف**: قابلیتهای پیشرفته
|
||||
|
||||
1. **Functions Handler** (8 tools)
|
||||
2. **Admin Handler** (12 tools)
|
||||
|
||||
**ابزارها**: 20 (جمع: 70)
|
||||
|
||||
---
|
||||
|
||||
## PostgREST Operators Reference
|
||||
|
||||
| Operator | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `eq` | Equal | `?column=eq.value` |
|
||||
| `neq` | Not equal | `?column=neq.value` |
|
||||
| `gt` | Greater than | `?column=gt.5` |
|
||||
| `gte` | Greater or equal | `?column=gte.5` |
|
||||
| `lt` | Less than | `?column=lt.10` |
|
||||
| `lte` | Less or equal | `?column=lte.10` |
|
||||
| `like` | LIKE (case-sensitive) | `?column=like.*pattern*` |
|
||||
| `ilike` | LIKE (case-insensitive) | `?column=ilike.*pattern*` |
|
||||
| `in` | IN array | `?column=in.(a,b,c)` |
|
||||
| `is` | IS (null, true, false) | `?column=is.null` |
|
||||
| `cs` | Contains (arrays) | `?column=cs.{a,b}` |
|
||||
| `cd` | Contained by | `?column=cd.{a,b,c}` |
|
||||
| `fts` | Full-text search | `?column=fts.query` |
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### PostgREST Errors
|
||||
|
||||
```python
|
||||
async def handle_postgrest_error(response):
|
||||
data = await response.json()
|
||||
|
||||
if response.status == 400:
|
||||
# Validation error
|
||||
raise ValidationError(data.get("message", "Invalid request"))
|
||||
elif response.status == 401:
|
||||
raise AuthError("Invalid API key")
|
||||
elif response.status == 403:
|
||||
# RLS policy violation
|
||||
raise RLSError(f"Row Level Security: {data.get('message')}")
|
||||
elif response.status == 404:
|
||||
raise NotFoundError("Resource not found")
|
||||
elif response.status == 409:
|
||||
raise ConflictError("Unique constraint violation")
|
||||
elif response.status == 406:
|
||||
raise NotAcceptableError("Invalid Accept header")
|
||||
```
|
||||
|
||||
### GoTrue Errors
|
||||
|
||||
```python
|
||||
async def handle_gotrue_error(response):
|
||||
data = await response.json()
|
||||
|
||||
error_code = data.get("error_code") or data.get("code")
|
||||
message = data.get("msg") or data.get("message") or data.get("error_description")
|
||||
|
||||
if error_code == "user_not_found":
|
||||
raise UserNotFoundError(message)
|
||||
elif error_code == "email_exists":
|
||||
raise DuplicateError("Email already registered")
|
||||
# ... more error codes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Key Security
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ API Key Security │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ anon_key: │
|
||||
│ ├── ✅ Safe for client-side │
|
||||
│ ├── ✅ Protected by RLS policies │
|
||||
│ ├── ⚠️ Always enable RLS on tables │
|
||||
│ └── Used for: read operations, authenticated user actions │
|
||||
│ │
|
||||
│ service_role_key: │
|
||||
│ ├── ❌ NEVER expose to client │
|
||||
│ ├── ❌ Bypasses ALL RLS policies │
|
||||
│ ├── ✅ Server-side only │
|
||||
│ └── Used for: admin operations, background jobs │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Always use RLS** - حتی با service_role_key، RLS را فعال نگه دارید
|
||||
2. **Minimal service_role usage** - فقط وقتی واقعاً نیاز است
|
||||
3. **Never log keys** - حتی در error messages
|
||||
4. **Validate input** - قبل از اجرای SQL
|
||||
5. **Audit admin operations** - تمام عملیات admin لاگ شود
|
||||
|
||||
---
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Query Database
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "supabase_query_table",
|
||||
"args": {
|
||||
"site": "mysupabase",
|
||||
"table": "users",
|
||||
"select": "id,email,created_at",
|
||||
"filters": [
|
||||
{"column": "role", "operator": "eq", "value": "admin"}
|
||||
],
|
||||
"order": "created_at.desc",
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create User
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "supabase_create_user",
|
||||
"args": {
|
||||
"site": "mysupabase",
|
||||
"email": "user@example.com",
|
||||
"password": "secure-password",
|
||||
"email_confirm": true,
|
||||
"user_metadata": {
|
||||
"name": "John Doe",
|
||||
"role": "editor"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Upload File
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "supabase_upload_file",
|
||||
"args": {
|
||||
"site": "mysupabase",
|
||||
"bucket": "avatars",
|
||||
"path": "users/123/profile.png",
|
||||
"content_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
|
||||
"content_type": "image/png",
|
||||
"upsert": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Invoke Edge Function
|
||||
|
||||
```json
|
||||
{
|
||||
"tool": "supabase_invoke_function",
|
||||
"args": {
|
||||
"site": "mysupabase",
|
||||
"function_name": "send-notification",
|
||||
"body": {
|
||||
"user_id": "123",
|
||||
"message": "Hello from AI!"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coolify Deployment Notes
|
||||
|
||||
### Finding Supabase Credentials
|
||||
|
||||
در Coolify، بعد از deploy کردن Supabase:
|
||||
|
||||
1. **URL**: از Coolify dashboard → Project → Supabase → Domain
|
||||
2. **Keys**: در Environment Variables:
|
||||
- `ANON_KEY` - کلید عمومی
|
||||
- `SERVICE_ROLE_KEY` - کلید ادمین
|
||||
- `JWT_SECRET` - برای verify کردن tokens
|
||||
|
||||
### Kong Gateway Port
|
||||
|
||||
```
|
||||
Default: 8000
|
||||
HTTPS: 8443 (اگر SSL فعال باشد)
|
||||
|
||||
Coolify معمولاً reverse proxy میکند:
|
||||
https://supabase.example.com → Kong:8000
|
||||
```
|
||||
|
||||
### Docker Compose Services
|
||||
|
||||
```yaml
|
||||
# Supabase services on Coolify
|
||||
services:
|
||||
kong: # API Gateway - port 8000
|
||||
auth: # GoTrue - /auth/v1/
|
||||
rest: # PostgREST - /rest/v1/
|
||||
storage: # Storage API - /storage/v1/
|
||||
meta: # postgres-meta - /pg/
|
||||
functions: # Edge Functions - /functions/v1/
|
||||
db: # PostgreSQL
|
||||
realtime: # Realtime WebSocket
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoint Registration
|
||||
|
||||
### Endpoint Config
|
||||
|
||||
```python
|
||||
# core/endpoints/config.py
|
||||
|
||||
EndpointType.SUPABASE: EndpointConfig(
|
||||
path="/supabase",
|
||||
name="Supabase Manager",
|
||||
description="Supabase Self-Hosted management (database, auth, storage, functions)",
|
||||
endpoint_type=EndpointType.SUPABASE,
|
||||
plugin_types=["supabase"],
|
||||
require_master_key=False,
|
||||
allowed_scopes={"read", "write", "admin"},
|
||||
tool_blacklist={
|
||||
"manage_api_keys_create",
|
||||
"manage_api_keys_delete",
|
||||
"manage_api_keys_rotate",
|
||||
"oauth_register_client",
|
||||
"oauth_revoke_client",
|
||||
},
|
||||
max_tools=80,
|
||||
),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- [ ] SupabaseClient authentication
|
||||
- [ ] PostgREST CRUD operations
|
||||
- [ ] PostgREST filtering and pagination
|
||||
- [ ] GoTrue user operations
|
||||
- [ ] Storage file operations
|
||||
- [ ] Error handling for all endpoints
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- [ ] Query and modify database
|
||||
- [ ] Create and authenticate user
|
||||
- [ ] Upload and download file
|
||||
- [ ] Invoke Edge Function
|
||||
- [ ] RLS policy enforcement
|
||||
- [ ] Service role bypass
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Supabase Self-Hosting Docker](https://supabase.com/docs/guides/self-hosting/docker)
|
||||
- [PostgREST Documentation](https://postgrest.org/en/stable/)
|
||||
- [GoTrue API Reference](https://github.com/supabase/auth)
|
||||
- [Supabase Storage API](https://supabase.com/docs/guides/storage)
|
||||
- [Kong API Gateway](https://docs.konghq.com/)
|
||||
- [postgres-meta](https://github.com/supabase/postgres-meta)
|
||||
|
||||
---
|
||||
|
||||
**Created**: 2025-11-29
|
||||
**Updated**: 2025-11-29 (Self-Hosted version)
|
||||
**Author**: Claude AI Assistant
|
||||
**Status**: Design Phase
|
||||
676
docs/troubleshooting.md
Normal file
676
docs/troubleshooting.md
Normal file
@@ -0,0 +1,676 @@
|
||||
# 🔧 Troubleshooting Guide
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Common Errors](#common-errors)
|
||||
2. [Connection Issues](#connection-issues)
|
||||
3. [Authentication Problems](#authentication-problems)
|
||||
4. [Rate Limiting Issues](#rate-limiting-issues)
|
||||
5. [Docker Problems](#docker-problems)
|
||||
6. [Performance Issues](#performance-issues)
|
||||
7. [Tool Registration Issues](#tool-registration-issues)
|
||||
8. [Logging and Debugging](#logging-and-debugging)
|
||||
9. [Getting Help](#getting-help)
|
||||
|
||||
---
|
||||
|
||||
## Common Errors
|
||||
|
||||
### Error: "No module named 'fastmcp'"
|
||||
|
||||
**Cause**: Dependencies not installed or virtual environment not activated.
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
# Activate virtual environment
|
||||
source venv/bin/activate # Linux/Mac
|
||||
.\venv\Scripts\Activate.ps1 # Windows
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Error: "KeyError: 'WORDPRESS_SITE1_URL'"
|
||||
|
||||
**Cause**: Environment variables not configured.
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
# Check if .env file exists
|
||||
ls -la .env
|
||||
|
||||
# If not, create from template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit with your credentials
|
||||
nano .env # Linux/Mac
|
||||
notepad .env # Windows
|
||||
```
|
||||
|
||||
### Error: "ModuleNotFoundError: No module named 'core'"
|
||||
|
||||
**Cause**: Running from wrong directory or Python path issue.
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
# Make sure you're in project root
|
||||
cd /path/to/mcphub
|
||||
|
||||
# Run the server directly
|
||||
python server.py
|
||||
|
||||
# Or add to .env
|
||||
echo "PYTHONPATH=." >> .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Connection Issues
|
||||
|
||||
### WordPress Site Not Accessible
|
||||
|
||||
**Symptoms**: `Connection timeout`, `Connection refused`, `Name or service not known`
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Test site accessibility
|
||||
curl -I https://your-wordpress-site.com
|
||||
|
||||
# Check DNS resolution
|
||||
nslocalhost your-wordpress-site.com
|
||||
|
||||
# Test with timeout
|
||||
timeout 5 curl https://your-wordpress-site.com
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check URL format**:
|
||||
```bash
|
||||
# Correct
|
||||
WORDPRESS_SITE1_URL=https://example.com
|
||||
|
||||
# Incorrect
|
||||
WORDPRESS_SITE1_URL=example.com # Missing https://
|
||||
WORDPRESS_SITE1_URL=https://example.com/ # Extra trailing slash
|
||||
```
|
||||
|
||||
2. **Verify HTTPS certificate**:
|
||||
```bash
|
||||
curl -v https://your-site.com 2>&1 | grep SSL
|
||||
```
|
||||
|
||||
3. **Check firewall rules**:
|
||||
- Ensure port 443 (HTTPS) is open
|
||||
- Check if IP is whitelisted (if using server firewall)
|
||||
|
||||
4. **Test from different network**:
|
||||
- Try from different IP address
|
||||
- Check if WordPress site blocks data center IPs
|
||||
|
||||
### WordPress REST API Not Available
|
||||
|
||||
**Symptoms**: `404 Not Found` on `/wp-json/`
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
curl https://your-site.com/wp-json/
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check permalink settings**:
|
||||
- Go to: WordPress Admin → Settings → Permalinks
|
||||
- Select any option except "Plain"
|
||||
- Click "Save Changes"
|
||||
|
||||
2. **Check .htaccess**:
|
||||
```apache
|
||||
# Must have these rules
|
||||
RewriteEngine On
|
||||
RewriteRule ^index\.php$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . /index.php [L]
|
||||
```
|
||||
|
||||
3. **Check nginx configuration** (if using nginx):
|
||||
```nginx
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authentication Problems
|
||||
|
||||
### Error: "Invalid username or password"
|
||||
|
||||
**Cause**: Application Password not configured correctly.
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Verify Application Password is enabled**:
|
||||
- WordPress 5.6+ only
|
||||
- Go to: Users → Your Profile
|
||||
- Look for "Application Passwords" section
|
||||
|
||||
2. **Generate new Application Password**:
|
||||
```
|
||||
Name: MCP Server
|
||||
Click: Add New Application Password
|
||||
Copy password (format: xxxx xxxx xxxx xxxx xxxx xxxx)
|
||||
```
|
||||
|
||||
3. **Update .env file**:
|
||||
```bash
|
||||
WORDPRESS_SITE1_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
```
|
||||
|
||||
4. **Important notes**:
|
||||
- Include spaces in password
|
||||
- Password is one-time display only
|
||||
- Each application needs unique password
|
||||
|
||||
### Error: "Application Passwords not available"
|
||||
|
||||
**Cause**: WordPress version < 5.6 or disabled by plugin/filter.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Update WordPress**:
|
||||
```bash
|
||||
# Via WP-CLI
|
||||
wp core update
|
||||
```
|
||||
|
||||
2. **Check if disabled by plugin/filter**:
|
||||
- Some security plugins disable Application Passwords
|
||||
- Check: Security Plugins → Settings → Application Passwords
|
||||
|
||||
3. **Enable via code** (add to `functions.php`):
|
||||
```php
|
||||
// Remove filter that may disable it
|
||||
add_filter('wp_is_application_passwords_available', '__return_true');
|
||||
```
|
||||
|
||||
### WooCommerce Authentication Failed
|
||||
|
||||
**Cause**: Invalid Consumer Key/Secret.
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Regenerate API keys**:
|
||||
- WooCommerce → Settings → Advanced → REST API
|
||||
- Add Key
|
||||
- Permissions: Read/Write
|
||||
- Copy both Consumer Key and Consumer Secret
|
||||
|
||||
2. **Verify format in .env**:
|
||||
```bash
|
||||
WORDPRESS_SITE1_WC_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxx
|
||||
WORDPRESS_SITE1_WC_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
3. **Check permissions**:
|
||||
- User must have `manage_woocommerce` capability
|
||||
- Keys must be for admin user
|
||||
|
||||
---
|
||||
|
||||
## Rate Limiting Issues
|
||||
|
||||
### Error: "Rate limit exceeded"
|
||||
|
||||
**Symptoms**: HTTP 429, "Too many requests"
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check rate limit stats
|
||||
python -c "
|
||||
from src.core.rate_limiter import RateLimiter
|
||||
limiter = RateLimiter()
|
||||
print(limiter.get_stats())
|
||||
"
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Adjust rate limits** in `.env`:
|
||||
```bash
|
||||
RATE_LIMIT_PER_MINUTE=120 # Increase from 60
|
||||
RATE_LIMIT_PER_HOUR=2000 # Increase from 1000
|
||||
RATE_LIMIT_PER_DAY=20000 # Increase from 10000
|
||||
```
|
||||
|
||||
2. **Reset rate limiter**:
|
||||
```bash
|
||||
# Via MCP tool
|
||||
reset_rate_limit()
|
||||
|
||||
# Or restart server
|
||||
docker compose restart # If using Docker
|
||||
```
|
||||
|
||||
3. **Distribute requests**:
|
||||
- Add delays between bulk operations
|
||||
- Use batching for large operations
|
||||
|
||||
### Rate Limit Not Working
|
||||
|
||||
**Symptoms**: No rate limiting being applied.
|
||||
|
||||
**Solution**:
|
||||
|
||||
Check rate limiter initialization in logs:
|
||||
```bash
|
||||
grep "Rate limiter" logs/audit.log
|
||||
```
|
||||
|
||||
Ensure rate limiter is enabled:
|
||||
```python
|
||||
# In .env
|
||||
RATE_LIMITING_ENABLED=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker Problems
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
**Symptoms**: `docker compose up` fails, container exits immediately.
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check container logs
|
||||
docker compose logs
|
||||
|
||||
# Check container exit code
|
||||
docker compose ps -a
|
||||
```
|
||||
|
||||
**Common Solutions**:
|
||||
|
||||
1. **Port already in use**:
|
||||
```bash
|
||||
# Check what's using port 8000
|
||||
lsof -i :8000 # Linux/Mac
|
||||
netstat -ano | findstr :8000 # Windows
|
||||
|
||||
# Change port in docker-compose.yml
|
||||
ports:
|
||||
- "8080:8000" # Use 8080 instead
|
||||
```
|
||||
|
||||
2. **Invalid environment variables**:
|
||||
```bash
|
||||
# Validate .env file
|
||||
docker compose config
|
||||
```
|
||||
|
||||
3. **Permission issues**:
|
||||
```bash
|
||||
# Fix permissions
|
||||
sudo chown -R 1000:1000 logs/
|
||||
```
|
||||
|
||||
### Container Running but Not Accessible
|
||||
|
||||
**Symptoms**: Container status shows "Up" but health check fails.
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check container health
|
||||
docker compose ps
|
||||
|
||||
# Test from inside container
|
||||
docker compose exec mcp-server curl localhost:8000/health
|
||||
|
||||
# Check container network
|
||||
docker compose exec mcp-server cat /etc/hosts
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check binding address**:
|
||||
- Should bind to `0.0.0.0`, not `127.0.0.1`
|
||||
- Update `server.py` if needed
|
||||
|
||||
2. **Check firewall**:
|
||||
```bash
|
||||
# Allow Docker network
|
||||
sudo ufw allow from 172.0.0.0/8
|
||||
```
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
**Symptoms**: Container using excessive RAM.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Set memory limits** in `docker-compose.yml`:
|
||||
```yaml
|
||||
services:
|
||||
mcp-server:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
```
|
||||
|
||||
2. **Optimize logging**:
|
||||
```bash
|
||||
# Reduce log level
|
||||
LOG_LEVEL=WARNING
|
||||
```
|
||||
|
||||
3. **Clear cache**:
|
||||
```bash
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Issues
|
||||
|
||||
### Slow Response Times
|
||||
|
||||
**Symptoms**: Tools taking > 5 seconds to respond.
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# Check health metrics
|
||||
python -c "
|
||||
from core.health import HealthMonitor
|
||||
monitor = HealthMonitor()
|
||||
print(monitor.get_all_health())
|
||||
"
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check WordPress site performance**:
|
||||
```bash
|
||||
# Test direct WordPress API
|
||||
time curl https://your-site.com/wp-json/wp/v2/posts
|
||||
```
|
||||
|
||||
2. **Enable caching** on WordPress:
|
||||
- Install caching plugin (WP Super Cache, W3 Total Cache)
|
||||
- Enable object caching (Redis/Memcached)
|
||||
|
||||
3. **Optimize database**:
|
||||
```bash
|
||||
# Use WP-CLI tool
|
||||
wordpress_wp_db_optimize(site="site1")
|
||||
```
|
||||
|
||||
4. **Reduce payload size**:
|
||||
```python
|
||||
# Request fewer items
|
||||
wordpress_list_posts(site="site1", per_page=10) # Instead of 100
|
||||
```
|
||||
|
||||
### High CPU Usage
|
||||
|
||||
**Symptoms**: Server using 100% CPU.
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check for infinite loops** in logs:
|
||||
```bash
|
||||
tail -f logs/audit.log | grep ERROR
|
||||
```
|
||||
|
||||
2. **Limit concurrent requests**:
|
||||
```bash
|
||||
# In .env
|
||||
MAX_CONCURRENT_REQUESTS=5
|
||||
```
|
||||
|
||||
3. **Optimize queries**:
|
||||
- Use pagination
|
||||
- Filter results
|
||||
- Cache responses
|
||||
|
||||
---
|
||||
|
||||
## Tool Registration Issues
|
||||
|
||||
### Error: "Tool not found"
|
||||
|
||||
**Symptoms**: MCP reports tool doesn't exist.
|
||||
|
||||
**Diagnosis**:
|
||||
```bash
|
||||
# List all registered tools
|
||||
python -c "
|
||||
from server import mcp
|
||||
tools = app.list_tools()
|
||||
for tool in tools:
|
||||
print(tool['name'])
|
||||
"
|
||||
```
|
||||
|
||||
**Solutions**:
|
||||
|
||||
1. **Check site configuration**:
|
||||
```bash
|
||||
# Ensure site is configured in .env
|
||||
grep "WORDPRESS_SITE1" .env
|
||||
```
|
||||
|
||||
2. **Verify plugin loaded**:
|
||||
```bash
|
||||
# Check logs for plugin initialization
|
||||
grep "plugin loaded" logs/audit.log
|
||||
```
|
||||
|
||||
3. **Restart server**:
|
||||
```bash
|
||||
# Tools are registered at startup
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### Duplicate Tools
|
||||
|
||||
**Symptoms**: Same tool name registered multiple times.
|
||||
|
||||
**Cause**: Multiple plugins or sites with same alias.
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. **Check for duplicate aliases**:
|
||||
```bash
|
||||
grep "ALIAS" .env | sort
|
||||
```
|
||||
|
||||
2. **Ensure unique aliases**:
|
||||
```bash
|
||||
WORDPRESS_SITE1_ALIAS=mainsite
|
||||
WORDPRESS_SITE2_ALIAS=shop # Not mainsite
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logging and Debugging
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
```bash
|
||||
# In .env
|
||||
LOG_LEVEL=DEBUG
|
||||
|
||||
# Restart server
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
### View Real-time Logs
|
||||
|
||||
```bash
|
||||
# Audit logs
|
||||
tail -f logs/audit.log
|
||||
|
||||
# Application logs
|
||||
docker compose logs -f
|
||||
|
||||
# Filter for errors
|
||||
grep ERROR logs/audit.log
|
||||
|
||||
# Filter for specific site
|
||||
grep "site1" logs/audit.log
|
||||
```
|
||||
|
||||
### Common Log Patterns
|
||||
|
||||
**Successful request**:
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-11-11T10:30:00Z",
|
||||
"event_type": "tool_execution",
|
||||
"level": "INFO",
|
||||
"event": "wordpress_list_posts",
|
||||
"details": {
|
||||
"site": "site1",
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Failed request**:
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-11-11T10:30:00Z",
|
||||
"event_type": "tool_execution",
|
||||
"level": "ERROR",
|
||||
"event": "wordpress_list_posts",
|
||||
"details": {
|
||||
"site": "site1",
|
||||
"error": "Connection timeout",
|
||||
"status": "failed"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Debugging Tips
|
||||
|
||||
1. **Test with curl**:
|
||||
```bash
|
||||
# Test WordPress directly
|
||||
curl -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \
|
||||
https://your-site.com/wp-json/wp/v2/posts
|
||||
```
|
||||
|
||||
2. **Check environment loading**:
|
||||
```python
|
||||
python -c "
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
load_dotenv()
|
||||
print(os.getenv('WORDPRESS_SITE1_URL'))
|
||||
"
|
||||
```
|
||||
|
||||
3. **Test individual components**:
|
||||
```bash
|
||||
# Test WordPress plugin
|
||||
pytest tests/test_wordpress_plugin.py -v
|
||||
|
||||
# Test rate limiter
|
||||
pytest tests/test_rate_limiter.py -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Before Asking for Help
|
||||
|
||||
1. **Check logs**:
|
||||
```bash
|
||||
tail -50 logs/audit.log
|
||||
```
|
||||
|
||||
2. **Run health check**:
|
||||
```bash
|
||||
python -c "
|
||||
from core.health import HealthMonitor
|
||||
monitor = HealthMonitor()
|
||||
print(monitor.check_all_projects())
|
||||
"
|
||||
```
|
||||
|
||||
3. **Verify configuration**:
|
||||
```bash
|
||||
# Mask sensitive data
|
||||
grep -v "PASSWORD\|KEY\|SECRET" .env
|
||||
```
|
||||
|
||||
4. **Test connectivity**:
|
||||
```bash
|
||||
curl -I https://your-wordpress-site.com
|
||||
```
|
||||
|
||||
### What to Include in Bug Reports
|
||||
|
||||
1. **Environment information**:
|
||||
- Python version: `python --version`
|
||||
- Docker version: `docker --version`
|
||||
- OS: `uname -a` (Linux/Mac) or `systeminfo` (Windows)
|
||||
|
||||
2. **Error messages**:
|
||||
- Full error output
|
||||
- Stack trace if available
|
||||
- Relevant log entries
|
||||
|
||||
3. **Configuration** (mask sensitive data):
|
||||
- Relevant .env variables
|
||||
- docker-compose.yml modifications
|
||||
- WordPress/WooCommerce versions
|
||||
|
||||
4. **Steps to reproduce**:
|
||||
- Exact commands run
|
||||
- Expected vs actual behavior
|
||||
- Frequency (always, sometimes, once)
|
||||
|
||||
### Contact Information
|
||||
|
||||
**Email**: hello@mcphub.dev
|
||||
|
||||
**Subject format**: `[BUG] Brief description`
|
||||
|
||||
**Example**:
|
||||
```
|
||||
Subject: [BUG] wordpress_list_posts returns 403 error
|
||||
|
||||
Environment:
|
||||
- Python 3.11.5
|
||||
- Docker 24.0.6
|
||||
- WordPress 6.4
|
||||
- Ubuntu 22.04
|
||||
|
||||
Issue:
|
||||
wordpress_list_posts(site="site1") returns 403 Forbidden
|
||||
|
||||
Steps to reproduce:
|
||||
1. Configure WORDPRESS_SITE1_* in .env
|
||||
2. Run python server.py
|
||||
3. Call wordpress_list_posts(site="site1", per_page=10)
|
||||
4. Receive 403 error
|
||||
|
||||
Logs:
|
||||
[Include relevant log entries]
|
||||
|
||||
Configuration:
|
||||
WORDPRESS_SITE1_URL=https://example.com
|
||||
WORDPRESS_SITE1_USERNAME=admin
|
||||
[Application password masked]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user