androjack-mcp 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,10 +18,10 @@
18
18
 
19
19
  [![npm version](https://img.shields.io/npm/v/androjack-mcp?color=0A7AFF&style=flat-square&logo=npm&label=npm)](https://www.npmjs.com/package/androjack-mcp)
20
20
  [![GitHub stars](https://img.shields.io/github/stars/VIKAS9793/AndroJack-mcp?style=flat-square&logo=github&color=0A7AFF)](https://github.com/VIKAS9793/AndroJack-mcp/stargazers)
21
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen?style=flat-square&logo=node.js)](https://nodejs.org)
21
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen?style=flat-square&logo=node.js)](https://nodejs.org)
22
22
  [![MCP Spec](https://img.shields.io/badge/MCP-2025--11--25-blueviolet?style=flat-square)](https://modelcontextprotocol.io)
23
23
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.5-3178C6?style=flat-square&logo=typescript)](https://typescriptlang.org)
24
- [![Tools](https://img.shields.io/badge/tools-20-orange?style=flat-square)](#-the-20-tools)
24
+ [![Tools](https://img.shields.io/badge/tools-21-orange?style=flat-square)](#-the-21-tools)
25
25
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
26
26
  [![Android API](https://img.shields.io/badge/Android-API%2021--36-34A853?style=flat-square&logo=android)](https://developer.android.com)
27
27
 
@@ -102,10 +102,12 @@ Kotlin Multiplatform went mainstream in 2025 — over 900 new KMP libraries publ
102
102
 
103
103
  ## 🧩 What AndroJack Does
104
104
 
105
- AndroJack is a **documentation-grounded Android engineering MCP server**. It gives your AI coding assistant 20 specialized tools that fetch live, verified answers from official Android and Kotlin sources — instead of predicting from stale training data.
105
+ AndroJack is a **documentation-grounded Android engineering MCP server**. It gives your AI coding assistant 21 specialized tools that fetch live, verified answers from official Android and Kotlin sources — instead of predicting from stale training data.
106
106
 
107
107
  > **It does not make the AI smarter. It makes the AI accountable to evidence.**
108
108
 
109
+ **Think of it as a pre-build linter for LLMs.** While other tools retrieve documentation, AndroJack acts as a strict architectural gatekeeper.
110
+
109
111
  ```
110
112
  Without AndroJack: You ask → AI predicts from stale weights → Code (possibly wrong)
111
113
 
@@ -119,14 +121,199 @@ This is the most important thing to understand before you install AndroJack:
119
121
 
120
122
  | Level | What's Active | What the AI Does |
121
123
  |---|---|---|
122
- | **Level 1** — Tools only installed | 20 tools registered in IDE | AI *may* call the right tool. Depends on the IDE and the AI's judgment. |
123
- | **Level 2** — Tools + Grounding Gate prompt loaded | 20 tools + mandatory rulebook | AI *must* call the correct tool for every decision. No discretion. |
124
+ | **Level 1** — Tools only installed | 21 tools registered in IDE | AI *may* call the right tool. Depends on the IDE and the AI's judgment. |
125
+ | **Level 2** — Tools + Grounding Gate prompt loaded | 21 tools + mandatory pre-generation rulebook | AI *must* call the correct tool for every decision before writing code. |
126
+ | **Level 3** — Level 2 + `android_code_validator` | Full loop: fetch → generate → validate → fix | AI validates every code block against 24 rules. Errors must be fixed before the user sees the code. |
124
127
 
125
128
  **Level 1 is passive.** The tools are available but the AI decides when to use them. An AI building a Compose screen may call `architecture_reference` but skip `material3_expressive` — and ship M3E violations silently.
126
129
 
127
- **Level 2 is active and guaranteed.** The `androjack_grounding_gate` system prompt (registered on the server — instructions below) maps every task type to the correct tool. Building Compose UI? The AI is mandated to call `material3_expressive` first. Adding a dependency? It must call `gradle_dependency_checker`. No exceptions.
130
+ **Level 2 is active.** The `androjack_grounding_gate` system prompt maps every task type to the correct tool. Building Compose UI? The AI is mandated to call `material3_expressive` first. Adding a dependency? It must call `gradle_dependency_checker`. No exceptions.
131
+
132
+ **Level 3 is the loop-back.** `android_code_validator` runs on every code block the AI generates before returning it to the user. 24 rules covering removed APIs, deprecated patterns, and Android 16 compliance. Verdict FAIL means the AI must fix and re-validate — the user never sees the broken code.
133
+
134
+ → **For full grounding, always activate Level 2 + Level 3.** See [Getting the Full Guarantee](#-getting-the-full-guarantee) below.
135
+
136
+ ---
137
+
138
+ ### 🪲 What Can Still Break — Even at Level 3
139
+
140
+ > [!IMPORTANT]
141
+ > **AndroJack is a documentation-grounding and API-validation tool. It is not a Compose layout engine, a design system enforcer, or a runtime renderer.** Level 3 catches removed APIs and deprecated patterns. It cannot catch every class of Android bug. This is not a limitation of AndroJack — it is a fundamental property of static text analysis applied to a visual, runtime-rendered UI framework.
142
+
143
+ The following bugs were encountered in a real Android app built with AndroJack at Level 2 (v1.4.0). They are documented here honestly so you know exactly what to watch for — and where to reach for different tools.
144
+
145
+ #### ✅ What Level 3 Catches
146
+
147
+ These are the bugs AndroJack was designed to prevent. The rule engine fires on these:
148
+
149
+ ```kotlin
150
+ // ❌ REMOVED — android_code_validator fires: REMOVED_ASYNCTASK
151
+ class MyTask : AsyncTask<Void, Void, String>()
152
+
153
+ // ❌ REMOVED — fires: REMOVED_TEST_COROUTINE_DISPATCHER
154
+ val dispatcher = TestCoroutineDispatcher()
155
+
156
+ // ❌ DEPRECATED — fires: DEPRECATED_CONTEXTUAL_FLOW_ROW
157
+ ContextualFlowRow { Text("hello") }
158
+
159
+ // ❌ LEAK — fires: GLOBALSCOPE_LAUNCH
160
+ GlobalScope.launch { fetchData() }
161
+
162
+ // ❌ ANDROID 16 — fires: XML_SCREEN_ORIENTATION_LOCK
163
+ // android:screenOrientation="portrait"
164
+ ```
165
+
166
+ ---
167
+
168
+ #### ⚠️ What Level 3 Cannot Catch — And Why
169
+
170
+ > [!WARNING]
171
+ > The following bugs were found in a real project. They are **valid, API-current Compose code that violates design system constraints, accessibility minimums, or architectural boundaries**. Static text scanning cannot detect them. This is not a gap in AndroJack — it requires a different tool class at a different layer of your quality stack.
172
+
173
+ ---
174
+
175
+ **Bug PH-UI-001 — Segmented button text truncation**
176
+
177
+ ```kotlin
178
+ // Compiles and runs. Level 3 sees no violation.
179
+ // The bug: Text inside MultiChoiceSegmentedButtonRow truncates
180
+ // ("Ligh t", "Drai ned") because a fixed height modifier prevents
181
+ // the Roboto Flex variable font from expanding the container.
182
+
183
+ MultiChoiceSegmentedButtonRow {
184
+ SegmentedButton(/* fixed height modifier */) {
185
+ Text("Light") // truncates at runtime on variable font sizes
186
+ }
187
+ }
188
+
189
+ // Fix: Replace fixed height with Modifier.wrapContentHeight() + heightIn(min = 48.dp)
190
+ ```
191
+
192
+ > [!NOTE]
193
+ > **This is an absence bug.** The correct modifier is missing — no wrong one is present. RegExp pattern matching detects patterns that exist in code. Absence is significantly harder for static analysis to detect and often requires structural rules or runtime validation rather than text-level pattern matching.
194
+
195
+ ---
196
+
197
+ **Bug PH-UI-003 — Disabled button contrast failure**
198
+
199
+ ```kotlin
200
+ // Correct Material 3 API. Level 3 sees no violation.
201
+ // The bug: disabled state colours fail WCAG AA 4.5:1 contrast ratio
202
+ // against the dark theme surface — but only visible when rendered.
203
+
204
+ Button(enabled = false, onClick = {}) {
205
+ Text("INITIALIZE VAULT") // illegible dark grey on dark grey surface
206
+ }
207
+
208
+ // Fix: Override ButtonDefaults.buttonColors(
209
+ // disabledContainerColor = ...,
210
+ // disabledContentColor = ...
211
+ // ) to achieve minimum 4.5:1 against MaterialTheme.colorScheme.surface
212
+ ```
213
+
214
+ > [!NOTE]
215
+ > **This is a runtime visual property bug.** A 4.5:1 contrast ratio only exists when the theming engine renders against a surface colour. Contrast validation requires rendering or screenshot-based testing rather than source text analysis. Use `paparazzi` screenshot tests or Google's Accessibility Scanner.
216
+
217
+ ---
218
+
219
+ **Bug PH-AR-004 — Raw stack trace rendered to end user**
220
+
221
+ ```kotlin
222
+ // The AI generated a ViewModel without catching the domain exception.
223
+ // Level 3 fires only if a flagged API (e.g. GlobalScope) caused the leak.
224
+ // A plain missing try/catch produces no pattern match.
128
225
 
129
- **For full grounding, always activate Level 2.** See [Getting the Full Guarantee](#-getting-the-full-guarantee) below.
226
+ class VaultViewModel : ViewModel() {
227
+ fun initializeVault() {
228
+ viewModelScope.launch {
229
+ val result = repository.initialize()
230
+ // Missing try/catch — LiteRT exception propagates to UI
231
+ _uiState.value = UiState.Success(result)
232
+ }
233
+ }
234
+ }
235
+ // What the user saw: "LiteRT initialization failed: ByteBuffer is not a
236
+ // valid TensorFlow Lite model flatbuffer" — raw crash text in the UI.
237
+
238
+ // Fix: Wrap in try/catch, emit UiState.Error with a user-friendly string resource.
239
+ ```
240
+
241
+ > [!WARNING]
242
+ > **UDF architecture boundary violations require architectural linting, not API pattern matching.** A missing `try/catch` has no detectable pattern. Use [Detekt](https://detekt.dev) with custom architecture rules, or write a ViewModel unit test that verifies exception mapping to `UiState.Error`.
243
+
244
+ ---
245
+
246
+ **Bug PH-UX-008 — Consent checkbox tap target too small**
247
+
248
+ ```kotlin
249
+ // Valid Compose code. Level 3 sees no violation.
250
+ // The bug: Modifier.toggleable scoped to the Checkbox icon only —
251
+ // tappable area is ~24dp instead of the required 48dp minimum.
252
+
253
+ Row {
254
+ Checkbox(
255
+ checked = isChecked,
256
+ onCheckedChange = { isChecked = it } // toggleable on icon only
257
+ )
258
+ Text("I agree to the terms") // not tappable — users miss the target
259
+ }
260
+
261
+ // Fix: Hoist Modifier.toggleable to the parent Row.
262
+ // The entire Row (icon + text) becomes the touch target.
263
+ ```
264
+
265
+ > [!NOTE]
266
+ > **Structural placement bugs require AST-level analysis.** The API is used correctly — in the wrong structural position. Detecting this requires understanding the composable tree, not the line in isolation. This is on the roadmap for a future `android_code_validator` AST extension.
267
+
268
+ ---
269
+
270
+ **Bug PH-UI-009 — Scaffold inner padding ignored**
271
+
272
+ ```kotlin
273
+ // Compiles and runs. Bottom content scrolls behind the navigation bar.
274
+ // Level 3 sees no violation — all APIs are correct and current.
275
+
276
+ Scaffold { innerPadding ->
277
+ LazyColumn(
278
+ // Missing: contentPadding = innerPadding
279
+ ) {
280
+ items(data) { ItemRow(it) } // bottom items cut off by BottomAppBar
281
+ }
282
+ }
283
+
284
+ // Fix: LazyColumn(contentPadding = innerPadding)
285
+ ```
286
+
287
+ > [!NOTE]
288
+ > **Unused-variable class bugs require data-flow analysis.** `innerPadding` is captured but never consumed. Android Lint's `UnusedVariable` rule and Android Studio's own live inspector flag this. It is not in scope for MCP-layer validation.
289
+
290
+ ---
291
+
292
+ ### 🗂️ Defence-in-Depth: The Right Tool for Each Bug Class
293
+
294
+ > [!IMPORTANT]
295
+ > AndroJack is one layer in a quality stack. Each layer catches what only it can catch. No single tool covers all four.
296
+
297
+ | Bug Class | Real Example | Right Tool |
298
+ |---|---|---|
299
+ | Removed / deprecated API | `AsyncTask`, `TestCoroutineDispatcher`, `ContextualFlowRow` | ✅ **AndroJack Level 3** |
300
+ | Android 16 manifest violations | `screenOrientation`, `resizeableActivity=false` | ✅ **AndroJack Level 3** |
301
+ | Architecture violation (flagged root cause) | `GlobalScope` leaking to UI | ✅ **AndroJack Level 3** |
302
+ | Absent modifier / missing constraint | PH-UI-001 (wrapContentHeight), PH-UI-009 (innerPadding) | 🔧 Android Lint / IDE inspector |
303
+ | Runtime contrast / colour failures | PH-UI-003 (disabled button WCAG) | 🔧 `paparazzi` + Accessibility Scanner |
304
+ | Touch target violations | PH-UI-002, PH-UX-008 | 🔧 Accessibility Scanner |
305
+ | Structural placement (wrong hierarchy) | PH-UX-008 (toggleable on wrong composable) | 🔧 Android Lint / future AST rule |
306
+ | Architecture boundary (missing try/catch) | PH-AR-004 (stack trace to UI) | 🔧 Detekt + ViewModel unit tests |
307
+ | M3 design system aesthetic | PH-UI-007 (corner radius), PH-UI-006 (casing) | 🔧 Design review / Figma handoff |
308
+
309
+ ---
310
+
311
+ ### Why MCP Is Not at Fault for Any of This
312
+
313
+ > [!NOTE]
314
+ > **MCP is a transport protocol.** It specifies how an AI client and a tool server exchange structured messages — nothing more. Blaming MCP for not catching a missing `contentPadding` in `DropdownMenuItem` is equivalent to blaming TCP/IP for a badly designed website. The protocol carried the message correctly.
315
+ >
316
+ > Anthropic donated MCP to the Linux Foundation in December 2025 — co-founded with OpenAI, Block, Google, Microsoft, and AWS — precisely because a neutral protocol does not encode domain-specific rules. HTTP does not enforce WCAG. gRPC does not enforce Material 3. MCP does not enforce Compose modifier semantics. That is what makes it universal. AndroJack exists as a specialised layer *on top of* MCP — it is not a replacement for runtime testing, accessibility auditing, or design system review.
130
317
 
131
318
  ---
132
319
 
@@ -282,15 +469,25 @@ Each tool lists the **specific failure mode it prevents** — not just what it d
282
469
  | 18 | 📋 `android_play_policy_advisor` | Play Store policies — age-gating, health apps, loan apps, subscription UI, data safety, Oct 2025 changes | Apps rejected at review for policy violations the developer didn't know existed |
283
470
  | 19 | 🥽 `android_xr_guide` | Android XR SDK (DP3), Compose for XR — Subspace, SpatialPanel, UserSubspace, SceneCore, ARCore for XR | Standard 2D Compose in an XR app — works but misses spatial capabilities entirely |
284
471
  | 20 | ⌚ `android_wearos_guide` | Wear OS — Tiles, Complications, Health Services, ambient mode, `WearApp` scaffold, M3 Expressive for Wear | Handheld UI patterns on a 40mm round display; missing Tiles API; battery-draining background patterns |
472
+ | 21 | 🛡️ `android_code_validator` | **Level 3 loop-back gate.** Validates AI-generated Kotlin, XML, and Gradle against 24 Android rules. Returns PASS/WARN/FAIL verdict, line-level violations with replacements and doc URLs. Called automatically after code generation. | The AI generates code and returns it — no validation pass. Errors only discovered at runtime, in CI, or at Play Store review. |
473
+
474
+ > **All 21 tools are read-only.** AndroJack fetches and returns information — it never modifies your project files.
475
+
476
+
477
+ ---
285
478
 
286
- > **All 20 tools are read-only.** AndroJack fetches and returns information — it never modifies your project files.
479
+ ## 🎯 Google's Own Recommendation (March 2026)
287
480
 
481
+ > *"To prevent the model from hallucinating code for niche or brand-new libraries, leverage Android Studio's Agent tools to have access to documentation… install a MCP Server that lets you access documentation like Context7 (or something similar)."*
482
+ > — **Android Studio Team, Official Android Developer Blog, March 2026**
483
+
484
+ **That MCP server is AndroJack** — purpose-built for Android, with 21 tools and a mandatory validation loop that no generic doc-retrieval tool provides.
288
485
 
289
486
  ---
290
487
 
291
488
  ## 🚀 Quick Start — Zero Install Required
292
489
 
293
- ### Option 1 — Interactive CLI (v1.4.0) ✨ Recommended
490
+ ### Option 1 — Interactive CLI (v1.5.0) ✨ Recommended
294
491
 
295
492
  ```bash
296
493
  npx androjack-mcp install
@@ -470,7 +667,7 @@ You: Build a login screen with ViewModel and Jetpack Compose
470
667
  → architecture_reference("mvvm")
471
668
  → material3_expressive("theme setup")
472
669
  → kotlin_best_practices("stateflow-ui")
473
- → gradle_dependency_checker("compose") → BOM 2025.05.01 / ui:1.11.0-alpha06
670
+ → gradle_dependency_checker("compose") → BOM 2026.02.01 / ui:1.8.0
474
671
  → gradle_dependency_checker("lifecycle") → lifecycle-viewmodel-ktx:2.11.0-alpha01
475
672
  → android_api_level_check("26") ✅ covers ~90% devices
476
673
  → android_permission_advisor("INTERNET") 🟢 normal — no runtime request
@@ -481,17 +678,38 @@ AI produces:
481
678
  ✅ Official MVVM + M3 Expressive theming
482
679
  ✅ StateFlow instead of LiveData in new code
483
680
  ✅ Source URL cited on every code block
681
+
682
+ → android_code_validator(generatedCode, "kotlin", 24, 36)
683
+ ✅ PASS — 0 errors, 0 warnings (code is grounded and rule-compliant)
484
684
  ```
485
685
 
486
686
  ---
487
687
 
488
- ## 📍 The Market Gap Why Nothing Else Does This
688
+ ## 📍 The Ecosystem: AndroJack vs. Other MCPs
689
+
690
+ ### 1. vs. Device Automation MCPs
691
+ Most Android MCP servers in the public registry (`minhalvp/android-mcp-server`, `CursorTouch/Android-MCP`) do the same thing: **ADB device control**. They tap screens and capture screenshots for QA testing. Not one of them knows what a `ViewModel` is or can distinguish Navigation 3 from Navigation 2. AndroJack owns the engineering and architecture category.
692
+
693
+ ### 2. vs. Google's Official Developer Knowledge MCP (Public Preview, Feb 2026)
694
+ In February 2026, Google launched the Developer Knowledge MCP in public preview — a generalist tool that retrieves Markdown from its documentation corpus covering Firebase, Android, Google Cloud, Maps, and more. You might ask: *Does this replace AndroJack?*
695
+
696
+ **No. They solve two different halves of the AI coding problem.**
489
697
 
490
- Every other Android MCP server in the public registry (minhalvp/android-mcp-server, CursorTouch/Android-MCP, mobile-mcp by mobile-next) does the same thing: **ADB device control**. They tap screens, capture screenshots, send keystrokes, and run UIAutomator2 queries. They are excellent QA automation tools. Not one of them knows what a `ViewModel` is. Not one can tell you whether a Gradle coordinate is current. Not one can distinguish Navigation 3 from Navigation 2.
698
+ | Feature | Google Developer Knowledge MCP | AndroJack MCP |
699
+ | :--- | :--- | :--- |
700
+ | **Identity** | **The Librarian** (Information) | **The Gatekeeper** (Enforcement) |
701
+ | **Core Job** | Feeds the AI the newest documentation so it knows what exists. | Acts as a strict pre-build linter to enforce modern architectural rules. |
702
+ | **Mechanism** | Context Retrieval | Context Enforcement |
703
+ | **Scope** | Generalist — Firebase, Cloud, Android, Maps, and more | Android specialist — 21 tools, one domain, zero drift |
704
+ | **Tools** | 3 retrieval tools (`search_documents`, `get_document`, `batch_get_documents`) | 21 specialized tools — live version checks, deprecation registry, Gradle lookups, API level validation, loop-back code validator |
705
+ | **Setup** | Google Cloud project + API key + `gcloud` CLI required | `npx androjack-mcp` — zero auth, zero cloud project |
706
+ | **Enforcement** | Passive — AI decides when to retrieve | Active — tool descriptions mandate calls before every task type |
707
+ | **Status** | Public preview (v1alpha / experimental) | Stable (v1.5.0) |
491
708
 
492
- AndroJack owns the only unclaimed category in the Android MCP ecosystem: **documentation-grounded Android engineering guidance** — the trust layer that AI coding assistants call when they need to verify whether an API actually exists, whether a dependency version is current, and whether a pattern is still the official recommendation.
709
+ **Why you need both in production:**
710
+ Google's tool cures AI "ignorance" by providing official text. However, **AndroJack cures AI "bad habits."** If you ask an AI to refactor an app, Google's tool will provide the new docs. But **AndroJack** is the tool that actively blocks the AI from writing legacy XML, enforces Jetpack Compose, checks Gradle versions against Maven, and ensures your `minSdk` doesn't violate Android 16's Play Store mandate.
493
711
 
494
- Android Studio added MCP support on January 15, 2026. The window between "first Android doc-grounded MCP" and "Google ships one themselves" is the window AndroJack is built to fill.
712
+ Google tells the AI the rules; **AndroJack forces the AI to follow them.**
495
713
 
496
714
  ---
497
715
 
@@ -504,7 +722,7 @@ Android Studio added MCP support on January 15, 2026. The window between "first
504
722
  | **No credentials** | Zero API keys, zero auth tokens required |
505
723
  | **No data stored** | Nothing persisted beyond process lifetime |
506
724
  | **Transparent agent** | User-Agent: `AndroJack-MCP/1.4 (documentation-grounding bot; not-a-scraper)` |
507
- | **Read-only** | All 20 tools are annotated `readOnlyHint: true` — no writes, no side effects |
725
+ | **Read-only** | All 21 tools are annotated `readOnlyHint: true` — no writes, no side effects |
508
726
  | **Input bounds** | All inputs length-capped and sanitized before use |
509
727
  | **Body size cap** | HTTP responses capped at 4 MB — no OOM risk on large documentation pages |
510
728
 
@@ -574,8 +792,10 @@ npm run install-mcp:list # check IDE detection status
574
792
 
575
793
  ## 📋 Changelog
576
794
 
577
- ### v1.4.0 — Interactive CLI Installer
795
+ ### v1.5.0 — Level 3 Loop-Back Validator + Interactive CLI Installer
578
796
 
797
+ - **New:** `android_code_validator` (Tool 21) — Level 3 loop-back validation gate. 24 rules across Kotlin, XML, and Gradle. Validates AI-generated code before it reaches the user. Returns PASS/WARN/FAIL verdict with line-level violations, replacements, and official doc URLs. Zero new dependencies — pure TypeScript.
798
+ - **New:** Grounding Gate upgraded to Level 3: Step 8 mandates `android_code_validator` after every code generation. Negative constraints section lists explicit prohibitions by API level (Android 16 targets, new Compose projects, universal rules).
579
799
  - **New:** Animated `figlet` ASCII-art banner with cyan→purple gradient and Android fixes tagline
580
800
  (`Gradle · ViewModel · Room · Compose · Navigation · Hilt · WorkManager`)
581
801
  - **New:** `@clack/prompts` arrow-key select + checkbox multiselect — no more typing numbers
package/build/cache.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Simple LRU cache implementation for AndroJack MCP.
3
+ */
4
+ export class LRUCache {
5
+ cache = new Map();
6
+ ttlMs = 24 * 60 * 60 * 1000; // 24 hours default
7
+ maxSize = 100;
8
+ // Stats
9
+ hits = 0;
10
+ misses = 0;
11
+ evictions = 0;
12
+ constructor(maxSize = 100) {
13
+ this.maxSize = maxSize;
14
+ }
15
+ setTtl(ttlMs) {
16
+ this.ttlMs = ttlMs;
17
+ }
18
+ clear() {
19
+ this.cache.clear();
20
+ this.hits = 0;
21
+ this.misses = 0;
22
+ this.evictions = 0;
23
+ }
24
+ stats() {
25
+ const totalRequests = this.hits + this.misses;
26
+ const hitRatePercent = totalRequests === 0
27
+ ? "0.00"
28
+ : ((this.hits / totalRequests) * 100).toFixed(2);
29
+ return {
30
+ size: this.cache.size,
31
+ hits: this.hits,
32
+ misses: this.misses,
33
+ evictions: this.evictions,
34
+ hitRatePercent,
35
+ };
36
+ }
37
+ get(key) {
38
+ if (this.ttlMs === 0) {
39
+ this.misses++;
40
+ return undefined;
41
+ }
42
+ const entry = this.cache.get(key);
43
+ if (!entry) {
44
+ this.misses++;
45
+ return undefined;
46
+ }
47
+ if (Date.now() - entry.timestamp > this.ttlMs) {
48
+ this.cache.delete(key);
49
+ this.misses++;
50
+ return undefined;
51
+ }
52
+ // Refresh LRU order by deleting and re-inserting
53
+ this.cache.delete(key);
54
+ this.cache.set(key, entry);
55
+ this.hits++;
56
+ return entry.value;
57
+ }
58
+ set(key, value) {
59
+ if (this.ttlMs === 0)
60
+ return;
61
+ if (this.cache.has(key)) {
62
+ this.cache.delete(key);
63
+ }
64
+ else if (this.cache.size >= this.maxSize) {
65
+ // Evict oldest (first item in Map)
66
+ const firstKey = this.cache.keys().next().value;
67
+ if (firstKey) {
68
+ this.cache.delete(firstKey);
69
+ this.evictions++;
70
+ }
71
+ }
72
+ this.cache.set(key, { value, timestamp: Date.now() });
73
+ }
74
+ }
75
+ export const docCache = new LRUCache(200);
@@ -45,7 +45,7 @@ export async function startHttpServer(server) {
45
45
  res.writeHead(200, { "Content-Type": "application/json" });
46
46
  res.end(JSON.stringify({
47
47
  name: "androjack-mcp",
48
- version: "1.4.0",
48
+ version: "1.5.0",
49
49
  description: "Documentation-grounded Android engineering MCP server. " +
50
50
  "Forces AI tools to verify official docs before generating Android/Kotlin code.",
51
51
  mcp_endpoint: `http://${host}:${port}${MCP_PATH}`,
package/build/index.js CHANGED
@@ -35,10 +35,11 @@ import { androidOnDeviceAiGuide } from "./tools/ondevice-ai.js";
35
35
  import { androidPlayPolicyAdvisor } from "./tools/play-policy.js";
36
36
  import { androidXrGuide } from "./tools/xr.js";
37
37
  import { androidWearOsGuide } from "./tools/wear.js";
38
+ import { androidCodeValidator } from "./tools/validator.js";
38
39
  // ── Server Instantiation ────────────────────────────────────────────────────
39
40
  const server = new McpServer({
40
41
  name: "androjack-mcp",
41
- version: "1.4.0",
42
+ version: "1.5.0",
42
43
  });
43
44
  // ── Tool 1: Official Android Documentation Search ──────────────────────────
44
45
  server.registerTool("android_official_search", {
@@ -260,15 +261,42 @@ Before writing ANY Android or Kotlin code, you MUST follow this sequence:
260
261
  5. **API LEVEL** — Call \`android_api_level_check\` if you are unsure about minSdk compatibility.
261
262
  6. **PATTERNS** — Call \`kotlin_best_practices\` for idiomatic coroutine, Flow, or Compose patterns.
262
263
  7. **DEBUG** — Call \`android_debugger\` for any stacktrace before proposing a fix.
264
+ 8. **VALIDATE OUTPUT** — Call \`android_code_validator\` on EVERY code block you generate before returning it to the user. If verdict is FAIL, fix all errors and re-run until PASS or WARN.
263
265
 
264
266
  ## HARD RULES — NO EXCEPTIONS
265
267
 
266
268
  - You CANNOT generate Android code without first retrieving official documentation evidence.
269
+ - You CANNOT return code to the user without first passing it through \`android_code_validator\`.
267
270
  - You CANNOT use any deprecated API (status: deprecated or removed) without explicit user acknowledgement.
268
271
  - Every code response MUST cite the official doc URL it was grounded in.
269
272
  - If a tool call fails, say so explicitly — do not fall back to training memory.
270
273
  - No hallucinated API names, method signatures, or Gradle coordinates.
271
274
 
275
+ ## NEGATIVE CONSTRAINTS BY API LEVEL
276
+
277
+ These are hard prohibitions. Generate none of the following without explicit user override:
278
+
279
+ **All targets (universal):**
280
+ - NEVER generate \`AsyncTask\` — removed API 33, crashes on modern devices
281
+ - NEVER generate \`TestCoroutineDispatcher\` — removed coroutines-test 1.8+, breaks CI
282
+ - NEVER generate \`TestCoroutineScope\` — removed, use \`runTest { }\` block
283
+ - NEVER generate \`GlobalScope.launch\` or \`GlobalScope.async\` — leaks coroutines
284
+ - NEVER generate \`ContextualFlowRow\` or \`ContextualFlowColumn\` — deprecated Compose 1.8
285
+ - NEVER generate \`Thread.sleep()\` in tests — causes flaky test failures
286
+ - NEVER generate \`startActivityForResult()\` — use \`registerForActivityResult()\`
287
+ - NEVER generate \`IntentService\` — deprecated API 30, use WorkManager or coroutines
288
+ - NEVER generate \`runBlocking { }\` on a UI/main thread — causes ANR
289
+
290
+ **targetSdk ≥ 36 (Android 16 mandate, Play Store August 2026):**
291
+ - NEVER generate \`android:screenOrientation="portrait"\` or any orientation lock in manifests
292
+ - NEVER generate \`android:resizeableActivity="false"\`
293
+ - Always verify large-screen compliance with \`android_api36_compliance\` before finalising
294
+
295
+ **New Compose projects (not migrating legacy):**
296
+ - NEVER generate \`rememberNavController()\` or \`NavHost()\` — use Navigation 3 (\`rememberNavBackStack\`, \`NavDisplay\`)
297
+ - NEVER generate \`MutableLiveData\` — use \`MutableStateFlow\`
298
+ - NEVER generate \`kapt\` annotation processing — use \`ksp\`
299
+
272
300
  ## CRITICAL INVARIANTS FOR 2025-2026 CODE
273
301
 
274
302
  NAVIGATION: For any new Compose navigation, use Navigation 3 (stable Nov 2025).
@@ -529,7 +557,36 @@ server.registerTool("android_wearos_guide", {
529
557
  }, async ({ topic }) => ({
530
558
  content: [{ type: "text", text: await androidWearOsGuide(topic ?? "overview") }],
531
559
  }));
532
- // ── Server Startup ──────────────────────────────────────────────────────────
560
+ // ── Tool 21: Android Code Validator (Level 3 Loop-Back) ───────────────────
561
+ server.registerTool("android_code_validator", {
562
+ title: "Android Code Validator",
563
+ description: "CALL THIS AFTER GENERATING EVERY ANDROID CODE BLOCK. " +
564
+ "This is the Level 3 loop-back gate: validates AI-generated Kotlin, XML, and Gradle code " +
565
+ "against 24 Android-specific rules before the user sees it. " +
566
+ "Detects removed APIs (AsyncTask, TestCoroutineDispatcher), deprecated patterns " +
567
+ "(ContextualFlowRow, NavController in new code, SharedPreferences), Android 16 violations " +
568
+ "(orientation locks, resizeableActivity=false), and structural issues (GlobalScope.launch, runBlocking in UI). " +
569
+ "Returns: verdict (PASS/WARN/FAIL), line-level violations with replacements and doc URLs, " +
570
+ "and explicit next-step instructions. " +
571
+ "If verdict is FAIL: fix all errors and re-run before returning code to the user. " +
572
+ "Inputs: code (required), language ('kotlin'|'xml'|'gradle', auto-detected if omitted), " +
573
+ "minSdk and targetSdk for context-aware API level checks.",
574
+ inputSchema: {
575
+ code: z.string().min(1).max(50_000).describe("The code block to validate"),
576
+ language: z.enum(["kotlin", "xml", "gradle"]).optional()
577
+ .describe("File type — auto-detected from content if omitted"),
578
+ minSdk: z.number().int().min(1).max(40).optional()
579
+ .describe("App minSdk for API level context (e.g. 24)"),
580
+ targetSdk: z.number().int().min(1).max(40).optional()
581
+ .describe("App targetSdk for API 36 compliance checks (e.g. 36)"),
582
+ },
583
+ annotations: { readOnlyHint: true },
584
+ }, async ({ code, language, minSdk, targetSdk }) => ({
585
+ content: [{
586
+ type: "text",
587
+ text: await androidCodeValidator(code, language, minSdk, targetSdk),
588
+ }],
589
+ }));
533
590
  // All tools/prompts must be registered above this point.
534
591
  // Pass --http to start Streamable HTTP transport instead of stdio.
535
592
  async function main() {