All posts
Best practicesEngineeringEcosystem

WebMCP for WordPress: a practical step‑by‑step guide

How to add WebMCP to WordPress: where to put the code, sample tools for posts and WooCommerce, agent support today, and what breaks in production.

Agent LayerSeptember 30, 202611 min read

If you searched for “WebMCP for WordPress,” you want a straight answer: can you make a WordPress site executable by AI agents, and how? Yes—you can add WebMCP to any WordPress theme or plugin with a short script and well-described tools. By the end, you’ll have working code you can drop into functions.php or a small plugin, plus guidance on WooCommerce, guardrails, and what breaks in production.

WordPress specifics matter: enqueuing your script, placing data attributes on buttons, and avoiding fragile selectors. We’ll cover both a vanilla setup and how Agent Layer helps keep these tools working when your theme changes.

TL;DR

  • You can implement WebMCP on WordPress today by enqueuing a small script that registers tools via document.modelContext (feature-detect navigator.modelContext for older agents).
  • Start with read-only tools (search_posts, get_product_info). For write actions (add_to_cart, start_checkout), include an in-page confirmation step.
  • For WooCommerce, bind tools to stable selectors or custom data-* attributes you add to templates—don’t rely on brittle class names.
  • ChatGPT desktop and ChatGPT Work can call page tools today; Chrome and Edge are in origin trials. Check current status on the public WebMCP ecosystem tracker.
  • Agent Layer adds drift detection, guardrails, versioned configs and analytics—useful once you move beyond a single custom script.

What WebMCP is (and what it isn’t)

WebMCP lets a web page register tools that AI agents can discover and call locally in the user’s browser tab, using the user’s existing session. Each tool has a name, a description, a JSON Schema for inputs, and an execute function that runs in the page. Agents prefer these tools over scraping your DOM or clicking pixels.

This is not MCP (Anthropic’s backend protocol). For a clear breakdown, see what is the difference between MCP and WebMCP?. WebMCP is front-end, in-page; no new backend is required.

On WordPress, WebMCP is just JavaScript you enqueue. You can do it yourself, or use Agent Layer to manage versioned tool configs per template, guardrails on sensitive actions, and health checks when your theme changes.

Where to put the code in WordPress

You have three clean options. Pick one based on how you deploy theme changes.

Approach Where Pros Cons
Child theme functions.php + inline script Ships with theme; easy for theme devs Tied to theme deploys
Small plugin mu-plugins or regular plugin Independent of theme; portable Another artifact to version
Snippet manager Admin UI Fast to trial Risky in prod if not versioned

The key is to enqueue a script after the DOM is available on the pages where the tool makes sense (e.g., single posts, product detail pages).

Minimal WebMCP bootstrap for WordPress

This snippet enqueues an inline script that registers a simple read-only tool on all front-end pages. Put it in your theme’s functions.php or a small plugin file.

<?php
// functions.php or a small plugin
add_action('wp_enqueue_scripts', function () {
  // Depend on jQuery if your theme needs it; otherwise no deps
  wp_register_script('webmcp-tools', false, [], null, true);
  wp_enqueue_script('webmcp-tools');

  $inline = <<<JS
(function() {
  // Feature-detect both current and older address
  const mc = (document && document.modelContext) || (navigator && navigator.modelContext);
  if (!mc) return; // Agent or browser doesn’t support WebMCP here

  // Example: search posts by a query string from the page
  mc.registerTool({
    name: 'search_posts',
    description: 'Search visible blog posts by text. Use on archive or search pages. Returns titles and URLs only. No side effects.',
    inputSchema: {
      type: 'object',
      properties: { q: { type: 'string', description: 'Query text' } },
      required: ['q'], additionalProperties: false
    },
    execute: async ({ q }) => {
      // Read from the DOM to keep it backend-free
      const items = Array.from(document.querySelectorAll('article'));
      const results = items.map(a => {
        const titleEl = a.querySelector('h2 a, h1 a, .entry-title a');
        const title = titleEl ? titleEl.textContent.trim() : null;
        const url = titleEl ? titleEl.href : null;
        const snippetEl = a.querySelector('.entry-summary, .excerpt');
        const snippet = snippetEl ? snippetEl.textContent.trim() : '';
        return { title, url, snippet };
      }).filter(p => (p.title || '').toLowerCase().includes(q.toLowerCase()));

      return { count: results.length, results: results.slice(0, 10) };
    }
  });
})();
JS;

  wp_add_inline_script('webmcp-tools', $inline);
});

What this gives you: a discoverable, well-scoped tool that an agent can call without scraping arbitrary selectors. It describes where to use it, what it returns, and that it has no side effects.

Adding WooCommerce: “get_product_info” and “add_to_cart”

On product pages, register tools that read the displayed product state and, if needed, add the item to the cart. For write actions, add a confirmation prompt in-page so the user is in control.

Two key patterns for WordPress:

  • Add stable data-* attributes to your template output so your tool bindings don’t break when class names change.
  • Keep results small and JSON-serialisable—return what happened, not whole DOM nodes.

Template tweaks: add stable hooks

In your child theme, wrap important elements with data attributes. For example, in a WooCommerce single-product template override:

<?php // single-product/add-to-cart/simple.php override excerpt ?>
<button type="submit" class="single_add_to_cart_button button alt" data-wmcp="add-to-cart">Add to cart</button>

You can do the same for quantity inputs and variant selects:

<input type="number" name="quantity" value="1" min="1" data-wmcp="qty" />

Tools for product info and add to cart

Register the tools only on product pages. You can gate by checking for a known element before registering.

<?php
add_action('wp_enqueue_scripts', function () {
  wp_register_script('webmcp-woo', false, [], null, true);
  wp_enqueue_script('webmcp-woo');

  $inline = <<<JS
(function() {
  const mc = (document && document.modelContext) || (navigator && navigator.modelContext);
  if (!mc) return;
  if (!document.body.classList.contains('single-product')) return; // Woo product pages

  mc.registerTool({
    name: 'get_product_info',
    description: 'Read the current product name, price text, and availability from the page. No side effects. Use on product pages.',
    inputSchema: { type: 'object', properties: {}, additionalProperties: false },
    execute: async () => {
      const name = document.querySelector('.product_title')?.textContent?.trim() || null;
      const price = document.querySelector('.summary .price')?.textContent?.trim() || null;
      const availability = document.querySelector('.stock')?.textContent?.trim() || 'Unknown';
      return { name, price, availability };
    }
  });

  mc.registerTool({
    name: 'add_to_cart',
    description: 'Add the displayed product to the cart. Requires explicit user confirmation in the page. Use only on product pages.',
    inputSchema: {
      type: 'object',
      properties: { quantity: { type: 'integer', minimum: 1, default: 1 } },
      required: ['quantity'], additionalProperties: false
    },
    execute: async ({ quantity }) => {
      // User confirmation guardrail in the page
      const ok = window.confirm(`Add ${quantity} to cart?`);
      if (!ok) return { added: false, reason: 'user_cancelled' };

      const qty = document.querySelector('[data-wmcp="qty"], input.qty');
      if (qty) { qty.value = String(quantity); }

      const btn = document.querySelector('[data-wmcp="add-to-cart"], .single_add_to_cart_button');
      if (!btn) return { added: false, error: 'button_not_found' };

      btn.click();

      // Naive post-click check: did Woo render a notice?
      await new Promise(r => setTimeout(r, 600));
      const notice = document.querySelector('.woocommerce-message, .woocommerce-error');
      const message = notice ? notice.textContent.trim() : 'unknown';

      const cartCount = (function(){
        const el = document.querySelector('.cart-contents .count, .site-header-cart .count');
        return el ? el.textContent.replace(/\D/g, '') : null;
      })();

      return { added: true, message, cart_count: cartCount };
    }
  });
})();
JS;

  wp_add_inline_script('webmcp-woo', $inline);
});

This is intentionally simple: no secrets, no backend calls, no fragile dependencies. The description tells the agent when to use the tool and that it has a confirmation step.

If you plan to support checkout, keep that as a separate tool and require an explicit confirmation. For more ideas on e‑commerce flows, see preparing your e‑commerce store for AI‑driven checkout.

How agents discover and call your tools

Today, not every agent or browser will see your tools. ChatGPT desktop and ChatGPT Work have native support for page tools. Chrome and Edge are running origin trials, and several frameworks work when they launch a compatible browser. You can track real support on the public WebMCP ecosystem page.

The high-level flow looks like this:

Agent discovers and calls a WebMCP tool in the WordPress page

Agents choose tools based on their names and descriptions. Write concrete descriptions: when to use it, preconditions, and side effects. For more patterns and naming tips, see Essential WebMCP tools for AI‑ready websites.

A safer “start_checkout” tool with guardrails

Sensitive actions—payments, account changes, deletes—should require explicit user confirmation. Keep the result small and descriptive.

<?php
add_action('wp_enqueue_scripts', function () {
  wp_register_script('webmcp-checkout', false, [], null, true);
  wp_enqueue_script('webmcp-checkout');

  $inline = <<<JS
(function() {
  const mc = (document && document.modelContext) || (navigator && navigator.modelContext);
  if (!mc) return;

  // Only register on cart page
  if (!document.body.classList.contains('woocommerce-cart')) return;

  mc.registerTool({
    name: 'start_checkout',
    description: 'Go to checkout from the cart page. Requires in-page confirmation. Use only when user intends to pay.',
    inputSchema: { type: 'object', properties: {}, additionalProperties: false },
    execute: async () => {
      const ok = window.confirm('Proceed to checkout?');
      if (!ok) return { started: false, reason: 'user_cancelled' };

      const btn = document.querySelector('.checkout-button, [name="proceed"]');
      if (!btn) return { started: false, error: 'button_not_found' };

      btn.click();
      return { started: true, destination: 'checkout' };
    }
  });
})();
JS;

  wp_add_inline_script('webmcp-checkout', $inline);
});

