Skip to main content
Glama
claude-android

claude-android

by duonglkh

claude-android

MCP server + Claude Code skills toolkit for Android dev workflows. Expose Gradle / Manifest / R8 context to Claude, ship a curated library of skills that consume it.

Status License Node MCP

What it does

Android projects with Kotlin DSL + convention plugins + KMP + AGP-upgrade pain repeat the same tasks: read versions, scan dependencies, plan migrations, audit R8 rules. Each task makes Claude grep files line by line.

claude-android is an MCP server that exposes a small set of read-only tools (Gradle, Manifest, ProGuard, string resources) so Claude can answer "what's my AGP version, what plugins, what permissions, which keep rule is this, which locale is missing this key" in milliseconds — and a skills library that orchestrates those tools to deliver complete workflows: agp-upgrade, r8-audit, string-sync (see scope below for exactly what each ships today).

┌──────────────────┐    stdio     ┌─────────────────────┐    fs    ┌──────────────┐
│  Claude Code     │  ────────▶   │  claude-android     │  ──────▶ │ your Android │
│  (CLI / agent)   │              │  MCP server         │           │ project      │
└──────────────────┘   tools list └─────────────────────┘  parsed   └──────────────┘
                                        ▲                  JSON
                                        │
                                ┌────────────────┐
                                │ skills/        │
                                │  agp-upgrade/  │
                                │  r8-audit/     │
                                │  string-sync/  │
                                └────────────────┘

Related MCP server: replicant-mcp

Scope

What ships today:

Component

Status

MCP server (stdio transport)

✅

Tool: get_project_info (settings.gradle + libs.versions.toml)

✅

Tool: read_gradle (module build.gradle.kts)

✅

Tool: read_manifest (AndroidManifest.xml)

✅

Tool: read_proguard_rules (ProGuard/R8 rules, comment-paired)

✅

Tool: read_string_catalog (values*/strings.xml per module)

✅

Skill: agp-upgrade (workflow only — no auto-apply)

✅

Skill: r8-audit (per-rule report, never edits the rules file)

✅

Skill: string-sync (per-module/locale gap report, delegates the actual fill)

✅

Tool: run_lint

❌ not planned — see Status for why

Requirements

Install

Option A — From npm (after publish)

npm install -g @duonglkh/claude-android

Option B — From source (v0.1 preview)

git clone https://github.com/duonglkh/claude-android.git
cd claude-android
npm install
npm run build
npm link    # so `claude-android-mcp` is on your PATH

Register the MCP server with Claude Code

claude mcp add android claude-android-mcp

Verify:

claude mcp list
# expected: "android" with status "connected" (or similar)

Use the skills

Skills live in skills/. To use them in Claude Code:

# Copy / symlink skills into Claude Code's skills directory
mkdir -p ~/.claude/skills
cp -r ./skills/agp-upgrade ~/.claude/skills/
cp -r ./skills/r8-audit ~/.claude/skills/
cp -r ./skills/string-sync ~/.claude/skills/

# Or, if installed via npm globally:
# Symlink from the global install:
ln -s "$(npm root -g)/@duonglkh/claude-android/skills/agp-upgrade" ~/.claude/skills/agp-upgrade

Then in any Android project:

cd ~/your-android-project
claude
> /agp-upgrade
> /r8-audit
> /string-sync

/agp-upgrade:

  1. Call mcp__android__get_project_info to read AGP / Kotlin / modules.

  2. Ask which AGP version to target.

  3. For each module, call mcp__android__read_gradle to find breaking changes.

  4. Produce a step-by-step migration plan without applying any changes.

  5. Wait for confirmation before patching.

/r8-audit:

  1. Call mcp__android__read_gradle to find the module's proguardFiles.

  2. Call mcp__android__read_proguard_rules for each — every rule comes back paired with the comment written immediately above it, since that comment is often the only record of why a broad-looking rule is actually necessary.

  3. Classify each rule (redundant / global optimization killer / needs justification / fine), checking the project's own CLAUDE.md for an explicit "don't touch without asking" marker before recommending anything.

  4. Produce a per-rule report. Never edits the rules file.

