Skip to content

feat(bridge-macos): Phase 0e1' scaffold + stdio JSON-RPC (macOS sidecar foundation) - #16

Merged
rrader26 merged 1 commit into
mainfrom
feat/bridge-macos-scaffold
May 11, 2026
Merged

feat(bridge-macos): Phase 0e1' scaffold + stdio JSON-RPC (macOS sidecar foundation)#16
rrader26 merged 1 commit into
mainfrom
feat/bridge-macos-scaffold

Conversation

@rrader26

Copy link
Copy Markdown
Contributor

Summary

Independent of the Windows PR stack. Adds the macOS-side sidecar
process for AgentMark Desktop — same architecture as the Windows
bridge (PR #13), same JSON-RPC protocol, same DesktopCaptureBackend
contract on the Node side. Uses Apple's Accessibility framework
(AXAPI) as the capture/execute substrate.

Why this matters strategically: once macOS bridge work completes
(0e2' + 0e3' + 0f'), you can demo AgentMark Desktop driving real
macOS apps (Pages, Excel-for-Mac, Numbers, native enterprise apps)
from Claude Desktop on your development machine — no Windows VM
dependency for the demo. Closes the cross-platform story and unblocks
local end-to-end validation while the Windows-side debugging
resolves separately.

What's in this PR

Bridge scaffold (apps/agent-runner/bridges/macos/)

  • Package.swift — SPM manifest, macOS 13+ deployment target
    (recent enough for everything AXAPI we'll need)
  • Sources/AgentMarkBridgeMacos/main.swift — entry point;
    stdin read loop with UTF-8 + BOM stripping (same defensive fix as
    the Windows bridge); dispatch + JSON-RPC envelope encoding
  • Sources/AgentMarkBridgeMacos/JsonRpc.swift — request /
    response types; flexible id handling (number / string / null);
    error code catalog (same numeric codes as the Windows bridge)
  • Sources/AgentMarkBridgeMacos/Dispatcher.swift — method
    routing (mirrors the C# RpcDispatcher)
  • scripts/smoke-test.sh — shell harness driving the binary
    via stdin; grep-based shape assertions (no jq dependency)
  • README.md — build + protocol + AXAPI permission docs

Methods in this phase

  • ping{ pong, version, arch, processId }
  • capabilities — supported methods + AXAPI provider info

.gitignore additions

Swift Package Manager output: .build/, .swiftpm/, Packages/

Validation

Built natively on Apple Silicon arm64. Smoke test runs in <2s:

Smoke testing .../.build/debug/agentmark-bridge-macos
  -> {"jsonrpc":"2.0","id":1,"result":{"version":"0.4.0","arch":"arm64","pong":true,"processId":88141}}
  -> {"jsonrpc":"2.0","id":2,"result":{"bridge":"agentmark-bridge-macos","version":"0.4.0","axapiProvider":"Accessibility (AXAPI)","methods":["ping","capabilities"],"platform":"macos"}}

SMOKE TEST PASSED

Protocol compatibility

Byte-identical envelope to the Windows bridge:

  • Same JSON-RPC 2.0 framing (one message per line)
  • Same error code numbering (-32700 parse, -32601 method-not-found,
    bridge-specific codes starting -32010+)
  • Same UTF-8 BOM stripping on stdin reads
  • Same stdout/stderr discipline (stdout = framed JSON only, stderr =
    diagnostics)

The Node-side MacosAxapiBackend (Phase 0f') will be a near-exact
mirror of WindowsUiaBackend, differing only in default search paths
for the binary (looking for .build/release/agentmark-bridge-macos
rather than bin/Release/.../agentmark-bridge-windows.exe).

Accessibility permission caveat

macOS guards AXAPI behind System Settings → Privacy & Security →
Accessibility. When capture / execute land in 0e2'/0e3', the
parent process (Claude Desktop, AgentMark MCP server, terminal during
dev) must be granted permission. Without it, the bridge will surface
a clear accessibilityNotGranted JSON-RPC error (code -32020).

Next PRs

  1. Phase 0e2'list_windows + capture via AXAPI (mirror of
    PR feat(bridge-windows): Phase 0e2 + 0e3 — list_windows, capture, execute (real UIA driving real Windows) #13's Windows work; uses NSWorkspace.runningApplications
    • AXUIElementCopyAttributeValue for window enumeration; recursive
      tree walking via kAXChildrenAttribute; role mapping
      AXButton/AXTextField/AXStaticText/etc. →
      normalised DesktopRole vocab)
  2. Phase 0e3'execute via AXAPI (AXPress, AXSetValue,
    AXSetAttributeValue for the various action types)
  3. Phase 0f' — Node-side MacosAxapiBackend (mirror of
    WindowsUiaBackend from PR feat(desktop): WindowsUiaBackend — Node-side bridge client (Phase 0f) #14)

🤖 Generated with Claude Code

Adds the macOS-side sidecar process for AgentMark Desktop, mirroring
the Windows bridge architecture exactly. Same stdio JSON-RPC 2.0
protocol; same DesktopCaptureBackend contract on the Node side. Uses
Apple's Accessibility framework (AXAPI) as the capture / execute
substrate when Phase 0e2'/0e3' land.

This first commit ships the protocol substrate and two no-AXAPI
methods so we can validate the cross-language pipeline before adding
the AXAPI walking + action dispatch logic:

  - ping         -> { pong, version, arch, processId }
  - capabilities -> supported methods + AXAPI provider info

Built natively on Apple Silicon (arm64). Smoke test runs locally on
the developer Mac in seconds.

Layout (apps/agent-runner/bridges/macos/):

  Package.swift                            -- SPM manifest (macOS 13+)
  Sources/AgentMarkBridgeMacos/
    main.swift                             -- entry + stdin read loop +
                                              BOM stripping + dispatch
    JsonRpc.swift                          -- request/response types +
                                              JSON-RPC 2.0 envelope
                                              encoder/decoder + error
                                              code catalog
    Dispatcher.swift                       -- method routing (mirrors
                                              the C# bridge's
                                              RpcDispatcher class)
  scripts/smoke-test.sh                    -- shell harness driving the
                                              binary via stdin; grep-
                                              based assertions, no jq
                                              dependency
  README.md                                -- build + protocol docs

The protocol -- request envelope, error codes (parseError -32700 ..
internalError -32603 plus bridge-specific 32010+), stderr discipline,
BOM stripping -- is byte-identical to the Windows bridge. This is
deliberate: the Node-side `MacosAxapiBackend` (Phase 0f') will be a
near-exact mirror of `WindowsUiaBackend`, sharing 90% of the code
through the abstract DesktopCaptureBackend interface.

.gitignore extended for Swift Package Manager output (.build/,
.swiftpm/, Packages/) alongside the existing .NET ignores.

Why now: Windows-side debugging (Claude Desktop MCP config) is blocked
on the user; macOS work unblocks local end-to-end validation while
that resolves. After Phase 0e2'/0e3' and Phase 0f' ship, the user can
demo AgentMark Desktop driving Pages / Excel-for-Mac / Numbers from
Claude Desktop on their development machine -- no Windows VM
dependency for the demo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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