mcphub-server 3.1.0__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/PKG-INFO +20 -5
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/README.md +19 -4
- mcphub_server-3.3.0/core/admin_utils.py +27 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/api_keys.py +16 -10
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/config_snippets.py +14 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/dashboard/auth.py +19 -10
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/dashboard/routes.py +613 -45
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/database.py +70 -5
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/health.py +18 -5
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/client_registry.py +3 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/schemas.py +6 -2
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/server.py +6 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/token_manager.py +11 -1
- mcphub_server-3.3.0/core/plugin_visibility.py +59 -0
- mcphub_server-3.3.0/core/settings.py +162 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/site_api.py +142 -13
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/404.html +21 -9
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/api-keys/list.html +7 -7
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/auth-login.html +3 -2
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/base.html +26 -7
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/connect.html +115 -12
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/health/index.html +1 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/index.html +39 -55
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/oauth-clients/list.html +4 -4
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/partials/head_assets.html +1 -3
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/projects/list.html +5 -5
- mcphub_server-3.3.0/core/templates/dashboard/service.html +185 -0
- mcphub_server-3.3.0/core/templates/dashboard/services_list.html +57 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/settings/index.html +115 -2
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/sites/add.html +27 -4
- mcphub_server-3.3.0/core/templates/dashboard/sites/edit.html +172 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/sites/list.html +63 -13
- mcphub_server-3.3.0/core/templates/dashboard/user-oauth-clients.html +241 -0
- mcphub_server-3.3.0/core/templates/oauth/authorize.html +268 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/user_endpoints.py +72 -21
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/user_keys.py +2 -5
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/PKG-INFO +20 -5
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/SOURCES.txt +15 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/client.py +245 -96
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/auth.py +0 -18
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/database.py +29 -12
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/plugin.py +15 -6
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/woocommerce/plugin.py +20 -6
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/client.py +1 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/seo.py +3 -3
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/wp_cli.py +66 -25
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/pyproject.toml +1 -1
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/server.py +264 -42
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/server_multi.py +8 -13
- mcphub_server-3.3.0/tests/test_admin_system.py +188 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_config_snippets.py +10 -5
- mcphub_server-3.3.0/tests/test_f3_admin_stats.py +17 -0
- mcphub_server-3.3.0/tests/test_f3_last_tested.py +77 -0
- mcphub_server-3.3.0/tests/test_f3_service_pages.py +35 -0
- mcphub_server-3.3.0/tests/test_oauth_basic_auth.py +165 -0
- mcphub_server-3.3.0/tests/test_oauth_resource.py +333 -0
- mcphub_server-3.3.0/tests/test_oauth_revoke.py +227 -0
- mcphub_server-3.3.0/tests/test_plugin_visibility.py +148 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_woocommerce_plugin.py +6 -5
- mcphub_server-3.1.0/core/templates/oauth/authorize.html +0 -170
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/LICENSE +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/audit_log.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/auth.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/context.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/dashboard/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/encryption.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/endpoints/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/endpoints/config.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/endpoints/factory.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/endpoints/middleware.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/endpoints/registry.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/i18n.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/middleware/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/csrf.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/pkce.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/oauth/storage.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/project_manager.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/rate_limiter.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/site_manager.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/base.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/audit-logs/list.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/health/projects-partial.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/login.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/profile.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/dashboard/projects/detail.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/templates/oauth/error.html +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/tool_generator.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/tool_registry.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/core/user_auth.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/dependency_links.txt +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/entry_points.txt +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/requires.txt +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/mcphub_server.egg-info/top_level.txt +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/client.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/databases.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/documents.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/functions.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/messaging.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/storage.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/teams.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/handlers/users.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/appwrite/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/base.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/client.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/access.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/automation.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/collections.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/content.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/dashboards.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/files.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/items.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/handlers/users.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/directus/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/client.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/issues.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/pull_requests.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/repositories.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/users.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/handlers/webhooks.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/common.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/issue.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/pull_request.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/repository.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/user.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/gitea/schemas/webhook.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/client.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/credentials.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/executions.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/projects.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/tags.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/users.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/variables.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/handlers/workflows.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/n8n/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/client.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/clients.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/dashboards.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/events.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/export.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/funnels.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/profiles.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/projects.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/reports.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/handlers/utils.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/openpanel/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/admin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/functions.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/storage.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/supabase/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/woocommerce/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/comments.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/coupons.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/customers.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/media.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/menus.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/orders.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/posts.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/products.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/reports.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/site.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/taxonomy.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/users.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/handlers/wp_cli.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/plugin_old_backup.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/common.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/media.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/order.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/post.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/product.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress/schemas/seo.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/handlers/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/handlers/bulk.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/handlers/database.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/handlers/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/plugin.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/schemas/__init__.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/schemas/bulk.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/schemas/database.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/plugins/wordpress_advanced/schemas/system.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/setup.cfg +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_api_keys.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_auth.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_auth_logic.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_dashboard.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_database.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_dynamic_endpoints_integration.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_encryption.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_client_registry.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_integration.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_pkce.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_schemas.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_storage.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_oauth_token_manager.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_rate_limiter.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_site_api.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_site_manager.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_tenant_isolation.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_tool_registry.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_user_auth.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_user_endpoints.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_user_keys.py +0 -0
- {mcphub_server-3.1.0 → mcphub_server-3.3.0}/tests/test_wordpress_plugin.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcphub-server
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: AI-native management hub for WordPress, WooCommerce, and self-hosted services via Model Context Protocol (MCP)
|
|
5
5
|
Author-email: MCP Hub <contact@mcphub.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -62,7 +62,7 @@ Connect your sites, stores, repos, and databases — manage them all through Cla
|
|
|
62
62
|
[](https://www.python.org/)
|
|
63
63
|
[](https://pypi.org/project/mcphub-server/)
|
|
64
64
|
[](https://hub.docker.com/r/airano/mcphub)
|
|
65
|
-
[]()
|
|
66
66
|
[]()
|
|
67
67
|
[](https://github.com/airano-ir/mcphub/actions/workflows/ci.yml)
|
|
68
68
|
|
|
@@ -157,7 +157,20 @@ curl http://localhost:8000/health
|
|
|
157
157
|
|
|
158
158
|
Open the **web dashboard** in your browser: **http://localhost:8000/dashboard**
|
|
159
159
|
|
|
160
|
-
You should see the login page.
|
|
160
|
+
You should see the login page. Log in with your `MASTER_API_KEY` or via **GitHub/Google OAuth** (if configured).
|
|
161
|
+
|
|
162
|
+
### Try It Now (No Setup Required)
|
|
163
|
+
|
|
164
|
+
**Don't want to self-host?** Try the demo instance at **[mcp.palebluedot.live](https://mcp.palebluedot.live)**:
|
|
165
|
+
|
|
166
|
+
1. Log in with **GitHub** or **Google**
|
|
167
|
+
2. Add your sites via the dashboard (My Sites → Add Service)
|
|
168
|
+
3. Go to **Connect** page — generate config for your AI client
|
|
169
|
+
4. Copy-paste the config into Claude Desktop, VS Code, or Claude Code
|
|
170
|
+
|
|
171
|
+
Your personal MCP endpoint: `https://mcp.palebluedot.live/u/{your-user-id}/{alias}/mcp`
|
|
172
|
+
|
|
173
|
+
---
|
|
161
174
|
|
|
162
175
|
### Configure Your Sites
|
|
163
176
|
|
|
@@ -346,12 +359,14 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
|
|
|
346
359
|
/appwrite/mcp → Appwrite tools (100 tools)
|
|
347
360
|
/directus/mcp → Directus tools (100 tools)
|
|
348
361
|
/project/{alias}/mcp → Per-project endpoint (auto-injects site)
|
|
362
|
+
/u/{user_id}/{alias}/mcp → Per-user endpoint (hosted/OAuth users)
|
|
349
363
|
```
|
|
350
364
|
|
|
351
365
|
**Recommendation**: Use plugin-specific endpoints instead of `/mcp` (596 tools) to minimize token usage.
|
|
352
366
|
|
|
353
367
|
| Endpoint | Use Case | Tools |
|
|
354
368
|
|----------|----------|------:|
|
|
369
|
+
| `/u/{user_id}/{alias}/mcp` | Hosted users (OAuth login) | 22-100 |
|
|
355
370
|
| `/project/{alias}/mcp` | Single-site workflow (recommended) | 22-100 |
|
|
356
371
|
| `/{plugin}/mcp` | Multi-site management | 23-101 |
|
|
357
372
|
| `/mcp` | Admin & discovery only | 596 |
|
|
@@ -372,7 +387,7 @@ Some MCP Hub tools require companion WordPress plugins:
|
|
|
372
387
|
|
|
373
388
|
| Tools | Requirement |
|
|
374
389
|
|-------|-------------|
|
|
375
|
-
| SEO tools (`wordpress_get_post_seo`, etc.) | [SEO
|
|
390
|
+
| SEO tools (`wordpress_get_post_seo`, etc.) | [Airano MCP SEO Bridge](https://wordpress.org/plugins/airano-mcp-seo-bridge/) ([GitHub](wordpress-plugin/airano-mcp-seo-bridge/)) + Rank Math or Yoast SEO |
|
|
376
391
|
| WP-CLI tools (15 tools: `wp_cache_*`, `wp_db_*`, etc.) | Docker socket + `CONTAINER` env var |
|
|
377
392
|
| WordPress Advanced database/system tools | Docker socket + `CONTAINER` env var |
|
|
378
393
|
| OpenPanel analytics integration | [OpenPanel Self-Hosted](wordpress-plugin/openpanel-self-hosted/) ([Download ZIP](wordpress-plugin/openpanel-self-hosted.zip)) |
|
|
@@ -412,7 +427,7 @@ Without Docker socket, WP-CLI tools return "not available" but all REST API tool
|
|
|
412
427
|
# Install with dev dependencies
|
|
413
428
|
pip install -e ".[dev]"
|
|
414
429
|
|
|
415
|
-
# Run tests (
|
|
430
|
+
# Run tests (481 tests)
|
|
416
431
|
pytest
|
|
417
432
|
|
|
418
433
|
# Format and lint
|
|
@@ -13,7 +13,7 @@ Connect your sites, stores, repos, and databases — manage them all through Cla
|
|
|
13
13
|
[](https://www.python.org/)
|
|
14
14
|
[](https://pypi.org/project/mcphub-server/)
|
|
15
15
|
[](https://hub.docker.com/r/airano/mcphub)
|
|
16
|
-
[]()
|
|
17
17
|
[]()
|
|
18
18
|
[](https://github.com/airano-ir/mcphub/actions/workflows/ci.yml)
|
|
19
19
|
|
|
@@ -108,7 +108,20 @@ curl http://localhost:8000/health
|
|
|
108
108
|
|
|
109
109
|
Open the **web dashboard** in your browser: **http://localhost:8000/dashboard**
|
|
110
110
|
|
|
111
|
-
You should see the login page.
|
|
111
|
+
You should see the login page. Log in with your `MASTER_API_KEY` or via **GitHub/Google OAuth** (if configured).
|
|
112
|
+
|
|
113
|
+
### Try It Now (No Setup Required)
|
|
114
|
+
|
|
115
|
+
**Don't want to self-host?** Try the demo instance at **[mcp.palebluedot.live](https://mcp.palebluedot.live)**:
|
|
116
|
+
|
|
117
|
+
1. Log in with **GitHub** or **Google**
|
|
118
|
+
2. Add your sites via the dashboard (My Sites → Add Service)
|
|
119
|
+
3. Go to **Connect** page — generate config for your AI client
|
|
120
|
+
4. Copy-paste the config into Claude Desktop, VS Code, or Claude Code
|
|
121
|
+
|
|
122
|
+
Your personal MCP endpoint: `https://mcp.palebluedot.live/u/{your-user-id}/{alias}/mcp`
|
|
123
|
+
|
|
124
|
+
---
|
|
112
125
|
|
|
113
126
|
### Configure Your Sites
|
|
114
127
|
|
|
@@ -297,12 +310,14 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
|
|
|
297
310
|
/appwrite/mcp → Appwrite tools (100 tools)
|
|
298
311
|
/directus/mcp → Directus tools (100 tools)
|
|
299
312
|
/project/{alias}/mcp → Per-project endpoint (auto-injects site)
|
|
313
|
+
/u/{user_id}/{alias}/mcp → Per-user endpoint (hosted/OAuth users)
|
|
300
314
|
```
|
|
301
315
|
|
|
302
316
|
**Recommendation**: Use plugin-specific endpoints instead of `/mcp` (596 tools) to minimize token usage.
|
|
303
317
|
|
|
304
318
|
| Endpoint | Use Case | Tools |
|
|
305
319
|
|----------|----------|------:|
|
|
320
|
+
| `/u/{user_id}/{alias}/mcp` | Hosted users (OAuth login) | 22-100 |
|
|
306
321
|
| `/project/{alias}/mcp` | Single-site workflow (recommended) | 22-100 |
|
|
307
322
|
| `/{plugin}/mcp` | Multi-site management | 23-101 |
|
|
308
323
|
| `/mcp` | Admin & discovery only | 596 |
|
|
@@ -323,7 +338,7 @@ Some MCP Hub tools require companion WordPress plugins:
|
|
|
323
338
|
|
|
324
339
|
| Tools | Requirement |
|
|
325
340
|
|-------|-------------|
|
|
326
|
-
| SEO tools (`wordpress_get_post_seo`, etc.) | [SEO
|
|
341
|
+
| SEO tools (`wordpress_get_post_seo`, etc.) | [Airano MCP SEO Bridge](https://wordpress.org/plugins/airano-mcp-seo-bridge/) ([GitHub](wordpress-plugin/airano-mcp-seo-bridge/)) + Rank Math or Yoast SEO |
|
|
327
342
|
| WP-CLI tools (15 tools: `wp_cache_*`, `wp_db_*`, etc.) | Docker socket + `CONTAINER` env var |
|
|
328
343
|
| WordPress Advanced database/system tools | Docker socket + `CONTAINER` env var |
|
|
329
344
|
| OpenPanel analytics integration | [OpenPanel Self-Hosted](wordpress-plugin/openpanel-self-hosted/) ([Download ZIP](wordpress-plugin/openpanel-self-hosted.zip)) |
|
|
@@ -363,7 +378,7 @@ Without Docker socket, WP-CLI tools return "not available" but all REST API tool
|
|
|
363
378
|
# Install with dev dependencies
|
|
364
379
|
pip install -e ".[dev]"
|
|
365
380
|
|
|
366
|
-
# Run tests (
|
|
381
|
+
# Run tests (481 tests)
|
|
367
382
|
pytest
|
|
368
383
|
|
|
369
384
|
# Format and lint
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Admin utility functions for role determination.
|
|
2
|
+
|
|
3
|
+
Centralizes admin email checking so it can be used in OAuth callback,
|
|
4
|
+
dashboard auth, and future admin/user panel unification (F.5+).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def is_admin_email(email: str | None) -> bool:
|
|
11
|
+
"""Check if an email is in the ADMIN_EMAILS env var list.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
email: Email address to check.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
True if email matches an admin email (case-insensitive).
|
|
18
|
+
"""
|
|
19
|
+
if not email:
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
admin_emails_raw = os.environ.get("ADMIN_EMAILS", "")
|
|
23
|
+
if not admin_emails_raw.strip():
|
|
24
|
+
return False
|
|
25
|
+
|
|
26
|
+
admin_emails = {e.strip().lower() for e in admin_emails_raw.split(",") if e.strip()}
|
|
27
|
+
return email.strip().lower() in admin_emails
|
|
@@ -14,6 +14,8 @@ from dataclasses import asdict, dataclass
|
|
|
14
14
|
from datetime import datetime, timedelta
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
import bcrypt
|
|
18
|
+
|
|
17
19
|
logger = logging.getLogger(__name__)
|
|
18
20
|
|
|
19
21
|
|
|
@@ -79,7 +81,7 @@ class APIKey:
|
|
|
79
81
|
"""
|
|
80
82
|
|
|
81
83
|
key_id: str
|
|
82
|
-
key_hash: str
|
|
84
|
+
key_hash: str # bcrypt hash (new keys) or SHA-256 hex (legacy)
|
|
83
85
|
project_id: str
|
|
84
86
|
scope: Scope
|
|
85
87
|
created_at: str
|
|
@@ -180,8 +182,16 @@ class APIKeyManager:
|
|
|
180
182
|
logger.error(f"Failed to save keys: {e}")
|
|
181
183
|
|
|
182
184
|
def _hash_key(self, api_key: str) -> str:
|
|
183
|
-
"""Hash API key for storage."""
|
|
184
|
-
return
|
|
185
|
+
"""Hash API key for storage using bcrypt."""
|
|
186
|
+
return bcrypt.hashpw(api_key.encode(), bcrypt.gensalt()).decode()
|
|
187
|
+
|
|
188
|
+
def _verify_key(self, api_key: str, key_hash: str) -> bool:
|
|
189
|
+
"""Verify API key against stored hash (supports bcrypt and legacy SHA-256)."""
|
|
190
|
+
if key_hash.startswith("$2"):
|
|
191
|
+
# bcrypt hash
|
|
192
|
+
return bcrypt.checkpw(api_key.encode(), key_hash.encode())
|
|
193
|
+
# Legacy SHA-256 fallback
|
|
194
|
+
return hashlib.sha256(api_key.encode()).hexdigest() == key_hash
|
|
185
195
|
|
|
186
196
|
def create_key(
|
|
187
197
|
self,
|
|
@@ -269,11 +279,9 @@ class APIKeyManager:
|
|
|
269
279
|
Returns:
|
|
270
280
|
Optional[str]: key_id if valid, None otherwise
|
|
271
281
|
"""
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
# Find key by hash
|
|
282
|
+
# Find key by verifying against stored hash (bcrypt or legacy SHA-256)
|
|
275
283
|
for key_id, key in self.keys.items():
|
|
276
|
-
if key.key_hash
|
|
284
|
+
if not self._verify_key(api_key, key.key_hash):
|
|
277
285
|
continue
|
|
278
286
|
|
|
279
287
|
# Check if valid (not revoked, not expired)
|
|
@@ -341,10 +349,8 @@ class APIKeyManager:
|
|
|
341
349
|
Returns:
|
|
342
350
|
Optional[APIKey]: The APIKey object if found, None otherwise
|
|
343
351
|
"""
|
|
344
|
-
key_hash = self._hash_key(api_key)
|
|
345
|
-
|
|
346
352
|
for key_id, key in self.keys.items():
|
|
347
|
-
if key.key_hash
|
|
353
|
+
if self._verify_key(api_key, key.key_hash):
|
|
348
354
|
logger.debug(f"Found API key {key_id} by token")
|
|
349
355
|
return key
|
|
350
356
|
|
|
@@ -20,6 +20,11 @@ import json
|
|
|
20
20
|
|
|
21
21
|
# Supported MCP client types
|
|
22
22
|
SUPPORTED_CLIENTS = [
|
|
23
|
+
{
|
|
24
|
+
"id": "claude_connectors",
|
|
25
|
+
"label": "Claude.ai Connectors",
|
|
26
|
+
"description": "claude.ai/customize/connectors",
|
|
27
|
+
},
|
|
23
28
|
{
|
|
24
29
|
"id": "claude_desktop",
|
|
25
30
|
"label": "Claude Desktop",
|
|
@@ -47,6 +52,9 @@ SUPPORTED_CLIENTS = [
|
|
|
47
52
|
},
|
|
48
53
|
]
|
|
49
54
|
|
|
55
|
+
# Clients that only need a URL (no JSON config snippet, no transport Note)
|
|
56
|
+
WEB_CLIENTS = {"claude_connectors", "chatgpt"}
|
|
57
|
+
|
|
50
58
|
|
|
51
59
|
def get_supported_clients() -> list[dict[str, str]]:
|
|
52
60
|
"""Return the list of supported MCP client types."""
|
|
@@ -79,10 +87,14 @@ def generate_config(
|
|
|
79
87
|
endpoint_url = f"{base_url}/u/{user_id}/{alias}/mcp"
|
|
80
88
|
server_name = f"mcphub-{alias}"
|
|
81
89
|
|
|
90
|
+
# Claude Desktop uses streamableHttp; Claude Code, VS Code, Cursor use http
|
|
91
|
+
transport_type = "streamableHttp" if client_type == "claude_desktop" else "http"
|
|
92
|
+
|
|
82
93
|
if client_type in ("claude_desktop", "claude_code"):
|
|
83
94
|
config = {
|
|
84
95
|
"mcpServers": {
|
|
85
96
|
server_name: {
|
|
97
|
+
"type": transport_type,
|
|
86
98
|
"url": endpoint_url,
|
|
87
99
|
"headers": {
|
|
88
100
|
"Authorization": f"Bearer {api_key}",
|
|
@@ -97,6 +109,7 @@ def generate_config(
|
|
|
97
109
|
"mcp": {
|
|
98
110
|
"servers": {
|
|
99
111
|
server_name: {
|
|
112
|
+
"type": transport_type,
|
|
100
113
|
"url": endpoint_url,
|
|
101
114
|
"headers": {
|
|
102
115
|
"Authorization": f"Bearer {api_key}",
|
|
@@ -107,7 +120,7 @@ def generate_config(
|
|
|
107
120
|
}
|
|
108
121
|
return json.dumps(config, indent=2)
|
|
109
122
|
|
|
110
|
-
elif client_type
|
|
123
|
+
elif client_type in ("claude_connectors", "chatgpt"):
|
|
111
124
|
return endpoint_url
|
|
112
125
|
|
|
113
126
|
else:
|
|
@@ -90,21 +90,29 @@ class DashboardAuth:
|
|
|
90
90
|
return False, "", None
|
|
91
91
|
|
|
92
92
|
api_key_clean = api_key.strip()
|
|
93
|
+
# Check if master key dashboard login is disabled
|
|
94
|
+
master_login_disabled = (
|
|
95
|
+
os.environ.get("DISABLE_MASTER_KEY_LOGIN", "false").lower() == "true"
|
|
96
|
+
)
|
|
97
|
+
|
|
93
98
|
# Check master API key (from env var)
|
|
94
|
-
if
|
|
95
|
-
|
|
99
|
+
if (
|
|
100
|
+
not master_login_disabled
|
|
101
|
+
and self.master_api_key
|
|
102
|
+
and secrets.compare_digest(api_key_clean, self.master_api_key.strip())
|
|
96
103
|
):
|
|
97
104
|
return True, "master", None
|
|
98
105
|
|
|
99
106
|
# Check AuthManager's master key (covers auto-generated temp keys)
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
if not master_login_disabled:
|
|
108
|
+
try:
|
|
109
|
+
from core.auth import get_auth_manager
|
|
102
110
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
auth_mgr = get_auth_manager()
|
|
112
|
+
if auth_mgr.validate_master_key(api_key):
|
|
113
|
+
return True, "master", None
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.debug(f"AuthManager check skipped: {e}")
|
|
108
116
|
|
|
109
117
|
# Check project API keys with admin scope
|
|
110
118
|
try:
|
|
@@ -353,9 +361,10 @@ def get_session_display_info(session) -> dict:
|
|
|
353
361
|
if isinstance(session, DashboardSession):
|
|
354
362
|
return {"name": "Admin", "type": "admin", "email": None, "avatar": None}
|
|
355
363
|
if isinstance(session, dict):
|
|
364
|
+
session_type = "admin" if session.get("role") == "admin" else "user"
|
|
356
365
|
return {
|
|
357
366
|
"name": session.get("name") or session.get("email", "User"),
|
|
358
|
-
"type":
|
|
367
|
+
"type": session_type,
|
|
359
368
|
"email": session.get("email"),
|
|
360
369
|
"avatar": None,
|
|
361
370
|
}
|