Skip to main content
Glama
Kommisaar

dotnet-decompiler-mcp

by Kommisaar

dotnet-decompiler-mcp

An MCP server that decompiles and inspects .NET assemblies to C# source, wrapping the ICSharpCode.Decompiler engine (ILSpy, v9.0.0.7889) behind a set of callable tools.

Point an MCP client at any .NET DLL and ask an LLM to "decompile Foo.Bar, then list its public methods" — it returns structured results (C# source, type summaries, symbol matches) the model can reason over.

What it does

  • Decompile a whole type or a single member to readable C# source (with comments — the ILSpy "gold standard" output).

  • Inspect an assembly: list types, list namespaces with counts, get a detailed member summary of one type (methods, fields, properties, events, attributes, base type).

  • Search for symbols by name across one or more assemblies (case-insensitive substring, filterable by kind).

  • A check_env diagnostic tool reports the active Python, .NET runtime, and engine version.

All .NET access is via reflection through pythonnet on CoreCLR; no .NET SDK install is required on the host beyond the runtime.

Related MCP server: dotnet-sherlock-mcp

Requirements

  • Python ≥ 3.14

  • .NET 8 runtime on the host (the decompiler targets net8.0; the bundled CoreCLR runtime pack is 8.0.6, the minimum host runtime is 8.0.17).

  • uv to run the project.

Install

git clone <repo-url> dotnet-decompiler-mcp
cd dotnet-decompiler-mcp
uv sync

The ILSpy engine DLL ships in lib/ICSharpCode.Decompiler.dll — nothing else to download.

Environment variables

These are set automatically at runtime by the bootstrap (runtime/clr.py); you normally do not need to configure them. They are listed for completeness / troubleshooting.

Variable

Value

Purpose

PYTHONNET_RUNTIME

coreclr

Selects CoreCLR over Mono.

PYTHONNET_CORECLR_RUNTIME_CONFIG

path to a temp *.runtimeconfig.json

Tells CoreCLR which framework (Microsoft.NETCore.App 8.0.6) to load. The file is generated into the system temp dir on first boot.

If the runtime fails to start, run check_env (below) — it reports the resolved versions.

MCP client registration

The server speaks MCP over stdio. Register it with any MCP client.

ZCode / OpenCode (.zcode/config.json)

{
  "mcp": {
    "servers": {
      "dotnet-decompiler": {
        "type": "stdio",
        "command": "uv",
        "args": [
          "run",
          "--project",
          "/absolute/path/to/dotnet-decompiler-mcp",
          "python",
          "-m",
          "dotnet_decompiler_mcp"
        ],
        "env": {}
      }
    }
  }
}

Write this to the workspace .zcode/config.json or the user-level ~/.zcode/v2/config.json, then restart the client.

Generic mcpServers (Claude Desktop and others)

{
  "mcpServers": {
    "dotnet-decompiler": {
      "command": "uv",
      "args": [
        "run",
        "--project",
        "/absolute/path/to/dotnet-decompiler-mcp",
        "python",
        "-m",
        "dotnet_decompiler_mcp"
      ]
    }
  }
}

You can also run it directly to smoke-test the stdio server:

uv run python -m dotnet_decompiler_mcp

It should start without errors and wait on stdin. Ctrl+C to exit.

Tools

Seven tools are registered. asm_paths (where present) is an optional list of extra assembly search directories used to resolve cross-DLL references; pass it when the target assembly depends on types in other DLLs.

Tool

Arguments

Returns

Purpose

check_env

(none)

EnvInfo

Startup diagnostics: Python, .NET runtime, engine version, lib dir.

decompile_type

dll, type_name, asm_paths?

DecompileResult

Decompile a whole type to C# source.

decompile_member

dll, type_name, member_name, asm_paths?

MemberDecompileResult

Decompile a single method/field/property/event.

list_types

dll, namespace?, asm_paths?

TypeListResult

List types, optionally filtered by namespace prefix.

list_namespaces

dll, asm_paths?

NamespaceListResult

Distinct namespaces with type counts.

get_type_summary

dll, type_name, asm_paths?

TypeSummary

Detailed public-member breakdown of one type.

search_symbol

dlls, query, kind?, asm_paths?

SearchResult

Case-insensitive symbol search across one or more DLLs.

Notes:

  • type_name is a fully-qualified, case-sensitive name (e.g. ICSharpCode.Decompiler.DecompilerSettings).

  • namespace is a prefix filter — ICSharpCode matches ICSharpCode.Decompiler but not ICSharpCodeX; empty string = all types.

  • search_symbol kind is one of type / method / field / property / event / any (default any).

Usage examples

These target the engine DLL bundled in lib/ — the same cases the test suite pins, so they are known to work. Replace the path with any .NET assembly you want to explore.

check_env
  → EnvInfo(decompiler_version="9.0.0.7889", net_tfm_target="net8.0", ...)

decompile_type("lib/ICSharpCode.Decompiler.dll",
               "ICSharpCode.Decompiler.DecompilerSettings")
  → DecompileResult(source="public class DecompilerSettings : ...", ...)

decompile_member("lib/ICSharpCode.Decompiler.dll",
                 "ICSharpCode.Decompiler.DecompilerSettings",
                 "GetMinimumRequiredVersion")
  → MemberDecompileResult(source="public static Version ...", ...)

get_type_summary("lib/ICSharpCode.Decompiler.dll",
                 "ICSharpCode.Decompiler.DecompilerSettings")
  → TypeSummary(base_type="System.Object",
                events=[EventInfo(name="PropertyChanged", ...)], ...)

search_symbol(["lib/ICSharpCode.Decompiler.dll"], "GetMinimum", kind="method")
  → SearchResult(matches=[SymbolMatch(kind="method",
          name="GetMinimumRequiredVersion", type="...DecompilerSettings")])

Errors

The engine raises typed exceptions; the tool layer does not catch them, so they surface to the MCP client as is_error responses with the exception message. All engine errors inherit from DecompilerError.

Error

Meaning

DllNotFoundError

The dll path does not exist or is not readable.

TypeNotFoundError

type_name was not found in the assembly.

MemberNotFoundError

member_name was not found in the type.

DecompilationFailedError

A reflected .NET call raised; the original exception text is appended as (inner: ...).

InvalidArgumentError

An argument was rejected (e.g. an unknown kind).

Development

uv run pytest          # 65 tests (incl. real-.NET integration tests)
uv run ruff check      # lint (D/E/F/W, Google docstring convention)

Architecture

Four one-way layers, no cycles:

config.py     constants (single source of truth)
runtime/      CoreCLR bootstrap via pythonnet (init_runtime, ensure_initialised)
engine/       CSharpDecompiler reflection wrappers (cache, decompile, metadata, version, errors)
tools/        thin async wrappers (list[str]|None -> tuple|None), errors bubble up
server.py     FastMCP assembly + tool registration
models/       Pydantic response DTOs (anemic, serialization only)

Dependency direction: server → tools → engine → runtime/models/config.

Status

Milestones M0–M4 complete: runtime bootstrap, decompile (type/member), inspect (list/summary) + search, error handling, and documentation.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Kommisaar/dotnet-decompiler-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server