Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/mcp-android-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@prover-coder-ai/docker-git": minor
---

Add Android MCP integration alongside the existing Playwright MCP support (issue #436).

Projects can now opt into a nested Android emulator sidecar driven by the
first-party Rust `android-connection` MCP server, mirroring how Playwright MCP works. Enable it
Comment on lines +7 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Уточните упоминание "first-party" и версионирование android-connection.

Строка 8 упоминает "first-party Rust android-connection MCP server", но в changeset не указывается:

  • Где находится крейт (например, crates/android-connection)
  • Что это — новый компонент в этом PR

Рекомендуется добавить уточнение в скобках: "новый Rust крейт android-connection" или аналогично для ясности, что это не существующий компонент.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/mcp-android-integration.md around lines 7 - 8, The changeset text
mentions "first-party Rust `android-connection` MCP server" but does not clarify
that this is a newly introduced component. Update the changeset text to
explicitly indicate that `android-connection` is a new Rust crate being added in
this PR. You can add a parenthetical clarification such as "new Rust crate
`android-connection`" or include the location context (e.g.,
`crates/android-connection`) to make it clear this is not an existing component
and is being introduced for the first time.

with the new `--mcp-android` / `--no-mcp-android` create flags, the `mcp-android`
subcommand, the interactive create-flow prompt, or the `enableMcpAndroid` field
on the web/API create-project request. When enabled, the generated
`docker-compose.yml` adds a gated `docker-android` emulator service (KVM,
ADB port forwarding, headless CI mode) and the agent MCP config writers register
the Android server so it coexists with Playwright.
20 changes: 20 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ jobs:
- name: Build (api)
run: bun run --cwd packages/api build

rust-android-connection:
name: Rust Android connection
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Rust version
run: |
rustc --version
cargo --version
- name: Format
working-directory: crates/android-connection
run: cargo fmt --check
- name: Test
working-directory: crates/android-connection
run: cargo test --locked
- name: Clippy
working-directory: crates/android-connection
run: cargo clippy --locked --all-targets -- -D warnings

dist-deps-prune:
name: Dist deps prune
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bun run docker-git clone https://github.com/ProverCoderAI/docker-git/issues/122

- `--force` пересоздаёт окружение и удаляет volumes проекта.
- `--mcp-playwright` включает Playwright MCP и Chromium sidecar для браузерной автоматизации.
- `--mcp-android` включает first-party Android MCP (`android-connection`) и вложенный sidecar с Android-эмулятором (`docker-android`) для мобильной автоматизации.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Упростите формулировку для параллельности со строкой --mcp-playwright.

Текущая формулировка:

- `--mcp-android` включает first-party Android MCP (`android-connection`) и вложенный sidecar с Android-эмулятором (`docker-android`) для мобильной автоматизации.

содержит больше деталей реализации, чем описание Playwright выше (line 73). Для лучшей параллельности и читаемости рекомендуется:

- `--mcp-android` включает Android MCP и Android-эмулятор sidecar для мобильной автоматизации.

Либо, если детали важны, добавьте аналогичную детализацию для Playwright:

- `--mcp-playwright` включает Playwright MCP (chromium-connection) и Chromium sidecar для браузерной автоматизации.
- `--mcp-android` включает Android MCP (android-connection) и Android-эмулятор sidecar для мобильной автоматизации.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 74, The documentation line describing the --mcp-android
flag contains excessive implementation details (mentioning first-party
designation, specific component names like android-connection and
docker-android) compared to the --mcp-playwright line above it, breaking
parallel structure. Simplify the --mcp-android description by removing the
implementation-specific terminology and details to match the conciseness of the
--mcp-playwright description, keeping only the essential information about what
capabilities are enabled for mobile automation.

Source: Path instructions


Автоматический запуск агента:

Expand Down
1 change: 1 addition & 0 deletions crates/android-connection/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
249 changes: 249 additions & 0 deletions crates/android-connection/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions crates/android-connection/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "docker-git-android-connection"
version = "0.1.0"
edition = "2021"
description = "First-party Android MCP and lifecycle module for docker-git"
license = "MIT"
repository = "https://github.com/ProverCoderAI/docker-git"

[lib]
name = "docker_git_android_connection"
path = "src/lib.rs"

[[bin]]
name = "docker-git-android-connection"
path = "src/main.rs"

[[bin]]
name = "android-connection"
path = "src/bin/android-connection.rs"

[dependencies]
clap = { version = "4.5.53", features = ["derive"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.145"
10 changes: 10 additions & 0 deletions crates/android-connection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# docker-git Android connection

First-party Android MCP module for docker-git.

The crate provides two binaries:

- `android-connection`: MCP stdio server used by Codex, Claude, Gemini, and Grok.
- `docker-git-android-connection`: lifecycle CLI for deterministic Android runtime naming and Docker command construction.

The core module keeps deterministic naming, endpoint validation, and tool specifications pure. Shell effects are isolated in the binaries and MCP tool handlers.
54 changes: 54 additions & 0 deletions crates/android-connection/src/bin/android-connection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use clap::Parser;
use docker_git_android_connection::mcp::{run_stdio, McpState};
use docker_git_android_connection::{
android_spec, DEFAULT_ADB_ENDPOINT, DEFAULT_ANDROID_IMAGE, DEFAULT_PROJECT_ID,
};
use std::io::{self, BufReader};
use std::path::PathBuf;
use std::process::ExitCode;

#[derive(Parser, Debug)]
#[command(version, about = "Android MCP stdio server for docker-git")]
struct Cli {
#[arg(long, default_value = DEFAULT_PROJECT_ID)]
project: String,
#[arg(long, default_value = "docker-git-shared")]
network: String,
#[arg(long, default_value = DEFAULT_ADB_ENDPOINT)]
endpoint: String,
#[arg(long, default_value = DEFAULT_ANDROID_IMAGE)]
image: String,
#[arg(long, default_value = ".")]
workspace: PathBuf,
#[arg(long)]
allow_install: bool,
#[arg(long)]
no_adb_probe: bool,
}

fn main() -> ExitCode {
match run() {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("{error}");
ExitCode::from(1)
}
}
}

fn run() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let spec = android_spec(&cli.project, &cli.network, &cli.endpoint, &cli.image)?;
let state = McpState {
spec,
workspace: cli.workspace,
adb_probe: !cli.no_adb_probe,
allow_install: cli.allow_install,
};
let stdin = io::stdin();
let stdout = io::stdout();
let mut reader = BufReader::new(stdin.lock());
let mut writer = stdout.lock();
run_stdio(&mut reader, &mut writer, state)?;
Ok(())
}
Loading
Loading