Fixing Laravel Boost in Windsurf: A Global MCP Setup Guide
If you’ve tried adding Laravel Boost as an MCP server in Windsurf and hit “cannot initialize server”, you’re not alone.
The most common cause is simple:
- Windsurf often starts MCP servers from a working directory that is NOT your Laravel project root.
- So a “normal” MCP command like
php artisan boost:mcpfails becauseartisanisn’t in the current directory (or it runs with the wrong PHP).
In other words: this is usually not a Boost problem — it’s a Windsurf MCP launch context problem.
When Laravel announced Boost, I was thrilled.
I rushed over to the docs expecting to see a simple “Use this with Windsurf” section.
But as I kept scrolling… that smile gradually dropped from my face.
I saw Cursor, Junie, and a bunch of familiar integrations — but not Windsurf.
So I kept searching until I landed on a setup that’s boringly reliable.
This tutorial shows a robust approach that works across all your Laravel projects:
- Install Boost per project (required)
- Add a Windsurf MCP server that calls a wrapper script
- The wrapper script finds the correct Laravel project and runs
php artisan boost:mcp
If you keep multiple Laravel projects open at the same time, you’ll also see how to configure per-project MCP entries so each project stays isolated.
Note: While we’re configuring Windsurf “globally” so it can work with any project, Laravel Boost itself must still be installed locally in every Laravel project via Composer. This wrapper simply helps Windsurf find the correct local installation.
Bonus:
- Add Herd MCP to Windsurf too (handy if you use Herd for local sites/PHP)
The target architecture (what we’re building)
Windsurf can launch MCP servers from arbitrary directories, so the reliable design is to put an adaptive layer in front of Boost:
Windsurf (any cwd)
-> wrapper script (stable entrypoint)
-> find Laravel project root (locate artisan)
-> choose correct PHP (prefer Herd / isolated PHP)
-> exec: php artisan boost:mcp
Once you understand that flow, every config choice in this guide makes sense.
Prerequisites
- You have Windsurf installed
- You have PHP installed (Herd/Homebrew/Linux packages/Windows PHP)
-
Python 3 is recommended (only needed for the optional auto-detection fallback; without it the script falls back to
$PWD/SITE_PATH) - You have at least one Laravel project
Install Boost in each Laravel project (required)
In every Laravel project you want Boost to work with:
composer require laravel/boost --dev
php artisan boost:install
Then verify inside that project:
php artisan boost:mcp
If this fails, fix your Laravel app boot/dependencies first. MCP depends on the app being able to boot.
Understanding Windsurf MCP config files
Windsurf follows the Claude Desktop MCP config schema.
-
Windsurf Editor:
- macOS/Linux:
~/.codeium/mcp_config.json - Windows:
C:\Users\<you>\.codeium\mcp_config.json
- macOS/Linux:
-
Windsurf JetBrains plugin (PhpStorm/IntelliJ):
- macOS/Linux:
~/.codeium/windsurf/mcp_config.json - Windows:
C:\Users\<you>\.codeium\windsurf\mcp_config.json
- macOS/Linux:
Warning: If you edit the wrong file, you’ll keep seeing “cannot initialise server” even though the JSON looks correct.
Quick way to confirm you’re editing the right file:
- Temporarily point the
commandto a definitely-invalid path (or rename your wrapper script). - Refresh MCP servers in Windsurf.
- If the error message doesn’t change, you’re editing the wrong config file.
For the rest of this guide:
- If you’re using the Windsurf Editor, edit
~/.codeium/mcp_config.json - If you’re using Windsurf inside PhpStorm, edit
~/.codeium/windsurf/mcp_config.json
Tip: You can include multiple servers (Boost, Herd, etc.) inside the same mcpServers object.
The Fix: Use a Wrapper Script
Instead of configuring laravel-boost as:
{
"command": "php",
"args": ["artisan", "boost:mcp"]
}
…we configure it to run a wrapper script. The wrapper script:
Phase 1 — Locate the Laravel project root
- Search upward for
artisan - Fall back to other hints like
SITE_PATH - (Optional) Use Windsurf trackers to guess active workspaces (requires Python 3)
Phase 2 — Choose the right PHP
- Prefer Herd’s per-site PHP when available (so isolated sites use their own PHP)
- Fall back to a usable
phpbinary
Phase 3 — Launch MCP
-
exec herd php artisan boost:mcp(preferred) - or
exec <php_bin> artisan boost:mcp
Using the right PHP version per project (Herd + alternatives)
One subtle issue when you have lots of Laravel projects is PHP version drift: one project might require PHP 8.1 while another needs PHP 8.3.
If you use Laravel Herd (recommended)
Herd supports per-site PHP versions via “isolation”. Once a project is isolated, Herd can automatically run the correct PHP when you execute commands from that project.
Set a PHP version for a project:
cd /path/to/your-project
herd isolate 8.3
Confirm what PHP Herd will use for that project:
cd /path/to/your-project
herd which-php
That’s why the wrapper script in this tutorial prefers:
herd php artisan boost:mcp
If you’re not using Herd
You still have options:
-
asdf / mise / phpenv
- These can select PHP based on the current directory (e.g.
.tool-versions/.mise.toml). - The key is ensuring the tool’s “shims” are available to Windsurf (non-interactive process).
- These can select PHP based on the current directory (e.g.
-
Docker / Laravel Sail
- You can run Boost using the project’s containerized PHP instead of your host PHP.
- This is heavier, but very consistent across teams.
-
One global PHP
- If all your projects support the same PHP version, the simplest option is to keep one PHP installed globally (Herd/Homebrew/etc.).
macOS / Linux Setup
Step 1: Create the wrapper script
Create a file at:
- macOS/Linux:
~/.codeium/laravel-boost-mcp.sh
Then make it executable:
chmod +x ~/.codeium/laravel-boost-mcp.sh
Step 2: Add laravel-boost to Windsurf MCP config
Edit:
- Windsurf Editor (macOS/Linux):
~/.codeium/mcp_config.json - Windsurf JetBrains plugin (macOS/Linux):
~/.codeium/windsurf/mcp_config.json
Add (or replace) your laravel-boost entry:
{
"mcpServers": {
"laravel-boost": {
"command": "/Users/<you>/.codeium/laravel-boost-mcp.sh",
"args": ["${workspaceFolder}"],
"disabled": false,
"env": {}
}
}
}
Multi-project isolation (recommended)
If you work on multiple Laravel projects in parallel, create one Boost entry per project (same wrapper, different env), and give each entry a unique server name.
{
"mcpServers": {
"laravel-boost-project-name": {
"command": "/Users/<you>/.codeium/laravel-boost-mcp.sh",
"args": ["${workspaceFolder}"],
"disabled": false,
"env": { "LARAVEL_PROJECT_ROOT": "/path/to/project-name" }
},
"laravel-boost-another-project": {
"command": "/Users/<you>/.codeium/laravel-boost-mcp.sh",
"args": ["${workspaceFolder}"],
"disabled": false,
"env": { "LARAVEL_PROJECT_ROOT": "/path/to/another-project" }
}
}
}
Notes:
- Keep your other MCP servers in the same file; just add this entry inside the existing
mcpServersobject. - The path must be the full absolute path to the script.
If you’re adding multiple MCP servers, don’t replace the whole file—just add laravel-boost inside the existing mcpServers object.
Step 3: Restart/refresh MCP servers in Windsurf
- Open Windsurf settings
- Go to MCP / Tools
- Click refresh (or restart Windsurf)
Step 4: Quick sanity check
Run:
~/.codeium/laravel-boost-mcp.sh --check
You should see:
- what directory it decided is the Laravel project root (
artisan_dir) - which php binary it found as a fallback (
php_bin) - whether Herd CLI is available (
herd_bin) - what Herd would use as the PHP for that project (
herd_which_php) if available
If this output looks correct but Windsurf still can’t start the server, jump to the Troubleshooting section below.
Step 5: Test the wrapper in real-world scenarios
This wrapper is designed to behave well even when Windsurf starts it from a “random” working directory.
Scenario A: Not a Laravel project (expected: skipped)
From any folder that is not a Laravel app:
~/.codeium/laravel-boost-mcp.sh --check
Expected output includes:
skipped (no Laravel project detected; artisan not found)
Scenario B: Laravel project without Boost installed (expected: skipped)
Inside a Laravel project that does NOT have Boost:
cd /path/to/laravel-project
~/.codeium/laravel-boost-mcp.sh --check
Expected output includes:
skipped (Boost not installed in this project)
Scenario C: Laravel project with Boost + Herd per-site PHP (expected: Herd isolated PHP)
Inside a Laravel project with Boost installed:
cd /path/to/laravel-project
composer require laravel/boost --dev
herd isolate 8.3
herd which-php
~/.codeium/laravel-boost-mcp.sh --check
Expected output includes:
herd_bin: ...-
herd_which_php: ...(matching your isolated version)
Then, to confirm it can actually start, run the wrapper (this is a long-running process; stop with Ctrl+C):
~/.codeium/laravel-boost-mcp.sh
Final macOS/Linux wrapper script (multi-project safe)
Save as:
~/.codeium/laravel-boost-mcp.sh
#!/usr/bin/env bash
set -euo pipefail
find_artisan_dir() {
local dir="$1"
while true; do
if [[ -f "$dir/artisan" ]]; then
printf "%s" "$dir"
return 0
fi
local parent
parent="$(dirname "$dir")"
if [[ "$parent" == "$dir" ]]; then
return 1
fi
dir="$parent"
done
}
find_php() {
if command -v php >/dev/null 2>&1; then
command -v php
return 0
fi
local candidates=(
"/opt/homebrew/bin/php"
"/usr/local/bin/php"
"$HOME/Library/Application Support/Herd/bin/php"
)
local p
for p in "${candidates[@]}"; do
if [[ -x "$p" ]]; then
printf "%s" "$p"
return 0
fi
done
return 1
}
get_windsurf_active_paths() {
local py=""
if [[ -x "/usr/bin/python3" ]]; then
py="/usr/bin/python3"
elif command -v python3 >/dev/null 2>&1; then
py="$(command -v python3)"
else
return 0
fi
"$py" - <<'PY'
from pathlib import Path
import re
base = Path.home() / '.codeium' / 'windsurf' / 'code_tracker' / 'active'
if not base.exists():
raise SystemExit(0)
paths = []
for f in base.rglob('*_mcp.json'):
try:
b = f.read_bytes()
except Exception:
continue
for m in re.finditer(br'file:///[^\x00\s"]+', b):
u = m.group(0).decode('utf-8', 'ignore')
if u.startswith('file:///'):
paths.append(u[7:])
seen = set()
for p in paths:
if p in seen:
continue
seen.add(p)
print(p)
PY
}
collect_candidate_start_dirs() {
local candidates=()
candidates+=("$PWD")
if [[ -n "${SITE_PATH:-}" ]]; then
candidates+=("$SITE_PATH")
fi
local p
while IFS= read -r p; do
[[ -n "$p" ]] && candidates+=("$p")
done < <(get_windsurf_active_paths 2>/dev/null || true)
printf "%s\n" "${candidates[@]}" | awk 'NF && !seen[$0]++'
}
start_dir="${PWD}"
artisan_dir=""
check_mode=0
root_arg=""
if [[ "${1:-}" == "--check" ]]; then
check_mode=1
shift
fi
if [[ -n "${1:-}" ]]; then
root_arg="$1"
shift
fi
if [[ -n "${root_arg}" ]] && [[ "${root_arg}" != "\${workspaceFolder}" ]] && [[ "${root_arg}" != "${workspaceFolder}" ]] && [[ "${root_arg}" != "\${workspaceRoot}" ]] && [[ "${root_arg}" != "${workspaceRoot}" ]]; then
if [[ -d "${root_arg}" ]]; then
artisan_dir="$(find_artisan_dir "${root_arg}" 2>/dev/null || true)"
fi
fi
if [[ -z "${artisan_dir}" ]] && [[ -n "${LARAVEL_PROJECT_ROOT:-}" ]]; then
if ! artisan_dir="$(find_artisan_dir "${LARAVEL_PROJECT_ROOT}" 2>/dev/null)"; then
echo "laravel-boost MCP: LARAVEL_PROJECT_ROOT set but artisan not found." >&2
echo "- LARAVEL_PROJECT_ROOT: ${LARAVEL_PROJECT_ROOT}" >&2
exit 1
fi
fi
if [[ -z "${artisan_dir}" ]]; then
while IFS= read -r candidate; do
if artisan_dir="$(find_artisan_dir "$candidate" 2>/dev/null)"; then
break
fi
done < <(collect_candidate_start_dirs)
fi
if [[ -z "$artisan_dir" ]]; then
echo "laravel-boost MCP: skipped (no Laravel project detected; artisan not found)." >&2
echo "- starting directory: $start_dir" >&2
if [[ -n "${SITE_PATH:-}" ]]; then
echo "- SITE_PATH: ${SITE_PATH}" >&2
fi
exit 0
fi
if [[ ! -d "${artisan_dir}/vendor/laravel/boost" ]]; then
echo "laravel-boost MCP: skipped (Boost not installed in this project)." >&2
echo "- artisan_dir: ${artisan_dir}" >&2
echo "Tip: run 'composer require laravel/boost --dev' in this project." >&2
exit 0
fi
php_bin=""
if ! php_bin="$(find_php)"; then
echo "laravel-boost MCP: php binary not found in PATH or common locations." >&2
echo "Ensure PHP is installed and available to your IDE (Herd/Homebrew)." >&2
exit 1
fi
if [[ "${check_mode}" == "1" ]]; then
echo "laravel-boost MCP wrapper check" >&2
echo "- starting directory: ${start_dir}" >&2
if [[ -n "${root_arg}" ]]; then
echo "- root_arg: ${root_arg}" >&2
fi
if [[ -n "${LARAVEL_PROJECT_ROOT:-}" ]]; then
echo "- LARAVEL_PROJECT_ROOT: ${LARAVEL_PROJECT_ROOT}" >&2
fi
if [[ -n "${SITE_PATH:-}" ]]; then
echo "- SITE_PATH: ${SITE_PATH}" >&2
fi
echo "- artisan_dir: ${artisan_dir}" >&2
echo "- php_bin: ${php_bin}" >&2
herd_bin=""
if command -v herd >/dev/null 2>&1; then
herd_bin="$(command -v herd)"
fi
if [[ -n "${herd_bin}" ]]; then
echo "- herd_bin: ${herd_bin}" >&2
herd_php="$(cd "${artisan_dir}" && herd which-php 2>/dev/null || true)"
if [[ -n "${herd_php}" ]]; then
echo "- herd_which_php: ${herd_php}" >&2
fi
else
echo "- herd_bin: <not found>" >&2
fi
exit 0
fi
cd "$artisan_dir"
if command -v herd >/dev/null 2>&1; then
exec herd php artisan boost:mcp
fi
exec "$php_bin" artisan boost:mcp
Add Herd MCP to Windsurf (macOS, Linux, Windows notes)
If you use Laravel Herd, you can also add Herd’s MCP server to Windsurf.
What Herd MCP does
Herd MCP provides tools around Herd’s local dev environment (sites, PHP versions, etc.).
Important OS note
- macOS: Fully supported.
- Windows: Fully supported.
- Linux: Herd is not typically available, so you can skip this section.
Step 1: Create a Herd wrapper script
Create a file at:
- macOS:
~/.codeium/herd-mcp.sh
Make it executable:
chmod +x ~/.codeium/herd-mcp.sh
Step 2: Add the herd server in Windsurf MCP config
Edit:
- macOS:
~/.codeium/windsurf/mcp_config.json
Add (or update) this entry inside mcpServers:
{
"mcpServers": {
"herd": {
"command": "bash",
"args": [
"/Users/<you>/.codeium/herd-mcp.sh",
"${workspaceFolder}"
],
"disabled": false,
"env": {}
}
}
}
Why run it with bash?
- On macOS, some security/xattr quirks can cause direct execution errors.
- Running via
bash <script>tends to be more reliable inside GUI apps.
Windows Herd MCP (no wrapper required)
On Windows, Herd installs its MCP PHAR under:
%USERPROFILE%\.config\herd\bin\herd-mcp.phar
You can add it directly in your MCP config (Windsurf Editor or the JetBrains plugin config file, depending on what you use):
{
"mcpServers": {
"herd": {
"command": "php",
"args": [
"%USERPROFILE%/.config/herd/bin/herd-mcp.phar"
],
"env": {
"SITE_PATH": "YOUR-SITE-PATH"
}
}
}
}
Step 3: Restart/refresh MCP servers
In Windsurf MCP settings, click Refresh (or restart Windsurf).
Step 4: Sanity check
~/.codeium/herd-mcp.sh --check
You should see:
- detected project root (exported as
SITE_PATH) - php binary used
- Herd MCP phar path
Final macOS Herd wrapper script (multi-project safe)
Save as:
~/.codeium/herd-mcp.sh
#!/usr/bin/env bash
# A robust wrapper to start Herd MCP in Windsurf.
#
# Why this exists:
# - Windsurf may launch MCP servers from a directory that is NOT your project.
# - Herd MCP benefits from knowing the project root via SITE_PATH.
#
# What this script does:
# 1) Finds a Laravel project root by searching upwards for an `artisan` file.
# 2) Falls back to SITE_PATH if provided.
# 3) Optionally uses Windsurf trackers to guess your active workspace.
# 4) Finds a usable PHP binary (PATH first, then common locations like Herd).
# 5) Runs Herd's MCP PHAR with SITE_PATH exported.
set -euo pipefail
find_artisan_dir() {
local dir="$1"
while true; do
if [[ -f "$dir/artisan" ]]; then
printf "%s" "$dir"
return 0
fi
local parent
parent="$(dirname "$dir")"
if [[ "$parent" == "$dir" ]]; then
return 1
fi
dir="$parent"
done
}
find_php() {
if command -v php >/dev/null 2>&1; then
command -v php
return 0
fi
local candidates=(
"/opt/homebrew/bin/php"
"/usr/local/bin/php"
"$HOME/Library/Application Support/Herd/bin/php"
"$HOME/Library/Application Support/Herd/bin/php82"
)
local p
for p in "${candidates[@]}"; do
if [[ -x "$p" ]]; then
printf "%s" "$p"
return 0
fi
done
return 1
}
get_windsurf_active_paths() {
local py=""
if [[ -x "/usr/bin/python3" ]]; then
py="/usr/bin/python3"
elif command -v python3 >/dev/null 2>&1; then
py="$(command -v python3)"
else
return 0
fi
"$py" - <<'PY'
from pathlib import Path
import re
base = Path.home() / '.codeium' / 'windsurf' / 'code_tracker' / 'active'
if not base.exists():
raise SystemExit(0)
paths = []
for f in base.rglob('*_mcp.json'):
try:
b = f.read_bytes()
except Exception:
continue
for m in re.finditer(br'file:///[\x21-\x7E]+', b):
u = m.group(0).decode('utf-8', 'ignore')
if u.startswith('file:///'):
paths.append(u[7:])
seen = set()
for p in paths:
if p in seen:
continue
seen.add(p)
print(p)
PY
}
find_herd_mcp_phar() {
local candidates=(
"/Applications/Herd.app/Contents/Resources/herd-mcp.phar"
)
local p
for p in "${candidates[@]}"; do
if [[ -f "$p" ]]; then
printf "%s" "$p"
return 0
fi
done
return 1
}
start_dir="${PWD}"
project_dir=""
check_mode=0
root_arg=""
if [[ "${1:-}" == "--check" ]]; then
check_mode=1
shift
fi
if [[ -n "${1:-}" ]]; then
root_arg="$1"
shift
fi
if [[ -n "${root_arg}" ]] && [[ "${root_arg}" != "\${workspaceFolder}" ]] && [[ "${root_arg}" != "${workspaceFolder}" ]] && [[ "${root_arg}" != "\${workspaceRoot}" ]] && [[ "${root_arg}" != "${workspaceRoot}" ]]; then
if [[ -d "${root_arg}" ]]; then
project_dir="$(find_artisan_dir "${root_arg}" 2>/dev/null || true)"
fi
fi
if [[ -z "${project_dir}" ]] && [[ -n "${LARAVEL_PROJECT_ROOT:-}" ]]; then
if ! project_dir="$(find_artisan_dir "${LARAVEL_PROJECT_ROOT}" 2>/dev/null)"; then
echo "herd MCP: LARAVEL_PROJECT_ROOT set but artisan not found." >&2
echo "- LARAVEL_PROJECT_ROOT: ${LARAVEL_PROJECT_ROOT}" >&2
exit 1
fi
fi
if [[ -z "${project_dir}" ]]; then
while IFS= read -r candidate; do
if project_dir="$(find_artisan_dir "$candidate" 2>/dev/null)"; then
break
fi
done < <(collect_candidate_start_dirs)
fi
if [[ -z "$project_dir" ]]; then
echo "herd MCP: could not find artisan." >&2
echo "- starting directory: $start_dir" >&2
if [[ -n "${SITE_PATH:-}" ]]; then
echo "- SITE_PATH: ${SITE_PATH}" >&2
fi
echo "Tip: Open a Laravel project folder (or set SITE_PATH to the project root) and try again." >&2
exit 1
fi
php_bin=""
if ! php_bin="$(find_php)"; then
echo "herd MCP: php binary not found in PATH or common locations." >&2
exit 1
fi
herd_phar=""
if ! herd_phar="$(find_herd_mcp_phar)"; then
echo "herd MCP: herd-mcp.phar not found." >&2
echo "Tip: Ensure Laravel Herd is installed, or update find_herd_mcp_phar() with your Herd path." >&2
exit 1
fi
if [[ "${check_mode}" == "1" ]]; then
echo "herd MCP wrapper check" >&2
echo "- starting directory: ${start_dir}" >&2
if [[ -n "${root_arg}" ]]; then
echo "- root_arg: ${root_arg}" >&2
fi
if [[ -n "${LARAVEL_PROJECT_ROOT:-}" ]]; then
echo "- LARAVEL_PROJECT_ROOT: ${LARAVEL_PROJECT_ROOT}" >&2
fi
if [[ -n "${SITE_PATH:-}" ]]; then
echo "- SITE_PATH (env): ${SITE_PATH}" >&2
fi
echo "- SITE_PATH (resolved): ${project_dir}" >&2
echo "- php_bin: ${php_bin}" >&2
echo "- herd_phar: ${herd_phar}" >&2
exit 0
fi
export SITE_PATH="${project_dir}"
exec "$php_bin" "$herd_phar"
Combined mcp_config.json example (Boost + Herd)
This is how your MCP config can look with both servers configured (same schema, different file location depending on Windsurf Editor vs JetBrains plugin):
{
"mcpServers": {
"laravel-boost": {
"command": "/Users/<you>/.codeium/laravel-boost-mcp.sh",
"args": ["${workspaceFolder}"],
"disabled": false,
"env": {}
},
"herd": {
"command": "bash",
"args": [
"/Users/<you>/.codeium/herd-mcp.sh",
"${workspaceFolder}"
],
"disabled": false,
"env": {}
}
}
}
Windows Setup (PowerShell)
Windsurf on Windows can also launch MCP servers from an unexpected working directory. The fix is the same idea: use a wrapper.
Step 1: Create the wrapper script
Create:
C:\Users\<you>\.codeium\laravel-boost-mcp.ps1
Step 2: Configure Windsurf MCP to run the script
Edit:
C:\Users\<you>\.codeium\windsurf\mcp_config.json
Add:
{
"mcpServers": {
"laravel-boost": {
"command": "powershell.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
"C:\\Users\\<you>\\.codeium\\laravel-boost-mcp.ps1",
"${workspaceFolder}"
]
}
}
}
Step 3: Restart/refresh MCP servers in Windsurf
Refresh MCP servers (or restart Windsurf).
Final Windows PowerShell wrapper script (well-commented)
Save as:
C:\Users\<you>\.codeium\laravel-boost-mcp.ps1
<#
A robust wrapper to start Laravel Boost MCP in Windsurf on Windows.
Why this exists:
- Windsurf may start MCP servers from a non-project directory.
- `php artisan boost:mcp` fails if it can’t find `artisan`.
What this script does:
1) Finds a Laravel project root by walking up directories looking for `artisan`.
2) Falls back to SITE_PATH if provided.
3) Finds a usable php binary.
4) Runs `php artisan boost:mcp` inside the detected project.
Usage:
- Check mode:
.\laravel-boost-mcp.ps1 --check
#>
param(
[Parameter(ValueFromRemainingArguments=$true)]
[string[]]$Args
)
function Find-ArtisanDir([string]$StartDir) {
$dir = Resolve-Path $StartDir
while ($true) {
if (Test-Path (Join-Path $dir 'artisan')) {
return $dir
}
$parent = Split-Path $dir -Parent
if ($parent -eq $dir) {
return $null
}
$dir = $parent
}
}
function Find-Php() {
# Prefer php on PATH
$php = Get-Command php -ErrorAction SilentlyContinue
if ($php) { return $php.Source }
# Common candidates
$candidates = @(
"C:\\Program Files\\PHP\\php.exe",
"C:\\PHP\\php.exe"
)
foreach ($c in $candidates) {
if (Test-Path $c) { return $c }
}
return $null
}
$startDir = Get-Location
$artisanDir = $null
$checkMode = $false
$rootArg = $null
# Support: --check [<workspaceFolder>]
if ($Args.Count -gt 0 -and $Args[0] -eq '--check') {
$checkMode = $true
if ($Args.Count -gt 1) {
$Args = $Args[1..($Args.Count - 1)]
} else {
$Args = @()
}
}
if ($Args.Count -gt 0) {
$rootArg = $Args[0]
}
# 1) If Windsurf passed the project path explicitly (via ${workspaceFolder}), use it first
if ($rootArg -and $rootArg -ne '${workspaceFolder}' -and (Test-Path $rootArg)) {
$artisanDir = Find-ArtisanDir $rootArg
}
# 2) Try from current directory
if (-not $artisanDir) {
$artisanDir = Find-ArtisanDir $startDir
}
# 3) Fallback to SITE_PATH if provided
if (-not $artisanDir -and $env:SITE_PATH) {
$artisanDir = Find-ArtisanDir $env:SITE_PATH
}
if (-not $artisanDir) {
Write-Error "laravel-boost MCP: could not find artisan. Starting directory: $startDir"
if ($env:SITE_PATH) { Write-Error "SITE_PATH: $($env:SITE_PATH)" }
exit 1
}
$phpBin = Find-Php
if (-not $phpBin) {
Write-Error "laravel-boost MCP: php binary not found. Ensure PHP is installed and available in PATH."
exit 1
}
if ($checkMode) {
Write-Host "laravel-boost MCP wrapper check"
Write-Host "- starting directory: $startDir"
if ($rootArg) { Write-Host "- root_arg: $rootArg" }
if ($env:SITE_PATH) { Write-Host "- SITE_PATH: $($env:SITE_PATH)" }
Write-Host "- artisan_dir: $artisanDir"
Write-Host "- php_bin: $phpBin"
exit 0
}
Set-Location $artisanDir
& $phpBin artisan boost:mcp
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Could not open input file: ./artisan |
MCP server started outside project root | Use the wrapper script (it finds artisan by walking up directories) |
| “Cannot initialize server” never changes | Edited the wrong MCP config file | Verify the config path; use the temporary “invalid command” test above |
| MCP starts, but Boost tools are missing | Boost not installed in that project |
composer require laravel/boost --dev in the target project |
php artisan boost:mcp fails in terminal |
Laravel app can’t boot | Fix the underlying Laravel error first (env/config/extensions) |
| Wrong PHP version / missing extensions | Windsurf uses PATH PHP, not project PHP | |
| Wrong project info returned (multi-project) | MCP server reused across projects, or wrapper guessed the wrong root | |
| Auto-detection doesn’t work |
python3 not available |
Quick checks
- Run
~/.codeium/laravel-boost-mcp.sh --checkand confirm the resolvedartisan_diris the correct project.
- If you use Herd, confirm herd which-php matches what you expect in that directory.
Summary
- Windsurf MCP servers can fail if started from the wrong working directory.
- A wrapper script that finds
artisanand a workingphpmakes Boost reliable. - Configure Windsurf to run the wrapper instead of
php artisan boost:mcpdirectly.
What this teaches us about AI tooling (meta takeaway)
This isn’t unique to Windsurf or Boost.
Any AI tool that shells out to a project-specific CLI will eventually hit the same class of issues:
- The tool assumes
cwdis the project root. - The tool assumes the runtime (PHP, Node, Python, etc.) matches the project.
The durable solution is the same pattern you used here: create an adaptive entrypoint that can find the project, select the right runtime, and print diagnostics when things go wrong.
If this helped, consider sharing your wrapper suggestions and or improvements back to the community.
Top comments (0)