feat(bridge-macos): Phase 0e1' scaffold + stdio JSON-RPC (macOS sidecar foundation) - #16
Merged
Merged
Conversation
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>
This was referenced May 11, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
DesktopCaptureBackendcontract 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— methodrouting (mirrors the C#
RpcDispatcher)scripts/smoke-test.sh— shell harness driving the binaryvia stdin; grep-based shape assertions (no jq dependency)
README.md— build + protocol + AXAPI permission docsMethods in this phase
ping—{ pong, version, arch, processId }capabilities— supported methods + AXAPI provider info.gitignoreadditionsSwift Package Manager output:
.build/,.swiftpm/,Packages/Validation
Built natively on Apple Silicon arm64. Smoke test runs in <2s:
Protocol compatibility
Byte-identical envelope to the Windows bridge:
-32700parse,-32601method-not-found,bridge-specific codes starting
-32010+)diagnostics)
The Node-side
MacosAxapiBackend(Phase 0f') will be a near-exactmirror of
WindowsUiaBackend, differing only in default search pathsfor the binary (looking for
.build/release/agentmark-bridge-macosrather than
bin/Release/.../agentmark-bridge-windows.exe).Accessibility permission caveat
macOS guards AXAPI behind System Settings → Privacy & Security →
Accessibility. When
capture/executeland in 0e2'/0e3', theparent process (Claude Desktop, AgentMark MCP server, terminal during
dev) must be granted permission. Without it, the bridge will surface
a clear
accessibilityNotGrantedJSON-RPC error (code -32020).Next PRs
list_windows+capturevia AXAPI (mirror ofPR feat(bridge-windows): Phase 0e2 + 0e3 — list_windows, capture, execute (real UIA driving real Windows) #13's Windows work; uses
NSWorkspace.runningApplicationsAXUIElementCopyAttributeValuefor window enumeration; recursivetree walking via
kAXChildrenAttribute; role mappingAXButton/AXTextField/AXStaticText/etc. →normalised
DesktopRolevocab)executevia AXAPI (AXPress,AXSetValue,AXSetAttributeValuefor the various action types)MacosAxapiBackend(mirror ofWindowsUiaBackendfrom PR feat(desktop): WindowsUiaBackend — Node-side bridge client (Phase 0f) #14)🤖 Generated with Claude Code