# AndroidViewClient compares view trees, not screenshots

> AndroidViewClient, also called culebra, is an Apache-2.0 pure Python client for the Android ViewServer and ADB that drives a device through the UI Automator hierarchy instead of pixel comparison. Version 25.0.1 adds an MCP server so an AI assistant can drive the device, and the packaging has a few inconsistencies worth reading before you pin it.

**dtmilano/AndroidViewClient** — Android ViewServer and ADB client

- Repository: https://github.com/dtmilano/AndroidViewClient
- Stars: 1,724 · Forks: 341
- Language: Python
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/dtmilano-androidviewclient

## Interaction is by view, not by coordinate

The design decision that separates this from a screenshot based tool is stated in the feature list: it uses logical screen comparison, based on the UI Automator Hierarchy, instead of image comparison, to avoid extraneous detail issues like time or data changes.

That difference shows up in ordinary use. A test that asserts a clock is present can assert that the view exists, rather than asserting that the pixels in a region look a certain way. A test that taps Submit can find the view by text or by resource id and tap its centre, rather than tapping a fixed x and y that a different screen density invalidates.

The package description in `setup.py` says the same thing in its own words: a 100% pure python library that simplifies test script creation, provides higher level operations, and can obtain the tree of Views present at any given moment on the device or emulator screen.

The rest of the feature list is broader than that. It automates navigation, generates reusable scripts, supports concurrent operation on multiple devices, provides straightforward control for high-level operations such as language change and activity start, and claims full support for all Android APIs.

The history is worth one sentence, because it explains the shape. It began as an extension to monkeyrunner and evolved into a versatile pure Python tool. The repository topics still list `monkeyrunner` and `culebra` alongside `automation`, `testing` and `ui`.

## One pip command, three installed scripts

Installation is a single command:

```bash
pip3 install androidviewclient --upgrade
```

The README points at the wiki for more alternatives. The distribution name is `androidviewclient`, and the version in `setup.py` is `25.0.1`, which matches the release tag v25.0.1 from 2026-09-21 and the last push on 2026-09-21. Earlier in the tag history, v25.0.0 shipped twice on 2025-12-23, once for the repository and once tagged for PyPI, which is worth knowing if you ever see both tags in a changelog.

`setup.py` declares three things under `scripts`: `tools/culebra`, `tools/dump` and `tools/culebra-mcp`. `setup.py` lists those three files under `scripts`, so they are installed as package scripts.

The runtime dependencies are `setuptools`, `requests`, `numpy`, `matplotlib` and `culebratester-client >= 2.0.73`. That last one means CulebraTester2 is a client-side dependency of the Python package, which is a preview of the architecture in the next section.

Declared support is `python_requires='>=3.9'`, with classifiers for 3.9 through 3.12.

## The MCP server drives the device from an AI assistant

Version 25 is where the project changed shape. The README marks it as new: AndroidViewClient now includes a Model Context Protocol server that enables AI assistants such as Claude Code and Kiro to interact with Android devices through natural language.

The architecture is two processes. On the device you run CulebraTester2, which is a separate repository with its own run instructions, and the MCP server talks to it over HTTP. The base URL comes from an environment variable:

```bash
claude mcp add culebratester2 --env CULEBRATESTER2_URL=http://localhost:9987 -- culebra-mcp
```

The same server can live in a project file so a team shares one configuration, in `.mcp.json` at the repository root:

```json
{
  "mcpServers": {
    "culebratester2": {
      "command": "culebra-mcp",
      "env": {
        "CULEBRATESTER2_URL": "http://localhost:9987"
      }
    }
  }
}
```

Kiro uses the same entry in `.kiro/settings/mcp.json` or `~/.kiro/settings/mcp.json`.

Three environment variables control it: `CULEBRATESTER2_URL`, defaulting to `http://localhost:9987`, `CULEBRATESTER2_TIMEOUT` in seconds, defaulting to 30, and `CULEBRATESTER2_DEBUG` accepting `1`, `true` or `yes`.

The server exposes 20 tools in three groups. Element based interactions find elements by text or resource id, click, long click, enter text, clear text, navigate with back and home, and launch applications. Coordinate based interactions click and long click at coordinates and perform swipe gestures. Device actions wake and sleep the device, get the current app, force stop apps and take screenshots.

Tool pre-approval differs between the two clients, which is the security setting to read before pointing an assistant at a real device: Claude Code uses `permissions.allow` in `.claude/settings.json`, while Kiro uses `autoApprove` in the server entry.

## A Kotlin backend is where the project is heading, and it is not in this repository

The README flags that a new Kotlin backend is under development to provide more functionality and improve performance, pointing at CulebraTester2 and the 20.x.y series prereleases.

So the direction of travel is a rewrite of the device side in Kotlin while the Python side becomes a client. That is consistent with the MCP architecture above, where the Python package is mostly a client and CulebraTester2 does the work on the device.

For a team evaluating this today, the practical consequence is that there are two things to track: this repository, which is the Python library and tooling, and CulebraTester2-public, which is the on-device component. Version numbers do not obviously correspond across the two, so pinning one does not pin the other.

The claim of full support for all Android APIs sits alongside this, and it is a claim about the view based interface rather than about every Android version of the tooling. The README's own history note on PyPI statistics being broken, with new numbers obtainable from BigQuery, is a good indication of how much of this project's reporting is approximate.

## Three dependency declarations that disagree with each other

The repository carries `setup.py`, `requirements.txt` and `pytest.ini`, and they do not describe the same thing. Anyone vendoring this needs to know which one governs.

`setup.py` is the authoritative one for an install. It declares `python_requires='>=3.9'` and classifies 3.9 through 3.12.

The README says something different about Python versions. The feature list states the tool is written in Python with support for Python 3.6 and above in versions 20.x.y and beyond, which was accurate for the 20 series and is not accurate for 25.x. A reader who takes the README literally will try 3.6 and fail on the install.

`requirements.txt` is the odd one out. It pins `matplotlib~=3.4.3`, `pillow~=8.3.2` and `setuptools~=52.0.0` with compatible release operators, and requires `numpy>=1.23.4` and `pytest~=7.1.3`. A compatible release operator on matplotlib means 3.4.x only, which is a very old version for Python 3.12. This file looks like a development environment for the project's own tooling rather than an install requirement, since `setup.py` does not constrain matplotlib at all. Installing from it directly will fight with a modern scientific stack.

The practical rule is to install with pip and ignore `requirements.txt` unless you are working on the project itself.

## Where Espresso, UIAutomator and a coordinate driver fit instead

The comparison has to start with where the test runs. 

View-based lookup can be more stable than fixed coordinates when a layout, font scale or screen density changes.

The honest cost is the transport. Every operation crosses a process boundary through ViewServer, and the ViewServer has to be running, which is a precondition to check on an emulator image or a device with an unusual build.

## Conclusion

Adopt AndroidViewClient when you need Python scripts that interact with an Android device by view identity rather than by screen coordinates, because that survives a layout change that would break an image comparison. Do not adopt it without reading the packaging first: the README says Python 3.6 and above for the 20.x.y series while `setup.py` declares `python_requires='>=3.9'` for 25.0.1, and the pinned `matplotlib~=3.4.3` in `requirements.txt` is far older than what 25.x expects. The package lists `tools/culebra`, `tools/dump` and `tools/culebra-mcp` as package scripts.

## FAQ

### How do I install AndroidViewClient?

Run `pip3 install androidviewclient --upgrade`. The README points at the wiki for further alternatives, and the package declares `python_requires='>=3.9'` in setup.py for the 25.x series.

### What does the culebra-mcp command do?

It is the Model Context Protocol server entry point, installed as a console script from `com.dtmilano.android.mcp.server:main`. It lets AI assistants drive an Android device through CulebraTester2 using natural language.

### Which environment variables does the AndroidViewClient MCP server read?

`CULEBRATESTER2_URL` for the base URL, defaulting to `http://localhost:9987`, `CULEBRATESTER2_TIMEOUT` in seconds, defaulting to 30, and `CULEBRATESTER2_DEBUG` taking `1`, `true` or `yes`.

### Why does AndroidViewClient compare view hierarchies instead of images?

The README states that logical screen comparison based on the UI Automator Hierarchy avoids extraneous detail issues like time or data changes, which would make image comparison flaky.

### What licence is AndroidViewClient released under?

Apache-2.0. The LICENSE file is at the repository root and setup.py declares the license as Apache.

## Sources

- [dtmilano/AndroidViewClient on GitHub](https://github.com/dtmilano/AndroidViewClient)
- [Issues](https://github.com/dtmilano/AndroidViewClient/issues)
- [License: Apache-2.0](https://github.com/dtmilano/AndroidViewClient/blob/master/LICENSE)
- [README](https://github.com/dtmilano/AndroidViewClient/blob/master/README.md)
- [Releases](https://github.com/dtmilano/AndroidViewClient/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dtmilano-androidviewclient
