
This fix is part of MCP troubleshooting, within The MCP Guide. Still stuck? Request a free MCP readiness review.
A stdio MCP server uses stdout as its protocol channel, so anything else printed there, such as print("Server started") or console.log(), corrupts the JSON-RPC stream. Clients then show parse errors, ignore messages or drop the connection. The fastest fix is to send all logging to stderr: use Python's logging module or print(..., file=sys.stderr), and console.error() in Node. Then restart the client.
Checked against: the MCP 2026-07-28 stdio transport, the MCP build-a-server tutorial, the MCP debugging guide and the source of the @modelcontextprotocol/sdk 1.32.2 npm package on 2 November 2026. Python defaults were checked by running Python 3.9 locally. eSEOspace did not test servers in each client.
Key Takeaways
- The stdio spec says the server "MUST NOT write anything to its stdout that is not a valid MCP message" and "MAY write UTF-8 strings to stderr" for logging.
- The build tutorial warns that writing to stdout "will corrupt the JSON-RPC messages and break your server."
- Python's
print()defaults to stdout;logging.basicConfig()sets up a handler that writes to stderr. - In Node,
console.log()writes to stdout andconsole.error()writes to stderr. - HTTP servers are different: the tutorial says stdout logging "is fine since it doesn't interfere with HTTP responses."
What this error means
With the stdio transport, the client starts your server and reads its stdout one line at a time. Each line must be one JSON-RPC message. The stdio spec says messages are "delimited by newlines" and must not contain embedded newlines.
When your code prints "Connecting to database..." to stdout, the client reads it as a message and fails to parse it. In the TypeScript SDK 1.32.2 client, each line goes through JSON.parse. A non-JSON line raises an error, which that client reports and then skips. Other clients may close the connection. Either way, the server looks broken even though its tools are fine.
stderr is the safe channel. The spec says the client "MAY capture, forward, or ignore" stderr and "SHOULD NOT assume stderr output indicates error conditions." The MCP debugging guide says messages logged to stderr "will be captured by the host application automatically."
Quick fix
- Search your code for
print(,console.log(,System.out.println,Console.WriteLine,putsandprintln. - Replace them with stderr logging (examples below).
- Check dependencies. Libraries, progress bars and package managers sometimes print to stdout. Turn their output off or point it at stderr.
- Run the server by hand and send nothing. If any text appears on stdout before a request, something still prints there. In a shell,
your-server-command 2>/dev/nullhides stderr so only stdout shows. - Restart the client and read the server log.
Python
The build tutorial recommends "the standard library logging module, which writes to stderr":
import logging
import sys
logging.basicConfig(level=logging.INFO) # default stream is stderr
logger = logging.getLogger(__name__)
# Bad on stdio: goes to stdout
# print("Processing request")
# Good: logging writes to stderr by default
logger.info("Processing request")
# Also fine: print explicitly to stderr
print("Processing request", file=sys.stderr)
Python's own print docstring says it prints "to sys.stdout by default," which is why a stray print() breaks the stream.
TypeScript and Node
The tutorial says: "Never use console.log()" on a stdio server, and use console.error() or a logger that writes to stderr or files.
// Bad on stdio
// console.log("Server started");
// Good: stderr is safe
console.error("Server started");
Java, Kotlin, C# and Ruby
The tutorial gives the same rule for each: avoid System.out.println() in Java, println() in Kotlin, Console.WriteLine() in C# and puts or print in Ruby on stdio servers. Configure your logging framework so it never writes to stdout.
Fix by client / OS
Claude Desktop
The local server guide says files named mcp-server-SERVERNAME.log "contain the stderr output from the named server." Once your logs go to stderr, they show up there. Folders: ~/Library/Logs/Claude (macOS), %APPDATA%\Claude\logs (Windows), ~/.config/Claude/logs (Linux).
Cursor
Open the Output panel and pick MCP Logs, per Cursor's MCP docs.
Claude Code
Check /mcp and claude mcp get <name> for the error. Server stderr is not the protocol channel, so moving logs there does not affect Claude Code's connection.
HTTP servers
For Streamable HTTP, the debugging guide says "stderr is not captured by the client." Use your own log aggregation or OpenTelemetry. stdout logging is fine there.
Where to find the logs
| Client | stderr ends up in |
|---|---|
| Claude Desktop | mcp-server-SERVERNAME.log |
| Cursor | Output panel, MCP Logs |
| VS Code | MCP: List Servers > Show Output |
| Remote server | Your host's logs |
If it still fails
- You see
-32700or "Unexpected token." See JSON-RPC parse error. - The server disconnects. See Connection closed.
- You used protocol logging. The debugging guide says
notifications/messagelogging is deprecated as of protocol version 2026-07-28. See MCP logging status. - You want better logs. The logging and monitoring lesson covers what to record, and the stdio transport reference covers the framing rules.
Paste any error code into the MCP error code lookup. If you want a second pair of eyes on a server before you ship it, our MCP development team does reviews.
More in the MCP Guide
Free tools: MCP Error Code Lookup · MCP Config Generator
Latest research: State of MCP: October 2026
Frequently asked questions
Why can't my MCP server print to stdout?
On stdio, stdout carries the JSON-RPC protocol. The spec forbids anything else there, so a stray line looks like a broken message to the client.
Is it safe to log to stderr?
Yes. The spec allows servers to write UTF-8 log text to stderr, and clients should not treat stderr output as an error by itself.
Does this apply to remote MCP servers?
No. HTTP servers send protocol messages in HTTP responses, so stdout logging does not interfere. The build tutorial says stdout logging is fine for HTTP-based servers.
Should I log secrets to help debugging?
No. The debugging guide lists sanitizing logs, protecting credentials and masking personal information as best practices. See MCP secret leakage for why.











