npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

drupal-mcp-connector

v1.0.0

Published

A secure, multi-site Model Context Protocol (MCP) connector for Drupal — dual-protocol JSON:API and GraphQL.

Readme

drupal-mcp-connector

A secure, multi-site Model Context Protocol (MCP) connector for Drupal — dual-protocol JSON:API and GraphQL access, governed content tools, audit reports, and an SSH Drush bridge.

License: MIT Node.js Drupal MCP

Built by Jeremy Michael Cerda ([email protected]). Maintained by Wilkes & Liberty, LLC.


What It Does

drupal-mcp-connector connects any Model Context Protocol client to one or more Drupal sites. It exposes Drupal content and configuration as a set of MCP tools, resources, and prompts, so an MCP client can read, audit, and (where permitted) write content through structured, governed operations instead of the admin UI:

"Find all articles missing a meta description and list them."
"Show me every user account that hasn't logged in for 90 days."
"Create 10 draft product nodes from this structured data."
"Run an SEO and accessibility audit on the article content type."
"What content types exist on the site and which are barely used?"

The connector speaks two Drupal backends interchangeably — Drupal core's JSON:API and GraphQL (via GraphQL Compose) — selectable per site. It normalizes both into one canonical entity shape, so the same tools work whether a site exposes JSON:API, GraphQL, or both. An optional SSH Drush bridge adds administrative operations the HTTP APIs can't reach.


Dual-Protocol Backends

Each site declares which backend(s) it exposes via the api key:

"sites": {
  "main":         { "baseUrl": "https://example.com", "api": "jsonapi" },
  "graphql_only": { "baseUrl": "https://api.example.com", "api": "graphql" },
  "either":       { "baseUrl": "https://example.com", "api": ["graphql", "jsonapi"] }
}
  • api accepts "jsonapi", "graphql", or a priority array like ["graphql","jsonapi"]. Omit it to auto-detect (the connector probes both once and caches the result).
  • One canonical shape. Both backends return entities as { id, entityType, bundle, title, status, langcode, created, changed, url, fields, relationships, _backend }, so tool output is identical regardless of protocol.
  • Capability-aware. Each backend advertises what it supports (read, write, delete, server-side filter/sort, revisions). GraphQL via GraphQL Compose is read-only (no mutations) and has no server-side field filter, so filters are applied client-side over a bounded fetch and flagged approximate/truncated. Write tools against a read-only backend return a clear capability error rather than failing silently.
  • Writes go through JSON:API. Use a JSON:API-enabled site as the write plane; keep GraphQL as a read plane where that suits your architecture.

See docs/architecture.md for the backend abstraction and docs/graphql-local-setup.md for the GraphQL specifics.


Features

89 Tools Across 20 Modules

| Module | Tools | |--------|-------| | Nodes | CRUD for any content type with arbitrary field support | | Taxonomy | Vocabulary listing + full term CRUD | | Users | List, get, create, update, block/unblock, role management (PII-gated) | | Media | List types, CRUD, file upload, orphaned-media detection | | GraphQL | Execute a query, schema introspection (mutation-gated) | | Entities | Generic CRUD for any Drupal entity type (paragraphs, commerce, webforms, …) | | Site | Site info, content-type discovery, configured-site listing | | Reports | Content summary, stale content, field completeness, SEO/accessibility audits, taxonomy usage, user activity, revision hotspots (10 read-only reports) | | Drush | Cache rebuild, cron, config sync, module management, DB updates via SSH | | Revisions | List/get entity revisions; governed revert to a prior revision | | Moderation | Set moderation state; list content by state; observed-state discovery (content_moderation) | | Scheduler | Set publish-on / unpublish-on dates (Scheduler module) | | Fields | Describe a bundle's fields (type/required/cardinality, best-effort) | | References | Resolve a human name/title to an entity UUID for relationship fields | | Bulk | Bulk create/update with per-item partial-failure reporting | | Translations | List + create entity translations | | Paragraphs | Create/get Paragraph components for embedding in host fields | | Structure | Menu links + custom blocks (list/create) | | Search | Best-effort content search (title match; Search API/Solr-ready) | | Reports (extra) | Orphaned references, unpublished content, missing-field audits |

MCP Resources

Browsable, always-fresh context the client can read without calling a tool:

  • drupal://sites — configured site profiles (no credentials)
  • drupal://{site}/content-types — content types with field schemas
  • drupal://{site}/security-policy — the active security configuration

