android-adb-mcp 0.1.0__tar.gz

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.
Files changed (209) hide show
  1. android_adb_mcp-0.1.0/.claude/CLAUDE.md +105 -0
  2. android_adb_mcp-0.1.0/.claude/agents/architecture-reviewer.md +60 -0
  3. android_adb_mcp-0.1.0/.claude/agents/module-implementer.md +85 -0
  4. android_adb_mcp-0.1.0/.github/workflows/ci.yml +61 -0
  5. android_adb_mcp-0.1.0/.github/workflows/publish.yml +27 -0
  6. android_adb_mcp-0.1.0/.gitignore +65 -0
  7. android_adb_mcp-0.1.0/LICENSE +21 -0
  8. android_adb_mcp-0.1.0/PKG-INFO +73 -0
  9. android_adb_mcp-0.1.0/README.md +45 -0
  10. android_adb_mcp-0.1.0/docs/ADR.md +536 -0
  11. android_adb_mcp-0.1.0/docs/ARCHITECTURE.md +502 -0
  12. android_adb_mcp-0.1.0/docs/assets/extra.css +30 -0
  13. android_adb_mcp-0.1.0/docs/assets/extra.js +64 -0
  14. android_adb_mcp-0.1.0/docs/index.md +60 -0
  15. android_adb_mcp-0.1.0/docs/integrations/claude-code.md +21 -0
  16. android_adb_mcp-0.1.0/docs/reference/activities.md +8 -0
  17. android_adb_mcp-0.1.0/docs/reference/android_services.md +9 -0
  18. android_adb_mcp-0.1.0/docs/reference/app_data.md +8 -0
  19. android_adb_mcp-0.1.0/docs/reference/broadcasts.md +6 -0
  20. android_adb_mcp-0.1.0/docs/reference/connection.md +7 -0
  21. android_adb_mcp-0.1.0/docs/reference/date_time.md +9 -0
  22. android_adb_mcp-0.1.0/docs/reference/device_info.md +5 -0
  23. android_adb_mcp-0.1.0/docs/reference/diagnostics.md +7 -0
  24. android_adb_mcp-0.1.0/docs/reference/displays.md +6 -0
  25. android_adb_mcp-0.1.0/docs/reference/files.md +7 -0
  26. android_adb_mcp-0.1.0/docs/reference/input.md +6 -0
  27. android_adb_mcp-0.1.0/docs/reference/logger.md +6 -0
  28. android_adb_mcp-0.1.0/docs/reference/network.md +7 -0
  29. android_adb_mcp-0.1.0/docs/reference/packages.md +6 -0
  30. android_adb_mcp-0.1.0/docs/reference/permissions.md +7 -0
  31. android_adb_mcp-0.1.0/docs/reference/power.md +7 -0
  32. android_adb_mcp-0.1.0/docs/reference/processes.md +7 -0
  33. android_adb_mcp-0.1.0/docs/reference/screen.md +8 -0
  34. android_adb_mcp-0.1.0/docs/reference/settings.md +7 -0
  35. android_adb_mcp-0.1.0/docs/reference/system_properties.md +8 -0
  36. android_adb_mcp-0.1.0/docs/reference/ui.md +8 -0
  37. android_adb_mcp-0.1.0/docs/reference/user.md +6 -0
  38. android_adb_mcp-0.1.0/mkdocs.yml +114 -0
  39. android_adb_mcp-0.1.0/pyproject.toml +101 -0
  40. android_adb_mcp-0.1.0/server.json +22 -0
  41. android_adb_mcp-0.1.0/src/adb_mcp/__init__.py +1 -0
  42. android_adb_mcp-0.1.0/src/adb_mcp/__main__.py +4 -0
  43. android_adb_mcp-0.1.0/src/adb_mcp/backend/__init__.py +0 -0
  44. android_adb_mcp-0.1.0/src/adb_mcp/backend/protocol.py +64 -0
  45. android_adb_mcp-0.1.0/src/adb_mcp/backend/subprocess_backend.py +126 -0
  46. android_adb_mcp-0.1.0/src/adb_mcp/backend/testing.py +644 -0
  47. android_adb_mcp-0.1.0/src/adb_mcp/errors.py +275 -0
  48. android_adb_mcp-0.1.0/src/adb_mcp/modules/__init__.py +0 -0
  49. android_adb_mcp-0.1.0/src/adb_mcp/modules/activities/__init__.py +0 -0
  50. android_adb_mcp-0.1.0/src/adb_mcp/modules/activities/manifest.py +17 -0
  51. android_adb_mcp-0.1.0/src/adb_mcp/modules/activities/service.py +178 -0
  52. android_adb_mcp-0.1.0/src/adb_mcp/modules/activities/tools.py +107 -0
  53. android_adb_mcp-0.1.0/src/adb_mcp/modules/android_services/__init__.py +0 -0
  54. android_adb_mcp-0.1.0/src/adb_mcp/modules/android_services/manifest.py +17 -0
  55. android_adb_mcp-0.1.0/src/adb_mcp/modules/android_services/service.py +112 -0
  56. android_adb_mcp-0.1.0/src/adb_mcp/modules/android_services/tools.py +78 -0
  57. android_adb_mcp-0.1.0/src/adb_mcp/modules/app_data/__init__.py +0 -0
  58. android_adb_mcp-0.1.0/src/adb_mcp/modules/app_data/manifest.py +17 -0
  59. android_adb_mcp-0.1.0/src/adb_mcp/modules/app_data/service.py +105 -0
  60. android_adb_mcp-0.1.0/src/adb_mcp/modules/app_data/tools.py +75 -0
  61. android_adb_mcp-0.1.0/src/adb_mcp/modules/broadcasts/__init__.py +0 -0
  62. android_adb_mcp-0.1.0/src/adb_mcp/modules/broadcasts/manifest.py +17 -0
  63. android_adb_mcp-0.1.0/src/adb_mcp/modules/broadcasts/service.py +163 -0
  64. android_adb_mcp-0.1.0/src/adb_mcp/modules/broadcasts/tools.py +106 -0
  65. android_adb_mcp-0.1.0/src/adb_mcp/modules/connection/__init__.py +0 -0
  66. android_adb_mcp-0.1.0/src/adb_mcp/modules/connection/manifest.py +22 -0
  67. android_adb_mcp-0.1.0/src/adb_mcp/modules/connection/service.py +171 -0
  68. android_adb_mcp-0.1.0/src/adb_mcp/modules/connection/tools.py +226 -0
  69. android_adb_mcp-0.1.0/src/adb_mcp/modules/date_time/__init__.py +0 -0
  70. android_adb_mcp-0.1.0/src/adb_mcp/modules/date_time/manifest.py +17 -0
  71. android_adb_mcp-0.1.0/src/adb_mcp/modules/date_time/service.py +110 -0
  72. android_adb_mcp-0.1.0/src/adb_mcp/modules/date_time/tools.py +67 -0
  73. android_adb_mcp-0.1.0/src/adb_mcp/modules/device_info/__init__.py +0 -0
  74. android_adb_mcp-0.1.0/src/adb_mcp/modules/device_info/manifest.py +22 -0
  75. android_adb_mcp-0.1.0/src/adb_mcp/modules/device_info/service.py +33 -0
  76. android_adb_mcp-0.1.0/src/adb_mcp/modules/device_info/tools.py +43 -0
  77. android_adb_mcp-0.1.0/src/adb_mcp/modules/diagnostics/__init__.py +0 -0
  78. android_adb_mcp-0.1.0/src/adb_mcp/modules/diagnostics/manifest.py +17 -0
  79. android_adb_mcp-0.1.0/src/adb_mcp/modules/diagnostics/service.py +46 -0
  80. android_adb_mcp-0.1.0/src/adb_mcp/modules/diagnostics/tools.py +49 -0
  81. android_adb_mcp-0.1.0/src/adb_mcp/modules/displays/__init__.py +0 -0
  82. android_adb_mcp-0.1.0/src/adb_mcp/modules/displays/manifest.py +16 -0
  83. android_adb_mcp-0.1.0/src/adb_mcp/modules/displays/service.py +15 -0
  84. android_adb_mcp-0.1.0/src/adb_mcp/modules/files/__init__.py +0 -0
  85. android_adb_mcp-0.1.0/src/adb_mcp/modules/files/manifest.py +32 -0
  86. android_adb_mcp-0.1.0/src/adb_mcp/modules/files/service.py +111 -0
  87. android_adb_mcp-0.1.0/src/adb_mcp/modules/files/tools.py +73 -0
  88. android_adb_mcp-0.1.0/src/adb_mcp/modules/input/__init__.py +0 -0
  89. android_adb_mcp-0.1.0/src/adb_mcp/modules/input/manifest.py +17 -0
  90. android_adb_mcp-0.1.0/src/adb_mcp/modules/input/service.py +78 -0
  91. android_adb_mcp-0.1.0/src/adb_mcp/modules/input/tools.py +70 -0
  92. android_adb_mcp-0.1.0/src/adb_mcp/modules/logger/__init__.py +0 -0
  93. android_adb_mcp-0.1.0/src/adb_mcp/modules/logger/manifest.py +45 -0
  94. android_adb_mcp-0.1.0/src/adb_mcp/modules/logger/service.py +374 -0
  95. android_adb_mcp-0.1.0/src/adb_mcp/modules/logger/tools.py +392 -0
  96. android_adb_mcp-0.1.0/src/adb_mcp/modules/network/__init__.py +0 -0
  97. android_adb_mcp-0.1.0/src/adb_mcp/modules/network/manifest.py +17 -0
  98. android_adb_mcp-0.1.0/src/adb_mcp/modules/network/service.py +143 -0
  99. android_adb_mcp-0.1.0/src/adb_mcp/modules/network/tools.py +66 -0
  100. android_adb_mcp-0.1.0/src/adb_mcp/modules/packages/__init__.py +0 -0
  101. android_adb_mcp-0.1.0/src/adb_mcp/modules/packages/manifest.py +17 -0
  102. android_adb_mcp-0.1.0/src/adb_mcp/modules/packages/service.py +80 -0
  103. android_adb_mcp-0.1.0/src/adb_mcp/modules/packages/tools.py +64 -0
  104. android_adb_mcp-0.1.0/src/adb_mcp/modules/permissions/__init__.py +0 -0
  105. android_adb_mcp-0.1.0/src/adb_mcp/modules/permissions/manifest.py +17 -0
  106. android_adb_mcp-0.1.0/src/adb_mcp/modules/permissions/service.py +127 -0
  107. android_adb_mcp-0.1.0/src/adb_mcp/modules/permissions/tools.py +78 -0
  108. android_adb_mcp-0.1.0/src/adb_mcp/modules/power/__init__.py +0 -0
  109. android_adb_mcp-0.1.0/src/adb_mcp/modules/power/manifest.py +17 -0
  110. android_adb_mcp-0.1.0/src/adb_mcp/modules/power/service.py +94 -0
  111. android_adb_mcp-0.1.0/src/adb_mcp/modules/power/tools.py +66 -0
  112. android_adb_mcp-0.1.0/src/adb_mcp/modules/processes/__init__.py +0 -0
  113. android_adb_mcp-0.1.0/src/adb_mcp/modules/processes/manifest.py +17 -0
  114. android_adb_mcp-0.1.0/src/adb_mcp/modules/processes/service.py +80 -0
  115. android_adb_mcp-0.1.0/src/adb_mcp/modules/processes/tools.py +73 -0
  116. android_adb_mcp-0.1.0/src/adb_mcp/modules/screen/__init__.py +0 -0
  117. android_adb_mcp-0.1.0/src/adb_mcp/modules/screen/manifest.py +32 -0
  118. android_adb_mcp-0.1.0/src/adb_mcp/modules/screen/service.py +182 -0
  119. android_adb_mcp-0.1.0/src/adb_mcp/modules/screen/tools.py +81 -0
  120. android_adb_mcp-0.1.0/src/adb_mcp/modules/settings/__init__.py +0 -0
  121. android_adb_mcp-0.1.0/src/adb_mcp/modules/settings/manifest.py +17 -0
  122. android_adb_mcp-0.1.0/src/adb_mcp/modules/settings/service.py +110 -0
  123. android_adb_mcp-0.1.0/src/adb_mcp/modules/settings/tools.py +79 -0
  124. android_adb_mcp-0.1.0/src/adb_mcp/modules/system_properties/__init__.py +0 -0
  125. android_adb_mcp-0.1.0/src/adb_mcp/modules/system_properties/manifest.py +27 -0
  126. android_adb_mcp-0.1.0/src/adb_mcp/modules/system_properties/service.py +215 -0
  127. android_adb_mcp-0.1.0/src/adb_mcp/modules/system_properties/tools.py +216 -0
  128. android_adb_mcp-0.1.0/src/adb_mcp/modules/ui/__init__.py +0 -0
  129. android_adb_mcp-0.1.0/src/adb_mcp/modules/ui/manifest.py +17 -0
  130. android_adb_mcp-0.1.0/src/adb_mcp/modules/ui/service.py +151 -0
  131. android_adb_mcp-0.1.0/src/adb_mcp/modules/ui/tools.py +74 -0
  132. android_adb_mcp-0.1.0/src/adb_mcp/modules/user/__init__.py +0 -0
  133. android_adb_mcp-0.1.0/src/adb_mcp/modules/user/manifest.py +35 -0
  134. android_adb_mcp-0.1.0/src/adb_mcp/modules/user/service.py +394 -0
  135. android_adb_mcp-0.1.0/src/adb_mcp/modules/user/tools.py +399 -0
  136. android_adb_mcp-0.1.0/src/adb_mcp/policy.py +46 -0
  137. android_adb_mcp-0.1.0/src/adb_mcp/registry.py +219 -0
  138. android_adb_mcp-0.1.0/src/adb_mcp/responses.py +29 -0
  139. android_adb_mcp-0.1.0/src/adb_mcp/server.py +69 -0
  140. android_adb_mcp-0.1.0/tests/__init__.py +0 -0
  141. android_adb_mcp-0.1.0/tests/e2e/__init__.py +0 -0
  142. android_adb_mcp-0.1.0/tests/e2e/test_activities_e2e.py +134 -0
  143. android_adb_mcp-0.1.0/tests/e2e/test_android_services_e2e.py +143 -0
  144. android_adb_mcp-0.1.0/tests/e2e/test_app_data_e2e.py +134 -0
  145. android_adb_mcp-0.1.0/tests/e2e/test_broadcasts_e2e.py +155 -0
  146. android_adb_mcp-0.1.0/tests/e2e/test_connection_root_e2e.py +76 -0
  147. android_adb_mcp-0.1.0/tests/e2e/test_date_time_e2e.py +81 -0
  148. android_adb_mcp-0.1.0/tests/e2e/test_files_e2e.py +169 -0
  149. android_adb_mcp-0.1.0/tests/e2e/test_input_e2e.py +79 -0
  150. android_adb_mcp-0.1.0/tests/e2e/test_network_e2e.py +95 -0
  151. android_adb_mcp-0.1.0/tests/e2e/test_packages_e2e.py +83 -0
  152. android_adb_mcp-0.1.0/tests/e2e/test_permissions_e2e.py +242 -0
  153. android_adb_mcp-0.1.0/tests/e2e/test_power_e2e.py +86 -0
  154. android_adb_mcp-0.1.0/tests/e2e/test_processes_e2e.py +108 -0
  155. android_adb_mcp-0.1.0/tests/e2e/test_protocol_e2e.py +452 -0
  156. android_adb_mcp-0.1.0/tests/e2e/test_screen_e2e.py +138 -0
  157. android_adb_mcp-0.1.0/tests/e2e/test_settings_e2e.py +143 -0
  158. android_adb_mcp-0.1.0/tests/e2e/test_ui_e2e.py +112 -0
  159. android_adb_mcp-0.1.0/tests/e2e/test_user_capabilities_e2e.py +67 -0
  160. android_adb_mcp-0.1.0/tests/meta/__init__.py +0 -0
  161. android_adb_mcp-0.1.0/tests/meta/test_tool_contract.py +58 -0
  162. android_adb_mcp-0.1.0/tests/unit/__init__.py +0 -0
  163. android_adb_mcp-0.1.0/tests/unit/activities/__init__.py +0 -0
  164. android_adb_mcp-0.1.0/tests/unit/activities/test_service.py +189 -0
  165. android_adb_mcp-0.1.0/tests/unit/android_services/__init__.py +0 -0
  166. android_adb_mcp-0.1.0/tests/unit/android_services/test_service.py +171 -0
  167. android_adb_mcp-0.1.0/tests/unit/app_data/__init__.py +0 -0
  168. android_adb_mcp-0.1.0/tests/unit/app_data/test_service.py +148 -0
  169. android_adb_mcp-0.1.0/tests/unit/broadcasts/__init__.py +0 -0
  170. android_adb_mcp-0.1.0/tests/unit/broadcasts/test_service.py +182 -0
  171. android_adb_mcp-0.1.0/tests/unit/connection/__init__.py +0 -0
  172. android_adb_mcp-0.1.0/tests/unit/connection/test_service.py +285 -0
  173. android_adb_mcp-0.1.0/tests/unit/date_time/__init__.py +0 -0
  174. android_adb_mcp-0.1.0/tests/unit/date_time/test_service.py +129 -0
  175. android_adb_mcp-0.1.0/tests/unit/device_info/__init__.py +0 -0
  176. android_adb_mcp-0.1.0/tests/unit/device_info/test_service.py +43 -0
  177. android_adb_mcp-0.1.0/tests/unit/diagnostics/__init__.py +0 -0
  178. android_adb_mcp-0.1.0/tests/unit/diagnostics/test_service.py +61 -0
  179. android_adb_mcp-0.1.0/tests/unit/displays/__init__.py +0 -0
  180. android_adb_mcp-0.1.0/tests/unit/displays/test_service.py +15 -0
  181. android_adb_mcp-0.1.0/tests/unit/files/__init__.py +0 -0
  182. android_adb_mcp-0.1.0/tests/unit/files/test_service.py +141 -0
  183. android_adb_mcp-0.1.0/tests/unit/input/__init__.py +0 -0
  184. android_adb_mcp-0.1.0/tests/unit/input/test_service.py +150 -0
  185. android_adb_mcp-0.1.0/tests/unit/logger/__init__.py +0 -0
  186. android_adb_mcp-0.1.0/tests/unit/logger/test_service.py +673 -0
  187. android_adb_mcp-0.1.0/tests/unit/network/__init__.py +0 -0
  188. android_adb_mcp-0.1.0/tests/unit/network/test_service.py +182 -0
  189. android_adb_mcp-0.1.0/tests/unit/packages/__init__.py +0 -0
  190. android_adb_mcp-0.1.0/tests/unit/packages/test_service.py +148 -0
  191. android_adb_mcp-0.1.0/tests/unit/permissions/__init__.py +0 -0
  192. android_adb_mcp-0.1.0/tests/unit/permissions/test_service.py +207 -0
  193. android_adb_mcp-0.1.0/tests/unit/power/__init__.py +0 -0
  194. android_adb_mcp-0.1.0/tests/unit/power/test_service.py +108 -0
  195. android_adb_mcp-0.1.0/tests/unit/processes/__init__.py +0 -0
  196. android_adb_mcp-0.1.0/tests/unit/processes/test_service.py +99 -0
  197. android_adb_mcp-0.1.0/tests/unit/screen/__init__.py +0 -0
  198. android_adb_mcp-0.1.0/tests/unit/screen/test_service.py +267 -0
  199. android_adb_mcp-0.1.0/tests/unit/settings/__init__.py +0 -0
  200. android_adb_mcp-0.1.0/tests/unit/settings/test_service.py +127 -0
  201. android_adb_mcp-0.1.0/tests/unit/system_properties/__init__.py +0 -0
  202. android_adb_mcp-0.1.0/tests/unit/system_properties/test_service.py +380 -0
  203. android_adb_mcp-0.1.0/tests/unit/test_empty_modules_discovery.py +57 -0
  204. android_adb_mcp-0.1.0/tests/unit/test_registry.py +139 -0
  205. android_adb_mcp-0.1.0/tests/unit/ui/__init__.py +0 -0
  206. android_adb_mcp-0.1.0/tests/unit/ui/test_service.py +170 -0
  207. android_adb_mcp-0.1.0/tests/unit/user/__init__.py +0 -0
  208. android_adb_mcp-0.1.0/tests/unit/user/test_service.py +681 -0
  209. android_adb_mcp-0.1.0/uv.lock +2914 -0
