Add support for steam-mcp #52
Labels
No labels
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/mcp-beaver#52
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
https://forgejo.coilysiren.me/coilyco-gaming/steam-ops
Picked this up in a sweep of the open queue. It needs a decision from you before code, because "add support" has two readings with very different work behind them - and I would rather ask than build the wrong one.
Reading A - proxy the existing server.
serve-upstreamalready wraps any streamable-HTTP MCP with a name allowlist, and steam-mcp is exactly that. Nothing to build; it is a values file in deploy. Witha328d5eit can also carry--pinto bound arguments.Reading B - replace the bespoke server with a guardfile, so
steam-opsstops shipping its own Go and becomes one more.mcp.kdlon the generic runtime. That is the product thesis, and I assume it is what you meant.Feasibility for B, from the deploy README's description of the source: partial, and the split is clean.
key=query parameter, which is exactlyauth query-param, andsteamid64is an ordinary path or query field. This part is a straightforward guardfile.So B is "most of it, plus a decision about PICS", not a clean lift-and-shift.
Related finding worth carrying across all three of these issues (#50, #51, #52): the guardfile
authblock resolves a static value -env,file, orliteral. It cannot perform a login or token exchange. That is what makes Steam easy (a fixed API key) and Bluesky hard (an app password exchanged for a session token). Steam is the tractable one of the three.Which reading did you intend, and do you want the Web API plus storefront half as a guardfile with PICS left in the bespoke server?
Reading B confirmed by Kai. Steam is done — landed in
d262653.Two guardfiles, because the Web API and storefront are different hosts and one guardfile has one
base-url. That split turns out to be right on its own terms: different credentials, different risk, different rate profile.examples/steam-web-api.mcp.kdl—get_owned_games,get_recently_playedexamples/steam-storefront.mcp.kdl—get_store_app_details,get_store_search_resultsDelivering this safely needed one runtime capability first.
setwrites fixed body values only, so a GET carrying its scope in the query string had no server-side way to fix it. Without that,steamidwould have to be a declared caller field — turning "Kai's library" into "any steamid64's library". That is the same hole as #56, in the mode #56 did not cover. So:Resolved at call time from
env/file/literal, likeauth. The pinned name is absent from the tool schema andsplitArgsdrops anything unschemed, so a caller can neither supply nor override it — tested by calling with a competing steamid and asserting the pinned value still reaches the upstream. No umbra change needed: opcore passes undeclared query names through.Four of six tools.
get_account_licensesandget_pics_product_inforide Steam's authenticated client plane (PICS, refresh-token first), a binary session protocol this HTTP runtime cannot speak. They ship aswithholdstubs, so the surface says so instead of leaving an agent to infer it from a hole. Moving them behind a PICS-speaking sidecar is possible now that #59 landed, but it means writing that process — not obviously better than leaving those two in the bespoke server.Two migration details found by building it rather than reasoning about it:
verb_resourcekeeps underscores, socan get owned_gamesmintsget_owned_games. No consumer sees a rename — which I had assumed would be a cost and is not.queryis a reserved opcore engine flag (withdry-run,output,body-file) and fails closed, so the storefront search input istermrather thanquery. That is the only caller-visible difference in the whole migration.The deploy-side work is a values file per server plus
STEAM_API_KEYandSTEAM_STEAMID64in SSM.ward exec lint-exampleslints both, and every other committed example, on demand.Closing. The two client-plane tools are recorded above rather than left implicit; reopen or file fresh if you want the sidecar.