-
-
Notifications
You must be signed in to change notification settings - Fork 1
Development and Integration
delamain/
├── src/main/java/com/zin/delamain/ ← Java backend (Javalin + JadxDecompiler)
├── src/test/java/com/zin/delamain/ ← JUnit tests
├── gateway/ ← Python MCP gateway (FastMCP)
│ ├── main.py
│ ├── src/
│ │ ├── tools/ ← one MCP tool module per feature area
│ │ ├── config/ ← TOML config loading
│ │ ├── auth/ ← MCP client bearer-token auth
│ │ └── registry/ ← JADX backend instance registry
│ └── tests/
│ ├── *.py ← unit tests (mocked HTTP)
│ └── integration/ ← integration tests (needs a running service)
├── tests/ ← Python integration tests against a live Java backend + gateway pair
├── tools/delamain-cli/ ← Rust out-of-band upload CLI
└── docker/
└── Dockerfile ← fused image: Java + Python, no Xvfb/noVNC
Full architecture (Java package responsibilities, the on-disk index stack, auth model) is in docs/architecture-reference.md.
| Component | Version |
|---|---|
| Java | 21 (Maven build, Javalin runtime) |
| Maven | 3.9+ |
| Python | 3.10+ (gateway) |
| uv | latest |
| Rust | stable (only if building delamain-cli) |
# Java backend — build
mvn -DskipTests clean package # artifact: target/delamain-*.jar
# Java backend — unit tests
mvn test
# Python gateway — setup
cd gateway && uv sync
# Python gateway — unit tests (mocked HTTP, no live service needed)
cd gateway && pytest tests --ignore=tests/integration
# Python gateway — integration tests (needs a running gateway/backend)
cd gateway && pytest tests/integration
# Root integration tests (needs a live Java backend + gateway)
export JADX_JAVA_URL=http://localhost:28650
export GATEWAY_URL=http://localhost:8651
export JADX_AUTH_TOKEN="$DELAMAIN_AUTH_TOKEN"
export MCP_AUTH_TOKEN="$MCP_AUTH_TOKEN"
pytest tests/
# delamain-cli (Rust)
cd tools/delamain-cli
cargo build --release
cargo testRecommended CI split: run the two unit-test commands (Java mvn test + gateway pytest tests --ignore=tests/integration) on every push; save the live-service integration suites for pre-release.
- Create or pick a module under
gateway/src/tools/. - Implement
async def tool_name(param: type, ...) -> dict. - Register it with
@mcp.tool()inside that module'sregister_*_tools(mcp). - Wire the registration function into
gateway/src/tools/__init__.py. - Write a matching unit test (mock
get_from_jadx, assert only on the HTTP call shape — endpoint,params/json_body,method— not on business logic).
Design conventions to follow (from docs/mcp-tool-design-guide.md — written specifically for AI-consumed tools, not human-consumed APIs):
- Keep tool descriptions under ~200 characters; token overhead is paid on every call.
- Always return a
dict, never let an exception reach the AI — standard error shape{"error": "ERROR_CODE", "message": "..."}. - Every list-returning tool needs pagination (
offset/count, capped page size,has_more). - Anything that can take longer than ~10 seconds must use the submit/poll ticket pattern (
submit_x()→ ticket →get_task_result(ticket)), or the MCP client will time out. - Tier timeouts by operation type (metadata search vs. code decompilation vs. code search vs. warmup) rather than one blanket value.
- Provide a batch variant (
batch_get_x) for any frequently-used single-item tool. -
instance_id: Optional[str] = Noneis accepted on most tools for call-site compatibility but is otherwise ignored — the gateway is single-instance (see FAQ); don't build new routing logic on it. - Follow the naming convention:
get_/search_/list_/submit_/generate_/export_verbs,submit_x+get_x_resultpairs for async work.
Point your MCP client at the gateway's Streamable-HTTP MCP endpoint:
http://<host>:8651/mcp
Authorization: Bearer <one of your DELAMAIN_AUTH_TOKENS values>
Any token in the DELAMAIN_AUTH_TOKENS whitelist grants identical, full access — see Configuration for the three-token model. There is no stdio fallback for the gateway; it runs strictly as an HTTP server (mcp.run(transport="http", ...) in gateway/main.py) with a single uvicorn worker.
Once connected, call get_jadx_guide(verbose=True) for the server's own full workflow guide, then typically:
-
list_available_files_tool— see what's staged under the mounted APK directory. -
load_file_tool(path=...)— load a file relative to/apks. - Poll
get_decompile_statusuntil the warmup/decompile state stabilizes, then use the decompilation/search/graph/resource/Frida/security tool families.
Any operation that could exceed ~10 seconds (security scans, callgraph export, code search over a cold or very large index) is exposed as a submit_x(...) tool that returns a ticket immediately, paired with a polling tool:
result = submit_security_scan(scan_type="full")
# → {"ticket": "...", "status": "submitted", "retry_after_seconds": 5}
status = get_task_result(ticket=result["ticket"])
# → status: running | done | error | not_foundTicket TTL is 300s on the Python gateway side, 600s on the Java backend side (the longer Java-side TTL accounts for search requests queued during warmup).
For an APK too large (or too awkward) to place in the mounted directory, pair the create_transfer_token MCP tool with the standalone delamain-cli Rust CLI so the file's bytes never traverse the AI's context window:
- The AI calls
create_transfer_token(filename=...), which returnstoken,upload_url,status_path, andexpires_at_epoch_ms. - The human (or an automation) runs:
(or
delamain-cli --server http://<host>:8651 --token <token> /path/to/app.apk
--upload-url <upload_url> --token <token> ...using the URL returned directly). This resumes automatically fromGET /transfer/statusif a previous attempt was interrupted, streams the file once to compute SHA-256, then sends chunked, checksummedPUTrequests. - On success it prints the server-confirmed
path,bytes, andsha256; the AI then callsload_filewith thatpath.
A one-shot, non-resumable alternative needing no extra tooling:
curl -T /path/to/app.apk -H "X-Transfer-Token: <token>" <upload_url>Full protocol (headers, TTL, size caps, sandbox rules) is in docs/file-upload.md; CLI build/cross-compile instructions are in tools/delamain-cli/README.md.
See also: Configuration for every relevant env var, Deployment for how to stand up an instance, FAQ for the token model and health-check quick reference.