This project is not covered by Drupal’s security advisory policy.
Droost gives AI coding agents structured, first-hand knowledge of this Drupal application. It is the Drupal analog of Laravel Boost: a developer-acceleration toolkit that exposes the application and codebase itself - versions, the entity and configuration model, routes, services, logs, database schema, and a set of guarded operations - as Model Context Protocol (MCP) tools.
It is built entirely on MCP Server and the official mcp/sdk: MCP Server provides the runtime and the #[Tool] plugin system; Droost provides the tools.
The problem it solves
An AI agent asked to write Drupal code is usually working blind. It does not know which modules and versions are installed, what entity types and fields exist, which services it should inject instead of calling \Drupal::, what the routes and permissions are, or whether the last request errored. It guesses - and guesses age badly as a project evolves.
The common workaround is to tell the agent to run Drush and parse the free-text output. Droost takes a different path: it exposes that information as explicit, schema-described tools that return structured JSON. The agent gets reliable, version-correct answers about the real site, and capabilities become discoverable and individually gateable rather than hidden behind a shell.
Features
- 22 MCP tools spanning read-only introspection and guarded operations, each returning a uniform
{success, message, data}envelope. - Read-only by default. State-changing tools are registered so an agent can discover them, but refuse to act until explicitly opted in.
- A real security model (see below): per-flag gating, secret redaction in config reads, and a read-only SQL guard.
- Bundled, version-stamped guidelines - composable Drupal conventions plus on-demand deep-dive topics, served over MCP and writable to
AGENTS.md. - On-disk documentation search across core, contrib, and custom modules, so answers match the exact versions installed.
- One-command adoption with
drush droost:install(auto-detects DDEV).
Requirements
- Drupal 10.3+ or 11; PHP 8.3+.
- MCP Server (
drupal/mcp_server)^2.0@alpha- provides the MCP runtime and thedrush mcp:servercommand. - Drush 12+ - Droost is served over STDIO by Drush and ships the
droost:installcommand. - The core Database Logging (
dblog) module - optional; only thedroost_logsanddroost_last_errortools depend on it, and they degrade gracefully when it is absent.
Installation
Install with Composer (recommended) so the MCP Server dependency is resolved:
composer require drupal/droost drush en droost -y
Note: MCP Server is currently an alpha release, so a site on the default stable minimum-stability cannot resolve it without opting in. Either require the dependency explicitly first:
composer require drupal/mcp_server:^2.0@alpha composer require drupal/droost
or set "minimum-stability": "alpha" with "prefer-stable": true in your root composer.json before requiring Droost.
Usage
1. Wire up your editor
drush droost:installdroost:install (alias droost) registers the Droost MCP server in the project's .mcp.json, writes the bundled guidelines to AGENTS.md, and prints ready-to-paste registration commands for common clients. It auto-detects DDEV and, in that case, uses ddev drush mcp:server as the launch command.
Options:
| Option | Values | Effect |
|---|---|---|
--launcher |
auto (default), ddev, drush, vendor |
How editors launch the server. auto picks ddev when a .ddev directory is present, otherwise drush. |
--guidelines |
true (default) / false |
Whether to also (re)write the Droost block in AGENTS.md. |
The command prints per-editor hints, for example:
Claude Code: claude mcp add -s local -t stdio droost ddev drush mcp:server Gemini CLI: gemini mcp add -s project -t stdio droost ddev drush mcp:server Codex: codex mcp add droost -- ddev drush mcp:server
2. Serve the tools
MCP Server serves Droost's enabled tools over STDIO with drush mcp:server (run as ddev drush mcp:server under DDEV); your editor launches this and speaks JSON-RPC to it. After enabling or adding tools, rebuild caches and reload MCP servers in your editor:
drush cache:rebuildA quick manual handshake, list, and call check:
printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"c","version":"0"}}}' \ '{"jsonrpc":"2.0","method":"notifications/initialized"}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \ | drush mcp:server
Configuration
Droost ships read-only. State-changing tools are gated by two boolean flags in droost.settings, both off by default. Configure them at Admin > Configuration > Development > Droost (/admin/config/development/droost, requires the Administer Droost permission), or from the CLI:
drush config:set droost.settings allow_destructive true drush config:set droost.settings allow_eval true
| Flag | Unlocks | Default |
|---|---|---|
allow_destructive |
droost_config_set, droost_module_install, droost_module_uninstall |
false |
allow_eval |
droost_eval (arbitrary PHP - the Tinker analog) |
false |
Each flag is independent: enabling destructive tools does not enable the eval tool.
Tool reference
Every tool returns {success, message, data}. The columns mirror the MCP annotations Droost sets on each tool.
Introspection (read-only)
| Tool | Purpose | Key arguments |
|---|---|---|
droost_app_info |
Drupal/PHP versions, install profile, DB engine, themes, and enabled contrib/custom modules with versions. | None |
droost_entities |
Entity types > bundles > field definitions. | entity_type_id, bundle |
droost_entity_load |
One entity's raw field values, loaded by ID or UUID. | entity_type, id / uuid, fields |
droost_config_get |
Read a config object's values (sensitive keys redacted) or list config names. | name, prefix, limit |
droost_config_status |
Configuration drift between active config and the sync directory. | name, limit |
droost_db_schema |
List tables, or one table's columns. | table, limit |
droost_db_query |
Run a single read-only SQL statement (SELECT / WITH / SHOW / DESCRIBE / EXPLAIN only). | query, limit |
droost_routes |
Routes with path, methods, controller, and access requirements. | pattern, limit |
droost_services |
Registered dependency-injection service IDs. | pattern, limit |
droost_logs |
Recent dblog entries, newest first. Requires dblog. | type, severity, limit |
droost_last_error |
The most recent error-level dblog entries. Requires dblog. | limit |
droost_url |
Resolve an internal path or a route (+ parameters) to an absolute URL. | path, route, parameters |
droost_permissions |
Permission catalog and role grants; or one role's permissions; or which roles grant a permission. | role, permission |
droost_update_status |
Pending hook_update_N and post-update functions ("do I need drush updatedb?"). |
None |
droost_guidelines |
Curated Drupal guidelines: core conventions + a list of deep-dive topics, or one topic. | topic |
droost_module_docs |
Read or search README / *.md / *.api.php / docs/*.md / info descriptions across modules. |
query, module, file, scope, limit |
Operations
| Tool | Purpose | Gating |
|---|---|---|
droost_cache_rebuild |
Rebuild all caches (drush cr). |
Ungated (safe, idempotent). |
droost_cron_run |
Run cron: process queues and scheduled maintenance. | Ungated (safe). |
droost_config_set |
Set a single value on an existing config object. | allow_destructive |
droost_module_install |
Install (enable) modules and their dependencies. | allow_destructive |
droost_module_uninstall |
Uninstall (disable) modules; deletes their config and data. | allow_destructive |
droost_eval |
Execute PHP in the bootstrapped Drupal context (the Tinker analog). High risk. | allow_eval |
Security model
Droost is explicit about runtime safety:
- Read-only by default. Every tool sets accurate MCP annotations (
readOnly,destructive,idempotent,openWorld). These are advisory hints to the client; the real gate is enforced in code. - Opt-in gating. State-changing tools are registered (so an agent can discover them) but call a gate at the top of execution and refuse unless the relevant
droost.settingsflag is on. The refusal message explains exactly how to enable the tool. - Why a config flag, not a permission. Over STDIO there is no web session or authenticated user, so a Drupal permission cannot gate the call; the config flag does. The module still ships the matching
use droost *permissions for the case where MCP Server is additionally exposed over HTTP at/_mcp- in which case destructive tools should remain STDIO-only. - Secret redaction.
droost_config_getrecursively redacts values whose keys look sensitive (*pass*,*secret*,*token*,*credential*,*hmac*,*salt*,key/*_key, API/client keys), so credentials never reach the agent. It never returnssettings.phpvalues. - Read-only SQL guard.
droost_db_queryaccepts a single statement, allows onlySELECT/WITH/SHOW/DESCRIBE/EXPLAIN, and rejects write or DDL keywords, stacked statements, and file functions (INTO OUTFILE,LOAD_FILE). - Eval is doubly gated.
droost_evalis off by default behind its ownallow_evalflag (separate fromallow_destructive) and is documented as trusted-local-development only.
Guidelines
Droost bundles composable Drupal know-how under guidelines/:
- Core conventions (
guidelines/core/) - always-on guidance an agent should follow on every change: dependency injection over\Drupal::, hooks, the entity and config APIs, render arrays, plugins, coding standards, and security. - Deep-dive topics (
guidelines/topics/) - pulled on demand by name:entity-api,plugins,mcp-tools, andsecurity.
The droost_guidelines tool serves the core conventions (version-stamped to the live Drupal and PHP versions) plus the topic list; pass topic for one topic's full content. drush droost:install writes the same composed guidelines into a delimited block in AGENTS.md so non-MCP tooling can use them too.
Submodules
droost_devel(requires Devel) -droost_generatecreates content, users, or terms viadevel_generate. Destructive; gated byallow_destructive.droost_profiler(self-contained, no external dependency) - a lightweight request profiler. Opt-in middleware records DB queries, wall-clock time, and peak memory per HTTP request;droost_profile_listanddroost_profileread them back over MCP, surfacing the slowest and duplicate queries.
Extending Droost
A Droost tool is a plugin class under src/Plugin/Tool/. To add one:
- Carry the
#[Tool]attribute (id, label, description,inputSchema,outputSchema, and thereadOnly/destructive/idempotent/openWorldannotations). - Extend
DroostToolBase(orDestructiveToolBasefor state-changing tools). The base classes provide thesucceed()/fail()envelope helpers, small typed-argument coercion helpers (stringArg(),intArg(),stringListArg(),toString(),toInt()), theenabled => TRUEdefault so the tool auto-registers, and - forDestructiveToolBase- thegate()check. - Implement
execute(array $arguments, ClientGateway $gateway): mixedand return a{success, message, data}array. - Inject services through
create()rather than calling\Drupal::.
A minimal read-only tool:
#[Tool( id: 'droost_example', label: new TranslatableMarkup('Droost: Example'), description: new TranslatableMarkup('Returns a greeting. Read-only.'), inputSchema: ['type' => 'object'], readOnly: TRUE, destructive: FALSE, idempotent: TRUE, openWorld: FALSE, )] final class Example extends DroostToolBase { public function execute(array $arguments, ClientGateway $gateway): mixed { return $this->succeed('Hello from Droost.', ['greeting' => 'hello']); } }
A state-changing tool calls the gate first:
public function execute(array $arguments, ClientGateway $gateway): mixed { if (($blocked = $this->gate()) !== NULL) { return $blocked; } // perform the guarded operation }
See src/Plugin/Tool/AppInfo.php for a complete read-only example, src/Plugin/Tool/ConfigSet.php for a gated one, and the mcp-tools guideline topic for the full contract. Run drush cache:rebuild and the tool appears in tools/list.
Project information
- Project categories: Artificial Intelligence (AI)
- Ecosystem: MCP Server
- Created by chadmandoo on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
