Skip to content

Commit 58a2d09

Browse files
Behat MCP Server
0 parents  commit 58a2d09

18 files changed

Lines changed: 1312 additions & 0 deletions

.github/workflows/tests.yml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- 'main'
7+
- '*.x'
8+
paths-ignore:
9+
- '**.md'
10+
pull_request:
11+
paths-ignore:
12+
- '**.md'
13+
workflow_dispatch: ~
14+
15+
jobs:
16+
tests:
17+
name: Tests
18+
runs-on: ${{ matrix.os }}
19+
defaults:
20+
run:
21+
shell: bash
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
php: ['8.2', '8.3', '8.4', '8.5']
26+
os: [ubuntu-latest]
27+
composer-mode: [update]
28+
symfony-version: ['']
29+
include:
30+
# Build on the lowest supported PHP with the lowest supported dependencies
31+
- php: '8.2'
32+
os: ubuntu-latest
33+
composer-mode: lowest
34+
symfony-version: ''
35+
36+
# Symfony LTS job:
37+
- php: '8.2'
38+
os: ubuntu-latest
39+
composer-mode: update
40+
symfony-version: '6.4'
41+
42+
steps:
43+
- uses: actions/checkout@v4
44+
45+
- name: Setup PHP
46+
uses: shivammathur/setup-php@v2
47+
with:
48+
php-version: "${{ matrix.php }}"
49+
ini-file: "development"
50+
ini-values: "zend.exception_ignore_args=Off"
51+
coverage: none
52+
53+
- name: Install latest dependencies
54+
if: matrix.composer-mode == 'update'
55+
env:
56+
SYMFONY_REQUIRE: ${{ matrix.symfony-version }}.*
57+
run: composer update
58+
59+
- name: Install lowest dependencies
60+
if: matrix.composer-mode == 'lowest'
61+
run: composer update --prefer-lowest
62+
63+
- name: Run tests (Behat)
64+
run: ./vendor/bin/behat --no-colors
65+
66+
static-analysis:
67+
name: Static analysis
68+
runs-on: ubuntu-latest
69+
strategy:
70+
fail-fast: false
71+
matrix:
72+
php: ['8.2', '8.5']
73+
steps:
74+
- uses: actions/checkout@v4
75+
76+
- name: Setup PHP
77+
uses: shivammathur/setup-php@v2
78+
with:
79+
php-version: "${{ matrix.php }}"
80+
ini-values: "zend.exception_ignore_args=Off"
81+
coverage: none
82+
83+
- name: Install dependencies
84+
run: composer update
85+
86+
- name: Run PHPStan
87+
run: ./vendor/bin/phpstan
88+
89+
coding-standard:
90+
name: Coding standards
91+
runs-on: ubuntu-latest
92+
steps:
93+
- uses: actions/checkout@v4
94+
95+
- name: Setup PHP
96+
uses: shivammathur/setup-php@v2
97+
with:
98+
php-version: "8.2"
99+
ini-values: "zend.exception_ignore_args=Off"
100+
coverage: none
101+
102+
- name: Install dependencies
103+
run: composer update
104+
105+
- name: Run PHP CS Fixer
106+
run: ./vendor/bin/php-cs-fixer fix --dry-run --verbose --diff
107+
108+
rector:
109+
name: Rector
110+
runs-on: ubuntu-latest
111+
steps:
112+
- uses: actions/checkout@v4
113+
114+
- name: Setup PHP
115+
uses: shivammathur/setup-php@v2
116+
with:
117+
php-version: "8.2"
118+
ini-values: "zend.exception_ignore_args=Off"
119+
coverage: none
120+
121+
- name: Install dependencies
122+
run: composer update
123+
124+
- name: Run Rector
125+
run: ./vendor/bin/rector --dry-run

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor
2+
.php-cs-fixer.cache
3+
composer.lock

