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>
13 KiB
🔐 API Keys Management Guide
Complete guide for managing API keys in MCP Hub.
Table of Contents
- Overview
- Key Types
- Scopes & Permissions
- Creating Keys
- Managing Keys
- Best Practices
- Examples
- Troubleshooting
Overview
MCP Hub supports two types of API keys for authentication:
- Master API Key - Full access to all operations and projects
- 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_KEYenvironment 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:
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_postwordpress_list_products,wordpress_get_productwordpress_list_orders,wordpress_get_order- All WordPress/WooCommerce
get_*andlist_*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_postwordpress_create_product,wordpress_update_productwordpress_create_order,wordpress_update_order_statuswordpress_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:
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:
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:
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:
result = manage_api_keys_create(
project_id="*", # All projects
scope="admin",
description="Backup admin key"
)
Managing Keys
List All Keys
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
result = manage_api_keys_list(
project_id="wordpress_site1"
)
Include Revoked Keys
result = manage_api_keys_list(
include_revoked=True
)
Get Key Information
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):
result = manage_api_keys_revoke(
key_id="key_abc123"
)
Delete a Key
Permanent deletion:
result = manage_api_keys_delete(
key_id="key_abc123"
)
Rotate All Project Keys
Create new keys and revoke old ones:
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:
# Giving admin access when read is enough
manage_api_keys_create("wordpress_site1", scope="admin")
✅ Do:
# Use minimal required scope
manage_api_keys_create("wordpress_site1", scope="read")
2. Set Expiration for Temporary Access
❌ Don't:
# Permanent key for temporary contractor
manage_api_keys_create("wordpress_site1", scope="write")
✅ Do:
# 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:
manage_api_keys_create("wordpress_site1", "write")
✅ Do:
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:
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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:
- Check if key is revoked:
info = manage_api_keys_get_info("key_abc123")
if info['key']['revoked']:
print("Key has been revoked")
- Check if key expired:
if info['key']['expired']:
print("Key has expired")
- Verify scope matches operation:
# 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:
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:
# 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:
- Check file permissions:
ls -l data/api_keys.json
chmod 600 data/api_keys.json # Read/write for owner only
- Check directory exists:
mkdir -p data
- Validate JSON format:
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_countandlast_used_at - Regular review of active keys
- Compliance with GDPR, SOC 2, ISO 27001
Related Documentation
Version: 1.0.0 Last Updated: 2025-11-11 Maintained by: Airano (https://mcphub.dev)