Skip to content

Comments

Feature/java adapter#12

Merged
debugmcpdev merged 9 commits intodebugmcp:mainfrom
roofpig95008:feature/java-adapter
Feb 9, 2026
Merged

Feature/java adapter#12
debugmcpdev merged 9 commits intodebugmcp:mainfrom
roofpig95008:feature/java-adapter

Conversation

@roofpig95008
Copy link

@roofpig95008 roofpig95008 commented Feb 7, 2026


📋 Description

Adds Java/JDB debugging support to mcp-debugger as a new language adapter. This enables AI agents to step-through
debug Java applications using the standard jdb debugger included with the JDK, following the same adapter architecture
used by Python, JavaScript, and Rust adapters.

The implementation includes:

  • @debugmcp/adapter-java package with JavaAdapterFactory and JavaDebugAdapter
  • jdb-dap-server — a DAP protocol bridge that wraps jdb's text-based interface
  • Java adapter policy for DAP proxy integration
  • JDWP detection utilities for remote attach support
  • Java utility layer for executable/JDK discovery across platforms
  • Full launch and attach mode support
  • E2E smoke tests and attach tests

🔄 Type of Change

  • ✨ New feature (non-breaking change which adds functionality)

✅ Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

🧪 Testing

All 134 test suites pass (1517 tests), with 5 suites skipped (Docker/stress tests requiring infrastructure not
available in all environments).

Full test suite

npm test

Unit tests only

npm run test:unit

Java adapter unit tests specifically

npx vitest run packages/adapter-java/tests/

E2E Java smoke tests (requires JDK 8+)

npx vitest run tests/e2e/mcp-server-smoke-java.test.ts

E2E Java attach tests (requires JDK 8+)

npx vitest run tests/e2e/mcp-server-java-attach.test.ts

Test Configuration:

  • OS: Debian 13 (trixie) / Linux 6.6.116-0-virt (aarch64)
  • Node version: v24.13.0
  • Python version: 3.13 (for existing Python test suite)
  • Rust version: 1.93.0 (for existing Rust test suite)

📸 Screenshots (if applicable)

N/A — backend adapter with no UI components.

🔗 Related Issues

  • N/A

📝 Additional Notes

  • Java adapter follows the same patterns established by the Python and Rust adapters: factory pattern, dependency
    injection, AdapterError/AdapterErrorCode error types, and two-parameter stateChanged event emission.
  • The jdb-dap-server bridges DAP ↔ jdb's text protocol, similar to how the Python adapter bridges DAP ↔ debugpy.
  • JDK 8+ is required; jdb must be available (included in JDK, not JRE).
  • Attach mode supports both host:port and process ID targeting via JDWP/JPDA.
  • This PR also includes fixes to the pre-push hook (graceful Docker buildx detection, SIGPIPE handling, cargo
    env sourcing) and Docker test skip support via SKIP_DOCKER_TESTS.
  • The push with the hook still didn't succeed until we added ServerAliveInterval and ServerAliveCountMax to .ssh/config

Reviewer: @debugmcp

Richard Berlin and others added 8 commits February 7, 2026 02:40
Implements comprehensive Java debugging support using jdb (Java Debugger) as the
underlying debug engine, with full DAP (Debug Adapter Protocol) integration.

The Java adapter follows the established adapter pattern:
- **JdbDapServer**: DAP protocol server that translates DAP requests to jdb commands
- **JdbWrapper**: High-level wrapper around the jdb process
- **JdbParser**: Parses jdb command-line output into structured data
- **JavaAdapterPolicy**: Configures spawn behavior for Java debug sessions
- **JavaAdapterFactory**: Creates and initializes Java debug adapters

- Starts new JVM with jdb attached
- Supports `stopOnEntry` via breakpoint at main method
- Automatically extracts fully qualified class names from source files
- Compiles .java files if .class files not found

- Connects to running JVM with JDWP agent enabled
- Uses unified attach API (host/port in create_debug_session)
- Proper DAP sequencing with attach-specific flow

- Breakpoints (set, clear, verify)
- Step operations (step over, step into, step out)
- Stack traces with source locations
- Variable inspection (locals, scopes)
- Expression evaluation
- Continue/pause execution
- Thread management

- Accepts absolute paths for Java source files
- Extracts package declarations to build FQN
- Handles both packaged and default package classes

When `stopOnEntry: true` is specified in launch mode:
1. Extract FQN from Java source (package + class name)
2. Set breakpoint at main: `stop in com.example.MyClass.main`
3. Execute `run` command to start JVM
4. Emit 'entry' stop reason when breakpoint hits

