{
  "markdown": "# ⏱️ speedrun-mcp\n\n<!-- mcp-name: io.github.williamcodes/speedrun-mcp -->\n\n[![PyPI version](https://img.shields.io/pypi/v/speedrun-mcp?logo=pypi&logoColor=white)](https://pypi.org/project/speedrun-mcp/)\n[![Python](https://img.shields.io/badge/python-3.10%2B-blue?logo=python&logoColor=white)](https://pypi.org/project/speedrun-mcp/)\n[![CI](https://github.com/williamcodes/speedrun-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/williamcodes/speedrun-mcp/actions/workflows/ci.yml)\n[![MCP registry](https://img.shields.io/badge/MCP-registry-0098FF)](https://registry.modelcontextprotocol.io)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n\nA [Model Context Protocol](https://modelcontextprotocol.io) server for\n[speedrun.com](https://www.speedrun.com) — let an AI assistant query games,\ncategories, leaderboards, world records, players and their personal bests, and\n(with an API key) submit and moderate runs.\n\n> *\"What's the current Super Mario 64 16-star world record, and who holds it?\"*\n\nBuilt on speedrun.com's official [REST API](https://github.com/speedruncomorg/api).\n**The read tools need no account or API key** — add a key (see\n[Authenticated features](#authenticated-features)) to unlock identity reads and,\noptionally, run submission and moderation. Results come back as compact,\nmodel-friendly JSON (player ids resolved to names, durations formatted,\nsubcategory variables labeled).\n\n## Example\n\nAsk *\"the SM64 16-star world record?\"* and the model calls `get_world_record`,\nwhich returns compact, resolved JSON:\n\n```json\n{\n  \"game_name\": \"Super Mario 64\",\n  \"category_name\": \"16 Star\",\n  \"world_record\": {\n    \"players\": [\"Suigi\"],\n    \"time\": \"14m 35.5s\",\n    \"date\": \"2023-03-22\",\n    \"video\": \"https://youtu.be/1_vkwkniHuI\"\n  }\n}\n```\n\n## Tools\n\n| Tool | What it does |\n| --- | --- |\n| `search_games` | Fuzzy-search games by name → ids & abbreviations |\n| `get_game` | A game's details plus its categories (and optionally levels) |\n| `list_categories` | A game's categories (`Any%`, `120 Star`, …) with rules |\n| `list_variables` | Subcategory/filter variables and their value ids |\n| `list_platforms` / `list_regions` | Platform / region ids for the `platform`/`region` leaderboard filters |\n| `get_leaderboard` | A ranked leaderboard (top N; filter by variable / platform / region / timing) |\n| `get_world_record` | The current #1 run for a game/category, plus any runs tied for first |\n| `get_game_records` | Every category's records for a game in one call (defaults to world records) |\n| `search_series` | Fuzzy-search game series (e.g. `Mario`, `Zelda`) |\n| `get_series` | A series' details and the games it contains |\n| `search_users` | Find players by username (partial, fuzzy match) |\n| `get_user_personal_bests` | A player's PBs across all games |\n| `get_run` | Details of a single run |\n| `list_runs` | Runs filtered by player / game / category / status / examiner |\n| `list_unverified_runs` | A game's runs awaiting verification (the moderation queue) |\n| `whoami` | The profile that owns your API key *(only shown when a key is set)* |\n| `list_notifications` | Your speedrun.com notifications *(only shown when a key is set)* |\n\nA typical flow: `search_games` → `list_categories` (and `list_variables` for\nsubcategories) → `get_leaderboard` / `get_world_record`. Use `list_platforms` /\n`list_regions` when you need an id for the `platform` / `region` filters.\n\nWith write tools enabled (see below), `submit_run`, `verify_run`, `reject_run`,\n`set_run_players` and `delete_run` are also available.\n\n## Install & run\n\nRequires Python 3.10+.\n\n```bash\n# from PyPI\npipx install speedrun-mcp        # or: uv tool install speedrun-mcp\n\n# from source\ngit clone https://github.com/williamcodes/speedrun-mcp\ncd speedrun-mcp\npip install -e .\n```\n\nThe server speaks MCP over stdio:\n\n```bash\nspeedrun-mcp          # console script\npython -m speedrun_mcp # equivalent\n```\n\n## Use with Claude Desktop / Claude Code\n\nAdd to your MCP client config (e.g. `claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"speedrun\": {\n      \"command\": \"speedrun-mcp\"\n    }\n  }\n}\n```\n\nIf you installed from source into a virtualenv, point `command` at that\ninterpreter, e.g. `\"command\": \"/path/to/.venv/bin/speedrun-mcp\"`.\n\nFor Claude Code:\n\n```bash\nclaude mcp add speedrun -- speedrun-mcp\n\n# with authenticated features (optional):\nclaude mcp add speedrun \\\n  -e SPEEDRUN_API_KEY=your-key-here \\\n  -e SPEEDRUN_ENABLE_WRITES=1 \\\n  -- speedrun-mcp\n```\n\n## Authenticated features\n\n**An API key is entirely optional.** With no key, the server exposes only the\npublic read tools (leaderboards, games, players, the moderation queue) and works\nexactly as described above — no account required. Adding your key unlocks more:\n\n| Set this env var | Effect |\n| --- | --- |\n| `SPEEDRUN_API_KEY` | Puts the server in **read-only authenticated mode**. Adds the identity reads — `whoami` (the profile your key belongs to) and `list_notifications`. The write tools (`submit_run`, `verify_run`, `reject_run`, `set_run_players`, `delete_run`) also become *visible*, but stay disabled — calling one returns a message telling you to enable writes. Until a key is set, none of these are advertised at all. |\n| `SPEEDRUN_ENABLE_WRITES=1` | Switches to **read-write mode**: arms the write tools so they actually submit/moderate. Requires `SPEEDRUN_API_KEY` (moderation also needs a moderator key). Off by default — submitting and rejecting/deleting are real, permanent actions on real leaderboards, so opt in deliberately. |\n\n**Read-only is the default.** Just adding a key never changes anything on\nspeedrun.com — you get identity reads, and everything keeps working perfectly. If\na write tool is invoked while writes are off, it doesn't silently fail; it returns:\n\n> *This server is in read-only mode, so this write action is disabled. To allow\n> run submission and moderation, set the environment variable\n> SPEEDRUN_ENABLE_WRITES=1 (alongside SPEEDRUN_API_KEY) and restart the server.*\n\nSo the way to switch to read-write mode is always discoverable from the error\nitself.\n\n### Getting your API key\n\n1. Log in to [speedrun.com](https://www.speedrun.com).\n2. Go to your account **settings**.\n3. In the left-hand nav, find the **Developers** section and click **API Key**.\n4. Copy the key shown there.\n\nTreat the key like a password — anyone who has it can act as you on\nspeedrun.com. If it ever leaks, regenerate it from that same page.\n\n### Using your key\n\nAdd the key to your MCP client config under `env`. It is read **only from the\nenvironment** — never passed as a tool argument — so it can't leak into the\nmodel's context or transcripts. Add `SPEEDRUN_ENABLE_WRITES=1` only when you want\nwrites to actually run; with the key alone you stay safely read-only.\n\n```json\n{\n  \"mcpServers\": {\n    \"speedrun\": {\n      \"command\": \"speedrun-mcp\",\n      \"env\": {\n        \"SPEEDRUN_API_KEY\": \"your-key-here\",\n        \"SPEEDRUN_ENABLE_WRITES\": \"1\"\n      }\n    }\n  }\n}\n```\n\nOr with Claude Code:\n\n```bash\nclaude mcp add speedrun -e SPEEDRUN_API_KEY=your-key-here -- speedrun-mcp\n# add -e SPEEDRUN_ENABLE_WRITES=1 as well if you want the write tools\n```\n\nKeep the key out of version control — put it in your client config or a local,\ngit-ignored `.env`, never in a committed file. All tools carry MCP read-only /\ndestructive hints so clients can flag the write and moderation actions.\n\n## Notes & limits\n\n- **Reads need no key; writes are opt-in.** Leaderboards, games, players and the\n  moderation queue are open reads. Run submission and moderation need\n  `SPEEDRUN_API_KEY` **and** `SPEEDRUN_ENABLE_WRITES` (see above).\n- **Rate limit:** speedrun.com allows 100 requests/minute per IP and responds\n  with HTTP 420 when exceeded; the client surfaces a clear error if you hit it.\n- Game and category arguments accept either an id (`o1y9wo6q`) or an\n  abbreviation (`sm64`). For precise subcategory leaderboards (e.g. `16 Star`),\n  discover the variable/value ids with `list_variables` and pass\n  `variables={variable_id: value_id}`.\n- **Errors are explanatory.** Invalid ids/filters raise an error that includes\n  speedrun.com's own message — e.g. passing a `level` to a full-game category\n  returns *\"The selected category is for full-game runs, but a level was selected.\"*\n\n### Output shape\n\n- **Times** reflect the leaderboard's sort timing. When you pass `timing`\n  (`realtime` / `realtime_noloads` / `ingame`), the reported `time` /\n  `time_seconds` match that ranking, not the game's default timing.\n- **`get_leaderboard`** returns `returned_runs` (the number of runs returned,\n  bounded by `top` and ties — not the full board size) and a `runs` list with\n  resolved player names, formatted times, and labeled subcategories.\n- **`get_world_record`** returns `world_record` (the place-1 run, or `null` if\n  the board is empty) plus `tied` (a list of any other runs sharing first place).\n- **`get_user_personal_bests`** returns `returned` (how many came back, capped by\n  `limit`) and `total_available` (the player's true PB count), plus the\n  `personal_bests` list with game/category names and resolved players.\n\n## Development\n\n```bash\npip install -e \".[dev]\"\npytest -m \"not network\"   # unit tests (offline)\npytest                    # include live-API tests\nruff check .\n```\n\n## License\n\nMIT\n",
  "bytes": 9319,
  "sha": "6e5c3dff5ea55902c95ab12e1e589c3cecd8464720b7a565399924db7a6ae219",
  "repo_slug": "williamcodes/speedrun-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_williamcodes_speedrun_mcp_bc177f25/readme"
}