Skip to main content
Drupal is a registered trademark of Dries Buytaert
Release: OpenID Connect / OAuth client 3.0.0-alpha9 New alpha version released for module openid_connect (3.0.0-alpha9). Usage Milestone: Google Analytics Module google_analytics crossed 1,000 active installs. Release: Timelinr 1.0.1 Minor update available for module timelinr (1.0.1). Release: GraphQL Compose Codegen 1.1.2 Minor update available for module graphql_compose_codegen (1.1.2). Release: Mapy.com 1.1.3 Minor update available for module mapycom (1.1.3). Release: Ckeditor5 entity browser 3.0.3 Minor update available for module ckeditor5_entity_browser (3.0.3). Release: Ckeditor5 entity browser 3.0.1 Minor update available for module ckeditor5_entity_browser (3.0.1). Release: Ckeditor5 entity browser 3.0.2 Minor update available for module ckeditor5_entity_browser (3.0.2). Release: Teamleader Integration 4.0.2 Minor update available for module teamleader (4.0.2). Module Revived: Entityqueue Buttons 1.1.2 Module entityqueue_buttons updated after 8 months of inactivity (1.1.2).

MCP Sentinel

5 sites No security coverage Drupal 10–11 MCP ecosystem
View on drupal.org

MCP Sentinel provides a security and governance layer for Drupal sites that allow AI agents to interact with content. It controls what AI agents can access, hides sensitive fields, logs all actions in a tamper-evident log, limits data retrieval, and protects content being edited by humans. It also includes a dashboard for monitoring these activities.

MCP Sentinel is the governance layer for Drupal sites that expose content to AI agents over the Model Context Protocol (MCP), JSON:API, and GraphQL. It decides what an agent may touch, hides what it must not see, records everything it does, and protects content people are editing — so you don't have to build that control yourself.

It sits on top of MCP Server and the Tool API and adds only the governance those projects leave to the site builder. It does not reimplement the protocol, OAuth, or the tool system.

How governance triggers. It applies to traffic on the validated OAuth agent channel — a designated consumer, or an agent scope on the request's token, checked server-side and never from a header. Your public frontend and your own cookie-session admin work are untouched. Each agent's role selects a policy profile, and every action is attributed to its account.

What it does not cover. A policy profile governs requests that reach Drupal through the MCP server's entity-API path. It cannot govern channels that bypass that API — raw SQL, most Drush commands, direct file access, or programmatic entity loads in custom code. drush sql:query is the clearest case: it declares a bootstrap ceiling below the level at which module command files are discovered, so no hook or policy check in any Drupal module can fire for it. That is a property of Drush, not a gap this module can close. The boundary for those paths is who can reach the host: shell and database credentials sit outside this module's threat model and must be controlled separately. Stating this makes the guarantee stronger, because it becomes checkable.

