Drupal MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| DRUSH_PATH | No | Path to Drush binary, may contain arguments (e.g., 'ddev drush') | drush |
| MCP_TRANSPORT | No | Transport protocol. One of: stdio, http, sse, streamable-http | stdio |
| DRUPAL_BASE_URL | No | Base URL of the Drupal site | http://localhost |
| DRUPAL_PASSWORD | No | Password for Drupal authentication (used with DRUPAL_USERNAME) | |
| DRUPAL_USERNAME | No | Username for Drupal authentication (used with DRUPAL_PASSWORD) | |
| DRUPAL_API_TOKEN | No | Bearer token for authentication (sent as Authorization: Bearer) | |
| DRUPAL_VERIFY_SSL | No | Set to false for self-signed dev certs (DDEV, Lando) | true |
| DEFAULT_AI_PROVIDER | No | AI provider to use. One of: ollama, openai, anthropic, nvidia_nim, google | ollama |
| DRUPAL_OAUTH_CLIENT_ID | No | OAuth2 client ID (alternative authentication method) | |
| DRUPAL_OAUTH_TOKEN_URL | No | OAuth2 token URL (alternative authentication method) | |
| DRUPAL_OAUTH_CLIENT_SECRET | No | OAuth2 client secret (alternative authentication method) |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": true
} |
| resources | {
"subscribe": false,
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| analyze_d7_siteC | Analyze a Drupal 7 site for D10 upgrade readiness. |
| analyze_d9_siteC | Analyze a Drupal 9+ site for deprecated code and APIs. |
| inventory_content_typesC | List all content types on a Drupal site. |
| inventory_modulesC | List all modules on a Drupal site. |
| map_modules_d7_to_d10C | Map Drupal 7 modules to D10 equivalents using AI + known mappings. |
| find_deprecated_codeC | Scan custom modules for deprecated Drupal APIs. |
| find_entity_referencesA | Find which bundles use reference fields targeting an entity type. Answers "where are these used?" at the configuration level: for
This reads field configuration, not content: it reports where
references can live, not which individual rows currently point at
which entity. For the data, query the field's table with |
| search_entitiesA | Case-insensitive substring search across entity titles and names. Scans node titles, user names and emails, taxonomy term names, comment subjects, media names, and file names with one read-only LIKE query per type, returning matches grouped by entity type. Pass |
| find_entity_by_pathA | Resolve a URL path or alias ("/about", "/node/123") to its entity. Internal routes such as /node/123 are read directly. Anything else is looked up in the path alias table, and the resolved target is parsed the same way. A full URL is accepted; the query string and fragment are ignored. Returns the entity id and a short summary, or found: false when nothing resolves. |
| generate_migration_yamlD | Generate migration YAML configuration. |
| generate_module_migrationC | Generate migration module for a custom module with source plugin, process plugins, and migration template. |
| run_migration_testC | Test migration with limited records. |
| validate_migrationC | Validate migration configuration. |
| rollback_migrationC | Rollback a completed migration. |
| sync_media_filesC | Sync media files between paths. |
| migrate_taxonomyC | Migrate taxonomy vocabularies and their terms. |
| create_migration_planC | Create or replace a persisted migration plan. |
| get_migration_planC | Read a persisted migration plan and its tracked state. |
| list_migration_plansB | List all persisted migration plans. |
| migration_statusC | Summarize migration progress for a persisted plan. |
| migrate_recordsC | Copy a batch of source records into the target Drupal site through JSON:API. |
| record_migration_resultC | Record the outcome of a manually executed migration operation. |
| analyze_source_siteC | Analyze a source Drupal JSON:API resource type and optionally store counts in a plan.
|
| reconcile_migration_countsC | Compare recorded source counts with current target-site counts. |
| run_migration_waveC | Fetch and migrate one resource type from the plan's source site into the target site.
|
| run_migrationB | Run an ordered end-to-end migration for one or all planned entity types. Waves run in the order given (dependencies first). A failed wave stops
the run by default, since a schema or auth problem tends to repeat;
set |
| create_nodeC | Create a single node of the specified bundle with given fields. |
| get_nodeB | Get a single node by ID with optional relationship includes. |
| update_nodeC | Update a single node by ID with given fields. |
| delete_nodeB | Delete a single node by ID. |
| query_nodesC | Query nodes with filters, sorts, includes, and pagination. |
| upload_mediaC | Upload a file to the media library. |
| create_mediaC | Create media entity from a remote URL (image, video, document, etc.). |
| clean_nodes_aiC | Clean duplicate or malformed nodes using AI. Requires confirm=True to execute deletions. |
| map_fields_aiB | Suggest AI-powered field mappings from a source field list to a target bundle. Reads the target bundle's available fields, then asks the AI provider to map each source field onto the closest target field. |
| bulk_update_nodesC | Apply the same field updates to every node matching a set of filters. |
| fix_media_referencesC | Find broken media references across a content type. Scans nodes of the given type and checks every media relationship, reporting references whose target media entity no longer resolves. |
| bulk_update_aliasesB | Regenerate URL aliases for a content type. Alias generation belongs to the Pathauto module, so this runs
|
| analyze_content_qualityC | Analyze content quality with AI for specific nodes or an entire type. |
| generate_test_contentA | Generate sample nodes for a bundle to populate a development site. |
| config_getC | Get a single configuration object by name. |
| config_setC | Set a single configuration value. |
| export_configC | Export Drupal configuration to files. |
| import_configC | Import Drupal configuration from files. |
| sync_configC | Sync configuration between environments via Drush. |
| diff_configB | Show differences in configuration between environments. |
| split_configC | Split configuration into separate directories for atomic deployment. Reads from source_dir (exported config) and creates individual config files in output_dir for each specified config object. |
| config_statusA | Compare active configuration with the exported sync directory. Read-only: reports how many config objects are the same, differ,
exist only in the database (never exported, or changed since), or
exist only in the sync directory, with the differing names. This is
what An empty sync directory shows everything as "Only in DB" -- export
first with |
| drush_commandB | Execute any Drush command.
|
| ddev_setupA | Generate .ddev/config.yaml for a local Drupal environment. Refuses to overwrite an existing config: calling this with defaults on
a working project used to replace the whole file with |
| ddev_startC | Start DDEV project. |
| ddev_stopC | Stop DDEV project. |
| ddev_execC | Execute command in DDEV container. |
| lando_startC | Start Lando project. |
| lando_stopC | Stop Lando project. |
| lando_execC | Execute command in Lando container. |
| lando_setupC | Generate .lando.yml for a local Drupal environment. |
| acquia_deployC | Deploy to Acquia Cloud via acquia-cli or Drush acquia integration. Supports both acquia-cli (preferred) and legacy Drush acquia commands. |
| backup_databaseC | Create database backup via Drush. |
| cache_rebuildB | Clear and rebuild all Drupal caches via Drush. |
| composer_installD | Run composer install. |
| composer_requireC | Require one or more packages via composer. Several packages may be given at once, space separated, the way
|
| composer_updateC | Run composer update. |
| drush_cronC | Run cron. |
| drush_watchdogC | Show recent log entries from watchdog. |
| cache_clearC | Clear specific cache bins. |
| drush_updbC | Run database updates. |
| drush_php_evalC | Execute arbitrary PHP code via Drush. |
| ai_analyze_content_qualityC | Analyze content quality using AI. |
| ai_suggest_field_mappingsC | Suggest field mappings using AI. |
| ai_generate_migration_planD | Generate migration plan using AI. |
| ai_translate_contentC | Translate content using AI. |
| create_vocabularyC | Create a taxonomy vocabulary. |
| get_vocabularyB | Get a taxonomy vocabulary by ID. |
| update_vocabularyD | Update a taxonomy vocabulary. |
| delete_vocabularyC | Delete a taxonomy vocabulary. |
| list_vocabulariesB | List all taxonomy vocabularies. |
| create_termC | Create a taxonomy term in a vocabulary. |
| get_termC | Get a taxonomy term by ID. |
| update_termD | Update a taxonomy term. |
| delete_termC | Delete a taxonomy term. |
| list_termsC | List terms in a vocabulary with filters and pagination. |
| create_userC | Create a user account. |
| get_userC | Get a user by ID with optional relationship includes. |
| get_user_by_emailC | Get a user by email address. |
| update_userC | Update a user account. |
| delete_userC | Delete a user account. |
| list_usersC | List users with filters and pagination. |
| assign_roleC | Assign a role to a user. |
| remove_roleC | Remove a role from a user. |
| list_rolesB | List all available roles. |
| get_user_rolesC | Get roles assigned to a user. |
| block_userC | Block a user account. |
| unblock_userC | Unblock a user account. |
| db_queryA | Execute a single read-only SELECT query on the Drupal database. One statement only, no comments, and no write or file-access clauses. |
| db_tablesB | List all database tables. |
| db_table_infoC | Get table schema information. |
| db_countC | Count rows in a table. |
| views_listC | List all views on a Drupal site. |
| views_getC | Get a single view configuration by ID. |
| views_createC | Create a new view. |
| views_updateD | Update an existing view. |
| views_deleteC | Delete a view. |
| views_executeA | Execute a view and return its rows. Runs the view through the Views API rather than guessing at a GraphQL
schema. The graphql module ships no
|
| views_exportB | Export a view as configuration YAML or JSON. |
| paragraphs_type_listC | List all paragraph types on a Drupal site. |
| paragraphs_type_getC | Get a single paragraph type configuration by ID. |
| paragraphs_type_createC | Create a new paragraph type. |
| paragraphs_type_updateC | Update an existing paragraph type. |
| paragraphs_type_deleteC | Delete a paragraph type. |
| paragraphs_item_listA | List paragraph items, optionally filtered by type. A paragraph's type is its bundle, so filtering by type means addressing
the |
| paragraphs_item_getC | Get a single paragraph item by ID. |
| paragraphs_item_createC | Create a new paragraph item of the specified type. |
| paragraphs_item_updateC | Update a paragraph item. |
| paragraphs_item_deleteC | Delete a paragraph item. |
| menu_listC | List all menus on a Drupal site. |
| menu_getC | Get a single menu configuration by ID. |
| menu_createC | Create a new menu. |
| menu_updateC | Update an existing menu. |
| menu_deleteC | Delete a menu. |
| menu_link_listC | List menu links, optionally filtered by menu. |
| menu_link_getC | Get a single menu link by ID. |
| menu_link_createC | Create a new menu link. |
| menu_link_updateC | Update a menu link. |
| menu_link_deleteC | Delete a menu link. |
| field_config_listC | List all field configurations on a Drupal site. |
| field_config_getB | Get a single field configuration by ID. |
| field_config_createC | Create a new field configuration. |
| field_config_updateC | Update a field configuration. |
| field_config_deleteC | Delete a field configuration. |
| field_storage_listC | List all field storage configurations on a Drupal site. |
| field_storage_getB | Get a single field storage configuration by ID. |
| field_storage_createC | Create a new field storage configuration. |
| field_storage_updateD | Update a field storage configuration. |
| field_storage_deleteC | Delete a field storage configuration. |
| revision_listC | List revisions for an entity. Only the current revision is enumerable over JSON:API; the tool reports that honestly rather than inventing a collection URL. |
| revision_getC | Get a specific revision of an entity. |
| revision_revertA | Revert an entity to a specific revision. Applies the revision's field values to the current entity. A PATCH that Drupal rejects is atomic, so a failure leaves the entity untouched. |
| revision_deleteC | Delete a specific revision of an entity. |
| revision_diffC | Diff two revisions of an entity. |
| redirect_listC | List all redirects on a Drupal site. |
| redirect_getB | Get a single redirect configuration by ID. |
| redirect_createC | Create a new redirect. |
| redirect_updateC | Update an existing redirect. |
| redirect_deleteC | Delete a redirect. |
| redirect_bulk_createC | Create multiple redirects in bulk. |
| redirect_bulk_deleteC | Delete multiple redirects in bulk. |
| cron_runC | Run cron. |
| cron_listA | List the jobs Drupal runs on cron, and when cron last ran. In Drupal 8+ a "cron job" is a module implementing The implementations sit behind |
| queue_listB | List all queues. |
| queue_runC | Run a specific queue. |
| queue_deleteA | Delete queue items: one by id, the oldest Drush's Even the plain case now runs in PHP rather than through Drush, because
|
| queue_infoC | Get queue information. |
| queue_createA | Create a queue and make it ready to accept items.
|
| code_audit_phpstanC | Run PHPStan static analysis on Drupal custom modules. |
| drupal_checkC | Run Drupal Check for deprecated code detection. |
| code_snifferC | Run PHP_CodeSniffer with Drupal coding standards. |
| deprecation_scanC | Scan for deprecated Drupal API usage. |
| security_auditC | Run security-focused static analysis. |
| composer_auditB | Run Composer security audit on dependencies. |
| code_quality_reportC | Run multiple code quality tools and generate combined report. |
| codebase_index_refreshA | Rebuild the local codebase module index. Call after installing, enabling or creating modules so the other codebase tools see the current state. Returns counts of indexed modules by type and the module directories that were scanned. |
| codebase_searchB | Search the local codebase for modules providing a capability. Ranks exact machine-name/name matches above description matches, which rank above code-body matches (hooks, services, routes, classes). Use scope 'custom' or 'contrib' to filter by module origin; 'all' includes core. |
| codebase_module_listA | List indexed local modules with metadata. Each item carries machine name, human name, type (custom/contrib/ core), version, dependencies, path and description. With show_unused=True each item is flagged when nothing references it and it implements no hooks. |
| codebase_module_describeB | Describe one local module in full. Returns the module's info.yml fields, dependencies, reverse dependencies, hooks, services, routes, classes and file count — everything the index knows about it. |
| codebase_unused_modulesA | List custom/contrib modules nothing references and that define no hooks. A module counts as used when another module depends on it, when another module's services inject one of its services, or when it implements hooks itself. Candidates for removal. |
| codebase_redundancy_checkA | Check whether the local codebase already covers a capability. Searches the index and reports the closest existing modules plus a recommendation: extend what exists rather than duplicating it. |
| codebase_hooks_findA | Find which local modules implement a hook, with file and line. Accepts the hook with or without its 'hook_' prefix (both 'form_alter' and 'hook_form_alter' work). Implementations are reported per module with the file and line of the function. |
| codebase_paths_listA | Show the configured docroot and the module directories indexed. Use this to verify which locations the codebase tools actually scan (modules, web/modules, sites/*/modules, core) before relying on search results. |
| codebase_files_listA | List every file in a local module as module-relative paths. Useful to find the right path before calling codebase_file_read or codebase_function_read. |
| codebase_directory_treeB | Show a local module's directory structure as a nested tree. Directories have children; files carry a size. The tree is depth and item capped to keep responses bounded. |
| codebase_file_readA | Read one file from a local module.
|
| codebase_function_readA | Extract a single PHP function (with its docblock) from a module. Returns the file path, the line of the function and its code — enough to review one hook or method without reading whole files. Searches all PHP-ish files in the module, including class methods. |
| security_scanC | Run security-focused SAST using PHPStan with security extensions. |
| dependency_scanB | Scan dependencies for vulnerabilities using Composer audit and other tools. |
| config_security_checkB | Check Drupal configuration for security issues. |
| permission_auditC | Audit user permissions and roles. |
| sql_injection_scanC | Scan for SQL injection vulnerabilities in custom code. |
| xss_scanC | Scan for XSS vulnerabilities in custom code. |
| csp_auditC | Content Security Policy audit. |
| file_permissions_auditC | Audit file permissions for security issues. |
| code_security_scanA | Scan custom code for vulnerability patterns — no tools to install. Matches PHP/JS/Drupal files against a curated registry of XSS, SQL injection, command injection, path traversal, hardcoded secrets, access-control, CSRF, and deprecated-API patterns, with Drupal-aware false-positive rules (EntityQuery conditions, stream wrappers, escapeshellarg, and similar safe APIs are recognized). The counterpart of security_scan, which needs PHPStan installed. Target one module by machine name, or a directory relative to DRUPAL_ROOT; with neither, the site's own modules/ and themes/ directories are scanned (contrib and core excluded). categories narrows to registry keys ('xss', 'sql_injection', 'command_injection', 'path_traversal', 'hardcoded_secrets', 'access_control', 'csrf', 'deprecated_api'); severity narrows to one level. Findings carry file, line, snippet, and a fix recommendation; counts cover the full run even when max_findings truncates the list. |
| route_access_auditA | Classify every route's access control from *.routing.yml files. The routing half of a pre-deployment review: each route is
classified by what it requires — fully anonymous ( |
| status_reportA | Run the site's status report (what /admin/reports/status shows). Read-only. Returns each requirement with its title, severity
("error", "warning", "info", or "ok"), description, and value.
By default errors and warnings are returned; use A failure here is usually the site's own requirements checker breaking, not this tool: the drush error is returned verbatim. |
| database_updatesA | List pending database updates (read-only; runs nothing). Answers "did the modules I just updated leave schema behind?".
Use |
| available_updatesA | List packages with newer versions available, from composer. Read-only ( With |
| health_checkA | Check that this server can actually reach a working Drupal site. Runs four read-only probes: Drush and the site status, the database connection, the JSON:API index, and the modules the other tools assume (jsonapi required; dblog and basic_auth recommended). Each failure comes with the concrete fix. Run this first when other tools return opaque connection errors. |
| module_searchC | Search Drupal.org for modules by name or description. |
| module_getB | Get module details from Drupal.org by machine name. |
| module_versionsC | Get all available releases for a module. |
| module_dependenciesA | Get the packages a module release requires. Read from Composer metadata on packages.drupal.org, which is where
Drupal publishes dependency data today. Omit |
| theme_searchC | Search Drupal.org for themes by name or description. |
| theme_getB | Get theme details from Drupal.org by machine name. |
| release_historyC | Get release history for a project. |
| project_usageC | Get download/usage statistics for a project. |
| module_compatibilityB | Check whether a project has releases for a given core version. |
| module_issues_searchA | Search a module's drupal.org issue queue for issues that match a problem. Describes the problem (e.g. "Azure AD attribute mapping fails") and the most recently updated issues are scored on keyword overlap with their titles and bodies; the best matches come back first, each with a link. Set drupal_version (e.g. "10") to hide issues filed against other major versions; when unset it is detected from DRUPAL_ROOT if configured. |
| module_popularA | List the most-installed modules on Drupal.org, newest usage first. Optionally filter by a drupal.org category such as "E-commerce", "Security", "SEO", or "Media" (case-insensitive, substrings work). Usage is summed across every release line, so a module's full install base shows up in one number. Categories are listed in the error if the name does not match one. |
| module_recommendationB | Recommend modules for a need: what the local codebase already ships, plus drupal.org options. Combines the local codebase index (available when DRUPAL_ROOT is set) with drupal.org search, so the answer starts with modules you already have before suggesting downloads. |
| moderation_state_listC | List all moderation states. |
| moderation_state_getC | Get a single moderation state by ID. |
| moderation_state_createC | Create a new moderation state. |
| moderation_state_updateC | Update a moderation state. |
| moderation_state_deleteC | Delete a moderation state. |
| moderation_transition_listA | List a workflow's moderation transitions. Transitions are configuration inside the Every workflow is read when |
| moderation_transition_getA | Get a single moderation transition by ID. Transitions belong to a workflow rather than being entities, so this
searches every workflow's transitions for the named one. Pass
|
| moderation_transition_createA | Create a new moderation transition on a workflow. Transitions are configuration inside the Both the origin states and the target state must already exist in the
workflow; an error names the ones that do not and lists the states the
workflow does have. |
| moderation_transition_deleteA | Delete a moderation transition from a workflow. The counterpart of |
| moderation_transition_executeA | Execute a moderation transition on an entity. Looks the transition up on its workflow and applies its target state to the entity, refusing when the entity's current state is not one the transition starts from. The old version fetched the transition through JSON:API, which has no such resource, so this never ran. |
| content_moderation_dashboardC | Get content pending moderation - dashboard view. |
| workflow_listC | List all workflows. |
| workflow_getC | Get a single workflow by ID. |
| module_createC | Create a new Drupal module with full scaffolding. |
| module_service_createC | Create a service definition with PHP class stub. |
| module_plugin_createC | Create a plugin (block, field, views, etc.) with proper scaffolding. |
| module_form_createC | Create a form class (ConfigForm, ConfirmForm, FormBase, etc.) with proper scaffolding. |
| module_controller_createC | Create a controller class with routing. |
| module_event_subscriber_createC | Create an event subscriber service with getSubscribedEvents method. |
| module_hook_implementC | Implement a hook in an existing module. |
| module_info_generateC | Generate .info.yml from existing module code (reverse engineering). |
| module_permission_createC | Create or update permissions.yml with custom permissions. |
| module_config_schema_createC | Create or update config schema YAML for module settings. |
| module_test_createC | Create a PHPUnit/Kernel test skeleton. |
| module_dependencies_analyzeC | Analyze module code and suggest missing dependencies. |
| theme_createC | Create a new Drupal theme with full scaffolding. |
| theme_library_createC | Create or update a theme library. |
| theme_region_createC | Add a region to theme. |
| theme_template_overrideC | Create a template override in theme. |
| theme_preprocess_functionC | Add a preprocess function to theme. |
| theme_breakpoint_createC | Add a breakpoint to theme. |
| theme_base_changeC | Change the base theme. |
| theme_settings_formD | Generate theme settings form. |
| theme_asset_optimizeD | Configure theme asset optimization. |
| theme_debug_enableC | Enable theme debugging (Twig debug, etc.). |
| theme_lint_twigC | Lint Twig templates in theme. |
| block_listC | List all blocks. |
| block_getC | Get a single block by ID. |
| block_createD | Create a new block. |
| block_updateD | Update a block. |
| block_deleteC | Delete a block. |
| block_placeC | Place a block in a region with weight. |
| layout_builder_listB | Report which entity view displays have Layout Builder enabled. Layouts themselves are not readable over JSON:API (see the other layout_builder_* tools), but the display config that switches Layout Builder on for a bundle is, so this returns that instead of a 404. |
| layout_builder_getA | Read the Layout Builder layout for an entity type and bundle. Returns whether Layout Builder is enabled and overridable for the bundle, plus every section with its layout plugin, region and components. This reads the real view display rather than the JSON:API resource that does not exist. |
| layout_builder_createB | Replace the Layout Builder layout for a bundle.
|
| layout_builder_updateA | Update the Layout Builder layout for a bundle. With |
| layout_builder_sections_listB | List the sections in a bundle's Layout Builder layout. Each section reports its layout plugin, and the components in it report region, plugin id and weight. |
| layout_builder_section_addA | Append a section to a bundle's Layout Builder layout.
|
| block_plugin_listC | List available block plugins. |
| block_region_listC | List available regions for a theme. |
| layout_builder_override_removeA | Remove a Layout Builder override so an entity falls back to the default. Pass Reverting clears the entity's |
| search_api_server_listC | List all Search API servers. |
| search_api_server_getC | Get a single Search API server by ID. |
| search_api_server_createC | Create a new Search API server. |
| search_api_index_listC | List Search API indexes. |
| search_api_index_getC | Get a single Search API index by ID. |
| search_api_index_createC | Create a new Search API index. |
| search_api_index_updateD | Update a Search API index. |
| search_api_index_reindexC | Trigger reindexing of a Search API index. |
| search_api_index_clearC | Clear a Search API index. |
| search_api_server_enableC | Enable a Search API server. |
| search_api_server_disableC | Disable a Search API server. |
| search_api_facet_listB | List Search API facets.
|
| search_api_facet_createC | Create a Search API facet. |
| language_listC | List all languages. |
| language_getC | Get a single language by langcode. |
| language_addC | Add a new language. |
| language_enableC | Enable a language. |
| language_disableC | Disable a language. |
| language_deleteC | Delete a language. |
| content_translation_enableC | Enable content translation for entity type/bundle. |
| translation_statusC | Get translation status for an entity. |
| translation_addD | Add translation for an entity. |
| translation_updateC | Update translation for an entity. |
| interface_translation_listA | List the interface translations Drupal holds. Locale does not store translations as entities, so there is no
|
| interface_translation_addA | Add an interface translation for one source string. Written through Locale's own string storage -- If the source string is not one Drupal has already collected, it is created too and the reply says so: a translation nobody will ever look up is worth knowing about. The locale lookup cache is invalidated, so the new text is visible without a cache rebuild. |
| interface_translation_updateA | Change an existing interface translation. Same storage as |
| interface_translation_deleteA | Remove an interface translation from one language. Drops the row from |
| config_translation_listB | List the config objects that support translation. There is no Each mapping is returned with the entity type it translates. The
mapping's own config-name list is empty until Drupal builds it inside
the translation form, so it is not reported here -- the id and the
entity type are what |
| config_translation_addA | Translate a config entity.
A config entity is not a translatable entity. There is no
|
| language_negotiation_getB | Get language negotiation configuration. |
| language_negotiation_setC | Set language negotiation method. |
| media_type_listC | List all media types. |
| media_type_getC | Get a single media type by ID. |
| media_type_createD | Create a new media type. |
| media_create_from_urlC | Create media from URL (oEmbed). |
| media_create_from_base64C | Create media from base64 encoded file data. |
| media_derivative_generateC | Generate a specific derivative for media. |
| media_bulk_importC | Bulk import media files from directory. |
| media_library_listD | List media library items. |
| pathauto_pattern_listA | List pathauto patterns. A pattern's target entity type and bundle are encoded in its id, as
|
| pathauto_pattern_getC | Get a single pathauto pattern by ID. |
| pathauto_pattern_createD | Create a new pathauto pattern. |
| pathauto_pattern_updateD | Update a pathauto pattern. |
| pathauto_pattern_deleteC | Delete a pathauto pattern. |
| pathauto_generateC | Generate pathauto aliases. |
| pathauto_token_listC | List available pathauto tokens. |
| redirect_pattern_listC | List redirect patterns. |
| metatag_config_listC | List all metatag configurations. |
| metatag_config_getC | Get a single metatag configuration by ID. |
| metatag_config_createC | Create a new metatag configuration. |
| metatag_config_updateD | Update a metatag configuration. |
| metatag_defaults_getC | Get default metatag values for entity type/bundle. |
| metatag_defaults_setC | Set default metatag values for entity type/bundle. |
| metatag_token_listC | List available metatag tokens. |
| metatag_canonical_setC | Set canonical URL for an entity. |
| metatag_jsonld_generateC | Generate JSON-LD structured data for entity. |
| commerce_store_listC | List all commerce stores. |
| commerce_store_getC | Get a single commerce store by ID. |
| commerce_store_createC | Create a new commerce store. |
| commerce_store_updateC | Update a commerce store. |
| commerce_product_listC | List commerce products. |
| commerce_product_getB | Get a single commerce product by ID. |
| commerce_product_createC | Create a new commerce product. |
| commerce_product_updateC | Update a commerce product. |
| commerce_order_listC | List commerce orders. |
| commerce_order_getC | Get a single commerce order by ID. |
| commerce_order_createC | Create a new commerce order. |
| commerce_order_updateD | Update a commerce order. |
| commerce_payment_gateway_listC | List payment gateways. |
| commerce_payment_gateway_getC | Get a single payment gateway by ID. |
| commerce_promotion_listC | List commerce promotions. |
| commerce_promotion_createC | Create a new commerce promotion. |
| commerce_shipping_method_listC | List shipping methods. |
| commerce_shipping_method_createC | Create a new shipping method. |
| webform_listC | List all webforms. |
| webform_getC | Get a single webform by ID. |
| webform_createC | Create a new webform. |
| webform_updateD | Update a webform. |
| webform_deleteC | Delete a webform. |
| webform_submission_listC | List webform submissions. |
| webform_submission_getC | Get a single webform submission by ID. |
| webform_submission_deleteC | Delete a webform submission. |
| webform_element_listB | List elements in a webform. |
| webform_element_createC | Add an element to a webform. |
| webform_handler_listB | List the handlers attached to a webform. Handlers are plugins configured on the webform, not entities, so there
is no |
| webform_handler_createA | Create a webform handler (email, remote post, etc.). A handler is a plugin held inside the webform's own configuration --
there is no
|
| webform_handler_updateA | Update a webform handler. Handlers have no entity id of their own, so this finds the webform
that owns
|
| webform_handler_deleteB | Delete a webform handler from its webform. Removes it the way Webform's own delete form does -- through
|
| webform_token_listC | List available webform tokens. |
| webform_export_submissionsC | Export webform submissions. |
| jsonapi_schema_getC | Get JSON:API schema (OpenAPI/Swagger). |
| jsonapi_include_optimizeC | Get optimized include paths for entity type. |
| jsonapi_sparse_fieldsetsC | Get entity with sparse fieldsets (only requested fields). |
| graphql_schema_getC | Get GraphQL schema. |
| graphql_queryC | Execute a GraphQL query. |
| graphql_schema_extendC | Extend GraphQL schema with custom fields (requires schema customization module). |
| nextjs_helpers_generateC | Generate Next.js helper functions for Drupal entities. |
| gatsby_helpers_generateC | Generate Gatsby source plugin config and helpers. |
| jsonapi_resources_listC | List all available JSON:API resources. |
| jsonapi_resource_typesB | Get all resource types available in JSON:API. |
| test_run_phpunitC | Run PHPUnit tests. |
| test_run_kernelD | Run Kernel tests. |
| test_run_behatC | Run Behat tests. |
| test_run_nightwatchC | Run Nightwatch tests. |
| test_scaffold_phpunitC | Scaffold a PHPUnit test class. |
| test_scaffold_behatC | Scaffold a Behat feature file. |
| test_scaffold_nightwatchC | Scaffold a Nightwatch test. |
| test_coverage_reportC | Generate test coverage report. |
| test_list_suitesB | List available test suites. |
| accessibility_axe_scanC | Run axe-core accessibility scan on a URL. |
| accessibility_wcag_checkC | Check WCAG compliance for entity content. |
| accessibility_color_contrastB | Check color contrast ratio. Pure arithmetic: it deliberately does not touch the site, so it works without Drush configured. |
| accessibility_aria_validateC | Validate ARIA attributes on entity. |
| accessibility_report_generateC | Generate comprehensive accessibility report. |
| performance_query_logC | Get slow query log. |
| performance_cache_statsB | Get cache performance statistics. |
| performance_redis_infoB | Get Redis server info. |
| performance_bigpipe_statusB | Check BigPipe status and configuration. |
| performance_bigpipe_enableC | Enable or disable BigPipe. |
| performance_memcached_statsC | Get Memcached statistics. |
| performance_page_load_analyzeC | Analyze page load performance. |
| contact_form_listC | List all contact forms. |
| contact_form_getC | Get a single contact form by ID. |
| contact_form_createC | Create a new contact form. |
| contact_form_updateD | Update a contact form. |
| contact_form_deleteC | Delete a contact form. |
| contact_message_listC | List contact form submissions. |
| contact_message_getC | Get a single contact message by ID. |
| contact_message_deleteC | Delete a contact message. |
| contact_spam_checkC | Check if a contact message is spam. |
| comment_listD | List comments. |
| comment_getC | Get a single comment by ID. |
| comment_createC | Create a new comment. |
| comment_updateC | Update a comment. |
| comment_deleteC | Delete a comment. |
| comment_thread_listC | List comment thread for an entity. Returns the whole thread, replies included. It used to add
|
| comment_approveB | Approve a comment (set status to published). |
| comment_unapproveB | Unapprove a comment (set status to unpublished). |
| comment_field_settingsC | Get comment field settings for entity type/bundle. |
| comment_field_configureD | Configure comment field settings. |
| feeds_feed_listC | List all feeds. |
| feeds_feed_getC | Get a single feed by ID. |
| feeds_feed_createC | Create a new feed. |
| feeds_feed_updateD | Update a feed. |
| feeds_feed_deleteC | Delete a feed. |
| feeds_importC | Run a feed import. |
| feeds_import_statusC | Get feed import status. |
| feeds_log_listA | List feed import logs. Superseded by |
| feeds_tamper_listB | List tamper plugins for a feed. |
| feeds_parser_listA | List available feed parsers. |
| feeds_fetcher_listB | List available feed fetchers. |
| feeds_processor_listB | List available feed processors. |
| export_nodesA | Export a node inventory to a CSV or Excel file on disk. Writes one row per node (id, type, title, status, dates, author, path) and returns only the file path and statistics, so a 5,000-node audit never has to travel through the conversation. The data comes from JSON:API, so titles and bodies with newlines or accents survive intact. content_type limits the export to one bundle (for example "article"); unpublished nodes are left out unless asked for. With include_fields a final fields column carries the node's remaining field values as JSON, each string capped at 5000 characters. limit caps the rows written (0 = no cap, 100000 maximum). format is "csv" (UTF-8 with BOM, opens cleanly in Excel) or "xlsx". The file may be written only inside the Drupal root, the system temp directory, or your home directory; without output_path it lands in {Drupal root}/exports/ or /tmp/drupal-mcp-exports/ with a timestamped name. |
| export_usersA | Export the site's user accounts to a CSV or Excel file on disk. One row per user: id, name, email, active/blocked status, role labels, registration/last-login dates. Blocked accounts are always included (their status column says so) - an audit needs them. The file lands in {Drupal root}/exports/ or /tmp/drupal-mcp-exports/ unless output_path says otherwise (confined to the Drupal root, the temp directory, or your home). Drupal's uid-0 anonymous pseudo-account carries no id attributes and is skipped rather than exported as a row of nulls (see skipped_without_id). |
| export_mediaB | Export the media library to a CSV or Excel file on disk. One row per media item: id, bundle, name, status, dates, owner, and the managed file's filename and URI when there is one (found through relationships, so renamed file fields still work). media_type limits the export to a bundle such as "image". Empty sites write nothing and say so. |
| export_taxonomyA | Export taxonomy terms to a CSV or Excel file on disk. One row per term: id, vocabulary, name, description, weight, status, and - with include_usage (the default) - how many entities reference the term, through which fields, and a safe_to_delete verdict ("yes" only when nothing references it, and withheld entirely whenever some field could not be counted). Usage comes from one COUNT query per field storage targeting taxonomy terms, so a 5,000-term vocabulary costs a handful of queries, not 5,000. vocabulary limits the export to one vocabulary machine name (for example "tags"). When Drush is unavailable the export still succeeds and says the usage columns are empty. |
| theme_activeA | List the site's themes: default, admin, and every enabled one. Reads system.theme and |
| theme_infoA | Describe one theme: metadata, base-theme chain, regions, libraries. Combines |
| theme_regionsA | Region layout of a theme with the blocks placed in each one. Regions come from the theme's info.yml in declaration order; each carries its blocks (label, plugin, weight, enabled state) and a count, so empty regions and placements in regions the theme no longer defines are both visible at a glance. Needs DRUPAL_ROOT (info.yml) and the JSON:API client (block placements). |
| theme_blocksA | List placed blocks with optional theme, region, and text filters. Reads every block.block.* placement from JSON:API: id, theme, region, label, plugin, weight, and enabled state. search matches label and plugin case-insensitively (the "do we have a block like Site branding?" question); theme_name and region narrow the list to one placement set. With no filters every placement on the site is returned, most specific sort first (theme, region, weight). |
| theme_templatesA | List a theme's Twig templates ( Walks the theme directory on the local docroot (symlinks skipped, nothing outside DRUPAL_ROOT reported). pattern is a case-insensitive substring matched against the template name — "node--", "views", "field" — to narrow the list. Returns docroot-relative paths and byte sizes, sorted. |
| theme_template_overridesB | Which core/module templates a theme overrides, and which it invented. For every Twig file in the theme, the docroot is indexed once for files with the same name outside that theme; a match means the theme's copy wins at render time (an override), no match means a theme-original template. Returns both lists with paths, plus how many Twig files were scanned. Requires DRUPAL_ROOT. |
| template_suggestionsA | Twig template names Drupal will try for an entity, specific first. The suggestion chain for node, block, taxonomy_term, user, field, or page rendering (bracketed parts are placeholders Drupal fills in, e.g. node--article--123.html.twig beats node--article.html.twig). Unknown entity types get the generic chain. When DRUPAL_ROOT is configured each suggestion is marked in_checked_theme: whether the default theme already ships that file, so you know which name creating one would actually take effect. |
| view_template_infoA | Template names for overriding a Views display, verified against the site. Looks the view up in the JSON:API view collection by its machine id (drupal_internal__id), so the display list is real: with display_id the chain starts at views-view--NAME--DISPLAY and falls back to the whole view; without it every display gets an entry, then the views-view base template. An unknown view errors with the views the site has, an unknown display_id with the displays that view has, and suggestions are marked in_checked_theme when the default theme's templates can be read (DRUPAL_ROOT). Views config changed names between Drupal generations (view.* on older sites, views.view.* on Drupal 11.4+), so the collection — addressed by entity id — is the stable source. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 414 tools
With 414 tools, many overlap heavily: cron_run vs drush_cron, cache_rebuild vs cache_clear, security_audit vs security_scan vs code_security_scan, and ai_analyze_content_quality vs analyze_content_quality are just a few examples. The CRUD families for each Drupal entity are distinct, but the sheer number of near-duplicates makes selection error-prone.
Most names are snake_case and readable, but the verb/noun ordering is inconsistent: create_node uses verb_noun, while commerce_store_list and webform_submission_list use noun_verb. Mixed prefixed families and occasional abbreviations keep this from being fully predictable.
414 tools is an extreme mismatch for a Drupal MCP server. Even a comprehensive site-management surface should be far smaller; this count guarantees heavy redundancy and makes tool discovery impractical for an agent.
The surface covers an enormous range of Drupal domains: content, taxonomy, users, config, migrations, testing, accessibility, performance, commerce, webforms, search, and translation. Some lifecycle gaps exist (e.g. no delete for several commerce entities), but most major workflows have some supporting tool.