MCP Prompts

Workflow templates usable as slash-commands from any MCP client:

  • drupal-content-audit — walk through a full site content audit
  • drupal-create-article — guided article creation with all fields
  • drupal-seo-fix — find and fix SEO gaps
  • drupal-user-cleanup — identify and handle inactive accounts

Security Model

Defense-in-depth with four one-line presets, enforced connector-side and complemented by Drupal-side governance:

"security": { "preset": "auditor" }

| Preset | What it does | |--------|-------------| | development | Everything allowed — local development only | | content-editor | Create/edit nodes, media, terms; no deletes; no user access | | auditor | Read-only, all entity types, PII fields redacted | | production-strict | Read-only, no user entities, broad PII redaction |

Presets layer with entity allow/deny lists, per-bundle operation rules, and field-level redaction. Optional transport hardening (bearer-authenticated HTTPS, bind-address restriction, secrets-from-env) is covered in docs/security-hardening.md.


Requirements

  • Node.js 20+
  • Drupal 10 or 11 (JSON:API ships in core)
  • For the GraphQL backend: GraphQL Compose
  • For token auth (recommended): Simple OAuth
  • For the Drush bridge: SSH key access to the Drupal server

Quick Start

# 1. Clone and install
git clone https://github.com/Wilkes-Liberty/drupal-mcp-connector
cd drupal-mcp-connector
npm install

# 2. Configure
cp config/config.example.json config/config.json
# Edit config/config.json — add your site's baseUrl, api backend, and auth

# 3. Run (stdio transport)
node src/index.js

Register with an MCP client

Most desktop and CLI MCP clients launch the connector over stdio. Add an entry to your client's MCP server configuration:

{
  "mcpServers": {
    "drupal": {
      "command": "node",
      "args": ["/absolute/path/to/drupal-mcp-connector/src/index.js"],
      "env": {
        "DRUPAL_BASE_URL": "https://mysite.com",
        "DRUPAL_API_TOKEN": "your-token-here"
      }
    }
  }
}

For multi-client or remote use, run the HTTPS transport and register the endpoint instead — see docs/getting-started.md.


Companion Drupal Module — MCP Sentinel

The connector works out of the box against Drupal core's JSON:API and a GraphQL Compose schema. For server-side governance, pair it with the MCP Sentinel module (drupal/mcp_sentinel), which enforces policy inside Drupal — independent of any connector configuration:

  • Role-bound policy profiles (operation gates, entity allow/deny, field redaction)
  • Tamper-evident audit log of every governed MCP operation, attributed to the acting account
  • Content locks that prevent edits to content a human is actively editing
  • OAuth scope enforcement (mcp:read / mcp:write) per tool
  • HMAC-signed webhooks on MCP-driven entity changes
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

Governance keys off the authenticated account's role and OAuth scopes — not request headers. The connector sends an X-MCP-Client identity header purely as a log label. See the MCP Sentinel project page for the full contract.


Documentation

| Doc | Description | |-----|-------------| | Getting Started | Full setup: DDEV/Lando, Simple OAuth, multi-site, transports | | MCP Clients | Wire the connector into Claude (Code/Desktop), Grok (Build/API), and OpenAI (Codex/ChatGPT) — copy-paste config per client | | OAuth client_credentials | Production OAuth deploy: scope→role mapping, JSON:API writes, config persistence, secret handling, troubleshooting | | Architecture | Backend abstraction, canonical model, and how to extend it | | GraphQL Setup | GraphQL Compose backend + local TLS notes | | Tools Reference | Full reference for all 89 tools | | Security Guide | Presets, entity access control, field redaction | | Security Hardening | Optional transport, identity, and secrets controls | | Threat Model | Trust boundaries, threats & mitigations, residual risks, and the security-pass results | | Deployment | Run the HTTPS transport in production: Docker, systemd, launchd, reverse proxy, pre-exposure checklist | | Integration Contract | The connector ↔ Drupal-governance contract (identity, OAuth scopes, compatibility) | | Versioning & Stability | Semver policy: the stable surface, deprecation process, MCP protocol + Node support | | Whitepaper | Vision, personas, and use cases |


Contributing

PRs welcome. See CONTRIBUTING.md for guidelines.

Security

Found a vulnerability? See SECURITY.md. Please do not open a public issue.

License

MIT © 2026 Jeremy Michael Cerda and Wilkes & Liberty, LLC