What it does

  • Policy profiles per role — gates, redaction, limits, quotas, and IP rules live on a reusable config entity; the agent's role selects which profile applies.
  • Operation gates — a master switch plus independent read, write, delete, and GraphQL-mutation toggles.
  • Open-redirect guard — stop an agent from pointing a redirect off-domain (secure by default, with a per-profile host allowlist).
  • Entity allow / deny lists — restrict agents to specific entity types, or block sensitive ones (users are blocked by default). Enforced through Drupal's own access system, so JSON:API and GraphQL honour it automatically.
  • Field redaction — hide fields like mail or pass from agent requests: stripped from JSON:API/REST, returned as [REDACTED] in GraphQL, and cached separately so nothing leaks across the boundary.
  • PII redaction (opt-in) — scan field values for emails, phone numbers, SSNs, and card numbers and mask the matches. A pattern may declare a classification label (2.11.0): a hit can only lower the egress ceiling, never raise or invent one.
  • Audit log — every operation and GraphQL query recorded with user, IP, time, and payload metadata; filterable, exportable to CSV or JSON, with automatic retention pruning.
  • Escape-hatch permission assertions — a profile declares permissions its governed roles must not hold (bypass node access, administer users and similar), so a role cannot quietly step around the policy it appears to be under. Violations surface on the status report and through drush mcp-sentinel:role-audit; deliberate grants are recorded in config as role_id:permission, optionally scoped with role_id:permission@environment (environment from $settings['mcp_sentinel.environment'] in settings.php — never from exported config; fails closed when unset).
  • Governed raw SQL (opt-in, off by default) — where an agent genuinely needs to read with SQL, drush mcp-sentinel:sql-query runs it inside Drupal behind a fail-closed check, so deny lists, redaction and the audit chain still apply. Gated on a per-profile allow_raw_sql flag that ships FALSE.
  • Tamper-evident trail — every entry is hash-chained (HMAC-SHA256 when keyed via a Key entity) by Audit Chain, so an inserted, deleted or edited row is detectable rather than merely discouraged. drush audit-chain:verify checks it. Optional at-rest encryption and SIEM streaming.
  • Change diffs — updates record which fields changed; redacted fields never enter the trail.
  • Rate limits and quotas — throttle agent traffic per profile, keyed on the resolved user ID so one token can't saturate the server.
  • Exfiltration guards — finite-by-default read budgets (2.7.0) cap result counts, response bytes, requests, and collection pages per window across Tool, JSON:API, and GraphQL responses, so neither a single call nor a pagination loop can bulk-export your content.
  • Evidence-required actions — mark action classes (2.8.0) whose governed mutations execute only when their evidence can commit to the keyed audit chain: the precommit lands in the same transaction as the mutation so both are durable together or neither is, uncertain receipts are refused and reconciled instead of reported as success, and unkeyed logging never satisfies the class.
  • Classification labels and egress ceilings — label data by configuration (2.9.0): an ordered site vocabulary assigned by entity type, bundle or field, plus a ceiling per policy profile for each governed surface — Tool, context, JSON:API, GraphQL and the governed drush SQL command. Data above a surface’s ceiling is refused or redacted before it leaves, with the stable code classification_egress_denied and bounded evidence that names labels, never values. A northbound declaration can only narrow a ceiling, never widen it. Ships inert: label nothing, set no ceilings, and no read decision changes.
  • Secure-install verifierdrush mcp-sentinel:verify produces an evidence document that this install carries the secure, tenant-neutral floor (2.10.0). Posture checks always run. --live adds hostile-input probes without writing content. A skipped check fails the run; residuals (prompt injection, operator trust) are recorded as managed.
  • Portable policy bundles — a versioned, HMAC-sealed artifact (2.11.0) that can be verified, activated (with last-known-good rollback), simulated, revoked, or used to arm emergency deny. Denials apply on the live access path since 2.12.0 — the entity, create, config and JSON:API-filter checks, the context schema document, GraphQL query and mutation gates, and the governed drush SQL command — refusing with the stable code policy_bundle_denied. A bundle can only tighten: local deny cannot be widened by an upstream allow, an attested digest whose document will not verify (expired, revoked, tampered, or missing key) fails closed, and cached allows do not outlive the attested document's remaining TTL. Every audit row cites the attested digest when a bundle is active.
  • IP allowlisting — restrict agent connections to specific addresses or CIDR blocks (trusted-proxy aware).
  • Anomaly detection — cron rules over the audit log raise alerts by log, email, or webhook, with per-rule debounce. Rules can fire on a count threshold, off-hours governed activity, or a complete/near-complete bulk read (2.11.0). No rules are enabled by default.
  • Content locks — stop agents from overwriting content a person is editing, with TTL expiry.
  • Webhooks — queue-backed, HTTPS-only, HMAC-signed delivery with retries, an SSRF guard, and one-click replay.
  • Context endpoint/drupal-mcp/context exposes your content model so agents can discover it before acting; /drupal-mcp/health remains the public uptime probe; authenticated GET /drupal-mcp/readiness reports whether the fail-closed governed source contract is ready (contract_ready plus a stable non-secret reason) without claiming policy effectiveness or overall posture, and anonymous callers are refused (403).
  • Governed Tool plugins — ready-made tools for content, media, workflow transitions, bulk actions, and schema discovery, each run through the same checks.
  • Dashboard — a read-only console at /admin/reports/mcp-sentinel with posture, alerts, top agents, and denied-by-policy panels. The hero never reports all-clear until audit-chain evidence is verified (2.11.0).

