Add MCP headless API for the JavaSE port#5377
Conversation
Expose the running simulator / a Codename One desktop tool to an LLM agent over the Model Context Protocol. Built on the accessibility semantics tree: the same immutable tree that describes the screen to VoiceOver/TalkBack drives it for an agent, so any UI is drivable with zero code. Scope: the JavaSE port (simulator + tooling) only. Packaged desktop app / jar / cloud desktop builds are out of scope, so there is no launcher-arg plumbing and no cn1:mcp-setup goal. - Core engine com.codename1.mcp: MCP facade, MCPServer (JSON-RPC 2.0), MCPTransport + SocketTransport, McpUiTools built-in tools (ui_snapshot, ui_perform_action, ui_activate, ui_set_text, ui_find), screenshot resource, MCPClientRegistrar/MCPClientDescriptor for host detection/registration. Developer tools reuse com.codename1.ai.Tool. Enablement is API-invocation only. - ParparVM-safe core: no System.in/setOut/getenv or BufferedReader (missing on the iOS/Catalyst runtime). The stdio transport lives in the JavaSE port (MCPStdioTransport) behind a factory registered by JavaSEPort.init. - Simulator gains a Tools > Model Context Protocol menu (socket attach + detect hosts) in both window modes. - Unit + MCP-spec conformance tests (MCPServerTest), an MCP Inspector E2E harness (scripts/mcp*), and a developer guide chapter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c8397b1 to
37b2f4f
Compare
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ore build) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cloudflare Preview
|
|
Compared 12 screenshots: 12 matched. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
…ninit field) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Compared 145 screenshots: 145 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
…s/imports, preserve stack trace) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 168 screenshots: 168 matched. |
|
Compared 143 screenshots: 143 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 216 screenshots: 216 matched. |
|
Compared 139 screenshots: 139 matched. |
|
Compared 138 screenshots: 138 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 144 screenshots: 144 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
…ools
Every desktop Codename One tool (the simulator, Codename One Settings, and any
other CN1-app tool) now gets a native "MCP" pull-down menu, added by the JavaSE
port with no per-tool code:
- Expose This Tool To Agents - start/stop the loopback MCP server
- Install in MCP Hosts - register the tool with detected hosts
(Claude Desktop, Claude Code, ...)
- Remove From MCP Hosts - unregister
- Detect MCP Hosts - list installed hosts + config paths
- Debug Logging - OFF / Errors / Summary / Full
Install registers MCPStdioLauncher, a stdio<->socket bridge, so a stdio host
such as Claude Desktop can drive the already-running, human-visible tool.
Debug logging (MCPVerbosity OFF/ERRORS/SUMMARY/FULL) echoes the MCP conversation
to the Codename One log so a user can watch and debug what an agent is doing.
- Core: MCPVerbosity, MCPServer.setVerbosity + per-level logging, MCP facade.
- JavaSE port: MCPDesktopMenu (the native menu), MCPStdioLauncher (the bridge),
wired into buildNativeMenuBar (all desktop tools) and the simulator menu bar.
- Developer guide: documents the menu, install/uninstall and debug logging.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ild) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tall) MCPClientRegistrar round-tripped the whole host config (e.g. Claude Desktop's claude_desktop_config.json) through the default JSONParser, which turns JSON booleans into "true"/"false" strings, integers into X.0 floats, and drops null values. That corrupted the user's other settings in the config, which could make the host reset its config and drop existing mcpServers entries. Read with a JSONParser instance configured for useBoolean + useLongs + includeNulls, and write with mapToJson (which preserves nulls) instead of toJson. Editing a host config now leaves every other setting byte-faithful. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves the six review findings:
1/4 Socket transport moved from core to the JavaSE port
(MCPSocketTransport). It binds java.net.ServerSocket to the loopback
address only (the portable com.codename1.io.Socket bound the wildcard
address, exposing the control channel on every interface) and owns the
listening and accepted sockets so stop() closes them and unblocks a
pending accept()/read(). A fresh instance is created per run; the core
SocketTransport and MCPLineReader are deleted. MCP exposes a
SocketTransportFactory the port registers in init().
2/5 MCPServer parses requests and re-serializes tool arguments through the
new MCPJson helper, preserving booleans, integers (as longs) and nulls
instead of turning them into strings/floats/dropped keys. initialize
only echoes a protocolVersion the server actually implements.
3/6 MCPClientRegistrar refuses to overwrite a host config it could not
read or that is not a complete JSON object (structural check, since
CN1's parser returns a partial map rather than throwing), and writes
through a temp file renamed into place so an interrupted write cannot
truncate the config. Detection no longer treats the home directory as a
present "parent" (a dotfile such as ~/.claude.json is only detected when
the file itself exists), removing the false-positive Claude Code match.
Adds tests for protocol negotiation, faithful argument types and the
config completeness guard. PMD and SpotBugs clean; 17 mcp tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Expose the running simulator — or a Codename One desktop tool — to an LLM agent (Claude Desktop/Code, Codex, opencode, ...) over the Model Context Protocol. The agent can read the current screen, drive the UI, and call tools the app publishes.
Built on the accessibility semantics tree (now on master): the same immutable tree that describes the screen to VoiceOver/TalkBack drives it for an agent, so any UI is drivable with zero code.
Scope: the JavaSE port (simulator + tooling) only. Packaged desktop app / executable jar / cloud desktop builds are out of scope — there is no launcher-arg plumbing and no
cn1:mcp-setupgoal.What's included
com.codename1.mcp—MCPfacade,MCPServer(JSON-RPC 2.0: initialize/tools/resources/ping),MCPTransport+SocketTransport,McpUiToolsbuilt-in tools (ui_snapshot,ui_perform_action,ui_activate,ui_set_text,ui_find) over the accessibility snapshot, a PNG screenshot resource, andMCPClientRegistrar/MCPClientDescriptorfor host detection/registration. Developer tools reusecom.codename1.ai.Tool. Enablement is API-invocation only (no build hints).System.in/setOut/getenvand noBufferedReader, so the stdio transport lives in the JavaSE port (MCPStdioTransport, registered via a factory inJavaSEPort.init); core uses onlySystem.getProperty+ a hand-rolled line reader.Testing
MCPServerTest— 13 tests: capabilities handshake, protocol-version negotiation, JSON-RPC error codes, notifications, tools list/call/isError, and real UI driving (snapshot reads a live form, set-text mutates a field, activate fires a button listener, find-by-label).scripts/mcp-inspector-e2e.sh+scripts/mcp/McpStdioDemo.java) —tools/list,ui_snapshot, andui_set_textverified against the reference@modelcontextprotocol/inspectorclient.🤖 Generated with Claude Code