Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

WebMCP Abilities for WordPress

WordPressPHPChromeLicenseTestsWebMCP Spec

Turn any WordPress site into a structured tool server for AI agents — no custom API, no scraping, no prompt engineering required.

Already running in production on wppopupmaker.com. See the WordPress core WebMCP experiment for where this is heading.

Product Page · GitHub · WordPress.org(pending review)

WebMCP Abilities connects the WordPress Abilities API to the WebMCP browser standard, so AI agents running in Chrome 146+ can discover and call your site's capabilities as reliable, schema-driven tools.

Demo

WebMCP Abilities Demo

Gemini 2.5 Flash discovering and calling WordPress tools via Chrome's navigator.modelContext API on a live production site.


What Is WebMCP?

WebMCP is a browser API (navigator.modelContext) that lets websites register structured tools directly discoverable by AI agents. Instead of agents clicking through UIs, taking screenshots, and guessing at intent, they get:

  • Structured tool definitions with JSON Schema inputs
  • Direct execution via navigator.modelContext.registerTool()
  • Security enforced by the browser — same-origin, HTTPS-only
  • ~98% task accuracy vs ~45% for vision-based approaches

Currently in Early Preview — enable at chrome://flagsWebMCP for testing in Chrome 146+.

References:


What This Plugin Does

WordPress Site AI Agent (Claude, ChatGPT, etc.)
───────────────── ──────────────────────────────────
┌──────────────────────┐ ┌────────────────────────────────┐
│ WP Abilities API │ │ Chrome 146+ browser │
│ (register tools │──── bridge ───▶│ navigator.modelContext │
│ with schema + │ │ .registerTool(...) │
│ permissions) │ └────────────────────────────────┘
└──────────────────────┘ │
│ tool call
▼
┌────────────────────────────────┐
│ POST /wp-json/webmcp/v1/ │
│ execute/{ability} │
│ with nonce + auth │
└────────────────────────────────┘
  1. Plugins register WordPress Abilities — structured capabilities with labels, descriptions, JSON Schema inputs, permission callbacks, and execute callbacks.
  2. This plugin bridges them to WebMCP — the front-end script calls navigator.modelContext.registerTool() for each exposed ability.
  3. AI agents discover and call tools — structured JSON in, structured JSON out. No DOM parsing. No screenshots.

Built-in Tools

Four starter tools are included out of the box:

ToolDescriptionAuth
wp/search-postsFull-text search across published postsPublic
wp/get-postRetrieve a post by ID or slug with full contentPublic
wp/get-categoriesList all categories with counts and descriptionsPublic
wp/submit-commentSubmit a comment (respects WP comment settings)Configurable

Disable all built-ins with one filter:

add_filter( 'wmcp_include_builtin_tools', '__return_false' );

Installation

Requirements

  • WordPress 6.9+ (requires the Abilities API)
  • PHP 8.0+
  • HTTPS (WebMCP is a secure context API)
  • Chrome 146+ with WebMCP flag enabled (for AI agents)

From Source

git clone https://github.com/code-atlantic/webmcp-abilities.git
cd webmcp-abilities
composer install --no-dev

Upload to wp-content/plugins/webmcp-abilities/ and activate.


Registering Custom Tools

Any plugin can expose tools to AI agents by registering WordPress Abilities. First register your category, then your abilities:

// 1. Register your category.add_action( 'wp_abilities_api_categories_init', function () {
wp_register_ability_category( 'my-plugin', array(
'label' => __( 'My Plugin', 'my-plugin' ),
'description' => __( 'Tools provided by My Plugin.', 'my-plugin' ),
) );
} );
// 2. Register abilities that use the category.add_action( 'wp_abilities_api_init', function () {
wp_register_ability(
'my-plugin/get-products',
array(
'label' => __( 'Get Products', 'my-plugin' ),
'description' => __( 'Search the product catalog by keyword.', 'my-plugin' ),
'category' => 'my-plugin',
'input_schema' => array(
'type' => 'object',
'properties' => array(
'query' => array( 'type' => 'string', 'description' => 'Search term' ),
'limit' => array( 'type' => 'integer', 'default' => 10 ),
),
'required' => array( 'query' ),
),
'execute_callback' => 'my_plugin_get_products',
'permission_callback' => '__return_true',
'meta' => array( 'wmcp_visibility' => 'public' ),
)
);
} );

Important: WordPress requires the category to be registered via wp_register_ability_category() before any ability can use it. Abilities with unregistered categories are silently dropped by core. You can also use the 'webmcp' category registered by this plugin.

WebMCP Abilities automatically picks up any registered ability — but the site admin must enable third-party tools in Settings → WebMCP (they default to hidden on fresh installs).

Visibility Control

// Public: visible to all agents (logged-in or not)'meta' => array( 'wmcp_visibility' => 'public' )
// Hidden: never exposed to agents, even if registered'meta' => array( 'wmcp_visibility' => 'private' )

REST API Endpoints

The plugin registers three endpoints under /wp-json/webmcp/v1/:

