Skip to content

Add MCP output size measurement tooling - #3288

Merged
Larry Osterman (LarryOsterman) merged 13 commits into
mainfrom
larryosterman-mcp-output-size-measurement
Aug 25, 2026
Merged

Add MCP output size measurement tooling#3288
Larry Osterman (LarryOsterman) merged 13 commits into
mainfrom
larryosterman-mcp-output-size-measurement

Conversation

@LarryOsterman

@LarryOsterman Larry Osterman (LarryOsterman) commented Aug 14, 2026

Copy link
Copy Markdown
Member

Why

MCP clients benefit from understanding the protocol cost of tool discovery and learn-mode responses. This adds a repeatable, opt-in measurement workflow to compare consolidated and namespace server modes.

This tool is written as a test to take advantage of the existing MCP test infrastructure that invokes the MCP tool so that the metrics can be generated based on the actual output of the MCP server.

Approach

  • Adds an opt-in stdio integration test that captures initialize, discovery, top-level learn, and per-command learn responses across both modes.
  • Writes structured reports and response artifacts, including decoded top learn descriptions and extracted inner-command schemas.
  • Adds PowerShell scripts to summarize JSON reports as console, JSON, and Markdown output, and to run build, measurement, and summarization end to end.

Validation

Ran the end-to-end measurement script successfully.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an opt-in measurement workflow to quantify MCP server response sizes (initialize, tools/list discovery, and learn-mode tool/command responses) to help compare protocol cost between consolidated and namespace modes.

Changes:

  • Adds an opt-in stdio integration test that starts azmcp in both modes and records response sizes + artifacts.
  • Adds a summarization script to compare modes, emit console/JSON/Markdown summaries, and extract learn text / inner-command schemas.
  • Adds an end-to-end runner script that builds, runs the measurement test, and then summarizes results.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/McpOutputSizeTests.cs New opt-in integration test that runs stdio discovery/learn flows and writes structured measurement artifacts.
eng/scripts/Summarize-McpOutputSizes.ps1 Summarizes measurement report and extracts per-tool learn text and inner-command artifacts.
eng/scripts/Measure-McpOutputSizes.ps1 Orchestrates build → measurement test run → summarization into a single workflow.
Suppressed comments (3)

servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/McpOutputSizeTests.cs:191

  • JsonDocument should be disposed (it uses pooled buffers). This loop can run for hundreds of tools, so leaving documents undisposed can significantly increase transient memory usage.
                });
                var response = await SendRequestAsync(process, request);
                var document = JsonDocument.Parse(response);
                Assert.True(
                    document.RootElement.TryGetProperty("result", out _),

servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/McpOutputSizeTests.cs:246

  • JsonDocument should be disposed here as well (pooled buffers). This inner loop can run many times (tools × commands) so it’s worth keeping allocations bounded.
                    });
                    var response = await SendRequestAsync(process, request);
                    var document = JsonDocument.Parse(response);
                    Assert.True(
                        document.RootElement.TryGetProperty("result", out var commandResult),
                        $"The learn response for '{tool}.{command}' did not contain a result.");

servers/Azure.Mcp.Server/tests/Azure.Mcp.Server.Tests/Infrastructure/McpOutputSizeTests.cs:75

  • ServerTestOptions is referenced here, but no such type exists in the repo, so the test project won’t compile. Use the same direct server-start argument pattern as other infrastructure tests.
        using var process = Process.Start(new ProcessStartInfo
        {
            FileName = executablePath,
            Arguments = ServerTestOptions.GetServerStartArguments($"server start --mode {mode}"),
            UseShellExecute = false,

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread eng/tools/McpOutputSizeMeasurer/src/McpOutputSizeMeasurer.cs Outdated
Comment thread eng/scripts/Summarize-McpOutputSizes.ps1 Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will review the CSharp portion after we determine if we want it as a test or a standalone application like many of our other outer loop tooling (like Vally)

Comment thread eng/scripts/Measure-McpOutputSizes.ps1 Outdated
Comment thread eng/scripts/Measure-McpOutputSizes.ps1 Outdated
Comment thread eng/scripts/Measure-McpOutputSizes.ps1
Comment thread eng/scripts/Measure-McpOutputSizes.ps1 Outdated
Comment thread eng/scripts/Summarize-McpOutputSizes.ps1 Outdated
@LarryOsterman

Copy link
Copy Markdown
Member Author

Alan Zimmer (@alzimmermsft) It's now a standalone tool, and a single script :).

@LarryOsterman

Copy link
Copy Markdown
Member Author

Ping :). I'd like to get this in if possible.

Comment thread eng/scripts/Measure-McpOutputSizes.ps1 Outdated
Comment thread eng/tools/McpOutputSizeMeasurer/src/McpOutputSizeMeasurer.cs Outdated
Comment thread eng/tools/McpOutputSizeMeasurer/build-info.json
Adds an opt-in stdio integration test (McpOutputSizeTests) that measures
the MCP server's initialize greeting, tools/list discovery response, and
per-tool learn-mode responses in both consolidated and namespace server
modes, including tool counts and inner-command schema verification.

Adds Summarize-McpOutputSizes.ps1 to produce console, JSON, and Markdown
summaries comparing the two modes, extract readable top learn-response
text, split inner commands into per-tool files, and report every learn
response over a configurable UTF-8 byte threshold (default 45000) in
addition to the top 10 largest.

Adds Measure-McpOutputSizes.ps1 to chain build, test, and summarize into
a single command, with comment-based help and CmdletBinding support on
both scripts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: LarryOsterman <8220172+LarryOsterman@users.noreply.github.com>
Co-authored-by: LarryOsterman <8220172+LarryOsterman@users.noreply.github.com>
Extract the raw JSON-RPC/stdio output-size measurement logic out of the
xunit test McpOutputSizeTests.cs into a new standalone console app,
eng/tools/McpOutputSizeMeasurer, following existing eng/tools/* conventions
(Exe project, AOT-compatible where possible, InternalsVisibleTo test
project, reuses McpToolEvaluator.Core.Utilities.FindRepoRoot).

- New eng/tools/McpOutputSizeMeasurer/src: ported MeasureAsync/MeasureModeAsync,
  raw stdio JSON-RPC handshake/discovery/learn measurement, with
  Assert-based validation replaced by thrown exceptions since it's no
  longer test code. Disabled AOT-compat (anonymous-type JSON serialization
  is incompatible with trimming analysis for this dev/CI-only tool).
- New Program.cs CLI: --executable/--report/--mode/--verbose/--help,
  defaulting to the built azmcp binary and TestResults/mcp-output-size.json.
- New McpOutputSizeMeasurer.Tests: 3 unit tests for GetInnerCommandNames.
- Registered both projects in Microsoft.Mcp.slnx and eng/tools/Tools.sln.
- Updated Measure-McpOutputSizes.ps1 to build/run the new standalone tool
  directly instead of the (now removed) xunit test via env vars.
- Removed servers/Azure.Mcp.Server/tests/.../Infrastructure/McpOutputSizeTests.cs
  entirely; its functionality is fully absorbed by the new tool.
- Minor doc comment updates in Summarize-McpOutputSizes.ps1 / the new tool
  referencing the old test name.

Validated: dotnet build for the new src/tests projects succeeds; the 3 new
unit tests pass; Azure.Mcp.Server.Tests still builds after the file removal;
ran the new McpOutputSizeMeasurer.exe end-to-end against the built azmcp.exe
and fed the report into Summarize-McpOutputSizes.ps1, confirming console/JSON
output (including the >45000-byte threshold list) is produced correctly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Allows measuring a pre-built or published azmcp binary (e.g. extracted
from a GitHub release) instead of always building the local
servers/Azure.Mcp.Server/src project. When -ServerExecutable is supplied,
the local server build step is skipped (the measurer tool is still built
unless -SkipBuild is also passed), enabling side-by-side comparisons of
current-source vs. a previously released server by running the script
twice with different -OutputDirectory values.

Validated by running the script against the locally built azmcp.exe as a
stand-in released binary, both with and without -SkipBuild, confirming the
measurement/summarize pipeline completes and produces correct output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Measure-McpOutputSizes.ps1 changes:
- Default -OutputDirectory moved from <repo-root>/TestResults to the
  repo-standard <repo-root>/.work/mcp-output-size (already gitignored via
  .work/, consistent with Pack-Zip.ps1/VallyEvaluator/ToolMetadataExporter
  conventions).
- New -ReleaseTag parameter: given a microsoft/mcp GitHub release tag (e.g.
  Azure.Mcp.Server-3.0.0-beta.36), downloads the matching platform asset
  (Azure.Mcp.Server-<os>-<arch>.zip, matching Pack-Zip.ps1's naming),
  extracts it under <OutputDirectory>/release-download/<tag>, and measures
  the extracted azmcp binary instead of building the local source tree.
  Mutually exclusive with -ServerExecutable.
- New -GitHubRepository parameter (defaults to microsoft/mcp) to resolve
  the release download URL, for forks/mirrors.

This lets a previously released server version be measured without it
being present locally, so its output sizes can be diffed against the
current source tree by running the script twice with different
-OutputDirectory values.

Validated end-to-end: downloaded and measured the win-arm64 asset for
Azure.Mcp.Server-3.0.0-beta.36, confirmed the report and console/JSON/
Markdown summaries were produced correctly under the new default
.work/mcp-output-size location.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@LarryOsterman
Larry Osterman (LarryOsterman) force-pushed the larryosterman-mcp-output-size-measurement branch from 8bdfbf2 to 40c11a0 Compare August 25, 2026 22:20
@LarryOsterman
Larry Osterman (LarryOsterman) merged commit 8ab9c1e into main Aug 25, 2026
17 checks passed
@LarryOsterman
Larry Osterman (LarryOsterman) deleted the larryosterman-mcp-output-size-measurement branch August 25, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

server-Azure.Mcp Azure.Mcp.Server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants