Problem/Motivation
This one might be very controversial at first glance, but I think in the new world of MCP this might be a good way of getting Drupal usage up, without necessarily needing to know PHP or Drupal. This issue is very much just for discussion at this time, since MCP is nowhere near production ready.
With MCP (see
https://www.drupal.org/project/mcp →
) interoperabiility might actually be a solved concept, because it opens up for business processes (like ECA) and agents (like AI Agents) to talk directly to tools on other systems. So if a company for instance has a Python application that has self documentation, but are using Drupal for documentation, before MCP you could either manually publish updates or create some API on the Python side and some pull mechanism on the Drupal side. While some of this can be done with Feeds/Site Buidling, there might be some generic detail where you need to code and know Drupal.
With MCP you could just generate a tool for it.
MCP in Python for instance does this if you want a multiplcation tool:
@mcp.tool()
def add(a: int, b: int, sidenote: str) -> int:
"""
Adds two numbers.
"""
return a + b
MCP tools in nodejs does this
server.tool("add", "Add two numbers", { a: z.number(), b: z.number() }, async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }],
}))
Both are not super simple, but can be setup by someone with rudimental knowledge.
However Drupal tools uses the plugin system at the current time and its quite complex to know where to put files. Say that you want to create a multpilcation tool, you would need to create the file src/Plugin/AiFunctionCall/Multiplicator.php with code like this (and note that this does not do Dependency Injection that makes it way harder):
namespace Drupal\my_module\Plugin\AiFunctionCall;
use Drupal\ai\Attribute\FunctionCall;
use Drupal\Core\Plugin\Context\ContextDefinition;
#[FunctionCall(
id: 'my_module:multiplicator',
function_name: 'my_module_multiplicator',
name: 'Multiplicator',
description: 'This function adds two numbers together',
group: 'some_group',
module_dependencies: [],
context_definitions: [
'number_a' => new ContextDefinition(
data_type: 'integer',
label: new TranslatableMarkup("Number A"),
description: new TranslatableMarkup("The first number."),
required: TRUE,
),
'number_b' => new ContextDefinition(
data_type: 'integer',
label: new TranslatableMarkup("Number B"),
description: new TranslatableMarkup("The second number."),
required: TRUE,
),
),
)]
class Multiplicate extends FunctionCallBase implements ExecutableFunctionCallInterface {
/**
* The result.
*
* @var string
*/
protected string $result;
/**
* {@inheritdoc}
*/
public function execute() {
$number_a = $this->getContextValue('number_a');
$number_b = $this->getContextValue('number_b');
$this->result = $number_a + $number_b;
}
/**
* {@inheritdoc}
*/
public function getReadableOutput(): string {
return (string) $this->result;
}
}
What if we instead could create the file tools/multiplicator.tool.php
with the following code
/**
* This tools multiplies two numbers.
*
* @param int $number_a
* The first number to multiply.
* @param int $number_b
* The second number to multiply.
*
* @return string
* The returned value.
*/
function my_module_multiplicator(int $number_a, int $number_b): string {
return $number_a + $number_b
}
The phpdoc might not be obvious to people at the beginning, but it should be easy enough to log when its not following correct standards, so people know why there tool does not show up.
We could make sure that these files are not in the autoloader and only included when used. Discovery would happen on cache similar to plugin system and they would have their own linter system. Multiple tools could be added in one file. They should be able to use Drupal static class abstraction, so do \Drupal::entityTypeManager->... etc.
It would use a Plugin Decorator to actually create the correct plugin code.
This would open up a new world for people that wants to add some smaller logic to Agents or ECA without having to know the whole of Drupal.
Thoughts?