The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Maven Decoder listing page.
Your agent guesses at library APIs it has never read. This makes it read them.
Lets AI agents read the actual source of any Maven dependency — decompiles jars from
~/.m2 or Maven Central, and diffs versions for breaking changes.

Ask an agent "I'm upgrading org.jsoup:jsoup from 1.17.2 to 1.23.2 — what breaks?" and
without a way to read the jars it will answer from memory. With this server,
compare_versions reads both jars and reports what actually changed:
| 1.17.2 → 1.23.2 | |
|---|---|
| Breaking changes | 45 |
| Members removed | 31 |
| Members added | 150 |
| Classes with API changes | 47 of 115 compared |
Members are compared as declared, so one that moved to a supertype is reported as removed even though it may still be callable. The tool states this in its own output.
It works on artifacts that have no sources jar too: extract_class_info falls back
to javap and returns parsed fields, methods, and bytecode version — which is exactly
the case for the internal artifacts in a corporate Nexus.
That installs the maven-code-search agent skill, which tells your agent when to reach
for these tools. For a raw MCP server setup instead, see Installation.
~/.m2/repository)For a source checkout, use Python 3.10 or newer and a JDK on PATH. From the
repository root, create and activate a virtual environment in PowerShell:
In Command Prompt (cmd.exe), activate with .venv\Scripts\activate.bat and set
the repository with set "MAVEN_REPOSITORY=F:\data\repository" instead. These
environment settings apply to programs launched from that terminal; set them in
your MCP client's environment when it launches the server separately.
Remote downloads use a separate cache, resolved in this order (empty values are skipped):
MAVEN_DECODER_CACHE_DIR: the complete cache directory; no subdirectory is appended.XDG_CACHE_HOME: append maven-decoder-mcp\repository.LOCALAPPDATA: append maven-decoder-mcp\repository.~/.cache/maven-decoder-mcp/repository under your home directory.On Windows, this usually means %LOCALAPPDATA%\maven-decoder-mcp\repository;
XDG_CACHE_HOME still takes precedence if set. The cache uses Maven's directory
layout but stays separate from the real local repository so downloads do not
interfere with Maven builds. Setting MAVEN_REPOSITORY does not change the cache
location.
Add to your ~/.cursor/mcp_servers.json:
The server runs as a standard MCP server and can be integrated with any MCP-compatible client.
This repository includes a maven-code-search agent skill that tells AI coding agents when and how to use this MCP for searching installed Maven package code.
The skill is located at skills/maven-code-search and is ready for skills.sh indexing after the repository is pushed.
| Tool | Description |
|---|---|
list_artifacts | List artifacts in Maven repository with filtering |
analyze_jar | Analyze jar file structure and contents |
extract_class_info | Get detailed information about Java classes |
get_dependencies | Retrieve Maven dependencies from POM files |
search_classes | Search for classes across all jars, optionally filtered by annotation |
extract_source_code | Decompile and extract Java source code |
extract_jar_resource | Extract text resources such as .proto files, services, and metadata |
compare_versions | Compare two versions, including a public API diff and breaking changes |
find_usage_examples | Find classes that reference a given class or method |
get_dependency_tree | Get complete dependency tree |
find_dependents | Find artifacts that depend on a specific artifact |
get_version_info | Get installed versions of an artifact (set include_remote to add published ones) |
analyze_jar_structure | Analyze overall jar structure and metadata |
extract_method_info | Extract specific method information from Java classes |
| Tool | Description |
|---|---|
search_maven_central | Search Maven Central for artifacts by name, coordinates, or contained class |
get_remote_versions | List every version published remotely, flagging which are installed |
download_artifact | Download an artifact (jar/sources/POM) into the local cache; accepts latest |
| Tool | Parameter | Type | Default | Description |
|---|---|---|---|---|
list_artifacts | group_id | string | — | Filter by group ID (e.g., 'org.springframework') |
list_artifacts | artifact_id | string | — | Filter by artifact ID (e.g., 'spring-core') |
list_artifacts | version | string | — | Filter by version (e.g., '5.3.21') |
list_artifacts | sort_by | string | name | Order results by: 'name' (group/artifact/version ascending, default), 'size' (largest jars first), or 'modified' (most recently modified first). Unknown values fall back to 'name'. |
list_artifacts | limit | integer | 50 | Maximum number of artifacts to return |
list_artifacts | page | integer | 1 | Page number for pagination |
list_artifacts | items_per_page | integer | 20 | Items per page |
analyze_jar | group_id* | string | — | Maven group ID |
analyze_jar | artifact_id* | string | — | Maven artifact ID |
analyze_jar | version* | string | — | Maven version |
analyze_jar | include_bytecode | boolean | False | Include bytecode analysis |
analyze_jar | include_manifest | boolean | True | Include JAR manifest |
analyze_jar | summarize_large_content | boolean | True | Summarize large content automatically |
extract_class_info | group_id* | string | — | Maven group ID |
extract_class_info | artifact_id* | string | — | Maven artifact ID |
extract_class_info | version* | string | — | Maven version |
extract_class_info | class_pattern | string | — | Pattern to match class names (regex supported) |
extract_class_info | include_methods | boolean | True | Include method signatures |
extract_class_info | include_fields | boolean | True | Include field information |
extract_class_info | include_bytecode | boolean | False | Include verbose javap bytecode output for matched classes |
extract_class_info | page | integer | 1 | Page number for pagination |
extract_class_info | items_per_page | integer | 20 | Items per page |
extract_class_info | summarize_large_content | boolean | True | Summarize large content automatically |
get_dependencies | group_id* | string | — | Maven group ID |
get_dependencies | artifact_id* | string | — | Maven artifact ID |
get_dependencies | version* | string | — | Maven version |
get_dependencies | include_transitive | boolean | False | Include transitive dependencies |
get_dependencies | page | integer | 1 | Page number for pagination |
get_dependencies | items_per_page | integer | 20 | Items per page |
search_classes | class_name | string | — | Class name to search for (supports wildcards) |
search_classes | package_pattern | string | — | Package pattern to filter by |
search_classes | annotation | string | — | Search for classes with specific annotation |
search_classes | case_sensitive | boolean | True | Match class_name and package_pattern case-sensitively. Set false for a case-insensitive search (e.g. 'arraylist' matches 'ArrayList'). |
search_classes | limit | integer | 100 | Maximum results to return |
search_classes | page | integer | 1 | Page number for pagination |
search_classes | items_per_page | integer | 20 | Items per page |
extract_source_code | group_id* | string | — | Maven group ID |
extract_source_code | artifact_id* | string | — | Maven artifact ID |
extract_source_code | version* | string | — | Maven version |
extract_source_code | class_name* | string | — | Fully qualified class name |
extract_source_code | prefer_sources | boolean | True | Prefer source jar over decompilation |
extract_source_code | summarize_large_content | boolean | True | Summarize large content automatically |
extract_source_code | max_lines | integer | 500 | Maximum lines to return (0 for all) |
extract_jar_resource | group_id* | string | — | Maven group ID |
extract_jar_resource | artifact_id* | string | — | Maven artifact ID |
extract_jar_resource | version* | string | — | Maven version |
extract_jar_resource | resource_path | string | — | Exact resource path inside the jar |
extract_jar_resource | resource_pattern | string | — | Regex pattern to match resource paths |
extract_jar_resource | max_bytes | integer | 65536 | Maximum bytes to read per resource |
extract_jar_resource | limit | integer | 20 | Maximum matching resources to return |
compare_versions | group_id* | string | — | Maven group ID |
compare_versions | artifact_id* | string | — | Maven artifact ID |
compare_versions | version1* | string | — | First (older) version to compare |
compare_versions | version2* | string | — | Second (newer) version to compare |
compare_versions | compare_api | boolean | True | Diff the public API: added/removed public and protected methods and fields, and breaking changes |
compare_versions | resolve_inherited | boolean | False | Reclassify members that disappeared from a class but are still declared on a supertype within the new jar into a 'moved to supertype' bucket instead of counting them as breaking removals. Defaults to false (byte-identical to the as-declared diff). |
compare_versions | summarize_large_content | boolean | True | Summarize large content automatically |
find_usage_examples | class_name* | string | — | Class name to find usage for |
find_usage_examples | method_name | string | — | Method name to find usage for |
find_usage_examples | search_tests | boolean | True | Search in test jars |
find_usage_examples | limit | integer | 50 | Maximum results to return |
find_usage_examples | page | integer | 1 | Page number for pagination |
find_usage_examples | items_per_page | integer | 20 | Items per page |
get_dependency_tree | group_id* | string | — | Maven group ID |
get_dependency_tree | artifact_id* | string | — | Maven artifact ID |
get_dependency_tree | version* | string | — | Maven version |
get_dependency_tree | max_depth | integer | 3 | Maximum depth to show |
get_dependency_tree | summarize_large_content | boolean | True | Summarize large content automatically |
find_dependents | group_id* | string | — | Target group ID |
find_dependents | artifact_id* | string | — | Target artifact ID |
find_dependents | version | string | — | Specific version to search for (optional) |
find_dependents | limit | integer | 100 | Maximum results to return |
find_dependents | page | integer | 1 | Page number for pagination |
find_dependents | items_per_page | integer | 20 | Items per page |
get_version_info | group_id* | string | — | Maven group ID |
get_version_info | artifact_id* | string | — | Maven artifact ID |
get_version_info | include_remote | boolean | False | Also list versions published on the remote repository (not just installed ones) |
get_version_info | limit | integer | 50 | Maximum versions to return |
get_version_info | page | integer | 1 | Page number for pagination |
get_version_info | items_per_page | integer | 20 | Items per page |
analyze_jar_structure | group_id* | string | — | Maven group ID |
analyze_jar_structure | artifact_id* | string | — | Maven artifact ID |
analyze_jar_structure | version* | string | — | Maven version |
analyze_jar_structure | summarize_large_content | boolean | True | Summarize large content automatically |
extract_method_info | group_id* | string | — | Maven group ID |
extract_method_info | artifact_id* | string | — | Maven artifact ID |
extract_method_info | version* | string | — | Maven version |
extract_method_info | class_name* | string | — | Fully qualified class name |
extract_method_info | method_pattern | string | — | Pattern to match method names (regex supported) |
extract_method_info | include_bytecode | boolean | False | Include bytecode analysis |
extract_method_info | max_methods | integer | 10 | Maximum number of methods to return |
search_maven_central | query | string | — | Free-text search term (e.g. 'jackson databind') |
search_maven_central | group_id | string | — | Exact group ID filter (e.g. 'org.springframework') |
search_maven_central | artifact_id | string | — | Exact artifact ID filter (e.g. 'spring-core') |
search_maven_central | class_name | string | — | Simple class name to find the containing artifact (e.g. 'ObjectMapper') |
search_maven_central | fully_qualified_class | string | — | Fully qualified class name (e.g. 'com.fasterxml.jackson.databind.ObjectMapper') |
search_maven_central | packaging | string | — | Packaging filter (e.g. 'jar', 'pom') |
search_maven_central | all_versions | boolean | False | Return every published version instead of only the latest per artifact |
search_maven_central | limit | integer | 20 | Maximum results to return (max 200) |
search_maven_central | page | integer | 1 | Page number for pagination |
get_remote_versions | group_id* | string | — | Maven group ID |
get_remote_versions | artifact_id* | string | — | Maven artifact ID |
get_remote_versions | include_snapshots | boolean | True | Include -SNAPSHOT versions. Set false to list only released versions. |
get_remote_versions | limit | integer | 100 | Maximum versions to return |
download_artifact | group_id* | string | — | Maven group ID |
download_artifact | artifact_id* | string | — | Maven artifact ID |
download_artifact | version* | string | — | Version to download, or 'latest' for the newest release |
download_artifact | include_sources | boolean | True | Also download the sources jar when published |
download_artifact | include_javadoc | boolean | False | Also download the javadoc jar when published |
download_artifact | classifier | string | — | Download a specific classified jar instead of the main one |
download_artifact | force | boolean | False | Re-download even when the file is already cached |
* Required — the parameter appears in the tool's inputSchema required array. Parameters without a * are optional and may be omitted.
compare_versions diffs the public and protected members of every class the
two versions share, and reports removals separately from additions. Removed
members and removed classes are counted as breaking changes. Members are
compared as declared, so one that moved to a supertype is reported as
removed even though it may still be callable.
find_usage_examples scans compiled class constant pools, so it finds real callers
rather than simple name matches. Pass method_name (such as readValue) to narrow
the results to callers of a specific method. Test jars are included by default and
ranked first because they often contain the clearest examples; set search_tests to
false to exclude them. The scan stops after MCP_USAGE_SCAN_LIMIT classes (default:
200000) to stay responsive on large repositories.
When a dependency has no sources jar, extract_class_info uses javap internally and returns parsed fields, methods, bytecode version, and optional verbose bytecode output. Agents should use analyze_jar, extract_class_info, extract_source_code, and extract_jar_resource through this MCP instead of running jar or javap directly.
The server works against the local repository and remote repositories. Online access is enabled by default.
~/.m2/repository).~/.cache/maven-decoder-mcp/repository) that uses the standard Maven layout.The cache is deliberately separate from ~/.m2 so downloads never interfere
with your Maven or Gradle builds. Responses include an origin field
(local-repository or remote-cache) so you always know where a result came from.
Artifact downloads use repo1.maven.org, which is fast and reliable.
Artifact search uses search.maven.org, the only public index that answers
class-level (c: / fc:) queries correctly. That index rate-limits bursts, so
requests are retried with backoff; a busy period can still surface as a timeout.
Downloads and version listing are unaffected, because they read
maven-metadata.xml directly from the repository.
The server automatically handles large responses through intelligent pagination:
list_artifacts, extract_class_info, search_classes, get_dependencies, find_dependents, get_version_infoLarge text content is automatically summarized to improve readability:
New tool for targeted access to specific methods:
The server is built with a modular architecture:
MavenDecoderServer: Main MCP server implementationResponseManager: Handles pagination and summarizationJavaDecompiler: Handles multiple decompilation strategiesMavenDependencyAnalyzer: Analyzes Maven dependencies and metadataMavenCentralClient: Remote search, version listing, and artifact downloadsMAVEN_REPOSITORY / MAVEN_REPO: direct path to local Maven repository (e.g. F:\data\repository). Highest precedence.MAVEN_HOME / M2_HOME: Maven install dir or repository dir. A nested repository/ subdir wins when it exists; conf/settings.xml <localRepository> honored.~/.m2/settings.xml <localRepository> honored when no env var set. Fallback: ~/.m2/repository.MAVEN_OFFLINE: set to true to disable all network access (default: false)MAVEN_AUTO_DOWNLOAD: auto-fetch artifacts missing locally (default: true)MAVEN_REMOTE_REPOS / MAVEN_REMOTE_REPO: comma/space separated repository base URLs (default: https://repo1.maven.org/maven2)MAVEN_SEARCH_URL: comma/space separated Solr search endpoints (default: https://search.maven.org/solrsearch/select)MAVEN_DECODER_CACHE_DIR: where downloaded artifacts are cached (default: ~/.cache/maven-decoder-mcp/repository)MAVEN_REMOTE_USERNAME / MAVEN_REMOTE_PASSWORD: basic-auth credentials for a private mirrorMAVEN_HTTP_TIMEOUT: per-request timeout in seconds (default: 30)MAVEN_HTTP_RETRIES: retries for transient network failures (default: 3)MAVEN_MAX_DOWNLOAD_SIZE: maximum download size in bytes (default: 104857600)MAVEN_VERIFY_CHECKSUM: verify downloads against published SHA-1 (default: true)MCP_LOG_LEVEL: Logging level (DEBUG, INFO, WARNING, ERROR)MCP_MAX_RESPONSE_SIZE: Maximum response size in bytes (default: 50000)MCP_MAX_ITEMS_PER_PAGE: Default items per page (default: 20)MCP_MAX_TEXT_LENGTH: Maximum text length before summarization (default: 10000)MCP_MAX_LINES: Maximum lines before summarization (default: 500)MCP_USAGE_SCAN_LIMIT: Max classes scanned by find_usage_examples (default: 200000)MCP_API_DIFF_LIMIT: Max classes compared by compare_versions (default: 2000)MAVEN_DECODER_DECOMPILER_DIR: Directory holding cfr.jar / procyon-decompiler.jarThe server automatically detects and configures:
Server won't start
Decompilation fails
From a source checkout you can instead run ./setup_decompilers.sh, which downloads
CFR and Procyon into a decompilers/ directory beside the script, as
decompilers/cfr.jar and decompilers/procyon-decompiler.jar.
If maven-decoder-setup status reports no decompilers even though you have the jars,
they are somewhere the server does not look. It searches these roots in order, taking
the first match:
$MAVEN_DECODER_DECOMPILER_DIR, if setdecompilers/ inside the installed packagedecompilers/ beside the package — the source-checkout layout~/.cache/maven-decoder-mcp/decompilersdecompilers/ in the current working directoryYour MCP client launches the server from an arbitrary working directory, so the last two are unreliable in practice. If your jars live anywhere else, point at them explicitly:
The directory must contain the jars under the exact names cfr.jar and
procyon-decompiler.jar. The value expands ~ and environment variables.
Without CFR or Procyon the server still works, falling back to javap from
the JDK for signatures, fields and methods.
No artifacts found
Maven Central search times out
The public search index rate-limits bursts of requests. Retries with backoff are built in, but during heavy throttling a search can still fail. Workarounds:
Downloads fail behind a proxy or firewall
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ for the Java development community