Skip to main content
Glama

Orca — ATK Accessibility MCP Server

Captures the ATK (Accessibility Toolkit) widget tree from running GTK applications on Linux, normalizes it to ARIA roles/types, applies a configurable declarative security policy, and exposes the result as MCP tools to any standard MCP client (Claude, Cursor, Windsurf, etc.).

Quick Start

cd orca
just shell        # enter nix-shell with all dependencies
just server       # start the MCP server on stdio

Or manually:

nix-shell
PYTHONPATH=src python3 -m src

Related MCP server: blade-computer-use

Architecture

orca/
├── shell.nix                 # nix-shell environment
├── pyproject.toml            # package config
├── Justfile                  # task runner
├── docs/
│   ├── README.md             # this file
│   ├── usage.md              # client integration guide
│   ├── policy.md             # policy engine reference
│   ├── atk.md                # ATK capture internals
│   └── contribute.md         # development guide
└── src/
    ├── __init__.py
    ├── __main__.py           # entry point
    ├── atk.py                # ATK tree capture
    ├── normalize.py          # ATK→ARIA normalization
    ├── policy.py             # declarative security policy
    ├── server.py             # MCP server
    └── default_policy.yaml   # ship-default policy

MCP Tools

Tool

Params

Description

get_tree

none

Full ARIA-normalized tree, policy-filtered

get_tree_for_app

app_name: str

Tree scoped to an app (fnmatch glob)

get_node_info

node_id: str

Single node lookup by obj_id

list_apps

none

Top-level app objects (name, pid, role)

Configuration

Policy

Policy files are loaded in this priority:

  1. ~/.config/atk-mcp/policy.yaml (user override)

  2. src/default_policy.yaml (bundled default)

If neither exists or either fails to parse, the server starts with default_action: allow and no user rules.

Policy is loaded once at startup — restart the server to pick up changes.

See docs/policy.md for the full schema and examples.

Nix Environment

All dependencies are managed via shell.nix. No uv, no virtualenv. Key packages:

  • python314 — runtime

  • python314Packages.pyatspi — ATK tree access

  • python314Packages.pygobject3 — GI introspection

  • python314Packages.mcp — MCP SDK v2

  • python314Packages.pydantic-settings — policy config

  • python314Packages.pyyaml — policy parsing

  • at-spi2-core, at-spi2-atk, atk, gtk3 — runtime libs

Usage

With Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "atk-accessibility": {
      "command": "nix-shell",
      "args": ["--run", "python -m src"],
      "cwd": "/path/to/orca"
    }
  }
}

With Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "atk-accessibility": {
      "command": "nix-shell",
      "args": ["--run", "python -m src"],
      "cwd": "/path/to/orca"
    }
  }
}

With Windsurf

Add to .mcp.json in your project:

{
  "mcpServers": {
    "atk-accessibility": {
      "command": "nix-shell",
      "args": ["--run", "python -m src"],
      "cwd": "/path/to/orca"
    }
  }
}

From the command line (interactive test)

just shell
python -m src    # runs indefinitely on stdio

Pipe a raw MCP request to test individual tools:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
  | python -m src

Policy Engine

See docs/policy.md for the full reference.

Quick example — deny all heading nodes and redact textbox names:

default_action: allow
built_in_deny:
  aria_roles:
    - "password"
  state_keywords:
    - "hidden"
    - "invisible"
rules:
  - id: deny-headings
    conditions:
      role: "heading"
    action: deny
  - id: redact-forms
    conditions:
      role: "textbox"
    action: redact
    redact_fields:
      - "name"
      - "description"

ATK Capture

See docs/atk.md for internals. Key points:

  • Walks gi.repository.Atspi desktop root recursively

  • Fail-closed: subprocess isolation prevents GLib abort from crashing the server when no AT-SPI bus is available

  • Each node captures: obj_id, role (int), role_name, name, description, state_set, attributes, child_count, index_in_parent, app_name, pid

Normalization

See docs/normalize.md for the role map.

ATK integer roles (0–132) are mapped to ARIA role strings. Unmapped roles pass through as their role_name string. State names are translated (e.g. FOCUSEDfocused, CHECKEDchecked).

Development

See docs/contribute.md for the development guide.

just shell        # enter dev environment
just test         # run verification suite
just compile      # syntax check
just lint         # import + smoke check
just server       # start server for manual testing

Limitations

  • Wayland apps without AT-SPI: Some Wayland-native GTK apps don't expose AT-SPI interfaces. get_tree_for_app returns [] for those apps. Expected, not a bug.

  • No hot-reload: Policy is loaded once at startup.

  • Requires AT-SPI bus: Without a running accessibility bus (e.g. at-spi-bus-launcher), the ATK module returns [] gracefully.

  • Python 3.14+: No typing-extensions dependency.

License

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables MCP clients to control macOS via accessibility and screen recording, providing tools to list apps, observe UI, click, type, press keys, and scroll.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP clients to control a Linux/X11 desktop like a human: see the screen, move the mouse, click UI elements via the accessibility tree, type text, and manage windows.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Browser automation MCP server that uses a real browser to give agents eyes and hands—open pages, click, fill, screenshot, and run scripts via accessibility-tree snapshots.
    22
    398
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sachin-sankar/orca'

If you have feedback or need assistance with the MCP directory API, please join our Discord server