KeyboardExtAX

io.github.Nikitosina由 GitHub 帳號 Nikitosina 發布v0.1.2更新於 Oct 24, 2026

Accessibility snapshots and tap coordinates for active third-party iOS keyboards in Simulator.

已驗證STDIO僅桌面瀏覽器自動化開發者工具

概覽

AI 產生的概覽

唯讀的 MCP 伺服器,為 iOS 模擬器中執行中的第三方 iOS 鍵盤擴充功能回傳無障礙快照與點擊座標。

可以做什麼
依模擬器 ID 與擴充功能 Bundle 識別碼,對模擬器中執行中的第三方鍵盤擴充功能做唯讀無障礙快照,回傳按鍵與控制項的扁平 JSON 清單,含位置框、中心點與取整後的點擊座標。可選擇回傳原始巢狀無障礙樹與 XCTest 診斷資訊。依模擬器重複使用常駐 XCTest 執行器,讓重複快照保持快速,並提供 client_refocus_required、extension_not_active 等穩定錯誤碼。
適用情境
適合在模擬器中自動化或測試自訂 iOS 鍵盤,尤其是一般 UI 自動化只會把鍵盤視為單一不透明元素的情況。需搭配獨立的點擊工具,在回傳的座標上執行手勢。
執行需求
macOS 主機,安裝 Xcode 26.5 與目標 iOS 模擬器執行環境,Python 3.10 或更新版本;鍵盤 App 與擴充功能已安裝並在模擬器設定中啟用,前景用戶端 App 有聚焦的文字欄位。以 stdio 在本機執行,例如透過 uvx。DEVELOPER_DIR 可選填指定 Xcode 安裝位置,KEYBOARD_EXT_AX_CACHE_DIR 可選填設定快取目錄。
安裝前請注意
僅唯讀:不會點擊、輸入、啟動 App、啟用鍵盤,也不存取實體裝置。它會在本機建置並執行 XCTest 測試框架與執行器程序;解析依賴未公開的 XCTest 文字格式,未測試的 Xcode 版本不保證相容。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 KeyboardExtAX,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

KeyboardExtAX

[KeyboardExtAX accessibility snapshot illustration]

Fast, read-only accessibility snapshots of active third-party iOS keyboard extensions in Simulator.

Why this project exists

A custom iOS keyboard runs in a separate app-extension process. When a client app presents that keyboard, ordinary UI automation usually sees the client application's accessibility tree but not the keyboard's useful descendants. The entire keyboard may appear as one opaque element.

That creates a practical automation gap:

  • screenshots can show the keyboard, but extracting reliable tap coordinates from pixels is slow and brittle;
  • the client application's accessibility snapshot does not necessarily expose the extension's keys and controls;
  • starting a new XCTest session for every query is expensive and can disturb keyboard focus;
  • XCTest element handles become stale whenever the keyboard changes layout;
  • automation agents should not need to manage test plans, ports, build products, or runner processes.

KeyboardExtAX fills that gap. It attaches XCTest directly to the already-running keyboard extension by bundle identifier, parses its accessibility hierarchy, and returns plain JSON with absolute logical coordinates. A persistent runner keeps warm snapshots fast, while a small controller owns building, caching, ports, and per-simulator lifecycle.

KeyboardExtAX observes only. Use a separate automation tool, such as XcodeBuildMCP, to launch apps, focus text fields, and perform gestures with the returned coordinates.

Quick start: MCP

Configure keyboard-ext-ax-mcp as a stdio MCP server. Most MCP clients use a configuration shaped like this:

json
{  "mcpServers": {    "KeyboardExtAX": {      "command": "keyboard-ext-ax-mcp",      "env": {        "DEVELOPER_DIR": "/Applications/Xcode.app/Contents/Developer"      }    }  }}

If the MCP client does not inherit your shell PATH, replace the command with the absolute path printed by command -v keyboard-ext-ax-mcp.

The server exposes one tool:

text
keyboard_snapshot(  simulator_id: "<SIMULATOR_UDID>",  extension_bundle_id: "com.example.keyboard.extension",  raw: false)

Example input:

json
{  "simulator_id": "2D78332B-A3C3-4CEE-962B-99EF531FD201",  "extension_bundle_id": "com.example.keyboard.extension"}

The result is returned as structured MCP content. The MCP layer delegates directly to the same controller used by the CLI, so build caching, sessions, errors, and output are identical.

Quick start: CLI

With the client text field focused and the requested keyboard visible:

sh
keyboard-ext-ax snapshot \  --simulator <SIMULATOR_UDID> \  --extension com.example.keyboard.extension

Add --output /tmp/keyboard.json to write the result to a file. Add --raw for the nested tree and XCTest diagnostics.

Scope and limitations

KeyboardExtAX currently supports:

  • macOS hosts;
  • iOS Simulator;
  • third-party keyboard extensions;
  • Xcode 26.5;
  • read-only accessibility snapshots.

