dotnet-assembly-cli 0.22.1

dotnet tool install --global dotnet-assembly-cli --version 0.22.1
                    
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 dotnet-assembly-cli --version 0.22.1
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=dotnet-assembly-cli&version=0.22.1
                    
nuke :add-package dotnet-assembly-cli --version 0.22.1
                    

dotnet-assembly-mcp

Status: 22 tools shipped, dual transport (stdio + HTTP), packaged as dotnet tool, Docker image, and self-contained single-file binaries. Latest release: v0.14.0 — collapsed find_member_references (field/property/event in one tool) and get_method_il(format=raw|text|scan) (issue #83, breaking).

An MCP server for static navigation of compiled .NET assemblies — types, methods, attributes, signatures, IL, cross-references, and on-demand decompilation — designed as a token-efficient alternative to feeding source code into an LLM context.

Why

When an AI agent needs to understand what a method does, the default today is to read the source file. For a 1,000-LOC class that's ~4–8k tokens, and most of it is irrelevant.

This server lets the agent drill down:

load_assembly(path)                  →  moduleVersionId + method count   (~30 tokens)
get_method(mvid, token)              →  signature, attributes, IL size   (~30 tokens)
get_method_il(mvid, token, format='raw')   →  raw IL hex, instruction count    (~80 tokens)
get_method_il(mvid, token, format='scan')  →  outbound calls / fields / types  (~150 tokens)
decompile_method(mvid, token)        →  C# body, hard-capped             (~200–500 tokens)
find_callers(mvid, token)            →  reverse call graph (intra+cross) (~100 tokens)
get_method_source(mvid, token)       →  PDB file/lines + SourceLink URL  (~40 tokens)

Closed generic instantiations are first-class: get_method / find_callers accept genericTypeArguments so the agent gets int Echo(int) instead of T Echo(T) and find_callers narrows to callers whose MethodSpec matches the requested instantiation. Producers that already have a MethodSpec row in the caller's module can skip the string-rendering step and supply methodSpecModuleVersionId + methodSpecMetadataToken as a fast-path; when both forms are present they are cross-checked and a mismatch yields generic_instantiation_mismatch. See docs/handoff-contract.md §3.5.

The agent pays only for what it actually needs to see.

Install

For the full guide (single-file binaries, systemd / launchd / Scheduled Task supervisors, Kubernetes manifest), see docs/consumer-install.md.

As a global dotnet tool (stdio — local MCP clients)

dotnet tool install -g dotnet-assembly-mcp
dotnet-assembly-mcp --stdio    # speak MCP over STDIN/STDOUT

Requires the .NET 10 runtime. Logs go to STDERR so STDOUT stays a clean JSON-RPC channel.

As a Docker image (HTTP — sidecar / multi-client)

docker run --rm -p 8788:8080 \
  -v /path/to/assemblies:/assemblies:ro \
  ghcr.io/pedrosakuma/dotnet-assembly-mcp:latest
# MCP endpoint: http://localhost:8788/mcp
# Health:       http://localhost:8788/health

Or build locally: docker build -t dotnet-assembly-mcp:dev -f deploy/Dockerfile ..

The diagnostics server emits MethodIdentity / TypeIdentity handles. As of dotnet-diagnostics-mcp #28, the diagnostics server already resolves PDBs locally and stamps SourceLocation directly onto every CPU-sample hotspot identity — so for dev workflows where the source tree is open in your editor, the diagnostics server is sufficient on its own.

Pairing this server with diagnostics is recommended when you also want:

  • Stripped binaries / NativeAOT (no PDB, no inline source).
  • Third-party assemblies you don't have source for.
  • Decompilation (decompile_method), reverse cross-reference (find_callers, find_type_references, …).

Run both together:

export ASSEMBLIES_DIR=/abs/path/to/your/published/binaries
docker compose -f deploy/docker-compose.yml up -d
# diagnostics: http://localhost:8787/mcp
# assembly:    http://localhost:8788/mcp

The same docker-compose.yml ships in pedrosakuma/dotnet-diagnostics-mcp:deploy/docker-compose.yml — bring it up from either checkout. Set MCP_BEARER_TOKEN on the host to gate both servers with one shared token.

Verifying releases

Every release artifact (NuGet package, self-contained binary archive, GHCR container image) is published with a SLSA build provenance attestation generated by actions/attest-build-provenance and signed by Sigstore via GitHub's OIDC issuer. The attestation proves the artifact was built by this repository on a specific commit by GitHub-hosted runners — no separate cert to install, no key to rotate.

Verify with the GitHub CLI:

# NuGet package
gh attestation verify dotnet-assembly-mcp.0.18.0.nupkg \
  --repo pedrosakuma/dotnet-assembly-mcp

# Self-contained binary tarball / zip
gh attestation verify dotnet-assembly-mcp-0.18.0-linux-x64.tar.gz \
  --repo pedrosakuma/dotnet-assembly-mcp

# Container image (attestation is published to the registry alongside the image)
gh attestation verify oci://ghcr.io/pedrosakuma/dotnet-assembly-mcp:0.18.0 \
  --repo pedrosakuma/dotnet-assembly-mcp

A passing verification confirms the build came from pedrosakuma/dotnet-assembly-mcp on the expected commit and tag.

Client configuration

Claude Desktop / Cursor / VS Code / Copilot CLI (stdio)

mcp.json (Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "dotnet-assembly-mcp": {
      "command": "dotnet-assembly-mcp",
      "args": ["--stdio"]
    }
  }
}

If the tool isn't on PATH, point command at the absolute path (e.g. ~/.dotnet/tools/dotnet-assembly-mcp).

