infinitebacklog-mcp

Hybrid MCP server for Infinite Backlog (https://infinitebacklog.net/), a free multi-platform video game collection tracker. Topics

Documentation

Infinite Backlog MCP

Infinite Backlog MCP Server

Hybrid Model Context Protocol server for Infinite Backlog, a free multi-platform video game collection tracker.

Infinite Backlog has no public write API, so this server drives a real Chromium session. After login it also uses read-only GET /api/user_collections to audit nested extras.

Python 3.11+ License: MIT MCP

Recommended login (user)

  • Sign in once on Infinite Backlog in your usual browser (any browser is fine).
  • Point the agent at that tab, or run headless if a session is already available.
  • Leave the signed-in tab open so ratings, reviews, and collection writes reuse it.

Agents: prefer headless unless the user asks otherwise. For a private collection, use the tab the user pointed to, or IB_COOKIES / set_cookies only when a cookie JSON array is already in the environment. Never ask the user to harvest cookies from DevTools.

Features

  • Deterministic Playwright tools for precise, low-cost reads and collection edits (no extra LLM cost).
  • Optional autonomous agent (run_browser_use_task) powered by browser-use for multi-step or fragile goals.
  • Related-content coverage for DLC, packs, add-ons, editions, remakes, bundles, and extras.
  • Collection tools for ratings, reviews, extra platform copies, progress, acquisition info, and Play Records.
  • User login in any browser (point the agent at the tab) or headless with an existing session.

Tools

Deterministic (always available)

NameDescriptionKey inputs
open_siteOpen /, /games, /challenges, or another IB path. Locked to https://infinitebacklog.net. headless=false opens a visible window for login; later calls reuse that session.path, wait_ms, headless
search_gamesSearch the games catalog via #game-search. Live filter is /games?q=. /games?search= does not filter. Do not fill #platforms-search.query, wait_ms
get_page_textExtract visible page text.max_chars
get_page_htmlRead HTML for a selector (default body).selector, max_chars
get_linksList links on the current page.max_links
clickClick by CSS selector or text=... on an IB page. Blocked for DELETE GAME, DELETE DRAFT, YES/NO, and UNLOCK CUSTOM TAGS.selector, wait_ms
fillFill an input. Refuses password and credential selectors.selector, value
evaluate_jsDebug-only page JavaScript. Disabled unless IB_ALLOW_EVAL_JS=true.expression
screenshotSave a PNG under the OS temp infinitebacklog-mcp directory (path is confined).path, full_page
set_cookiesInject auth cookies as a JSON array. Only infinitebacklog.net domains are accepted.cookies_json
current_urlReturn the current URL and title.none
close_browserClose the shared Playwright browser.none
list_related_contentExpand ul.related-games-nav tabs only (one tab is enough). Stay on /games/{slug}; do not click card labels such as EDITION.game_slug, wait_ms
list_collection_content_menusRead Add DLC, owned DLC, addon-* boxes, and GAME EDITION text on an edit form (login required).edit_path, wait_ms
add_game_contentAttach nested extras on the parent edit form. Searches DLC first, then every other menu before not_found.parent_slug, names, collection_id
list_collection_game_optionsRead copies, extra-platform control, progress, acquisition, ratings, reviews, and Play Records (no save).slug, collection_id
set_game_ratingSet or clear 1-10 overall plus Visual / Gameplay / Story / Audio / Playability.slug, score, sub-ratings, clear
add_game_reviewDraft or publish at /games/{slug}/add-review. Publish needs 800+ characters.slug, body, publish, title
delete_game_reviewDelete a draft review. Published reviews are out of scope unless named.slug, confirm, published
add_game_platform_copyAdd another GAME INFORMATION copy via button.extra-platform.slug, platform, digital, submit
set_game_progressSet per-copy status, completion, 0-100 bar, and notes.slug, collection_id, status, completion, progress, notes, clear_fields
set_game_acquisitionSet or clear ACQUISITION INFO (type, source, date, amount, costs, notes, Digital Service).slug, collection_id, acquisition fields, clear_fields
delete_game_copyDELETE GAME for a saved copy.collection_id (required), confirm=true (required)
list_play_recordsRead Play Records categories on /edit/stats.slug, collection_id
set_play_record_categoryAdd a category (keyValue / checkbox / progress / table).slug, name, type, layout
set_play_recordAdd or update a row inside a category.slug, category, action, name, value
remove_play_recordRemove a row, or a whole category with confirm=true.slug, category, row_index, confirm

If a title is missing from DLC, search PACK/ADDON, EDITIONS, extra-content checklists, and every other live related tab before reporting not_found. Skins are often packs, not DLC.

Autonomous (requires browser-use and an LLM key)

NameDescriptionKey inputs
run_browser_use_taskHigh-level goal on infinitebacklog.net only. The agent plans and executes with vision plus DOM. Best for multi-step or fragile flows.task, max_steps, model, headless

When to use which

  • Simple read or a known selector -> deterministic tools.
  • "Find all unfinished JRPGs and summarize playtime" -> run_browser_use_task.

Requirements

  • Python 3.11 or newer
  • Playwright Chromium
  • An MCP-compatible client (Cursor, Claude Desktop, VS Code, and others)
  • An LLM API key only when using run_browser_use_task

Installation

cd infinitebacklog-mcp
python -m venv .venv
# Windows: .venv\Scripts\activate
# Unix: source .venv/bin/activate
pip install -e .
python -m playwright install chromium

Optional autonomous agent:

pip install -e ".[agent]"

Copy [.env.example](.env.example) to .env and fill in keys as needed. Do not commit .env.

Quick start

After install:

infinitebacklog-mcp

Or as a module:

python -m infinitebacklog_mcp.server

Development without installing the console script still works:

python server.py

The MCP server name is infinitebacklog. Logging goes to stderr only (required for stdio transport).

MCP client configuration

Replace the working directory with the absolute path to this project. Treat API keys and IB_COOKIES as secrets.

Installed command (Cursor / Claude Desktop style):

{
  "mcpServers": {
    "infinitebacklog": {
      "command": "infinitebacklog-mcp",
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "IB_COOKIES": "[{\"name\":\"...\",\"value\":\"...\",\"domain\":\".infinitebacklog.net\",\"path\":\"/\"}]"
      }
    }
  }
}

Module path (development):

{
  "mcpServers": {
    "infinitebacklog": {
      "command": "python",
      "args": ["-m", "infinitebacklog_mcp.server"],
      "cwd": "/absolute/path/to/infinitebacklog-mcp",
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "IB_COOKIES": ""
      }
    }
  }
}

Legacy file launch (still supported):

{
  "mcpServers": {
    "infinitebacklog": {
      "command": "python",
      "args": ["/absolute/path/to/infinitebacklog-mcp/server.py"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "IB_COOKIES": ""
      }
    }
  }
}

Public pages work without login. Private collection features use the signed-in tab in Recommended login (user), or IB_COOKIES / set_cookies when those values are already in the environment.

Environment variables

VariableRequiredDescription
OPENAI_API_KEYFor autonomous tool (one of the four keys)OpenAI key for run_browser_use_task
ANTHROPIC_API_KEYAlternativeAnthropic key
GOOGLE_API_KEYAlternativeGoogle key
BROWSER_USE_API_KEYAlternativebrowser-use Cloud key
IB_COOKIESOptional (agents only)JSON array of cookies for a logged-in session. Do not ask a human to fill this by hand.
IB_HEADLESSOptionalDefault headless mode for tools that do not pass headless (true / false)
IB_VIEWPORT_WIDTHOptionalPlaywright viewport width (default 1280, clamped)
IB_VIEWPORT_HEIGHTOptionalPlaywright viewport height (default 800, clamped)
IB_ALLOW_EVAL_JSOptionalEnable the evaluate_js debug tool (true / false, default false)
IB_CHROMIUM_NO_SANDBOXOptionalPass --no-sandbox to Chromium (default false; containers only)

Collection model (live IB v1.13.6)

DLC and packs are nested additions on the parent collection row, not standalone collection games.

  • GET /api/user_collections?user_id=...&game_id=<DLC> is empty even when that DLC is owned.
  • already_owned is parent additions[] (and the edit form Owned DLC list).
  • /games/add/{dlc-slug} SPA-redirects to /games/{slug}. There is no add form.
  • Parent edit path: /users/{user}/collection/{parent-slug}/edit?id={collection_id}
  • Pick extras from Add DLC to your game, tick ADDONS/PACKS labels only when unchecked, then click UPDATE GAME once.
  • Never click DELETE GAME, fill Acquisition Info, or change edition / Digital-Physical / play status during add_game_content.
  • Ratings and reviews are per IGDB game. Extra copies are extra POST /user_collections rows via button.extra-platform.
  • Only set_game_acquisition writes Acquisition Info. Only delete_game_copy clicks DELETE GAME (confirm=true).

Security and etiquette

  • Unofficial project. Not affiliated with Infinite Backlog.
  • Tool navigation, cookies, in-page API fetches, and run_browser_use_task are locked to https://infinitebacklog.net. Off-origin URLs are rejected.
  • evaluate_js is off by default. Screenshots can only be written under the OS temp infinitebacklog-mcp directory. Chromium --no-sandbox is opt-in via IB_CHROMIUM_NO_SANDBOX.
  • Generic click / fill cannot drive DELETE GAME, DELETE DRAFT, YES/NO confirms, UNLOCK CUSTOM TAGS, or password fields. Dedicated delete tools still require confirm=true.
  • Be polite with request rate.
  • SPA pages often need a short wait after navigation. About 281 characters with no h1 is the Vue chrome. Wait for h1, #game-search, or more text. On an edit form, wait until UPDATE GAME is visible.
  • Catalog search is #game-search (placeholder "Search for a game") with the Vue native value setter. #platforms-search is a sidebar filter. Live filter is /games?q=. /games?search= does not filter.
  • Duplicate titles use IGDB-style slugs (Hades 1995 is hades, Hades 2020 is hades--1).
  • list_related_content clicks only ul.related-games-nav tabs (href is often empty). A page-wide EDITION/DLC label is a card link to another game.
  • Collection rows use /users/{user}/collection/{slug}?id={collection_id}. WRITE A REVIEW on the edit form goes to /games/{slug}/add-review. DELETE DRAFT confirm is YES.
  • Nested extras are add-only in this pass. Do not auto-untick owned DLC.
  • Do not click UNLOCK CUSTOM TAGS, Play Records SETTINGS, or edit /settings / profile widgets. Return profile_scope.
  • delete_game_review only deletes a draft (confirm=true). Published reviews are profile_scope unless you name them.
  • Prefer headed open_site so the user logs into Infinite Backlog in the MCP-controlled Chromium window. Cookie injection is an agent-only fallback. A logged-in Brave tab with CDP is a separate attach path and is not launched by this server.
  • Concurrent tool calls share one browser and are serialized with a lock.

Development

Project layout:

infinitebacklog-mcp/
├── src/infinitebacklog_mcp/
│   ├── server.py          # MCPServer, instructions, main()
│   ├── browser.py         # Playwright lifecycle
│   ├── config.py          # constants and env
│   ├── security.py        # origin, cookie, path, and identifier allowlists
│   ├── matching.py        # name / kind matching
│   ├── tools/             # deterministic + agent tools
│   └── ...
├── tests/
├── docs/assets/           # README logos
└── server.py              # compatibility shim

Inspector:

npx @modelcontextprotocol/inspector python -m infinitebacklog_mcp.server
# after install:
npx @modelcontextprotocol/inspector infinitebacklog-mcp

Tests:

python -m unittest discover -s tests -v

License

MIT. See LICENSE.