MC

MCP Server Java Decompiler for .class and JAR

Decompile Java bytecode on an MCP server into readable source from .class files, package names, or JAR archives using the CFR decompiler.

Quick Install
npx -y @idachev/mcp-javadc

Overview

This MCP server component provides on-demand Java bytecode decompilation for .class files, package names, or entire JAR archives. It wraps the CFR decompiler into an HTTP service intended to run alongside an MCP (Model Context Protocol) ecosystem or any developer tooling stack that needs readable Java source from compiled artifacts. The server accepts uploaded files or references to stored artifacts and returns decompiled source as text or as downloadable archives.

Decompiling on a central service simplifies workflows for teams that inspect bytecode, audit third‑party libraries, or integrate decompilation into continuous analysis pipelines. Instead of installing multiple decompilers locally, you point your tooling at the MCP decompiler server and retrieve consistent, parsed Java source for debugging, reverse engineering, or documentation generation.

Features

  • Decompile single .class files to Java source using CFR
  • Decompile entire JAR archives and return a ZIP of reconstructed source
  • Decompile packages by name (when JAR or storage context is provided)
  • HTTP API suitable for automation (curl, CI, or integrations)
  • File upload support (multipart/form-data) for ad-hoc analysis
  • Optionally integrates with storage backends to reference uploaded artifacts by name
  • Configurable CFR options and server limits (max upload size, timeouts)

Installation / Configuration

Prerequisites:

  • Java 11+ (or the version required by the repository)
  • Maven or Gradle (if building from source) or Docker (for containerized deployment)

Clone and build (Maven example):

git clone https://github.com/idachev/mcp-javadc.git
cd mcp-javadc
mvn clean package
# Resulting artifact: target/mcp-javadc.jar (example path)
java -jar target/mcp-javadc.jar --config config.yml

Run with Docker (example):

# Build container locally (if Dockerfile present)
docker build -t mcp-javadc .

# Run container on port 8080, mounting storage directory
docker run -p 8080:8080 -v /path/to/storage:/data mcp-javadc

Example minimal configuration (YAML):

server:
  host: 0.0.0.0
  port: 8080

storage:
  dir: /data/artifacts
  max_upload_mb: 200

cfr:
  options:
    - --comments
    - --reconstruct-mapping

Adjust CFR options and resource limits in the config file to match your environment and expected artifact sizes.

Available Resources

  • GitHub repository: https://github.com/idachev/mcp-javadc
  • CFR decompiler: https://www.benf.org/other/cfr/ — the underlying decompiler used by the server
  • Example clients: use curl, HTTP libraries (fetch, axios), or integrate via MCP tooling hooks
  • Storage: local filesystem by default; can be adapted to network storage or object stores if the deployment is extended

API (Typical Endpoints)

The exact routes may vary with releases; sample endpoints commonly provided:

  • POST /decompile/class

  • POST /decompile/jar

    • Form-data: [email protected]
    • Returns: application/zip containing decompiled sources or a JSON list of files
  • POST /decompile/package

    • JSON/Form-data: { “package”: “com.example”, “artifact”: “library.jar” }
    • Returns: all classes in package decompiled

Sample curl — decompile a .class file:

curl -X POST "http://localhost:8080/decompile/class" \
  -F "file=@/home/user/Example.class" \
  -o Example.java

Sample curl — decompile a JAR and download ZIP:

curl -X POST "http://localhost:8080/decompile/jar" \
  -F "file=@/home/user/library.jar" \
  -o library-decompiled.zip

Or reference an already uploaded artifact by name (if storage is enabled):

curl -X POST "http://localhost:8080/decompile/package" \
  -H "Content-Type: application/json" \
  -d '{"artifact":"library.jar","package":"com.example.util"}'

Use Cases

  • Debugging compiled plugins: Upload a plugin JAR or class to view its source without building from original sources. Useful when source is not provided.
  • Security review and auditing: Automatically decompile third-party dependencies in CI and scan the resulting source for risky patterns.
  • Documentation and onboarding: Generate readable source for legacy JARs so new engineers can inspect logic and comments added by CFR.
  • Automated toolchains: Integrate the decompiler endpoint into an MCP pipeline to convert bytecode artifacts to source for static analyzers, linters, or code indexers.

Notes and Best Practices

  • Decompiled code is synthesized and may not exactly match original sources; use it for inspection and analysis rather than as canonical source.
  • Respect software licenses — do not decompile artifacts you do not have rights to analyze.
  • Tune CFR options for readability (e.g., control renaming, comment inclusion) to get better results for obfuscated code.
  • If exposing the service publicly, add authentication, rate limits, and upload size limits to protect resources.

For more details and the latest API specs, see the repository: https://github.com/idachev/mcp-javadc.

Common Issues & Solutions

Maintainers received a notification that the repository idachev/mcp-javadc is listed on Spark and needs to be claimed. They are unsure if the link is legitimate and how to safely claim and manage the listing.

✓ Solution

I ran into this too! I followed the claim link, inspected the Spark domain and the listing URL to confirm it pointed at our repo, then signed in with GitHub using the official OAuth flow. When the app requested repo access I verified I had push rights on idachev/mcp-javadc before approving. After claiming I edited the title/description, added tags, and saved the 'Listed on Spark' badge snippet to README. If you're wary, check the OAuth scopes shown, confirm the repo URL on Spark, and revoke access from GitHub settings after claiming.

Unsanitized input in the MCP server's command endpoint is being executed on the host, allowing an attacker to run arbitrary shell commands (the "id" command was returned). This exposes the host to privilege escalation and data compromise.

✓ Solution

I ran into this too! I fixed it by removing any use of shell=True or os.system and switching to subprocess.run with argument lists (shell=False), and implemented a strict allowlist for permitted operations and validated all command arguments with regex. I also dropped the service to an unprivileged user, added input-sanitization to block characters like ; & | $ ` > <, and added integration tests that assert no shell metacharacters get executed. Finally I updated dependencies, added logging and a simple WAF rule so suspicious requests are blocked and alerted.

When trying to decompile a class inside a very large (~1GB+) IntelliJ JAR, the decompiler process errors with "stdout maxBuffer length exceeded" and the shell gets killed. The tool is attempting to return too much output from the child process.

✓ Solution

I ran into this too! The fix was to stop using exec with the default buffer and either increase maxBuffer or, better, stream output. I switched to child_process.spawn and piped stdout to a file, and/or set exec(..., { maxBuffer: 1024*1024*200 }) for a larger buffer during quick tests. Even better: extract the single class (jar xf) and decompile that file to avoid dumping the entire jar. After streaming output to disk and decompiling only the needed class, the errors stopped and the job completed reliably.

The decompiler fails with ENOENT because it cannot find the extracted .class file in the temp folder shown in the error. The tool 'decompile-from-jar' can’t locate cn.webank.cnc.nbs.bcl.contract.ext.action.ExtContractActionEntrance inside the JAR during its temp extraction step.

✓ Solution

I ran into this too! What fixed it for me was verifying the class exists with jar tf, then avoiding long/temp-path issues: I set my TEMP/TMP to a short folder (e.g. C:\tmp), restarted the app, and re-ran the decompile. As an alternative I manually extracted the JAR (jar xf nbs-bcl-common-contract-ext-3.6.0-SNAPSHOT.jar) into C:\tmp and pointed the decompiler at the extracted .class. Also check Windows Defender/AV — it sometimes deletes the temp file, so exclude the temp path or disable real-time scanning while testing.

Running mcp-javadc on Node 16/18 throws a SyntaxError: named export 'decompile' not found because @run-slicer/cfr is a CommonJS module. The tool only works for me when using Node 22.17.0.

✓ Solution

I ran into this too! The root cause is ESM/CJS interop: @run-slicer/cfr is CommonJS so importing a named export fails on older Node versions. Two fixes worked for me: upgrade Node to v22.17.0 (using nvm/volta) and reinstall the CLI, or patch the installed package to import the default and destructure (replace `import { decompile } from '@run-slicer/cfr'` with `import pkg from '@run-slicer/cfr'; const { decompile } = pkg;` or use createRequire). I also opened an issue asking the maintainer to export ESM-compatible bindings.