droidasc-mcp
# droidasc-mcp
A small, defensive MCP server for [Droid ASC](https://github.com/MG1937/ASC), the fast
on-demand Android APK decompiler.
`droidasc-mcp` exposes ASC's public CLI as six typed, read-only MCP tools. Every analysis runs in an
isolated subprocess group, accepts only APK paths under configured roots, and returns paginated
structured data instead of unbounded terminal output.
> Community project. Not affiliated with or endorsed by the Droid ASC maintainers.
[中文文档](README.zh-CN.md)
## Tools
| Tool | Purpose |
| --- | --- |
| `asc_ping` | Show adapter/engine versions and effective runtime limits |
| `asc_apk_info` | Return size, SHA-256, manifest presence, and DEX entries |
| `asc_get_manifest` | Decode `AndroidManifest.xml` with line pagination |
| `asc_list_classes` | List class descriptors with prefix filtering and pagination |
| `asc_get_class_source` | Decompile one class with line pagination |
| `asc_find_refs` | Find string, type, method, or field references across DEX files |
## Install
Python 3.10 or newer is required. CI checks Linux and native Windows runners on Python 3.10-3.13, including
all six tools over stdio/HTTP against a source-built [acceptance APK](tests/fixtures/android/README.md)
and package installation. macOS remains unverified.
Install the version-pinned GitHub release on Linux:
```bash
python -m venv .venv
.venv/bin/python -m pip install https://github.com/cnlnn/droidasc-mcp/releases/download/v0.2.1/droidasc_mcp-0.2.1-py3-none-any.whl
```
Windows (PowerShell):
```powershell
py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install https://github.com/cnlnn/droidasc-mcp/releases/download/v0.2.1/droidasc_mcp-0.2.1-py3-none-any.whl
```
Windows uses `.venv\Scripts\droidasc-mcp.exe` for the server command. For development,
clone this repository and run `uv sync --locked --extra dev` instead.
## Connect
The default transport is stdio. Limit the server to directories that contain APKs:
```bash
export DROIDASC_MCP_ALLOWED_ROOTS=/absolute/path/to/apks
.venv/bin/droidasc-mcp
```
### Codex
```bash
codex mcp add droidasc \
--env DROIDASC_MCP_ALLOWED_ROOTS=/absolute/path/to/apks \
-- /absolute/path/to/droidasc-mcp/.venv/bin/droidasc-mcp
```
### Claude Desktop and compatible hosts
```json
{
"mcpServers": {
"droidasc": {
"command": "/absolute/path/to/droidasc-mcp/.venv/bin/droidasc-mcp",
"env": {
"DROIDASC_MCP_ALLOWED_ROOTS": "/absolute/path/to/apks"
}
}
}
}
```
### Streamable HTTP
```bash
DROIDASC_MCP_ALLOWED_ROOTS=/absolute/path/to/apks \
.venv/bin/droidasc-mcp --transport streamable-http --host 127.0.0.1 --port 8000
```
The endpoint is `http://127.0.0.1:8000/mcp`. Keep it on loopback unless you add an authenticated,
TLS-terminating reverse proxy.
## Examples
Ask an MCP host to call:
```text
asc_apk_info(apk_path="/samples/app.apk")
asc_list_classes(apk_path="/samples/app.apk", prefix="com.example", limit=100)
asc_find_refs(apk_path="/samples/app.apk", kind="string", value="Authorization")
asc_get_class_source(apk_path="/samples/app.apk", class_name="com.example.MainActivity")
```
Results include `total`, `offset`, `limit`, `truncated`, and `next_offset`. Use `next_offset` for the
next request (`null` means done): the response budget can shorten a page. A single line
that exceeds the budget produces an explicit error rather than silent truncation.
Reference fields are best-effort parsing of ASC CLI text. Embedded newlines can split records;
`total` counts output lines, not semantic references. Reference lines are sorted before pagination.
Snapshots are decoded and sorted once, then cached for 60 seconds (up to 8 entries). The cache
budget accounts for Python strings and tuple pointers, not just original output bytes. Identical
concurrent queries share a single computation; unrelated queries and cache hits do not wait on
a global computation lock. Snapshots are
keyed by query and file identity/size/timestamps. Cache misses rerun ASC; this is not an immutable
content-addressed evidence store. Do not modify APK files between pages.
## Configuration
| Environment variable | Default | Meaning |
| --- | --- | --- |
| `DROIDASC_MCP_ALLOWED_ROOTS` | current directory | Allowed roots, separated by `os.pathsep` (`:` on Unix, `;` on Windows) |
| `DROIDASC_MCP_TIMEOUT_SECONDS` | `180` | Per-operation timeout |
| `DROIDASC_MCP_MAX_APK_BYTES` | `2147483648` | Maximum accepted APK size |
| `DROIDASC_MCP_MAX_OUTPUT_BYTES` | `67108864` | Captured stdout limit and aggregate decoded snapshot budget |
| `DROIDASC_MCP_MAX_WORKER_MEMORY_BYTES` | `2147483648` | Worker-tree budget (Windows Job aggregate; POSIX per-process address-space cap plus aggregate RSS watchdog) |
| `DROIDASC_MCP_MAX_PAGE_SIZE` | `1000` | Maximum lines returned by one call |
| `DROIDASC_MCP_MAX_PARALLEL` | `2` | Maximum concurrent ASC subprocesses |
## Design
- Uses the public `droidasc` CLI module entry point; it does not import ASC private internals.
- Never invokes a shell and does not expose a generic command tool.
- Drains stdout and stderr concurrently with hard capture caps; no bulk output files are created.
- Caps stderr at 64 KiB and budgets page content conservatively within 256 KiB.
- Runs ZIP inspection and hashing in a supervised worker under the same concurrency budget.
- On POSIX, kills the operation's process group on completion or failure, even if its leader exited.
- On Windows, assigns the worker to a kill-on-close Job Object before starting ASC. Cleanup
includes descendants even after the worker exits; Job setup failure prevents analysis from starting.
- Propagates MCP request cancellation through queue/snapshot waits and active sync tools; cleanup
completes before the cancelled server task exits, and the session can continue serving requests.
- Applies the configured worker memory ceiling before importing ASC. Windows limits aggregate
committed memory for the Job tree. POSIX applies an inherited per-process kernel `RLIMIT_AS`
and samples aggregate tree RSS every 50 ms, terminating the tree if it crosses the same budget.
- Resolves symlinks before checking the allowed-root policy.
ASC and its dependencies still parse untrusted binary input. Use a container or disposable VM for
hostile APKs. This adapter is a process boundary, not a malware sandbox.
Native Windows CI checks live-parent and orphan cleanup, including grandchildren, successful
completion, output overflow, reader termination, and repeated-operation handle counts.
Capture buffers, snapshots being built, and active pages can coexist with the cache; this budget
is not a hard MCP-host total-RSS cap. The POSIX aggregate tree check is a sampled watchdog, while
the inherited per-process address-space ceiling is kernel-enforced. Dense outputs may hit the
decoded-memory budget before the wire cap.
## Development
See [local acceptance checks](docs/VALIDATION.md) for real-process tests, optional APK transport
checks, measured outcomes, and the remaining verification limits.
```bash
uv sync --locked --extra dev
uv run ruff check .
uv run pytest --cov --cov-report=term-missing
uv run python scripts/validate_corpus.py /path/to/one.apk /path/to/another.apk
uv run python scripts/stability_check.py /path/to/one.apk --duration 300 --workers 2
uv build
# Python 3.12+; use fresh dist outputs matching the current version:
uv run python scripts/verify_dist.py dist/droidasc_mcp-0.2.1.tar.gz dist/droidasc_mcp-0.2.1-py3-none-any.whl
```
## License
Apache License 2.0. Droid ASC is a separate upstream project and retains its own copyright and
license.
TDQS
Scored across 6 tools
Each tool targets a distinct concern: configuration, APK metadata, manifest decoding, class listing, source decompilation, and cross-DEX reference searching. There is no meaningful overlap between tool purposes, so an agent can reliably select the right tool.
The tools share a clear asc_ prefix and mostly follow a verb_noun pattern (ping, get_manifest, list_classes, get_class_source, find_refs). The single exception is asc_apk_info, which uses a noun phrase rather than a verb, creating a minor inconsistency.
Six tools is well-scoped for an APK static analysis server. Each tool covers a distinct capability without redundancy or bloat, making the surface easy for an agent to navigate.
The tool set covers the core APK inspection workflow: metadata, manifest, class enumeration, source decompilation, and reference lookup. Minor gaps exist such as resource decoding or raw DEX dumping, but the provided surface supports common reverse-engineering tasks end to end.