Skip to main content
Glama
SDNick484

mcp-server-steam-backlog

by SDNick484

mcp-server-steam-backlog

An MCP server for Steam Backlog Triage, the self-hosted dashboard for working through a Steam backlog with an eye on the Steam Deck. It lets an MCP client such as Claude answer "what should I play tonight on the Deck, under 10 hours?" in one call, search and filter the library with the dashboard's filters, and triage games into lanes, add notes, reorder Up next and refresh the library, all saved to the same dashboard.

Status: alpha. Tested against a wire-level fake of the backlog server, against steam-backlog-triage's real backlog_server.py (both today's version and a prototype of the API it's built for), and its installer against a stubbed Alpine run. Some features need a newer steam-backlog-triage (see API versions); everything else works with the current one.

This project isn't affiliated with Valve, HowLongToBeat or ProtonDB.

How it works

MCP client ──stdio, or HTTPS through Cloudflare Access──▶ mcp-server-steam-backlog
                                                               │  HTTP, loopback only
                                                               ▼
                                         backlog_server.py (steam-backlog-triage)
                                                               │  one writer: lock + atomic writes
                                                               ▼
                                   steam_backlog.json, triage.json, notes.json, order.json
  • The MCP server is a client of backlog_server.py's JSON API. It never opens the backlog's files, so there's still one writer, and the dashboard and Claude never race each other. It runs as its own user and can't read the backlog's keys.

  • The couch score is the dashboard's score(), ported term by term and checked against shared test vectors generated from backlog.html itself, so Claude and the dashboard never disagree about the best pick. backlog://scoring explains it.

  • The interface is specified in docs/backlog-api-contract.md.

Related MCP server: steam-mcp

Tools

Tool

What it does

backlog_get_overview

Start here: library size, never/tried/played, Deck ratings, the backlog by Deck rating × length, lane counts, Up next length, export age, data coverage

backlog_find_games

Search and filter with the dashboard's filters (genres, HLTB length, ProtonDB, Metacritic, year, Deck rating, controller, play state, lane, notes); sort and page; relaxes filters instead of answering "not found"

backlog_get_game

Everything about one game, with its score breakdown and store link

backlog_suggest_picks

Couch picks with the same filters, each with a score breakdown to explain it

backlog_get_next_queue

The Up next lane in order, with notes

backlog_set_lane

Move 1–50 games to next, someday, skip, done, or out of every lane

backlog_set_note

Write, replace or clear a game's note

backlog_reorder_next

Move a game within Up next, or set the order

backlog_start_export

Refresh the library (runs on the backlog server; minutes to an hour)

backlog_get_export_status

How the refresh is going, with redacted log lines

Resources: backlog://scoring (how the score works) and backlog://game/{appid}. Prompts: triage_session (walk untriaged games one at a time) and pick_for_tonight.

Not exposed, on purpose: replacing the library, deleting data, anything touching keys or settings.

Safety design

  • Writes never guess. A game argument is an app id or an exact name. A name that matches several games (two called "DOOM") or none returns candidates and changes nothing.

  • Confirmation for bulk and destructive-feeling changes. A single game the user named can move to any lane, done and skip included. Moving more than five games, or replacing an existing note, returns needs_confirmation with the planned change until the call is repeated with confirmed=true. The server instructions also ask the model to confirm skip/done for games it inferred.

  • Bounded. At most 50 games per call; a token bucket limits writes (60 a minute by default) and exports (two, then one per five minutes), so a looping agent can't churn the files.

  • Reversible. Every write returns what it replaced: previous lanes, the previous note, the previous Up next order.

  • No lost updates. Reorders use If-Match; if the dashboard reordered at the same moment, the server re-reads once and retries, then reports a conflict rather than overwriting.

  • Data isn't instructions. Game names and notes only ever appear in their own fields.

  • Private. The export's SteamID and persona are dropped when it's parsed; SteamIDs are redacted from every log line even with --no-redact. Errors to the client are generic and actionable; details go to the log.

  • Dry run. BACKLOG_DRY_RUN=1 (or --dry-run): writes validate and report, and send nothing.

API versions

Feature

API 1 (steam-backlog-triage today)

API 2 (after its API PR)

Reading, filtering, picks, triage, notes, reorder

✓

✓

Library cached and revalidated with ETags

refetched at most once a minute

✓

Previous values read atomically

read just before writing (flagged atomic: false)

✓

Reorders safe against a concurrent dashboard edit

no (flagged protected: false)

✓

Start an export, see its status

"not available"

✓

mcp-server-steam-backlog doctor says which the server has.

Install

You need steam-backlog-triage running (its backlog_server.py on port 8484).

Trying it without the backlog

pip install git+https://github.com/SDNick484/mcp-server-steam-backlog
mcp-server-steam-backlog simulate --port 8484      # a fake backlog server with a sample library
# in another terminal:
mcp-server-steam-backlog doctor
mcp-server-steam-backlog call suggest_picks count=3

simulate --api 1 imitates today's steam-backlog-triage.

Claude Code or Claude Desktop (stdio)

On the machine that runs the backlog, or with BACKLOG_URL pointing at it over a private network:

claude mcp add steam-backlog -e BACKLOG_URL=http://127.0.0.1:8484 -- \
  uvx --from git+https://github.com/SDNick484/mcp-server-steam-backlog mcp-server-steam-backlog

(Once it's published to PyPI, plain uvx mcp-server-steam-backlog works.) Or in a client's JSON config:

{
  "mcpServers": {
    "steam-backlog": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/SDNick484/mcp-server-steam-backlog", "mcp-server-steam-backlog"],
      "env": { "BACKLOG_URL": "http://127.0.0.1:8484" }
    }
  }
}

On Alpine (OpenRC), next to the backlog

git clone https://github.com/SDNick484/mcp-server-steam-backlog.git
cd mcp-server-steam-backlog
sh deploy/alpine/install.sh "$PWD"
mcp-server-steam-backlog doctor
rc-update add mcp-server-steam-backlog default && rc-service mcp-server-steam-backlog start

The installer creates the mcp-steam-backlog user, a venv in /opt/mcp-server-steam-backlog, settings in /etc/mcp-server-steam-backlog/env (kept on re-runs), and an OpenRC service on 127.0.0.1:8486/mcp/backlog. Re-running it upgrades the code. To edit the settings: vim /etc/mcp-server-steam-backlog/env, then rc-service mcp-server-steam-backlog restart.

systemd hosts: see contrib/systemd/. A non-root container: deploy/docker/Dockerfile (optional).

Remote access: HTTP behind Cloudflare Access

For Claude on the web and mobile, the service speaks Streamable HTTP and checks a Cloudflare Access assertion on every request (remote.py, shared with the sibling servers). With no Access settings it answers only requests that start on the same machine.

  1. Snapshot first if this shares a container with other services.

  2. In Cloudflare Zero Trust, create an Access application for the MCP path (for example backlog.example.com/mcp/backlog) with Managed OAuth, and note its AUD tag.

  3. Add a tunnel rule sending ^/mcp/ to http://localhost:8486, above any broader rule for the same hostname.

  4. Put the settings in the env file (placeholders shown):

    MCP_PUBLIC_HOSTS=backlog.example.com
    CF_ACCESS_TEAM_DOMAIN=example.cloudflareaccess.com
    CF_ACCESS_AUD=<the Access application's AUD tag>

    then rc-service mcp-server-steam-backlog restart and mcp-server-steam-backlog doctor.

  5. Check that an unauthenticated request gets Access's 401 (with WWW-Authenticate), not a 302 to a login page:

    curl -si -X POST https://backlog.example.com/mcp/backlog | head -5

    If it redirects, give the MCP its own hostname instead.

  6. Add https://backlog.example.com/mcp/backlog as a custom connector in Claude.

Settings

Variable

Default

BACKLOG_URL

http://127.0.0.1:8484

The backlog server

BACKLOG_DRY_RUN

off

Report writes without sending them

BACKLOG_WRITE_RATE

60

Writes per minute (1–600)

BACKLOG_DEBUG

off

Debug logging

BACKLOG_LOG_UNREDACTED

off

Show LAN addresses in logs (secrets and SteamIDs stay hidden)

MCP_HTTP_BIND, MCP_HTTP_PORT, MCP_HTTP_PATH

127.0.0.1, 8486, /mcp/backlog

The HTTP service

MCP_PUBLIC_HOSTS, CF_ACCESS_TEAM_DOMAIN, CF_ACCESS_AUD, MCP_ALLOWED_EMAILS

Cloudflare Access

Checking it with the MCP Inspector

npx @modelcontextprotocol/inspector mcp-server-steam-backlog
  • Ten tools listed, each with a title, annotations and an output schema

  • backlog_get_overview returns the library size and export age

  • backlog_suggest_picks returns picks with score_breakdown

  • backlog_set_lane with games=["DOOM"] (or any duplicated name) returns not_resolved and changes nothing

  • backlog_set_lane with six games returns needs_confirmation; with confirmed=true, done

  • backlog_set_note over an existing note returns needs_confirmation

  • With BACKLOG_DRY_RUN=1, writes return dry_run and the dashboard doesn't change

  • backlog://scoring reads; backlog://game/620 reads for a game in the library

  • Prompts triage_session and pick_for_tonight render

Development

pip install -e ".[dev]"
ruff check . && ruff format --check . && mypy && pytest --cov
  • The contract tests run against a fake, against the fake imitating API 1, and against a real backlog_server.py: BACKLOG_REF=<ref> clones steam-backlog-triage at that ref (default: its PR A merge commit, set in tests/conftest.py), BACKLOG_CHECKOUT=<dir> uses a local checkout. See docs/handoff-pr-a.md.

  • tests/fixtures/score_vectors.json comes from node scripts/gen_score_vectors.mjs path/to/backlog.html. CI regenerates it and fails if the page's score() changed.

  • Files shared with the sibling MCP servers (remote.py, logsafe.py, lookup.py, ratelimit.py, tools.py, tasks.py and their tests) come from mcp-server-shared; change them there, then python scripts/sync_shared.py --update.

License

MIT

Available Tools

10 tools
backlog_find_gamesFind gamesA
Read-only

<use_case> Search and filter the whole Steam library with the dashboard's filters: name or genre words, genres, HowLongToBeat length, ProtonDB tier, Metacritic, release year, Steam Deck rating, controller support, play state, triage lane (list/bucket/shelf) and notes. Use it to find a game's app id before changing it, or to answer questions like "which Verified RPGs have I never played?". </use_case> <important_notes>

  • Filters combine with AND. Games with no data for a filter are excluded unless include_unknown.

  • length uses the dashboard's presets on one HLTB measure; hours_min/hours_max set an exact range.

  • When nothing matches, it returns the closest games instead (exact=false) and says which filters it dropped (relaxed) or that it matched the name loosely (fuzzy_query). Tell the user that.

  • To recommend what to play, use backlog_suggest_picks instead: it ranks and explains. </important_notes> backlog_find_games(genres=["RPG"], deck=["verified"], play_state=["never"], sort="short")

NameRequiredDescriptionDefault
deckNoSteam Deck ratings to include
laneNoTriage lanes; 'none' = untriaged
sortNoscore (couch score), short (shortest first), name, recent, most (playtime), mcscore
limitNo
queryNoWords from the name or a genre, e.g. 'hollow'
genresNoStore genres, e.g. ['RPG', 'Roguelike']
lengthNoshort (<5 h), mid (5-15), long (15-40), epic (40+), none (no HLTB data)
offsetNo
year_toNo
has_noteNotrue: only games with a note; false: without
protondbNoProtonDB tiers to include
hours_maxNo
hours_minNo
year_fromNo
controllerNoController support
play_stateNonever (0 min), tried (<2 h), played (2 h+)
genre_matchNoany: one of the genres; all: every oneany
backlog_onlyNoOnly unplayed games not in skip or done
protondb_minNoMinimum ProtonDB tier: native > platinum > gold > silver > bronze > borked
length_measureNoWhich HowLongToBeat time the length uses: main, extra (main+extras), completemain
metacritic_minNo
include_unknownNoAlso include games with no data for a filter (unknown length, tier, year...)

Output Schema

NameRequiredDescription
exactYesfalse: nothing matched as asked; these are the closest matches
gamesYes
detailYes
offsetYes
matchesYes
relaxedYesFilters dropped to find these (weakest first)
truncatedYes
fuzzy_queryYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a safe read (readOnlyHint=true), so the description correctly spends its space on semantics the annotations cannot carry: filters combine with AND, unknown-data games are dropped unless include_unknown, and the no-match fallback returns closest matches with exact=false plus relaxed/fuzzy_query flags that the agent must disclose to the user. Pagination via limit/offset is never mentioned, which is the main remaining gap for a 22-parameter search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Tagged sections (use_case, important_notes, example) front-load the purpose before caveats, every bullet carries a distinct rule, and the closing line redirects to the ranking sibling. No filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 22-parameter search with an output schema and read-only annotations, the description covers the behaviors an agent must know (AND semantics, unknown handling, fallback signaling, sibling routing). Only pagination behavior and sort tie-breaking remain undocumented, which are secondary at this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

At 68% schema coverage the description meaningfully adds to the schema: it explains the AND combination rule, that length uses dashboard presets on one HLTB measure while hours_min/hours_max set an exact range, and that include_unknown widens every filter. It does not clarify offset/limit or the year/metacritic bounds, so it does not fully close the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (search and filter the whole Steam library) and enumerates the filter dimensions the tool spans. It also explicitly positions itself against backlog_suggest_picks and against backlog_get_game-style lookups ('find a game's app id before changing it').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use scenarios (resolve an app id, answer filtered questions), an explicit when-not-to-use with the named alternative (backlog_suggest_picks for recommendations), and a worked example call. Little is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_get_export_statusExport statusA
Read-only

<use_case> How the library refresh is going: running, finished or failed, with the phase (deck, details, proton, hltb), progress, elapsed time, the last lines of its log, and whether the library changed. </use_case> <important_notes>

  • available=false: this backlog server is too old to run exports from here.

  • After a successful export, the other tools see the new library automatically. </important_notes> backlog_get_export_status()

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
linesYes
phaseYes
stateYes
detailYes
originYes
reasonYes
progressYes
availableYesfalse: this backlog server can't run exports from the API
exit_codeYes
started_atYes
exported_atYes
finished_atYes
elapsed_secondsYes
library_changedYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the description's added value is the available=false condition (server too old to run exports) and the side-effect note that a successful export makes the new library visible to other tools. These are genuinely non-obvious behaviors an agent would otherwise misinterpret. Polling cadence and failure semantics are still unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The use_case block is front-loaded and dense with concrete facts, and the important_notes carry the two operational caveats. Minor waste remains: the <example> line shows a zero-argument call that conveys nothing, and the return-field enumeration partially duplicates the existing output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters, an output schema, and read-only annotations, the description only needs to supply the non-obvious semantics, which it does via the available=false case and the post-export visibility note. What is missing is operational framing around polling (one-shot vs. repeated calls, whether a terminal state is guaranteed), which matters for a status tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is no parameter meaning to add and the baseline of 4 applies. The description does not waste words on inputs, which is correct here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource and enumerates exactly what is reported: running/finished/failed state, phase (deck, details, proton, hltb), progress, elapsed time, log tail, and whether the library changed. It never explicitly contrasts itself with the sibling backlog_start_export, so an agent must infer that this is the read-side counterpart of the export pair rather than being told.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"How the library refresh is going" plus the note that other tools see the new library after a successful export clearly frames this as the post-start monitoring call. It stops short of explicit guidance such as when to poll, how often, or that it should be called after backlog_start_export, and no alternative tool is named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_get_gameGet one gameA
Read-only

<use_case> Everything about one game: playtime and Deck playtime, last played, Steam Deck rating, ProtonDB tier and report count, HowLongToBeat times, genres, Metacritic, controller support, triage lane, note, position in Up next, couch score with its breakdown, and the Steam store link. </use_case> <important_notes>

  • game is an app id or the exact name. If the name matches several games or none, found is false and unresolved lists candidates (reason ambiguous/no_match): pick one by app id or ask the user.

  • null fields are unknown, not zero. </important_notes> backlog_get_game(game="Hades")

NameRequiredDescriptionDefault
gameYesA Steam app id (e.g. '620') or the game's exact name

Output Schema

NameRequiredDescription
gameYes
foundYes
unresolvedYesWhen found is false: why, and candidates to pick from

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely useful behavior beyond that: failure semantics (found=false, unresolved with ambiguous/no_match reasons) and the null-means-unknown-not-zero rule, which prevents misreading missing data. It says nothing about size limits, ordering, or whether all listed fields are always present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Tagged sections (use_case, important_notes, example) keep it front-loaded and scannable, with the critical resolution rule placed early. The field enumeration is the only padding, and even that is expressed as a compact comma list rather than prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the long enumeration of returned fields is partly redundant, and the description never needs to explain return shape. Everything an agent needs to call it correctly — input form, ambiguity recovery, null semantics, and a worked example — is present, so completeness is strong despite that redundancy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents the single 'game' parameter and its min/max length. The description still contributes meaning the schema lacks: the acceptance of a numeric app id or an exact name, the ambiguity fallback, and a concrete call example. Baseline 3 raised to 4 for that added resolution semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description leads with 'Everything about one game' and enumerates the exact payload domains (playtime, Deck rating, ProtonDB, HLTB, triage lane, note, queue position, couch score, store link), so the resource and single-game scope are unmistakable. It never contrasts itself explicitly with the sibling backlog_find_games, which is the only thing keeping it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The important_notes give concrete operating guidance: pass an app id or exact name, and when the name is ambiguous or unmatched the call returns found=false with unresolved candidates plus a reason code, at which point the agent should pick by app id or ask the user. It stops short of stating when to reach for this versus backlog_find_games for discovery.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_get_next_queueUp next queueA
Read-only

<use_case> The Up next lane (queue, play soon) in the user's order, with each game's note. </use_case> <important_notes>

  • Same order as the dashboard: the saved order first, then any unordered Up next games by score.

  • Change the order with backlog_reorder_next; add or remove games with backlog_set_lane. </important_notes> backlog_get_next_queue()

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
queueYes
detailYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description does add real behavioral context beyond that: the ordering rule (saved order first, then unordered games by score) and the inclusion of per-game notes. With annotations carrying the read-only signal, a 3 is the appropriate level for this incremental detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The tagged structure (<use_case>, <important_notes>, <example>) front-loads the purpose and keeps each line substantive. Every sentence either defines the resource or routes to a sibling; nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not required, and the ordering semantics are disclosed. The only remaining gap is edge-case behavior (e.g. an empty Up next lane), which is minor for a zero-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline of 4 applies. There is nothing for the description to disambiguate and it correctly stays silent rather than padding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource ('The Up next lane (queue, play soon)') and states what is returned ('with each game's note'), so an agent knows exactly what it fetches. It does not, however, distinguish itself from the main read sibling backlog_get_overview, leaving that separation to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The important_notes section routes the agent explicitly for mutations: ordering changes go to backlog_reorder_next, membership changes to backlog_set_lane. What's missing is guidance on when to call this versus backlog_get_overview or backlog_suggest_picks, so usage context is clear but not fully exclusionary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_get_overviewBacklog overviewA
Read-only

<use_case> Start here. Summarizes the user's Steam library and backlog (pile of shame): how many games are never played, tried or played; Steam Deck ratings; the backlog by Deck rating and length; triage lane counts; the Up next queue length; how old the library export is; and how complete each data source is. </use_case> <important_notes>

  • coverage says how much data exists (e.g. hltb 0.8 = 80% of games have HowLongToBeat times). Low coverage means many unknowns, not bad games.

  • export.age_days: the library is as of the last export; offer backlog_start_export if it's stale and the user asks about recent purchases.

  • dry_run true: writes are simulated. </important_notes> backlog_get_overview()

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
deckYes
gridYesBacklog games by Deck rating, then length bucket
gamesYes
lanesYes
notesYes
exportYes
backlogYes
dry_runYes
coverageYesShare of games with each data source (0..1)
next_queueYes
api_versionYes
play_statesYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true and openWorldHint=false, so the safety profile is covered; the description adds genuine beyond-schema meaning such as coverage semantics ("hltb 0.8 = 80% of games have HowLongToBeat times. Low coverage means many unknowns, not bad games") and the temporal meaning of export.age_days. The "dry_run true: writes are simulated" note is inert and slightly confusing for a zero-parameter read-only tool, which keeps this from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The use_case block is front-loaded and information-dense, the notes are bulleted, and the example is a single trivial call. The one wasteful line is the dry_run note, which earns no place in a parameterless read-only tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be spelled out, and the description instead explains how to interpret the trickiest fields (coverage, age_days). For a zero-parameter aggregate tool, an agent has everything needed to call it correctly and to act on the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so the baseline is 4 and there is nothing for the description to disambiguate. It still usefully frames what the returned aggregates represent (coverage per data source, export staleness), which is the only semantic work available here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Start here. Summarizes the user's Steam library and backlog" gives a specific verb and resource, then enumerates exactly what the summary contains (played/never-played counts, Deck ratings, backlog by rating and length, triage lanes, Up next length, export age, data completeness). This clearly separates it from siblings like backlog_get_next_queue or backlog_find_games, which return a queue or a list rather than aggregate stats.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Start here" is an explicit entry-point instruction, and the description names a concrete alternative branch: use backlog_start_export when export.age_days is stale and the user asks about recent purchases. It does not state any case where this tool should be avoided in favour of backlog_get_game or backlog_suggest_picks, so it falls short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_reorder_nextReorder Up nextA
Idempotent

<use_case> Change the order of the Up next lane (queue): move one game to a position ("put Celeste first"), or give the order of several games. </use_case> <important_notes>

  • Give either game + position, or order; not both.

  • Only games already in Up next can be ordered; add a game with backlog_set_lane(lane="next") first.

  • Positions are 1-based; a position past the end moves the game to the end.

  • If the dashboard reorders at the same moment, this re-reads once and retries; if that also collides, the outcome is conflict and nothing was changed.

  • Returns the previous order, so it can be undone. </important_notes> backlog_reorder_next(game="Celeste", position=1)

NameRequiredDescriptionDefault
gameNoMove this one game...
orderNoOr the new order: these Up next games first, in this order; the rest keep theirs
positionNo...to this 1-based position

Output Schema

NameRequiredDescription
orderYes
detailYes
outcomeYes
previousYes
warningsYes
protectedYesfalse: written without a concurrency check (older backlog server)
unresolvedYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, idempotentHint=true), the description discloses non-obvious runtime behavior: a single re-read and retry on concurrent dashboard reordering, and that a second collision yields a 'conflict' outcome with no change made. It also notes the previous order is returned, enabling undo.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The XML-tagged structure front-loads the use case, then constraints, then a concrete example call. Every sentence carries information — no marketing or filler — and the example anchors the syntax.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with an output schema available, the description covers constraints, prerequisites, concurrency semantics, and undo. Nothing an agent needs in order to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameter meaning is already documented and the baseline is 3. The description adds genuine value with the mutual-exclusivity rule and the note that positions are 1-based and that a position past the end appends to the end. It doesn't add format details for the game identifier itself, which the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Change the order of the Up next lane') and enumerates the two operating modes (single game + position, or a full order list). This clearly distinguishes it from siblings like backlog_set_lane and backlog_get_next_queue.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when the tool applies ('Only games already in Up next can be ordered') and names the prerequisite alternative ('add a game with backlog_set_lane(lane="next") first'). It also states that game+position and order are mutually exclusive, so the agent knows how to choose between modes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_set_laneSet triage laneA
Idempotent

<use_case> Put games in a triage lane (list, bucket, shelf): next (up next, play soon), someday, skip, or done (finished, beaten), or take them out of every lane (none). Saved to the user's dashboard immediately. </use_case> <important_notes>

  • A single game the user named can be moved to any lane, done and skip included, without asking.

  • Ask the user first before moving more than five games, or before marking skip or done a game the user didn't name. Then call again with confirmed=true. Over five games without it, nothing is changed and the outcome is needs_confirmation with the list of changes.

  • Never mark a game done just because it has playtime.

  • Every game must resolve to exactly one library game; otherwise nothing is changed and unresolved lists candidates. Pass app ids from backlog_find_games when names are ambiguous (two games called "DOOM").

  • Returns each game's previous lane, so a mistake can be undone.

  • Adding to next puts a game at the end of Up next; reorder with backlog_reorder_next. </important_notes> backlog_set_lane(games=["Hades"], lane="done")

NameRequiredDescriptionDefault
laneYesnext (up next/queue), someday, skip, done (finished), or none (untriage)
gamesYesApp ids or exact names, 1 to 50 games
confirmedNotrue once the user has confirmed a change to more than five games

Output Schema

NameRequiredDescription
atomicYesfalse: previous values were read separately (older backlog server)
detailYes
changesYes
outcomeYes
warningsYes
unresolvedYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (which only declare idempotent, non-destructive writes) by disclosing the confirmation gate, the needs_confirmation outcome, atomic all-or-nothing resolution, unresolved candidate listing, and that previous lanes are returned for undo. The only missing detail is whether partial writes can occur mid-batch, though 'nothing is changed' largely covers this.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Use-case, notes, and example sections make it scannable and front-loaded, with each note carrying a distinct rule. The lane list is repeated in both the use_case block and the schema enum, which is slight redundancy but not harmful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need only light mention; the description still notes that previous lanes come back. For a mutation tool with a confirmation flow, the safety rules, resolution requirement, and failure outcomes are all covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description still adds real meaning by explaining when confirmed=true is required and why app ids beat names when two games share a title. The lane vocabulary is largely duplicated from the enum description, which caps it below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Put games in a triage lane') plus the exact set of destinations (next, someday, skip, done, none) and the immediate-persistence behavior. The parenthetical synonyms (up next, finished, beaten) make the lane vocabulary unambiguous, and 'none' is explicitly framed as untriaging rather than a fifth lane.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-act rules: a single named game can be moved freely, more than five games or unnamed skip/done requires asking first, then confirmed=true. It also routes to the right sibling for ambiguity (backlog_find_games) and for ordering (backlog_reorder_next), and warns against inferring 'done' from playtime.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_set_noteSet a noteA
Idempotent

<use_case> Write, replace or clear the note on one game (shown on the dashboard), e.g. "save for the flight" or "stuck at the second boss". </use_case> <important_notes>

  • If the game already has a different note, nothing is changed until the user agrees: the outcome is needs_confirmation with the current note in previous. Then call again with confirmed=true.

  • An empty note clears it. Returns the previous note, so a mistake can be undone.

  • The note is the user's text; store what they asked for, not instructions. </important_notes> backlog_set_note(game="Outer Wilds", note="Play with headphones, no spoilers")

NameRequiredDescriptionDefault
gameYesA Steam app id (e.g. '620') or the game's exact name
noteYesThe note text (up to 2,000 characters); empty clears it
confirmedNotrue once the user has agreed to replace or clear an existing note

Output Schema

NameRequiredDescription
nameYes
noteYes
appidYes
atomicYes
detailYes
outcomeYes
previousYes
warningsYes
unresolvedYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a non-destructive, idempotent write, and the description goes further by describing the confirmation gate, the needs_confirmation outcome with the prior note, and that the previous note is returned so a mistake can be undone. The added warning to store the user's text rather than follow instructions is a genuinely useful behavioral disclosure. It stops short of describing response shape details, which the output schema presumably covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The sectioned layout front-loads the use case and then the behavioral rules, and the example is compact and illustrative. The tag markup adds a little visual overhead, but every sentence carries information the agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter mutation with a confirmation flow, the description covers the trigger, the retry path, the clearing semantics, and the undo affordance, and an output schema exists to explain return values. Nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it ties confirmed=true to the post-agreement retry and clarifies that an empty note is a clear operation rather than a no-op. The game parameter is only illustrated through the example, which is already documented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb set (write, replace, clear) against a specific resource (the note on one game) and scopes it to the dashboard. It is clearly distinct from siblings such as backlog_set_lane or backlog_reorder_next, which mutate different fields.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit when-to-use case with examples and an explicit conditional path: if a different note exists, nothing changes and the call returns needs_confirmation, so the agent must re-call with confirmed=true. It also states the empty-string clearing case, leaving little to infer.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_start_exportRefresh the libraryA
Idempotent

