This repository provides a minimal scaffold to run a Model Context Protocol (MCP) server for ProcessWire using the php-mcp/server ecosystem. It's intended as a developer-friendly starting point so you can quickly iterate on tools and transports.
Requirements
Quick start
- Install dependencies
composer install- Run discovery of available tools
php server.php --discover- Start the server using stdin/stdout transport (good for local agent integrations)
php server.php --transport=stdioSend a JSON request on a single line (example):
{"action":"serverInfo","params":{}}- Start a simple HTTP transport (requires
react/httpinstalled via composer)
php server.php --transport=http --host=127.0.0.1 --port=8080Then browse http://127.0.0.1:8080/ to see the tools list, or call /{toolName}?param=value to run an example tool.
This project can be easily developed, run and debugged from Visual Studio Code. Below are recommended steps and example configuration you can drop into .vscode/ in this project.
- Recommended extensions
- PHP Debug (felixfbecker.php-debug) — attach/launch debugging sessions with Xdebug
- PHP Intelephense (bmewburn.vscode-intelephense-client) — code intelligence
- Composer (ikappas.vscode-composer) — helper commands
- PHPUnit (emallin.phpunit) — test runner integration
- Install dependencies
Open the project in VS Code and run the Terminal → New Terminal then:
composer install- Launch / debug server
If you have Xdebug configured, you can add the following debug config to .vscode/launch.json and use the VS Code debug panel to start the server under the debugger.
Example .vscode/launch.json configuration:
{
"version": "0.2.0",
"configurations": [
{
"name": "PHP: Run server (stdio transport)",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/server.php",
"args": ["--transport=stdio"],
"cwd": "${workspaceFolder}",
"runtimeExecutable": "php"
},
{
"name": "PHP: Run server (http transport)",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/server.php",
"args": ["--transport=http","--host=127.0.0.1","--port=8080"],
"cwd": "${workspaceFolder}",
"runtimeExecutable": "php"
}
]
}Notes: the debug launch will start the script using the system PHP binary. Make sure PHP is accessible in PATH and Xdebug is enabled with xdebug.mode=debug.
- Use VS Code Tasks
You can add tasks to run common commands (install, run tests) from the command palette or terminal.
Example .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "composer install",
"type": "shell",
"command": "composer install",
"problemMatcher": []
},
{
"label": "phpunit",
"type": "shell",
"command": "vendor/bin/phpunit --colors=always",
"problemMatcher": []
},
{
"label": "discover tools",
"type": "shell",
"command": "php server.php --discover",
"problemMatcher": []
}
]
}- Running / testing
- Use the VS Code debug panel to start a server configuration and add breakpoints in
src/to debug handler/tool invocation. - Use the 'phpunit' task or PHPUnit extension to run unit tests from the editor.
That's it — with these small helpers you can iterate quickly in VS Code and run the MCP server or tests with editor integrations.
Integration tests can be run against a real ProcessWire site by placing the ProcessWire site files under tests/fixtures/processwire and ensuring PROCESSWIRE_ROOT is set or the site bootstrap is available.
If you need an automated integration flow, you can add or provide the required scripts and helpers (for example a local web installer or test runner). Integration tests will auto-skip if PROCESSWIRE_ROOT is not set or the expected site bootstrap isn't found.
Installable via Composer
This repository is configured to be installable via Composer as a library package. There are three common ways to use it:
- From Packagist (recommended once published):
composer require your-organization/processwire-mcp-server- From a VCS repository (for development or PRs):
Add a VCS repository entry to your project's composer.json then require the package using the branch name:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/your-organization/processwire-mcp-server"
}
]
}composer require your-organization/processwire-mcp-server:dev-main- Using a local path repository (very convenient for local development):
{
"repositories": [
{
"type": "path",
"url": "../processwire-mcp",
"options": { "symlink": true }
}
]
}composer require your-organization/processwire-mcp-server:dev-main --prefer-sourceIf you want to use the package directly from GitHub without publishing to Packagist, add a VCS repository entry to your consuming project's composer.json then require a branch or tag. Example:
- Add the VCS repository to your project's
composer.json:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/choirool/processwire-mcp"
}
]
}- Require the package from the repo (here we use the master branch):
composer require choirool/processwire-mcp:dev-master --prefer-sourceNotes:
- Use
--prefer-sourceif you want composer to clone the repository (useful for development and patching). Omit it to install a distribution archive when available. - You can also reference a specific tag or commit (
choirool/processwire-mcp:1.0.0orchoirool/processwire-mcp:dev-master#commit-hash).
Notes:
- Replace
your-organizationwith your GitHub organization or vendor name. The examplehomepage,supportandauthorsincomposer.jsonshould also be updated to match your project. - After publishing on Packagist, consumers can require the package directly with
composer require your-organization/processwire-mcp-server.
Once the package is required in your project, helper commands are exposed via vendor/bin/pw-mcp.
Use these to scaffold editor helper files and to run or discover the packaged MCP server:
# create a simple editor helper file in the current project
vendor/bin/pw-mcp install
# run the server using stdio transport
vendor/bin/pw-mcp run --transport=stdio
# discover available tools (printed to stdout)
vendor/bin/pw-mcp discoverComposer scripts are also installed (available in your project after requiring this package):
composer setup # run vendor/bin/pw-mcp install
composer start # run vendor/bin/pw-mcp run --transport=stdio
composer discover # run vendor/bin/pw-mcp discoverThe install helper supports a few convenience flags to write editor snippets and example configurations into your project:
--vscode— write.mcp.jsonand helper.vscode/launch.json+.vscode/tasks.jsonconfigured to runvendor/bin/pw-mcp.--phpstorm— write a.phpstorm-mcp.jsonsample file for JetBrains editors that points tovendor/bin/pw-mcp.--all— write both VS Code and PhpStorm examples.--force— overwrite any existing files when running the installer.
Examples:
# create editor helper + VS Code integration files
vendor/bin/pw-mcp install --vscode
# write both vscode and phpstorm samples, overwrite existing files
vendor/bin/pw-mcp install --all --force- Create a GitHub repository (or other public VCS) and push this project there.
- Create a Packagist account and submit the repository URL.
- After Packagist indexes the repo you can require the package with
composer require your-organization/processwire-mcp-server.
If you prefer not to publish the package publicly, using a VCS or path repository (above) is a common alternative for teams and CI pipelines.
Testing
composer testSecurity notes
Next steps
Implemented tool groups (sample):
- $page tools: get_current_page, get_page_parent, get_page_children, get_page_template, get_page_fields, update_page_field
- $pages tools: get_page_by_id, get_page_by_path, find_pages, create_page, update_page_fields, delete_page, duplicate_page, move_page
- $user tools: get_current_user, list_users, create_user, update_user_fields, change_user_password, delete_user, add_role_to_user, remove_role_from_user
Also implemented tool groups (sample):
- $input tools: get_query_param, get_post_param, get_cookie_param, get_url_segment, get_page_number
- $sanitizer tools: sanitize_text, sanitize_int, sanitize_float, sanitize_email, sanitize_url, sanitize_boolean, sanitize_date
- $session tools: get_session_variable, set_session_variable, remove_session_variable, login_user, logout_user, is_user_logged_in, redirect_to