One MCP server, two stores: App Store Connect + Google Play.
개요
Let your AI assistant manage both stores. Drop this line on your AI assistant, it handles the rest: How much is Nota Defteri's monthly subscription on App Store vs. Play in Turkey? ₺129.99 on the App Store, ₺99.99 on Play. Play is noticeably cheaper — if you want the same price in both stores, you need to update the base plan on Play. No other MCP server can answer that in a single call, because they all look at one store. magaza-mcp sees both at once. No server sits in the middle: the package runs on your own machine, talks directly to Apple and Google, and your keys never leave your Keychain. Almost every MCP server on the market covers a single store. If you want both, you install two separate servers, juggle two separate tool sets, and manually stitch together any question that needs a comparison. Tell your assistant (Claude Code, Antigravity, Cursor, Codex, Gemini CLI…): The assistant reads AGENTS.md and handles the entire setup. All you do is answer its questions:
README
You: How much is Nota Defteri’s monthly subscription on App Store vs. Play in Turkey?
Assistant: ₺129.99 on the App Store, ₺99.99 on Play. Play is noticeably cheaper — if you want the same price in both stores, you need to update the base plan on Play.
No other MCP server can answer that in a single call, because they all look at
one store. magaza-mcp sees both at once.
flowchart LR
A["🤖 Your assistantClaude · Antigravity · Cursor"] -->|MCP / stdio| B["📦 magaza-mcpruns on your machine"]
B -->|appstore__| C["🍎 App Store Connect"]
B -->|play__| D["🤖 Google Play"]
B -->|magaza__| E["🔀 Both at oncecomparison · diagnostics"]
E -.-> C
E -.-> D
F["🔑 Keychain"] -.->|keys stay here| B
style B fill:#2d6cdf,stroke:#1a4a9e,color:#fff
style E fill:#7c3aed,stroke:#5b21b6,color:#fff
style F fill:#059669,stroke:#047857,color:#fff
No server sits in the middle: the package runs on your own machine, talks directly to Apple and Google, and your keys never leave your Keychain.
📚 Table of contents
| 🎯 Why this exists | The difference from single-store servers |
| ⚡ Setup | Have your assistant do it — you don’t type commands |
| 🧑💻 Manual setup | If you’re not using an assistant |
| 🧩 Do the two stores mix up? | No — here’s why |
| 💬 What you can ask | Example prompts |
| 🧰 Tools | Full list of all 39 tools |
| 🌐 Full API access | 1,440 operations, ~8,500 tokens |
| 🔑 Required permissions | What Apple and Google require |
| 🔒 Security | Keys, approval gates, telemetry |
| 🩺 Troubleshooting | Common errors |
🎯 Why this exists
Almost every MCP server on the market covers a single store. If you want both, you install two separate servers, juggle two separate tool sets, and manually stitch together any question that needs a comparison.
| Question | With single-store servers | With magaza-mcp |
|---|---|---|
| “How much is this subscription in both stores?” | Two separate queries, manual comparison | One call, side by side |
| “User paid but didn’t get premium, what’s wrong?” | You figure out which store first | Scans both at once, ranks findings |
| “Where is what published?” | Two lists, manual matching | One list with iOS/Android pairs already matched |
The real win isn’t more tools: it’s tools that can query both stores in the same call, which is only possible once both are in one server.
⚡ Setup
Tell your assistant (Claude Code, Antigravity, Cursor, Codex, Gemini CLI…):
https://github.com/tunaarikaya/magaza-mcp — install this, read AGENTS.md
The assistant reads AGENTS.md and handles the entire setup. All you do is answer its questions:
You › https://github.com/tunaarikaya/magaza-mcp — install this, read AGENTS.md
Assistant › Looking for your keys on this machine...
Found two keys:
App Store : ~/Downloads/AuthKey_ABC123DEFG.p8 (Key ID ABC123DEFG)
Play : ~/.config/play/account.json ([email protected]...)
Want me to use these? If there's another file, tell me the path,
or copy the key and paste it — either works.
You › yes, use them
Assistant › I need the Issuer ID for App Store. It's the UUID above the key
list on App Store Connect → Users and Access → Integrations.
You › 69a6de70-0000-0000-0000-000000000000
Assistant › ✓ App Store Connect connected — 4 apps found
✓ Google Play connected — 3 apps found
✓ Registered in Claude Code and Antigravity settings
Restart Claude Code, then ask:
"List my apps across both stores"
If it can’t find your key, it will ask you how to proceed: give it the file path, copy the key to your clipboard, or — if you don’t have a key yet — it’ll walk you through getting one step by step.
[!IMPORTANT] The assistant never sees the contents of your key. It runs the setup, but the commands take the file’s path, read its contents themselves, and write it straight into the Keychain. Even when you paste the key via clipboard (
pbpaste | …), the content flows through a pipe and never enters the assistant’s context. AGENTS.md tells the assistant this explicitly.
After setup, restart any open applications — MCP servers only load at startup.
🧑💻 Manual setup
If you’re not using an assistant, a wizard does the same job:
npx magaza-mcp kur
Keys are never written to the config file. On macOS they’re saved to the
Keychain; the config file only gets which stores are enabled (MAGAZALAR).
On systems without Keychain access, it falls back to a file with 0600
permissions.
🧩 Do the two stores mix up?
No — and that’s not an accident, it’s the design itself.
1. Tool names are separated by prefix. Every tool going to App Store
starts with appstore__, every tool going to Play starts with play__. A
tool never talks to both APIs. There’s no shared name, so there’s nothing to
mix up.
2. Tools for the store you didn’t pick are never loaded. On startup, the
server reads the MAGAZALAR variable and builds the tool list from it — the
other store’s tools aren’t even loaded into memory, aren’t shown to the
model, and cost zero tokens.
| Setup | Tools loaded |
|---|---|
| Both stores | 39 |
| App Store only | 20 |
| Play only | 19 |
| Read-only (both stores) | 26 |
3. Cross-store tools only exist when both stores are enabled. In a single-store setup they’re never created at all — they’d have no meaning.
4. The dispatch tools know their scope too. The magaza parameter on
magaza__endpoint_ara and magaza__cagir is an enum that only accepts the
stores you’ve set up. If you only installed Play, the model can’t make a call
with magaza: "appstore" — the schema doesn’t allow it.
💬 What you can ask
The app names in the examples are made up; you’d use your own app’s name.
Both stores at once
- “List my apps across both stores — where’s each one published?”
- “What’s Nota Defteri’s monthly subscription on App Store vs. Play in Turkey? Is there a difference?”
- “A user says they paid but didn’t get premium. Check the purchase setup in both stores.”
App Store
- “Which of my versions is stuck in review?”
- “Did yesterday’s TestFlight build finish processing?”
- “Summarize the 1- and 2-star reviews from the last week — what’s the most common complaint?”
- “Update the ‘What’s New’ text for the version in preparation.”
Google Play
- “Which version is on the production channel and what percentage of users does it reach?”
- “Has the crash rate gone up over the last 14 days?”
- “Is this purchase token valid, is the subscription still active?”
- “Draft a polite reply to this review, but show me first.”
🧰 Tools
The prefix tells you which store a tool goes to. Tools marked ✎ modify
data and won’t run without onayla=true.
🌐 Full API access
The curated tools cover most day-to-day work. For everything else, the server carries the entire API surface of both stores:
| Source | Operations |
|---|---|
| App Store Connect API v4.5 | 1,270 |
| Android Publisher API v3 | 145 |
| Play Developer Reporting API v1beta1 | 25 |
| Total | 1,440 |
When the curated tools aren’t enough, the model first finds the operation it
needs with magaza__endpoint_ara, then runs it with magaza__cagir.
Why aren’t they all separate tools?
MCP tool definitions get loaded into context on every request — the installed tool list is paid for again on every message, even if you don’t use any of them.
| Tools | Paid on every message | |
|---|---|---|
| magaza-mcp | 39 | ~8,500 tokens |
| If all were separate tools | 1,440 | ~210,000 tokens |
[!NOTE] Nothing is locked away: all 1,440 operations are reachable, but the ones you don’t use cost nothing. There’s no “should I turn this feature on, it costs tokens” setting either — there’s nothing to turn on.
The catalogs are generated from Apple’s and Google’s official
specifications: Apple’s published App Store Connect OpenAPI file, and
Google’s Android Publisher and Play Developer Reporting discovery documents.
There’s no hand-written endpoint list. The 159 operations Apple marks as
deprecated aren’t dropped from the catalog — some of them are the only way to
reach that capability — but their summaries start with [ESKİMİŞ]
(deprecated) and are pushed down in search results.
🔑 Required permissions
App Store Connect — The App Manager role is enough when creating the key; Admin isn’t required. Exceptions: user/access management endpoints and some analytics reports need higher privileges.
Google Play — Both steps are required:
- The service account must be invited from Play Console → Users and permissions and granted access to the relevant apps.
- The Android Publisher API and Play Developer Reporting API must be enabled on the Cloud project. App listing and crash metrics come from the Reporting API, so the second one is genuinely required too.
[!WARNING] Contract, tax, and banking information cannot be read with any API key. Apple never exposes this data to the API at all; only the Account Holder can see it in the dashboard.
🔒 Security
- Keys live in the Keychain. The Apple
.p8and Google service account JSON are stored in the macOS Keychain; never written to config files, environment variables, or the repo. - The assistant never sees the key, even when it runs the setup. The
anahtarcommand takes the file’s path, reads the content itself, and writes it straight to the vault; a key given via clipboard also flows through a pipe. The key’s content never appears in any command’s output —durumonly prints the last four characters of the Key ID,taraonly prints file paths. - Operations that modify data require approval. Write tools don’t run on
the first call: they return what would happen and the expected request
body; the operation only runs once the user approves and it’s called again
with
onayla=true. This is enforced server-side — it doesn’t depend on the client’s approval UI. - Read-only mode.
--salt-okunur(orSALT_OKUNUR=1) removes every write-capable tool from the list entirely: the model can’t see them or call them. 39 tools become 26.magaza__cagirstays in the list because it’s also the single gateway for read endpoints in the catalog — but it refuses write operations when read-only mode is on. - Path parameters are validated. IDs passed to tools are encoded before
entering a URL; path-traversal attempts like
.and..are rejected. For absolute URLs the target host is validated, so no request can carry a token to anywhere other than Apple or Google. - Clients can see which tools modify data. The tool list ships with MCP
annotations(readOnlyHint,destructiveHint). - Package provenance is verifiable. Every version published to npm is built inside GitHub Actions, and npm generates a Sigstore-signed provenance attestation: the Provenance section on the npm page shows which commit in this repo the tarball you downloaded was built from. No publish token is stored in the repo; GitHub issues a short-lived, signed identity on every release (trusted publishing), so there’s no publish key to steal either.
- No telemetry. No analytics, error reports, or usage data are sent.
Network traffic only goes to
api.appstoreconnect.apple.com,androidpublisher.googleapis.com,playdeveloperreporting.googleapis.com, andoauth2.googleapis.comfor tokens. The one exception is the twofiyat_analizitools, which read public purchasing-power figures fromapi.worldbank.org(no key, nothing of yours is sent). There’s no server in the middle; data flows directly between your machine and Apple/Google.
🩺 Troubleshooting
🛠 Development
git clone https://github.com/tunaarikaya/magaza-mcp.git
cd magaza-mcp
npm install
npm run build # Compile TypeScript
npm run kontrol # Type-check (tsc --noEmit)
npm run dev # Compile in watch mode
To regenerate the tool catalogs from the specs:
node scripts/uret-katalog.mjs
This reads the three spec files under spec/ and rewrites the catalogs under
src/katalog/. The operation list is never hand-edited.
🤝 Similar projects
There are good projects in this space that came before this one. If your needs are limited to a single store, we genuinely recommend looking at them:
- Heimdall — Covers the entire App Store Connect API with 890 tools, with a profile system that lets you narrow the tool set down. The deepest project in this space if you’re only interested in iOS.
- app-store-connect-mcp-server — The first one. Established the idea of putting App Store Connect behind an MCP server; everyone who came after owes something to it.
- google-play-developer-mcp — A comprehensive, mature server on the Play side. More than enough if you’re only publishing on Android.
Our difference: all of these look at a single store. magaza-mcp combines
both in one setup and offers tools that can compare both stores in the same
call — exactly what a single-store server can’t do.
📄 License
MIT — see LICENSE for details. See THIRD-PARTY-NOTICES.md for third-party sources.
App Store, TestFlight, App Store Connect, Google Play, and Play Console are trademarks of their respective owners. This is an independent open-source project; it is not affiliated with, endorsed, sponsored, or supported by Apple Inc. or Google LLC.
설치
npx magaza-mcp kur