<use_case> Refresh the library: re-export the Steam library with fresh playtime, new purchases, Deck ratings, ProtonDB and HowLongToBeat data. Use when the user just bought or played something and the overview's export is older than that. </use_case> <important_notes>

  • Returns immediately; the export runs on the server for minutes (up to an hour for a first run of a big library). Check on it with backlog_get_export_status; don't poll in a tight loop.

  • If one is already running (including the weekly scheduled one), returns its status instead.

  • Reaches out to Steam, HowLongToBeat and ProtonDB through the backlog server; no keys pass through here. </important_notes> backlog_start_export()

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
detailYes
statusYes
outcomeYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations say readOnlyHint=false and idempotentHint=true, but the description carries the real burden: it discloses that the call returns immediately while work runs server-side for minutes (up to an hour on a first run), that a concurrent/scheduled run yields its status instead, and that external services (Steam, HLTB, ProtonDB) are contacted with no key handling on this side. That is exactly the async/mutation context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the use case, then separates operational caveats into bullets, which is easy to scan. The trailing <example>backlog_start_export()</example> block adds essentially no information for a zero-argument tool and is the only real filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even though an output schema exists, the description supplies the missing lifecycle context an agent needs: fire-and-forget semantics, expected duration, where to check progress, and what happens on a duplicate call. Nothing needed to invoke this correctly is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so the baseline of 4 applies; the description correctly implies a zero-argument call and does not invent or omit any input semantics. Nothing further could be added beyond what the empty schema already conveys.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('re-export the Steam library') and enumerates exactly what gets refreshed: playtime, purchases, Deck ratings, ProtonDB, HowLongToBeat. The verb 'start/refresh' plus the explicit pointer to backlog_get_export_status makes it distinguishable from every sibling, including the status-checking one.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete trigger ('when the user just bought or played something and the overview's export is older than that'), names the alternative tool for checking progress, and explicitly forbids the wrong behavior ('don't poll in a tight loop'). It also covers the already-running case, telling the agent it gets the existing status rather than a new job.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backlog_suggest_picksSuggest couch picksA
Read-only

<use_case> Answer "what should I play (tonight / next / on the Steam Deck)?": the best backlog games for the couch, ranked by the dashboard's couch score, each with a score breakdown (e.g. never played +30, Verified +30, 8 h +18, MC 86 +5.5) so you can explain why it was picked. </use_case> <important_notes>

  • Only backlog games (unplayed and not in skip or done), with the same filters as backlog_find_games.

  • Ranked by score alone, exactly like the dashboard's Couch picks. Up next games get +100, which usually but not always puts them first. exclude_next=true shows fresh candidates.

  • Explain picks from score_breakdown; don't invent reasons, lengths or ratings.

  • If the filters leave nothing, the closest picks come back with exact=false and the dropped filters. </important_notes> backlog_suggest_picks(count=3, deck=["verified"], hours_max=10)