/string-sync:

  1. Call mcp__android__get_project_info for the module list, then mcp__android__read_string_catalog on each module that has its own resources.

  2. Report missing/extra keys per module per locale, and flag any locale directory using a modern ISO code where Android's resource qualifier resolution still expects the historical one (values-id → should be values-in, etc.) — those locales are never served at all, not just incompletely translated.

  3. For the actual fill, delegates to the user's androidstrings skill if installed, or offers to edit one module/locale at a time with confirmation. Does not bulk-write files itself.

Tools reference

get_project_info

Input:

{ "projectPath": "/absolute/path/to/android/project" }

Output (example):

{
  "projectPath": "/Users/me/MyApp",
  "rootProjectName": "MyApp",
  "modules": ["app", "core:ui", "feature:home"],
  "agpVersion": "8.7.3",
  "kotlinVersion": "2.0.21",
  "composeBomVersion": "2024.12.01",
  "isKmp": false,
  "hasBuildLogic": true,
  "warnings": []
}

read_gradle

Input:

{ "modulePath": "/absolute/path/to/module" }

Output includes: plugins, namespace, compileSdk, minSdk, targetSdk, applicationId, versionCode, versionName, composeEnabled, productFlavors, buildTypes, dependencies, warnings.

Convention-plugin fallback: if compileSdk/minSdk/targetSdk aren't declared in the module's own build.gradle.kts (common once a project uses build-logic convention plugins), the tool scans build-logic/**/*.kt for them instead and lists that in warnings. Treat those three fields as a heuristic — not a Gradle-evaluated value — whenever warnings is non-empty; a module could apply a different convention plugin than the one the fallback happened to read.

read_manifest

Input:

{ "manifestPath": "/absolute/path/to/AndroidManifest.xml" }

Output includes: packageAttr, permissions, applicationName, applicationLabel, applicationIcon, applicationTheme, usesCleartextTraffic, activities, services, receivers, providers.

read_proguard_rules

Input:

{ "filePath": "/absolute/path/to/proguard-rules.pro" }

