Skip to content

Commit e203dea

Browse files
committed
Merge public/master: align histories for unified sync
2 parents b95e491 + e0dd49e commit e203dea

File tree

8 files changed

+196
-109
lines changed

8 files changed

+196
-109
lines changed

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
/behat.yml export-ignore
2626
/behat.yml.dist export-ignore
2727

28+
# Project instructions (dev-only)
29+
/CLAUDE.md export-ignore
30+
2831
# Documentation (keep README and CHANGELOG, exclude dev docs)
2932
/CONTRIBUTING.md export-ignore
3033
/ROADMAP.md export-ignore

.github/workflows/ci.yml

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,94 @@ jobs:
210210
SIMPLETEST_BASE_URL: http://localhost:8888
211211
SIMPLETEST_DB: mysql://root:root@127.0.0.1/drupal
212212

213-
# NOTE: E2E tests (mcp-e2e job) run in the dev repo only.
214-
# They require scripts/ which are not included in the public release.
213+
mcp-e2e:
214+
name: MCP E2E (STDIO + HTTP)
215+
runs-on: ubuntu-latest
216+
services:
217+
mysql:
218+
image: mysql:8.0
219+
env:
220+
MYSQL_ROOT_PASSWORD: root
221+
MYSQL_DATABASE: drupal
222+
ports:
223+
- 3306:3306
224+
options: >-
225+
--health-cmd="mysqladmin ping"
226+
--health-interval=10s
227+
--health-timeout=5s
228+
--health-retries=3
229+
230+
steps:
231+
- name: Checkout code
232+
uses: actions/checkout@v4
233+
234+
- name: Setup PHP
235+
uses: shivammathur/setup-php@v2
236+
with:
237+
php-version: '8.3'
238+
extensions: mbstring, pdo_mysql, gd, dom, xml
239+
tools: composer
240+
coverage: none
241+
242+
- name: Install Drupal
243+
run: |
244+
composer create-project drupal/recommended-project:^10.3 drupal --no-interaction
245+
cd drupal
246+
composer require --dev drupal/core-dev:^10.3 phpspec/prophecy-phpunit:^2 drush/drush --with-all-dependencies --no-interaction
247+
composer require drupal/tool:1.0.0-alpha9 mcp/sdk:^0.2.2 code-wheel/mcp-http-security:^1.0 code-wheel/mcp-error-codes:^1.2 code-wheel/mcp-events:^2.0 code-wheel/mcp-schema-builder:^1.1 code-wheel/mcp-tool-gateway:^1.1 -W --no-interaction
248+
249+
- name: Copy MCP Tools module
250+
run: |
251+
mkdir -p drupal/web/modules/contrib/mcp_tools
252+
rsync -av \
253+
--exclude='.git' \
254+
--exclude='.github' \
255+
--exclude='.ddev' \
256+
--exclude='docs' \
257+
--exclude='scripts' \
258+
--exclude='drupal' \
259+
--exclude='vendor' \
260+
--exclude='.phpunit.cache' \
261+
./ drupal/web/modules/contrib/mcp_tools/
262+
263+
- name: Install Drupal site
264+
run: |
265+
cd drupal
266+
./vendor/bin/drush site:install minimal \
267+
--db-url=mysql://root:root@127.0.0.1/drupal \
268+
--site-name="MCP Tools Test" \
269+
--account-name=admin \
270+
--account-pass=admin \
271+
-y
272+
273+
- name: Enable modules
274+
run: |
275+
cd drupal
276+
./vendor/bin/drush en tool dblog update -y
277+
./vendor/bin/drush en mcp_tools -y
278+
./vendor/bin/drush en mcp_tools_stdio mcp_tools_remote mcp_tools_cache -y
279+
./vendor/bin/drush cr
280+
281+
- name: Setup Node
282+
uses: actions/setup-node@v4
283+
with:
284+
node-version: '20'
285+
286+
- name: Install MCP JS SDK (no-lock)
287+
run: |
288+
npm install --no-save --no-package-lock @modelcontextprotocol/sdk zod
289+
290+
- name: JS SDK STDIO compatibility
291+
run: |
292+
node scripts/mcp_js_sdk_compat.mjs --drupal-root drupal
293+
294+
- name: STDIO transport E2E
295+
run: |
296+
python3 scripts/mcp_stdio_e2e.py --drupal-root drupal
297+
298+
- name: HTTP transport E2E
299+
run: |
300+
python3 scripts/mcp_http_e2e.py --drupal-root drupal --base-url http://localhost:8888
215301
216302
code-coverage:
217303
name: Code Coverage