NameRequiredDescriptionDefault
deckNoSteam Deck ratings to include
countNo
queryNoWords from the name or a genre, e.g. 'hollow'
genresNoStore genres, e.g. ['RPG', 'Roguelike']
lengthNoshort (<5 h), mid (5-15), long (15-40), epic (40+), none (no HLTB data)
year_toNo
has_noteNotrue: only games with a note; false: without
protondbNoProtonDB tiers to include
hours_maxNo
hours_minNo
year_fromNo
controllerNoController support
play_stateNonever (0 min), tried (<2 h), played (2 h+)
genre_matchNoany: one of the genres; all: every oneany
exclude_nextNoLeave out games already in Up next, to see fresh candidates
protondb_minNoMinimum ProtonDB tier: native > platinum > gold > silver > bronze > borked
length_measureNoWhich HowLongToBeat time the length uses: main, extra (main+extras), completemain
metacritic_minNo
include_unknownNoAlso include games with no data for a filter (unknown length, tier, year...)

Output Schema

NameRequiredDescription
exactYes
picksYes
detailYes
relaxedYes
consideredYesBacklog games that passed the filters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, yet the description still adds real behavior: only unplayed, non-skipped, non-done games are eligible, ranking is score-only with a +100 Up-next bonus that "usually but not always" wins, and empty filter results degrade to closest picks with exact=false plus the dropped filters. It also warns not to invent reasons and to explain picks from score_breakdown, which constrains downstream behavior meaningfully.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the use case, then notes, then a concrete example — the ordering matches how an agent reads. The tag structure is slightly heavy for the amount of content, and the score-breakdown example is repeated in two places, but every sentence carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 19-parameter ranking tool with an output schema, the description covers what the schema cannot: eligibility rules, ranking mechanics, the fallback/degradation path, and how to explain results. Nothing an agent needs in order to call it correctly or interpret a surprising result is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 19 parameters at 68% schema description coverage, the schema already documents most filters, and the description adds little per-parameter meaning beyond reiterating exclude_next and showing one example call with count, deck and hours_max. Many parameters (year_from/year_to, hours_min, metacritic_min, length_measure) get no elaboration in the description, so it neither compensates for the coverage gap nor adds much beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — pick the best backlog games for the couch, ranked by the dashboard's couch score — and frames it around the exact user question it answers ("what should I play tonight / on the Steam Deck"). It distinguishes itself from the sibling search tool by noting it shares filters with backlog_find_games while adding ranking, so an agent can tell the two apart without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The <use_case> block gives clear context for when to call it, and the notes add conditions such as exclude_next=true for fresh candidates and the fact that near-miss results come back with exact=false. It references backlog_find_games as the filtering counterpart but never explicitly says when NOT to use this tool (e.g. for a known-title lookup), so the routing guidance stops just short of fully explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.1.0
    • First observedbacklog_find_games
    • First observedbacklog_get_export_status
    • First observedbacklog_get_game
    • First observedbacklog_get_next_queue
    • First observedbacklog_get_overview
    • First observedbacklog_reorder_next
    • First observedbacklog_set_lane
    • First observedbacklog_set_note
    • First observedbacklog_start_export
    • First observedbacklog_suggest_picks

TDQS

A4.4/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct resource+action: search (find_games), single-game detail (get_game), summary (get_overview), recommendation (suggest_picks), queue read vs. reorder, note write, lane write, and export start vs. status. The descriptions explicitly cross-reference each other (e.g. find_games says to use suggest_picks for recommendations), eliminating the main potential overlap.

Naming Consistency5/5

All ten tools share the backlog_ prefix and follow a consistent snake_case verb_noun pattern (find_games, get_game, set_lane, reorder_next, start_export). No mixed conventions or vague verbs.

Tool Count5/5

Ten tools is well within the ideal 3-15 range and each maps to a clear, non-redundant capability for a backlog dashboard: read, filter, recommend, triage, annotate, order, and refresh. Nothing feels padded or missing a counterpart.

Completeness4/5

The lifecycle is well covered: overview, filtered search, per-game detail, ranked picks, lane transitions, note management (including clearing), queue ordering, and export start/status. Minor gaps exist (no dedicated lane-listing beyond filter-by-lane in find_games, no batch note operations), but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Connects Claude to your Steam library via the Steam Web API. Query your games, playtime, recently played history, and store metadata using natural language. Zero-config install via npx steam-mcp.
    5
    25 npm
    6
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Exposes Steam Web API tools as MCP resources for Claude Code, Claude Desktop, and Gemini CLI, enabling profile lookups, game searches, achievement tracking, and more.
    11
    25 npm
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that connects AI assistants to the Steam Web API and storefront, enabling game library analysis, mood-based backlog recommendations, wishlist evaluation, and storefront searches.
    8
    18 npm
    MIT