.php-cs-fixer.dist.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
use PhpCsFixer\Finder;
4+
use PhpCsFixer\Config;
5+
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
6+
use PhpCsFixer\Fixer\Phpdoc\PhpdocSeparationFixer;
7+
8+
$finder = (new Finder())
9+
->in(__DIR__)
10+
;
11+
12+
return (new Config())
13+
->setParallelConfig(ParallelConfigFactory::detect())
14+
->setRules([
15+
'@Symfony' => true,
16+
'concat_space' => false, // override Symfony
17+
'global_namespace_import' => [ //override Symfony
18+
'import_classes' => true,
19+
'import_constants' => true,
20+
'import_functions' => true,
21+
],
22+
'phpdoc_align' => false, //override Symfony
23+
'phpdoc_separation' => [ // override Symfony
24+
'groups' => [
25+
['Annotation', 'NamedArgumentConstructor', 'Target'],
26+
['Given', 'When', 'Then'],
27+
...PhpdocSeparationFixer::OPTION_GROUPS_DEFAULT,
28+
],
29+
],
30+
'single_line_throw' => false, //override Symfony
31+
'yoda_style' => false, //override Symfony
32+
'phpdoc_to_comment' => [ // Keep as a phpdoc if it contains the `@var` annotation
33+
'ignored_tags' => ['var'],
34+
],
35+
])
36+
->setFinder($finder);

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Permission is hereby granted, free of charge, to any person
2+
obtaining a copy of this software and associated documentation
3+
files (the "Software"), to deal in the Software without
4+
restriction, including without limitation the rights to use,
5+
copy, modify, merge, publish, distribute, sublicense, and/or sell
6+
copies of the Software, and to permit persons to whom the
7+
Software is furnished to do so, subject to the following
8+
conditions:
9+
10+
The above copyright notice and this permission notice shall be
11+
included in all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20+
OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Behat MCP Server
2+
3+
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server for the [Behat](https://behat.org) BDD testing framework. This server allows AI assistants (such as Claude, Cursor, or other MCP-compatible clients) to run Behat tests directly.
4+
5+
> **Note:** This MCP server currently does not run on Windows due to PHP's limitations with non-blocking pipes.
6+
7+
## Installation
8+
9+
Install via Composer:
10+
11+
```bash
12+
composer require behat/mcp-server
13+
```
14+
15+
## Starting the MCP Server
16+
17+
The MCP server can be started using the `behat-mcp-server` command:
18+
19+
```bash
20+
vendor/bin/behat-mcp-server
21+
```
22+
23+
### Command Line Options
24+
25+
| Option | Short | Description | Default |
26+
|--------|-------|-------------|---------|
27+
| `--transport` | `-t` | Transport type (`stdio` or `http`) | `stdio` |
28+
| `--host` | `-o` | Host for HTTP transport | `127.0.0.1` |
29+
| `--port` | `-p` | Port for HTTP transport | `8080` |
30+
31+
### Examples
32+
33+
Start with stdio transport (default):
34+
35+
```bash
36+
vendor/bin/behat-mcp-server
37+
```
38+
39+
Start with HTTP transport:
40+
41+
```bash
42+
vendor/bin/behat-mcp-server --transport=http --host=127.0.0.1 --port=8080
43+
```
44+
45+
## Available Tools
46+
47+
### `run-behat-tests`
48+
49+
Runs Behat BDD tests in the current project.
50+
51+
#### Parameters
52+
53+
| Parameter | Type | Required | Description |
54+
|-----------|-------|----------|-------------|
55+
| `config` | string | No | Path to a Behat configuration file |
56+
| `profile` | string | No | Name of a profile to use |
57+
| `suite` | string | No | Name of a suite to use |
58+
| `paths` | array | No | List of paths to execute (features or scenarios) |
59+
| `additionalOptions` | array | No | Additional command-line options as key-value pairs |
60+
61+
## Configuring AI Agents
62+
63+
### Stdio Transport
64+
65+
The stdio transport is the recommended method for local development. The MCP server communicates via standard input/output streams.
66+
67+
Add this to your configuration file:
68+
69+
```json
70+
{
71+
"mcpServers": {
72+
"behat": {
73+
"command": "php",
74+
"args": ["/path/to/your/project/vendor/bin/behat-mcp-server"],
75+
"cwd": "/path/to/your/project"
76+
}
77+
}
78+
}
79+
```
80+
81+
### HTTP Transport
82+
83+
The HTTP transport is useful for remote servers or when using Docker.
84+
85+
Start the MCP server using the HTTP transport as described above and add this to your configuration file
86+
(using the host and port that you used when starting the server):
87+
88+
89+
```json
90+
{
91+
"mcpServers": {
92+
"behat": {
93+
"url": "http://127.0.0.1:8080/mcp"
94+
}
95+
}
96+
}
97+
```
98+
99+
## License
100+
101+
MIT License. See [LICENSE](LICENSE) for details.

bin/behat-mcp-server

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
declare(strict_types=1);
5+
6+
use Behat\McpServer\Command\McpServerCommand;
7+
use Symfony\Component\Console\Application;
8+
9+
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
10+
require __DIR__ . '/../vendor/autoload.php';
11+
} elseif (file_exists(__DIR__ . '/../../../autoload.php')) {
12+
require __DIR__ . '/../../../autoload.php';
13+
} else {
14+
fwrite(STDERR, "Could not find autoloader. Please run 'composer install'.\n");
15+
exit(1);
16+
}
17+
18+
$application = new Application('Behat MCP Server', '1.0.0');
19+
$application->add(new McpServerCommand());
20+
$application->setDefaultCommand('mcp:serve', true);
21+
$application->run();

composer.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "behat/mcp-server",
3+
"description": "MCP Server for Behat BDD testing framework",
4+
"type": "library",
5+
"license": "MIT",
6+
"bin": ["bin/behat-mcp-server"],
7+
"autoload": {
8+
"psr-4": {
9+
"Behat\\McpServer\\": "src/"
10+
}
11+
},
12+
"autoload-dev": {
13+
"psr-4": {
14+
"Behat\\McpServer\\Tests\\": "tests/"
15+
}
16+
},
17+
"require": {
18+
"php": ">=8.2 <8.6",
19+
"behat/behat": "^3.29",
20+
"php-mcp/server": "^3.3",
21+
"symfony/console": "^6.4 || ^7.0",
22+
"evenement/evenement": "^2.0 || ^3.0"
23+
},
24+
"require-dev": {
25+
"php-cs-fixer/shim": "^3.89",
26+
"phpstan/phpstan": "^2.1",
27+
"phpunit/phpunit": "^9.6 || ^10.0",
28+
"react/async": "^4.3",
29+
"react/child-process": "^0.6.7",
30+
"react/http": "^1.11",
31+
"react/promise-timer": "^1.11",
32+
"rector/rector": "^2.1",
33+
"symfony/filesystem": "^6.4 || ^7.0",
34+
"symfony/process": "^6.4 || ^7.0"
35+
},
36+
"scripts": {
37+
"all-tests": [
38+
"@cs",
39+
"@behat",
40+
"@phpstan",
41+
"@rector"
42+
],
43+
"behat": "behat --no-colors",
44+
"cs": "php-cs-fixer fix --dry-run --verbose --diff",
45+
"cs-fix": "php-cs-fixer fix",
46+
"phpstan": "phpstan analyse",
47+
"rector": "rector --dry-run",
48+
"rector-fix": "rector"
49+
}
50+
}

0 commit comments

Comments
 (0)