Apple Documentation MCP Server. Search Apple developer docs, Swift Evolution proposals, and 600+ sample code projects with full-text search.
Add to Claude Desktop config.json
{
"mcpServers": {
"mihaelamj-cupertino": {
"command": "node",
"args": [
"~/.mcp/cupertino/index.js"
]
}
}
} Get the source and run locally
git clone https://github.com/mihaelamj/cupertino.git ~/.mcp/cupertino
cd ~/.mcp/cupertino Apple documentation CLI for humans and MCP server for AI agents.
Cupertino is a CLI for human developers and an MCP server for AI agents. Both surfaces use the same local index of Apple documentation, Swift packages, sample code, Human Interface Guidelines, Swift Evolution proposals, and Swift.org pages.

Latest: v1.3.0 (2026-05-31): per-source database bundle, read-only databases. The shipped bundle carries 351,505 documents / 240,543 symbols across 420+ frameworks. Release notes · CHANGELOG · Roadmap · live dashboard at https://cupertino.aleahim.com/. Follow updates on X: @cupertinomcp.
Cupertino is a local, structured documentation system for Apple platforms. It:
search, read, doctor, and setup commandsWhy build this:
Requires macOS 15+ (Sequoia) and ~4.2 GB free disk for the full v1.3.0 bundle (compressed download ~742 MB). Building from source additionally needs Swift 6.3+ and Xcode 26+ (use xcrun swift build, not bare swift).
One-command install (recommended): downloads a signed, notarized universal binary to /usr/local/bin and fetches the databases:
bash <(curl -sSL https://raw.githubusercontent.com/mihaelamj/cupertino/main/install.sh)
Homebrew:
brew tap mihaelamj/tap
brew install cupertino
cupertino setup # download the pre-built databases
Build from source:
git clone https://github.com/mihaelamj/cupertino.git
cd cupertino
make build # release binary (or: cd Packages && swift build -c release)
sudo make install # install to /usr/local/bin
cupertino setup # download the pre-built databases
The Homebrew path on Apple Silicon installs to
/opt/homebrew/bin/cupertino; Intel and manual installs use/usr/local/bin/cupertino. Runwhich cupertinoto confirm your path. See docs/DEPLOYMENT.md for distribution and CI/CD notes.
cupertino setup # download pre-built databases (~30s)
cupertino search "NavigationStack" --limit 5 # search from the terminal
cupertino read "apple-docs://swiftui/navigationstack" --source apple-docs
cupertino doctor # check local database health
cupertino serve # start the MCP server (also the default command)
Prefer to build the index yourself instead of downloading it? cupertino save --remote streams the corpus from GitHub and rebuilds locally, and cupertino fetch --source <name> crawls a single source from the original site. See docs/commands/ for every command, flag, and the slower self-hosted paths.
A terminal search prints a human-friendly result with scores and follow-up commands:
$ cupertino search "NavigationStack" --format text --limit 2
Question: NavigationStack
Searched: apple-docs, samples, swift-evolution, swift-org, swift-book, packages
======================================================================
[1] NavigationStack • source: apple-docs • score: 0.0324
apple-docs://swiftui/navigationstack
----------------------------------------------------------------------
A view that displays a root view and enables navigation to additional views.
▶ Read full: cupertino read "apple-docs://swiftui/navigationstack" --source apple-docs
💡 Narrow with --source <name>: apple-docs, samples, hig, apple-archive, swift-evolution, swift-org, swift-book, packages
💡 Filter by platform: --platform iOS --min-version 16.0 (or macOS / tvOS / watchOS / visionOS)
The same query over MCP returns a structured tool result an AI client can read, cite, and follow with read_document:
{
"name": "search",
"arguments": { "query": "NavigationStack", "source": "apple-docs", "limit": 2 }
}
Demo: Watch on YouTube.
Claude Code registers Cupertino globally with one command:
claude mcp add cupertino --scope user -- $(which cupertino)
Claude Desktop, OpenAI Codex, Cursor, VS Code (Copilot), GitHub Copilot for Xcode, Zed, Windsurf, and opencode are all covered with copy-paste config in docs/mcp-clients.md. Cupertino can also run as a stateless CLI Agent Skill with no server: see docs/agent-skill.md.
| Framework | Documents |
|---|---|
| Kernel | 39,396 |
| Matter | 24,320 |
| Swift | 17,466 |
| AppKit | 12,443 |
| Foundation | 12,423 |
| UIKit | 11,158 |
| Accelerate | 9,114 |
| SwiftUI | 7,062 |
| … | … |
| 420+ frameworks | 351,505 |
packages.db ships 185 packages with full source, stars, licenses, deployment-target platforms, and authored swift-tools-version--include-archive)uri, source, framework, language, title, content, summary, symbols, symbol_components). Title 10×, AST-extracted symbols 5×, summary 3×, framework 2×, CamelCase-split components 1.5×.symbols column, so a query like Task ranks the Swift Task struct above prose mentions of “task”.cupertino search (and the Search.SmartQuery API) fans the question across every source in parallel and fuses per-source rankings via reciprocal rank fusion (RRF, k=60, Cormack/Clarke/Büttcher 2009); one dead source never takes the whole query down.apple-docs://{framework}/{page}, swift-evolution://{proposal-id}, hig://{category}/{page}search: unified full-text search across every indexed source. Parameters: query (required), source, framework, language, include_archive, limit, and the min_ios/min_macos/min_tvos/min_watchos/min_visionos/min_swift platform filters (AND-combined; malformed values are rejected at the boundary with a clear error frame). Replaces the pre-#239 per-source tools.list_frameworks, read_document (format: json for agents, markdown for humans)list_samples, read_sample, read_sample_filesearch_symbols, search_property_wrappers, search_concurrency, search_conformances, search_generics, get_inheritanceSee docs/tools/ for per-tool documentation.
Resumable from saved state, change-detection to skip unchanged pages, a respectful 0.05 s default delay (configurable), automatic URL-queue deduplication, and priority queues so important content is fetched first.
Cupertino uses an ExtremePackaging architecture: 49 strict-producer SPM targets across 63 source packages. See docs/ARCHITECTURE.md for the full breakdown and docs/package-import-contract.md for the strict per-target import rules.
Foundation tier: SharedConstants, LoggingModels, MCPCore, MCPSharedTools, Resources
Infrastructure: ASTIndexer, Diagnostics, Logging (concrete, composition-root only)
Producers: Crawler, Core, Search, SampleIndex, Services,
AppleConstraintsKit, Availability, Cleanup, and more
Operation packs: Distribution (setup), Diagnostics (doctor),
Indexer (save), Ingest (fetch)
MCP layer: MCPSupport, MCPClient, SearchToolProvider
Front doors: CLI (cupertino), TUI (cupertino-tui)
Data flows through three distinct phases:
1. Fetch cupertino fetch --source apple-docs
WKWebView → Apple JSON API → JSON files on disk (~/.cupertino/docs/)
2. Save cupertino save --all
JSON → parse + AST extract → per-source SQLite FTS5 indexes
(~/.cupertino/apple-documentation.db, hig.db, …)
3. Serve cupertino serve
MCP server (stdio) ← JSON-RPC ← AI client
DocsResourceProvider + CupertinoSearchToolProvider
Key design principles: Swift 6.3 with 100% strict concurrency checking, value semantics and Sendable by default, actor isolation (@MainActor for WKWebView), explicit dependency injection with no singletons, and a hard separation of Crawling → Indexing → Serving.
Cupertino factors three reusable, independently-versioned Swift packages out of the monorepo. Each is its own public repository, depended on by tag (from: "0.1.0"), Foundation-only, and built so an external consumer can adopt it without pulling in cupertino’s engine:
| Package | Repo | What it is |
|---|---|---|
| SwiftMCPCore | mihaelamj/SwiftMCPCore | Neutral MCP wire types (the JSON-RPC + protocol value types). Not cupertino-specific; a general MCP building block. |
| SwiftMCPClient | mihaelamj/SwiftMCPClient | Neutral, transport-injectable MCP client (Client.MCP seam, MCPClient actor, subprocess transport). Depends on SwiftMCPCore. |
| CupertinoDataKit | mihaelamj/CupertinoDataKit | Cupertino’s public read contract: the documentation + sample-code read protocols (Search.DocumentReading, Search.SymbolReading, Search.Database, Sample.Index.Reader) plus every value type they return. Protocols + value types only, zero implementation; cupertino’s engine conforms server-side, and an embedded/in-process reader (e.g. an iOS app) conforms a different implementation. Cupertino’s foundation tier re-exports it (@_exported import CupertinoDataKit). |
The canonical living roadmap is #183; the diagram below tracks epic progress at a glance.
Status colors:
flowchart TB
classDef done fill:#34C759,stroke:#248A3D,color:#ffffff;
classDef active fill:#0A84FF,stroke:#0060DF,color:#ffffff;
classDef next fill:#FF9F0A,stroke:#C77700,color:#000000;
classDef partial fill:#FFD60A,stroke:#B59B00,color:#000000;
classDef todo fill:#8E8E93,stroke:#636366,color:#ffffff;
subgraph Legend["Status colors"]
direction TB
L1["Shipped"]:::done ~~~ L2["In progress"]:::active ~~~ L3["Next up"]:::next ~~~ L4["Partial or blocked"]:::partial ~~~ L5["Planned"]:::todo
end
Epic progress:
flowchart TB
classDef done fill:#34C759,stroke:#248A3D,color:#ffffff;
classDef active fill:#0A84FF,stroke:#0060DF,color:#ffffff;
classDef next fill:#FF9F0A,stroke:#C77700,color:#000000;
classDef partial fill:#FFD60A,stroke:#B59B00,color:#000000;
classDef todo fill:#8E8E93,stroke:#636366,color:#ffffff;
subgraph InFlight["Epics in flight"]
direction TB
E1221["#1221 recrawl (--resume in progress)"]:::active ~~~ E1036["#1036 per-source DB split"]:::partial ~~~ E191["#191 search quality + FTS"]:::partial
end
subgraph Next["Epics next"]
direction TB
E769["#769 layer separation"]:::next
end
subgraph Planned["Epics planned"]
direction TB
E268["#268 MCP capability (keystone #742)"]:::todo ~~~ E266["#266 availability annotation v2"]:::todo ~~~ E190["#190 source expansion"]:::todo ~~~ E1223["#1223 declarative pluggability"]:::todo ~~~ E1222["#1222 Linux port"]:::todo ~~~ E1228["#1228 semantic + vector"]:::todo ~~~ E189["#189 TUI (dormant)"]:::todo
end
subgraph Shipped["Epics shipped"]
direction TB
E943["#943 comprehensive query batteries"]:::done ~~~ E251["#251 unify sources + databases"]:::done
end
InFlight ~~~ Next ~~~ Planned ~~~ Shipped
| Operation | Time | Size |
|---|---|---|
cupertino setup (download pre-built bundle) | ~30 s | ~742 MB download, ~4.2 GB on disk |
| Build CLI | 10–15 s | 4.3 MB |
| Search query | <100 ms | n/a |
| Swift Evolution fetch | 2–5 min | 429 proposals |
| Swift.org fetch | 5–10 min | 501 pages |
Build the full index from local JSON (cupertino save --all) | ~12 h | ~2.8 GB apple-documentation.db + per-source siblings |
Full crawl of Apple docs from source (cupertino fetch) | ~12 days | ~404,000 raw pages → 351,505 indexed |
The full crawl is slow by design: with the 0.05 s default delay, ~404,000 pages cost ~5.6 hours in delay alone, and WKWebView rendering, parsing, and saving per page dominate the rest, pushing wall-clock to ~12 days at depth 21+. This is a one-time operation, and incremental updates skip unchanged pages. Almost everyone should run cupertino setup instead and get the same corpus in seconds.
make help # all available commands
make build # build release binaries
sudo make install # install to /usr/local/bin
make test # run all tests
make test-unit # fast unit tests only
make test-integration # all tests (includes network calls)
make format # SwiftFormat
make lint # SwiftLint
Tests: 3,095 @Test functions across 344 test files (493 @Suites); parameterized @Test(arguments:) cases expand further at runtime. Built on Swift Testing (@Test, @Suite, #expect) with withDependencies for injection, spanning unit tests, integration tests (real WKWebView against real Apple docs), and formatter tests.
Logging: structured os.log under the com.cupertino.cli subsystem (categories: crawler, mcp, search, cli, transport, evolution, samples, package-downloader, archive, hig).
log show --predicate 'subsystem == "com.cupertino.cli"' --last 1h
log stream --predicate 'subsystem == "com.cupertino.cli"'
MCP JSON-RPC wire traffic goes to stderr, not
os.log, because stdout carries the protocol itself. Capture it withcupertino serve 2>/tmp/cupertino-mcp.logor your client’s server-output panel. MCP lifecycle and diagnostic messages still log toos.logunder themcpcategory.
See CONTRIBUTING.md for the full build, test, and release workflow.
Released: v1.3.0 (2026-05-31): the per-source database bundle + read-only databases release. The unified search.db is split into 8 per-source databases shipped in rollback journal mode, so each opens read-only without an -shm sidecar and no query / read / serve connection can write or delete rows (#1194). databaseVersion is 1.3.0; cupertino setup downloads cupertino-databases-v1.3.0.zip (742 MB) carrying 351,505 documents / 240,543 symbols in apple-documentation.db (2.8 GB, user_version 18), plus packages.db (1.09 GB, 185 packages), apple-sample-code.db (192 MB), and the HIG / archive / evolution / org / book databases.
Previously: v1.2.1 (2026-05-23, maintenance + Source Independence Day), v1.2.0 “ironclad” (2026-05-20, search-quality release: rank-1 accuracy on canonical-lookup queries 52% → 92%), v1.1.0 (2026-05-14), v1.0.2 (2026-05-11). Full history in CHANGELOG.md.
docs/design/search-quality-eval.md): single-system baselines on 7 query classes + 3 paired v1.1.0 → v1.2.0 version-diff audits, all checked into docs/audits/Issues and pull requests are welcome, and I’d love to hear how you’re using Cupertino with your AI workflow. For questions and discussion, use GitHub Discussions.
I prefer collaboration over competition: if you’re working on something similar, let’s find ways to work together. Don’t hesitate to submit a PR because of code style; I’d rather have your contribution than perfect formatting. By participating you agree to abide by the Contributor Covenant Code of Conduct. For development setup, see CONTRIBUTING.md.
packages.dbapple-constraints.json and apple-conformances.json enrichment tablesMIT License, see LICENSE for details.
Note: This tool is for educational and development purposes. Respect Apple’s Terms of Service when using their documentation.
AI-powered task management system for AI-driven development. Features PRD parsing, task expansion, multi-provider support (Claude, OpenAI, Gemini, Perplexity, xAI), and selective tool loading for optimized context usage.
Provide coding agents direct access to Figma data to help them one-shot design implementation.
gitmcp.io is a generic remote MCP server to connect to ANY GitHub repository or project for documentation
MCP Server for Android/iOS application and device automation, development and app scraping. Simulator/Emulator/Physical devices like iPhone, Google Pixel, Samsung supported.
Create crafted UI components inspired by the best 21st.dev design engineers.
An Excel manipulation server providing workbook creation, data operations, formatting, and advanced features (charts, pivot tables, formulae).