jar-inspector-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jar-inspector-mcp Show me the outline of com.example.UserService in target/app.jar"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 bytecodeAll of it lands in the context window, most of it is noise, and some of it writes temporary files into the working tree.
Related MCP server: dejared-mcp
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 | |||
| 79,674 chars |
| 2,632 chars | 97% less |
| 36,008 chars |
| 18,061 chars | 50% less |
| 303,105 chars |
| 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-mcpAdd --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 |
| What is this artifact? Manifest, packages, class count, bytecode level, are sources attached |
| What entries are in it? Filtered by glob and kind, paged |
| Where does |
| What is this class's API? Declaration, annotations, fields, method signatures |
| What does it actually do? Attached |
| What is in this config? One text entry: MANIFEST, |
| Where is this string? Grep across text entries and compiled string constants |
| What does this class touch? Internal vs external references |
| What does this method compile to? One method's bytecode via |
| 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,.jmodan exploded classes directory —
target/classes,build/classes/java/maina 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 |
| Path-separated roots the server may read. Unset means no restriction |
| Extra directories |
| Maven repository location, if not |
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-mcpNudging 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,InnerClassesand the runtime annotation attributes. Method bodies are skipped unlessjar_disassembleasks for them.Archives are read through
zipfilein 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.jarin 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 testsThe 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
Available Tools
10 toolsjar_class_dependenciesARead-only
List the classes a compiled class references, split into internal and external.
Useful for tracing what a class actually touches, and for spotting which dependency supplies a type, without decompiling anything.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
class_name: FQCN, simple name or glob.
include_jdk: Include java.*/javax.*/jdk.* references.
limit: Maximum references to list.
Inputs: jar (required), class_name (required), limit, include_jdk. Returns: result
jar_class_outlineARead-only
Show a class's API: declaration, annotations, fields and method signatures.
This is the cheap alternative to decompiling or reading source. Signatures
keep generics, parameter names (when compiled with -g), thrown exceptions
and constant values; method bodies are not included.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
class_name: FQCN, simple name or glob (resolved like jar_find_class).
visibility: Lowest visibility to include: public, protected, package, private.
include_synthetic: Include compiler-generated bridge/synthetic members.
fully_qualified_types: Print java.util.List instead of List.
Inputs: jar (required), class_name (required), visibility, include_synthetic, +1 more. Returns: result
jar_disassembleARead-only
Disassemble one method's bytecode with javap (needs a JDK on PATH).
Reach for this only when the API outline and the source are not enough --
for example when checking what a method compiles to, or reading a class
that has no sources attached. Always pass method to keep it small.
Args:
jar: Archive path or classes directory (nested ! specs are not supported).
class_name: FQCN, simple name or glob.
method: Method name to keep; empty returns every method (often large).
limit: Maximum lines of disassembly to return.
Inputs: jar (required), class_name (required), limit, method. Returns: result
jar_findARead-only
Find jar files on this machine by name: build output, Maven repo, Gradle cache.
Use it to turn "the Jackson databind jar" into a path you can pass to the other tools.
Args:
query: Part of the file name, or a glob such as jackson-databind-*.jar.
search_path: Extra directories to scan first, separated by the path separator.
include_classifiers: Also list -sources, -javadoc and -tests jars.
limit: Maximum jars to return.
Inputs: query (required), limit, search_path, include_classifiers. Returns: result
jar_find_classARead-only
Find classes in an archive by simple name, fully-qualified name or glob.
Use this to turn "where does HttpClient live" into a concrete class name
you can pass to jar_class_outline or jar_read_source.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
name: HttpClient, com.acme.HttpClient, or a glob like com.acme.*Repo.
limit: Maximum matches to return.
Inputs: jar (required), name (required), limit. Returns: result
jar_listARead-only
List entries in an archive, filtered by glob and kind.
Prefer this over unzip -l. Use kind='text' to find configuration,
kind='archive' to find jars bundled inside a fat jar.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
pattern: Comma-separated globs matched against the entry path, e.g.
META-INF/* or *.properties. Empty matches everything.
kind: One of all, class, source, text, binary, archive.
limit: Maximum entries to return.
offset: Entries to skip, for paging.
Inputs: jar (required), kind, limit, offset, +1 more. Returns: result
jar_overviewARead-only
Summarize a Java archive: manifest, size, packages, class count, and whether sources are attached.
Start here when you meet an unfamiliar jar, instead of unzipping it or listing every entry.
Args:
jar: Path to a .jar/.war/.aar/.zip, an exploded classes directory, or a
nested archive such as app.jar!BOOT-INF/lib/dep-1.0.jar.
Inputs: jar (required). Returns: result
jar_read_entryARead-only
Read one text entry from an archive: MANIFEST, service files, XML, config.
Prefer this over unzip -p. Binary entries are described, not dumped.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
entry: Exact entry path, e.g. META-INF/spring.factories.
start_line: 1-based first line to show.
line_count: How many lines to show.
Inputs: jar (required), entry (required), line_count, start_line. Returns: result
jar_read_sourceARead-only
Read attached Java/Kotlin source for a class, one line window at a time.
Looks inside the archive itself, then the matching -sources.jar next to it
(Maven layout) or beside it in the Gradle cache. If no source is available,
say so and fall back to jar_class_outline.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
target: FQCN (com.acme.Foo) or an entry path (com/acme/Foo.java).
start_line: 1-based first line to show.
line_count: How many lines to show; use a window rather than whole files.
sources_jar: Explicit sources archive, when auto-detection misses it.
Inputs: jar (required), target (required), line_count, start_line, +1 more. Returns: result
jar_searchARead-only
Grep text and source entries inside an archive, returning matching lines.
Use it to find a property key, a bean name, an SQL fragment or a log
message without extracting anything. With include_class_strings=True it
also searches string constants compiled into .class files.
Args:
jar: Archive path, classes directory, or outer.jar!nested.jar.
query: Literal text, or a Python regular expression when regex=True.
regex: Treat query as a regular expression.
ignore_case: Case-insensitive matching.
path: Comma-separated globs limiting which entries are searched.
include_class_strings: Also search string constants inside .class files.
limit: Maximum matches to report.
Inputs: jar (required), query (required), path, limit, +3 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 10 tools
Each tool targets a distinct inspection task: overview, listing, class lookup, API outline, source reading, entry reading, search, dependency analysis, disassembly, and jar discovery. There is no meaningful overlap that would make an agent likely to pick the wrong tool.
All tools share the jar_ prefix, which helps, but the grammatical pattern is mixed: jar_list and jar_search are bare verbs, jar_find_class and jar_read_source are verb_noun, while jar_overview and jar_class_outline are noun phrases. The names are readable but not consistently verb_noun.
Ten tools is well within the ideal range and each tool covers a distinct facet of archive inspection. The count feels neither bloated nor thin for the stated purpose.
The read-only jar inspection domain is covered thoroughly: overview, listing, class lookup, API outline, source reading, arbitrary text entries, grep-like search, class dependency analysis, bytecode disassembly, and locating jars on disk. An agent can move from finding a jar to reading its source or bytecode without obvious dead ends.
Maintenance
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…
MCP server for developer documentation, generated by doc2mcp.
Related MCP Servers
- AlicenseAqualityBmaintenanceAn MCP server for intelligently reading Java source code, supporting extraction from Maven dependencies and local projects with dual decompilers.2102 PyPI154Apache 2.0
- AlicenseNot gradedqualityBmaintenanceA Model Context Protocol (MCP) server for exploring, analyzing, and decompiling Java JAR files.570 npm9MIT
- AlicenseAqualityDmaintenanceMCP server that indexes your codebase's public API at startup and serves it via compact tool responses, saving tokens vs reading source files.533 PyPI21MIT
- AlicenseBqualityBmaintenanceMCP server for searching, browsing, and analyzing decompiled Minecraft source code locally. Supports symbol lookup, text search, reference lookup, and lightweight RAG.11Apache 2.0