Drupal is a registered trademark of Dries Buytaert
Release: Leaflet 10.4.11 Minor update available for module leaflet (10.4.11). Release: Session Inspector 1.0.8 Minor update available for module session_inspector (1.0.8). Release: Migrate QA 2.0.4 Minor update available for module migrate_qa (2.0.4). Release: CKEditor Description List 3.0.0 Major update available for module ckeditor_descriptionlist (3.0.0). Release: FlowDrop 2.4.0 Minor update available for module flowdrop (2.4.0). Release: JWT Token Refresh 1.0.4 Minor update available for module jwt_token_refresh (1.0.4). Release: ConReg 1.0.0-beta1 First beta version released for module conreg (1.0.0-beta1). Release: AI Image Studio 1.0.0-beta8 New beta version released for module ai_image_studio (1.0.0-beta8). Usage Milestone: Role Theme Switcher Module role_theme_switcher crossed 1,000 active installs. Module Revived: Decoupled Router 2.0.7 Module decoupled_router updated after 11 months of inactivity (2.0.7).

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.

Built by a human using an AI assistant: 🤖 ➕ 🧠

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

  1. Install a module that provides Tool API tools.
  2. Go to Configuration » Web services » MCP Server » Tools and add a configuration.
  3. Type part of a tool name into Tool Plugin ID. Autocomplete matches on plugin ID, label, and description.
  4. Give it a machine name. That name becomes the MCP wire name, prefixed: a config with the ID summarize is advertised as tool_api__summarize.
  5. Save with Enabled checked. Discovery caches are invalidated on save, so the tool shows up on the next tools/list.
  6. A tools/call upcasts 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.

Tool API data type JSON Schema type 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 return success: false and never execute.
  • Reaching the MCP endpoint at all requires MCP Server's access mcp server permission.
  • 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, and status. 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.

Activity

Tracked releases
2
Tracked since
Jul 2026
Latest release
3 weeks ago
Releases (12 mo)
2 ▲ from 0
Maintenance
Active

Releases

Version Type Release date
1.0.0-beta1 Pre-release Jul 29, 2026
1.x-dev Dev Jul 2, 2026