mcp-server-steam-backlog
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-server-steam-backlogWhat should I play tonight on the Deck under 10 hours?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.jsonThe 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 frombacklog.htmlitself, so Claude and the dashboard never disagree about the best pick.backlog://scoringexplains it.The interface is specified in
docs/backlog-api-contract.md.
Related MCP server: steam-mcp
Tools
Tool | What it does |
| Start here: library size, never/tried/played, Deck ratings, the backlog by Deck rating × length, lane counts, Up next length, export age, data coverage |
| 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" |
| Everything about one game, with its score breakdown and store link |
| Couch picks with the same filters, each with a score breakdown to explain it |
| The Up next lane in order, with notes |
| Move 1–50 games to next, someday, skip, done, or out of every lane |
| Write, replace or clear a game's note |
| Move a game within Up next, or set the order |
| Refresh the library (runs on the backlog server; minutes to an hour) |
| 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_confirmationwith the planned change until the call is repeated withconfirmed=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 | ✓ |
Reorders safe against a concurrent dashboard edit | no (flagged | ✓ |
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=3simulate --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 startThe 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.
Snapshot first if this shares a container with other services.
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.Add a tunnel rule sending
^/mcp/tohttp://localhost:8486, above any broader rule for the same hostname.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 restartandmcp-server-steam-backlog doctor.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 -5If it redirects, give the MCP its own hostname instead.
Add
https://backlog.example.com/mcp/backlogas a custom connector in Claude.
Settings
Variable | Default | |
|
| The backlog server |
| off | Report writes without sending them |
| 60 | Writes per minute (1–600) |
| off | Debug logging |
| off | Show LAN addresses in logs (secrets and SteamIDs stay hidden) |
|
| The HTTP service |
| Cloudflare Access |
Checking it with the MCP Inspector
npx @modelcontextprotocol/inspector mcp-server-steam-backlogTen tools listed, each with a title, annotations and an output schema
backlog_get_overviewreturns the library size and export agebacklog_suggest_picksreturns picks withscore_breakdownbacklog_set_lanewithgames=["DOOM"](or any duplicated name) returnsnot_resolvedand changes nothingbacklog_set_lanewith six games returnsneeds_confirmation; withconfirmed=true,donebacklog_set_noteover an existing note returnsneeds_confirmationWith
BACKLOG_DRY_RUN=1, writes returndry_runand the dashboard doesn't changebacklog://scoringreads;backlog://game/620reads for a game in the libraryPrompts
triage_sessionandpick_for_tonightrender
Development
pip install -e ".[dev]"
ruff check . && ruff format --check . && mypy && pytest --covThe 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 intests/conftest.py),BACKLOG_CHECKOUT=<dir>uses a local checkout. Seedocs/handoff-pr-a.md.tests/fixtures/score_vectors.jsoncomes fromnode scripts/gen_score_vectors.mjs path/to/backlog.html. CI regenerates it and fails if the page'sscore()changed.Files shared with the sibling MCP servers (
remote.py,logsafe.py,lookup.py,ratelimit.py,tools.py,tasks.pyand their tests) come from mcp-server-shared; change them there, thenpython scripts/sync_shared.py --update.
License
MIT
Available Tools
10 toolsbacklog_find_gamesFind gamesARead-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")
| Name | Required | Description | Default |
|---|---|---|---|
| deck | No | Steam Deck ratings to include | |
| lane | No | Triage lanes; 'none' = untriaged | |
| sort | No | score (couch score), short (shortest first), name, recent, most (playtime), mc | score |
| limit | No | ||
| query | No | Words from the name or a genre, e.g. 'hollow' | |
| genres | No | Store genres, e.g. ['RPG', 'Roguelike'] | |
| length | No | short (<5 h), mid (5-15), long (15-40), epic (40+), none (no HLTB data) | |
| offset | No | ||
| year_to | No | ||
| has_note | No | true: only games with a note; false: without | |
| protondb | No | ProtonDB tiers to include | |
| hours_max | No | ||
| hours_min | No | ||
| year_from | No | ||
| controller | No | Controller support | |
| play_state | No | never (0 min), tried (<2 h), played (2 h+) | |
| genre_match | No | any: one of the genres; all: every one | any |
| backlog_only | No | Only unplayed games not in skip or done | |
| protondb_min | No | Minimum ProtonDB tier: native > platinum > gold > silver > bronze > borked | |
| length_measure | No | Which HowLongToBeat time the length uses: main, extra (main+extras), complete | main |
| metacritic_min | No | ||
| include_unknown | No | Also include games with no data for a filter (unknown length, tier, year...) |
Output Schema
| Name | Required | Description |
|---|---|---|
| exact | Yes | false: nothing matched as asked; these are the closest matches |
| games | Yes | |
| detail | Yes | |
| offset | Yes | |
| matches | Yes | |
| relaxed | Yes | Filters dropped to find these (weakest first) |
| truncated | Yes | |
| fuzzy_query | Yes |
TDQS
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.
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.
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.
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.
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.
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 statusARead-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()
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| lines | Yes | |
| phase | Yes | |
| state | Yes | |
| detail | Yes | |
| origin | Yes | |
| reason | Yes | |
| progress | Yes | |
| available | Yes | false: this backlog server can't run exports from the API |
| exit_code | Yes | |
| started_at | Yes | |
| exported_at | Yes | |
| finished_at | Yes | |
| elapsed_seconds | Yes | |
| library_changed | Yes |
TDQS
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.
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.
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.
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.
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.
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 gameARead-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")
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | A Steam app id (e.g. '620') or the game's exact name |
Output Schema
| Name | Required | Description |
|---|---|---|
| game | Yes | |
| found | Yes | |
| unresolved | Yes | When found is false: why, and candidates to pick from |
TDQS
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.
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.
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.
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.
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.
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 queueARead-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()
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| queue | Yes | |
| detail | Yes |
TDQS
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.
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.
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.
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.
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.
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 overviewARead-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()
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| deck | Yes | |
| grid | Yes | Backlog games by Deck rating, then length bucket |
| games | Yes | |
| lanes | Yes | |
| notes | Yes | |
| export | Yes | |
| backlog | Yes | |
| dry_run | Yes | |
| coverage | Yes | Share of games with each data source (0..1) |
| next_queue | Yes | |
| api_version | Yes | |
| play_states | Yes |
TDQS
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.
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.
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.
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.
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.
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 nextAIdempotent
<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)
| Name | Required | Description | Default |
|---|---|---|---|
| game | No | Move this one game... | |
| order | No | Or the new order: these Up next games first, in this order; the rest keep theirs | |
| position | No | ...to this 1-based position |
Output Schema
| Name | Required | Description |
|---|---|---|
| order | Yes | |
| detail | Yes | |
| outcome | Yes | |
| previous | Yes | |
| warnings | Yes | |
| protected | Yes | false: written without a concurrency check (older backlog server) |
| unresolved | Yes |
TDQS
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.
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.
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.
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.
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.
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 laneAIdempotent
<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")
| Name | Required | Description | Default |
|---|---|---|---|
| lane | Yes | next (up next/queue), someday, skip, done (finished), or none (untriage) | |
| games | Yes | App ids or exact names, 1 to 50 games | |
| confirmed | No | true once the user has confirmed a change to more than five games |
Output Schema
| Name | Required | Description |
|---|---|---|
| atomic | Yes | false: previous values were read separately (older backlog server) |
| detail | Yes | |
| changes | Yes | |
| outcome | Yes | |
| warnings | Yes | |
| unresolved | Yes |
TDQS
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.
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.
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.
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.
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.
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 noteAIdempotent
<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")
| Name | Required | Description | Default |
|---|---|---|---|
| game | Yes | A Steam app id (e.g. '620') or the game's exact name | |
| note | Yes | The note text (up to 2,000 characters); empty clears it | |
| confirmed | No | true once the user has agreed to replace or clear an existing note |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | Yes | |
| note | Yes | |
| appid | Yes | |
| atomic | Yes | |
| detail | Yes | |
| outcome | Yes | |
| previous | Yes | |
| warnings | Yes | |
| unresolved | Yes |
TDQS
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.
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.
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.
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.
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.
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 libraryAIdempotent
<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()
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| detail | Yes | |
| status | Yes | |
| outcome | Yes |
TDQS
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.
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.
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.
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.
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.
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 picksARead-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)
| Name | Required | Description | Default |
|---|---|---|---|
| deck | No | Steam Deck ratings to include | |
| count | No | ||
| query | No | Words from the name or a genre, e.g. 'hollow' | |
| genres | No | Store genres, e.g. ['RPG', 'Roguelike'] | |
| length | No | short (<5 h), mid (5-15), long (15-40), epic (40+), none (no HLTB data) | |
| year_to | No | ||
| has_note | No | true: only games with a note; false: without | |
| protondb | No | ProtonDB tiers to include | |
| hours_max | No | ||
| hours_min | No | ||
| year_from | No | ||
| controller | No | Controller support | |
| play_state | No | never (0 min), tried (<2 h), played (2 h+) | |
| genre_match | No | any: one of the genres; all: every one | any |
| exclude_next | No | Leave out games already in Up next, to see fresh candidates | |
| protondb_min | No | Minimum ProtonDB tier: native > platinum > gold > silver > bronze > borked | |
| length_measure | No | Which HowLongToBeat time the length uses: main, extra (main+extras), complete | main |
| metacritic_min | No | ||
| include_unknown | No | Also include games with no data for a filter (unknown length, tier, year...) |
Output Schema
| Name | Required | Description |
|---|---|---|
| exact | Yes | |
| picks | Yes | |
| detail | Yes | |
| relaxed | Yes | |
| considered | Yes | Backlog games that passed the filters |
TDQS
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.
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.
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.
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.
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.
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.
10 tool updates
v0.1.0- First observed
backlog_find_games - First observed
backlog_get_export_status - First observed
backlog_get_game - First observed
backlog_get_next_queue - First observed
backlog_get_overview - First observed
backlog_reorder_next - First observed
backlog_set_lane - First observed
backlog_set_note - First observed
backlog_start_export - First observed
backlog_suggest_picks
TDQS
Scored across 10 tools
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.
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.
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.
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
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Official Fibery MCP server: query and update your workspace from any AI client via OAuth.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Related MCP Servers
- AlicenseAqualityDmaintenanceConnects 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.525 npm6MIT
- AlicenseAqualityBmaintenanceExposes Steam Web API tools as MCP resources for Claude Code, Claude Desktop, and Gemini CLI, enabling profile lookups, game searches, achievement tracking, and more.1125 npm1MIT
- AlicenseAqualityDmaintenanceA local MCP server that lets Claude fetch data from your Steam game library via the Steam Web API. All tools are read-only.5Apache 2.0
- AlicenseAqualityDmaintenanceAn 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.818 npmMIT