beyondcode / beyondcode/herd-community

[Bug]: herd-mcp.phar emits non-JSON [warning] on stdout for completion/complete (breaks Cursor MCP)

Open
#1,702 0 comments 0 reactions 0 assignees View on GitHub
macOS
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.