Added JavaAdapterPolicy to `selectAdapterPolicy()` in dap-proxy-worker.ts.
Previously, Java sessions were using DefaultAdapterPolicy which lacked proper
spawn configuration, causing "Proxy exited during initialization" errors.

Modified `run()` in JdbWrapper to use `sendCommandDirect()` instead of
`executeCommand()`. The run command doesn't return a prompt until the program
stops, so we send it asynchronously and listen for stopped events.

- ✅ Complete Java debugging flow (breakpoint, stack, vars, step, continue)
- ✅ Multiple breakpoints
- ⚠️  Expression evaluation with stopOnEntry (times out in full suite)
- ✅ Source context retrieval
- ⚠️  Step into operations (times out in full suite)

Note: The two tests that timeout in the full suite pass consistently when run
individually, suggesting resource contention or cleanup issues when running
many E2E tests in sequence. Will be addressed in future work.

- ✅ Attach to running Java process
- ✅ Set breakpoint after attaching
- ✅ Detach without terminating process
- ✅ Session lifecycle management

- Added to pnpm workspace packages
- Included in build:packages script
- Integrated with CI/CD pipeline

- src/index.ts - Adapter factory export
- src/jdb-dap-server.ts - DAP server implementation
- src/factory.ts - JavaAdapterFactory
- src/utils/jdb-wrapper.ts - jdb process manager
- src/utils/jdb-parser.ts - Output parser
- tests/ - Comprehensive test suite

- src/proxy/dap-proxy-worker.ts - Added JavaAdapterPolicy selection
- packages/shared/src/interfaces/adapter-policy.ts - Exported JavaAdapterPolicy
- tests/e2e/ - Added Java smoke and attach tests
- package.json - Added build scripts and workspace config

- Java 8+ installed
- jdb available in PATH (included with JDK)
- For attach mode: Target JVM started with JDWP agent
  Example: `java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005`

- jdb includes Java internal frames in stack traces (by design)
- Requires absolute paths for file references
- stopOnEntry only works for main method entry point
- Expression evaluation requires VM to be running (jdb limitation)
- Two E2E tests timeout in full suite but pass individually (resource contention)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Enable the Java/jdb debug adapter to be loaded at runtime by adding
it to the optionalDependencies in package.json.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract mainClass from program path in transformLaunchConfig instead
  of hardcoding 'Main'. This fixes "Could not find or load main class"
  errors in launch mode.

- Fix attach tests to use 127.0.0.1 instead of 'localhost' to avoid
  IPv6 resolution issues when the Java process binds to IPv4 only.

- Improve attach test stability by:
  - Waiting for "Listening for transport" message before proceeding
  - Adding 2 second delay after session close to allow JDWP to accept
    new connections (JDWP only allows one debugger at a time)
  - Accepting 'initializing' as valid state since attach is async

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Different debug adapters send the 'initialized' event at different
points in the DAP sequence:
- Java/jdb: sends 'initialized' after initialize response, before attach
- Python/debugpy: sends 'initialized' AFTER receiving the launch request

This fix:
- For attach mode: wait for 'initialized' before sending attach
- For launch mode: send launch first, then handle 'initialized' later

Also updates unit tests to properly mock EventEmitter-based DAP client
and emit 'initialized' events in test stubs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update package version from 0.16.0 to 0.17.0 to match other adapters
- Use AdapterError/AdapterErrorCode instead of generic Error
- Fix stateChanged event to emit two params instead of object
- Add missing JSDoc comments on exported interfaces

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pre-push hook would fail when Docker was installed but buildx
was missing. Now checks for buildx availability before attempting
to build, allowing the push to proceed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pre-push hook auto-detects Docker buildx and sets SKIP_DOCKER_TESTS
- Pre-push hook sources cargo env for Rust test availability
- Docker smoke tests respect SKIP_DOCKER_TESTS via describe.skipIf
- docker-build-if-needed.js checks buildx before attempting build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verbose output from vitest (thousands of lines) was flooding the pipe
buffer between git and the hook process, causing SIGPIPE (exit 141)
which git treated as a hook failure even when all tests passed.

Now redirects lint/build/test output to a temp log file and only
prints a concise summary to stdout. On failure, shows relevant
error lines and preserves the log for inspection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Author

@roofpig95008 roofpig95008 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean these up before submitting PR

@roofpig95008 roofpig95008 marked this pull request as ready for review February 8, 2026 06:24
@debugmcpdev debugmcpdev merged commit abeaf44 into debugmcp:main Feb 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants