Microsoft.AITools.BinlogMcp 1.0.0

Prefix Reserved
dotnet tool install --global Microsoft.AITools.BinlogMcp --version 1.0.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Microsoft.AITools.BinlogMcp --version 1.0.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Microsoft.AITools.BinlogMcp&version=1.0.0
                    
nuke :add-package Microsoft.AITools.BinlogMcp --version 1.0.0
                    

MSBuild Binlog MCP Server

An MCP (Model Context Protocol) server for MSBuild binary log (.binlog) analysis, providing 31 tools for AI-assisted build investigation, performance analysis, and comparison.

Bug reports

For bug reports and support please use the https://github.com/dotnet/skills repository

Notice

The tool is meant to be used solely by the plugins distributed via https://github.com/dotnet/skills, Microsoft does not guarantees and compatibility nor support for direct usages. The MCP and its implementation are considered internal technical details of the msbuild skills.

Overview

This tool parses MSBuild binary logs using the StructuredLogger library and exposes them through the MCP protocol. It enables AI assistants to investigate build failures, trace property origins, analyze performance bottlenecks, and compare builds — all through structured tool calls.

Key capabilities:

  • StructuredLog Viewer search DSL with tree-format output and stable node [id]s
  • Property origin tracing — find which file/target/task set a property
  • Performance analysis — expensive projects, targets, and tasks
  • Embedded file inspection — read and search .csproj/.props/.targets files captured during build
  • Query result caching for repeated tool calls
  • LRU memory management for multiple loaded binlogs

Tools (33)

Investigation (10)

Tool Description
binlog_overview Build status, duration, project count, error/warning counts. Start here.
binlog_errors Build errors with project, target, task, file, and line context
binlog_warnings Build warnings, filterable by warning code
binlog_search Search using StructuredLog Viewer DSL — returns hierarchical tree with node [id]s
binlog_projects List all projects with status and duration
binlog_properties MSBuild property values (curated defaults or filtered)
binlog_compare_property Compare a property's value across all projects in one call (e.g. find which projects lack Configuration as a global property)
binlog_items MSBuild items (PackageReference, Compile, etc.)
binlog_imports Full import chain (.props/.targets files)
binlog_explain_property Traces where a property gets its value (file/target/task that set it)

Specialized diagnostics (5)

Tool Description
binlog_assembly_conflicts MSB3277 / RAR analysis — extracts assembly version conflicts plus the RAR task parameters (AppConfigFile, Assemblies) per target framework
binlog_diagnose Automated build diagnosis: failed targets, missing references, double writes, slow analyzers
binlog_double_writes Detect files written by multiple tasks/targets (build correctness issue)
binlog_compiler Extract compiler (Csc/Vbc/Fsc) command-line invocations, response files, and key switches
binlog_nuget NuGet package restore information: resolved packages, versions, sources, duration

Files (3)

Tool Description
binlog_files List or retrieve source files embedded in the binlog (App.config, .csproj, .props, .targets) with paginated line-range reads
binlog_search_files Search text or regex across all embedded source files with configurable context lines
binlog_preprocess Preprocessed view of a project file with its full import chain (equivalent to msbuild /pp)

Tree navigation (1)

Tool Description
binlog_explore_node Navigate the build log tree by node ID — shows ancestor chain, node details, and children at configurable depth. Use with IDs from binlog_search to freely walk the tree.

Targets & tasks (5)

Tool Description
binlog_project_targets List targets executed in a specific project with timing and skip status
binlog_search_targets Search for targets by name across all projects
binlog_target_reasons Why a target ran or was skipped (inputs/outputs, dependency chain)
binlog_tasks_in_target List all tasks within a specific target of a project
binlog_task_details Full input parameters and output messages of a specific task execution (essential for RAR / Exec / Copy investigation)

Evaluations (3)

Tool Description
binlog_evaluations List project evaluations (project + TFM combinations) with their IDs
binlog_evaluation_properties All evaluated properties for a specific project+TFM
binlog_evaluation_global_properties Global properties (Configuration, Platform, TargetFramework) per evaluation — essential for diagnosing configuration mismatches

Performance (5)

Tool Description
binlog_expensive_projects Slowest projects by exclusive duration
binlog_expensive_targets Slowest targets across the build
binlog_expensive_tasks Slowest tasks across the build
binlog_expensive_analyzers Slowest Roslyn analyzers and source generators
binlog_project_target_times Target-level timing breakdown for a specific project

