Problem/Motivation

The `mcp_tools_remote` submodule declares its HTTP endpoint route (`/_mcp_tools`) with `_access: 'TRUE'` in `mcp_tools_remote.routing.yml:7`. This bypasses Drupal's entire route access system, leaving authentication and authorization entirely to the controller's `handle()` method.
While the controller does perform API key validation and security checks (IP allowlist, origin validation, etc.), this pattern is fragile:
if a bug, early return, or exception occurs in the controller before the auth checks at lines 85-101, the endpoint is completely open with no safety net.
route-level access subscribers, event listeners, and debugging tools (e.g. `devel` route info) all report this route as "open to everyone", which is misleading.
Drupal's routing access system exists specifically to prevent this class of bugs. Custom access checkers are the documented pattern for non-standard authentication (see [Drupal Access Checking documentation](https://www.drupal.org/docs/drupal-apis/routing-system/access-checking-o...)).

Steps to reproduce

1. Install `mcp_tools` with the `mcp_tools_remote` submodule enabled.
2. Inspect `modules/mcp_tools_remote/mcp_tools_remote.routing.yml`.
3. Observe `_access: 'TRUE'` on the `mcp_tools_remote.handle` route.
4. Use `drush route:list --path=/_mcp_tools` or Devel route info — the route shows as requiring no access control.

Proposed resolution

Replace `_access: 'TRUE'` with a custom route access checker that gates requests at the routing layer before the controller is invoked.
The access checker (`McpRemoteAccessCheck`) performs two lightweight gate checks:
denies access if `mcp_tools_remote.settings:enabled` is `FALSE`.
denies access if no `Authorization: Bearer ...` or `X-MCP-Api-Key` header is present. This is a **presence check only** — the controller continues to perform full key validation, scope resolution, IP allowlist, origin check, and account switching as a second defense layer.

Remaining tasks

Changes

`src/Access/McpRemoteAccessCheck.php` — implements `Drupal\Core\Routing\Access\AccessInterface`.
`mcp_tools_remote.services.yml` — registers the access checker as a tagged service (`access_check`, `applies_to: _mcp_remote_access`).
`mcp_tools_remote.routing.yml` — replaces `_access: 'TRUE'` with `_mcp_remote_access: 'TRUE'`.
The controller's existing auth logic is **not removed** — it remains as the authoritative validation layer. The access checker is a lightweight first gate that ensures unauthenticated requests are rejected before the controller is even instantiated.

API changes

Data model changes

Issue fork mcp_tools-3587523

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

julien created an issue. See original summary.

ishani patel made their first commit to this issue’s fork.

jaydub’s picture

Status: Active » Needs review
mowens’s picture

fixed thank you for your work on this.

  • mowens committed 306dac13 on master
    Sync from dev 228b857: Preserve endpoint concealment in route access...