Output: sections[], each { comment, rules[] } — comment is the text of the comment block immediately above that group of rules (null if there isn't one), stripped of leading #. Each rule is { raw, directive, modifiers, target, members, lineStart }. Also returns fileHeaderComment (a leading pure-comment block with no rule attached, e.g. a file banner) and ruleCount.

This tool only parses — it does not judge which rules are redundant or safe to remove. That reasoning is the r8-audit skill's job, specifically so the comment-per-rule context (often the only record of why a rule exists) is never thrown away before a judgment is made.

read_string_catalog

Input:

{ "modulePath": "/absolute/path/to/module" }

Output: baseKeyCount, nonTranslatableKeys (excluded from the missing-key check), and locales[] — each { locale, keyCount, missingKeys, extraKeys }. Resource qualifiers that aren't locales (values-sw600dp, values-v31, values-night, density buckets, …) are filtered out before counting, rather than being miscounted as under-translated languages — a naive values-* directory count on a real project reported 24 "locales" for one module vs. 22 for its siblings purely because of two non-locale config-qualifier directories. warnings flags locale directories using a modern ISO code where Android's resource resolution still expects the historical one (values-id should be values-in, values-he should be values-iw, values-yi should be values-ji) — those locales are never selected at all, for any device.

Roadmap

  • v0.1 — read-only tools (get_project_info, read_gradle, read_manifest) + agp-upgrade skill

  • v0.2 (this release) — read_proguard_rules; r8-audit skill

  • v0.3 (this release) — read_string_catalog; string-sync skill

  • v0.5 — first npm publish (@duonglkh/claude-android)

  • v1.0 — write tools (apply patches with confirmation), Crashlytics adapter

run_lint is off the roadmap — see Status for the measurement behind that call.

See issues for current work.

Status

v0.1 preview — tools are functional but parsers are regex-based, not full AST. They handle modern Kotlin DSL Gradle projects well, including build-logic convention-plugin setups (read_gradle falls back to scanning build-logic/ for compileSdk/minSdk/targetSdk when a module doesn't declare them itself, and flags it in warnings); legacy Groovy build.gradle may parse poorly. Open an issue with a sample if you hit it.

Why regex and not ./gradlew :app:properties / an AGP-aware task? Measured on a real 10-module Kotlin DSL + convention-plugin project: a cold Gradle daemon start adds ~9s, a warm one ~1.5s — and the stock properties task doesn't even expose compileSdk/minSdk/ targetSdk (those live on the AGP DSL extension, not as plain Gradle project properties), so getting them from Gradle itself would need a custom init-script task, not just a flag. That also means invoking Gradle requires the project to fully configure — which can fail on things unrelated to what you're asking for (e.g. a missing credential env var referenced by settings.gradle.kts). For v0.1, regex-with-heuristic-fallback (and an honest warnings array when it's guessing) stays the only mode. A --resolve flag that shells out to Gradle for ground truth, with the custom task that implies, is a reasonable v0.2+ feature — not something to half-build now.

Why no run_lint tool? Measured on the same real project: ./gradlew :app:lintStagingDebug — the cheapest single-variant lint task available, with the Gradle daemon already warm from a prior invocation — took 7m9s, and still failed (a KSP/Hilt codegen mismatch, most likely from unrelated concurrent builds against the same project rather than a real lint defect — not investigated further, out of scope here). Whatever the cause, a tool whose timing is "7+ minutes, and it might not even finish" is disqualifying on its own. That's not a "add a timeout" problem: this MCP server is a synchronous stdio request/response loop with no progress-reporting, and most MCP clients apply their own timeout to a tool call well under 6 minutes. Wrapping ./gradlew lint as a tool call would mean the call times out client-side before Gradle finishes, which is worse than not having the tool — it would look like a hang or a crash, not "still working." A lint integration needs either a background-job tool shape (start, poll, fetch-result) or a client with long-running-call support, not a single blocking run_lint call. That's a different enough feature that it's not on the roadmap at all right now, rather than postponed to "later."

Testing

npm test          # vitest; fixtures under test/fixtures/ (sanitized, derived from real projects)
npm run typecheck

Contributing

PRs welcome. Open an issue first for non-trivial changes. New skills are especially valued — if your team has an Android workflow that Claude could orchestrate, propose it.

Part of the hidev open-source ecosystem

See duonglkh.github.io for the full roster.

License

MIT © 2026 Hidev (Hung Duong)

Available Tools

3 tools
get_project_infoA

Read root Android project info: AGP version, Kotlin version, modules list, project name. Pass projectPath = absolute path to the project root (the directory containing settings.gradle.kts).

Inputs: projectPath (required).

read_gradleA

Read a module's build.gradle.kts and return parsed structure: plugins, android { } block, dependencies block. Pass modulePath = absolute path to the module directory (e.g. /path/to/project/app).

Inputs: modulePath (required).

read_manifestA

Read AndroidManifest.xml and return parsed structure: package, permissions, application class, activities. Pass manifestPath = absolute path to the AndroidManifest.xml file.

Inputs: manifestPath (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 3 tools

    Disambiguation5/5

    Each tool targets a distinct file type: project info, Gradle build file, and Android manifest. There is no overlap in functionality.

    Naming Consistency5/5

    All tool names follow a clear verb_noun pattern (get_project_info, read_gradle, read_manifest) with consistent snake_case. The verbs 'get' and 'read' are synonymous in this context.

    Tool Count4/5

    Three tools is on the low side but appropriate for a focused read-only server that inspects core Android project files. Each tool serves a distinct purpose without unnecessary bloat.

    Completeness3/5

    The set covers the essential files for reading an Android project, but lacks write capabilities and may miss some auxiliary files (e.g., settings.gradle.kts, proguard rules). This leaves some gaps for interactive modification.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      An MCP server that enables AI assistants to build, test, and debug Android applications by interacting directly with the Android development environment. It provides tools for managing emulators, executing Gradle tasks, running ADB commands, and performing UI automation via accessibility trees.
      14
      105 npm
      19
      MIT
    • F
      license
      Not graded
      quality
      A
      maintenance
      MCP server that provides AI coding agents real Android development tools—Gradle, adb, logcat, lint, crash triage—through a local, permissioned interface. Enables agents to inspect projects, run safe Gradle tasks, capture logs/screenshots, and triage crashes.
      1
      -