It does not:

  • tap, swipe, or type;
  • launch or foreground the client app;
  • select or enable a keyboard for the user;
  • access physical iOS devices;
  • guarantee compatibility with widgets, Live Activities, or other extension types;
  • guarantee parser compatibility with untested Xcode versions.

The parser reads XCUIApplication.debugDescription. Its text format is not a documented compatibility contract, so each Xcode version must be validated before support is claimed.

Requirements

  • macOS
  • Xcode 26.5 with the desired iOS Simulator runtime installed
  • Python 3.10 or newer
  • A keyboard app and extension already installed in the target simulator
  • The keyboard enabled in Settings → General → Keyboard → Keyboards
  • A foreground client app with a focused text field

If multiple Xcode installations are present, select one with DEVELOPER_DIR or --developer-dir:

sh
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

Installation

Homebrew (recommended)

sh
brew install nikitosina/tap/keyboard-ext-ax

PyPI with uv

Install both executables permanently:

sh
uv tool install keyboard-ext-ax

Or run the MCP server without a persistent installation:

sh
uvx keyboard-ext-ax mcp

From source

sh
git clone https://github.com/Nikitosina/KeyboardExtAX.gitcd KeyboardExtAXpython3 -m venv .venv.venv/bin/python -m pip install -e .source .venv/bin/activate

Every installation provides keyboard-ext-ax and keyboard-ext-ax-mcp. The MCP server can be started with either keyboard-ext-ax-mcp or keyboard-ext-ax mcp.

The bundled Xcode project is ready to use. XcodeGen is needed only when modifying keyboard_ext_ax/harness/project.yml.

Output

The default response is a compact, flat array:

json
{  "ok": true,  "snapshot_id": "9543E2AA-C4D9-4281-9645-7792F7953FE3",  "simulator_udid": "2D78332B-A3C3-4CEE-962B-99EF531FD201",  "extension_bundle_id": "com.example.keyboard.extension",  "pid": 12345,  "elapsed_ms": 103.4,  "round_trip_ms": 106.1,  "session_reused": true,  "total_ms": 171.8,  "elements": [    {      "ref": "0.0.3",      "type": "Key",      "identifier": "space",      "label": "Space",      "frame": {        "x": 112,        "y": 746,        "width": 178,        "height": 44      },      "center": {        "x": 201,        "y": 768      },      "tap_x": 201,      "tap_y": 768    }  ]}

Element fields

FieldMeaning
refStable path within this snapshot only. Refresh it after layout changes.
typeXCTest accessibility element type.
identifierAccessibility identifier, when provided by the extension.
labelAccessibility label, when provided by the extension.
frameAbsolute logical frame in Simulator coordinates.
centerExact floating-point frame center.
tap_x, tap_yRounded integer center, ready for a gesture tool.

Coordinates are Simulator logical coordinates, not screenshot pixels. Do not rescale them before passing them to XcodeBuildMCP for the same simulator.

Session management

sh
keyboard-ext-ax statuskeyboard-ext-ax status --simulator <SIMULATOR_UDID>keyboard-ext-ax stop --simulator <SIMULATOR_UDID>keyboard-ext-ax stop --all

One runner is maintained per simulator. Multiple simulators can be queried concurrently. If a reused runner loses the extension process, KeyboardExtAX recycles it once and returns client_refocus_required.

Errors

Errors are JSON objects with stable codes.

CodeMeaningRecovery
client_refocus_requiredA new or restarted runner is ready.Refocus the client text field and repeat the request.
extension_not_activeXCTest could not attach after three attempts.Confirm that the requested extension—not the system keyboard—is visible, then retry.
runner_start_failedThe persistent XCTest runner did not become ready.Inspect the returned log and log_tail.
build_failedThe XCTest harness failed to build.Inspect the returned build log and verify the selected Xcode.
xcode_unavailableXcode could not be located or queried.Set DEVELOPER_DIR or pass --developer-dir.
extension_bundle_id_missingThe runner received no extension identifier.Supply extension_bundle_id.
snapshot_failedXCTest raised an unexpected snapshot error.Retry with raw: true and inspect diagnostics.

The CLI exits with:

  • 0 for success;
  • 2 for a normal snapshot-state error such as inactive extension;
  • 1 for lifecycle, build, or controller failures.

Architecture

text
MCP client / CLI        │        ▼KeyboardExtAXController  ├─ build cache  ├─ per-simulator lock and state  ├─ free-port allocation  └─ XCTest runner lifecycle        │  JSON over loopback TCP        ▼PersistentKeyboardExtAXTests        │  XCUIApplication(bundleIdentifier:)        ▼Active keyboard extension process        │        ▼Parsed tree → compact elements → MCP/CLI JSON

The host app included in this repository is XCTest scaffolding. Snapshot mode does not launch it and does not replace the consumer's foreground client app.

License

KeyboardExtAX is available under the MIT License.

來源:README.md,提交 347b854

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

2
  1. v0.1.2最新Sep 23, 2026
  2. v0.1.1Sep 18, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分