.github/workflows/full-tool-registration.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# =============================================================================
22
# Full Tool Registration Workflow
3-
# Installs optional contrib dependencies and verifies all 205 tools register.
3+
# Installs optional contrib dependencies and verifies all 222 tools register.
44
# Intended for scheduled/manual runs (not every PR) to keep CI fast and stable.
55
# =============================================================================
66

@@ -13,7 +13,7 @@ on:
1313

1414
jobs:
1515
all-tools-register:
16-
name: Verify All 205 Tools Register
16+
name: Verify All 222 Tools Register
1717
runs-on: ubuntu-latest
1818
services:
1919
mysql:
@@ -108,11 +108,11 @@ jobs:
108108
MCP_TOOL_COUNT=$(./vendor/bin/drush eval '$defs = \Drupal::service("plugin.manager.tool")->getDefinitions(); $defs = array_filter($defs, static fn($def): bool => str_starts_with($def->getProvider(), "mcp_tools")); echo count($defs);')
109109
echo "Registered MCP Tools tools: $MCP_TOOL_COUNT"
110110
111-
if [ "$MCP_TOOL_COUNT" -ne 205 ]; then
112-
echo "ERROR: Expected 205 MCP Tools tools, found $MCP_TOOL_COUNT"
111+
if [ "$MCP_TOOL_COUNT" -ne 222 ]; then
112+
echo "ERROR: Expected 222 MCP Tools tools, found $MCP_TOOL_COUNT"
113113
exit 1
114114
fi
115-
echo "✓ All tools registered (205)"
115+
echo "✓ All tools registered (222)"
116116
117117
- name: Verify all tool schemas convert
118118
run: |

.github/workflows/release.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ jobs:
8585
- name: Install MCP dependencies
8686
run: |
8787
cd drupal
88-
composer require drupal/tool:1.0.0-alpha9 mcp/sdk:^0.2.2 code-wheel/mcp-http-security:^1.0 code-wheel/mcp-error-codes:^1.2 code-wheel/mcp-events:^2.0 code-wheel/mcp-schema-builder:^1.1 code-wheel/mcp-tool-gateway:^1.1 -W --no-interaction
88+
composer require drupal/tool:1.0.0-alpha9 mcp/sdk:^0.2.2 code-wheel/mcp-http-security:^1.0 -W --no-interaction
8989
9090
- name: Copy module
9191
run: |
@@ -152,8 +152,10 @@ jobs:
152152
153153
./vendor/bin/phpunit --testsuite unit,kernel,functional --colors=always
154154
155-
# NOTE: E2E tests using scripts/ are only available in the dev repo
156-
# and are excluded from the public release package
155+
- name: MCP transport E2E
156+
run: |
157+
python3 scripts/mcp_stdio_e2e.py --drupal-root drupal
158+
python3 scripts/mcp_http_e2e.py --drupal-root drupal --base-url http://localhost:8888
157159
158160
release:
159161
name: Create GitHub Release

.github/workflows/security.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ jobs:
3030
chmod +x gitleaks
3131
3232
- name: Run Gitleaks
33-
# Note: May report false positives on test data. Review findings manually.
34-
continue-on-error: true
3533
run: |
36-
./gitleaks detect --source . --verbose
34+
./gitleaks detect --source . --config .gitleaks.toml --verbose
3735
3836
php-security:
3937
name: PHP Security Check

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ mcp.json
77
# Environment files
88
.env
99
.env.local
10+
11+
# PromptWheel
12+
.promptwheel/

RELEASE_NOTES.md

Lines changed: 0 additions & 96 deletions
This file was deleted.

