Optimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents).#2535
Conversation
In CLI mode, log messages emitted by the Azure SDK HTTP pipeline and the .NET logging infrastructure were written to stdout alongside the JSON response payload. This inflated token consumption by ~66% for agents consuming raw stdout (e.g. ~55K tokens vs ~33K JSON-only tokens per the benchmark in kvenkatrajan/fuse-poc). Set LogToStandardErrorThreshold = LogLevel.Trace so that all console log messages are routed exclusively to stderr. Stdout now contains only the JSON CommandResponse. Pipelines using 2>$null or | ConvertFrom-Json work without stripping info: prefixes. MCP server mode (ServiceStartCommand) is unaffected - it already uses ClearProviders() and never adds a console logger except under --debug, where LogToStandardErrorThreshold was already set correctly. Docs: added a CLI logging note to azmcp-commands.md explaining the stdout/stderr split and showing 2>&1 / 2>$null / 2>file.log patterns.
jongio
left a comment
There was a problem hiding this comment.
Clean fix - LogToStandardErrorThreshold = LogLevel.Trace correctly routes all console log output to stderr, keeping stdout clean for JSON. Server mode is unaffected since ServiceStartCommand already calls ClearProviders() and only re-adds console logging under --debug (with stderr configured).
One thing to consider: Fabric.Mcp.Server/src/Program.cs and Template.Mcp.Server/src/Program.cs both have the identical plain AddConsole() without the stderr threshold. Worth fixing those in a follow-up (or this PR if scope allows) so the same issue doesn't persist in the other servers.
Docs and changelog look good.
There was a problem hiding this comment.
Pull request overview
Redirects azmcp CLI logging away from stdout so that stdout remains clean JSON (reducing downstream token usage and avoiding parser noise), while logs/diagnostics go to stderr.
Changes:
- Configure console logging to route all log levels to stderr via
LogToStandardErrorThreshold. - Document stdout vs stderr behavior for CLI consumers, including common redirection patterns.
- Add a changelog entry describing the fix.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
servers/Azure.Mcp.Server/src/Program.cs |
Routes console logs to stderr to keep stdout clean for JSON responses. |
servers/Azure.Mcp.Server/docs/azmcp-commands.md |
Documents the stdout/stderr contract and how to redirect logs. |
servers/Azure.Mcp.Server/changelog-entries/1777452002350.yaml |
Adds release-note entry for the stdout/stderr logging change. |
In CLI mode, azmcp was writing informational log messages (Azure SDK HTTP pipeline traces, etc.) to stdout alongside the JSON response. This inflated token consumption for AI agents and pipelines parsing stdout — benchmarks showed up to ~44.5% of stdout bytes were log noise, not JSON.
The issue was AddConsole() in Program.cs defaults LogToStandardErrorThreshold to LogLevel.None, routing all log levels to stdout.
This PR sets LogToStandardErrorThreshold = LogLevel.Trace so every log level routes exclusively to stderr. Stdout now contains only the JSON CommandResponse.
Impact:
No behavior change for interactive terminal users (stderr is visible by default)
AI agents and pipelines consuming stdout receive clean JSON only