Skip to main content
Glama
README.md
# drozer-mcp

**MCP server wrapping [Drozer](https://github.com/WithSecureLabs/drozer) for LLM-driven Android IPC security testing.**

Lets any [Model Context Protocol](https://modelcontextprotocol.io) client — Claude
Code, Claude Desktop, Cursor, LM Studio, custom agents — drive Drozer
autonomously. The LLM enumerates exported activities, services, broadcast
receivers, and content providers across installed apps, then exercises them
with intents, broadcasts, and provider queries to surface IPC vulnerabilities.

Designed for the gap in the mobile-security-AI landscape: while there are
solid MCP wrappers for [Frida](https://github.com/dnakov/frida-mcp),
[JADX](https://github.com/zinja-coder/jadx-ai-mcp), and
[MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF), the canonical
Android IPC tool — Drozer — has had no agentic interface until now.

## Status

Alpha. Working core: connection lifecycle, package/component enumeration,
content provider querying, intent launching, and the most commonly-used
scanner modules. Tested against the Drozer 3.1.x console.

## Install

```bash
pip install drozer-mcp
```

Or from source:

```bash
git clone https://github.com/YOUR-USERNAME/drozer-mcp
cd drozer-mcp
pip install -e .
```

You also need:

1. **A working Drozer install** (`pip install drozer` plus a Java runtime).
   The MCP server shells out to the `drozer` binary.
2. **The Drozer agent APK** running on a rooted physical device or emulator.
   Download from the [Drozer releases page](https://github.com/WithSecureLabs/drozer/releases).
3. **ADB port forwarding**:

   ```bash
   adb forward tcp:31415 tcp:31415
   ```

## Configure your MCP client

### Claude Desktop / Claude Code

Add to `~/.config/claude/claude_desktop_config.json` (Linux) or the equivalent
on macOS / Windows:

```json
{
  "mcpServers": {
    "drozer": {
      "command": "drozer-mcp"
    }
  }
}
```

Restart the client. The Drozer tools will appear with the `drozer__` prefix.

### Environment variables

| Variable | Purpose | Default |
|---|---|---|
| `DROZER_BIN` | Path to the `drozer` console binary | `drozer` (PATH) |
| `DROZER_SERVER` | Override the agent host:port | drozer's own default |
| `DROZER_LOG` | Log level: `DEBUG`/`INFO`/`WARNING`/`ERROR` | `INFO` |

## Tools

### Connection

| Tool | Purpose |
|---|---|
| `drozer_connect` | Open a console session against the agent |
| `drozer_disconnect` | Close the session |

The first non-connection tool call connects implicitly. If the underlying
console dies (agent crash, ADB hiccup), the next call transparently reconnects.

### Enumeration

| Tool | Drozer command | Returns |
|---|---|---|
| `list_packages` | `app.package.list` | List of package names |
| `package_attack_surface` | `app.package.attacksurface` | Per-kind counts + `debuggable` |
| `list_activities` | `app.activity.info` | Components with required permissions |
| `list_services` | `app.service.info` | Same shape as activities |
| `list_receivers` | `app.broadcast.info` | Same shape |
| `list_providers` | `app.provider.info` | Same shape |
| `find_provider_uris` | `app.provider.finduri` | Deduped list of `content://...` URIs |

### Attacks

| Tool | Drozer command | Purpose |
|---|---|---|
| `query_provider` | `app.provider.query` | Read a provider with full WHERE/projection/sort args |
| `read_provider` | `app.provider.read` | Read file-backed providers (FileProvider path-traversal) |
| `start_activity` | `app.activity.start` | Launch with component / action / data / extras |
| `start_service` | `app.service.start` | Start or bind a service with intent params |
| `send_broadcast` | `app.broadcast.send` | Send a broadcast intent |

### Scanners

| Tool | Drozer module | Finds |
|---|---|---|
| `scan_provider_injection` | `scanner.provider.injection` | SQLi in content providers |
| `scan_provider_traversal` | `scanner.provider.traversal` | Directory traversal in file providers |
| `scan_activity_browsable` | `scanner.activity.browsable` | Deep-link / URL scheme entry points |

### Shell + escape hatch

| Tool | Purpose |
|---|---|
| `shell_exec` | Run a shell command on the device via `shell.exec` |
| `drozer_run_raw` | Run any Drozer command verbatim — for modules not yet wrapped |

## Example session (Claude Code)

```
You: Find SQL injection in any installed app.
Claude: [calls list_packages with filter="com.example"]
        [calls package_attack_surface for each result]
        [calls scan_provider_injection for those with providers exported]
        [calls query_provider with payloads on each finding]

Found 1 injection in com.example.app's UserProvider:
  URI: content://com.example.app.provider/users
  Injectable parameter: selection
  PoC: query with selection="1=1 UNION SELECT password FROM ..."
       returned 47 rows including hashed credentials.
```

## Why a long-lived console?

Drozer's `console connect` starts a JVM-backed REPL that talks to the agent over
a TCP port. Cold-start is ~1-2 seconds; once warm, command roundtrips are
sub-second. Re-spawning per tool call would make an LLM-driven workflow painfully
slow, so this MCP server runs a single `pexpect`-managed session and dispatches
each tool call to it as a REPL command.

That comes with one caveat: the session is **not thread-safe**. The MCP runtime
serializes tool calls per server process, which makes this safe in practice. If
you want parallel scans of multiple devices, run multiple MCP server instances
with different `DROZER_SERVER` settings.

## Roadmap

- More scanners: `scanner.misc.checkparcel`, `scanner.misc.native`, the full
  `scanner.misc.*` family.
- Structured JSON output mode for `query_provider` (currently raw text).
- Drozer Module API integration so custom modules show up automatically.
- iOS / Objective-C equivalents (probably a separate `frida-ios-mcp` rather than
  shoehorning here).

## License

Apache-2.0.

TDQS

A3.7/5.0

Scored across 19 tools

Disambiguation5/5

Each tool targets a distinct action (connect, disconnect, list packages, list activities, query provider, scan for injection, etc.) with clear boundaries. Even similar tools like query_provider and read_provider are differentiated by their use case.

Naming Consistency5/5

All tool names use consistent snake_case with a verb_noun pattern. The drozer_ prefix for connection and raw commands is a consistent sub-pattern, and there is no mixing of styles.

Tool Count5/5

19 tools is appropriate for the Android security assessment domain, covering connection management, enumeration, scanning, and exploitation without being excessive. Each tool serves a clear purpose.

Completeness4/5

The tool set covers the core Drozer workflow: connect, enumerate packages and components, query providers, scan for injection/traversal, and send intents. Some advanced modules are missing but can be accessed via drozer_run_raw, and the set is well-scoped for practical use.

Maintenance

ActivityStale
ResponsivenessNo issues