Links
Correction to the original issue
This issue previously proposed migrating to MCP logging notifications (notifications/message). That is now against spec guidance. From the 2026-07-28 logging specification:
Deprecated: The Logging feature is deprecated as of protocol version 2026-07-28 (SEP-2577). [...] New implementations SHOULD NOT adopt it; existing implementations SHOULD migrate to logging to stderr for stdio transports, or to OpenTelemetry for structured observability.
Also withdrawn: the claim that "most clients ignore stderr". The spec says clients MAY capture, forward, or ignore it, and current MCP debugging guidance says stdio hosts capture stderr.
Problem
Four bare print() calls remain, for a defaults-file conflict warning and three filter resolution messages.
They are not corrupting the protocol. The SDK takes a private duplicate of fd 1 for the wire and re-points fd 1 at stderr, so print() lands on stderr. The SDK does have documented fallback paths where the diversion is not established and the stream is served in place; on those a stray print() would splice non-JSON into a stream the client parses strictly.
The real problems are that print() has no level, no logger name, and no way to be filtered, and that some of these messages matter to the model and never reach it.
Revised approach, split by audience
| Audience |
Channel |
| The model, for anything affecting the result |
The tool result text. Dropped media, ignored parameters, format fallbacks |
| A human debugging |
logging module to stderr, with levels and a logger name |
| Neither |
Delete the message |
Acceptance criteria
Out of scope
OpenTelemetry. Worth revisiting only if structured observability is ever needed.
Links
docs/audits/2026-08-agent-workflow-audit.md→ Finding 7src/mcp_pandoc/server.pyL209, L280, L282, L285Correction to the original issue
This issue previously proposed migrating to MCP logging notifications (
notifications/message). That is now against spec guidance. From the 2026-07-28 logging specification:Also withdrawn: the claim that "most clients ignore stderr". The spec says clients MAY capture, forward, or ignore it, and current MCP debugging guidance says stdio hosts capture stderr.
Problem
Four bare
print()calls remain, for a defaults-file conflict warning and three filter resolution messages.They are not corrupting the protocol. The SDK takes a private duplicate of fd 1 for the wire and re-points fd 1 at stderr, so
print()lands on stderr. The SDK does have documented fallback paths where the diversion is not established and the stream is served in place; on those a strayprint()would splice non-JSON into a stream the client parses strictly.The real problems are that
print()has no level, no logger name, and no way to be filtered, and that some of these messages matter to the model and never reach it.Revised approach, split by audience
loggingmodule to stderr, with levels and a logger nameAcceptance criteria
print()insrc/mcp_pandoc/loggingto stderr with sensible levelsprint()in the packagenotifications/messageand nologgingcapability declarationOut of scope
OpenTelemetry. Worth revisiting only if structured observability is ever needed.