Offline MCP server for Apple Developer Documentation, reading directly from a
Dash-format Apple_API_Reference.docset. No network calls, no Dash.app required —
just the .docset directory on disk.
LLM agents working on Apple platforms need accurate, current API documentation,
but developer.apple.com is heavy JS, scrapers fight TLS quirks, and Apple's docs
aren't shipped in Xcode anymore. Dash maintains a complete, regularly-updated
offline mirror as a single self-contained docset bundle. This server reads that
bundle directly.
- Python 3.11+
- An
Apple_API_Reference.docsetdirectory. The easiest way to get one is to install Dash and download the Apple API Reference docset there. After download the bundle lives at:You can copy it anywhere; the server doesn't need Dash running.~/Library/Application Support/Dash/DocSets/Apple_API_Reference/Apple_API_Reference.docset
Pick the option that fits your workflow.
uvx --from git+https://github.com/nzrsky/appleref-mcp appleref-mcpuv tool install git+https://github.com/nzrsky/appleref-mcp
appleref-mcp # binary on your PATHTo upgrade later: uv tool upgrade appleref-mcp.
git clone https://github.com/nzrsky/appleref-mcp.git
cd appleref-mcp
uv tool install --from . appleref-mcp
# or, for hacking:
uv sync && uv run appleref-mcpThe server looks for the docset in this order:
APPLEREF_DOCSETenvironment variable (path to the.docsetdirectory, or its parent)./Apple_API_Reference.docset~/Library/Application Support/Dash/DocSets/Apple_API_Reference/Apple_API_Reference.docset~/Apple_API_Reference.docset
If you don't have Dash installed, copy any existing Apple_API_Reference.docset
bundle to one of those paths or point APPLEREF_DOCSET at it.
The fastest path uses uvx so nothing needs to be installed up front:
claude mcp add appleref -- uvx --from git+https://github.com/nzrsky/appleref-mcp appleref-mcpIf your docset isn't in the default Dash location, pass APPLEREF_DOCSET:
claude mcp add appleref \
--env APPLEREF_DOCSET=/path/to/Apple_API_Reference.docset \
-- uvx --from git+https://github.com/nzrsky/appleref-mcp appleref-mcpAfter adding, restart Claude Code and verify:
claude mcp list # should show 'appleref'
# or, in a Claude Code session:
/mcp # interactive view of connected serversIf you installed via uv tool install, swap the command for the bare binary:
claude mcp add appleref -- appleref-mcp{
"mcpServers": {
"appleref": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/nzrsky/appleref-mcp",
"appleref-mcp"
],
"env": {
"APPLEREF_DOCSET": "/path/to/Apple_API_Reference.docset"
}
}
}
}Without a Claude client, you can drive the server directly over stdio:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| appleref-mcpYou should see two JSON-RPC responses listing the four tools.
| Tool | Purpose |
|---|---|
search_apple_docs(query, language?, framework?, type?, limit?) |
Find symbols by name. |
get_apple_doc(query, language?, framework?) |
Return a full documentation page as markdown. Accepts a name or a canonical path. |
list_frameworks(filter?) |
List indexed frameworks. |
list_types() |
List symbol kinds with counts. |
language is "swift" (default) or "objc".
The Dash docset stores documentation in two SQLite databases plus a directory of brotli-compressed files:
Contents/Resources/optimizedIndex.dsidx ← name → URL index (FTS4)
Contents/Resources/Documents/cache.db ← uuid → (data_id, offset, length)
Contents/Resources/Documents/fs/<data_id> ← brotli(concatenated DocC RenderJSON)
For a given symbol path:
canonical = "/documentation/swiftui/griditem"
uuid = lang_prefix + base64url(sha1(canonical)[:6]).rstrip("=")
(lang_prefix is "ls" for Swift, "lc" for ObjC)
→ refs WHERE uuid=? → (data_id, offset, length)
→ brotli.decompress(fs/<data_id>)[offset:offset+length] = DocC JSON
The server renders the JSON to markdown and returns it.
uv sync
uv run pytest -vTests run end-to-end against a real docset and skip cleanly if none is available.
MIT