This module provides a bridge to connect your Drupal site with a server tool. It enables communication and data exchange between Drupal and the specified server, allowing for integrated workflows.
A lot of the code in this module has been created using an AI assistant using Strikethroo & Kenkeep for improved Drupal code generation.
Overview
Exposes Tool API tools as MCP tools. Point a small config entity at a tool plugin ID, enable it, and that tool appears on tools/list for every connected MCP client.
You write the tool once, against Drupal's Tool API. Drupal's own AI agents can call it. So can Claude, Cursor, or anything else that speaks MCP. This module is the adapter in between.
Requires MCP Server 2.x and Tool 1.x. Tools themselves come from other modules; this one exposes them.
What it does
One entity per tool
The add form has four fields: a machine name, the tool plugin ID (autocompleted from what's installed), an optional description override, and an enabled checkbox.
Schemas are derived
Tool API input definitions are typed, so the bridge converts them into the JSON Schema MCP clients read. Length, range, regex, and allowed-value constraints carry across too.
The tool decides access
Every call runs the tool's own access() check before execution, against the account behind the MCP request. The bridge never elevates privileges.
One mapping, all the way to the client
Tool Configurations is the whole configuration surface: pick a Tool API tool, give the mapping a machine name, optionally override the description. The machine name doubles as the wire-name suffix, so entity_list becomes tool_api.entity_list for MCP clients and tool_api__entity_list for the Drupal plugin system.
Once saved, the mapping is just another MCP tool. A deriver emits one plugin per enabled mapping, so bridged tools sit next to the ones shipped by MCP Server and Examples with no extra plugin code from you.
The inputSchema a client sees in tools/list is derived from the Tool API tool's own parameter definitions. You do not hand-write JSON Schema, and the schema stays in step with the tool when it changes.
Calling the tool executes the Drupal tool and hands back structured content, so the client gets typed results rather than a wall of prose it has to parse.
How it works
- Install a module that provides Tool API tools.
- Go to Configuration » Web services » MCP Server » Tools and add a configuration.
- Type part of a tool name into Tool Plugin ID. Autocomplete matches on plugin ID, label, and description.
- Give it a machine name. That name becomes the MCP wire name, prefixed: a config with the ID
summarizeis advertised astool_api__summarize. - Save with Enabled checked. Discovery caches are invalidated on save, so the tool shows up on the next
tools/list. - A
tools/callupcasts the arguments, runs the access check, executes the tool, and returns its result.
What you configure:
id: echo tool_id: 'mcp_server_test:example' description: null status: true
What the client sees on tools/list:
{ "name": "tool_api__echo", "description": "A simple test tool that echoes a message with a prefix", "inputSchema": { "type": "object", "properties": { "message": {"type": "string"}, "prefix": {"type": "string"}, "count": {"type": "integer"} }, "required": ["message"] } }
A call returns the tool's ExecutableResult flattened into three keys:
{ "success": true, "message": "Successfully processed message 2 time(s)", "data": {"result": "Echo: hello | Echo: hello"} }
Output values are used when the tool defines them; otherwise the result's context values are returned. On failure, success is false and message explains why. Exceptions are caught, logged to the mcp_server_tool_bridge channel, and reported back to the client instead of breaking the session.
Schema conversion
Each Tool API input definition becomes one JSON Schema property. Required inputs land in the schema's required array.
string, email, uri, datetime_iso8601
string
integer, timestamp
integer
float
number
boolean
boolean
list
array
map
object
anything else
string
Validation constraints on the input definition are translated as well: Length to minLength and maxLength, Range to minimum and maximum, Regex to pattern, and AllowedValues to enum. An enum is worth adding wherever the value set is finite, since it stops the model from guessing.
Tools flagged destructive in their Tool API definition are advertised with the MCP destructive hint, so clients that ask for confirmation before destructive calls will do so.
Passing entities between calls
MCP arguments are JSON, and a Drupal entity is not. Inputs typed as entity or entity:* are advertised as strings that accept an artifact token, and the schema description tells the model as much.
When a tool returns an entity, the bridge stores it in a private tempstore and hands the client a token such as {{entity:a1b2c3}} together with the entity type, bundle, ID, langcode, and revision ID. Pass that token back as an argument on a later call and the bridge swaps it for the stored entity before execution. A model can chain a load, a transform, and a save without ever seeing an entity's internals.
Access and safety
- The MCP request's account is what the tool's
access()method is evaluated against. Denied calls returnsuccess: falseand never execute. - Reaching the MCP endpoint at all requires MCP Server's
access mcp serverpermission. - Managing the mappings requires
administer mcp tool configurations, a restricted permission. - A tool is reachable only while its configuration is enabled. Unchecking the box removes it from discovery.
- Configurations whose tool plugin is missing are skipped rather than advertised, so uninstalling a tool provider degrades quietly.
Write good descriptions
The description is the only thing a model reads when deciding whether to call a tool. Tool API descriptions are written for developers and often too terse for that job. The Description field on the configuration overrides it, so you can say when the tool applies and what it expects without touching the tool's code.
Machine names must match ^[a-zA-Z0-9_-]{1,64}$. This is stricter than Drupal's usual machine name rules because the name travels on the wire as an MCP tool name.
Architecture
- McpToolConfig: a config entity holding
id,tool_id,description, andstatus. Its machine name doubles as the wire-name suffix, so there is no separate name field to keep in sync. - McpToolConfigDeriver: emits one MCP tool derivative per enabled configuration and builds the input schema from the backing tool's definition.
- ToolApi: the MCP tool plugin. It upcasts arguments, resolves artifact tokens, checks access, executes, and downcasts entities on the way out.
- ToolAutocompleteController: powers the tool ID autocomplete on the configuration form.
The bridge consumes only MCP Server's published plugin interface, attribute, manager, and base class. It has no dependency on Simple OAuth; authentication is handled by MCP Server and its OAuth submodule.
Related projects
- MCP Server: the MCP runtime this module plugs into.
- Tool: the Tool API that defines the tool plugins being exposed.
- MCP Server Views: the same idea for read-only data, using Views displays as MCP resources.
- MCP Server UI: admin forms for MCP Server's other plugin types.
Resources
Credits
Maintained by the MCP Server contributors.