fix(qa): health check, admin notice, docs, logo, Coolify port

- WP Advanced health_check uses aiohttp to /wp-json/ directly
- SEO Bridge admin notice only on Plugins page
- SEO Bridge README.md consolidated, changelog complete
- OpenPanel Self-Hosted README.md created
- Dashboard sidebar uses actual logo.svg
- docker-compose: expose instead of ports for Coolify
- README: version badge, wordpress_advanced endpoint, env var table
- Docs: SSE references fixed to streamable-http

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
airano
2026-02-19 01:55:29 +03:30
parent ff79968170
commit bb2a416dd5
10 changed files with 346 additions and 285 deletions

View File

@@ -6,6 +6,7 @@
Connect your sites, stores, repos, and databases — manage them all through Claude, ChatGPT, Cursor, or any MCP client. Connect your sites, stores, repos, and databases — manage them all through Claude, ChatGPT, Cursor, or any MCP client.
[![Version: 3.0.1](https://img.shields.io/badge/version-3.0.1-blue.svg)](https://github.com/airano-ir/mcphub/releases)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-3776ab.svg)](https://www.python.org/) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-3776ab.svg)](https://www.python.org/)
[![PyPI](https://img.shields.io/pypi/v/mcphub-server.svg)](https://pypi.org/project/mcphub-server/) [![PyPI](https://img.shields.io/pypi/v/mcphub-server.svg)](https://pypi.org/project/mcphub-server/)
@@ -133,6 +134,53 @@ GITEA_REPO1_TOKEN=your_gitea_token
GITEA_REPO1_ALIAS=mygitea GITEA_REPO1_ALIAS=mygitea
``` ```
<details>
<summary><b>Full Environment Variable Reference</b></summary>
**System Configuration:**
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `MASTER_API_KEY` | Recommended | Auto-generated | Master API key for admin access |
| `LOG_LEVEL` | No | `INFO` | Logging level (DEBUG, INFO, WARNING, ERROR) |
| `OAUTH_JWT_SECRET_KEY` | For OAuth | — | JWT signing secret for OAuth tokens |
| `OAUTH_BASE_URL` | For OAuth | — | Public URL (e.g., `https://mcp.example.com`) |
| `OAUTH_JWT_ALGORITHM` | No | `HS256` | JWT algorithm |
| `OAUTH_ACCESS_TOKEN_TTL` | No | `3600` | Access token TTL in seconds |
| `OAUTH_REFRESH_TOKEN_TTL` | No | `604800` | Refresh token TTL in seconds |
| `OAUTH_STORAGE_TYPE` | No | `json` | Token storage type |
| `OAUTH_STORAGE_PATH` | No | `/app/data` | Data directory path |
**Plugin Site Configuration** — Pattern: `{PLUGIN_TYPE}_{SITE_ID}_{KEY}`
| Plugin | Required Keys | Optional Keys |
|--------|--------------|---------------|
| `WORDPRESS` | `URL`, `USERNAME`, `APP_PASSWORD` | `ALIAS`, `CONTAINER` |
| `WOOCOMMERCE` | `URL`, `CONSUMER_KEY`, `CONSUMER_SECRET` | `ALIAS` |
| `WORDPRESS_ADVANCED` | `URL`, `USERNAME`, `APP_PASSWORD`, `CONTAINER` | `ALIAS` |
| `GITEA` | `URL`, `TOKEN` | `ALIAS` |
| `N8N` | `URL`, `API_KEY` | `ALIAS` |
| `SUPABASE` | `URL`, `SERVICE_ROLE_KEY` | `ALIAS` |
| `OPENPANEL` | `URL`, `CLIENT_ID`, `CLIENT_SECRET` | `ALIAS` |
| `APPWRITE` | `URL`, `API_KEY`, `PROJECT_ID` | `ALIAS` |
| `DIRECTUS` | `URL`, `TOKEN` | `ALIAS` |
**Example** — Multiple WordPress sites:
```bash
WORDPRESS_BLOG_URL=https://blog.example.com
WORDPRESS_BLOG_USERNAME=admin
WORDPRESS_BLOG_APP_PASSWORD=xxxx xxxx xxxx xxxx
WORDPRESS_BLOG_ALIAS=blog
WORDPRESS_SHOP_URL=https://shop.example.com
WORDPRESS_SHOP_USERNAME=admin
WORDPRESS_SHOP_APP_PASSWORD=yyyy yyyy yyyy yyyy
WORDPRESS_SHOP_ALIAS=shop
```
</details>
### Connect Your AI Client ### Connect Your AI Client
All MCP clients use **Bearer token** authentication: `Authorization: Bearer YOUR_API_KEY` All MCP clients use **Bearer token** authentication: `Authorization: Bearer YOUR_API_KEY`
@@ -235,6 +283,7 @@ MCP Hub supports **Open Dynamic Client Registration** (RFC 7591). ChatGPT can au
/system/mcp → System tools only (24 tools) /system/mcp → System tools only (24 tools)
/wordpress/mcp → WordPress tools (67 tools) /wordpress/mcp → WordPress tools (67 tools)
/woocommerce/mcp → WooCommerce tools (28 tools) /woocommerce/mcp → WooCommerce tools (28 tools)
/wordpress_advanced/mcp → WordPress Advanced tools (22 tools)
/gitea/mcp → Gitea tools (56 tools) /gitea/mcp → Gitea tools (56 tools)
/n8n/mcp → n8n tools (56 tools) /n8n/mcp → n8n tools (56 tools)
/supabase/mcp → Supabase tools (70 tools) /supabase/mcp → Supabase tools (70 tools)

View File

@@ -120,13 +120,12 @@
<!-- Logo --> <!-- Logo -->
<div class="flex items-center justify-between h-16 px-4 border-b border-gray-700"> <div class="flex items-center justify-between h-16 px-4 border-b border-gray-700">
<div class="flex items-center" x-show="sidebarOpen"> <div class="flex items-center" x-show="sidebarOpen">
<div class="w-8 h-8 bg-primary-600 rounded-lg flex items-center justify-center"> <img src="/static/logo.svg" alt="MCP Hub" class="w-8 h-8">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
</div>
<span class="{% if lang == 'fa' %}mr-3{% else %}ml-3{% endif %} font-bold text-lg">MCP Hub</span> <span class="{% if lang == 'fa' %}mr-3{% else %}ml-3{% endif %} font-bold text-lg">MCP Hub</span>
</div> </div>
<div x-show="!sidebarOpen" class="flex items-center justify-center">
<img src="/static/logo.svg" alt="MCP Hub" class="w-8 h-8">
</div>
<button <button
@click="sidebarOpen = !sidebarOpen" @click="sidebarOpen = !sidebarOpen"
class="p-2 rounded-lg hover:bg-gray-700 transition-colors" class="p-2 rounded-lg hover:bg-gray-700 transition-colors"

View File

@@ -7,8 +7,10 @@
# curl http://localhost:8000/health # verify server is running # curl http://localhost:8000/health # verify server is running
# open http://localhost:8000/dashboard # web dashboard # open http://localhost:8000/dashboard # web dashboard
# #
# For Coolify deployments: # Port mapping:
# Change ports to "8000" (no host mapping) — Coolify handles routing. # - Coolify: Do NOT use 'ports' — Coolify's reverse proxy handles routing.
# The 'expose' directive below is sufficient.
# - Standalone Docker: Uncomment the 'ports' section below to bind to host.
# =================================== # ===================================
services: services:
@@ -19,8 +21,14 @@ services:
container_name: mcphub container_name: mcphub
restart: unless-stopped restart: unless-stopped
ports: # Container exposes port 8000 to linked services / Coolify proxy
- "8000:8000" expose:
- "8000"
# Standalone Docker: Uncomment below to access at http://localhost:8000
# Coolify: Leave commented — Coolify's reverse proxy handles routing
# ports:
# - "8000:8000"
# Environment variables # Environment variables
environment: environment:

View File

@@ -302,7 +302,7 @@ DIRECTUS_SITE1_ALIAS=my-directus # Recommended
## Running the Server ## Running the Server
### SSE Transport (for remote AI clients) ### Streamable HTTP Transport (for remote AI clients)
```bash ```bash
python server.py --transport streamable-http --port 8000 python server.py --transport streamable-http --port 8000

View File

@@ -112,11 +112,23 @@ class WordPressAdvancedPlugin(BasePlugin):
Dict with health status and WP-CLI availability Dict with health status and WP-CLI availability
""" """
try: try:
# Test REST API access (primary health indicator — most tools use REST) # Test REST API access by hitting /wp-json/ directly
# NOTE: self.client.get("/") hits /wp-json/wp/v2/ which doesn't
# return a "name" field. We need /wp-json/ for the site index.
rest_api_available = False rest_api_available = False
try: try:
site_info = await self.client.get("/") import aiohttp
rest_api_available = bool(site_info.get("name"))
site_url = self.client.site_url
async with aiohttp.ClientSession() as session:
async with session.get(
f"{site_url}/wp-json/",
timeout=aiohttp.ClientTimeout(total=10),
ssl=False,
) as resp:
if resp.status == 200:
data = await resp.json()
rest_api_available = bool(data.get("name"))
except Exception as e: except Exception as e:
self.logger.warning(f"REST API check failed: {e}") self.logger.warning(f"REST API check failed: {e}")

View File

@@ -0,0 +1,106 @@
# OpenPanel Self-Hosted - WordPress Plugin
**Version:** 1.1.1
**Requires:** WordPress 5.8+, PHP 7.4+
**License:** GPLv2 or later
## Description
**OpenPanel Self-Hosted** is a fork of the [official OpenPanel WordPress plugin](https://wordpress.org/plugins/openpanel/) with full **Self-Hosted instance support**. [OpenPanel](https://openpanel.dev) is an open-source web and product analytics platform — a privacy-friendly alternative to Google Analytics.
This plugin seamlessly integrates OpenPanel (Cloud or Self-Hosted) with your WordPress site while maximizing reliability and avoiding ad-blocker interference.
Designed to work with [MCP Hub](https://github.com/airano-ir/mcphub) for AI-powered analytics management.
## Key Features
- **Self-Hosted Support**: Works with both OpenPanel Cloud and your own Self-Hosted instance
- **Ad-Blocker Resistant**: Serves analytics scripts and API calls from your own domain
- **Real-Time Analytics**: Instant insights without processing delays
- **Privacy-Friendly**: Cookie-less tracking — no cookie banners needed
- **Performance Optimized**: Local script caching and efficient proxying
- **Product Analytics**: Funnel analysis, retention tracking, conversion metrics
- **Web Analytics**: Visitors, referrals, top pages, devices, sessions, bounce rates
## How It Works
1. **Inlines** `op1.js` directly into your pages (cached locally for 1 week)
2. **Bootstraps** the OpenPanel SDK with your Client ID automatically
3. **Proxies** all SDK requests through WordPress REST API (`/wp-json/openpanel/`)
4. **Preserves** all request methods, headers, query parameters, and body data
Serving scripts and data from your own domain origin avoids third-party blocking and improves tracking reliability.
## Installation
### Method 1: Upload via WordPress Admin
1. Download `openpanel-self-hosted.zip` from [Releases](https://github.com/airano-ir/mcphub)
2. Go to WordPress Admin > Plugins > Add New > Upload Plugin
3. Upload the ZIP and click "Install Now"
4. Activate the plugin
### Method 2: Manual Upload
1. Upload the `openpanel-self-hosted` folder to `/wp-content/plugins/`
2. Activate via WordPress Admin > Plugins
## Configuration
### Cloud Mode (openpanel.dev)
1. Sign up at [OpenPanel.dev](https://openpanel.dev) and create a project
2. Go to **Settings > OpenPanel** in WordPress admin
3. Select **Cloud (openpanel.dev)** as hosting mode
4. Paste your **Client ID** (starts with `op_client_`)
5. Enable desired auto-tracking features
### Self-Hosted Mode
1. Go to **Settings > OpenPanel** in WordPress admin
2. Select **Self-Hosted** as hosting mode
3. Enter your **API URL** (e.g., `https://api.openpanel.yourdomain.com`)
4. Enter your **Dashboard URL** (e.g., `https://openpanel.yourdomain.com`)
5. Paste your **Client ID** from your self-hosted instance
6. Enable desired auto-tracking features
| Setting | Example Value |
|---------|---------------|
| API URL | `https://api.openpanel.yourdomain.com` |
| Dashboard URL | `https://openpanel.yourdomain.com` |
| Client ID | Your project's client ID from OpenPanel |
## Privacy
- **No Cookie Banners Required**: Cookie-less tracking technology
- **GDPR Friendly**: Compliant without requiring user consent for basic analytics
- **Data Ownership**: Full control over your analytics data
- **No PII Collection**: Tracks behavior patterns without personal information
## Changelog
### 1.1.1
- Fixed op1.js loading for self-hosted instances (was always loading from CDN)
- Both inline cache and external fallback now use the correct self-hosted URL
### 1.1.0
- Full self-hosted OpenPanel instance support
- Hosting mode selector: Cloud vs Self-Hosted
- Configurable API URL and Dashboard URL
- Dynamic proxy validation for custom domains
### 1.0.0
- Initial release with OpenPanel Cloud integration
- Automatic script inlining with local caching
- REST API proxy for ad-blocker resistant tracking
- Auto-tracking: page views, outgoing links, page attributes
## Support
- **Plugin issues:** [GitHub Issues](https://github.com/airano-ir/mcphub/issues)
- **OpenPanel platform:** [OpenPanel.dev](https://openpanel.dev)
- **MCP Hub:** [MCP Hub Documentation](https://github.com/airano-ir/mcphub)
## License
GPLv2 or later - See [LICENSE](https://www.gnu.org/licenses/gpl-2.0.html) for details

Binary file not shown.

View File

@@ -10,94 +10,82 @@ SEO API Bridge is a comprehensive WordPress plugin that exposes Rank Math SEO an
## What's New in 1.3.0 ## What's New in 1.3.0
**Full REST API Endpoints** - GET and POST operations for all post types - **Full REST API Endpoints** - GET and POST operations for all post types
**Product SEO Support** - Complete WooCommerce product SEO management - **Product SEO Support** - Complete WooCommerce product SEO management
**Simplified Integration** - Direct API calls instead of meta field manipulation - **Simplified Integration** - Direct API calls instead of meta field manipulation
**Better Error Handling** - Proper validation and error responses - **Better Error Handling** - Proper validation and error responses
## Features ## Features
- **Rank Math SEO Support** - Full access to all Rank Math meta fields - **Rank Math SEO Support** - Full access to all Rank Math meta fields
- **Yoast SEO Support** - Full access to all Yoast SEO meta fields - **Yoast SEO Support** - Full access to all Yoast SEO meta fields
- **WooCommerce Compatible** - Works with product post types - **WooCommerce Compatible** - Works with product post types
- **Secure** - Requires proper authentication and edit_posts capability - **Secure** - Requires proper authentication and edit_posts capability
- **Auto-Detection** - Automatically detects which SEO plugin is active - **Auto-Detection** - Automatically detects which SEO plugin is active
- **Health Check Endpoint** - NEW! Dedicated API endpoint for plugin detection - **Health Check Endpoint** - Dedicated API endpoint for plugin detection
- **Zero Configuration** - Works out of the box after activation - **Zero Configuration** - Works out of the box after activation
## Supported SEO Fields ## Supported SEO Fields
### Rank Math SEO ### Rank Math SEO
#### Core Fields | Category | Field | Description |
- `rank_math_focus_keyword` - Focus keyword |----------|-------|-------------|
- `rank_math_title` - Meta title | Core | `rank_math_focus_keyword` | Focus keyword |
- `rank_math_description` - Meta description | Core | `rank_math_title` | Meta title |
- `rank_math_additional_keywords` - Additional keywords | Core | `rank_math_description` | Meta description |
| Core | `rank_math_additional_keywords` | Additional keywords |
#### Advanced Fields | Advanced | `rank_math_canonical_url` | Canonical URL |
- `rank_math_canonical_url` - Canonical URL | Advanced | `rank_math_robots` | Robots meta directives |
- `rank_math_robots` - Robots meta directives | Advanced | `rank_math_breadcrumb_title` | Breadcrumb title |
- `rank_math_breadcrumb_title` - Breadcrumb title | Open Graph | `rank_math_facebook_title` | OG title |
| Open Graph | `rank_math_facebook_description` | OG description |
#### Open Graph (Facebook) | Open Graph | `rank_math_facebook_image` | OG image URL |
- `rank_math_facebook_title` - OG title | Open Graph | `rank_math_facebook_image_id` | OG image ID |
- `rank_math_facebook_description` - OG description | Twitter | `rank_math_twitter_title` | Twitter title |
- `rank_math_facebook_image` - OG image URL | Twitter | `rank_math_twitter_description` | Twitter description |
- `rank_math_facebook_image_id` - OG image ID | Twitter | `rank_math_twitter_image` | Twitter image URL |
| Twitter | `rank_math_twitter_image_id` | Twitter image ID |
#### Twitter Card | Twitter | `rank_math_twitter_card_type` | Card type (summary, summary_large_image) |
- `rank_math_twitter_title` - Twitter title
- `rank_math_twitter_description` - Twitter description
- `rank_math_twitter_image` - Twitter image URL
- `rank_math_twitter_image_id` - Twitter image ID
- `rank_math_twitter_card_type` - Card type (summary, summary_large_image)
### Yoast SEO ### Yoast SEO
#### Core Fields | Category | Field | Description |
- `_yoast_wpseo_focuskw` - Focus keyword |----------|-------|-------------|
- `_yoast_wpseo_title` - Meta title | Core | `_yoast_wpseo_focuskw` | Focus keyword |
- `_yoast_wpseo_metadesc` - Meta description | Core | `_yoast_wpseo_title` | Meta title |
| Core | `_yoast_wpseo_metadesc` | Meta description |
#### Advanced Fields | Advanced | `_yoast_wpseo_canonical` | Canonical URL |
- `_yoast_wpseo_canonical` - Canonical URL | Advanced | `_yoast_wpseo_meta-robots-noindex` | Noindex setting |
- `_yoast_wpseo_meta-robots-noindex` - Noindex setting | Advanced | `_yoast_wpseo_meta-robots-nofollow` | Nofollow setting |
- `_yoast_wpseo_meta-robots-nofollow` - Nofollow setting | Advanced | `_yoast_wpseo_bctitle` | Breadcrumb title |
- `_yoast_wpseo_bctitle` - Breadcrumb title | Open Graph | `_yoast_wpseo_opengraph-title` | OG title |
| Open Graph | `_yoast_wpseo_opengraph-description` | OG description |
#### Open Graph | Open Graph | `_yoast_wpseo_opengraph-image` | OG image URL |
- `_yoast_wpseo_opengraph-title` - OG title | Open Graph | `_yoast_wpseo_opengraph-image-id` | OG image ID |
- `_yoast_wpseo_opengraph-description` - OG description | Twitter | `_yoast_wpseo_twitter-title` | Twitter title |
- `_yoast_wpseo_opengraph-image` - OG image URL | Twitter | `_yoast_wpseo_twitter-description` | Twitter description |
- `_yoast_wpseo_opengraph-image-id` - OG image ID | Twitter | `_yoast_wpseo_twitter-image` | Twitter image URL |
| Twitter | `_yoast_wpseo_twitter-image-id` | Twitter image ID |
#### Twitter Card
- `_yoast_wpseo_twitter-title` - Twitter title
- `_yoast_wpseo_twitter-description` - Twitter description
- `_yoast_wpseo_twitter-image` - Twitter image URL
- `_yoast_wpseo_twitter-image-id` - Twitter image ID
## Installation ## Installation
### Method 1: Manual Upload via WordPress Admin ### Method 1: Upload via WordPress Admin
1. Download the plugin folder 1. Download `seo-api-bridge.zip` from [Releases](https://github.com/airano-ir/mcphub)
2. Create a ZIP file: `seo-api-bridge.zip` 2. Go to WordPress Admin > Plugins > Add New > Upload Plugin
3. Go to WordPress Admin → Plugins → Add New → Upload Plugin 3. Upload the ZIP file and click "Install Now"
4. Upload the ZIP file and click "Install Now" 4. Click "Activate Plugin"
5. Click "Activate Plugin"
### Method 2: FTP/SSH Upload ### Method 2: FTP/SSH Upload
1. Upload the `seo-api-bridge` folder to `/wp-content/plugins/` 1. Upload the `seo-api-bridge` folder to `/wp-content/plugins/`
2. Go to WordPress Admin Plugins 2. Go to WordPress Admin > Plugins
3. Find "SEO API Bridge" and click "Activate" 3. Find "SEO API Bridge" and click "Activate"
### Method 3: WP-CLI ### Method 3: WP-CLI
```bash ```bash
# Via SSH to your WordPress container
cd /var/www/html/wp-content/plugins/ cd /var/www/html/wp-content/plugins/
# Copy the plugin folder here # Copy the plugin folder here
wp plugin activate seo-api-bridge wp plugin activate seo-api-bridge
@@ -105,28 +93,46 @@ wp plugin activate seo-api-bridge
## REST API Endpoints ## REST API Endpoints
All endpoints require **WordPress Application Password** authentication.
### Status Endpoint ### Status Endpoint
**GET** `/wp-json/seo-api-bridge/v1/status` **GET** `/wp-json/seo-api-bridge/v1/status`
Check plugin status and detected SEO plugins.
```bash ```bash
curl https://yoursite.com/wp-json/seo-api-bridge/v1/status curl -X GET "https://yoursite.com/wp-json/seo-api-bridge/v1/status" \
-u "username:application_password"
```
**Response:**
```json
{
"plugin": "SEO API Bridge",
"version": "1.3.0",
"active": true,
"seo_plugins": {
"rank_math": { "active": true, "version": "1.0.257" },
"yoast": { "active": false, "version": null }
},
"supported_post_types": ["post", "page", "product"],
"message": "SEO API Bridge is active and working with Rank Math SEO."
}
``` ```
### Post SEO Endpoints ### Post SEO Endpoints
**GET** `/wp-json/seo-api-bridge/v1/posts/{id}/seo` **GET** `/wp-json/seo-api-bridge/v1/posts/{id}/seo` — Get SEO metadata for a post
Get SEO metadata for a post. **POST** `/wp-json/seo-api-bridge/v1/posts/{id}/seo` — Update SEO metadata for a post
**POST** `/wp-json/seo-api-bridge/v1/posts/{id}/seo`
Update SEO metadata for a post.
```bash ```bash
curl -X POST https://yoursite.com/wp-json/seo-api-bridge/v1/posts/123/seo \ # Get post SEO
curl -X GET "https://yoursite.com/wp-json/seo-api-bridge/v1/posts/123/seo" \
-u "username:application_password"
# Update post SEO
curl -X POST "https://yoursite.com/wp-json/seo-api-bridge/v1/posts/123/seo" \
-u "username:application_password" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"focus_keyword": "wordpress", "seo_title": "My Title"}' -d '{"focus_keyword": "wordpress", "seo_title": "My Title"}'
``` ```
@@ -141,19 +147,38 @@ curl -X POST https://yoursite.com/wp-json/seo-api-bridge/v1/posts/123/seo \
**GET** `/wp-json/seo-api-bridge/v1/products/{id}/seo` **GET** `/wp-json/seo-api-bridge/v1/products/{id}/seo`
Get SEO metadata for a WooCommerce product.
**POST** `/wp-json/seo-api-bridge/v1/products/{id}/seo` **POST** `/wp-json/seo-api-bridge/v1/products/{id}/seo`
Update SEO metadata for a WooCommerce product.
```bash ```bash
curl -X POST https://yoursite.com/wp-json/seo-api-bridge/v1/products/1217/seo \ curl -X POST "https://yoursite.com/wp-json/seo-api-bridge/v1/products/1217/seo" \
-u "username:application_password" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"focus_keyword": "product keyword", "seo_title": "Product Title"}' -d '{"focus_keyword": "product keyword", "seo_title": "Product Title"}'
``` ```
## Usage with MCP Servers ### Alternative: Standard WordPress REST API
The plugin also registers all SEO meta fields on standard WordPress REST API endpoints. You can read/write SEO data directly via:
- `GET/POST /wp-json/wp/v2/posts/{id}` — SEO fields in the `meta` object
- `GET/POST /wp-json/wp/v2/pages/{id}`
- `GET/POST /wp-json/wp/v2/products/{id}` (WooCommerce)
```bash
# Read SEO fields via standard endpoint
curl -X GET "https://yoursite.com/wp-json/wp/v2/posts/123" \
-u "username:application_password"
# Update SEO via standard endpoint
curl -X POST "https://yoursite.com/wp-json/wp/v2/posts/123" \
-u "username:application_password" \
-H "Content-Type: application/json" \
-d '{"meta": {"rank_math_focus_keyword": "wordpress optimization"}}'
```
## Usage with MCP Hub
This plugin is designed to work with [MCP Hub](https://github.com/airano-ir/mcphub).
```javascript ```javascript
// Get product SEO // Get product SEO
@@ -172,244 +197,98 @@ await mcp.wordpress_update_product_seo({
}); });
``` ```
**Benefits of this approach:**
1.**WordPress Best Practice** - Uses recommended core REST API functionality
2.**Zero Maintenance** - Leverages WordPress built-in features
3.**Universal Compatibility** - Works with all WordPress REST API clients
4.**Inherits Security** - Uses WordPress authentication and permissions
5.**Simpler Code** - No custom endpoints to maintain
**Standard Endpoints:**
- Posts/Pages: `/wp-json/wp/v2/posts/{id}` or `/wp-json/wp/v2/pages/{id}`
- Products: `/wp-json/wp/v2/products/{id}` (WooCommerce custom post type)
**SEO data is in the `meta` object:**
```json
{
"id": 123,
"title": {"rendered": "My Post"},
"meta": {
"rank_math_focus_keyword": "wordpress seo",
"rank_math_title": "Complete SEO Guide",
"rank_math_description": "Learn WordPress SEO best practices..."
}
}
```
### Reading SEO Data
**Get Post with SEO Fields:**
```bash
GET /wp-json/wp/v2/posts/{id}
```
**Response includes:**
```json
{
"id": 123,
"title": {"rendered": "My Post"},
"meta": {
"rank_math_focus_keyword": "wordpress seo",
"rank_math_title": "Complete WordPress SEO Guide",
"rank_math_description": "Learn how to optimize your WordPress site...",
"rank_math_facebook_title": "SEO Guide for Facebook",
"rank_math_twitter_card_type": "summary_large_image"
}
}
```
### Writing SEO Data
**Update Post SEO Fields:**
```bash
POST /wp-json/wp/v2/posts/{id}
Authorization: Basic [base64(username:application_password)]
Content-Type: application/json
{
"meta": {
"rank_math_focus_keyword": "wordpress optimization",
"rank_math_title": "WordPress Optimization Tips",
"rank_math_description": "Discover the best practices for WordPress optimization"
}
}
```
### WooCommerce Products
**Get Product with SEO:**
```bash
GET /wp-json/wp/v2/products/{id}
```
**Update Product SEO:**
```bash
POST /wp-json/wp/v2/products/{id}
{
"meta": {
"rank_math_focus_keyword": "premium widget",
"rank_math_description": "Buy the best premium widget online"
}
}
```
## Usage with MCP Server
This plugin is designed to work with the [MCP Hub](https://github.com/airano-ir/mcphub).
### Example MCP Tool Usage
```python ```python
# Get post SEO data # Get post SEO data
result = await mcp.call_tool( result = await mcp.call_tool(
"wordpress_site1_get_post_seo", "wordpress_get_post_seo",
{"post_id": 123} {"site": "yoursite", "post_id": 123}
) )
# Update post SEO # Update post SEO
result = await mcp.call_tool( result = await mcp.call_tool(
"wordpress_site1_update_post_seo", "wordpress_update_post_seo",
{ {
"site": "yoursite",
"post_id": 123, "post_id": 123,
"focus_keyword": "wordpress seo", "focus_keyword": "wordpress seo",
"seo_title": "Complete SEO Guide", "seo_title": "Complete SEO Guide",
"meta_description": "Learn WordPress SEO..." "meta_description": "Learn WordPress SEO..."
} }
) )
# Update WooCommerce product SEO
result = await mcp.call_tool(
"wordpress_site1_update_product_seo",
{
"product_id": 456,
"focus_keyword": "premium widget",
"meta_description": "Buy the best widget"
}
)
``` ```
## Verification ## Verification
### Check if Plugin is Working 1. **Admin Notice:** After activation, visit the Plugins page to see a status notice indicating which SEO plugin was detected.
1. **Admin Notice:** After activation, you should see a success notice indicating which SEO plugin was detected 2. **Status Endpoint:**
2. **Health Check Endpoint (v1.1.0+):**
```bash ```bash
# Check plugin status directly
curl -X GET "https://your-site.com/wp-json/seo-api-bridge/v1/status" \ curl -X GET "https://your-site.com/wp-json/seo-api-bridge/v1/status" \
-u "username:application_password" -u "username:application_password"
``` ```
**Response:**
```json
{
"plugin": "SEO API Bridge",
"version": "1.1.0",
"active": true,
"seo_plugins": {
"rank_math": {
"active": true,
"version": "1.0.257"
},
"yoast": {
"active": false,
"version": null
}
},
"supported_post_types": ["post", "page", "product"],
"message": "SEO API Bridge is active and working with Rank Math SEO."
}
```
3. **REST API Test:** 3. **REST API Test:**
```bash ```bash
# Get any post and check if meta fields are present
curl -X GET "https://your-site.com/wp-json/wp/v2/posts/1" \ curl -X GET "https://your-site.com/wp-json/wp/v2/posts/1" \
-u "username:application_password" -u "username:application_password"
``` ```
4. **MCP Health Check:** The MCP server will automatically detect the plugin using the new endpoint 4. **MCP Health Check:** The MCP server automatically detects the plugin using the status endpoint.
## Security ## Security
- All meta fields require authentication via Application Passwords - All meta fields require authentication via Application Passwords
- Write access requires `edit_posts` capability - Write access requires `edit_posts` capability
- Read access follows WordPress post visibility rules - Read access follows WordPress post visibility rules
- No sensitive data exposed without proper permissions - No sensitive data exposed without proper permissions
## Troubleshooting ## Troubleshooting
### MCP Server Cannot Detect Plugin ### MCP Server Cannot Detect Plugin
**Issue:** MCP reports "SEO API Bridge plugin not detected" even though plugin is active 1. Upgrade to v1.1.0+ (has dedicated health check endpoint)
2. Restart MCP server
**Solution for v1.1.0+:** 3. Test endpoint: `curl "https://your-site.com/wp-json/seo-api-bridge/v1/status" -u "user:pass"`
1. **Upgrade to v1.1.0** - This version adds a dedicated health check endpoint
2. **Restart MCP server** - New detection logic will be used
3. **Test endpoint directly:**
```bash
curl "https://your-site.com/wp-json/seo-api-bridge/v1/status" -u "user:pass"
```
**Solution for v1.0.0 (legacy):**
1. Create at least one post or product with SEO metadata set
2. The old detection requires checking actual content meta fields
3. Upgrade to v1.1.0 to avoid this requirement
### SEO Plugin Not Detected ### SEO Plugin Not Detected
**Issue:** Admin notice says "Neither Rank Math SEO nor Yoast SEO is detected"
**Solution:**
1. Verify Rank Math or Yoast SEO is installed and activated 1. Verify Rank Math or Yoast SEO is installed and activated
2. Try deactivating and reactivating SEO API Bridge 2. Deactivate and reactivate SEO API Bridge
3. Check PHP error logs for any warnings 3. Check PHP error logs for warnings
### Meta Fields Not Appearing in REST API ### Meta Fields Not Appearing in REST API
**Issue:** `/wp-json/wp/v2/posts/{id}` doesn't show `meta` object
**Solution:**
1. Ensure you're authenticated (use Application Password) 1. Ensure you're authenticated (use Application Password)
2. Check that you have `edit_posts` permission 2. Check user has `edit_posts` permission
3. Verify the post type is supported (post, page, product) 3. Verify the post type is supported (post, page, product)
### Fields Are Read-Only
**Issue:** Can read SEO fields but cannot update them
**Solution:**
1. Verify authentication credentials
2. Check user has `edit_posts` capability
3. Ensure you're using POST/PUT request, not GET
## Compatibility ## Compatibility
- ✅ WordPress 5.0+ - WordPress 5.0+
- ✅ PHP 7.4+ - PHP 7.4+
- ✅ Rank Math SEO 1.0+ - Rank Math SEO 1.0+
- ✅ Yoast SEO 14.0+ - Yoast SEO 14.0+
- ✅ WooCommerce 5.0+ (for product support) - WooCommerce 5.0+ (for product support)
- ✅ Classic Editor & Gutenberg - Classic Editor & Gutenberg
- ✅ Multisite compatible - Multisite compatible
## Support
For issues related to:
- **This plugin:** [GitHub Issues](https://github.com/airano-ir/mcphub/issues)
- **MCP Server:** [MCP Server Documentation](https://github.com/airano-ir/mcphub)
- **Rank Math SEO:** [Rank Math Support](https://rankmath.com/support/)
- **Yoast SEO:** [Yoast Support](https://yoast.com/help/)
## Changelog ## Changelog
### 1.3.0 (2025-02-18)
- Added REST API endpoints for posts, pages, and products (GET/POST operations)
- Added authentication requirement for all endpoints
- Fixed `rank_math_title` meta key registration
- Fixed output escaping for WordPress.org compliance
### 1.2.0 (2025-02-15)
- Enhanced WooCommerce product support
- Improved MariaDB compatibility for meta field queries
### 1.1.0 (2025-01-10) ### 1.1.0 (2025-01-10)
- 🎉 **NEW:** Health check REST API endpoint `/seo-api-bridge/v1/status` - Added health check REST API endpoint `/seo-api-bridge/v1/status`
- 🎉 **NEW:** Direct plugin detection without requiring posts/products - Direct plugin detection without requiring posts/products
- 🎉 **IMPROVEMENT:** Better compatibility with sites that have no content - Better compatibility with sites that have no content
- 🎉 **IMPROVEMENT:** Returns SEO plugin versions in status endpoint - Returns SEO plugin versions in status endpoint
- 🎉 **FIX:** MCP server can now detect plugin even with zero posts
### 1.0.0 (2025-01-10) ### 1.0.0 (2025-01-10)
- Initial release - Initial release
@@ -417,12 +296,14 @@ For issues related to:
- Yoast SEO support (15 meta fields) - Yoast SEO support (15 meta fields)
- WooCommerce product support - WooCommerce product support
- Auto-detection of active SEO plugins - Auto-detection of active SEO plugins
- Admin notices for status
## Support
- **Plugin issues:** [GitHub Issues](https://github.com/airano-ir/mcphub/issues)
- **MCP Server:** [MCP Hub Documentation](https://github.com/airano-ir/mcphub)
- **Rank Math SEO:** [Rank Math Support](https://rankmath.com/support/)
- **Yoast SEO:** [Yoast Support](https://yoast.com/help/)
## License ## License
GPLv2 or later - See [LICENSE](https://www.gnu.org/licenses/gpl-2.0.html) for details GPLv2 or later - See [LICENSE](https://www.gnu.org/licenses/gpl-2.0.html) for details
## Credits
Developed for use with MCP Hub to enable AI-powered SEO content management.

View File

@@ -674,13 +674,19 @@ class SEO_API_Bridge {
* Display admin notices * Display admin notices
*/ */
public function admin_notices() { public function admin_notices() {
// Only show notices on the Plugins page to avoid clutter on every admin page
$screen = get_current_screen();
if ( ! $screen || $screen->id !== 'plugins' ) {
return;
}
$rank_math_active = $this->is_rank_math_active(); $rank_math_active = $this->is_rank_math_active();
$yoast_active = $this->is_yoast_active(); $yoast_active = $this->is_yoast_active();
$woocommerce_active = $this->is_woocommerce_active(); $woocommerce_active = $this->is_woocommerce_active();
if (!$rank_math_active && !$yoast_active) { if (!$rank_math_active && !$yoast_active) {
echo '<div class="notice notice-warning is-dismissible">'; echo '<div class="notice notice-warning is-dismissible">';
echo '<p><strong>SEO API Bridge:</strong> Neither Rank Math SEO nor Yoast SEO is detected. Please install and activate one of these plugins to enable SEO meta field access via REST API.</p>'; echo '<p><strong>SEO API Bridge:</strong> ' . esc_html__( 'Neither Rank Math SEO nor Yoast SEO is detected. Please install and activate one of these plugins to enable SEO meta field access via REST API.', 'seo-api-bridge' ) . '</p>';
echo '</div>'; echo '</div>';
} else { } else {
$active_plugins = []; $active_plugins = [];
@@ -691,10 +697,10 @@ class SEO_API_Bridge {
echo '<div class="notice notice-success is-dismissible">'; echo '<div class="notice notice-success is-dismissible">';
echo '<p><strong>SEO API Bridge v' . esc_html( self::VERSION ) . ':</strong> ' . esc_html( sprintf( 'Successfully registered meta fields for %s.', implode( ' and ', $active_plugins ) ) ) . '</p>'; echo '<p><strong>SEO API Bridge v' . esc_html( self::VERSION ) . ':</strong> ' . esc_html( sprintf( 'Successfully registered meta fields for %s.', implode( ' and ', $active_plugins ) ) ) . '</p>';
echo '<p><strong>Supported post types:</strong> ' . esc_html( $supported_types ) . '</p>'; echo '<p><strong>' . esc_html__( 'Supported post types:', 'seo-api-bridge' ) . '</strong> ' . esc_html( $supported_types ) . '</p>';
if ($woocommerce_active) { if ($woocommerce_active) {
echo '<p><strong>WooCommerce:</strong> Detected and supported. Product SEO fields are available via REST API.</p>'; echo '<p><strong>WooCommerce:</strong> ' . esc_html__( 'Detected and supported. Product SEO fields are available via REST API.', 'seo-api-bridge' ) . '</p>';
} }
echo '</div>'; echo '</div>';
} }