beyondcode / beyondcode/herd-community
[Bug]: herd-mcp.phar emits non-JSON [warning] on stdout for completion/complete (breaks Cursor MCP)
- Dominant language
- No language data
- Stars
- 122
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
## Environment
- **Herd:** 1.28.0 (reported as latest on macOS)
- **Client:** Cursor (MCP over stdio)
- **MCP server:** `php /Applications/Herd.app/Contents/Resources/herd-mcp.phar`
- **Config** (project `.cursor/mcp.json`):
```json
{
"mcpServers": {
"herd": {
"command": "php",
"args": ["/Applications/Herd.app/Contents/Resources/herd-mcp.phar"],
"env": {
"SITE_PATH": "/Users/foo/bar/example-project"
}
}
}
}
```
## Summary
After a successful MCP handshake, Cursor disconnects with:
```
Client error: Unexpected token 'w', "[warning] F"... is not valid JSON
```
Root cause: `herd-mcp.phar` writes a **plain-text** log line to **stdout** (not stderr) when handling `completion/complete`. MCP stdio transport requires **only JSON-RPC lines on stdout**; any other output breaks the client parser.
This is **not** a PHP `E_WARNING` — PHP flags such as `-d display_errors=0` / `-d error_reporting=0` do not suppress this line.
## Steps to reproduce
1. Configure Herd MCP in Cursor as above.
2. Connect — `initialize` succeeds; `tools/list`, `prompts/list`, `resources/list` succeed.
3. Cursor calls `completion/complete` because the server advertises a prompt.
Minimal repro (stdin, one JSON object per line):
```bash
export SITE_PATH="/Users/foo/bar/example-project"
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":5,"method":"completion/complete","params":{"ref":{"type":"ref/prompt","name":"debug_site"},"argument":{"name":"task","value":""}}}' \
| php /Applications/Herd.app/Contents/Resources/herd-mcp.phar
```
## Actual stdout (two lines — first line breaks clients)
**Line 1 (non-JSON on stdout):**
```
[warning] Failed to create response: No handler found for method "completion/complete".
```
**Line 2 (valid JSON-RPC error):**
```json
{"jsonrpc":"2.0","id":5,"error":{"code":-32601,"message":"No handler found for method \"completion/complete\"."}}
```
Cursor fails on line 1 (`Unexpected token 'w'` from `[warning] F...`).
## What Cursor sends
After `prompts/list` returns a prompt, Cursor requests autocomplete for the prompt argument:
```json
{
"jsonrpc": "2.0",
"id": 5,
"method": "completion/complete",
"params": {
"ref": { "type": "ref/prompt", "name": "debug_site" },
"argument": { "name": "task", "value": "" }
}
}
```
`prompts/list` currently returns (abridged):
```json
{
"prompts": [
{
"name": "debug_site",
"description": "Perform debug operations on a site...",
"arguments": [
{
"name": "task",
"required": true,
"description": "The debugging task to perform..."
}
]
}
]
}
```
Advertising `prompts` with arguments is valid MCP; clients may call `completion/complete`. The server should either implement the handler or return only JSON-RPC on stdout (errors belong in JSON; log lines belong on stderr).
## Expected behavior
- No non-JSON lines on stdout, **or**
- Implement `completion/complete`, **or**
- Do not advertise prompts if completion is unsupported
## Workaround (client-side)
Filter stdout so only lines starting with `{` are forwarded (community workaround from [laravel/boost#539](https://github.com/laravel/boost/issues/539)).
## Related
- [laravel/boost#539](https://github.com/laravel/boost/issues/539) (closed; documents same root cause)
- [Discussion: Herd MCP server fails in Cursor](https://github.com/beyondcode/herd-community/discussions/1644)
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.