RePythonNET-MCP

RePythonNET-MCP

Enables static analysis and patching of .NET binaries through decompilation, IL analysis, renaming, and IL patching over the Model Context Protocol.

Category
Visit Server

README

RePythonNET-MCP

An MCP (Model Context Protocol) server for static analysis and patching of .NET binaries.

Uses dnlib for IL parsing and editing, and the ILSpy/dnSpy decompiler engine for C# source reconstruction. Exposes 38 tools over a standard MCP interface, making it easy to integrate with any MCP-compatible LLM agent.

Designed to run as a standalone Docker container, and also ships with integration files for SARA — an internal automated malware reverse engineering system developed at Sekoia.io.


Features

  • Decompile any .NET class or method to readable C#
  • Enumerate types, methods, fields, imports, resources, entry point
  • Analyse IL opcodes, call graphs, callers, string literals
  • Detect P/Invoke declarations, reflection usage, large byte arrays
  • Rename obfuscated classes, methods, and fields (in-memory, non-destructive)
  • Patch IL instructions: replace strings, NOP out instructions, bypass checks, invert branches, patch static fields
  • Save the modified binary to disk
  • Upload binaries via HTTP, or load directly from a URL
  • Multi-session: analyse several binaries in parallel with separate analysis_id identifiers

Architecture

┌─────────────────────────────────┐
│  Any MCP client / LLM agent     │
│  (curl, Python, SARA, etc.)     │
└──────────────┬──────────────────┘
               │  JSON-RPC over HTTP
               ▼
┌─────────────────────────────────┐
│  pythonnet-mcp  (port 8001)     │
│                                 │
│  server.py                      │
│  ├── FastMCP (38 tools)         │
│  ├── POST /upload               │
│  └── GET  /download             │
│                                 │
│  Runtime: Python + Mono         │
│  .NET libs: dnlib, ILSpy/dnSpy  │
└─────────────────────────────────┘

The server is stateless across requests but holds in-memory sessions keyed by analysis_id. Each session stores the loaded dnlib module and a lazily-initialised ILSpy decompiler instance.


Quick Start

Docker (recommended)

# Create the required directories (first time only)
mkdir -p data/samples data/pythonnet_projects logs

# Build and run
docker compose -f docker-compose.yml up --build

# The server listens on http://localhost:8001

Direct (without Docker)

Prerequisites: Python 3.11+, mono-complete, and the .NET assemblies in dll/.

pip install -r requirements.txt

# Override default paths to avoid needing write access to /data/
export PYTHONNET_PROJECTS_DIR=./data/pythonnet_projects
export SAMPLES_DIR=./data/samples
mkdir -p data/pythonnet_projects data/samples

python server.py --host 0.0.0.0 --port 8001

CLI options:

Option Default Description
--host 0.0.0.0 Bind address
--port 8001 Bind port
--binary (none) Optional binary to pre-load at startup

Claude Desktop Configuration

The file scripts/wrapper.py is a wrapper to put on your host. Then configure Claude Desktop (claude_desktop_config.json) to execute this file.

{
  "mcpServers": {
    "pythonnet": {
      "command": "<path to python>",
      "args": [
        "<path to wrapper.py>"
      ]
    }
  },
}

Usage

Upload a binary

You first needs to upload the file using the /upload endpoint:

curl -F file=@malware.dll http://localhost:8001/upload
# {"path": "/data/pythonnet_projects/_uploads/malware.dll", "size_bytes": 45056}

You can then ask Claude Desktop to use this MCP service to load and analyze the binary. You can use pythonnet_list_uploaded_files to list already uploaded files.

Call an MCP tool (raw JSON-RPC)

curl -s -X POST http://localhost:8001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "pythonnet_load_binary",
      "arguments": {
        "binary_path": "/data/pythonnet_projects/_uploads/malware.dll",
        "analysis_id": "session1"
      }
    }
  }'

Session isolation: append ?session_id=<value> to the URL to keep sessions independent when running parallel analyses from multiple clients.

List available tools

curl -s -X POST http://localhost:8001/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Download a file

# Download a patched binary produced by pythonnet_save_binary
curl "http://localhost:8001/download?path=/data/pythonnet_projects/session1/malware_patched.dll" \
  -o malware_patched.dll

Downloads are restricted to files inside /data/pythonnet_projects/ and /data/samples/.


Tools Reference

All tool names are prefixed with pythonnet_. The analysis_id parameter defaults to "default" and identifies the session.

Loading

Tool Key Parameters Description
pythonnet_load_binary binary_path, analysis_id Load a .NET binary from disk. Copies it to a project directory before opening so the original is never modified.
pythonnet_load_from_url url, analysis_id Download a .NET binary from HTTP/HTTPS and load it.
pythonnet_unload_binary analysis_id Unload a binary and free its memory.
pythonnet_list_uploaded_files extension List binaries in the upload staging area and the samples directory.
pythonnet_list_active_sessions List all active and on-disk analysis sessions.

Enumeration

Tool Key Parameters Description
pythonnet_list_all_classes analysis_id, namespace_filter List all types defined in the binary.
pythonnet_list_all_methods analysis_id, class_filter List all methods that have a body.
pythonnet_list_all_methods_inside_class class_name, analysis_id List all methods (including abstract/interface) inside a specific class.

Decompilation

Tool Key Parameters Description
pythonnet_decompile_class class_name, analysis_id Decompile an entire class to C# source.
pythonnet_decompile_method class_name, method_name, analysis_id, method_index Decompile a single method. Use method_index to disambiguate overloads.
pythonnet_decompile_all_classes analysis_id Decompile every class in the binary at once.

Metadata

Tool Key Parameters Description
pythonnet_get_module_info analysis_id Assembly name, version, culture, runtime version, target framework.
pythonnet_get_entry_point analysis_id Managed entry point (Main or EntryPoint metadata).
pythonnet_get_imports analysis_id All external assemblies and types referenced by the binary.
pythonnet_get_fields class_name, analysis_id All fields of a class with their types and visibility.
pythonnet_get_custom_attributes class_name, analysis_id, method_name Custom attributes on a class or one of its methods.
pythonnet_get_resources analysis_id List all embedded resources.
pythonnet_extract_resource resource_name, analysis_id Extract a raw embedded resource to a file.

IL Analysis

Tool Key Parameters Description
pythonnet_get_opcodes class_name, method_name, analysis_id, method_index Dump the raw IL instruction listing of a method.
pythonnet_get_method_calls class_name, method_name, analysis_id, method_index List all outgoing call/callvirt instructions from a method.
pythonnet_get_callers class_name, method_name, analysis_id Find all methods that call a given method (reverse call graph).
pythonnet_get_call_graph class_name, method_name, analysis_id, max_depth BFS call graph from a root method (default max depth: 5, internal calls only).
pythonnet_find_dead_code analysis_id Find methods that are never called from within the binary.

String and Name Search

Tool Key Parameters Description
pythonnet_get_strings analysis_id, min_length List all unique ldstr string literals across all method bodies.
pythonnet_search_string search_string, analysis_id Find all methods that reference a given string literal.
pythonnet_search_method_by_name method_name, analysis_id Search for methods by partial name match across all classes.

Behavioral Indicators

Tool Key Parameters Description
pythonnet_find_pinvoke analysis_id, dll_filter List all P/Invoke (DllImport) declarations.
pythonnet_find_reflection_calls analysis_id Find all uses of System.Reflection (Assembly.Load, GetMethod, Invoke, etc.).
pythonnet_find_large_byte_arrays analysis_id, min_size Find methods that allocate large byte arrays (potential payload buffers; default min: 256 bytes).

Renaming (Deobfuscation)

Changes are in-memory only. Call pythonnet_save_binary to persist.

Tool Key Parameters Description
pythonnet_rename_class class_name, new_name, analysis_id, new_namespace Rename a class and optionally its namespace.
pythonnet_rename_method class_name, method_name, new_method_name, analysis_id, method_index Rename a method.
pythonnet_rename_field class_name, field_name, new_field_name, analysis_id Rename a field.

IL Patching

Changes are in-memory only. Call pythonnet_save_binary to persist.

Tool Key Parameters Description
pythonnet_patch_ldstr class_name, method_name, il_offset, new_string, analysis_id Replace the string operand of an ldstr instruction at a given IL offset.
pythonnet_nop_instructions class_name, method_name, il_offsets, analysis_id Replace one or more instructions with nop.
pythonnet_patch_return class_name, method_name, return_value, analysis_id Replace a method body with a minimal return (useful to bypass a check).
pythonnet_patch_branch class_name, method_name, il_offset, mode, analysis_id Flip (invert), force (always/never), or NOP a conditional branch.
pythonnet_set_field_constant class_name, field_name, new_value, analysis_id Patch the initialization value of a static field in .cctor.
pythonnet_save_binary analysis_id, output_path Write the modified module to disk.

Volumes and Paths

Path (in container) Purpose Notes
/data/samples/ Read-only input samples Mount your binary directory here
/data/pythonnet_projects/ Per-session working directories Created automatically; writable
/data/pythonnet_projects/_uploads/ HTTP upload staging area Used by the /upload endpoint

When running standalone, adjust the volume mounts in docker-compose.yml to your local directory layout.


Configuration

Environment Variable Default Description
WEB_SERVER_PORT 8001 Port the server binds to
PYTHONNET_PROJECTS_DIR /data/pythonnet_projects Working directory for analysis sessions (uploads, patched binaries, extracted resources)
SAMPLES_DIR /data/samples Read-only input directory scanned by pythonnet_list_uploaded_files

Dependencies

Python packages (see requirements.txt):

  • pythonnet ≥ 3.0 — Python/.NET CLR interop
  • fastmcp — MCP server framework
  • mcp ≥ 1.0 — MCP SDK
  • click, requests, aiofiles

System (installed in the Docker image): mono-complete

.NET assemblies (bundled in dll/):

Assembly License Source
dnlib.dll MIT 0xd4d/dnlib
ICSharpCode.Decompiler.dll MIT icsharpcode/ILSpy
ICSharpCode.NRefactory*.dll MIT ILSpy / NRefactory
dnSpy.Decompiler*.dll GPL-3.0 dnSpy/dnSpy
dnSpy.Contracts.Logic.dll GPL-3.0 dnSpy/dnSpy

License note: The dnSpy assemblies are GPL-3.0. If you distribute a modified version of this project that includes those files, the GPL-3.0 terms apply to the distribution. Using the service as-is (running the Docker container) is not affected.


SARA Integration

SARA is an internal automated malware reverse engineering system developed at Sekoia.io. It uses this service as its .NET analysis backend. Two additional files support that integration:

tools.py — MCP client

A lightweight HTTP client that runs inside the SARA process and proxies tool calls to this server. It:

  • Auto-detects whether it is running inside Docker (uses http://pythonnet-mcp:8001/mcp) or on the host (uses http://localhost:8001/mcp), and respects the PYTHONNET_MCP_URL environment variable.
  • Fetches tool definitions from the server at runtime (tools/list) with a 5-minute cache — the server is the single source of truth for schemas.
  • Normalises legacy relative paths (data/samples/file.dll/data/samples/file.dll) before forwarding requests.
  • Exposes PythonnetToolRegistry, the class that SARA's service registry instantiates per analysis run.
from services.pythonnet.tools import PythonnetToolRegistry

registry = PythonnetToolRegistry(session_id="sara-abc12")
result = registry.execute_tool("pythonnet_list_all_classes", {"analysis_id": "sara-abc12"})

policy.py — Tool usage policy

Controls tool call limits and deduplication inside SARA's LangGraph analysis loop. Not needed outside SARA.

Tool Limit
pythonnet_load_binary 1 per session
pythonnet_list_all_classes 3 + lock_clears
pythonnet_list_all_methods 3 + lock_clears
pythonnet_list_all_methods_inside_class 20 + (lock_clears × 5)
pythonnet_decompile_class 50 + (lock_clears × 10)
pythonnet_decompile_method unlimited
pythonnet_rename_class 20 + lock_clears
pythonnet_rename_method 50 + (lock_clears × 10)

lock_clears is incremented by SARA's loop when it detects the LLM is stuck, progressively relaxing limits.

Registration in SARA

In core/services_registry.py:

def _make_pythonnet_toolset(session_id: str):
    from services.pythonnet.tools import PythonnetToolRegistry
    return PythonnetToolRegistry(session_id=session_id)

SERVICE_FACTORIES["pythonnet"] = _make_pythonnet_toolset

PIPELINES["pythonnet"] = {
    "name": "Pythonnet",
    "description": ".NET assembly decompilation and patching",
    "supported_formats": ["EXE", "DLL", ".NET"],
    "capabilities": ["decompile", "patch", "rename"],
    "services": ["pythonnet"],
    "available": _pythonnet_available,
    "loader_tool": "pythonnet_load_binary",
}

Volume layout in SARA

When running inside SARA's docker-compose-sara-dev.yml:

  • /data/samples is mounted read-only in the pythonnet-mcp container. The server never writes there.
  • All write operations (working copies, patched binaries, extracted resources) go to /data/pythonnet_projects/{analysis_id}/.

License

The Python source files in this project are released under the MIT License — see LICENSE.

The bundled .NET assemblies in dll/ are subject to their own licenses — see the Dependencies section above, in particular the GPL-3.0 notice for the dnSpy assemblies.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured