orca
Enables standard MCP clients to inspect and query GTK application accessibility trees through ARIA-normalized, policy-filtered MCP tools.
README
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
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:
~/.config/atk-mcp/policy.yaml(user override)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— runtimepython314Packages.pyatspi— ATK tree accesspython314Packages.pygobject3— GI introspectionpython314Packages.mcp— MCP SDK v2python314Packages.pydantic-settings— policy configpython314Packages.pyyaml— policy parsingat-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.Atspidesktop 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. FOCUSED → focused, CHECKED → checked).
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_appreturns[]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-extensionsdependency.
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.