Skip to content

feat: add MCP server for Claude Code integration#17

Open
tosh7 wants to merge 5 commits intomainfrom
feature/mcp-server
Open

feat: add MCP server for Claude Code integration#17
tosh7 wants to merge 5 commits intomainfrom
feature/mcp-server

Conversation

@tosh7
Copy link
Copy Markdown
Owner

@tosh7 tosh7 commented Mar 24, 2026

Summary

  • Add pure Rust MCP (Model Context Protocol) server, enabling Claude Code to directly operate iOS Simulators via era mcp
  • 8 MCP tools: ios_session_connect, ios_list_devices, ios_snapshot, ios_tap, ios_fill, ios_swipe, ios_screenshot, ios_assert
  • JSON-RPC 2.0 over stdio transport — no Node.js dependency required

Changes

New src/mcp/ module (+1,359 lines)

  • protocol.rs: JSON-RPC 2.0 + MCP type definitions (request/response/content/error)
  • tools.rs: 8 tool schema definitions with JSON Schema input validation (6 tests)
  • handlers.rs: Tool handlers that directly call existing simulator/ module functions
  • transport.rs: stdin/stdout JSON-RPC loop with MCP protocol handling (8 tests)

Tool highlights

  • ios_snapshot returns Playwright-style ref-numbered UI tree (token-efficient, no screenshots needed)
  • ios_tap supports 4 selector modes: ref / text / type+index / coordinates
  • ios_swipe adds direction shortcuts (up/down/left/right)
  • ios_screenshot returns base64 PNG via MCP image content type
  • ios_assert checks visible/not_visible text arrays

Configuration

{
  "mcpServers": {
    "era": {
      "command": "era",
      "args": ["mcp"]
    }
  }
}

Dependencies

  • Added base64 = "0.22" (screenshot encoding only)

Test plan

  • All 210 tests pass (105 lib + 18 coordinate + 58 regression + 12 retry + 17 scale)
  • JSON-RPC protocol serialization/deserialization tests
  • MCP initialize/ping/tools-list/tools-call handling tests
  • Tool schema validation tests (count, uniqueness, required fields)
  • Unknown tool/method error handling tests

tosh7 added 5 commits March 24, 2026 17:53
- Add --text option: find element by AXLabel/AXValue (case-insensitive
  partial match) via live UI tree query
- Add --type/--index options: find element by type with optional 0-based
  index among matches
- Both tap and fill now support 4 target modes: -x/-y, --ref, --text,
  --type (mutually exclusive via clap conflicts)
- Fill --target for text-based element search, --type/--index for type
- Add find_by_text() and find_by_type_index() to snapshot module
- resolve_live_element() helper queries idb describe-all on the fly
Add era session connect/list/disconnect/disconnect-all commands.
Sessions store UDID, device name, and auto-detected scale factor
in ~/.era/sessions.json. Existing commands (tap, snapshot, fill,
swipe, tap-region) gain --session option as alternative to --device.
When neither is specified, the default session is used.
…tor-session

# Conflicts:
#	src/cli/mod.rs
#	tests/regression.rs
Add `era mcp` command that starts a JSON-RPC stdio server implementing
the Model Context Protocol. Exposes 8 tools for iOS Simulator automation:

- ios_session_connect: connect to simulator with auto-scale detection
- ios_list_devices: list available simulators
- ios_snapshot: ref-numbered UI tree (Playwright-style)
- ios_tap: tap by ref, text, type, or coordinates
- ios_fill: focus text field and input text
- ios_swipe: swipe by direction shortcut or coordinates
- ios_screenshot: capture as base64 or file
- ios_assert: verify UI state (visible/not_visible text checks)

Architecture:
- src/mcp/protocol.rs: JSON-RPC 2.0 + MCP type definitions
- src/mcp/tools.rs: tool schema definitions (8 tools)
- src/mcp/handlers.rs: tool dispatch to existing simulator operations
- src/mcp/transport.rs: stdio read/write loop with lifecycle handling

All existing simulator/ modules reused without modification.
210 tests passing (105 unit + 105 integration).
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.

1 participant