Skip to main content
Glama
pgatzka

jar-inspector-mcp

by pgatzka

jar-inspector-mcp

An MCP server that lets Claude Code read inside Java archives — classes, APIs, sources, resources, bytecode — without extracting them.

The problem

When Claude Code works on a JVM project and needs to know what is inside a jar, it falls back on shell tools:

unzip -l target/lib/jackson-databind-2.16.1.jar     # 780 lines of entry listing
unzip -o app.jar -d /tmp/x && cat /tmp/x/…/Foo.java # a whole file to answer one question
javap -p -c -cp app.jar com.acme.Foo                # 300 KB of bytecode

All of it lands in the context window, most of it is noise, and some of it writes temporary files into the working tree.

The solution

Ten focused tools that answer the actual questions — "what is in this jar", "what is this class's API", "where is this string set" — and return only that.

Measured on jackson-databind-2.16.1.jar (779 classes, 4.1 MB extracted):

Instead of

jar-inspector

unzip -l <jar>

79,674 chars

jar_overview

2,632 chars

97% less

javap <class>

36,008 chars

jar_class_outline

18,061 chars

50% less

javap -p -c <class>

303,105 chars

jar_class_outline

21,409 chars

93% less

Nothing is ever written to disk, and no JDK is required — the class file parser is pure Python. (jar_disassemble is the one exception; it shells out to javap.)

Install

Requires uv and Python 3.10+.

# from GitHub, nothing to clone
claude mcp add jar-inspector -- uvx --from git+https://github.com/pgatzka/jar-inspector-mcp jar-inspector-mcp

# or from a local clone
git clone https://github.com/pgatzka/jar-inspector-mcp && cd jar-inspector-mcp
claude mcp add jar-inspector -- uv run --directory "$PWD" jar-inspector-mcp

Add --scope project to share it with a repo through .mcp.json, or --scope user to enable it everywhere. To wire it up by hand instead:

// .mcp.json
{
  "mcpServers": {
    "jar-inspector": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/pgatzka/jar-inspector-mcp", "jar-inspector-mcp"]
    }
  }
}

Verify with claude mcp list, or /mcp inside Claude Code.

Other MCP clients: the server speaks stdio, so uvx --from … jar-inspector-mcp works as the command anywhere.

Tools

Tool

Answers

jar_overview

What is this artifact? Manifest, packages, class count, bytecode level, are sources attached

jar_list

What entries are in it? Filtered by glob and kind, paged

jar_find_class

Where does HttpClient live? Simple name, FQCN or glob → class names

jar_class_outline

What is this class's API? Declaration, annotations, fields, method signatures

jar_read_source

What does it actually do? Attached .java/.kt source, by line window

jar_read_entry

What is in this config? One text entry: MANIFEST, META-INF/services/…, XML

jar_search

Where is this string? Grep across text entries and compiled string constants

jar_class_dependencies

What does this class touch? Internal vs external references

jar_disassemble

What does this method compile to? One method's bytecode via javap

jar_find

Where is the jar? Searches build output, the Maven repo and the Gradle cache

Every tool is read-only and takes a jar argument that accepts:

  • an archive — .jar, .war, .ear, .aar, .zip, .jmod

  • an exploded classes directory — target/classes, build/classes/java/main

  • a nested archive — app.jar!BOOT-INF/lib/dep-1.0.jar (Spring Boot fat jars)

What the output looks like

jar_class_outline, verbatim (this is the exact output the tests assert on):

com.acme.demo.UserService  [class, Java 21, UserService.java]
// source is attached -- jar_read_source(jar, 'com.acme.demo.UserService') shows it

@Deprecated
@Marker(enabled=true, code='z', tags={"alpha", "beta"})
public class UserService implements Repository<String, Integer>

  // fields (2)
  public static final String CACHE_KEY = "user.cache"
  protected volatile boolean dirty

  // constructors (1)
  public UserService(Map<Integer, String> users)

  // methods (5)
  public long count()
  public List<String> findAll()
  public Optional<String> findById(Integer id) throws IllegalStateException
  public <R extends Comparable<R>> List<R> mapAll(Function<String, R> fn)
  public void rename(int id, String newName, String... aliases)

  // nested (1)
  UserService.Builder

  // 4 more member(s) hidden (visibility below 'protected', synthetic or bridge)

Generic signatures, parameter names (when compiled with -g), varargs, declared exceptions, constant values, records, enums and default methods all survive. Method bodies, bridge methods and constant pools do not.

Configuration

Environment variable

Effect

JAR_INSPECTOR_ALLOW

Path-separated roots the server may read. Unset means no restriction

JAR_INSPECTOR_SEARCH_PATH

Extra directories jar_find scans first

MAVEN_REPO_LOCAL

Maven repository location, if not ~/.m2/repository

jar_find searches, in order: ./target, ./build/libs, ./libs, ./lib, the Maven repository, the Gradle module cache, the Ivy cache and the Coursier cache.

To confine the server to one tree:

claude mcp add jar-inspector --env JAR_INSPECTOR_ALLOW="$HOME/work:$HOME/.m2" \
  -- uvx --from git+https://github.com/pgatzka/jar-inspector-mcp jar-inspector-mcp

Nudging Claude to use it

The server ships MCP instructions telling clients these tools replace unzip, jar xf and javap. If you still see Claude reaching for the shell, add a line to your project's CLAUDE.md:

To inspect jars, use the jar-inspector MCP tools instead of unzip/jar/javap.

How it works

  • Class parsing is a dependency-free reader for the class file format: constant pool, access flags, Signature, MethodParameters, LocalVariableTable, Exceptions, Record, InnerClasses and the runtime annotation attributes. Method bodies are skipped unless jar_disassemble asks for them.

  • Archives are read through zipfile in memory. Nested jars are opened from the bytes of the outer entry, so a Spring Boot fat jar needs no unpacking.

  • Sources are resolved from the archive itself, then from the sibling -sources.jar in Maven layout, then from the neighbouring hash directory that Gradle's cache uses.

  • Output is always capped and always says when it was truncated and how to page.

Development

uv sync
uv run pytest          # 49 tests

The tests compile the Java in tests/java with javac and assert against real bytecode, so generics, bridge methods and records are exercised for real; they skip when no JDK is present. The parser is additionally checked against every class in every jar shipped with Maven and Gradle — 65,573 classes, no failures.

License

MIT

-
license - not tested
-
quality - not tested
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.

Related MCP Connectors

  • Augments MCP Server - A comprehensive framework documentation provider for Claude Code

  • An MCP server that gives your AI access to the source code and docs of all public github repos

  • A MCP server built for developers enabling Git based project management with project and personal…

View all MCP Connectors

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/pgatzka/jar-inspector-mcp'

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