{
  "markdown": "# 🍎 apple-stocks-mcp\n\n[![CI](https://github.com/helderpgoncalves/apple-stocks-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/helderpgoncalves/apple-stocks-mcp/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/apple-stocks-mcp?logo=npm)](https://www.npmjs.com/package/apple-stocks-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/apple-stocks-mcp?logo=npm&color=cb3837)](https://www.npmjs.com/package/apple-stocks-mcp)\n[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-listed-5965F2)](https://registry.modelcontextprotocol.io/v0/servers?search=apple-stocks-mcp)\n[![platform: macOS](https://img.shields.io/badge/platform-macOS-000000?logo=apple)](https://www.apple.com/macos/)\n[![Node.js](https://img.shields.io/badge/node-%E2%89%A518-339933?logo=node.js&logoColor=white)](https://nodejs.org)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)\n\nA **macOS-only** [Model Context Protocol](https://modelcontextprotocol.io) (MCP)\nserver that lets an AI assistant read **your own** data from the Stocks app that\nships with macOS — your watchlist, and the quotes, fundamentals and intraday\ncharts the app has already cached on **your Mac**.\n\n**100% local and read-only.** It reads files that already exist on your own\nmachine, in the Stocks app's container under your home folder. It makes **no\nnetwork requests**, uses **no external API**, needs **no API keys**, and sends\n**nothing anywhere**. The data is whatever the Stocks app last synced — open the\napp to refresh it.\n\n![apple-stocks-mcp demo](./docs/demo.gif)\n\n> ⚠️ **macOS only.** The data lives inside the macOS Stocks app's container, so\n> this server does not work on Linux or Windows. On a non-macOS host the server\n> still starts, but exposes a single `platform_info` tool that politely explains\n> it's macOS-only and how to remove it — no failing tools, no crashes.\n\n---\n\n## Quick start (30 seconds)\n\nOn a Mac, open the **Stocks app once** (so its data exists), then:\n\n**Claude Desktop / any MCP client** — add this and restart:\n\n```json\n{ \"mcpServers\": { \"apple-stocks\": { \"command\": \"npx\", \"args\": [\"-y\", \"apple-stocks-mcp\"] } } }\n```\n\n**Claude Code:**\n\n```bash\nclaude mcp add apple-stocks -- npx -y apple-stocks-mcp\n```\n\nThen ask: *\"What's the Apple stock doing today?\"* The first time, your client\nasks permission to use the tool — choose **Yes** (or \"Yes, and don't ask again\").\nThat's it. If anything's off, ask it to run **`stocks_doctor`** — it tells you\nexactly what to fix.\n\n---\n\n## Contents\n\n- [What you can ask](#what-you-can-ask)\n- [Privacy](#privacy)\n- [Where the data comes from](#where-the-data-comes-from)\n- [Tools](#tools) · [Resources](#resources) · [Prompts](#prompts)\n- [Example output](#example-output)\n- [Requirements](#requirements)\n- [Setup](#setup)\n- [FAQ & troubleshooting](#faq--troubleshooting)\n- [Development & testing](#development--testing)\n- [Legal](#legal)\n\n---\n\n## What you can ask\n\nOnce connected (see [Setup](#setup)), ask your assistant things like:\n\n- *\"What's in my stock watchlist?\"*\n- *\"What's the Apple stock doing today?\"*\n- *\"Show me the fundamentals for NVDA.\"*\n- *\"Which of my stocks are up the most today?\"*\n- *\"Summarize my whole watchlist.\"*\n\n---\n\n## Privacy\n\nThis is the most important section, so it's first.\n\n- **Read-only.** The server never modifies, deletes, or writes to the Stocks\n  app's data. It opens the SQLite caches with sqlite3's `-readonly` flag and only\n  parses the watchlist file. The single write-style action, `add_stock`, does\n  **not** touch any file — it just asks macOS to open a symbol in the Stocks app\n  so *you* can add it with a tap.\n- **Local only.** Every byte read stays on your machine and is only returned to\n  the MCP client you connected (e.g. your local AI assistant). There are **no\n  outbound network connections** in this server's code — you can verify this:\n  there is no `fetch`/`http`/`https` client call anywhere in `src/`.\n- **Your own data.** It reads only files owned by your user account, in your home\n  folder (`~/Library/Group Containers/group.com.apple.stocks/`). It does not\n  access other users' data, remote accounts, or anything outside that container.\n- **No telemetry, no analytics, no tracking.** None. Ever. The only thing ever\n  written outside the tool results is a one-line startup message to `stderr`\n  (which platform it started on) — that goes to your MCP client's local logs and\n  is **never** sent anywhere.\n- **You stay in control of access.** On recent macOS versions the app reading\n  this data (your terminal or MCP client) must be granted **Full Disk Access** by\n  you, in System Settings. Revoke it any time and the server can no longer read.\n\n---\n\n## Where the data comes from\n\nAll paths are inside your own user container\n`~/Library/Group Containers/group.com.apple.stocks/`:\n\n| Data | File (read-only) |\n| --- | --- |\n| Watchlist symbols | `Library/Documents/PrivateData/com.apple.stocks.private-production-dbstore.json` |\n| Quotes, market cap | `Library/Caches/shared-database` (SQLite, `quotes` table) |\n| Fundamentals (P/E, EPS, ranges…) | same SQLite cache (`quote_details` table) |\n| Company names / exchanges | same SQLite cache (`stock_metadata` table) |\n| Intraday chart (OHLCV) | `Library/Caches/sparkline-database` (SQLite, `sparklines` table) |\n\nThis is the same \"read the app's own local store\" approach used by other macOS\nMCP servers such as [`apple-notes-mcp`](https://github.com/sirmews/apple-notes-mcp).\nIt is reading **your** data from **your** Mac — analogous to exporting your own\ninformation — and it does not bypass any DRM, access any account, or contact any\nApple service.\n\n---\n\n## Tools\n\n| Tool | What it does |\n| --- | --- |\n| `list_watchlist` | List every ticker in your Stocks watchlist (in order). |\n| `get_quote` | Price + daily change for one or more symbols, from the local cache. |\n| `quote_watchlist` | Cached quotes for every symbol in the watchlist. |\n| `stock_details` | Fundamentals: day & 52-week range, market cap, volume, P/E, EPS, beta, dividend yield, next earnings. |\n| `stock_chart` | Cached intraday OHLCV chart (ASCII sparkline) + change vs previous close. |\n| `apple_stock` | Apple (AAPL) fundamentals + whether it's in the watchlist. |\n| `portfolio_summary` | Whole-watchlist analysis: up/down counts, top gainers/losers, breakdown by currency & exchange. |\n| `top_movers` | The biggest gainers and losers in the watchlist today. |\n| `search_watchlist` | Search the watchlist by symbol or company name. |\n| `stocks_doctor` | Diagnose your setup (macOS? data present? readable? Full Disk Access?). |\n| `add_stock` | **Opens** a symbol in the Stocks app so you can add it with one tap (no file is written). |\n| `platform_info` | Report whether the server can run here (always available; the only tool on non-macOS). |\n\n### Resources\n\n| Resource URI | Contents |\n| --- | --- |\n| `stocks://watchlist` | The watchlist symbols, one per line (`text/plain`). |\n| `stocks://quotes` | Cached quotes for every watchlist symbol (`application/json`). |\n\n### Prompts\n\n| Prompt | What it does |\n| --- | --- |\n| `analyze_portfolio` | Reviews the whole watchlist and highlights what's notable today. |\n| `research_stock` | Pulls fundamentals + intraday chart for one symbol and summarizes it. |\n\n### Why `add_stock` opens the app instead of writing the database\n\nThe watchlist lives in an encrypted, iCloud-synced store. Editing it by hand\nrisks corrupting your watchlist and breaking sync, so `add_stock` deliberately\n**does not write** anything — it uses the `stocks://` URL scheme to open the\nsymbol in the Stocks app, where you add it with one tap and the app keeps its\nown data consistent.\n\n---\n\n## Example output\n\nThese are the actual text results the tools return (symbols shown are generic\nexamples). Numbers come straight from your Stocks app's local cache.\n\n**`apple_stock`** / **`stock_details AAPL`** — fundamentals at a glance:\n\n```text\nAAPL (Apple Inc.): 299.18 USD  +3.23 (+1.09%) [open]\n  Open: 298.44   Day range: 298.07 – 299.75\n  52-week range: 196.86 – 317.4\n  Market cap: 4.39T   Volume: 11.12M (avg 47.14M)\n  P/E: 36.27   EPS: 8.26   Beta: 1.09   Div yield: 0.36%\n  Next earnings: 2026-07-30\nAAPL is in the watchlist.\n```\n\n**`stock_chart NVDA`** — intraday OHLCV as an ASCII sparkline:\n\n```text\nNVDA intraday (7 points)\n  ▁▁▂▃▆▇█\n  prev close: 204.65   last: 208.69   day range: 207.36 – 208.69\n  change vs prev close: +4.04 (+1.97%)\n```\n\n**`portfolio_summary`** — whole-watchlist analysis:\n\n```text\nWatchlist summary — 98/99 quoted (1 without a cached quote)\n  Up: 57   Down: 41   Flat: 0\n\n  Top gainers:\n    NVDA: +1.97%\n    AMD:  +4.13%\n    MSFT: +0.31%\n  Top losers:\n    INTC: -2.10%\n    ...\n\n  By currency:\n    USD: 82\n    EUR: 16\n  By exchange:\n    NASDAQ: 38\n    NYSE: 35\n    XETRA: 9\n    ...\n```\n\n**`get_quote [\"AAPL\",\"MSFT\",\"BTC-USD\",\"EGL.LS\"]`** — one line per symbol, across\nUS / crypto / European tickers:\n\n```text\nAAPL (Apple Inc.): 299.18 USD  +3.23 (+1.09%) [open]\nMSFT (Microsoft Corporation): 378.83 USD  -0.08 (-0.02%) [open]\nBTC-USD (Bitcoin USD): 64291.09 USD  -928.50 (-1.42%) [open]\nEGL.LS (Mota-Engil, SGPS, S.A.): 4.67 EUR  -0.04 (-0.81%) [open]\n```\n\n### What each tool returns\n\n| Tool | Key fields in the result |\n| --- | --- |\n| `get_quote` / `quote_watchlist` | symbol, name, price, currency, daily change & %, market state |\n| `stock_details` | the above **plus** open, day range, 52-week range, market cap, volume & average volume, P/E, EPS, beta, dividend yield, next earnings date |\n| `stock_chart` | per-point open/high/low/close/volume, previous close, day range, change vs previous close, ASCII sparkline |\n| `portfolio_summary` | quoted vs total, up/down/flat counts, top gainers/losers, breakdown by currency and exchange |\n| `top_movers` | ranked gainers and losers (symbol, price, change %) |\n\n---\n\n## Requirements\n\n- **macOS**, with the **Stocks app** opened at least once (so its data exists).\n- **Node.js ≥ 18.**\n- The system `sqlite3` at `/usr/bin/sqlite3` (ships with macOS).\n- On recent macOS versions, the MCP client (or your terminal) may need\n  **Full Disk Access** to read the Stocks container. If tools return a\n  \"not found / unreadable\" error, run the `stocks_doctor` tool, then grant\n  Full Disk Access in *System Settings → Privacy & Security → Full Disk Access*.\n\n---\n\n## Setup\n\n### Option A — npx (no install)\n\nAdd this to your MCP client config (e.g. Claude Desktop:\n`~/Library/Application Support/Claude/claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-stocks\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"apple-stocks-mcp\"]\n    }\n  }\n}\n```\n\n### Option B — from source\n\n```bash\ngit clone https://github.com/helderpgoncalves/apple-stocks-mcp.git\ncd apple-stocks-mcp\nnpm install            # also builds via the `prepare` hook\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-stocks\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/apple-stocks-mcp/dist/index.js\"]\n    }\n  }\n}\n```\n\n### Claude Code\n\nAdd it as an MCP server:\n\n```bash\nclaude mcp add apple-stocks -- npx -y apple-stocks-mcp\n```\n\n…or install it as a **plugin** (this repo is also a Claude Code plugin\nmarketplace), which wires up the MCP server for you:\n\n```text\n/plugin marketplace add helderpgoncalves/apple-stocks-mcp\n/plugin install apple-stocks-mcp@apple-stocks\n```\n\nRestart the client after editing the config.\n\n### OpenAI Codex\n\nThis repo is also an **OpenAI Codex plugin**. Add the marketplace and install:\n\n```bash\ncodex plugin marketplace add helderpgoncalves/apple-stocks-mcp\ncodex plugin install apple-stocks-mcp\n```\n\nOr add it as a plain MCP server in your Codex config (`command: npx`,\n`args: [\"-y\", \"apple-stocks-mcp\"]`).\n\n---\n\n## Quick local test\n\nThe server speaks JSON-RPC over stdio:\n\n```bash\nprintf '%s\\n' \\\n'{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"t\",\"version\":\"1\"}}}' \\\n'{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}' \\\n'{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"apple_stock\",\"arguments\":{}}}' \\\n| npx -y apple-stocks-mcp\n```\n\nExample output: `AAPL (Apple Inc.): 299.18 USD  +3.23 (+1.09%) [open]`\n\nIf anything looks off, run the built-in diagnostics tool — ask your assistant to\nrun `stocks_doctor`, or:\n\n```bash\nprintf '%s\\n' \\\n'{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"t\",\"version\":\"1\"}}}' \\\n'{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}' \\\n'{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"stocks_doctor\",\"arguments\":{}}}' \\\n| npx -y apple-stocks-mcp\n```\n\n---\n\n## FAQ & troubleshooting\n\nThe tools' error messages are self-explanatory and tell you exactly what to do,\nso you rarely need this section. When in doubt, ask your assistant to run\n**`stocks_doctor`** — it checks everything and prints the fix.\n\n<details>\n<summary><b>It asks for permission the first time. Is that normal?</b></summary>\n\nYes — that's Claude's standard safety prompt the first time *any* MCP tool runs.\nChoose **Yes** (or \"Yes, and don't ask again\" to skip it next time). It's not an\nerror and nothing is sent anywhere.\n</details>\n\n<details>\n<summary><b>A tool says the data is \"not found\" or \"unreadable\".</b></summary>\n\nThe message tells you which case it is. The two causes:\n\n1. **The Stocks app has never run.** Open the macOS Stocks app once so it creates\n   its data, then try again.\n2. **Full Disk Access.** On recent macOS, the app running this server (your\n   terminal, or your MCP client) must be granted **Full Disk Access**:\n   1. System Settings → Privacy & Security → **Full Disk Access**\n   2. Turn it **on** for your terminal / MCP client (add it with **+** if missing)\n   3. **Fully quit and reopen** that app, then try again\n\nRun `stocks_doctor` to re-check.\n</details>\n\n<details>\n<summary><b>First call times out or shows \"failed to connect\".</b></summary>\n\nThe very first run downloads the package via `npx`, which can take a moment. Just\ntry again, or raise the startup timeout: start your client with\n`MCP_TIMEOUT=60000` (milliseconds).\n</details>\n\n<details>\n<summary><b>Why aren't the quotes real-time?</b></summary>\n\nThis server reads the Stocks app's **local cache** — the last data the app\nsynced. It intentionally makes no network calls. To refresh, open the Stocks app\n(or its widget); the cache updates and the next tool call reflects it.\n</details>\n\n<details>\n<summary><b>A symbol in my watchlist returns \"Not in the Apple Stocks cache\".</b></summary>\n\nThe app hadn't cached a quote for that exact symbol when you asked (some tickers,\ne.g. certain regional listings, aren't always cached). Open the Stocks app and\nview the symbol once, then retry. The watchlist still lists it; only its quote\nwas missing.\n</details>\n\n<details>\n<summary><b>Can it add a stock to my watchlist automatically?</b></summary>\n\n`add_stock` **opens** the symbol in the Stocks app so you add it with one tap. It\ndeliberately does **not** write to the app's encrypted, iCloud-synced store —\nthat would risk corrupting your watchlist and sync. This is a safety decision.\n</details>\n\n<details>\n<summary><b>Does it work on Linux or Windows?</b></summary>\n\nNo. The data lives in the macOS Stocks app's container, so the server is\nmacOS-only. (The pure parsing logic is unit-tested on Linux CI using synthetic\nfixtures, but the real data only exists on macOS.)\n</details>\n\n<details>\n<summary><b>Is any of my data sent anywhere?</b></summary>\n\nNo. There are **zero** network calls in the source — only local `sqlite3`\n(read-only) and `open`. Everything read is returned solely to the MCP client you\nconnected. See [Privacy](#privacy).\n</details>\n\n---\n\n## Development & testing\n\n```bash\nnpm run build      # compile to dist/\nnpm run typecheck  # type-check only\nnpm test           # build + run the test suite\n```\n\nTests run against **synthetic fixtures** in `test/fixtures/` (a generated\n`dbstore.json` and two small SQLite databases) — they **never touch your real\nStocks data**. `STOCKS_TEST_MODE=1` bypasses the macOS gate so the pure\nparsing/formatting logic can be tested on any OS, which is what CI does\n(GitHub Actions, Linux, Node 18/20/22).\n\nData paths can be overridden via env vars (used by the tests):\n`STOCKS_DBSTORE_PATH`, `STOCKS_SHARED_DB_PATH`, `STOCKS_SPARKLINE_DB_PATH`,\n`STOCKS_SQLITE_BIN`.\n\n### Project layout\n\n```\nsrc/\n  index.ts           # MCP server: tools, resources, prompts\n  appleStocks.ts     # reads your Stocks app data (read-only): watchlist + quotes/details/chart\n  bplist-parser.d.ts\ntest/\n  appleStocks.test.ts\n  fixtures/          # synthetic data — no personal holdings\ndocs/\n  demo.tape          # VHS script that generates demo.gif\n  run-tool.sh        # helper used by the demo\nserver.json          # MCP Registry metadata\n.github/workflows/ci.yml\n```\n\nTo regenerate the demo GIF (requires [VHS](https://github.com/charmbracelet/vhs)):\n\n```bash\nvhs docs/demo.tape   # writes docs/demo.gif\n```\n\n---\n\n## Legal\n\n### Not affiliated with Apple\n\nThis is an independent, community project. It is **not affiliated with,\nendorsed by, sponsored by, or supported by Apple Inc.** \"Apple\", \"Apple Stocks\",\n\"Stocks\", \"macOS\", and related marks are trademarks of Apple Inc. They are used\nhere **only nominatively** — to describe, factually and accurately, which app's\nlocal data this software reads. No claim of ownership or endorsement is made or\nimplied.\n\nThis project ships no Apple code, assets, or trademarks, and does not bundle or\nredistribute any Apple data.\n\n### How it accesses data\n\nThe server reads files that already exist on **your own Mac**, under **your own**\nuser account, in **read-only** mode. It does **not** circumvent any technical\nprotection measure or DRM, does **not** access any online account or third-party\ndata, and does **not** transmit data off your machine. The cache file formats may\nchange between macOS versions; if that happens, a tool may simply return \"no data\"\nrather than misbehave.\n\n### Not financial advice\n\nAll figures are read from your Stocks app's local cache, may be **delayed or\ninaccurate**, and are provided **as-is**. Nothing here is investment, financial,\nlegal, or tax advice. Do your own research; do not rely on this software for\ntrading decisions. Market data ultimately originates from third-party providers\nvia the Stocks app and is subject to their terms.\n\n### Warranty\n\nThis software is provided \"AS IS\", without warranty of any kind, to the fullest\nextent permitted by law. See the [MIT License](./LICENSE). Use at your own risk.\n\n---\n\n## License\n\n[MIT](./LICENSE) © Hélder Gonçalves\n",
  "bytes": 18667,
  "sha": "e9e0715682ae270146003663c8ff751bc0efb0af4d1cd49fbcbdc18b317876a8",
  "repo_slug": "helderpgoncalves/apple-stocks-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_helderpgoncalves_apple_stocks__4511cf14/readme"
}