Streamable HTTP

{
  "mcpServers": {
    "dotnet-assembly-mcp": {
      "url": "http://localhost:8788/mcp"
    }
  }
}

Tools

All tools share the same response envelope (summary, data, hints, error); hints advertise the suggested next tool so an agent can chain without rediscovering the API. Cross-module xref tools (find_callers, find_type_references, find_member_references, find_string_references, find_attribute_targets, list_derived_types) all use the same matching convention: same-module hits by metadata token, cross-module hits by (assembly simple name, type full name, member signature) against the child module's TypeRef / MemberRef rows.

Discovery & loading

Tool Purpose
load_assembly Load a .dll/.exe from disk (idempotent by MVID)
list_assemblies List currently loaded modules
list_assembly_references Outbound AssemblyRef rows for one module
list_resources ManifestResource rows (embedded resources) for one module
import_assembly_manifest Bulk-register a list of paths under configured roots

Type & method enumeration (Tier-1)

Tool Purpose
list_types Paginated TypeDef listing, filterable by namespace / name / kind
get_type Resolve (mvid, token) to a type summary (base type, interfaces, kind)
list_derived_types Walk subclasses and interface implementers across every loaded module (directOnly / transitive)
list_members Enumerate fields / properties / events of a type
list_methods Paginated MethodDef listing, filterable by declaring type
find_method Module-wide MethodDef search by regex on name / signature
list_attributes Custom attributes on a module / type / method / parameter / field / property / event

Single-method resolution (Tier-2 / Tier-3)

Tool Purpose
get_method Resolve (mvid, token) to a method summary; accepts genericTypeArguments / genericMethodArguments for a closed signature view
get_method_il IL reader for a method, dispatched by format: raw (hex IL bytes + max-stack + counts), text (ildasm-style textual dump, capped + LRU-cached), scan (structured outbound references — calls, fields, types, strings)
decompile_method C# body via ICSharpCode.Decompiler (hard-capped, LRU-cached)
decompile_type C# decompilation of a whole TypeDef — members in declaration order (hard-capped, LRU-cached)
get_method_source PDB-resolved file/lines plus SourceLink URL (embedded PDB or sibling .pdb)

Reverse cross-reference (Tier-4)

Tool Purpose
find_callers Every method whose IL calls a given method; narrows by instantiation when genericMethodArguments is supplied
find_type_references Every site referencing a TypeDef (field/parameter/return/local types + newobj / castclass / isinst / box / ldtoken / generic args)
find_member_references Inbound xref for a field, property, or event — dispatched by handle prefix (f: / p: / e:); accessor narrows property to getter/setter and event to add/remove/raise
find_string_references Every method whose IL emits ldstr for a given literal (exact / contains / regex)
find_attribute_targets Reverse custom-attribute index: every assembly/type/method/parameter/field/property/event bearing a given attribute

CLI (human-driven front-end)

The same engine ships as a standalone terminal tool, dotnet-assembly-cli, for when you (not an agent) want to navigate an assembly — every MCP tool has a matching subcommand, rendered as human-readable text by default (or --json for the full MCP envelope).

dotnet tool install -g dotnet-assembly-cli
dotnet-assembly-cli --help        # list every subcommand

Full walkthrough, subcommand table, composed commands (explain-type, explain-method, callgraph, diff-assemblies), global options, and exit codes: docs/cli-usage.md.

Companion project

Scope-disjoint from pedrosakuma/dotnet-diagnostics-mcp, which performs dynamic diagnostics (attach, EventPipe sampling, GC, exceptions) on a running .NET process. Together they form a closed loop:

[dotnet-diagnostics-mcp]                    [dotnet-assembly-mcp]
   ──────────────────────                     ──────────────────────
   inspect_process(view="list")                load_assembly
   collect_sample(kind="cpu")          ──┐  ┌─→ get_method
   collect_events(kind="exceptions")      │  │   get_method_il (format='scan')
                                          │  │   decompile_method
                                          ▼  │   find_callers
                                   (MethodIdentity)

The handoff contract — MethodIdentity = (moduleVersionId, metadataToken) plus optional genericTypeArguments (§3.5) — lives in docs/handoff-contract.md and is also served at assembly://contract/method-identity as an MCP resource.

MCP resources

In addition to the tool surface, the server publishes a small set of read-only resources that MCP clients can subscribe to or fetch directly. None of them require a tool call:

URI Content
assembly://contract/method-identity Full text of docs/handoff-contract.md — the producer/consumer wire contract for MethodIdentity.
assembly://manifest/loaded JSON array of every currently-loaded module (mvid, path, methodCount). Mirrors list_assemblies without consuming a tool slot.
assembly://manifest/loaded/{mvid} JSON object for one module by MVID. Returns 404-style empty body when the MVID isn't loaded.

Clients that support resource subscriptions get a notification whenever the loaded-module set changes (e.g. after load_assembly or a file-watcher reload).

This server does not replace SourceLink / TraceLog source resolution. It is what the agent reaches for when:

  • the deployed binary has no PDB or no SourceLink,
  • the target is a third-party NuGet dependency,
  • the runtime is NativeAOT-trimmed and metadata at runtime is sparse,
  • or the agent just wants a structural overview without pulling 8 KB of source.

get_method_source is the second-chance source resolver: it reads the on-disk PDB (embedded portable PDB first, then sibling .pdb) so the agent doesn't need a separate SourceLink fetch when one is available locally.

Building blocks

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET 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
0.22.1 34 8/29/2026
0.22.0 348 6/4/2026
0.21.0 116 6/3/2026
0.20.1 116 6/3/2026
0.20.0 119 6/3/2026