MethodEndpointDescription
GET/toolsList all tools visible to the current user
POST/execute/{ability}Run a tool (nonce required for write tools)
GET/nonceRefresh the execution nonce

The /tools endpoint supports:

  • Conditional requests (If-None-Match / ETag) for efficient polling
  • Cache-Control: private, max-age=300 to reduce load
  • Public discovery mode (opt-in) for unauthenticated tool listing

Admin Settings

Settings → WebMCP provides:

  • Enable/disable the bridge globally
  • Public tool discovery — allow unauthenticated agents to list tools (execution still requires auth)
  • Per-tool toggle — hide specific tools from discovery without unregistering them
  • Status panel — HTTPS check, Abilities API availability, registered count

Hooks & Filters

// Allow/block a tool from appearing at alladd_filter( 'wmcp_expose_ability', function ( $expose, $name, $ability ) {
return$name !== 'wp/submit-comment'; // hide comment tool
}, 10, 3 );
// Customize the tool definition before it's sent to the browseradd_filter( 'wmcp_tool_definition', function ( $tool, $name, $ability ) {
$tool['description'] .= ' Powered by Acme Corp.';
return$tool;
}, 10, 3 );
// Block execution with context (user ID, input)add_filter( 'wmcp_allow_execution', function ( $allow, $name, $input, $user_id ) {
if ( $name === 'my-plugin/delete-data' && ! is_vip_user( $user_id ) ) {
returnnewWP_Error( 'forbidden', 'VIP only.' );
}
return$allow;
}, 10, 4 );
// Adjust rate limitsadd_filter( 'wmcp_rate_limit', fn() => 30 ); // requests per minute per user/tooladd_filter( 'wmcp_rate_limit_window', fn() => 60 ); // window in seconds// Disable built-in toolsadd_filter( 'wmcp_include_builtin_tools', '__return_false' );
// Conditionally load the bridge scriptadd_filter( 'wmcp_should_enqueue', fn() => is_front_page() );

Security

  • HTTPS enforced — bridge script does not load over HTTP
  • Nonce verification on write tool execute requests (X-WP-Nonce header) — read-only tools skip this
  • Permission callbacks re-evaluated at execution time (not just discovery)
  • Private visibility flag prevents internal abilities from appearing
  • Admin allowlist — site owner controls exactly which tools are exposed
  • Rate limiting per user+tool pair plus global IP-based discovery limit
  • Input size cap — 100 KB max payload (filterable)
  • Schema validation — depth limit and $ref rejection to prevent injection
  • IP-based rate limiting on tool discovery (REMOTE_ADDR only, no proxy header trust)

Testing

51 PHPUnit integration tests run against a real WordPress 6.9 environment via wp-env.

# Start the test environment
npx wp-env start
# Run the suite
npx wp-env run tests-cli \
"bash -c 'cd /var/www/html/wp-content/plugins/webmcp-abilities && WP_TESTS_DIR=/wordpress-phpunit ./vendor/bin/phpunit'"

Test coverage:

  • Ability_Bridge — visibility filtering, permission checks, schema validation, filters
  • Builtin_Tools — all four tools including edge cases and sanitization
  • REST_API — all endpoints: auth, nonce, rate limiting, execution lifecycle
  • Rate_Limiter — per-user and global ceiling enforcement

Architecture

webmcp-abilities/
├── webmcp-abilities.php # Bootstrap, version guard
├── includes/
│ ├── class-plugin.php # Singleton wiring
│ ├── class-settings.php # Options: enabled, discovery, exposed list
│ ├── class-ability-bridge.php # WP_Ability → WebMCP tool definition
│ ├── class-builtin-tools.php # 4 starter abilities
│ ├── class-rest-api.php # /tools, /execute, /nonce endpoints
│ ├── class-rate-limiter.php # Transient-based rate limiting
│ └── class-admin-page.php # Settings UI
├── src/
│ ├── webmcp-abilities.ts # TypeScript source (navigator.modelContext bridge)
│ └── types/webmcp.d.ts # WebMCP type declarations
├── dist/ # Built output (@wordpress/scripts + webpack)
│ ├── webmcp-abilities.js # Compiled bundle
│ └── webmcp-abilities.asset.php # WP dependency manifest with version hash
└── tests/phpunit/ # 51 integration tests

Roadmap

  • MCP Adapter integration (expose tools to CLI/API agents, not just browser)
  • WooCommerce tools (products, cart, checkout)
  • BuddyPress / bbPress community tools
  • Declarative WebMCP API support (HTML form population)
  • Tool annotations (readonly, destructive, idempotent)
  • WordPress.org plugin directory submission

Contributing

PRs welcome. Please include tests for any new tools or behavior changes.

composer install
npx wp-env start
# make changes
npx wp-env run tests-cli "..."# verify green

License

GPL-2.0-or-later — see LICENSE or gnu.org/licenses/gpl-2.0.

Built by Code Atlantic · Product Page.

About

Bridges WordPress Abilities to the WebMCP browser API (navigator.modelContext)

Resources

Stars

14 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages