MCP server providing Java development capabilities through Eclipse JDT.LS
Project description
jons-mcp-java
MCP server that provides Java language intelligence through Eclipse JDT.LS.
Released packages are available from PyPI. Development versions can also be run from a source checkout or directly from GitHub.
The current public API is aligned with jons-mcp-typescript: public positions
are one-based, successful tool responses use structured items and pagination
shapes, and refactoring previews are read-only.
Requirements
- Python 3.10+
- Java 21+
- Eclipse JDT.LS
- A target Java workspace containing Gradle project markers:
settings.gradle,settings.gradle.kts,build.gradle, orbuild.gradle.kts
On macOS with Homebrew:
brew install openjdk@21 jdtls
If Java is not on your PATH, set JAVA_HOME. If JDT.LS is installed somewhere
custom, set JDTLS_HOME. The server also tries to resolve a jdtls
executable on PATH.
If JDTLS_HOME points at a read-only install such as the Nix store, the server
copies the small platform config_<os> directory into a writable cache under
$XDG_CACHE_HOME/jons-mcp-java or ~/.cache/jons-mcp-java. Set
JDTLS_CONFIG_DIR to choose a specific writable configuration directory. The
cached copy is repaired to be user-writable even when the source archive or
package ships read-only mode bits.
Install and Run
From PyPI:
uvx jons-mcp-java /path/to/java-workspace
From a source checkout:
git clone git@github.com:jonmmease/jons-mcp-java.git
cd jons-mcp-java
uv sync
uv run jons-mcp-java /path/to/java-workspace
From GitHub without a persistent checkout:
uvx --from git+https://github.com/jonmmease/jons-mcp-java.git \
jons-mcp-java /path/to/java-workspace
Pass the Java workspace root as the optional positional argument, or set
JONS_MCP_JAVA_WORKSPACE. The positional argument takes precedence. If neither
is provided, the server uses the MCP process current working directory. All
relative tool paths are resolved from this workspace root.
MCP Client Examples
Claude Code using PyPI:
claude mcp add jons-mcp-java \
-- uvx jons-mcp-java /path/to/java-workspace
Claude Code using a source checkout:
claude mcp add jons-mcp-java \
-- uv run --project /path/to/jons-mcp-java \
jons-mcp-java /path/to/java-workspace
Claude Code using GitHub:
claude mcp add jons-mcp-java \
-- uvx --from git+https://github.com/jonmmease/jons-mcp-java.git \
jons-mcp-java /path/to/java-workspace
Codex CLI using PyPI:
codex mcp add jons-mcp-java \
-- uvx jons-mcp-java /path/to/java-workspace
Codex CLI using GitHub:
codex mcp add jons-mcp-java \
-- uvx --from git+https://github.com/jonmmease/jons-mcp-java.git \
jons-mcp-java /path/to/java-workspace
.mcp.json:
{
"mcpServers": {
"jons-mcp-java": {
"command": "uvx",
"args": [
"jons-mcp-java",
"/path/to/java-workspace"
]
}
}
}
Codex TOML:
[mcp_servers.jons-mcp-java]
command = "uvx"
args = [
"jons-mcp-java",
"/path/to/java-workspace",
]
Workspace and Path Behavior
The configured workspace root is the filesystem security boundary.
- Tool paths may be workspace-relative paths, absolute in-workspace paths, or
file://URIs. - Relative paths are resolved from the configured workspace root, not from the MCP server process cwd.
- Paths containing
.., paths outside the workspace, non-file URIs, malformed URIs, missing files, and symlink escapes are rejected before any filesystem or JDT.LS access. - LSP locations outside the workspace may still be returned with
"inWorkspace": false, but the server does not open or read external files.
Path and startup failures use a stable error shape:
{
"status": "error",
"error": {
"type": "path_outside_workspace",
"message": "Path resolves outside the configured workspace root.",
"path": "../outside.java"
}
}
Available Tools
| Tool | Description |
|---|---|
definition |
Go to symbol definition |
references |
Find all references to a symbol |
implementation |
Find implementations of interfaces/abstract methods |
type_definition |
Go to type definition |
document_symbols |
List symbols in a file |
workspace_symbols |
Search symbols in an initialized project |
diagnostics |
Get fresh diagnostics for one file |
symbol_info |
Get hover-style Javadoc and type information |
preview_rename |
Preview symbol rename edits without writing files |
restart_server |
Stop one or all JDT.LS clients and clear runtime state |
The first file-backed call for a project starts JDT.LS lazily and usually returns:
{
"status": "initializing",
"message": "Starting project initialization; please retry shortly.",
"project": "/path/to/java-workspace/app"
}
Retry the same tool after initialization finishes.
Tool Behavior
Tools that accept or return line and character use one-based positions,
matching editor and agent Read output. If your editor shows line 28, pass
line=28; returned ranges use the same convention. Use document_symbols to
discover one-based symbol ranges when you do not already know a position.
Successful navigation tools return normalized items:
{
"items": [
{
"uri": "file:///path/to/Main.java",
"range": {
"start": { "line": 12, "character": 8 },
"end": { "line": 12, "character": 12 }
},
"inWorkspace": true
}
],
"totalItems": 1
}
references, document_symbols, workspace_symbols, and diagnostics return
paginated results with items, totalItems, offset, limit, hasMore, and
nextOffset.
Navigation tools preserve JDT.LS result order and return items plus
totalItems. references, diagnostics, and symbol lists are sorted
deterministically before pagination.
preview_rename is safe to inspect. It returns a flat list of file URI,
one-based replacement range, newText, and inWorkspace values, plus
totalEdits. It does not write to disk.
Freshness and Restart
The server tracks open LSP documents and compares disk metadata plus content
hashes before read-style tool calls. If a file changed outside JDT.LS, the
server sends a full-document didChange and didSave before requesting fresh
language data.
diagnostics is file-scoped and always refreshes the target file before
returning compiler diagnostics.
Use restart_server only as a fallback:
{ "file_path": "app/src/main/java/example/Main.java" }
With no file_path, restart_server stops all active JDT.LS clients. Servers
restart lazily on the next file-backed tool call.
Troubleshooting
JDT.LS not found: install JDT.LS, putjdtlson PATH, or setJDTLS_HOME.Java 21+ required: install Java 21+ or setJAVA_HOME.project_not_found: the file is inside the workspace, but not under a discovered Gradle root.path_outside_workspace: the path resolves outside the configured workspace root.project_startup_failed: the project import failed; check the JDT.LS stderr log under the generated workspace data directory in~/.cache/jdtls-workspaces.- Read-only
JDTLS_HOME: setJDTLS_CONFIG_DIRto a writable directory, or let the server create and permission-repair its cached config copy automatically.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jons_mcp_java-0.0.1-py3-none-any.whl.
File metadata
- Download URL: jons_mcp_java-0.0.1-py3-none-any.whl
- Upload date:
- Size: 38.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5da037cd703f1023d3056587b331bca2705c4b13538b4bbf6a068d2562361b21
|
|
| MD5 |
74c204b80de0a6d4c18a7db69b64ec2c
|
|
| BLAKE2b-256 |
bcf59f9a163b9756b324b08e8c963ddbff7fdbfc7504d4bc8b6b73f5f305d3fd
|
Provenance
The following attestation bundles were made for jons_mcp_java-0.0.1-py3-none-any.whl:
Publisher:
release.yml on jonmmease/jons-mcp-java
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jons_mcp_java-0.0.1-py3-none-any.whl -
Subject digest:
5da037cd703f1023d3056587b331bca2705c4b13538b4bbf6a068d2562361b21 - Sigstore transparency entry: 1704360953
- Sigstore integration time:
-
Permalink:
jonmmease/jons-mcp-java@f07cb5d3c376edc22230dbd96e75a341c1afb500 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/jonmmease
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f07cb5d3c376edc22230dbd96e75a341c1afb500 -
Trigger Event:
release
-
Statement type: