Skip to main content

Kranked MCP

An MCP server that exposes App Store keyword intelligence — keyword difficulty, popularity, and live rank — as tools any MCP client (Claude, etc.) can call. It's the headless companion to the Kranked ASO app: same scoring, no GUI.

Stateless and zero-config: every tool is a live call to Apple's public endpoints. Ranks come from the App Store's own search ordering; the iTunes Search API is used for app discovery and metadata, and search-hints for keyword popularity. No database, no API keys. Runs locally via uvx or as a hosted server.

Speaks MCP 2026-07-28 (Python SDK v2), and stays backwards compatible with 2025-era clients from the same server. Era is selected per request from the MCP-Protocol-Version header, so over stdio — which has no headers — the server answers the 2025 initialize handshake. Nothing to configure either way; clients negotiate it themselves.

Tools (free / open core)

Tool What it answers
search_apps Find apps (and their app_id) matching a term
check_keyword One-shot report: difficulty + popularity + KEI + competitors, and your app's rank
keyword_difficulty How hard a keyword is to rank for (0–100), with the top-10 competitors
keyword_popularity How searched a keyword is (0–100)
popular_keywords The most-searched keywords in a category, ranked
keyword_suggestions Apple's autocomplete hints for a seed term

All tools take a two-letter country (default us).

How the scores work

  • Difficulty (0–100) — analyzes the top-10 ranking apps' review volume and rating quality. More established competitors = harder. Labeled Very Easy → Very Hard.
  • Popularity (0–100) — two sources, and every response says which one it used. With Apple Ads credentials configured it is Apple's own searchPopularity, a real search-volume index. Without them, keyword_popularity falls back to a free suggest-based proxy (80 = Apple auto-suggests the exact term, 50 = a related term, 20 = neither) and popular_keywords reports source: unconfigured rather than inventing numbers. The two scales are not comparable — check source before ranking terms against each other.
  • KEI — Keyword Efficiency Index = popularity / difficulty. Higher is a better bet.
  • Rank comes from the App Store's own search ordering, not the iTunes Search API. The documented Search API does not return the store's ordering: measured across five US terms it matched on 29/60 positions against 60/60 for the store endpoint, and it caps out around 150–185 results instead of 200. The Search API is still used for app discovery and metadata.

Real popularity numbers (BYOK)

searchPopularity comes from Apple's own Ads Platform API, so it needs an Apple Search Ads account — your account, keys stay on your machine, no ad spend required. Install the extra and set the credentials:

uvx --with 'kranked-mcp[appleads]' kranked-mcp
Env var Purpose
KRANKED_APPLEADS_CLIENT_ID Ads API client id
KRANKED_APPLEADS_TEAM_ID Ads API team id
KRANKED_APPLEADS_KEY_ID Ads API key id
KRANKED_APPLEADS_ORG_ID your Ads account (org) id
KRANKED_APPLEADS_PRIVATE_KEY the ES256 signing key as PEM text…
KRANKED_APPLEADS_PRIVATE_KEY_PATH …or a path to the PEM file instead

All five are required (either key form counts as one).

Unconfigured is a normal state: the tools degrade to the free proxy instead of failing.

Install

On PyPI — nothing to clone or build. uvx fetches and runs it on demand. Needs Python 3.10+ and uv (brew install uv). Add to your MCP client config:

{
  "mcpServers": {
    "kranked": {
      "command": "uvx",
      "args": ["kranked-mcp"]
    }
  }
}

For Claude Code: claude mcp add kranked -- uvx kranked-mcp

Source

The sdist on PyPI carries the full source and the test suite — it's on the Download files tab. Unpack it and uv sync, then point your client at that directory:

{
  "mcpServers": {
    "kranked": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/kranked-mcp", "run", "kranked-mcp"]
    }
  }
}

Run the tests — they're offline (pure scoring plus server wiring driven through the real ASGI app), so they don't hit Apple and can't flake on rate limiting:

uv run pytest

Self-hosting (remote MCP)

Kranked runs in two modes from the same code:

Mode Transport Use Command
Local stdio one user, on your machine kranked-mcp
Hosted streamable-HTTP at /mcp shared server, many users kranked-mcp-serve

The hosted server is stateless, so it scales horizontally — no sticky routing, no session affinity. Since MCP 2026-07-28 that is the protocol's own model rather than an opt-in: there is no initialize handshake and no session id, and clients negotiate up front with server/discover instead. Deploy the included Dockerfile to any container host (Railway, Fly, Render, …); it reads PORT from the environment and exposes GET /health for liveness checks.

server/discover and tools/list carry a one-hour public cache hint (ttlMs / cacheScope), so clients can hold the tool list instead of re-listing it every session.

Deploy to Railway

Deployment is declared in .railway/railway.ts (Railway Infrastructure as Code): GitHub source, Dockerfile build, /health healthcheck, restart policy. To deploy:

# one-time
npm i -g @railway/cli && railway login

# from the repo root
railway init            # create/select a project
railway up              # build the Dockerfile and deploy
railway domain          # get a public https URL

The upstream repo is connected as the service's GitHub source, so pushing to main deploys. Set KRANKED_CACHE_TTL in the service's Variables if you want a longer/shorter cache.

Verify against the live server, not the build log. check_keyword for "keyword tracker" should report total_results around 247. A number in the low 180s means the old iTunes Search API path is answering and the deploy did not take. This is not theoretical: before auto-deploy was connected, the server sat on 2026-08-01 code for a month, and served old ranks for a full day after the fix was merged, because pushing looked like deploying.

Changing deployment config

.railway/railway.ts replaced the deprecated railway.toml (which stops working 2026-12-01). To edit it:

npm install railway --no-save   # needed only for plan/apply; not a project dependency
railway config plan             # preview
railway config apply --yes      # push

Two things worth knowing if you regenerate it. railway config migrate is lossy — it comments out builder and dockerfilePath, which would have silently left this service on Railpack rather than the Dockerfile. And railway config pull returns only what lives in Railway's own settings, so anything that used to come from railway.toml has to be carried across by hand. restartPolicyType is deliberately absent: ON_FAILURE is Railway's default, so it round-trips as null and leaves the plan permanently dirty.

Then point a client at the URL:

claude mcp add --transport http kranked https://your-app.up.railway.app/mcp

Config

Env var Default Purpose
PORT / HOST 8000 / 0.0.0.0 bind address
KRANKED_CACHE_TTL 3600 seconds to cache upstream responses (0 disables)
KRANKED_CACHE_MAX 2000 max cached entries

Caching is not optional for a hosted deployment. All users' requests leave from one IP, so without it you hit Apple's per-IP throttle immediately. Difficulty/popularity change slowly, so cached results stay useful for hours. For multiple instances, move the cache to Redis.

Setting KRANKED_API_KEY gates every endpoint except GET /health behind a bearer token; unauthenticated callers get a 401. Leave it unset and the server is open, which is what you want for a local stdio run. Usage metering for a paid tier is still roadmap.

Rate limiting

The iTunes API throttles unauthenticated callers per IP with a 403/429 and a non-JSON body. The server serializes requests through a global throttle and retries throttles with exponential backoff + jitter, so it degrades gracefully instead of surfacing bogus decoding errors.

License

MIT © Akos Komuves

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kranked_mcp-0.2.3.tar.gz (31.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kranked_mcp-0.2.3-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

File details

Details for the file kranked_mcp-0.2.3.tar.gz.

File metadata

  • Download URL: kranked_mcp-0.2.3.tar.gz
  • Upload date:
  • Size: 31.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for kranked_mcp-0.2.3.tar.gz
Algorithm Hash digest
SHA256 07fda7b0325ae76c6c8594e3f056492ece0d7d934c709a4e00e27d3ffef44bcd
MD5 d534765de6be2dde4a6c880ff8b1c50f
BLAKE2b-256 dffa7a48a3ac0f5091922234c824a1b01c4e43553695ecbdc0b348874a1483bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for kranked_mcp-0.2.3.tar.gz:

Publisher: release.yml on akoskomuves/kranked-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kranked_mcp-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: kranked_mcp-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 30.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for kranked_mcp-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 fd0885520bd34e05c6e12b811be38b860438b0a3f175cc84b2e755a106898348
MD5 d97efad5290749623521e9feb5066a9e
BLAKE2b-256 20248dc62e45147d1aaf99ef51d536dcefc9d6b059932da6bf509e02af8fcd22

See more details on using hashes here.

Provenance

The following attestation bundles were made for kranked_mcp-0.2.3-py3-none-any.whl:

Publisher: release.yml on akoskomuves/kranked-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.3 This release

2 files

0.2.2

2 files

0.2.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page