Comparison (1)

Tool Description
binlog_compare Diff two binlogs (properties, packages)

Prompts (2)

Prompt Description
analyze_errors Step-by-step error investigation workflow
analyze_performance Step-by-step performance investigation workflow

Setup

VS Code

Add to your .vscode/mcp.json:

{
  "servers": {
    "binlog-mcp": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["run", "--project", "<path-to>/src/Microsoft.AITools.BinlogMcp/Microsoft.AITools.BinlogMcp.csproj"]
    }
  }
}

Or if installed as a global tool:

{
  "servers": {
    "binlog-mcp": {
      "type": "stdio",
      "command": "binlog-mcp"
    }
  }
}

Pre-loading binlogs

Pass --binlog <path> to pre-load a binlog at startup:

{
  "servers": {
    "binlog-mcp": {
      "type": "stdio",
      "command": "binlog-mcp",
      "args": ["--binlog", "msbuild.binlog"]
    }
  }
}

Search DSL Reference

The binlog_search tool uses the native StructuredLog Viewer search syntax and returns results as a hierarchical tree with stable [id] references:

200 result(s) (matched=200)
Project MyApp.csproj → Build [123]
  Target CoreCompile [124]
    Task Csc [125]
      Error CS0246: The type 'Foo' could not be found [126]
Token Example Meaning
plain text error Case-insensitive substring match
"quoted" "error CS0246" Exact phrase match
$error $error All error nodes
$warning $warning All warning nodes
$task $task Csc Tasks (optionally named)
$target $target CoreCompile Targets (optionally named)
$project $project MyApp Project nodes
$property $property name=Config Properties with field match
$item $item PackageReference Items by type
$time $task $time Include timing info, sorted slowest first
under(query) under($project MyApp) $error Scope to under a parent
not(query) not($warning) Exclude nodes
name=value name=Configuration value=Debug Field match

Architecture

Microsoft.AITools.BinlogMcp.Core/   Query engine (no MCP dependency)
├── BinlogAnalyzer.cs           Binlog loading via StructuredLogger
├── TreeHelpers.cs              Ancestor traversal utilities
├── Models/Models.cs            Shared result types
└── Queries/                    One query class per tool category
    ├── BuildOverviewQuery.cs
    ├── DiagnosticsQuery.cs
    ├── PropertiesQuery.cs
    ├── PerformanceQueries.cs
    └── ...

Microsoft.AITools.BinlogMcp/        MCP server (stdio transport)
├── Program.cs                  Host setup, tool registration
├── BinlogCache.cs              LRU cache with file-change detection
├── Tools/                      One tool class per MCP tool
│   ├── OverviewTool.cs
│   ├── SearchTool.cs
│   └── ...
├── Prompts/                    MCP prompt templates
│   └── BinlogPrompts.cs
└── instructions/               LLM guidance
    └── server-instructions.md

The Core library has no MCP dependency and can be reused independently. The MCP layer is a thin wrapper that registers tools, manages caching, and handles the stdio transport.

Data Collection

The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described below. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.

Telemetry configuration

Telemetry collection is on by default to help improve the product. It can be disabled at any time.

Disabling telemetry

Set the standard .NET CLI opt-out environment variable to 1 or true (case-insensitive) before starting the MCP server:

export DOTNET_CLI_TELEMETRY_OPTOUT=true

Windows PowerShell:

$env:DOTNET_CLI_TELEMETRY_OPTOUT = "true"

When opted out the server starts no telemetry spans, records no metric values, and performs no hashing — nothing is emitted from BinlogTelemetry at all.

What is collected

Telemetry is emitted via .NET System.Diagnostics.ActivitySource, System.Diagnostics.Metrics.Meter, and Microsoft.Extensions.Logging.ILogger, with the in-process OpenTelemetry SDK wired up at startup. By default the SDK subscribes to the binlog-mcp source, runs the BinlogTelemetryEnricher (which stamps the correlation tags described below), writes one JSON file per activity to a local folder, and ships a structured log record per emit point to Microsoft via Azure Application Insights using the Azure Monitor direct log exporter (no local collector required). Activity spans themselves are not exported to Application Insights — the log record carries the same payload and inherits the span's trace context for correlation. Set DOTNET_CLI_TELEMETRY_OPTOUT=1 to disable all destinations.

Where the data goes

The pipeline has three destinations:

Destination Default How to opt out
Azure Application Insights (Microsoft-owned resource, ingested over HTTPS via the Azure Monitor OpenTelemetry direct log exporter; one log record per emit point) On DOTNET_CLI_TELEMETRY_OPTOUT=1
Local JSON dump%LOCALAPPDATA%/Microsoft/BinlogMcp/telemetry/<run-guid>/N-tool_binlog_<name>.json (one file per activity span, never leaves the box) On DOTNET_CLI_TELEMETRY_OPTOUT=1 or BINLOG_MCP_TELEMETRY_NO_LOCAL_LOG=1
External OTLP collector (copilot-watson, Aspire Dashboard, Jaeger, ...) — receives activity spans Off Set OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 (and optionally OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf) to enable

This matches the NuGet MCP server's posture: on by default, single canonical opt-out via DOTNET_CLI_TELEMETRY_OPTOUT, with finer-grained per-destination toggles available for advanced users.

On first run the server prints a one-line notice to stderr (never stdout — stdout is the MCP JSON-RPC transport) pointing here. A sentinel file at %LOCALAPPDATA%\Microsoft\BinlogMcp\.first-run-notice-<version> keeps subsequent runs silent.

Correlation tags (stamped on every span)

BinlogTelemetryEnricher automatically attaches these tags to every activity emitted by the server so a downstream collector can group them into one logical run:

Tag Source Purpose
binlog.run_guid Guid.NewGuid() at process startup Group all spans from a single MCP stdio session, even tool calls that aren't parented to each other. Also used as the folder name under LOCALAPPDATA for the JSON dump.
binlog.custom_marker BINLOG_MCP_TELEMETRY_MARKER env var (truncated to 128 chars) Tag benchmark / eval runs so they can be filtered or grouped downstream
binlog.build_version Assembly version Distinguish runs by tool version
binlog.is_development Only when DOTNET_ENVIRONMENT=Development Filter out local dev traffic

binlog.run_guid is a process-scoped random GUID, not a stable user id. binlog.custom_marker is whatever the operator chooses to put in the env var — keep PII out of it.

Trace span tags (per tool call)

All custom properties carry the unique binlog. prefix so that telemetry-backend property classifications never collide with properties emitted by other products to the same table. Spans are named tool_binlog/<tool> so the root segment uniquely identifies this product for ownership inference.

Tag Example Customer-influenced Notes
binlog.mcp.tool.name binlog_overview No Fixed tool name from the server registration
binlog.mcp.server.name binlog-mcp No Constant
binlog.file.hash a3f1c8e9d2b46758 Yes — hashed HMAC-SHA256 of the binlog filename (path stripped) truncated to 16 hex chars
binlog.result.chars 1234 No Size of response in characters
binlog.result.error false No Whether the call failed
binlog.error.message.hash b71e2f4a90c83d65 Yes — hashed HMAC-SHA256 of Exception.Message (only on error). Raw text never leaves the process.
binlog.exception.type System.IO.FileNotFoundException No Exception type name (only on error)
binlog.exception.stack.hash c92d4f1a8b03e756 Yes — hashed HMAC-SHA256 of the stack trace (only on error). Raw text never leaves the process.
Metrics
Metric Type Tags Description
binlog.tool.call.count Counter binlog.tool (fixed) Total tool calls
binlog.tool.error.count Counter binlog.tool (fixed) Failed tool calls
binlog.tool.call.duration Histogram (ms) binlog.tool (fixed) Tool call latency
binlog.tool.result.size Histogram (chars) binlog.tool (fixed) Response sizes
binlog.load.count Counter Binlog file loads
binlog.load.duration Histogram (ms) binlog.file.hash (hashed) Binlog load time
binlog.cache.hit.count Counter binlog.cache.type (build / query, fixed) Cache hits

Privacy

  • No binlog content (properties, items, build output, source files) is ever read by the telemetry layer.
  • No file paths — only the filename component is considered, and it is hashed before being attached to any span or metric.
  • No raw error messagesException.Message is hashed before being attached.
  • Hashing uses HMAC-SHA256 with a fixed per-tool key, so identical filenames within a session produce the same hash (enabling correlation) but the original value cannot be recovered.
  • All data stays local to whichever OTLP listener (if any) you have configured.

Using with Aspire Dashboard

docker run --rm -p 18888:18888 -p 4318:18889 mcr.microsoft.com/dotnet/aspire-dashboard
# Open http://localhost:18888 to see traces
# Set OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.0.0 922 6/16/2026