If you use Agent Layer, you can set guardrails centrally and apply them to all sensitive tools without custom code in each template.

Testing on real pages

  • Use your own browser with ChatGPT desktop or ChatGPT Work to verify that tools are discovered and callable.
  • Try a framework that supports WebMCP in a launched browser (e.g., Vercel agent-browser or Stagehand). See the ecosystem tracker for current details.
  • Write realistic prompts: “Find a size M blue shirt under $50 and add one to the cart.” Check which tool the agent picks and the result object it returns.

With Agent Layer, you can go further: write test scenarios (“intent → expected tool”), see logs of which agent called which tool, and get health checks when a selector changes.

Deployment tips for WordPress

  • Load only where needed: conditionally enqueue on is_single(), is_product(), is_cart(), etc., to avoid noise.
  • Keep results tiny: return { added: true, message: “…” } instead of dumping HTML.
  • Stable bindings: prefer data-wmcp attributes that you control. Avoid CSS classes from a theme or page builder.
  • Localise descriptions: tools can be language-agnostic, but keep copy short and unambiguous.
  • Progressive enhancement: register read-only tools site-wide; add write tools only on pages where the action is valid.

What breaks in production

  • Theme drift: class names or markup change, and your querySelector no longer finds the button. Symptom: error: ‘button_not_found’. Fix: use data-* attributes you control, or use Agent Layer’s health checks that flag broken selectors and suggest replacements.
  • Plugins altering flows: checkout or add-to-cart buttons move or are replaced by AJAX. Fix: re-bind to a higher-level container, or add explicit data-wmcp markers in your template overrides.
  • CAPTCHAs and bot gates: agents won’t solve CAPTCHAs for you. For gated pages, tools won’t help until a human passes the check. The free audit flags CAPTCHAs in critical funnels.
  • Auth walls: tools rely on the user’s session. If the user isn’t logged in, a tool that expects account access will fail. Describe preconditions in the tool description.
  • Heavy outputs: returning big arrays or HTML strings can slow or fail agent processing. Keep it small and precise.
  • Over-broad tools: vague descriptions or overlapping tools cause agents to pick the wrong one. Be concrete about when to use each tool and its side effects.

Honest state of support

WebMCP is early. Verified today:

  • Agents: ChatGPT desktop app and ChatGPT Work call page tools. Others range from “behind a flag” to “no signal”.
  • Browsers: Chrome and Edge are in origin trials; Brave is behind a flag; Firefox and Safari don’t support it. Some automation frameworks work when they launch a compatible Chrome.

Before you commit a large rollout, check the current status on the ecosystem page. We update it by hand.

For a fuller background, see WebMCP explained: the native standard turning websites into AI APIs and why DOM scraping and vision models are dead for agentic web workflows.

Troubleshooting checklist

  • No tools discovered: confirm document.modelContext or navigator.modelContext is defined in the page (open DevTools Console). If not, your agent/browser likely doesn’t support WebMCP on that page.
  • Wrong page: register tools only where relevant (e.g., body.single-product) so the descriptions stay true.
  • Non-deterministic flows: avoid relying on AJAX finishing without a check. Add a small wait and read a stable indicator (e.g., WooCommerce notice) before returning.
  • Security concerns: add in-page confirmation dialogs for any action that changes state, especially payment or account tools.

When Agent Layer helps

You can hand-roll WebMCP on WordPress as shown. Once you have more than a couple of tools across templates, keeping them working is the real tax. Agent Layer reduces that:

  • Health checks catch drift when a selector breaks and suggest the new binding.
  • Guardrails on sensitive actions without coding confirm() everywhere.
  • Versioned configs per template; publish, roll back, and see exactly what changed.
  • Analytics: which agent called which tool, success/error, duration.
  • Test scenarios: write intents and see if the agent picks the right tool.

It’s also the fastest way to see where you stand: the free audit scans your site for missing WebMCP tools, invalid or missing JSON‑LD, unlabeled forms, CAPTCHAs, blocked crawlers, and more.

Putting it together: simple WordPress structure

This flow shows how your site, tools, and an agent interact.

Next steps and extensions

  • Add read-only tools site-wide (e.g., get_site_info, search_posts) and action tools on specific templates.
  • For e‑commerce, model cart and checkout as separate tools with clear preconditions and confirmation. See preparing your e‑commerce store for AI‑driven checkout.
  • Document your tools in a short internal README so your team knows what’s registered where.

Try it

Run the free agent‑readiness audit at agentlayer.tech. It flags missing WebMCP tools, JSON‑LD issues, unlabeled fields, CAPTCHAs, and more—and proposes page‑by‑page tools to add. If you’re evaluating support or planning a rollout, check the live WebMCP ecosystem tracker.

Get started

Don't Be Invisible to Tomorrow's Buyers.

Make your platform executable for every AI assistant your customers already use. No engineering, no lock-in, no breakage.