drupal-mcp-server 0.1.0__tar.gz → 0.3.0__tar.gz
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.
- drupal_mcp_server-0.3.0/.codecov.yml +17 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/workflows/ci.yml +4 -1
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/workflows/docs.yml +9 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.gitignore +14 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/PKG-INFO +73 -15
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/README.md +71 -14
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0/docs}/CHANGELOG.md +106 -0
- drupal_mcp_server-0.3.0/docs/agents.md +221 -0
- drupal_mcp_server-0.3.0/docs/index.md +46 -0
- drupal_mcp_server-0.3.0/docs/migration.md +188 -0
- drupal_mcp_server-0.3.0/docs/quickstart.md +86 -0
- drupal_mcp_server-0.3.0/docs/tools/index.md +442 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/mkdocs.yml +7 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/pyproject.toml +3 -2
- drupal_mcp_server-0.3.0/scripts/live-migration-d7d11.sh +240 -0
- drupal_mcp_server-0.3.0/scripts/live-migration-d9d11-run.py +127 -0
- drupal_mcp_server-0.3.0/scripts/live-migration-d9d11.sh +193 -0
- drupal_mcp_server-0.3.0/scripts/live-migration-smoke-run.py +115 -0
- drupal_mcp_server-0.3.0/scripts/live-migration-smoke.sh +166 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/__init__.py +1 -1
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/cli.py +58 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/clients/drush.py +12 -1
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/codebase/__init__.py +319 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/codebase/indexer.py +229 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/codebase/parsers.py +301 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/codebase/search.py +272 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/config.py +13 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/installer.py +792 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/server.py +11 -2
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/services/migration_service.py +855 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/_utils.py +492 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/analysis.py +419 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/codebase.py +231 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/config.py +59 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/drupal_org.py +363 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/exports.py +658 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/migration.py +218 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/security_audit.py +1044 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/status.py +527 -0
- drupal_mcp_server-0.3.0/src/drupal_mcp_server/tools/theme_analysis.py +785 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/integration/test_server.py +54 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_clients.py +16 -0
- drupal_mcp_server-0.3.0/tests/unit/test_codebase.py +588 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_drupal_org.py +285 -3
- drupal_mcp_server-0.3.0/tests/unit/test_exports.py +726 -0
- drupal_mcp_server-0.3.0/tests/unit/test_insight_tools.py +399 -0
- drupal_mcp_server-0.3.0/tests/unit/test_installer.py +445 -0
- drupal_mcp_server-0.3.0/tests/unit/test_migration_service.py +246 -0
- drupal_mcp_server-0.3.0/tests/unit/test_security_scanners.py +471 -0
- drupal_mcp_server-0.3.0/tests/unit/test_status_tools.py +445 -0
- drupal_mcp_server-0.3.0/tests/unit/test_theme_analysis.py +567 -0
- drupal_mcp_server-0.1.0/docs/index.md +0 -39
- drupal_mcp_server-0.1.0/docs/migration.md +0 -139
- drupal_mcp_server-0.1.0/docs/tools/index.md +0 -88
- drupal_mcp_server-0.1.0/src/drupal_mcp_server/services/migration_service.py +0 -20
- drupal_mcp_server-0.1.0/src/drupal_mcp_server/tools/_utils.py +0 -239
- drupal_mcp_server-0.1.0/src/drupal_mcp_server/tools/security_audit.py +0 -265
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.env.example +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/.github/workflows/release.yml +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/LICENSE +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/MAINTAINERS.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0/docs}/CODE_OF_CONDUCT.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0/docs}/CONTRIBUTING.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0/docs}/SECURITY.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/adr/0001-use-fastmcp.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/adr/0002-pydantic-settings.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/adr/0003-subprocess-drush.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/adr/0004-http-transport.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/architecture.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/configuration.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/docstring_standard.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/installation.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/tools/content.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/tools/devops.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/docs/tools/users.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/.env.example +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/README.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/basic_usage.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/content_workflow.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/custom_tool.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/examples/migration_workflow.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/scripts/lint.sh +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/scripts/run.sh +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/scripts/setup.sh +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/scripts/test.sh +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/auth/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/auth/basic.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/auth/mcp_oauth.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/auth/session.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/auth/token.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/clients/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/clients/base.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/clients/graphql.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/clients/jsonapi.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/errors.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/exceptions.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/logging_config.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/schemas.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/services/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/services/ai_service.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/services/site_manager.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/accessibility.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/ai.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/code_audit.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/comments.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/commerce.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/contact.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/content.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/database.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/devops.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/feeds.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/fields.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/headless.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/layout_builder.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/media_enhanced.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/menus.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/metatag.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/moderation.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/module_dev.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/multilingual.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/paragraphs.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/pathauto.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/performance.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/redirects.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/revisions.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/scheduler.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/search_api.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/taxonomy.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/testing.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/theme_dev.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/users.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/views.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/tools/webform.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/src/drupal_mcp_server/validation.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/README.md +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/bootstrap.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/filter_check.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/install_modules.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/layout_builder_test.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/mcp_call.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/queue_test.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/resource_check.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/seed.php +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/smoke_test.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/live/sweep.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/__init__.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_auth.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_content_tools.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_errors.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_handler_and_translation_tools.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_logging_config.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_moderation_transitions.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_resource_names.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_revisions.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_scheduler_tools.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_schemas.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_sweep_harness.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_tool_utils.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_tools.py +0 -0
- {drupal_mcp_server-0.1.0 → drupal_mcp_server-0.3.0}/tests/unit/test_validation.py +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
coverage:
|
|
2
|
+
# The 367 tool modules are thin wrappers exercised by the live test harness,
|
|
3
|
+
# which needs a real Drupal site and cannot run in CI. The CI gate (70%)
|
|
4
|
+
# deliberately excludes them, so keep Codecov consistent with CI.
|
|
5
|
+
ignore:
|
|
6
|
+
- "src/drupal_mcp_server/tools/*"
|
|
7
|
+
|
|
8
|
+
status:
|
|
9
|
+
project:
|
|
10
|
+
default:
|
|
11
|
+
target: 80%
|
|
12
|
+
threshold: 2%
|
|
13
|
+
informational: true
|
|
14
|
+
patch:
|
|
15
|
+
default:
|
|
16
|
+
target: 80%
|
|
17
|
+
informational: true
|
|
@@ -46,10 +46,13 @@ jobs:
|
|
|
46
46
|
uses: codecov/codecov-action@v4
|
|
47
47
|
with:
|
|
48
48
|
files: ./coverage.xml
|
|
49
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
49
50
|
fail_ci_if_error: true
|
|
50
51
|
|
|
51
52
|
- name: Dependency vulnerability scan
|
|
52
|
-
run:
|
|
53
|
+
run: |
|
|
54
|
+
pip install --upgrade "setuptools>=83.0.0"
|
|
55
|
+
pip-audit
|
|
53
56
|
|
|
54
57
|
build:
|
|
55
58
|
runs-on: ubuntu-latest
|
|
@@ -7,15 +7,24 @@ on:
|
|
|
7
7
|
- 'docs/**'
|
|
8
8
|
- 'mkdocs.yml'
|
|
9
9
|
- 'README.md'
|
|
10
|
+
- '.github/workflows/docs.yml'
|
|
10
11
|
pull_request:
|
|
11
12
|
paths:
|
|
12
13
|
- 'docs/**'
|
|
13
14
|
- 'mkdocs.yml'
|
|
14
15
|
- 'README.md'
|
|
16
|
+
- '.github/workflows/docs.yml'
|
|
15
17
|
|
|
16
18
|
jobs:
|
|
17
19
|
docs:
|
|
18
20
|
runs-on: ubuntu-latest
|
|
21
|
+
# peaceiris/actions-gh-pages pushes the built site to the gh-pages
|
|
22
|
+
# branch, which requires write access. The repo's default workflow
|
|
23
|
+
# token is read-only, so grant it explicitly here.
|
|
24
|
+
permissions:
|
|
25
|
+
contents: write
|
|
26
|
+
pages: write
|
|
27
|
+
id-token: write
|
|
19
28
|
|
|
20
29
|
steps:
|
|
21
30
|
- uses: actions/checkout@v4
|
|
@@ -56,10 +56,22 @@ htmlcov/
|
|
|
56
56
|
# Ruff
|
|
57
57
|
.ruff_cache/
|
|
58
58
|
|
|
59
|
+
# mkdocs build output
|
|
60
|
+
site/
|
|
61
|
+
|
|
59
62
|
# Environment
|
|
60
63
|
.env
|
|
61
64
|
.env.local
|
|
62
65
|
.env.*.local
|
|
66
|
+
.env.live-smoke
|
|
67
|
+
# Env files generated by the live migration harness scripts (contain
|
|
68
|
+
# local dev credentials).
|
|
69
|
+
.env.live
|
|
70
|
+
.env.d9d11
|
|
71
|
+
.env.d7d11
|
|
72
|
+
|
|
73
|
+
# Runtime migration-plan state written by MigrationService
|
|
74
|
+
.drupal-mcp/
|
|
63
75
|
|
|
64
76
|
# OS
|
|
65
77
|
.DS_Store
|
|
@@ -76,3 +88,5 @@ config/sync/
|
|
|
76
88
|
.omc
|
|
77
89
|
.pi
|
|
78
90
|
.mutagen-*
|
|
91
|
+
# export tools' default destination when DRUPAL_ROOT points at the repo
|
|
92
|
+
exports/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: drupal-mcp-server
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: MCP server for Drupal operations - JSON:API, GraphQL, Drush, AI-powered migration
|
|
5
5
|
Author: Loganathane V
|
|
6
6
|
License: MIT
|
|
@@ -15,6 +15,7 @@ Requires-Python: >=3.11
|
|
|
15
15
|
Requires-Dist: click>=8.1.7
|
|
16
16
|
Requires-Dist: fastmcp>=2.0.0
|
|
17
17
|
Requires-Dist: httpx>=0.27.0
|
|
18
|
+
Requires-Dist: openpyxl>=3.1.2
|
|
18
19
|
Requires-Dist: pydantic-settings>=2.3.0
|
|
19
20
|
Requires-Dist: pydantic>=2.8.0
|
|
20
21
|
Requires-Dist: python-dotenv>=1.0.0
|
|
@@ -44,11 +45,12 @@ Description-Content-Type: text/markdown
|
|
|
44
45
|
|
|
45
46
|
[](https://github.com/vloganathane/drupal-mcp-server/actions/workflows/ci.yml)
|
|
46
47
|
[](https://codecov.io/gh/vloganathane/drupal-mcp-server)
|
|
47
|
-
[](https://pypi.org/project/drupal-mcp-server/)
|
|
48
49
|
[](https://pypi.org/project/drupal-mcp-server/)
|
|
50
|
+
[](https://pypi.org/project/drupal-mcp-server/)
|
|
49
51
|
[](https://github.com/vloganathane/drupal-mcp-server/blob/main/LICENSE)
|
|
50
52
|
|
|
51
|
-
A Model Context Protocol (MCP) server for Drupal operations. Provides **
|
|
53
|
+
A Model Context Protocol (MCP) server for Drupal operations. Provides **414 tools across 41 modules** for site analysis, migration, content management, configuration, commerce, headless, DevOps, security, and more.
|
|
52
54
|
|
|
53
55
|
## Why Use This?
|
|
54
56
|
|
|
@@ -130,6 +132,27 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
130
132
|
}
|
|
131
133
|
```
|
|
132
134
|
|
|
135
|
+
## AI Coding Agents
|
|
136
|
+
|
|
137
|
+
Register the server with any MCP client in one command:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
drupal-mcp install
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
It detects the agents on your machine — Claude Code, Claude Desktop, Cursor,
|
|
144
|
+
Codex CLI, OpenCode, Windsurf, Pi, Hermes Agent and OpenClaw — gathers
|
|
145
|
+
`DRUPAL_*` settings from `./.env` or the environment, and writes each client's
|
|
146
|
+
config (preferring the client's own `mcp add` command when it has one).
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
drupal-mcp install --client claude-code --print # preview without writing
|
|
150
|
+
drupal-mcp install --command 'uvx drupal-mcp-server' # run from PyPI, no install
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
See the [AI Coding Agents guide](docs/agents.md) for per-client copy-paste
|
|
154
|
+
snippets, options, and caveats.
|
|
155
|
+
|
|
133
156
|
## Configuration
|
|
134
157
|
|
|
135
158
|
### Drupal connection
|
|
@@ -181,7 +204,7 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
181
204
|
- `sse` (for Server-Sent Events)
|
|
182
205
|
- `streamable-http` (for Streamable HTTP)
|
|
183
206
|
|
|
184
|
-
## Tools (
|
|
207
|
+
## Tools (414 total)
|
|
185
208
|
|
|
186
209
|
### Accessibility (5)
|
|
187
210
|
- `accessibility_axe_scan` — Run axe-core accessibility scan
|
|
@@ -196,13 +219,16 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
196
219
|
- `ai_generate_migration_plan` — Generate migration plan with AI
|
|
197
220
|
- `ai_translate_content` — Translate content with AI
|
|
198
221
|
|
|
199
|
-
### Analysis (
|
|
222
|
+
### Analysis (9)
|
|
200
223
|
- `analyze_d7_site` — Analyze D7 site for D10 readiness
|
|
201
224
|
- `analyze_d9_site` — Analyze D9+ for deprecated APIs
|
|
202
225
|
- `inventory_content_types` — List all content types
|
|
203
226
|
- `inventory_modules` — List all modules
|
|
204
227
|
- `map_modules_d7_to_d10` — AI-powered module mapping D7→D10
|
|
205
228
|
- `find_deprecated_code` — Scan for deprecated APIs
|
|
229
|
+
- `find_entity_references` — Bundles whose reference fields target an entity type
|
|
230
|
+
- `search_entities` — Substring search across titles, names, and subjects
|
|
231
|
+
- `find_entity_by_path` — Resolve a URL path or alias to its entity
|
|
206
232
|
|
|
207
233
|
### Code Audit (7)
|
|
208
234
|
- `code_audit_phpstan` — Run PHPStan static analysis
|
|
@@ -213,6 +239,11 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
213
239
|
- `composer_audit` — Composer dependency audit
|
|
214
240
|
- `code_quality_report` — Combined code quality report
|
|
215
241
|
|
|
242
|
+
### Codebase (12)
|
|
243
|
+
- `codebase_index_refresh`, `codebase_search`, `codebase_module_list`, `codebase_module_describe`
|
|
244
|
+
- `codebase_unused_modules`, `codebase_redundancy_check`, `codebase_hooks_find`, `codebase_paths_list`
|
|
245
|
+
- `codebase_files_list`, `codebase_directory_tree`, `codebase_file_read`, `codebase_function_read`
|
|
246
|
+
|
|
216
247
|
### Comments (10)
|
|
217
248
|
- `comment_list`, `comment_get`, `comment_create`, `comment_update`, `comment_delete`
|
|
218
249
|
- `comment_thread_list`, `comment_approve`, `comment_unapprove`
|
|
@@ -226,8 +257,8 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
226
257
|
- `commerce_promotion_list`, `commerce_promotion_create`
|
|
227
258
|
- `commerce_shipping_method_list`, `commerce_shipping_method_create`
|
|
228
259
|
|
|
229
|
-
### Config (
|
|
230
|
-
- `config_get`, `config_set`, `export_config`, `import_config`, `sync_config`, `diff_config`, `split_config`
|
|
260
|
+
### Config (8)
|
|
261
|
+
- `config_get`, `config_set`, `export_config`, `import_config`, `sync_config`, `diff_config`, `split_config`, `config_status`
|
|
231
262
|
|
|
232
263
|
### Contact (9)
|
|
233
264
|
- `contact_form_list`, `contact_form_get`, `contact_form_create`, `contact_form_update`, `contact_form_delete`
|
|
@@ -251,9 +282,13 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
251
282
|
- `composer_install`, `composer_require`, `composer_update`
|
|
252
283
|
- `drush_cron`, `drush_watchdog`, `cache_clear`, `drush_updb`, `drush_php_eval`
|
|
253
284
|
|
|
254
|
-
### Drupal.org (
|
|
285
|
+
### Drupal.org (12)
|
|
255
286
|
- `module_search`, `module_get`, `module_versions`, `module_dependencies`, `module_compatibility`
|
|
256
287
|
- `theme_search`, `theme_get`, `release_history`, `project_usage`
|
|
288
|
+
- `module_issues_search`, `module_popular`, `module_recommendation`
|
|
289
|
+
|
|
290
|
+
### Exports (4)
|
|
291
|
+
- `export_nodes`, `export_users`, `export_media`, `export_taxonomy`
|
|
257
292
|
|
|
258
293
|
### Feeds (12)
|
|
259
294
|
- `feeds_feed_list`, `feeds_feed_get`, `feeds_feed_create`, `feeds_feed_update`, `feeds_feed_delete`
|
|
@@ -298,7 +333,7 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
298
333
|
- `metatag_defaults_get`, `metatag_defaults_set`, `metatag_token_list`
|
|
299
334
|
- `metatag_canonical_set`, `metatag_jsonld_generate`
|
|
300
335
|
|
|
301
|
-
### Migration (
|
|
336
|
+
### Migration (17)
|
|
302
337
|
- `generate_migration_yaml` — Generate migration YAML
|
|
303
338
|
- `generate_module_migration` — Generate migration module
|
|
304
339
|
- `run_migration_test` — Test migration with limited records
|
|
@@ -306,6 +341,16 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
306
341
|
- `rollback_migration` — Rollback a migration
|
|
307
342
|
- `sync_media_files` — Sync media between paths
|
|
308
343
|
- `migrate_taxonomy` — Migrate taxonomy vocabularies
|
|
344
|
+
- `create_migration_plan` — Create a persisted migration manifest
|
|
345
|
+
- `get_migration_plan` — Read a migration manifest and tracked state
|
|
346
|
+
- `list_migration_plans` — List migration manifests
|
|
347
|
+
- `migration_status` — Summarize migration progress
|
|
348
|
+
- `migrate_records` — Copy a batch of source records to the target site
|
|
349
|
+
- `record_migration_result` — Record externally executed migration outcomes
|
|
350
|
+
- `analyze_source_site` — Analyze a source Drupal JSON:API resource type
|
|
351
|
+
- `reconcile_migration_counts` — Compare source and target counts
|
|
352
|
+
- `run_migration_wave` — Fetch and migrate one source resource type
|
|
353
|
+
- `run_migration` — Run an ordered end-to-end migration for all planned types
|
|
309
354
|
|
|
310
355
|
### Moderation (13)
|
|
311
356
|
- `moderation_state_list`, `moderation_state_get`, `moderation_state_create`, `moderation_state_update`, `moderation_state_delete`
|
|
@@ -353,7 +398,7 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
353
398
|
- `search_api_index_list`, `search_api_index_get`, `search_api_index_create`, `search_api_index_update`
|
|
354
399
|
- `search_api_index_reindex`, `search_api_index_clear`, `search_api_facet_list`, `search_api_facet_create`
|
|
355
400
|
|
|
356
|
-
### Security Audit (
|
|
401
|
+
### Security Audit (10)
|
|
357
402
|
- `security_scan` — PHPStan with security extensions
|
|
358
403
|
- `dependency_scan` — Composer audit
|
|
359
404
|
- `config_security_check` — Drupal config security
|
|
@@ -362,6 +407,14 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
362
407
|
- `xss_scan` — XSS vulnerability detection
|
|
363
408
|
- `csp_audit` — Content Security Policy audit
|
|
364
409
|
- `file_permissions_audit` — File permissions audit
|
|
410
|
+
- `code_security_scan` — Local pattern scan, nothing to install
|
|
411
|
+
- `route_access_audit` — Route access control classification
|
|
412
|
+
|
|
413
|
+
### Status (4)
|
|
414
|
+
- `status_report` — The site's status report (/admin/reports/status), read-only
|
|
415
|
+
- `database_updates` — Pending database updates, read-only
|
|
416
|
+
- `available_updates` — Packages with newer versions, from composer
|
|
417
|
+
- `health_check` — Drush, database, JSON:API, and module diagnostics
|
|
365
418
|
|
|
366
419
|
### Taxonomy (10)
|
|
367
420
|
- `create_vocabulary`, `get_vocabulary`, `update_vocabulary`, `delete_vocabulary`, `list_vocabularies`
|
|
@@ -372,6 +425,11 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
372
425
|
- `test_scaffold_phpunit`, `test_scaffold_behat`, `test_scaffold_nightwatch`
|
|
373
426
|
- `test_coverage_report`, `test_list_suites`
|
|
374
427
|
|
|
428
|
+
### Theme Analysis (8)
|
|
429
|
+
- `theme_active`, `theme_info`, `theme_regions`, `theme_blocks`
|
|
430
|
+
- `theme_templates`, `theme_template_overrides`, `template_suggestions`
|
|
431
|
+
- `view_template_info`
|
|
432
|
+
|
|
375
433
|
### Theme Development (11)
|
|
376
434
|
- `theme_create`, `theme_library_create`, `theme_region_create`, `theme_template_override`
|
|
377
435
|
- `theme_preprocess_function`, `theme_breakpoint_create`, `theme_base_change`
|
|
@@ -393,10 +451,10 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
393
451
|
|
|
394
452
|
## Documentation
|
|
395
453
|
|
|
396
|
-
- [Contributing Guide](CONTRIBUTING.md)
|
|
397
|
-
- [Changelog](CHANGELOG.md)
|
|
398
|
-
- [Security Policy](SECURITY.md)
|
|
399
|
-
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
454
|
+
- [Contributing Guide](docs/CONTRIBUTING.md)
|
|
455
|
+
- [Changelog](docs/CHANGELOG.md)
|
|
456
|
+
- [Security Policy](docs/SECURITY.md)
|
|
457
|
+
- [Code of Conduct](docs/CODE_OF_CONDUCT.md)
|
|
400
458
|
- [Architecture](docs/architecture.md)
|
|
401
459
|
- [Migration Guide](docs/migration.md)
|
|
402
460
|
- [Docstring Standard](docs/docstring_standard.md)
|
|
@@ -491,7 +549,7 @@ python tests/live/queue_test.py # 18 cron/queue cases, ~60s
|
|
|
491
549
|
python tests/live/filter_check.py # every hard-coded JSON:API filter
|
|
492
550
|
python tests/live/resource_check.py # every resource name, asked of Drupal
|
|
493
551
|
python tests/live/install_modules.py # the modules the tools assume, ~10 min
|
|
494
|
-
python tests/live/sweep.py # all
|
|
552
|
+
python tests/live/sweep.py # all 414 tools, ~30 min
|
|
495
553
|
python tests/live/mcp_call.py content_list '{}' # one call, for spot checks
|
|
496
554
|
```
|
|
497
555
|
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/vloganathane/drupal-mcp-server/actions/workflows/ci.yml)
|
|
4
4
|
[](https://codecov.io/gh/vloganathane/drupal-mcp-server)
|
|
5
|
-
[](https://pypi.org/project/drupal-mcp-server/)
|
|
6
6
|
[](https://pypi.org/project/drupal-mcp-server/)
|
|
7
|
+
[](https://pypi.org/project/drupal-mcp-server/)
|
|
7
8
|
[](https://github.com/vloganathane/drupal-mcp-server/blob/main/LICENSE)
|
|
8
9
|
|
|
9
|
-
A Model Context Protocol (MCP) server for Drupal operations. Provides **
|
|
10
|
+
A Model Context Protocol (MCP) server for Drupal operations. Provides **414 tools across 41 modules** for site analysis, migration, content management, configuration, commerce, headless, DevOps, security, and more.
|
|
10
11
|
|
|
11
12
|
## Why Use This?
|
|
12
13
|
|
|
@@ -88,6 +89,27 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
88
89
|
}
|
|
89
90
|
```
|
|
90
91
|
|
|
92
|
+
## AI Coding Agents
|
|
93
|
+
|
|
94
|
+
Register the server with any MCP client in one command:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
drupal-mcp install
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
It detects the agents on your machine — Claude Code, Claude Desktop, Cursor,
|
|
101
|
+
Codex CLI, OpenCode, Windsurf, Pi, Hermes Agent and OpenClaw — gathers
|
|
102
|
+
`DRUPAL_*` settings from `./.env` or the environment, and writes each client's
|
|
103
|
+
config (preferring the client's own `mcp add` command when it has one).
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
drupal-mcp install --client claude-code --print # preview without writing
|
|
107
|
+
drupal-mcp install --command 'uvx drupal-mcp-server' # run from PyPI, no install
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
See the [AI Coding Agents guide](docs/agents.md) for per-client copy-paste
|
|
111
|
+
snippets, options, and caveats.
|
|
112
|
+
|
|
91
113
|
## Configuration
|
|
92
114
|
|
|
93
115
|
### Drupal connection
|
|
@@ -139,7 +161,7 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
139
161
|
- `sse` (for Server-Sent Events)
|
|
140
162
|
- `streamable-http` (for Streamable HTTP)
|
|
141
163
|
|
|
142
|
-
## Tools (
|
|
164
|
+
## Tools (414 total)
|
|
143
165
|
|
|
144
166
|
### Accessibility (5)
|
|
145
167
|
- `accessibility_axe_scan` — Run axe-core accessibility scan
|
|
@@ -154,13 +176,16 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
154
176
|
- `ai_generate_migration_plan` — Generate migration plan with AI
|
|
155
177
|
- `ai_translate_content` — Translate content with AI
|
|
156
178
|
|
|
157
|
-
### Analysis (
|
|
179
|
+
### Analysis (9)
|
|
158
180
|
- `analyze_d7_site` — Analyze D7 site for D10 readiness
|
|
159
181
|
- `analyze_d9_site` — Analyze D9+ for deprecated APIs
|
|
160
182
|
- `inventory_content_types` — List all content types
|
|
161
183
|
- `inventory_modules` — List all modules
|
|
162
184
|
- `map_modules_d7_to_d10` — AI-powered module mapping D7→D10
|
|
163
185
|
- `find_deprecated_code` — Scan for deprecated APIs
|
|
186
|
+
- `find_entity_references` — Bundles whose reference fields target an entity type
|
|
187
|
+
- `search_entities` — Substring search across titles, names, and subjects
|
|
188
|
+
- `find_entity_by_path` — Resolve a URL path or alias to its entity
|
|
164
189
|
|
|
165
190
|
### Code Audit (7)
|
|
166
191
|
- `code_audit_phpstan` — Run PHPStan static analysis
|
|
@@ -171,6 +196,11 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
171
196
|
- `composer_audit` — Composer dependency audit
|
|
172
197
|
- `code_quality_report` — Combined code quality report
|
|
173
198
|
|
|
199
|
+
### Codebase (12)
|
|
200
|
+
- `codebase_index_refresh`, `codebase_search`, `codebase_module_list`, `codebase_module_describe`
|
|
201
|
+
- `codebase_unused_modules`, `codebase_redundancy_check`, `codebase_hooks_find`, `codebase_paths_list`
|
|
202
|
+
- `codebase_files_list`, `codebase_directory_tree`, `codebase_file_read`, `codebase_function_read`
|
|
203
|
+
|
|
174
204
|
### Comments (10)
|
|
175
205
|
- `comment_list`, `comment_get`, `comment_create`, `comment_update`, `comment_delete`
|
|
176
206
|
- `comment_thread_list`, `comment_approve`, `comment_unapprove`
|
|
@@ -184,8 +214,8 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
184
214
|
- `commerce_promotion_list`, `commerce_promotion_create`
|
|
185
215
|
- `commerce_shipping_method_list`, `commerce_shipping_method_create`
|
|
186
216
|
|
|
187
|
-
### Config (
|
|
188
|
-
- `config_get`, `config_set`, `export_config`, `import_config`, `sync_config`, `diff_config`, `split_config`
|
|
217
|
+
### Config (8)
|
|
218
|
+
- `config_get`, `config_set`, `export_config`, `import_config`, `sync_config`, `diff_config`, `split_config`, `config_status`
|
|
189
219
|
|
|
190
220
|
### Contact (9)
|
|
191
221
|
- `contact_form_list`, `contact_form_get`, `contact_form_create`, `contact_form_update`, `contact_form_delete`
|
|
@@ -209,9 +239,13 @@ Set `MCP_TRANSPORT` to one of:
|
|
|
209
239
|
- `composer_install`, `composer_require`, `composer_update`
|
|
210
240
|
- `drush_cron`, `drush_watchdog`, `cache_clear`, `drush_updb`, `drush_php_eval`
|
|
211
241
|
|
|
212
|
-
### Drupal.org (
|
|
242
|
+
### Drupal.org (12)
|
|
213
243
|
- `module_search`, `module_get`, `module_versions`, `module_dependencies`, `module_compatibility`
|
|
214
244
|
- `theme_search`, `theme_get`, `release_history`, `project_usage`
|
|
245
|
+
- `module_issues_search`, `module_popular`, `module_recommendation`
|
|
246
|
+
|
|
247
|
+
### Exports (4)
|
|
248
|
+
- `export_nodes`, `export_users`, `export_media`, `export_taxonomy`
|
|
215
249
|
|
|
216
250
|
### Feeds (12)
|
|
217
251
|
- `feeds_feed_list`, `feeds_feed_get`, `feeds_feed_create`, `feeds_feed_update`, `feeds_feed_delete`
|
|
@@ -256,7 +290,7 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
256
290
|
- `metatag_defaults_get`, `metatag_defaults_set`, `metatag_token_list`
|
|
257
291
|
- `metatag_canonical_set`, `metatag_jsonld_generate`
|
|
258
292
|
|
|
259
|
-
### Migration (
|
|
293
|
+
### Migration (17)
|
|
260
294
|
- `generate_migration_yaml` — Generate migration YAML
|
|
261
295
|
- `generate_module_migration` — Generate migration module
|
|
262
296
|
- `run_migration_test` — Test migration with limited records
|
|
@@ -264,6 +298,16 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
264
298
|
- `rollback_migration` — Rollback a migration
|
|
265
299
|
- `sync_media_files` — Sync media between paths
|
|
266
300
|
- `migrate_taxonomy` — Migrate taxonomy vocabularies
|
|
301
|
+
- `create_migration_plan` — Create a persisted migration manifest
|
|
302
|
+
- `get_migration_plan` — Read a migration manifest and tracked state
|
|
303
|
+
- `list_migration_plans` — List migration manifests
|
|
304
|
+
- `migration_status` — Summarize migration progress
|
|
305
|
+
- `migrate_records` — Copy a batch of source records to the target site
|
|
306
|
+
- `record_migration_result` — Record externally executed migration outcomes
|
|
307
|
+
- `analyze_source_site` — Analyze a source Drupal JSON:API resource type
|
|
308
|
+
- `reconcile_migration_counts` — Compare source and target counts
|
|
309
|
+
- `run_migration_wave` — Fetch and migrate one source resource type
|
|
310
|
+
- `run_migration` — Run an ordered end-to-end migration for all planned types
|
|
267
311
|
|
|
268
312
|
### Moderation (13)
|
|
269
313
|
- `moderation_state_list`, `moderation_state_get`, `moderation_state_create`, `moderation_state_update`, `moderation_state_delete`
|
|
@@ -311,7 +355,7 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
311
355
|
- `search_api_index_list`, `search_api_index_get`, `search_api_index_create`, `search_api_index_update`
|
|
312
356
|
- `search_api_index_reindex`, `search_api_index_clear`, `search_api_facet_list`, `search_api_facet_create`
|
|
313
357
|
|
|
314
|
-
### Security Audit (
|
|
358
|
+
### Security Audit (10)
|
|
315
359
|
- `security_scan` — PHPStan with security extensions
|
|
316
360
|
- `dependency_scan` — Composer audit
|
|
317
361
|
- `config_security_check` — Drupal config security
|
|
@@ -320,6 +364,14 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
320
364
|
- `xss_scan` — XSS vulnerability detection
|
|
321
365
|
- `csp_audit` — Content Security Policy audit
|
|
322
366
|
- `file_permissions_audit` — File permissions audit
|
|
367
|
+
- `code_security_scan` — Local pattern scan, nothing to install
|
|
368
|
+
- `route_access_audit` — Route access control classification
|
|
369
|
+
|
|
370
|
+
### Status (4)
|
|
371
|
+
- `status_report` — The site's status report (/admin/reports/status), read-only
|
|
372
|
+
- `database_updates` — Pending database updates, read-only
|
|
373
|
+
- `available_updates` — Packages with newer versions, from composer
|
|
374
|
+
- `health_check` — Drush, database, JSON:API, and module diagnostics
|
|
323
375
|
|
|
324
376
|
### Taxonomy (10)
|
|
325
377
|
- `create_vocabulary`, `get_vocabulary`, `update_vocabulary`, `delete_vocabulary`, `list_vocabularies`
|
|
@@ -330,6 +382,11 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
330
382
|
- `test_scaffold_phpunit`, `test_scaffold_behat`, `test_scaffold_nightwatch`
|
|
331
383
|
- `test_coverage_report`, `test_list_suites`
|
|
332
384
|
|
|
385
|
+
### Theme Analysis (8)
|
|
386
|
+
- `theme_active`, `theme_info`, `theme_regions`, `theme_blocks`
|
|
387
|
+
- `theme_templates`, `theme_template_overrides`, `template_suggestions`
|
|
388
|
+
- `view_template_info`
|
|
389
|
+
|
|
333
390
|
### Theme Development (11)
|
|
334
391
|
- `theme_create`, `theme_library_create`, `theme_region_create`, `theme_template_override`
|
|
335
392
|
- `theme_preprocess_function`, `theme_breakpoint_create`, `theme_base_change`
|
|
@@ -351,10 +408,10 @@ displays have Layout Builder enabled; `layout_builder_get`,
|
|
|
351
408
|
|
|
352
409
|
## Documentation
|
|
353
410
|
|
|
354
|
-
- [Contributing Guide](CONTRIBUTING.md)
|
|
355
|
-
- [Changelog](CHANGELOG.md)
|
|
356
|
-
- [Security Policy](SECURITY.md)
|
|
357
|
-
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
411
|
+
- [Contributing Guide](docs/CONTRIBUTING.md)
|
|
412
|
+
- [Changelog](docs/CHANGELOG.md)
|
|
413
|
+
- [Security Policy](docs/SECURITY.md)
|
|
414
|
+
- [Code of Conduct](docs/CODE_OF_CONDUCT.md)
|
|
358
415
|
- [Architecture](docs/architecture.md)
|
|
359
416
|
- [Migration Guide](docs/migration.md)
|
|
360
417
|
- [Docstring Standard](docs/docstring_standard.md)
|
|
@@ -449,7 +506,7 @@ python tests/live/queue_test.py # 18 cron/queue cases, ~60s
|
|
|
449
506
|
python tests/live/filter_check.py # every hard-coded JSON:API filter
|
|
450
507
|
python tests/live/resource_check.py # every resource name, asked of Drupal
|
|
451
508
|
python tests/live/install_modules.py # the modules the tools assume, ~10 min
|
|
452
|
-
python tests/live/sweep.py # all
|
|
509
|
+
python tests/live/sweep.py # all 414 tools, ~30 min
|
|
453
510
|
python tests/live/mcp_call.py content_list '{}' # one call, for spot checks
|
|
454
511
|
```
|
|
455
512
|
|
|
@@ -7,6 +7,100 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-10-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Wave 5 of the drupal-scout-mcp port — 2 local security tools
|
|
15
|
+
(414 total, 41 modules): `code_security_scan` runs scout's
|
|
16
|
+
zero-dependency pattern engine (XSS, SQL injection, command injection,
|
|
17
|
+
path traversal, hardcoded secrets, access control, CSRF, deprecated
|
|
18
|
+
API — 8 families, category/severity filters, per-finding file/line/
|
|
19
|
+
snippet/fix recommendation) with its Drupal-aware false-positive table
|
|
20
|
+
(EntityQuery conditions, stream wrappers, escapeshellarg, example
|
|
21
|
+
secrets, comment lines), so a site without PHPStan gets concrete
|
|
22
|
+
findings; counts stay complete when `max_findings` truncates the list.
|
|
23
|
+
`route_access_audit` is the routing half of scout's anonymous-exploit
|
|
24
|
+
scan done properly per route: every `*.routing.yml` route classified
|
|
25
|
+
as anonymous / permission / role / entity / custom / a named
|
|
26
|
+
underscore requirement / an alias (whose definition may live in a
|
|
27
|
+
PHP route provider this YAML pass cannot read) / denied / **missing**,
|
|
28
|
+
with its controller mapped to the declaring file. Targets confine to
|
|
29
|
+
DRUPAL_ROOT and prune vendor, tests, and contrib from the default scan;
|
|
30
|
+
symlinks are skipped. Two accuracy corrections over scout's registry:
|
|
31
|
+
`t(` is a live D8+ function (scout flagged every translation call as a
|
|
32
|
+
Drupal 7 leftover) and scout's CSRF `$request` pattern was escaped so
|
|
33
|
+
it could never match PHP. Scout's `verify_vulnerability` was not
|
|
34
|
+
ported — it returns static advice rather than site-specific data —
|
|
35
|
+
and the optional tree-sitter AST layer is skipped: the pattern pass
|
|
36
|
+
carries the signal. Live testing on D11.4.10's core node module
|
|
37
|
+
(115 files) caught five accuracy bugs before release: JS template
|
|
38
|
+
literals matched the PHP backtick-shell pattern, Drupal's `{table}` /
|
|
39
|
+
`->...Table()` placeholder concatenation read as SQL injection,
|
|
40
|
+
unrecognized underscore requirements and alias-only entries were both
|
|
41
|
+
reported as missing access (node went from five "missing" routes to
|
|
42
|
+
zero real ones), and a zero-file scan read as a clean bill of health.
|
|
43
|
+
- Wave 4 of the drupal-scout-mcp port — 8 read-only theme analysis tools
|
|
44
|
+
(412 total, 41 modules): `theme_active` (default/admin/enabled themes
|
|
45
|
+
from `system.theme` + `pm:list`), `theme_info` (pm:list metadata merged
|
|
46
|
+
with a safe YAML parse of the theme's info.yml — regions in declaration
|
|
47
|
+
order, libraries, dependencies, and the base-theme chain followed
|
|
48
|
+
upward), `theme_regions` (regions with their block placements and
|
|
49
|
+
counts, empty regions visible, placements in regions the theme no
|
|
50
|
+
longer defines flagged), `theme_blocks` (every `block.block.*`
|
|
51
|
+
placement with theme/region/search filters — search matches labels and
|
|
52
|
+
plugins, folding scout's separate `search_blocks` into one tool),
|
|
53
|
+
`theme_templates` (pruned `*.html.twig` walk with sizes),
|
|
54
|
+
`theme_template_overrides` (one docroot-wide index splits templates
|
|
55
|
+
that shadow same-named core/module files from theme originals),
|
|
56
|
+
`template_suggestions` (the Twig suggestion chain per entity type, each
|
|
57
|
+
marked with whether the default theme already ships that file), and
|
|
58
|
+
`view_template_info` (the chain for a view display, looked up in the
|
|
59
|
+
JSON:API view collection by its machine id — Views config names differ
|
|
60
|
+
between Drupal generations, `view.*` on older sites and `views.view.*`
|
|
61
|
+
on Drupal 11.4+, so the entity collection is the stable source — with
|
|
62
|
+
an unknown display_id erroring with the display list and an unknown
|
|
63
|
+
view listing the ones the site has). Every file path resolves inside
|
|
64
|
+
DRUPAL_ROOT before a read — symlinks and `..` segments that leave the
|
|
65
|
+
docroot are rejected — and no caller input reaches a shell; theme
|
|
66
|
+
blocks come from JSON:API rather than scout's interpolated `drush ev`
|
|
67
|
+
- The shared JSON:API helpers (`jsonapi_collect`, `jsonapi_attrs`,
|
|
68
|
+
`jsonapi_bundle`, `jsonapi_rel_ids`), `flag_label`, and the export
|
|
69
|
+
path/write helpers moved from the exports module into `_utils` so both
|
|
70
|
+
waves page collections and confine destinations the same way
|
|
71
|
+
- Wave 3 of the drupal-scout-mcp port — 4 export tools (404 total, 40
|
|
72
|
+
modules): `export_nodes`, `export_users`, `export_media`,
|
|
73
|
+
`export_taxonomy` write CSV (UTF-8 with BOM) or Excel files
|
|
74
|
+
(`openpyxl`, new runtime dependency) and return only the path,
|
|
75
|
+
row/column counts, size, and a three-row preview. Destination paths are
|
|
76
|
+
confined to the Drupal root, the system temp directory, or the home
|
|
77
|
+
directory; data is paged per bundle over JSON:API (never through the
|
|
78
|
+
shared merged offset, which skips rows), and taxonomy usage counts come
|
|
79
|
+
from one validated `GROUP BY` query per field storage targeting
|
|
80
|
+
taxonomy terms, with unreadable tables reported in a note instead of
|
|
81
|
+
failing the export (and a `safe_to_delete` verdict withheld entirely
|
|
82
|
+
whenever the counts are incomplete). Entries with no internal id —
|
|
83
|
+
Drupal's uid-0 anonymous user serves only a display_name — are skipped
|
|
84
|
+
and counted as `skipped_without_id`, and an unreadable status stays
|
|
85
|
+
empty in the CSV rather than being presented as "blocked"
|
|
86
|
+
- `sql_output`/`sql_rows` moved from the analysis module into `_utils` so
|
|
87
|
+
the export tools parse `drush sql:query` text the same way
|
|
88
|
+
- Wave 2 of the drupal-scout-mcp port — 8 tools (400 total, 39 modules):
|
|
89
|
+
- Status section (4): `status_report` (drush core:requirements, severity
|
|
90
|
+
filter), `database_updates` (read-only pending DB updates),
|
|
91
|
+
`available_updates` (composer outdated with dev filtering and a
|
|
92
|
+
security-only mode intersected with composer audit), `health_check`
|
|
93
|
+
(Drush, database, JSON:API, and module probes with a fix per failure)
|
|
94
|
+
- Analysis: `find_entity_references` (bundles whose reference fields
|
|
95
|
+
target an entity type, via JSON:API field config), `search_entities`
|
|
96
|
+
(escaped LIKE search across six entity tables), `find_entity_by_path`
|
|
97
|
+
(route or path-alias resolution to an entity)
|
|
98
|
+
- Config: `config_status` (read-only active vs sync comparison)
|
|
99
|
+
- `run_composer` gained a `tail` argument so tools that parse full JSON
|
|
100
|
+
documents (`composer outdated`) are not truncated
|
|
101
|
+
|
|
102
|
+
## [0.2.0] - 2026-10-16
|
|
103
|
+
|
|
10
104
|
### Security
|
|
11
105
|
|
|
12
106
|
- Fix command injection vulnerabilities in code audit and security audit tools
|
|
@@ -17,6 +111,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
17
111
|
|
|
18
112
|
### Added
|
|
19
113
|
|
|
114
|
+
- Add `drupal-mcp install`, a self-installer that registers the server with
|
|
115
|
+
local MCP clients (Claude Code, Claude Desktop, Cursor, Codex CLI,
|
|
116
|
+
OpenCode, Windsurf, Pi, Hermes Agent, OpenClaw), with `--print`/`--json`
|
|
117
|
+
for scripted setup and an AI Coding Agents guide
|
|
118
|
+
- Add `module_issues_search`, `module_popular`, and `module_recommendation`
|
|
119
|
+
(client-side issue-queue relevance scoring, usage-ranked module lists by
|
|
120
|
+
category, local-index + drupal.org recommendations), plus the `DRUPAL_ROOT`
|
|
121
|
+
and `DRUPAL_MODULES_PATH` settings for local codebase analysis
|
|
122
|
+
- Add a local codebase index with 12 `codebase_*` tools: functionality
|
|
123
|
+
search, module inventory/descriptions, unused and redundant module
|
|
124
|
+
detection, hook implementation lookup, and safe module file/tree/function
|
|
125
|
+
reading (all reads confined to `DRUPAL_ROOT`)
|
|
20
126
|
- Add `moderation_transition_delete`, giving `moderation_transition_create` the
|
|
21
127
|
counterpart it never had. The tool count is now 367
|
|
22
128
|
- Add Lando support to SiteManager
|