Skip to content

Commit ac17129

Browse files
committed
Replace dashes with plain punctuation in prose added by this branch
No-Verification-Needed: docstring and docs prose only
1 parent 52d9409 commit ac17129

5 files changed

Lines changed: 9 additions & 8 deletions

File tree

docs/get-started/real-host.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ Once that command sits and waits, what's left is almost always one of three thin
165165

166166
* **A relative path.** The host launches your server from *its* working directory, not the one you registered from. `server.py` where `/absolute/path/to/server.py` is needed is the single most common failure. If the host can't find `uv` either, that path has to be absolute too.
167167
* **The host is still running its old config.** Hosts read their config at launch. Claude Desktop in particular has to be *fully quit* (not just its window closed) and reopened before an edit to `claude_desktop_config.json` takes effect.
168-
* **Something reached stdout before serving began.** On stdio, stdout *is* the protocol. The SDK diverts stray output to stderr while serving, but anything that reaches stdout before then -- a wrapper script echoing, an import-time `print()` in an unbuffered process -- hands the host a corrupt message and it drops the connection. Log with the `logging` module, which writes to stderr. **[Logging](../handlers/logging.md)** has the whole story.
168+
* **Something reached stdout before serving began.** On stdio, stdout *is* the protocol. The SDK diverts stray output to stderr while serving, but anything that reaches stdout before then (a wrapper script echoing, an import-time `print()` in an unbuffered process) hands the host a corrupt message and it drops the connection. Log with the `logging` module, which writes to stderr. **[Logging](../handlers/logging.md)** has the whole story.
169169

170170
Claude Desktop keeps a log per server: `mcp-server-<NAME>.log` is your server's stderr, next to `mcp.log` for connections, under `~/Library/Logs/Claude` on macOS and `%APPDATA%\Claude\logs` on Windows.
171171

docs/handlers/logging.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The standard library already does the right thing: log output goes to `sys.stder
3535
!!! tip
3636
Don't `print()` in a stdio server. `print` writes to **stdout**, and stdout belongs to the protocol:
3737
while serving, the SDK diverts stray stdout to stderr so it can't corrupt the wire, but that leaves
38-
your line interleaved raw among the log output -- no level, no logger name, no way to filter it.
38+
your line interleaved raw among the log output, with no level, no logger name, and no way to filter it.
3939

4040
`logger.debug("got here")` is the same one line of effort and goes to the right place.
4141

@@ -73,7 +73,7 @@ went to standard error: the terminal, not the wire.
7373
* The MCP protocol's logging capability is deprecated by the 2026-07-28 spec and not replaced. Don't build on it.
7474
* `logger = logging.getLogger(__name__)` at module level, `logger.info(...)` in the tool. That's the whole pattern.
7575
* Log output never reaches the model. Only the value you `return` does.
76-
* Standard error is yours; stdout belongs to the protocol. The SDK diverts a stray `print()` to stderr while serving, but it arrives unlabeled -- use `logging`.
76+
* Standard error is yours; stdout belongs to the protocol. The SDK diverts a stray `print()` to stderr while serving, but it arrives unlabeled; use `logging`.
7777
* `MCPServer(..., log_level="DEBUG")` sets the level, and a logging configuration you made first is left alone.
7878

7979
Telling connected clients that something on your server changed (the tool list, a resource) is **[Subscriptions](subscriptions.md)**.

docs/run/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ python server.py
3939

4040
Nothing prints, and it doesn't return. It is waiting on stdin for a host to speak first.
4141

42-
That also means stdout **is the wire**. While serving, the SDK moves the wire to a private descriptor and diverts stray output -- a `print()`, a subprocess writing to its inherited stdout -- to stderr, where it can't corrupt the stream. Output that reaches stdout *before* serving begins (a wrapper script echoing, an unbuffered import-time print) still lands on the wire. For output you actually want, the `logging` module is the right tool. That story is in **[Logging](../handlers/logging.md)**.
42+
That also means stdout **is the wire**. While serving, the SDK moves the wire to a private descriptor and diverts stray output (a `print()`, or a subprocess writing to its inherited stdout) to stderr, where it can't corrupt the stream. Output that reaches stdout *before* serving begins (a wrapper script echoing, an unbuffered import-time print) still lands on the wire. For output you actually want, the `logging` module is the right tool. That story is in **[Logging](../handlers/logging.md)**.
4343

4444
### Try it
4545

docs/troubleshooting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ There is no error string for this, which is exactly why it is hard to search. Th
137137
* **Is the tool on the `mcp` the host is running?** A second `MCPServer(...)` in another module is a different, empty server. Check which object the host's command actually imports.
138138
* **Did two tools share a name?** Then one of them is gone. Look for `Tool already exists:` in the server log.
139139
* **Is the host's list stale?** Adding a tool after startup only reaches clients that handle `notifications/tools/list_changed`. Restarting the host is the blunt fix.
140-
* **Did something write to `stdout` before the server started serving?** While serving, the SDK diverts stray stdout to stderr (best-effort: an environment that replaces the standard streams is served as-is), but output flushed to stdout earlier -- a wrapper script echoing, an import-time `print()` in an unbuffered process -- lands on the protocol stream, and one junk line can make the host drop the connection, which some hosts render as a server with nothing in it. Log with the `logging` module instead. The rest of the host-side checklist is on **[Connect to a real host](get-started/real-host.md)**.
140+
* **Did something write to `stdout` before the server started serving?** While serving, the SDK diverts stray stdout to stderr (best-effort: an environment that replaces the standard streams is served as-is), but output flushed to stdout earlier (a wrapper script echoing, an import-time `print()` in an unbuffered process) lands on the protocol stream, and one junk line can make the host drop the connection, which some hosts render as a server with nothing in it. Log with the `logging` module instead. The rest of the host-side checklist is on **[Connect to a real host](get-started/real-host.md)**.
141141

142142
An "invalid" tool name is *not* on that list: a non-conforming name logs a warning but the tool is registered and listed anyway.
143143

src/mcp/server/stdio.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ def _restore_fd(fd: int, private_fd: int) -> None:
115115
async def stdio_server(stdin: anyio.AsyncFile[str] | None = None, stdout: anyio.AsyncFile[str] | None = None):
116116
"""Serve MCP over the process's stdin and stdout.
117117
118-
While serving, fd 0 points at the null device and fd 1 at stderr — handlers
119-
and children read EOF and stray output misses the wire — both restored on exit.
120-
Explicit streams skip the claim; a second concurrent stdio_server() raises RuntimeError.
118+
While serving, fd 0 points at the null device and fd 1 at stderr, so handlers
119+
and children read EOF and their stray output misses the wire; both descriptors
120+
are restored on exit. Explicit streams skip the claim, and a second concurrent
121+
stdio_server() raises RuntimeError.
121122
"""
122123
# Re-wrap the binary buffers as UTF-8 text; the std handles' platform encodings are unreliable.
123124
restore_stdin: Callable[[], None] | None = None

0 commit comments

Comments
 (0)