src/Commands/McpToolsCommands.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,97 @@ public function devProfile(array $options = ['skip-modules' => FALSE]): void {
670670
$this->io()->text(' 3) Run drush mcp:status to verify configuration');
671671
}
672672

673+
/**
674+
* Generate MCP client configuration JSON for AI editors.
675+
*/
676+
#[CLI\Command(name: 'mcp-tools:client-config', aliases: ['mcp-client-config'])]
677+
#[CLI\Usage(name: 'drush mcp-tools:client-config', description: 'Generate MCP client config JSON')]
678+
#[CLI\Usage(name: 'drush mcp-tools:client-config --scope=read', description: 'Generate read-only config')]
679+
#[CLI\Usage(name: 'drush mcp-tools:client-config > .mcp.json', description: 'Save config directly to file')]
680+
#[CLI\Option(name: 'scope', description: 'Scopes for the MCP server (default: read,write)')]
681+
#[CLI\Option(name: 'uid', description: 'Drupal user ID for tool execution (default: 1)')]
682+
public function clientConfig(array $options = ['scope' => 'read,write', 'uid' => '1']): void {
683+
$scope = is_string($options['scope']) ? $options['scope'] : 'read,write';
684+
$uid = is_string($options['uid']) ? $options['uid'] : '1';
685+
686+
$drupalRoot = \Drupal::root();
687+
$isDdev = (bool) getenv('IS_DDEV_PROJECT');
688+
$isLando = (bool) getenv('LANDO');
689+
690+
if ($isDdev) {
691+
// Inside DDEV: the project root is one level above the Drupal root
692+
// (web/ docroot), or if Drupal IS the project root, use that.
693+
$projectRoot = dirname($drupalRoot);
694+
if (basename($drupalRoot) === $drupalRoot) {
695+
$projectRoot = $drupalRoot;
696+
}
697+
$config = [
698+
'mcpServers' => [
699+
'drupal' => [
700+
'command' => 'ddev',
701+
'args' => [
702+
'drush',
703+
'mcp-tools:serve',
704+
'--quiet',
705+
"--uid={$uid}",
706+
"--scope={$scope}",
707+
],
708+
'cwd' => $projectRoot,
709+
],
710+
],
711+
];
712+
}
713+
elseif ($isLando) {
714+
$projectRoot = dirname($drupalRoot);
715+
if (basename($drupalRoot) === $drupalRoot) {
716+
$projectRoot = $drupalRoot;
717+
}
718+
$config = [
719+
'mcpServers' => [
720+
'drupal' => [
721+
'command' => 'lando',
722+
'args' => [
723+
'drush',
724+
'mcp-tools:serve',
725+
'--quiet',
726+
"--uid={$uid}",
727+
"--scope={$scope}",
728+
],
729+
'cwd' => $projectRoot,
730+
],
731+
],
732+
];
733+
}
734+
else {
735+
// Bare metal / native.
736+
$drushPath = $drupalRoot . '/vendor/bin/drush';
737+
$config = [
738+
'mcpServers' => [
739+
'drupal' => [
740+
'command' => $drushPath,
741+
'args' => [
742+
'mcp-tools:serve',
743+
'--quiet',
744+
"--uid={$uid}",
745+
"--scope={$scope}",
746+
],
747+
'cwd' => $drupalRoot,
748+
],
749+
],
750+
];
751+
}
752+
753+
// JSON to stdout (pipeable to file).
754+
$this->output()->write(json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n");
755+
756+
// Instructions to stderr (not captured when piping).
757+
fwrite(\STDERR, "\nSave this as one of:\n");
758+
fwrite(\STDERR, " Claude Code: .mcp.json (project root)\n");
759+
fwrite(\STDERR, " Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json\n");
760+
fwrite(\STDERR, " Cursor: .cursor/mcp.json (project root)\n");
761+
fwrite(\STDERR, " Windsurf: .windsurf/mcp.json (project root)\n");
762+
}
763+
673764
/**
674765
* Count MCP tools from the tool manager.
675766
*

0 commit comments

Comments
 (0)