Skip to content

Optimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents).#2535

Merged
g2vinay merged 1 commit into
microsoft:mainfrom
g2vinay:fix-token-pollution
Apr 29, 2026
Merged

Optimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents).#2535
g2vinay merged 1 commit into
microsoft:mainfrom
g2vinay:fix-token-pollution

Conversation

@g2vinay
Copy link
Copy Markdown
Contributor

@g2vinay g2vinay commented Apr 29, 2026

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

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.
@g2vinay g2vinay changed the title Rdirect CLI log output from stdout to stderr Update: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents). Apr 29, 2026
@g2vinay g2vinay changed the title Update: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents). OPtimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents). Apr 29, 2026
@g2vinay g2vinay changed the title OPtimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents). Optimize: Redirect CLI log output from stdout to stderr (Optimizes Token usage for Agents). Apr 29, 2026
@g2vinay g2vinay marked this pull request as ready for review April 29, 2026 18:58
@g2vinay g2vinay requested a review from a team as a code owner April 29, 2026 18:58
Copilot AI review requested due to automatic review settings April 29, 2026 18:58
@g2vinay g2vinay requested a review from a team as a code owner April 29, 2026 18:58
Copy link
Copy Markdown
Contributor

@jongio jongio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread servers/Azure.Mcp.Server/src/Program.cs
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread servers/Azure.Mcp.Server/changelog-entries/1777452002350.yaml
Comment thread servers/Azure.Mcp.Server/docs/azmcp-commands.md
@g2vinay g2vinay merged commit ee2366a into microsoft:main Apr 29, 2026
29 checks passed
@github-project-automation github-project-automation Bot moved this from Untriaged to Done in Azure MCP Server Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants