mobile-docs-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.
- mobile_docs_mcp-0.1.0/.gitignore +25 -0
- mobile_docs_mcp-0.1.0/HOSTED.md +78 -0
- mobile_docs_mcp-0.1.0/LICENSE +21 -0
- mobile_docs_mcp-0.1.0/PKG-INFO +246 -0
- mobile_docs_mcp-0.1.0/README.md +214 -0
- mobile_docs_mcp-0.1.0/TESTING.md +173 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/__init__.py +3 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/embeddings.py +131 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/ingest/__init__.py +6 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/ingest/_common.py +47 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/ingest/android.py +155 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/ingest/apple.py +132 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/ingest/seed.py +209 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/models.py +145 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/server.py +184 -0
- mobile_docs_mcp-0.1.0/mobile_docs_mcp/store.py +170 -0
- mobile_docs_mcp-0.1.0/pyproject.toml +62 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
env/
|
|
11
|
+
|
|
12
|
+
# Crawled index output (regenerate via ingest; keep only the seed in git)
|
|
13
|
+
data/android/
|
|
14
|
+
data/apple/
|
|
15
|
+
*.index
|
|
16
|
+
|
|
17
|
+
# Tooling
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.DS_Store
|
|
22
|
+
|
|
23
|
+
# Secrets / local config
|
|
24
|
+
.env
|
|
25
|
+
.env.*
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Open-core architecture
|
|
2
|
+
|
|
3
|
+
`mobile-docs-mcp` is designed to live two lives from one codebase — the same
|
|
4
|
+
split Context7 uses (MIT client, proprietary backend).
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
┌─────────────────────────────┐ ┌──────────────────────────────┐
|
|
8
|
+
│ PUBLIC (this repo, MIT) │ │ HOSTED (yours, private) │
|
|
9
|
+
│ │ │ │
|
|
10
|
+
│ mobile_docs_mcp/ │ │ hosted/app.py │
|
|
11
|
+
│ server.py (MCP tools) │ HTTP │ FastAPI over the SAME │
|
|
12
|
+
│ store.py (retrieval) │ ─────▶ │ Store, but serving the │
|
|
13
|
+
│ ingest/ (crawlers) │ │ full crawled index │
|
|
14
|
+
│ + bundled SEED corpus │ │ + API keys + rate limits │
|
|
15
|
+
│ │ │ + freshness pipeline │
|
|
16
|
+
│ → the funnel & credibility │ │ → the paid product │
|
|
17
|
+
└─────────────────────────────┘ └──────────────────────────────┘
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The public half is fully usable on its own (`uvx mobile-docs-mcp` against the
|
|
21
|
+
seed corpus). That's what goes on GitHub and into interviews. The hosted half is
|
|
22
|
+
what you'd run as a service if you commercialize: it serves a large, continuously
|
|
23
|
+
refreshed, version-tagged index that isn't practical to bundle or self-host — the
|
|
24
|
+
same thing that makes Context7's backend defensible.
|
|
25
|
+
|
|
26
|
+
Open-sourcing the client does **not** give away the moat. The moat is index
|
|
27
|
+
breadth + freshness, which lives in the deployment, not the code.
|
|
28
|
+
|
|
29
|
+
## What stays public vs. private
|
|
30
|
+
|
|
31
|
+
| Public (MIT) | Private (if you monetize) |
|
|
32
|
+
|---|---|
|
|
33
|
+
| MCP server + tool surface | Full crawled index (all androidx + SwiftUI symbols/versions) |
|
|
34
|
+
| Retrieval logic (`store.py`) | Freshness pipeline (scheduled re-crawl + diff) |
|
|
35
|
+
| Ingestion framework (`ingest/`) | Hosted API auth, billing, rate limiting |
|
|
36
|
+
| Seed corpus (demo) | Enterprise mode: index a customer's **private** SDK docs |
|
|
37
|
+
|
|
38
|
+
## Run the hosted backend locally
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install fastapi uvicorn
|
|
42
|
+
uvicorn hosted.app:app --host 0.0.0.0 --port 8000
|
|
43
|
+
|
|
44
|
+
curl "http://localhost:8000/verify?name=scrollTargetBehavior&target_version=16.0&platform=apple"
|
|
45
|
+
# {"status":"unavailable","detail":"scrollTargetBehavior was introduced in 17.0 ..."}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Env vars:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
MOBILE_DOCS_DATA=data/android,data/apple # serve a real crawled index, not the seed
|
|
52
|
+
MOBILE_DOCS_REQUIRE_KEY=1 # enforce API keys
|
|
53
|
+
MOBILE_DOCS_API_KEYS=key_abc,key_def # (stub — replace with a real key store)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Deploy on Replit (fast MVP / demo)
|
|
57
|
+
|
|
58
|
+
1. Create a Replit from your GitHub repo (or the private fork holding a real index).
|
|
59
|
+
2. Set the run command:
|
|
60
|
+
```
|
|
61
|
+
uvicorn hosted.app:app --host 0.0.0.0 --port 8000
|
|
62
|
+
```
|
|
63
|
+
3. Add `fastapi` and `uvicorn` to the environment (Replit auto-detects from
|
|
64
|
+
`pip install`, or add a `requirements-hosted.txt`).
|
|
65
|
+
4. Replit exposes it at a public URL — point a landing page at `/search` and
|
|
66
|
+
`/verify`, collect usage, validate willingness-to-pay before investing in the
|
|
67
|
+
full crawl + freshness pipeline.
|
|
68
|
+
|
|
69
|
+
Replit is right for the demo endpoint and validation. If real pull appears, move
|
|
70
|
+
the crawl pipeline + vector store to durable infra; keep Replit as the front door.
|
|
71
|
+
|
|
72
|
+
## Next step: remote-index mode for the MCP server
|
|
73
|
+
|
|
74
|
+
To let the public MCP server call your hosted index instead of the local seed,
|
|
75
|
+
add a `RemoteStore` that implements `search()` / `find_symbols()` over HTTP and
|
|
76
|
+
select it in `server.py` when `MOBILE_DOCS_REMOTE` is set. That turns the same
|
|
77
|
+
`uvx mobile-docs-mcp` install into a thin client of your paid backend — the
|
|
78
|
+
Context7 distribution model exactly.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Asif
|
|
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,246 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mobile-docs-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Version-aware mobile docs MCP server for Android (Jetpack/Compose) and Apple (SwiftUI/UIKit)
|
|
5
|
+
Project-URL: Homepage, https://github.com/asif786ka/mobile-docs-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/asif786ka/mobile-docs-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/asif786ka/mobile-docs-mcp/issues
|
|
8
|
+
Author: Asif
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: android,documentation,ios,jetpack-compose,mcp,rag,swiftui
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: mcp>=1.2.0
|
|
23
|
+
Requires-Dist: rank-bm25>=0.2.2
|
|
24
|
+
Provides-Extra: hosted
|
|
25
|
+
Requires-Dist: fastapi>=0.110.0; extra == 'hosted'
|
|
26
|
+
Requires-Dist: uvicorn>=0.29.0; extra == 'hosted'
|
|
27
|
+
Provides-Extra: openai
|
|
28
|
+
Requires-Dist: openai>=1.40.0; extra == 'openai'
|
|
29
|
+
Provides-Extra: vector
|
|
30
|
+
Requires-Dist: sentence-transformers>=3.0.0; extra == 'vector'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# mobile-docs-mcp
|
|
34
|
+
|
|
35
|
+
A version-aware documentation MCP server for mobile development — the context7
|
|
36
|
+
idea, but specialized for the thing generic doc proxies get wrong: **which
|
|
37
|
+
version of an API you can actually use.**
|
|
38
|
+
|
|
39
|
+
It indexes Android (Jetpack / androidx / Compose) and Apple (SwiftUI / UIKit)
|
|
40
|
+
documentation with `since` / `deprecated` / `removed` metadata on every symbol,
|
|
41
|
+
so an agent can *verify an API exists on the version the project targets* before
|
|
42
|
+
writing code against it.
|
|
43
|
+
|
|
44
|
+
## Why it's different from a doc proxy
|
|
45
|
+
|
|
46
|
+
Most "Apple docs" / "Android docs" MCP servers live-fetch and parse the current
|
|
47
|
+
doc site. They answer "what is `scrollTargetBehavior`?" but not "can I use it on
|
|
48
|
+
iOS 16?" — and that second question is where coding agents hallucinate. Every
|
|
49
|
+
result here is filtered and annotated against a target version.
|
|
50
|
+
|
|
51
|
+
## Tools
|
|
52
|
+
|
|
53
|
+
| Tool | Purpose |
|
|
54
|
+
|------|---------|
|
|
55
|
+
| `search_mobile_docs` | Hybrid (BM25 + optional vector) retrieval, filtered by platform + target version |
|
|
56
|
+
| `get_api_reference` | Full symbol card: signature, availability, deprecation/migration pointer |
|
|
57
|
+
| `verify_api_exists` | Anti-hallucination check — real AND usable on a given version? |
|
|
58
|
+
| `list_api_versions` | since / deprecated / removed timeline + migration lineage |
|
|
59
|
+
| `get_release_notes` | What changed in a library/version |
|
|
60
|
+
|
|
61
|
+
Example verdict:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
verify_api_exists("scrollTargetBehavior", "16.0", "apple")
|
|
65
|
+
→ ❌ NOT AVAILABLE — introduced in 17.0, newer than 16.0. Will not compile there.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Run
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# From source
|
|
72
|
+
pip install -e .
|
|
73
|
+
python -m mobile_docs_mcp.server # stdio transport
|
|
74
|
+
|
|
75
|
+
# Once published
|
|
76
|
+
uvx mobile-docs-mcp
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Ships with a seed corpus, so it works immediately with no crawl.
|
|
80
|
+
|
|
81
|
+
## Editor & IDE setup (iOS + Android)
|
|
82
|
+
|
|
83
|
+
The server speaks MCP over stdio, so any MCP-capable editor can use it. All the
|
|
84
|
+
tools work for **both** platforms — you'll lean on the SwiftUI entries in an iOS
|
|
85
|
+
project and the Compose/androidx entries in an Android one, but nothing is
|
|
86
|
+
editor-specific. Two ways to launch it:
|
|
87
|
+
|
|
88
|
+
- **From source (this repo):** `command: "python"`, `args: ["-m", "mobile_docs_mcp.server"]`, with `cwd` set to the repo path.
|
|
89
|
+
- **Once published:** `command: "uvx"`, `args: ["mobile-docs-mcp"]` (no `cwd` needed).
|
|
90
|
+
|
|
91
|
+
Set `MOBILE_DOCS_DATA` in `env` to layer in any corpora you've crawled with the
|
|
92
|
+
ingesters (see "Growing the index").
|
|
93
|
+
|
|
94
|
+
### Claude Code (CLI)
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# from source, shared with the repo via .mcp.json (project scope)
|
|
98
|
+
claude mcp add mobile-docs-mcp --scope project -- python -m mobile_docs_mcp.server
|
|
99
|
+
# or, once published
|
|
100
|
+
claude mcp add mobile-docs-mcp -- uvx mobile-docs-mcp
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Verify with `claude mcp list`, or `/mcp` inside a session.
|
|
104
|
+
|
|
105
|
+
### Claude Desktop
|
|
106
|
+
|
|
107
|
+
Edit `claude_desktop_config.json` (Settings → Developer → Edit Config), then
|
|
108
|
+
restart the app:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"mcpServers": {
|
|
113
|
+
"mobile-docs-mcp": {
|
|
114
|
+
"command": "python",
|
|
115
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
116
|
+
"cwd": "/absolute/path/to/mobile-docs-mcp",
|
|
117
|
+
"env": { "MOBILE_DOCS_DATA": "data/android,data/apple" }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Cursor
|
|
124
|
+
|
|
125
|
+
Create `.cursor/mcp.json` in the project root (or `~/.cursor/mcp.json` for all
|
|
126
|
+
projects) — same `mcpServers` shape as above:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"mcpServers": {
|
|
131
|
+
"mobile-docs-mcp": {
|
|
132
|
+
"command": "python",
|
|
133
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
134
|
+
"cwd": "${workspaceFolder}"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Then enable it under Settings → MCP.
|
|
141
|
+
|
|
142
|
+
### Windsurf
|
|
143
|
+
|
|
144
|
+
Edit `~/.codeium/windsurf/mcp_config.json` (Cascade panel → MCP icon →
|
|
145
|
+
Configure). Same `mcpServers` shape; Windsurf supports `${env:VAR}` interpolation
|
|
146
|
+
so you can keep paths/secrets out of the file:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"mcpServers": {
|
|
151
|
+
"mobile-docs-mcp": {
|
|
152
|
+
"command": "python",
|
|
153
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
154
|
+
"cwd": "/absolute/path/to/mobile-docs-mcp"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Android Studio
|
|
161
|
+
|
|
162
|
+
Gemini in Android Studio is an MCP client. Go to **Settings → Tools → AI → MCP
|
|
163
|
+
Servers**, tick **Enable MCP Servers**, and paste the same `mcpServers` JSON
|
|
164
|
+
block shown for Claude Desktop. Confirm with the "Successfully connected"
|
|
165
|
+
notification, then type `/mcp` in the chat to see the tools. Great for checking
|
|
166
|
+
`androidx`/Compose availability against your module's `compileSdk` / library
|
|
167
|
+
versions without leaving the IDE.
|
|
168
|
+
|
|
169
|
+
### VS Code
|
|
170
|
+
|
|
171
|
+
VS Code's key is `servers` (not `mcpServers`) and wants an explicit `type`.
|
|
172
|
+
Create `.vscode/mcp.json` (commit it to share with the team):
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"servers": {
|
|
177
|
+
"mobile-docs-mcp": {
|
|
178
|
+
"type": "stdio",
|
|
179
|
+
"command": "python",
|
|
180
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
181
|
+
"cwd": "${workspaceFolder}",
|
|
182
|
+
"env": { "MOBILE_DOCS_DATA": "data/android,data/apple" }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Open the file and click **Start**, or run *MCP: List Servers* from the Command
|
|
189
|
+
Palette. Copilot Chat's Agent mode will then surface the tools.
|
|
190
|
+
|
|
191
|
+
### Xcode
|
|
192
|
+
|
|
193
|
+
Xcode 26.3+ is itself an **MCP server** (it exposes build / test / preview /
|
|
194
|
+
Apple-doc-search tools) rather than an MCP client — so you don't register
|
|
195
|
+
`mobile-docs-mcp` *inside* Xcode. Instead, run an agent that consumes both: point
|
|
196
|
+
Claude Code (or Cursor / Codex) at `mobile-docs-mcp` using the steps above while
|
|
197
|
+
it's also connected to Xcode's server. The agent then gets Xcode's build/preview
|
|
198
|
+
tools **and** this server's `verify_api_exists` version checks in one session —
|
|
199
|
+
e.g. it can confirm `scrollTargetBehavior` needs iOS 17 before writing it against
|
|
200
|
+
your iOS 16 deployment target, then build the project to check.
|
|
201
|
+
|
|
202
|
+
## Architecture
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
ingest/ (batch, offline) server.py (runtime)
|
|
206
|
+
android.py developer.android.com FastMCP
|
|
207
|
+
apple.py Apple JSON doc API │
|
|
208
|
+
│ ▼
|
|
209
|
+
▼ store.py — hybrid, version-aware
|
|
210
|
+
symbols.json + chunks.json 1. BM25 lexical recall
|
|
211
|
+
(version-tagged) 2. vector recall (optional)
|
|
212
|
+
3. RRF fusion
|
|
213
|
+
4. VERSION FILTER ← the differentiator
|
|
214
|
+
5. cross-encoder rerank (optional)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Retrieval is provider-agnostic (`embeddings.py`), same shape as a multi-provider
|
|
218
|
+
model gateway: BM25 works fully offline; vector recall and rerank switch on via
|
|
219
|
+
env var with no code change and degrade gracefully if a provider is missing.
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
MOBILE_DOCS_EMBEDDINGS=local # or openai ; default none (BM25-only)
|
|
223
|
+
MOBILE_DOCS_RERANK=local # default none
|
|
224
|
+
MOBILE_DOCS_DATA=data/android,data/apple # layer in crawled corpora
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Growing the index
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
python -m mobile_docs_mcp.ingest.android --out data/android \
|
|
231
|
+
--refs androidx.compose.foundation.lazy.LazyColumn \
|
|
232
|
+
--release-notes compose-foundation navigation
|
|
233
|
+
|
|
234
|
+
python -m mobile_docs_mcp.ingest.apple --out data/apple \
|
|
235
|
+
--paths swiftui/navigationstack swiftui/view/scrolltargetbehavior
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Then point the server at the output with `MOBILE_DOCS_DATA`.
|
|
239
|
+
|
|
240
|
+
## Status
|
|
241
|
+
|
|
242
|
+
MVP. The protocol layer, version logic, hybrid store, and tool surface are
|
|
243
|
+
production-shaped; the ingestion coverage is a seed. The real work — and the moat
|
|
244
|
+
— is breadth and freshness of the version-tagged index.
|
|
245
|
+
|
|
246
|
+
MIT.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# mobile-docs-mcp
|
|
2
|
+
|
|
3
|
+
A version-aware documentation MCP server for mobile development — the context7
|
|
4
|
+
idea, but specialized for the thing generic doc proxies get wrong: **which
|
|
5
|
+
version of an API you can actually use.**
|
|
6
|
+
|
|
7
|
+
It indexes Android (Jetpack / androidx / Compose) and Apple (SwiftUI / UIKit)
|
|
8
|
+
documentation with `since` / `deprecated` / `removed` metadata on every symbol,
|
|
9
|
+
so an agent can *verify an API exists on the version the project targets* before
|
|
10
|
+
writing code against it.
|
|
11
|
+
|
|
12
|
+
## Why it's different from a doc proxy
|
|
13
|
+
|
|
14
|
+
Most "Apple docs" / "Android docs" MCP servers live-fetch and parse the current
|
|
15
|
+
doc site. They answer "what is `scrollTargetBehavior`?" but not "can I use it on
|
|
16
|
+
iOS 16?" — and that second question is where coding agents hallucinate. Every
|
|
17
|
+
result here is filtered and annotated against a target version.
|
|
18
|
+
|
|
19
|
+
## Tools
|
|
20
|
+
|
|
21
|
+
| Tool | Purpose |
|
|
22
|
+
|------|---------|
|
|
23
|
+
| `search_mobile_docs` | Hybrid (BM25 + optional vector) retrieval, filtered by platform + target version |
|
|
24
|
+
| `get_api_reference` | Full symbol card: signature, availability, deprecation/migration pointer |
|
|
25
|
+
| `verify_api_exists` | Anti-hallucination check — real AND usable on a given version? |
|
|
26
|
+
| `list_api_versions` | since / deprecated / removed timeline + migration lineage |
|
|
27
|
+
| `get_release_notes` | What changed in a library/version |
|
|
28
|
+
|
|
29
|
+
Example verdict:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
verify_api_exists("scrollTargetBehavior", "16.0", "apple")
|
|
33
|
+
→ ❌ NOT AVAILABLE — introduced in 17.0, newer than 16.0. Will not compile there.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Run
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# From source
|
|
40
|
+
pip install -e .
|
|
41
|
+
python -m mobile_docs_mcp.server # stdio transport
|
|
42
|
+
|
|
43
|
+
# Once published
|
|
44
|
+
uvx mobile-docs-mcp
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Ships with a seed corpus, so it works immediately with no crawl.
|
|
48
|
+
|
|
49
|
+
## Editor & IDE setup (iOS + Android)
|
|
50
|
+
|
|
51
|
+
The server speaks MCP over stdio, so any MCP-capable editor can use it. All the
|
|
52
|
+
tools work for **both** platforms — you'll lean on the SwiftUI entries in an iOS
|
|
53
|
+
project and the Compose/androidx entries in an Android one, but nothing is
|
|
54
|
+
editor-specific. Two ways to launch it:
|
|
55
|
+
|
|
56
|
+
- **From source (this repo):** `command: "python"`, `args: ["-m", "mobile_docs_mcp.server"]`, with `cwd` set to the repo path.
|
|
57
|
+
- **Once published:** `command: "uvx"`, `args: ["mobile-docs-mcp"]` (no `cwd` needed).
|
|
58
|
+
|
|
59
|
+
Set `MOBILE_DOCS_DATA` in `env` to layer in any corpora you've crawled with the
|
|
60
|
+
ingesters (see "Growing the index").
|
|
61
|
+
|
|
62
|
+
### Claude Code (CLI)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# from source, shared with the repo via .mcp.json (project scope)
|
|
66
|
+
claude mcp add mobile-docs-mcp --scope project -- python -m mobile_docs_mcp.server
|
|
67
|
+
# or, once published
|
|
68
|
+
claude mcp add mobile-docs-mcp -- uvx mobile-docs-mcp
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Verify with `claude mcp list`, or `/mcp` inside a session.
|
|
72
|
+
|
|
73
|
+
### Claude Desktop
|
|
74
|
+
|
|
75
|
+
Edit `claude_desktop_config.json` (Settings → Developer → Edit Config), then
|
|
76
|
+
restart the app:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"mobile-docs-mcp": {
|
|
82
|
+
"command": "python",
|
|
83
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
84
|
+
"cwd": "/absolute/path/to/mobile-docs-mcp",
|
|
85
|
+
"env": { "MOBILE_DOCS_DATA": "data/android,data/apple" }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Cursor
|
|
92
|
+
|
|
93
|
+
Create `.cursor/mcp.json` in the project root (or `~/.cursor/mcp.json` for all
|
|
94
|
+
projects) — same `mcpServers` shape as above:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"mcpServers": {
|
|
99
|
+
"mobile-docs-mcp": {
|
|
100
|
+
"command": "python",
|
|
101
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
102
|
+
"cwd": "${workspaceFolder}"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Then enable it under Settings → MCP.
|
|
109
|
+
|
|
110
|
+
### Windsurf
|
|
111
|
+
|
|
112
|
+
Edit `~/.codeium/windsurf/mcp_config.json` (Cascade panel → MCP icon →
|
|
113
|
+
Configure). Same `mcpServers` shape; Windsurf supports `${env:VAR}` interpolation
|
|
114
|
+
so you can keep paths/secrets out of the file:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"mcpServers": {
|
|
119
|
+
"mobile-docs-mcp": {
|
|
120
|
+
"command": "python",
|
|
121
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
122
|
+
"cwd": "/absolute/path/to/mobile-docs-mcp"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Android Studio
|
|
129
|
+
|
|
130
|
+
Gemini in Android Studio is an MCP client. Go to **Settings → Tools → AI → MCP
|
|
131
|
+
Servers**, tick **Enable MCP Servers**, and paste the same `mcpServers` JSON
|
|
132
|
+
block shown for Claude Desktop. Confirm with the "Successfully connected"
|
|
133
|
+
notification, then type `/mcp` in the chat to see the tools. Great for checking
|
|
134
|
+
`androidx`/Compose availability against your module's `compileSdk` / library
|
|
135
|
+
versions without leaving the IDE.
|
|
136
|
+
|
|
137
|
+
### VS Code
|
|
138
|
+
|
|
139
|
+
VS Code's key is `servers` (not `mcpServers`) and wants an explicit `type`.
|
|
140
|
+
Create `.vscode/mcp.json` (commit it to share with the team):
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"servers": {
|
|
145
|
+
"mobile-docs-mcp": {
|
|
146
|
+
"type": "stdio",
|
|
147
|
+
"command": "python",
|
|
148
|
+
"args": ["-m", "mobile_docs_mcp.server"],
|
|
149
|
+
"cwd": "${workspaceFolder}",
|
|
150
|
+
"env": { "MOBILE_DOCS_DATA": "data/android,data/apple" }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Open the file and click **Start**, or run *MCP: List Servers* from the Command
|
|
157
|
+
Palette. Copilot Chat's Agent mode will then surface the tools.
|
|
158
|
+
|
|
159
|
+
### Xcode
|
|
160
|
+
|
|
161
|
+
Xcode 26.3+ is itself an **MCP server** (it exposes build / test / preview /
|
|
162
|
+
Apple-doc-search tools) rather than an MCP client — so you don't register
|
|
163
|
+
`mobile-docs-mcp` *inside* Xcode. Instead, run an agent that consumes both: point
|
|
164
|
+
Claude Code (or Cursor / Codex) at `mobile-docs-mcp` using the steps above while
|
|
165
|
+
it's also connected to Xcode's server. The agent then gets Xcode's build/preview
|
|
166
|
+
tools **and** this server's `verify_api_exists` version checks in one session —
|
|
167
|
+
e.g. it can confirm `scrollTargetBehavior` needs iOS 17 before writing it against
|
|
168
|
+
your iOS 16 deployment target, then build the project to check.
|
|
169
|
+
|
|
170
|
+
## Architecture
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
ingest/ (batch, offline) server.py (runtime)
|
|
174
|
+
android.py developer.android.com FastMCP
|
|
175
|
+
apple.py Apple JSON doc API │
|
|
176
|
+
│ ▼
|
|
177
|
+
▼ store.py — hybrid, version-aware
|
|
178
|
+
symbols.json + chunks.json 1. BM25 lexical recall
|
|
179
|
+
(version-tagged) 2. vector recall (optional)
|
|
180
|
+
3. RRF fusion
|
|
181
|
+
4. VERSION FILTER ← the differentiator
|
|
182
|
+
5. cross-encoder rerank (optional)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Retrieval is provider-agnostic (`embeddings.py`), same shape as a multi-provider
|
|
186
|
+
model gateway: BM25 works fully offline; vector recall and rerank switch on via
|
|
187
|
+
env var with no code change and degrade gracefully if a provider is missing.
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
MOBILE_DOCS_EMBEDDINGS=local # or openai ; default none (BM25-only)
|
|
191
|
+
MOBILE_DOCS_RERANK=local # default none
|
|
192
|
+
MOBILE_DOCS_DATA=data/android,data/apple # layer in crawled corpora
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Growing the index
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
python -m mobile_docs_mcp.ingest.android --out data/android \
|
|
199
|
+
--refs androidx.compose.foundation.lazy.LazyColumn \
|
|
200
|
+
--release-notes compose-foundation navigation
|
|
201
|
+
|
|
202
|
+
python -m mobile_docs_mcp.ingest.apple --out data/apple \
|
|
203
|
+
--paths swiftui/navigationstack swiftui/view/scrolltargetbehavior
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Then point the server at the output with `MOBILE_DOCS_DATA`.
|
|
207
|
+
|
|
208
|
+
## Status
|
|
209
|
+
|
|
210
|
+
MVP. The protocol layer, version logic, hybrid store, and tool surface are
|
|
211
|
+
production-shaped; the ingestion coverage is a seed. The real work — and the moat
|
|
212
|
+
— is breadth and freshness of the version-tagged index.
|
|
213
|
+
|
|
214
|
+
MIT.
|