drupal-mcp-connector 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.claude/commands/drupal-audit-config-best-practices.md +16 -0
  2. package/.claude/commands/drupal-audit-site-health.md +19 -0
  3. package/.claude/commands/drupal-block-user.md +20 -0
  4. package/.claude/commands/drupal-bulk-create.md +21 -0
  5. package/.claude/commands/drupal-bulk-update.md +21 -0
  6. package/.claude/commands/drupal-config-get.md +19 -0
  7. package/.claude/commands/drupal-config-list.md +17 -0
  8. package/.claude/commands/drupal-config-set.md +20 -0
  9. package/.claude/commands/drupal-content-by-moderation-state.md +22 -0
  10. package/.claude/commands/drupal-create-block.md +21 -0
  11. package/.claude/commands/drupal-create-media.md +22 -0
  12. package/.claude/commands/drupal-create-menu-link.md +24 -0
  13. package/.claude/commands/drupal-create-node.md +28 -0
  14. package/.claude/commands/drupal-create-paragraph.md +20 -0
  15. package/.claude/commands/drupal-create-redirect.md +22 -0
  16. package/.claude/commands/drupal-create-taxonomy-term.md +23 -0
  17. package/.claude/commands/drupal-create-translation.md +23 -0
  18. package/.claude/commands/drupal-create-user.md +24 -0
  19. package/.claude/commands/drupal-delete-media.md +22 -0
  20. package/.claude/commands/drupal-delete-node.md +23 -0
  21. package/.claude/commands/drupal-delete-taxonomy-term.md +22 -0
  22. package/.claude/commands/drupal-describe-fields.md +21 -0
  23. package/.claude/commands/drupal-drush-cache-rebuild.md +16 -0
  24. package/.claude/commands/drupal-drush-config-export.md +16 -0
  25. package/.claude/commands/drupal-drush-config-import.md +16 -0
  26. package/.claude/commands/drupal-drush-config-status.md +16 -0
  27. package/.claude/commands/drupal-drush-cron.md +16 -0
  28. package/.claude/commands/drupal-drush-module-disable.md +21 -0
  29. package/.claude/commands/drupal-drush-module-enable.md +19 -0
  30. package/.claude/commands/drupal-drush-module-list.md +17 -0
  31. package/.claude/commands/drupal-drush-security-updates.md +16 -0
  32. package/.claude/commands/drupal-drush-sql-query.md +19 -0
  33. package/.claude/commands/drupal-drush-status.md +16 -0
  34. package/.claude/commands/drupal-drush-updatedb.md +16 -0
  35. package/.claude/commands/drupal-drush-user-create.md +22 -0
  36. package/.claude/commands/drupal-drush-user-list.md +19 -0
  37. package/.claude/commands/drupal-drush-watchdog.md +19 -0
  38. package/.claude/commands/drupal-entity-create.md +24 -0
  39. package/.claude/commands/drupal-entity-delete.md +24 -0
  40. package/.claude/commands/drupal-entity-get.md +22 -0
  41. package/.claude/commands/drupal-entity-list.md +25 -0
  42. package/.claude/commands/drupal-entity-update.md +25 -0
  43. package/.claude/commands/drupal-find-orphaned-media.md +18 -0
  44. package/.claude/commands/drupal-get-entity-schema.md +20 -0
  45. package/.claude/commands/drupal-get-media.md +20 -0
  46. package/.claude/commands/drupal-get-node.md +20 -0
  47. package/.claude/commands/drupal-get-paragraph.md +20 -0
  48. package/.claude/commands/drupal-get-revision.md +21 -0
  49. package/.claude/commands/drupal-get-taxonomy-term.md +20 -0
  50. package/.claude/commands/drupal-get-taxonomy-terms.md +21 -0
  51. package/.claude/commands/drupal-get-user-by-name.md +19 -0
  52. package/.claude/commands/drupal-get-user.md +19 -0
  53. package/.claude/commands/drupal-graphql-introspect.md +17 -0
  54. package/.claude/commands/drupal-graphql.md +40 -0
  55. package/.claude/commands/drupal-list-blocks.md +20 -0
  56. package/.claude/commands/drupal-list-content-types.md +16 -0
  57. package/.claude/commands/drupal-list-entity-types.md +16 -0
  58. package/.claude/commands/drupal-list-media-types.md +16 -0
  59. package/.claude/commands/drupal-list-media.md +21 -0
  60. package/.claude/commands/drupal-list-menu-links.md +20 -0
  61. package/.claude/commands/drupal-list-moderation-states.md +20 -0
  62. package/.claude/commands/drupal-list-nodes.md +24 -0
  63. package/.claude/commands/drupal-list-revisions.md +20 -0
  64. package/.claude/commands/drupal-list-roles.md +16 -0
  65. package/.claude/commands/drupal-list-sites.md +10 -0
  66. package/.claude/commands/drupal-list-translations.md +21 -0
  67. package/.claude/commands/drupal-list-users.md +20 -0
  68. package/.claude/commands/drupal-list-vocabularies.md +16 -0
  69. package/.claude/commands/drupal-mcp-whoami.md +16 -0
  70. package/.claude/commands/drupal-report-404-log.md +17 -0
  71. package/.claude/commands/drupal-report-accessibility-audit.md +18 -0
  72. package/.claude/commands/drupal-report-alias-coverage.md +18 -0
  73. package/.claude/commands/drupal-report-broken-embeds.md +18 -0
  74. package/.claude/commands/drupal-report-broken-links.md +20 -0
  75. package/.claude/commands/drupal-report-cache-config.md +16 -0
  76. package/.claude/commands/drupal-report-config-drift.md +16 -0
  77. package/.claude/commands/drupal-report-content-by-author.md +18 -0
  78. package/.claude/commands/drupal-report-content-summary.md +16 -0
  79. package/.claude/commands/drupal-report-duplicate-content.md +18 -0
  80. package/.claude/commands/drupal-report-field-completeness.md +21 -0
  81. package/.claude/commands/drupal-report-menu-integrity.md +17 -0
  82. package/.claude/commands/drupal-report-missing-field.md +21 -0
  83. package/.claude/commands/drupal-report-module-audit.md +16 -0
  84. package/.claude/commands/drupal-report-orphan-pages.md +18 -0
  85. package/.claude/commands/drupal-report-orphaned-references.md +18 -0
  86. package/.claude/commands/drupal-report-permission-audit.md +16 -0
  87. package/.claude/commands/drupal-report-pii-exposure.md +19 -0
  88. package/.claude/commands/drupal-report-readability.md +19 -0
  89. package/.claude/commands/drupal-report-recently-published.md +18 -0
  90. package/.claude/commands/drupal-report-redirect-health.md +17 -0
  91. package/.claude/commands/drupal-report-revision-hotspots.md +18 -0
  92. package/.claude/commands/drupal-report-scheduled-content.md +18 -0
  93. package/.claude/commands/drupal-report-seo-audit.md +18 -0
  94. package/.claude/commands/drupal-report-seo-meta-coverage.md +19 -0
  95. package/.claude/commands/drupal-report-stale-content.md +20 -0
  96. package/.claude/commands/drupal-report-status-report.md +17 -0
  97. package/.claude/commands/drupal-report-taxonomy-usage.md +22 -0
  98. package/.claude/commands/drupal-report-text-format-audit.md +16 -0
  99. package/.claude/commands/drupal-report-translation-coverage.md +19 -0
  100. package/.claude/commands/drupal-report-unpublished.md +18 -0
  101. package/.claude/commands/drupal-report-user-activity.md +18 -0
  102. package/.claude/commands/drupal-report-workflow-bottlenecks.md +20 -0
  103. package/.claude/commands/drupal-resolve-reference.md +22 -0
  104. package/.claude/commands/drupal-revert-revision.md +21 -0
  105. package/.claude/commands/drupal-schedule-publish.md +22 -0
  106. package/.claude/commands/drupal-search-content.md +22 -0
  107. package/.claude/commands/drupal-search.md +21 -0
  108. package/.claude/commands/drupal-security-info.md +16 -0
  109. package/.claude/commands/drupal-set-moderation-state.md +21 -0
  110. package/.claude/commands/drupal-site-info.md +16 -0
  111. package/.claude/commands/drupal-update-media.md +23 -0
  112. package/.claude/commands/drupal-update-menu-link.md +25 -0
  113. package/.claude/commands/drupal-update-node.md +29 -0
  114. package/.claude/commands/drupal-update-paragraph.md +21 -0
  115. package/.claude/commands/drupal-update-redirect.md +22 -0
  116. package/.claude/commands/drupal-update-taxonomy-term.md +23 -0
  117. package/.claude/commands/drupal-update-user.md +25 -0
  118. package/.claude/commands/drupal-upload-file-and-create-media.md +24 -0
  119. package/.claude/commands/drupal-upload-file.md +22 -0
  120. package/CHANGELOG.md +122 -0
  121. package/README.md +27 -1
  122. package/package.json +4 -1
  123. package/scripts/generate-commands.js +118 -0
  124. package/src/index.js +30 -79
  125. package/src/lib/backends/index.js +87 -45
  126. package/src/lib/backends/jsonapi.js +9 -4
  127. package/src/lib/entity-response.js +46 -0
  128. package/src/lib/metatag-audit.js +117 -0
  129. package/src/lib/operations.js +57 -0
  130. package/src/lib/security.js +39 -0
  131. package/src/lib/tool-prompts.js +145 -0
  132. package/src/tools/bulk.js +3 -1
  133. package/src/tools/config.js +4 -3
  134. package/src/tools/entities.js +10 -5
  135. package/src/tools/fields.js +20 -7
  136. package/src/tools/index.js +51 -0
  137. package/src/tools/nodes.js +29 -16
  138. package/src/tools/reports.js +67 -13
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Lint key configuration for production-readiness and security: on-screen error display, CSS/JS aggregation, anonymous page cache, open user registration, missing 404/403 pages, and insecure file uploads. Severity-ranked. Requires config-read access and the server-tool bridge."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_audit_config_best_practices
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_audit_config_best_practices` MCP tool.
8
+
9
+ Lint key configuration for production-readiness and security: on-screen error display, CSS/JS aggregation, anonymous page cache, open user registration, missing 404/403 pages, and insecure file uploads. Severity-ranked. Requires config-read access and the server-tool bridge.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: "Composite site-health dashboard: runs a battery of content, link, and configuration audits and rolls them into one scored report with a letter grade. Each section degrades independently — gated/errored sections are recorded, not fatal. Read-only."
3
+ argument-hint: "[site] [type] [sampleSize] [sections]"
4
+ allowed-tools: mcp__drupal__drupal_audit_site_health
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_audit_site_health` MCP tool.
8
+
9
+ Composite site-health dashboard: runs a battery of content, link, and configuration audits and rolls them into one scored report with a letter grade. Each section degrades independently — gated/errored sections are recorded, not fatal. Read-only.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+ - `type` (string): Primary content type for content/link sections (default: article)
16
+ - `sampleSize` (number): Per-section scan cap (kept small for a fast roll-up)
17
+ - `sections` (array (pass as JSON)): Subset of sections to run (default: all). Available: content_summary, stale_content, seo_audit, accessibility, duplicate_content, readability, pii_exposure, broken_links, redirect_health, alias_coverage, log_404, config_best_practices, module_audit, permission_audit
18
+
19
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: "Block or unblock a Drupal user account without deleting it."
3
+ argument-hint: "<id> [site] [block]"
4
+ allowed-tools: mcp__drupal__drupal_block_user
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_block_user` MCP tool.
8
+
9
+ Block or unblock a Drupal user account without deleting it.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `id` (string): User UUID
15
+
16
+ **Optional:**
17
+ - `site` (string): omit for the default site
18
+ - `block` (boolean (true/false)): true = block, false = unblock
19
+
20
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Create many entities of a single type + bundle in one call. Permission is checked once; each item is created independently, so the batch continues past individual failures (partial success). Returns per-item { index, success, id | error } and a summary { created, failed }. Writes default to unpublished/draft."
3
+ argument-hint: "<entityType> <bundle> <items> [site]"
4
+ allowed-tools: mcp__drupal__drupal_bulk_create
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_bulk_create` MCP tool.
8
+
9
+ Create many entities of a single type + bundle in one call. Permission is checked once; each item is created independently, so the batch continues past individual failures (partial success). Returns per-item { index, success, id | error } and a summary { created, failed }. Writes default to unpublished/draft.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `entityType` (string): Entity type machine name, e.g. 'node', 'taxonomy_term'
15
+ - `bundle` (string): Bundle machine name, e.g. 'article'
16
+ - `items` (array (pass as JSON)): Entities to create. Each is { attributes?, relationships? }.
17
+
18
+ **Optional:**
19
+ - `site` (string): omit for the default site
20
+
21
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Update many entities of a single type + bundle in one call. Permission is checked once; each item is updated independently, so the batch continues past individual failures (partial success). Each item requires an 'id' (UUID); items missing an id are reported as per-item failures. Returns per-item { index, success, id | error } and a summary { updated, failed }."
3
+ argument-hint: "<entityType> <bundle> <items> [site]"
4
+ allowed-tools: mcp__drupal__drupal_bulk_update
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_bulk_update` MCP tool.
8
+
9
+ Update many entities of a single type + bundle in one call. Permission is checked once; each item is updated independently, so the batch continues past individual failures (partial success). Each item requires an 'id' (UUID); items missing an id are reported as per-item failures. Returns per-item { index, success, id | error } and a summary { updated, failed }.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `entityType` (string): Entity type machine name
15
+ - `bundle` (string): Bundle machine name
16
+ - `items` (array (pass as JSON)): Entities to update. Each is { id, attributes?, relationships? }.
17
+
18
+ **Optional:**
19
+ - `site` (string): omit for the default site
20
+
21
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: "Read a single Drupal configuration object by name (e.g. \"system.site\") via the governed server-side config tool. Requires config read access."
3
+ argument-hint: "<name> [site]"
4
+ allowed-tools: mcp__drupal__drupal_config_get
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_config_get` MCP tool.
8
+
9
+ Read a single Drupal configuration object by name (e.g. "system.site") via the governed server-side config tool. Requires config read access.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `name` (string)
15
+
16
+ **Optional:**
17
+ - `site` (string): omit for the default site
18
+
19
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,17 @@
1
+ ---
2
+ description: "List Drupal configuration object names, optionally filtered by a name prefix, via the governed server-side config tool. Requires config read access."
3
+ argument-hint: "[site] [prefix]"
4
+ allowed-tools: mcp__drupal__drupal_config_list
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_config_list` MCP tool.
8
+
9
+ List Drupal configuration object names, optionally filtered by a name prefix, via the governed server-side config tool. Requires config read access.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+ - `prefix` (string)
16
+
17
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: "Set a Drupal configuration value via the governed server-side config tool. Audited and gated server-side; requires the config-editor (Developer) tier. Then export to YAML for a PR."
3
+ argument-hint: "<name> <value> [site]"
4
+ allowed-tools: mcp__drupal__drupal_config_set
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_config_set` MCP tool.
8
+
9
+ Set a Drupal configuration value via the governed server-side config tool. Audited and gated server-side; requires the config-editor (Developer) tier. Then export to YAML for a PR.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `name` (string)
15
+ - `value` (object (pass as JSON)): A map of top-level config keys to their new values (e.g. { "slogan": "Information Technology" }). Other keys in the object are preserved server-side.
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+
20
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: "List nodes of a content type currently in a given moderation state (e.g. what is in 'draft' or 'needs_review')."
3
+ argument-hint: "<type> <state> [site] [limit] [offset]"
4
+ allowed-tools: mcp__drupal__drupal_content_by_moderation_state
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_content_by_moderation_state` MCP tool.
8
+
9
+ List nodes of a content type currently in a given moderation state (e.g. what is in 'draft' or 'needs_review').
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `type` (string): Content type machine name
15
+ - `state` (string): Moderation state machine name
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `limit` (number)
20
+ - `offset` (number)
21
+
22
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Create a custom content block of a given block type (bundle). 'info' is the administrative label; 'body' is optional rendered HTML. Checked against the site security config."
3
+ argument-hint: "<type> <info> [site] [body]"
4
+ allowed-tools: mcp__drupal__drupal_create_block
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_block` MCP tool.
8
+
9
+ Create a custom content block of a given block type (bundle). 'info' is the administrative label; 'body' is optional rendered HTML. Checked against the site security config.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `type` (string): Block type (bundle) machine name, e.g. 'basic'
15
+ - `info` (string): Administrative label / block description
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `body` (string): Block body HTML (optional)
20
+
21
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: "Create a media entity. For remote video (YouTube/Vimeo), pass the URL via fields.field_media_oembed_video. For file-based media, use drupal_upload_file first to get a file UUID, then pass it in fields."
3
+ argument-hint: "<type> <name> [site] [status] [fields]"
4
+ allowed-tools: mcp__drupal__drupal_create_media
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_media` MCP tool.
8
+
9
+ Create a media entity. For remote video (YouTube/Vimeo), pass the URL via fields.field_media_oembed_video. For file-based media, use drupal_upload_file first to get a file UUID, then pass it in fields.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `type` (string): Media type machine name
15
+ - `name` (string): Media entity name / label
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `status` (boolean (true/false))
20
+ - `fields` (object (pass as JSON)): Additional field values — include the source field (e.g. field_media_oembed_video: 'https://youtu.be/...')
21
+
22
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: "Create a custom menu link, enabled by default so it renders immediately. The link target is a Drupal URI such as 'internal:/about', 'entity:node/42', or an absolute 'https://…' URL — prefer 'entity:node/<id>' when linking to a node (avoids the alias-resolution 'path inaccessible' race). Set 'parent' (a parent link plugin id like 'menu_link_content:<uuid>') to nest the link, and 'enabled: false' to create it disabled. Checked against the site security config."
3
+ argument-hint: "<title> <link> <menu> [site] [weight] [parent] [enabled]"
4
+ allowed-tools: mcp__drupal__drupal_create_menu_link
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_menu_link` MCP tool.
8
+
9
+ Create a custom menu link, enabled by default so it renders immediately. The link target is a Drupal URI such as 'internal:/about', 'entity:node/42', or an absolute 'https://…' URL — prefer 'entity:node/<id>' when linking to a node (avoids the alias-resolution 'path inaccessible' race). Set 'parent' (a parent link plugin id like 'menu_link_content:<uuid>') to nest the link, and 'enabled: false' to create it disabled. Checked against the site security config.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `title` (string): Link label shown in the menu
15
+ - `link` (string): Target URI, e.g. 'entity:node/42', 'internal:/about', or 'https://example.com'
16
+ - `menu` (string): Menu machine name to place the link in, e.g. 'main' or 'footer'
17
+
18
+ **Optional:**
19
+ - `site` (string): omit for the default site
20
+ - `weight` (number): Ordering weight within the menu (lower sorts first)
21
+ - `parent` (string): Parent link plugin id to nest under, e.g. 'menu_link_content:<uuid>'. Omit for a top-level link.
22
+ - `enabled` (boolean (true/false)): Whether the link is enabled (renders). Defaults to true.
23
+
24
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,28 @@
1
+ ---
2
+ description: "Create a new content node. Returns the new node UUID, integer ID, and URL. For content types under an editorial (content_moderation) workflow, set moderationState (e.g. 'draft'/'published') instead of status. Entity-reference fields (taxonomy terms, related content, media) go in `relationships`, not `fields`."
3
+ argument-hint: "<type> <title> [site] [body] [summary] [status] [moderationState] [fields] [relationships] [dryRun] [returning]"
4
+ allowed-tools: mcp__drupal__drupal_create_node
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_node` MCP tool.
8
+
9
+ Create a new content node. Returns the new node UUID, integer ID, and URL. For content types under an editorial (content_moderation) workflow, set moderationState (e.g. 'draft'/'published') instead of status. Entity-reference fields (taxonomy terms, related content, media) go in `relationships`, not `fields`.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `type` (string): Content type machine name
15
+ - `title` (string)
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `body` (string): Body field HTML
20
+ - `summary` (string): Body summary / teaser
21
+ - `status` (boolean (true/false)): Published flag for NON-moderated types. true to publish immediately. Ignored if moderationState is set; on a moderated type it is dropped automatically.
22
+ - `moderationState` (string): Moderation state for content_moderation types, e.g. 'draft' or 'published'. Takes precedence over status.
23
+ - `fields` (object (pass as JSON)): Scalar/attribute field values keyed by Drupal machine name. Do NOT put entity-reference fields here — Drupal rejects them as attributes; use `relationships`.
24
+ - `relationships` (object (pass as JSON)): Entity-reference fields as JSON:API relationships, keyed by field machine name. Single-value: { field_resource_type: { data: { type: 'taxonomy_term--resource_type', id: '<uuid>' } } }. Multi-value: { field_tags: { data: [{ type: 'taxonomy_term--tags', id: '<uuid>' }] } }.
25
+ - `dryRun` (boolean (true/false)): Validate and return a preview of the write without committing.
26
+ - `returning` (string): Response verbosity. "full" (default) returns the complete saved entity; "minimal" returns just identity + state (id, type, bundle, title, status, changed, url) — much smaller, recommended for bulk writes where the echoed body would dominate the response.
27
+
28
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: "Create a Paragraph entity of a given paragraph type (bundle). Paragraphs are content fragments that are NOT standalone — they must be referenced by a host entity's paragraph / Entity Reference Revisions field. Returns the created paragraph plus `relationshipData` ({ type: 'paragraph--<bundle>', id: <uuid> }) to drop into a host field's relationships via drupal_entity_update / drupal_update_node. Use drupal_get_entity_schema (entityType 'paragraph', the bundle) first to discover fields. Governed by the site security policy."
3
+ argument-hint: "<paragraphType> [site] [attributes]"
4
+ allowed-tools: mcp__drupal__drupal_create_paragraph
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_paragraph` MCP tool.
8
+
9
+ Create a Paragraph entity of a given paragraph type (bundle). Paragraphs are content fragments that are NOT standalone — they must be referenced by a host entity's paragraph / Entity Reference Revisions field. Returns the created paragraph plus `relationshipData` ({ type: 'paragraph--<bundle>', id: <uuid> }) to drop into a host field's relationships via drupal_entity_update / drupal_update_node. Use drupal_get_entity_schema (entityType 'paragraph', the bundle) first to discover fields. Governed by the site security policy.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `paragraphType` (string): Paragraph type / bundle machine name, e.g. 'text', 'image', 'cta'
15
+
16
+ **Optional:**
17
+ - `site` (string): Named site (omit for default)
18
+ - `attributes` (object (pass as JSON)): Paragraph field values keyed by Drupal machine name, e.g. { field_body: { value: '<p>..</p>', format: 'full_html' } }
19
+
20
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: "Create an active URL redirect (contrib Redirect module). The redirect serves its 301 (or chosen code) immediately: 'source' is the old path (a leading slash is fine — it is normalized to the module's stored, slash-less form so the redirect actually matches and fires), and 'target' is the destination as a path ('/new'), an 'entity:node/ID', or an absolute URL. status_code defaults to 301; pass 302 for a temporary redirect. Governed by the site security policy (needs redirect write / 'administer redirects')."
3
+ argument-hint: "<source> <target> [site] [statusCode] [language]"
4
+ allowed-tools: mcp__drupal__drupal_create_redirect
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_redirect` MCP tool.
8
+
9
+ Create an active URL redirect (contrib Redirect module). The redirect serves its 301 (or chosen code) immediately: 'source' is the old path (a leading slash is fine — it is normalized to the module's stored, slash-less form so the redirect actually matches and fires), and 'target' is the destination as a path ('/new'), an 'entity:node/ID', or an absolute URL. status_code defaults to 301; pass 302 for a temporary redirect. Governed by the site security policy (needs redirect write / 'administer redirects').
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `source` (string): Source/old path to redirect from, e.g. '/old-slug'. Leading slash optional.
15
+ - `target` (string): Destination: a path ('/new-slug'), 'entity:node/42', or an absolute 'https://…' URL.
16
+
17
+ **Optional:**
18
+ - `site` (string): Named site (omit for default)
19
+ - `statusCode` (number): HTTP redirect status code. 301 (permanent, default) or 302 (temporary); 303/307/308 also accepted.
20
+ - `language` (string): Langcode the redirect applies to. Defaults to 'und' (all languages).
21
+
22
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: "Create a new taxonomy term in a vocabulary."
3
+ argument-hint: "<vocabulary> <name> [site] [description] [weight] [parentId]"
4
+ allowed-tools: mcp__drupal__drupal_create_taxonomy_term
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_taxonomy_term` MCP tool.
8
+
9
+ Create a new taxonomy term in a vocabulary.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `vocabulary` (string)
15
+ - `name` (string)
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `description` (string)
20
+ - `weight` (number)
21
+ - `parentId` (string): UUID of parent term (for hierarchical vocabularies)
22
+
23
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: "Create or replace a translation of a Drupal entity for a target language (governed write). Sets the given langcode plus the supplied translated field values. Requires the content_translation module enabled and the bundle configured as translatable; otherwise Drupal rejects the write. Defaults to node."
3
+ argument-hint: "<type> <id> <langcode> [site] [entityType] [attributes]"
4
+ allowed-tools: mcp__drupal__drupal_create_translation
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_translation` MCP tool.
8
+
9
+ Create or replace a translation of a Drupal entity for a target language (governed write). Sets the given langcode plus the supplied translated field values. Requires the content_translation module enabled and the bundle configured as translatable; otherwise Drupal rejects the write. Defaults to node.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `type` (string): Bundle machine name, e.g. 'article'
15
+ - `id` (string): Entity UUID
16
+ - `langcode` (string): Target language code, e.g. 'de', 'fr', 'pt_br'
17
+
18
+ **Optional:**
19
+ - `site` (string): omit for the default site
20
+ - `entityType` (string): Entity type machine name. Default: 'node'.
21
+ - `attributes` (object (pass as JSON)): Translated field values keyed by Drupal machine name
22
+
23
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,24 @@
1
+ ---
2
+ description: "Create a new Drupal user account with optional roles and password."
3
+ argument-hint: "<name> <mail> [site] [password] [status] [roles] [timezone]"
4
+ allowed-tools: mcp__drupal__drupal_create_user
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_create_user` MCP tool.
8
+
9
+ Create a new Drupal user account with optional roles and password.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `name` (string): Username
15
+ - `mail` (string): Email address
16
+
17
+ **Optional:**
18
+ - `site` (string): omit for the default site
19
+ - `password` (string): Initial password (plaintext — sent over HTTPS)
20
+ - `status` (boolean (true/false)): true = active (default)
21
+ - `roles` (array (pass as JSON)): Role UUIDs to assign
22
+ - `timezone` (string)
23
+
24
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: "Delete a media entity. Does not delete the underlying File entity. Confirm with the user before calling."
3
+ argument-hint: "<type> <id> [site]"
4
+ allowed-tools: mcp__drupal__drupal_delete_media
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_delete_media` MCP tool.
8
+
9
+ Delete a media entity. Does not delete the underlying File entity. Confirm with the user before calling.
10
+
11
+ > ⚠ **Destructive** — this permanently changes or deletes data. Confirm with the user before calling.
12
+
13
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
14
+
15
+ **Required:**
16
+ - `type` (string)
17
+ - `id` (string)
18
+
19
+ **Optional:**
20
+ - `site` (string): omit for the default site
21
+
22
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: "Permanently delete a node. Irreversible — confirm with the user before calling."
3
+ argument-hint: "<type> <id> [site] [dryRun]"
4
+ allowed-tools: mcp__drupal__drupal_delete_node
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_delete_node` MCP tool.
8
+
9
+ Permanently delete a node. Irreversible — confirm with the user before calling.
10
+
11
+ > ⚠ **Destructive** — this permanently changes or deletes data. Confirm with the user before calling.
12
+
13
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
14
+
15
+ **Required:**
16
+ - `type` (string)
17
+ - `id` (string): Node UUID
18
+
19
+ **Optional:**
20
+ - `site` (string): omit for the default site
21
+ - `dryRun` (boolean (true/false)): Validate and return a preview of the delete without committing.
22
+
23
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: "Delete a taxonomy term. Confirm with the user before calling."
3
+ argument-hint: "<vocabulary> <id> [site]"
4
+ allowed-tools: mcp__drupal__drupal_delete_taxonomy_term
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_delete_taxonomy_term` MCP tool.
8
+
9
+ Delete a taxonomy term. Confirm with the user before calling.
10
+
11
+ > ⚠ **Destructive** — this permanently changes or deletes data. Confirm with the user before calling.
12
+
13
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
14
+
15
+ **Required:**
16
+ - `vocabulary` (string)
17
+ - `id` (string)
18
+
19
+ **Optional:**
20
+ - `site` (string): omit for the default site
21
+
22
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Introspect the fields of a Drupal entity type + bundle: returns a per-field list of { name, type, kind, cardinality?, approximate }. Read-only. Built on schema SAMPLING (an existing entity), so results are approximate — only populated fields are visible and required/cardinality/allowedValues are inferred from value shape. Authoritative field metadata comes from the Drush bridge (Field API). Use this before creating/updating entities to learn field names."
3
+ argument-hint: "<site> [type] [entityType] [bundle]"
4
+ allowed-tools: mcp__drupal__drupal_describe_fields
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_describe_fields` MCP tool.
8
+
9
+ Introspect the fields of a Drupal entity type + bundle: returns a per-field list of { name, type, kind, cardinality?, approximate }. Read-only. Built on schema SAMPLING (an existing entity), so results are approximate — only populated fields are visible and required/cardinality/allowedValues are inferred from value shape. Authoritative field metadata comes from the Drush bridge (Field API). Use this before creating/updating entities to learn field names.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Required:**
14
+ - `site` (string): Configured site name.
15
+
16
+ **Optional:**
17
+ - `type` (string): Entity type machine name, e.g. 'node', 'taxonomy_term', 'user', 'media'. Alias: `entityType` (as used by the sibling tools).
18
+ - `entityType` (string): Alias for `type` — accepted for parity with get_entity_schema / entity_create / entity_update / resolve_reference.
19
+ - `bundle` (string): Bundle machine name, e.g. 'article'. Defaults to the entity type for single-bundle types (e.g. 'user').
20
+
21
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Run `drush cache:rebuild` via SSH. Clears all Drupal caches. Requires drushSsh config and write access."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_cache_rebuild
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_cache_rebuild` MCP tool.
8
+
9
+ Run `drush cache:rebuild` via SSH. Clears all Drupal caches. Requires drushSsh config and write access.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Export active configuration to the sync directory. Requires write access."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_config_export
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_config_export` MCP tool.
8
+
9
+ Export active configuration to the sync directory. Requires write access.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Import configuration from the sync directory into the database. Requires write access. Confirm with user before running on production."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_config_import
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_config_import` MCP tool.
8
+
9
+ Import configuration from the sync directory into the database. Requires write access. Confirm with user before running on production.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Check if active config is in sync with the sync directory. Returns out-of-sync items if any."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_config_status
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_config_status` MCP tool.
8
+
9
+ Check if active config is in sync with the sync directory. Returns out-of-sync items if any.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: "Run Drupal cron via `drush cron`."
3
+ argument-hint: "[site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_cron
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_cron` MCP tool.
8
+
9
+ Run Drupal cron via `drush cron`.
10
+
11
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
12
+
13
+ **Optional:**
14
+ - `site` (string): omit for the default site
15
+
16
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: "Uninstall a Drupal module. Irreversible for module-stored data. Confirm with user."
3
+ argument-hint: "<moduleName> [site]"
4
+ allowed-tools: mcp__drupal__drupal_drush_module_disable
5
+ ---
6
+
7
+ Call the `mcp__drupal__drupal_drush_module_disable` MCP tool.
8
+
9
+ Uninstall a Drupal module. Irreversible for module-stored data. Confirm with user.
10
+
11
+ > ⚠ **Destructive** — this permanently changes or deletes data. Confirm with the user before calling.
12
+
13
+ Parse the request in `$ARGUMENTS` into this tool's parameters:
14
+
15
+ **Required:**
16
+ - `moduleName` (string)
17
+
18
+ **Optional:**
19
+ - `site` (string): omit for the default site
20
+
21
+ If a required parameter is missing from `$ARGUMENTS`, ask before calling — do not invent values. Coerce each value to its JSON type (booleans → true/false, numbers → numeric, object/array → parse JSON), then make the single tool call and summarize the result.