Offline-first MCP server (and Antigravity plugin) for Apple Developer Documentation.
Local SQLite FTS5 over 65,787 symbols across SwiftUI, UIKit, Foundation, SwiftData, Combine, AppKit, Swift Standard Library, Observation, and CoreLocation. Optional Gemini embeddings for conceptual / visual queries. DocC JSON rendered to Markdown agents can actually use.
Two modes, same binary:
| Mode | What you need | What you get |
|---|---|---|
| Offline | Node 22+ and data/apple-docs.db |
Fast BM25 + wildcard symbol search, local docs, CDN fallback only when a symbol is missing |
| Hybrid | Offline + GEMINI_API_KEY or Google ADC |
Same lexical path, plus vector search, RRF fusion, and UI-layout preview cards |
No API key? It still works offline without a key. That is the point.
Coding agents hallucinate deprecated Apple APIs. Live doc scrapers are accurate until the CDN rate-limits you. This repo keeps a local index for the hot path and only hits Apple or Gemini when it has to.
Ships with:
search_symbols— lexical FTS5 search with exact-name boost, universal wildcard globbing (Grid*,*Style,Navigation*View), kind aliasing (funcmatches DocCmethod), runnable copy-pasteget_documentationcalls, and optional framework / platform filters (never calls Gemini)semantic_search— natural-language / behavioral queries (hybrid vector + FTS5 with guard against demoting exact symbols on sparse embeddings; falls back to lexical if Gemini credentials are not configured or circuit breaker trips)get_documentation— point lookup by symbol title (NavigationStack) or path (/documentation/swiftui/view), with disambiguation candidate list for colliding names, and clean error flags on missing symbolsdiscover_technologies— database-backed discovery listing indexed frameworks with exact symbol counts and valid tool call paginationindex_info/get_version— inspect runtime SQLite database status, symbol count, and freshness- Antigravity skill + rules that tell the agent to verify APIs and prefer
NavigationStack,@Observable, SwiftData, Swift Concurrency
The MCP tool shape (discover / choose technology, symbol search, get documentation) follows the path opened by MightyDillah/apple-doc-mcp. That server talks to Apple’s live documentation. This project is a separate codebase: local FTS5 index, hybrid ranking, DocC formatter, and Antigravity plugin packaging.
If you want always-fresh docs and npx with no native addon, use that one. If you want offline lookup + ranking + agent rules, use this one.
- Node.js 22+ (uses
process.loadEnvFile; badge is not decorative) - A working C/C++ toolchain the first time
better-sqlite3compiles (native addon; see docs/TROUBLESHOOTING.md) - Optional: Gemini API key or
gcloud auth application-default login
node -v # >= 22
npm install
npm run buildagy plugin install .
# or
agy plugin install AndrewMason7/apple-doc-plugin
agy plugin validate .That registers the MCP server (bin/launcher.cjs), the apple-docs skill, and rules/AGENTS.md.
Build first, then point MCP at the compiled entrypoint. Gemini env is optional.
{
"mcpServers": {
"apple-docs": {
"command": "node",
"args": ["/absolute/path/to/apple-doc-plugin/dist/index.js"],
"env": {
"GEMINI_API_KEY": "YOUR_GEMINI_API_KEY"
}
}
}
}Omit GEMINI_API_KEY for offline-only. You can also run bin/launcher.cjs if you installed the plugin layout.
Package name on npm is
apple-doc-plugin. Do notnpx apple-doc-mcp-serverand assume it is this repo — that name already belongs to MightyDillah’s live server.
Use the smallest tool that answers the question.
| Tool | Use when | Notes |
|---|---|---|
semantic_search |
You know the behavior or UI concept, not the symbol ("prevent sheet swipe dismiss") |
Preferred for agents. Needs Gemini for the vector half; lexical still runs if the circuit breaker is open or creds missing. Guards against demoting symbols when vectors are sparse (<100 items). |
search_symbols |
You know a name or pattern (Grid*, *Style, Navigation*View) |
Always purely local lexical. Exact title match gets a large score boost. Includes runnable copy-paste get_documentation calls and kind aliases (symbolType: "func" matches method). |
get_documentation |
You already have a symbol or DocC path (NavigationStack, SwiftUI/View) |
Point lookup: local SQLite first, Apple DocC CDN if missing. Resolves by title or path. Returns disambiguation candidates if ambiguous and isError: true if unresolvable. |
discover_technologies |
You need the list of indexed frameworks | Database-backed discovery showing exact symbol counts per framework with valid tool JSON pagination. |
get_version / index_info |
You want server version or snapshot freshness | Reports runtime symbol count, indexed frameworks, snapshot build timestamp, and embedding availability. |
semantic_search({ "query": "prevent user from dragging sheet down to close", "framework": "SwiftUI" })
semantic_search({ "query": "three column sidebar split view diagram", "framework": "SwiftUI" })
search_symbols({ "query": "Grid*" })
search_symbols({ "query": "*Style", "framework": "SwiftUI" })
search_symbols({ "query": "Navigation*View", "framework": "SwiftUI" })
search_symbols({ "query": "interactiveDismissDisabled", "symbolType": "func" })
get_documentation({ "path": "NavigationStack" })
get_documentation({ "path": "Button", "framework": "SwiftUI" })
get_documentation({ "path": "/documentation/swiftui/view" })query
├─ sanitize / clamp / escape FTS
├─ lexical: SQLite FTS5 BM25 (+100 exact-title boost)
└─ optional semantic: gemini-embedding-2 (3072-d), cosine vs precomputed L2 norms
└─ skip on missing creds, 401/403/429/5xx/timeout (30s circuit breaker)
fuse with Reciprocal Rank Fusion (k = 60)
optional suffix-wildcard rerank (types & protocols first)
attach visual preview markdown when a media hit exists
slice to maxResults
get_documentation does not go through that fusion path. It is a point lookup: local row → else CDN → DocC AST formatter → Markdown.
The shipped data/apple-docs.db is a snapshot (~99,903 symbols across SwiftUI, UIKit, Foundation, SwiftData, Combine, AppKit, Observation, CoreLocation). It goes stale when Apple ships new APIs.
cp .env.example .env # optional; add GEMINI_API_KEY to also rebuild vectors
npm run build:indexWhat build:index does:
- Open SQLite in WAL mode, ensure tables + FTS5 exist
- For each configured framework, pull the symbol tree + overview DocC from Apple’s CDN
- Upsert symbols and abstracts
- If Gemini auth is present: embed documents (asymmetric title/abstract prompts) and referenced UI media
- If not: log that this pass is FTS5-only
INSERT INTO symbols_fts(symbols_fts) VALUES('rebuild')PRAGMA wal_checkpoint(TRUNCATE)+VACUUM
Expect this to take a while and to hit Apple’s CDN. Hybrid rebuilds also cost Gemini embeddings. Run it on a machine with network, then copy the db if you want.
Override the db location with APPLE_DOCS_DB_PATH.
cp .env.example .env| Variable | Required | Purpose |
|---|---|---|
GEMINI_API_KEY |
No | Gemini embeddings (gemini-embedding-2). Google AI Studio |
GOOGLE_APPLICATION_CREDENTIALS |
No | Service-account JSON for ADC. gcloud auth application-default login also works |
APPLE_DOCS_DB_PATH |
No | Alternate path to the SQLite file (default data/apple-docs.db) |
The process loads .env at startup. Credentials are not logged.
apple-doc-plugin/
├── bin/launcher.cjs # Antigravity bootstrap
├── data/apple-docs.db # FTS5 + optional vectors
├── rules/AGENTS.md # modern Apple API rules for agents
├── skills/apple-docs/ # skill + workflow
├── scripts/build-index.ts # corpus rebuild
├── src/
│ ├── index.ts # stdio MCP entry
│ ├── apple-client/ # HTTP + DocC AST → Markdown
│ └── server/
│ ├── handlers/ # one handler per tool
│ ├── services/ # hybrid / semantic / resolution
│ └── db/ # SQLite access
└── test/
npm install
npm run build
npm test # Node native runner; currently 82 tests
npm run check # tsc --noEmit + prettier
npm run format
npm run build:index # rebuild the snapshot (network)better-sqlite3 will compile on install. If that fails, see docs/TROUBLESHOOTING.md — you are missing platform build tools, not an MCP bug.
- The snapshot is not the entire Apple documentation corpus. Niche frameworks may miss.
get_documentationcan still fall back to the live DocC CDN for a known path. - Hybrid quality depends on whatever was embedded the last time you ran
build:indexwith Gemini credentials. - Visual previews are derived from media references in Apple’s docs. Treat them as lookup aids, not a HIG replacement.
- Native addon (
better-sqlite3) requires C++ compilation tools during install.
MIT © 2026 Andrew Mason