Documentation / WordPress

Add your own WebMCP tool.

Register a PHP function with Cartonoma. After an administrator publishes it, visitors and compatible AI assistants can call it.

Go to the working example →

Before you start

Activate Cartonoma 0.8.2 or later on your WordPress site. Enable public discovery and WebMCP in Cartonoma settings. This example needs neither WooCommerce nor a Cartonoma account or paid plan.

The code runs in your WordPress plugin. Cartonoma registers the definition, validates the input and returns the result. Supporting browsers also expose the tools through WebMCP. REST testing does not require browser WebMCP support.

This first custom-tool API is for public, read-only tools, such as lookups and calculations. readOnly: true is a declaration; it does not sandbox your PHP code. Do not add data-changing operations to this example.

Working PHP example

The example divides the number of items by the number that fit on one sheet, then rounds up. Ten items at three per sheet need four sheets. It is an item-count calculation; it does not calculate dimensions, layout, waste or pricing.

Create the following file and paste in the complete code:

wp-content/plugins/cartonoma-example-tools/cartonoma-example-tools.php

PHP · cartonoma-example-tools.php
<?php
/**
 * Plugin Name: Cartonoma Example Tools
 * Description: Developer example: calculate sheet count without creating a quote.
 * Version: 1.0.0
 * Requires PHP: 7.4
 * License: GPL-2.0-or-later
 */
defined('ABSPATH') || exit;

add_action('cartonoma_register_tools', static function (\Cartonoma\Tools\ToolRegistry $registry): void {
    $registry->register('example_sheet_count', [
        'version' => '1', 'owner' => plugin_basename(__FILE__),
        'title' => 'Calculate sheet count', 'description' => 'Calculate sheets needed from item quantity and items per sheet. This example does not create a quote.',
        'access' => 'public', 'readOnly' => true,
        'inputSchema' => ['type' => 'object', 'additionalProperties' => false, 'required' => ['quantity', 'per_sheet'], 'properties' => [
            'quantity' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 100000],
            'per_sheet' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 1000],
        ]],
        'outputSchema' => ['type' => 'object', 'additionalProperties' => false, 'required' => ['sheets'], 'properties' => [
            'sheets' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 100000],
        ]],
        'permission_callback' => static function (): bool { return true; },
        'execute_callback' => static function (array $input): array { return ['sheets' => (int) ceil($input['quantity'] / $input['per_sheet'])]; },
    ]);
});

Activate “Cartonoma Example Tools” under WordPress → Plugins. The tool appears as “Calculate sheet count” in the administration screen.

Publish and try it

  1. Open Cartonoma → Developer tools.
  2. Review the input and output schemas in the “Calculate sheet count” card.
  3. Select “Publish tool”. This makes the tool available to visitors and AI assistants.
  4. Enter the following object in the JSON input and select “Run tool”.
JSON input in the admin screen
{ "quantity": 10, "per_sheet": 3 }
Expected result
{ "sheets": 4 }

Use “Unpublish tool” to stop offering the example. Deactivating its plugin also removes availability. Changing the tool version, schema or owner requires publication again. Translating titles or descriptions alone does not revoke approval; increment the tool version when behavior or the meaning of its description changes.

JavaScript and REST

Send requests to the WordPress site where Cartonoma is installed. This page on cartonoma.com is documentation; it does not host the example endpoint.

List available tools
GET /wp-json/cartonoma/v1/tools/manifest

“Open tool manifest” in the admin screen provides the correct URL for your site. With plain permalinks, it may use /?rest_route=/cartonoma/v1/tools/manifest. Use the listed executeUrl for calls.

POST /wp-json/cartonoma/v1/tools/execute
{
  "tool": "example_sheet_count",
  "input": { "quantity": 10, "per_sheet": 3 }
}
JavaScript · fetch
// Run on the WordPress site hosting the tool.
// Use the manifest URL shown in Cartonoma → Developer tools.
const manifestUrl = '/wp-json/cartonoma/v1/tools/manifest';
const manifestResponse = await fetch(manifestUrl, {
  credentials: 'omit', cache: 'no-store'
});
if (!manifestResponse.ok) throw new Error('Manifest unavailable');
const manifest = await manifestResponse.json();
const tool = manifest.tools.find(t => t.name === 'example_sheet_count');
if (!tool) throw new Error('Activate and publish the example tool first');
if (new URL(tool.executeUrl, location.href).origin !== location.origin) {
  throw new Error('Use a same-origin execution URL');
}
const response = await fetch(tool.executeUrl, {
  method: 'POST', credentials: 'omit', cache: 'no-store',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    tool: tool.name,
    fingerprint: tool.fingerprint,
    input: { quantity: 10, per_sheet: 3 }
  })
});
const result = await response.json();
if (!response.ok) throw new Error(result.message || 'Tool call failed');
console.log(result); // { sheets: 4 }
cURL
curl 'https://YOUR-WORDPRESS-SITE.example/wp-json/cartonoma/v1/tools/execute' \
  -H 'Content-Type: application/json' \
  --data '{"tool":"example_sheet_count","input":{"quantity":10,"per_sheet":3}}'

The manifest lists available registry tools: site profile, content search and published custom tools. It is not a complete list of the older WooCommerce browser tools. fingerprint is optional; sending it as shown prevents calling a changed definition with stale information.

Tool definition

The cartonoma_register_tools action supplies a ToolRegistry instance. register(name, definition) returns true on success or WP_Error for an invalid definition. Check that return value in your production plugin.

FieldUsage
nameUse a vendor or plugin prefix, such as example_sheet_count. The cartonoma_ prefix is reserved.
versionA string you increment when tool behavior changes. Separate from the plugin version.
ownerThe owning plugin’s relative PHP filename. Use plugin_basename(__FILE__) in its main plugin file.
title / descriptionA title and a description of what the tool does and which inputs it expects.
access / readOnlyThis registration API requires access: public and readOnly: true.
inputSchema / outputSchemaObject schemas defining the input and returned data using the supported JSON Schema fields.
permission_callbackMust return exactly true for the call to be available. Do not reuse the example’s public permission for a tool that reads personal data.
execute_callbackReceives validated input as a PHP array. Return an array matching outputSchema; do not echo output.

Supported schema subset

Types: object, array, string, integer and boolean. Fields: type, properties, required, additionalProperties, items, enum, minimum, maximum, maxLength, maxItems, description and default. Input and output roots must be objects; use additionalProperties: false on objects. Other fields such as $ref, oneOf and format are unsupported.

Input is limited to 16 KiB and output to 256 KiB. A site can register up to 64 custom tools. The new execution endpoint permits 60 requests per tool per minute across the site. Bound long-running callbacks yourself; cancelling a browser request does not forcibly terminate running PHP.

Troubleshooting

404 · cartonoma_tool_unavailable
Check that the plugin is active, the tool is published and WebMCP is enabled. permission_callback must return exactly true.
400 · cartonoma_tool_input_invalid
Check the JSON object and required schema fields. Enter only the input object in the admin screen; send the body containing tool and input to REST.
409 · cartonoma_tool_changed
Fetch the manifest again. Republish the tool in the admin screen if needed.
429 · cartonoma_tool_busy / cartonoma_tool_rate_limited
Wait for the response’s Retry-After interval before retrying.
500 · cartonoma_tool_failed / cartonoma_tool_output_invalid
Inspect the callback error on the server. Return an array matching outputSchema; do not send private error details to visitors.