Submodules

  • Server (mcp_sentinel_server) — registers the Tool plugins with MCP Server and wires per-tool OAuth scopes.
  • GraphQL (mcp_sentinel_graphql) — extends gating, auditing, and redaction to the GraphQL Compose endpoint.
  • Approval (mcp_sentinel_approval) — queues destructive operations for human approval bound to one HMAC-sealed action manifest (2.11.0). The requester cannot approve their own request; the form shows the sealed action against the live target. Includes time-boxed break-glass elevation into a shipped non-admin mcp_admin role (single-use sealed grant; uid 1 and standing is_admin refused; elevation cannot promote policy or lift the no-agent-publish floor).

Requirements

Audit, redaction, content locks, and webhooks all work without MCP Server installed.

Quick start

composer require drupal/mcp_sentinel drupal/mcp_server drupal/simple_oauth
drush en mcp_sentinel mcp_sentinel_server mcp_server_tool_bridge -y
drush mcp-sentinel:setup

Configure at Configuration → Web services → MCP Sentinel, and review activity at Reports → MCP Sentinel.

Companion connector

drupal-mcp-connector is a Node.js MCP connector (multi-site, JSON:API + GraphQL, Drush bridge) that pairs with MCP Sentinel and appears by its X-MCP-Client label in the audit log.

Security

Not covered by Drupal's security advisory policy. Report vulnerabilities privately as described in SECURITY.md on the project repository; do not open a public issue for an exploitable flaw. General bugs go through the project issue queue.

Maintainers

Maintained by Jeremy Michael Cerda, sponsored by Wilkes & Liberty, LLC.

Depends on

Dependencies of the latest stable release

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
44
Tracked since
Jun 2026
Latest release
4 days ago
Releases (12 mo)
44 ▲ from 0
Maintenance
Active

Release Timeline

Releases

Version Type Core Release date
2.14.0 Stable 10–11 Aug 27, 2026
2.13.2 Stable 10–11 Aug 26, 2026
2.13.1 Stable 10–11 Aug 26, 2026
2.13.0 Stable 10–11 Aug 25, 2026
2.12.0 Stable 10–11 Aug 18, 2026
2.11.0 Stable 10–11 Aug 17, 2026
2.10.0 Stable 10–11 Aug 16, 2026
2.9.0 Stable 10–11 Aug 15, 2026
2.8.0 Stable 10–11 Aug 15, 2026
2.7.0 Stable 10–11 Aug 15, 2026
2.6.0 Stable 10–11 Aug 14, 2026
2.5.0 Stable 10–11 Aug 14, 2026
2.4.0 Stable 10–11 Aug 13, 2026
2.3.0 Stable 10–11 Aug 1, 2026
2.2.0 Stable 10–11 Jul 31, 2026
2.1.0 Stable 10–11 Jul 31, 2026
2.0.1 Stable 10–11 Jul 30, 2026
2.0.0 Stable 10–11 Jul 30, 2026
1.13.0 Stable 10–11 Jul 26, 2026
1.12.1 Stable 10–11 Jul 26, 2026
1.12.0 Stable 10–11 Jul 26, 2026
1.x-dev Dev 10–11 Jul 23, 2026
1.11.0 Stable 10–11 Jul 23, 2026
1.10.0 Stable 10–11 Jul 22, 2026
1.9.0 Stable 10–11 Jul 16, 2026
1.8.0 Stable 10–11 Jul 15, 2026
1.7.0 Stable 10–11 Jul 14, 2026
1.6.1 Stable 10–11 Jul 6, 2026
1.6.0 Stable 10–11 Jul 5, 2026
1.5.1 Stable 10–11 Jul 4, 2026
1.5.0 Stable 10–11 Jul 4, 2026
1.4.0 Stable 10–11 Jun 29, 2026
1.3.0 Stable 10–11 Jun 29, 2026
1.2.0 Stable 10–11 Jun 27, 2026
1.1.0 Stable 10–11 Jun 27, 2026
1.0.0 Stable 10–11 Jun 26, 2026
1.0.0-beta6 Pre-release 10–11 Jun 26, 2026
1.0.0-beta5 Pre-release 10–11 Jun 26, 2026
1.0.0-beta4 Pre-release 10–11 Jun 23, 2026
1.0.x-dev Dev 10–11 Jun 3, 2026
1.0.0-beta3 Pre-release 10–11 Jun 3, 2026
1.0.0-beta2 Pre-release 10–11 Jun 3, 2026
1.0.0-beta1 Pre-release 10–11 Jun 2, 2026
1.0.0-alpha1 Pre-release 10–11 Jun 1, 2026