This documentation is intended for developers who want to use the AI Engine MCP framework to expose their plugin tools through MCP via AI Engine. If you are looking to use MCP as a regular user, please read this documentation instead.
AI Engine has two filters that allow you to first register (declare) the tools that will be available through your MCP and a second filter that will handle the execution.
The recommended usage is that your plugin already has an API class with simple routes to your core function execution so that the MCP just becomes a layer that redirects to your actual API routes (MCP → API → Executions). Of course, nothing is stopping you from making all of your logic in your MCP handling (MCP → Executions), which could be done if you are just looking to experiment or create quick custom MCP tools.
To get started, let’s create a new mcp.php file in our plugin which will have its own class, something like:
class MyPlugin_MCP {
private $core;
private $api;
public function __construct( $core, $api ) {
$this->core = $core;
$this->api = $api;
// Initialize everything on 'init'
add_action( 'init', array( $this, 'init' ), 20 );
}
}
Now we will add our init function that will be responsible for calling the AI Engine filters that will register the tools and handle their execution whenever they are called. You can use the $mwai global to ensure that AI Engine is installed or at least enabled.
public function init() {
global $mwai;
// Only register MCP if AI Engine is available
if ( isset( $mwai ) ) {
// Step 1: Register your tools
add_filter( 'mwai_mcp_tools', array( $this, 'register_tools' ) );
// Step 2: Handle tool execution
add_filter( 'mwai_mcp_callback', array( $this, 'handle_tool_execution' ), 10, 4 );
}
}
So now the goal is to have two big functions in our class: “register_tools” and “handle_tool_execution.”
To register the tools, you will receive a parameter from the filter called $tools, which contains all the already declared tools as an array of arrays with string keys. You can add or remove tools from this array, and then return its new value to the filter. As we want to register new tools, we will add some and return the updated value.
Supported types are: string, integer, boolean, array, object.
Never do ‘properties’ => [] as it can cause MCP parsers to fail.
public function register_tools( $tools ) {
// Example: Get User Info Tool
$tools[] = [
'name' => 'myplugin_get_user_info',
'description' => 'Get information about a WordPress user by their ID',
'category' => 'My Plugin',
'inputSchema' => [
'type' => 'object',
'properties' => [
'user_id' => [
'type' => 'integer',
'description' => 'The WordPress user ID'
]
],
'required' => ['user_id']
]
];
// Example: Update User Bio Tool
$tools[] = [
'name' => 'myplugin_update_user_bio',
'description' => 'Update the biography of a WordPress user',
'category' => 'My Plugin',
'inputSchema' => [
'type' => 'object',
'properties' => [
'user_id' => [
'type' => 'integer',
'description' => 'The WordPress user ID'
],
'bio' => [
'type' => 'string',
'description' => 'The new biography text'
]
],
'required' => ['user_id', 'bio']
]
];
// Example: Tool with no required parameters
$tools[] = [
'name' => 'myplugin_get_statistics',
'description' => 'Get overall plugin statistics',
'category' => 'My Plugin',
'inputSchema' => [
'type' => 'object'
// No properties needed - this tool takes no parameters
]
];
return $tools;
}
Now, whenever an MCP tool is called, AI Engine will run that second filter with the following four parameters: $result, $tool, $args, $id. You will need to check the “$tool” first to see if we are calling your plugin, as this filter might be called for a tool that is not yours.
Then we can get the different arguments from $args, and we simply call our logic (in this example, which is already done in our API) and return a value to the chatbot.
public function handle_tool_execution( $result, $tool, $args, $id ) {
// Only handle tools that belong to your plugin
if ( strpos( $tool, 'myplugin_' ) !== 0 ) {
return $result;
}
try {
switch ( $tool ) {
case 'myplugin_get_user_info':
// Route to your API
return $this->api->get_user_info( $args['user_id'] );
case 'myplugin_update_user_bio':
// Route to your API
return $this->api->update_user_bio( $args['user_id'], $args['bio'] );
case 'myplugin_get_statistics':
// Route to your API (no args needed)
return $this->api->get_statistics();
default:
return [ 'success' => false, 'error' => 'Unknown tool' ];
}
}
catch ( Exception $e ) {
return [ 'success' => false, 'error' => $e->getMessage() ];
}
return $result;
}
}
The response format from your logic should be an array containing the data and the status of the execution, like so:
// Success
return [
'success' => true,
'data' => [ /* your data here */ ]
];
// Error
return [
'success' => false,
'error' => 'Error message'
];