@@ -0,0 +1,105 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this is
6
+
7
+ An MCP server exposing Android Debug Bridge (ADB) capabilities as typed, documented
8
+ tools (stdio transport). Full design docs live in-repo — read them before making
9
+ non-trivial changes:
10
+
11
+ - `../docs/ARCHITECTURE.md` — current-state description: component diagram, boot
12
+ sequence, core concepts (Backend/Service/Tool/Registry/Policy/Envelope), module
13
+ layering, repo layout, testing layers, CI/CD. **Read this first.**
14
+ - `../docs/ADR.md` — decision log (17 ADRs). Explains *why* things are shaped this way,
15
+ including several non-obvious findings (fastmcp docstring-parsing quirks,
16
+ `docstring_parser` crashing on prose `Raises:` sections, `adb connect`'s exit code
17
+ being useless, etc.) that are easy to accidentally re-break.
18
+
19
+ Both are living docs updated in place, not changelogs — treat them as authoritative
20
+ over any summary here.
21
+
22
+ ## Commands
23
+
24
+ ```bash
25
+ uv sync # install deps (dev group for testing)
26
+ uv run adb-mcp-server # run the server (stdio)
27
+
28
+ uv run pytest # meta (Layer 0) + unit (Layer 1) + e2e (Layer 3) tests
29
+ uv run pytest tests/unit/user # run one module's tests
30
+ uv run pytest -k test_name # run a single test by name
31
+
32
+ uv run mypy src # strict type checking — must pass, no bare Any
33
+ uv run ruff check . # lint
34
+ uv run mkdocs build --strict # docs site (fails on broken nav/links)
35
+ ```
36
+
37
+ CI (`../.github/workflows/ci.yml`) runs `ruff check` → `mypy --strict` → `pytest` on
38
+ every push/PR to `main`, plus a strict `mkdocs build` (and `gh-deploy` on merge to
39
+ `main`).
40
+
41
+ Useful env vars (see `server.py` header and ADR-010):
42
+
43
+ - `ADB_MCP_BACKEND=fake` — use the deterministic `FakeBackend` instead of a real `adb`
44
+ - `ADB_MCP_ADB_PATH` — explicit path to the `adb` binary
45
+ - `ADB_MCP_TIMEOUT_S` — per-command timeout (default 10s)
46
+ - `ADB_MCP_ALLOW_DESTRUCTIVE=1` — flip default policy posture to also allow
47
+ `destructive`-category tools
48
+ - `ADB_MCP_LOCAL_ROOT` — host directory `stop_log_session`'s local path must resolve
49
+ under; no default, that tool refuses to run until this is set
50
+
51
+ ## Architecture (essentials — see `../docs/ARCHITECTURE.md` for the full picture)
52
+
53
+ - **Layering per module**: `tools.py` (thin, typed, module-level async function,
54
+ `@category("read"|"write"|"destructive")`) → `service.py` (domain logic: command
55
+ construction, output parsing, domain exceptions) → `AdbBackend` Protocol
56
+ (mechanical execution only). Tool functions are never closures — they're
57
+ module-level so `mkdocstrings` can statically introspect them (ADR-014).
58
+ - **Backend seam**: `AdbBackend` is a `typing.Protocol`. `SubprocessBackend` (real,
59
+ via `asyncio.create_subprocess_exec`) and `FakeBackend` (deterministic, in-memory,
60
+ test-only) are the two implementations. Nothing above this line knows which one
61
+ it's talking to.
62
+ - **Modules are plugins**: discovered via `entry_points` (group `adb_mcp.modules`),
63
+ declared in `../pyproject.toml`. Built-in modules (`diagnostics`, `device_info`,
64
+ `connection`, `user`, `logger`) use the exact same mechanism a third-party package
65
+ would — no special-cased "core module" path.
66
+ - **Registry** (`registry.py`) wires it all together at import time: discovers
67
+ manifests, asks `PolicyEngine` whether each tool is allowed *before* registering it
68
+ with `FastMCP` (a denied tool is never exposed to the client at all), wraps allowed
69
+ tools with the response envelope.
70
+ - **Response envelope**: every tool returns `ToolResponse[T]`
71
+ (`status`/`message`/`data`/`error`) — always `isError: false` at the MCP level; a
72
+ domain failure is `status: "error"` in the payload, not a protocol-level error.
73
+ Module/service code raises typed `AdbError` subclasses; only the registry wrapper
74
+ builds the envelope.
75
+ - **Policy**: category default posture (`destructive` denied unless
76
+ `ADB_MCP_ALLOW_DESTRUCTIVE=1`) plus explicit allow/deny lists by tool name,
77
+ evaluated once at registration time. `local_root` (host filesystem writes) is a
78
+ separate *call-time* check inside the service, not the policy engine, since it
79
+ depends on the actual argument value.
80
+ - **No generic shell tool** (ADR-009, deliberate): every operation is a specific,
81
+ named, parameterized tool. Don't add an `adb_shell(serial, command: str)`-shaped
82
+ tool.
83
+
84
+ ## Adding a new tool/module
85
+
86
+ Follow `../docs/ARCHITECTURE.md` §6 and ADR-014 exactly: module-level function in
87
+ `tools.py` (never a closure), service method in `service.py`, `AdbBackend` primitive
88
+ in `backend/protocol.py` only if the operation needs genuinely new mechanical
89
+ execution. Every tool must be fully typed (`mypy --strict`, no bare `Any`) and carry
90
+ a Google-style docstring with Summary/Args/Returns/Example — enforced by
91
+ `../tests/meta/test_tool_contract.py` against the live registry, not a fixed list. Use
92
+ `Error handling:` instead of `Raises:` for prose-style failure descriptions
93
+ (`docstring_parser`/`griffe` both mishandle a non-`ExceptionType: description`
94
+ `Raises:` section — ADR-017). Add fixture `CommandResult`s to `FakeBackend` using
95
+ real, captured `adb`/`pm`/`am`/`dumpsys` output, not hand-invented strings.
96
+
97
+ ## Testing layers
98
+
99
+ Layer 0 (`../tests/meta`) — registry contract: every registered tool fully typed +
100
+ documented. Layer 1 (`../tests/unit`, per module) — service class against
101
+ `FakeBackend`, no MCP machinery. Layer 3 (`../tests/e2e`) — real `fastmcp.Client`
102
+ against a `Registry`-wired server backed by `FakeBackend`, catching
103
+ registration/schema/serialization bugs the lower layers can't see. Layers 2
104
+ (dual-backend contract tests) and 4 (CI emulator integration) are not yet
105
+ implemented — see `../docs/ARCHITECTURE.md` §9.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: architecture-reviewer
3
+ description: Read-only architecture reviewer for ADB MCP Server module work. Use after implementing or changing a module, or before integrating parallel-agent changes, to check layering, ownership boundaries, MCP API quality, shared-contract leakage, and consistency with ARCHITECTURE.md.
4
+ tools: Read, Grep, Glob
5
+ model: opus
6
+ permissionMode: plan
7
+ effort: high
8
+ ---
9
+
10
+ You are the architecture reviewer for the ADB MCP Server repository.
11
+
12
+ ## Mission
13
+
14
+ Review proposed or completed work against the repository's documented architecture. `ARCHITECTURE.md` is the authoritative architectural contract. You are advisory and read-only: identify problems and recommend decisions, but do not edit files.
15
+
16
+ ## Review priorities
17
+
18
+ Review in this order:
19
+
20
+ 1. **Module ownership** — Is the behavior in the correct domain module?
21
+ 2. **Layering** — Are MCP tools thin delegates, domain decisions in the service, and mechanical ADB execution behind the backend abstraction?
22
+ 3. **Public API semantics** — Does the MCP surface expose user intent/domain concepts rather than mirroring `am`, `pm`, `cmd`, `dumpsys`, or shell syntax?
23
+ 4. **Shared-contract discipline** — Did module work unnecessarily change or depend on registry, backend, policy, response/error, server, or shared test infrastructure?
24
+ 5. **Typed results** — Are structured domain results used where appropriate instead of leaking raw command output?
25
+ 6. **Policy semantics** — Are operations categorized correctly as `read`, `write`, or `destructive`?
26
+ 7. **Error boundaries** — Are transport failures, domain failures, and legitimate negative states kept distinct according to project conventions?
27
+ 8. **Testing boundaries** — Are tests focused on module behavior without coupling unnecessarily to FastMCP or production ADB execution?
28
+ 9. **Parallel integration risk** — Would this change conflict with another independently developed module or force cross-module coordination?
29
+ 10. **Scope control** — Are there unrelated refactors or architecture changes hidden inside module work?
30
+
31
+ ## Decision rule
32
+
33
+ Do not reject a change merely because Android exposes the underlying capability through multiple command families. The project's domain API should remain stable even when its service internally combines `am`, `pm`, `cmd`, or `dumpsys` sources.
34
+
35
+ When a module needs a shared capability, distinguish between:
36
+
37
+ - a legitimate missing shared abstraction that should be decided centrally, and
38
+ - a module implementation detail that should remain inside the module service.
39
+
40
+ Do not design or implement the shared change yourself. State the architectural decision the parent needs to make and explain the tradeoff.
41
+
42
+ ## Severity
43
+
44
+ Classify findings as:
45
+
46
+ - **BLOCKER** — violates a core architectural boundary, creates unsafe cross-module coupling, or requires a central contract decision before integration
47
+ - **IMPORTANT** — should be corrected before merge but does not invalidate the overall design
48
+ - **MINOR** — consistency, naming, documentation, or maintainability improvement
49
+
50
+ Do not manufacture findings. If the implementation fits the architecture, say so.
51
+
52
+ ## Return to parent
53
+
54
+ Return:
55
+
56
+ - overall verdict: `APPROVE`, `APPROVE WITH CHANGES`, or `BLOCK`
57
+ - findings grouped by severity
58
+ - the exact architectural boundary involved
59
+ - concrete recommended direction without editing code
60
+ - any central/shared decision the parent must make before integration
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: module-implementer
3
+ description: Implements or extends one explicitly assigned adb_mcp domain module and its module-specific tests. Use for parallel work on independent modules such as users, logging, diagnostics, connection, or device_info. Do not use for shared architecture or cross-cutting infrastructure changes.
4
+ tools: Read, Write, Edit, Grep, Glob, Bash
5
+ model: sonnet
6
+ permissionMode: acceptEdits
7
+ effort: high
8
+ ---
9
+
10
+ You are a module implementation engineer for the ADB MCP Server repository.
11
+
12
+ ## Mission
13
+
14
+ Implement or extend exactly one domain module that the parent assigns to you. Treat the repository's `ARCHITECTURE.md` as the authoritative architectural contract. Inspect existing modules before making changes and follow their established patterns unless the parent explicitly instructs otherwise.
15
+
16
+ You own module implementation, not project architecture.
17
+
18
+ ## Required boundaries
19
+
20
+ You may change only:
21
+
22
+ - `src/adb_mcp/modules/<assigned-module>/**`
23
+ - module-specific unit tests for the assigned module
24
+ - module-specific protocol/e2e tests when they can be added without changing shared fixtures or infrastructure
25
+
26
+ Do not modify shared or cross-cutting project files, including:
27
+
28
+ - `src/adb_mcp/backend/**`
29
+ - `src/adb_mcp/registry.py`
30
+ - `src/adb_mcp/server.py`
31
+ - `src/adb_mcp/policy.py`
32
+ - `src/adb_mcp/errors.py`
33
+ - `src/adb_mcp/responses.py`
34
+ - shared test fixtures or test infrastructure
35
+ - `pyproject.toml`, CI configuration, or repository-wide documentation
36
+
37
+ If the assigned work genuinely requires a shared-contract change, do not make that change. Finish everything that can be completed within the module boundary and report the required shared change to the parent as a blocker or architecture request.
38
+
39
+ ## Architectural rules
40
+
41
+ Preserve these boundaries:
42
+
43
+ 1. MCP tools are thin, typed, documented module-level functions.
44
+ 2. Domain behavior, ADB command construction, parsing, and domain-specific decisions belong in the module service.
45
+ 3. Modules access ADB only through the existing backend abstraction; never invoke subprocesses directly.
46
+ 4. Public MCP operations represent user intent/domain concepts, not raw Android command ownership such as `am`, `pm`, `cmd`, or `dumpsys`.
47
+ 5. Use the project's existing response/error conventions rather than inventing module-specific envelopes.
48
+ 6. Respect the existing `read`, `write`, and `destructive` category semantics.
49
+ 7. Prefer typed structured results over returning raw shell output unless raw output is explicitly part of the requested API.
50
+ 8. Follow existing module naming, manifest, service-factory, typing, documentation, and testing conventions.
51
+
52
+ ## Parallel-work discipline
53
+
54
+ Assume other agents may be editing other modules at the same time.
55
+
56
+ - Do not reformat or clean up unrelated files.
57
+ - Do not rename shared symbols.
58
+ - Do not opportunistically refactor neighboring modules.
59
+ - Do not modify another agent's module.
60
+ - Keep edits narrowly scoped to the assigned module.
61
+
62
+ If the parent did not explicitly identify a module and concrete task, report that the assignment is incomplete rather than choosing work yourself.
63
+
64
+ ## Validation
65
+
66
+ Run the narrowest relevant checks first, then broader repository checks when practical. Do not change shared configuration merely to make tests pass.
67
+
68
+ Before finishing, verify:
69
+
70
+ - the module follows the repository layering
71
+ - public tools are fully typed and documented according to existing project conventions
72
+ - parsing and error behavior have module-level tests
73
+ - no unrelated/shared files were changed
74
+
75
+ ## Return to parent
76
+
77
+ Return a concise implementation report containing:
78
+
79
+ - what was implemented
80
+ - files changed
81
+ - tests/checks run and their results
82
+ - any assumptions
83
+ - any shared-contract change or architecture decision needed from the parent
84
+
85
+ Do not silently solve architecture questions yourself.
@@ -0,0 +1,61 @@
1
+ name: CI
2
+
3
+ "on":
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v7
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v10.0.1
17
+ with:
18
+ enable-cache: true
19
+
20
+ - name: Set up Python
21
+ run: uv python install 3.12
22
+
23
+ - name: Install dependencies
24
+ run: uv sync
25
+
26
+ - name: Lint (ruff)
27
+ run: uv run ruff check .
28
+
29
+ - name: Type check (mypy --strict)
30
+ run: uv run mypy src
31
+
32
+ - name: Test (pytest — meta + unit + e2e)
33
+ run: uv run pytest
34
+
35
+ docs:
36
+ runs-on: ubuntu-latest
37
+ permissions:
38
+ contents: write
39
+ steps:
40
+ - uses: actions/checkout@v7
41
+
42
+ - name: Install uv
43
+ uses: astral-sh/setup-uv@v10.0.1
44
+ with:
45
+ enable-cache: true
46
+
47
+ - name: Set up Python
48
+ run: uv python install 3.12
49
+
50
+ - name: Install dependencies
51
+ run: uv sync --group docs
52
+
53
+ - name: Build docs (strict)
54
+ run: uv run mkdocs build --strict
55
+
56
+ - name: Deploy to GitHub Pages
57
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
58
+ run: |
59
+ git config user.name "github-actions[bot]"
60
+ git config user.email "github-actions[bot]@users.noreply.github.com"
61
+ uv run mkdocs gh-deploy --force
@@ -0,0 +1,27 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write
12
+ steps:
13
+ - uses: actions/checkout@v7
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v10.0.1
17
+ with:
18
+ enable-cache: true
19
+
20
+ - name: Set up Python
21
+ run: uv python install 3.12
22
+
23
+ - name: Build
24
+ run: uv build
25
+
26
+ - name: Publish to PyPI
27
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,65 @@
1
+ # --- Python ---
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # --- Virtual environments ---
25
+ .venv/
26
+ venv/
27
+ env/
28
+ ENV/
29
+
30
+ # --- Testing / type-checking / linting ---
31
+ .pytest_cache/
32
+ .mypy_cache/
33
+ .ruff_cache/
34
+ .tox/
35
+ .nox/
36
+ .coverage
37
+ .coverage.*
38
+ htmlcov/
39
+ coverage.xml
40
+ *.cover
41
+
42
+ # --- mkdocs build output (ADR-013) ---
43
+ site/
44
+
45
+ # --- Local runtime config (never commit real local_root/policy paths — ADR-010) ---
46
+ adb-mcp.toml
47
+ .env
48
+ .env.*
49
+ !.env.example
50
+
51
+ # --- JetBrains / PyCharm ---
52
+ .idea/
53
+ .mcp.json
54
+
55
+ # --- VS Code ---
56
+ .vscode/
57
+
58
+ # --- OS cruft ---
59
+ .DS_Store
60
+ Thumbs.db
61
+
62
+ # --- Editor swap files ---
63
+ *.swp
64
+ *.swo
65
+ *~
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 M. Allaudin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.5
2
+ Name: android-adb-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server exposing Android Debug Bridge (ADB) capabilities as tools and resources.
5
+ Project-URL: Homepage, https://github.com/allaudin/adb-mcp-server
6
+ Project-URL: Repository, https://github.com/allaudin/adb-mcp-server
7
+ Project-URL: Documentation, https://allaudin.github.io/adb-mcp-server/
8
+ Project-URL: Issues, https://github.com/allaudin/adb-mcp-server/issues
9
+ Author-email: "M. Allaudin" <dev.allaudin@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: adb,android,android-debug-bridge,fastmcp,mcp,model-context-protocol
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Testing
23
+ Classifier: Topic :: System :: Networking
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: fastmcp>=3.0
26
+ Requires-Dist: pydantic>=2.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # adb-mcp-server
30
+
31
+ <!-- mcp-name: io.github.allaudin/adb-mcp-server -->
32
+
33
+ [![CI](https://github.com/allaudin/adb-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/allaudin/adb-mcp-server/actions/workflows/ci.yml)
34
+ [![PyPI](https://img.shields.io/pypi/v/android-adb-mcp.svg)](https://pypi.org/project/android-adb-mcp/)
35
+
36
+ An MCP server exposing Android Debug Bridge (ADB) capabilities as typed, documented
37
+ tools and resources.
38
+
39
+ **Full documentation: <https://allaudin.github.io/adb-mcp-server/>** — architecture,
40
+ decision log, per-tool reference, and client integration guides.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ uvx android-adb-mcp
46
+ # or
47
+ pip install android-adb-mcp
48
+ ```
49
+
50
+ ## Quickstart
51
+
52
+ ```bash
53
+ uv sync
54
+ uv run adb-mcp-server
55
+ ```
56
+
57
+ Talks to the `adb` binary on `PATH` by default. For real-device setup, the fake
58
+ backend, environment variables, the full tool list, and integrating with an MCP
59
+ client (Claude Code, Claude Desktop, ...), see the
60
+ [docs site](https://allaudin.github.io/adb-mcp-server/).
61
+
62
+ ## Testing
63
+
64
+ ```bash
65
+ uv run pytest # meta (Layer 0), unit (Layer 1), and e2e (Layer 3) tests
66
+ uv run mypy src # strict type checking
67
+ uv run ruff check . # lint
68
+ uv run mkdocs build --strict # docs site
69
+ ```
70
+
71
+ ## License
72
+
73
+ [MIT](LICENSE)
@@ -0,0 +1,45 @@
1
+ # adb-mcp-server
2
+
3
+ <!-- mcp-name: io.github.allaudin/adb-mcp-server -->
4
+
5
+ [![CI](https://github.com/allaudin/adb-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/allaudin/adb-mcp-server/actions/workflows/ci.yml)
6
+ [![PyPI](https://img.shields.io/pypi/v/android-adb-mcp.svg)](https://pypi.org/project/android-adb-mcp/)
7
+
8
+ An MCP server exposing Android Debug Bridge (ADB) capabilities as typed, documented
9
+ tools and resources.
10
+
11
+ **Full documentation: <https://allaudin.github.io/adb-mcp-server/>** — architecture,
12
+ decision log, per-tool reference, and client integration guides.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ uvx android-adb-mcp
18
+ # or
19
+ pip install android-adb-mcp
20
+ ```
21
+
22
+ ## Quickstart
23
+
24
+ ```bash
25
+ uv sync
26
+ uv run adb-mcp-server
27
+ ```
28
+
29
+ Talks to the `adb` binary on `PATH` by default. For real-device setup, the fake
30
+ backend, environment variables, the full tool list, and integrating with an MCP
31
+ client (Claude Code, Claude Desktop, ...), see the
32
+ [docs site](https://allaudin.github.io/adb-mcp-server/).
33
+
34
+ ## Testing
35
+
36
+ ```bash
37
+ uv run pytest # meta (Layer 0), unit (Layer 1), and e2e (Layer 3) tests
38
+ uv run mypy src # strict type checking
39
+ uv run ruff check . # lint
40
+ uv run mkdocs build --strict # docs site
41
+ ```
42
+
43
+ ## License
44
+
45
+ [MIT](LICENSE)