Skip to main content
Glama

Save Cloud Data

horizon_save_cloud_data
DestructiveIdempotent

Stores a player's save game as a single string on the server, replacing the previous save. Pass expectedRevision to prevent silently overwriting a save from another device.

Instructions

Stores a player's save game as one string (usually JSON) on the server, replacing the player's previous save. Use when: the game saves progress so it survives reinstalls and can be loaded on another device. Pass expectedRevision (the revision from horizon_load_cloud_data or the last save) so a save from another device is never overwritten silently. Not for: reading the save (use horizon_load_cloud_data) or server-owned currency that players must not edit (use Validated Actions: horizon_submit_validated and horizon_get_state). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Side effects: overwrites the player's single save slot; the old save is gone. With expectedRevision it only writes while the save is still at that revision. Saving the same data again changes nothing. Returns: {success: true, dataSizeBytes, revision}. revision is the new revision: pass it as expectedRevision to the next save. Errors: 409 (only with expectedRevision) when another device saved first: nothing was written, load the current save and revision, decide, then save again. 403 when the data exceeds the tier limit (defaults FREE 1 KB, BASIC 5 KB, PRO 20 KB, ENTERPRISE 250 KB): shrink the save or upgrade. 401 means the session is missing or expired: sign in again and retry with the new accessToken. 403 for a session means the token belongs to another user: pass the userId that signed in. Needs HORIZON_API_KEY. Every failure returns an error result (isError) with the HTTP status and body: a 401 that horizon_test_connection also returns means HORIZON_API_KEY is wrong, 429 means the account's per-minute rate limit was reached (wait a minute, then retry).

Input Schema

NameRequiredDescriptionDefault
dataYesThe complete save as a string, usually serialized JSON (max 300,000 characters; the tier limit is usually lower)
userIdYesPlayer user ID (UUID) from horizon_signup_* or horizon_signin_*
sessionTokenYesaccessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session
expectedRevisionNoOptional. Revision the save must still have, sent as If-Match: 0 for an empty slot, else the revision from horizon_load_cloud_data or the last save. Omit for an unconditional overwrite.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv1.9.1
    • addedInput schema / properties / expectedRevision
      Added value: +{
      +  "description": "Optional. Revision the save must still have, sent as If-Match: 0 for an empty slot, else the revision from horizon_load_cloud_data or the last save. Omit for an unconditional overwrite.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
  2. Changed3 schema fields changedv1.6.0
    • changedInput schema / properties / data / description
      Previous value: -"Save data string, usually serialized JSON (max 300,000 characters; the tier limit is usually lower)"New value: +"The complete save as a string, usually serialized JSON (max 300,000 characters; the tier limit is usually lower)"
    • changedInput schema / properties / sessionToken / description
      Previous value: -"accessToken returned by horizon_signin_email or horizon_signin_anonymous for this user; sent as a Bearer session"New value: +"accessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session"
    • changedInput schema / properties / userId / description
      Previous value: -"User ID (UUID) returned by a horizon_signup_* or horizon_signin_* tool"New value: +"Player user ID (UUID) from horizon_signup_* or horizon_signin_*"
  3. Changed4 schema fields changedv1.5.5
    • changedInput schema / properties / data / description
      Previous value: -"Save data string (max 300,000 characters)"New value: +"Save data string, usually serialized JSON (max 300,000 characters; the tier limit is usually lower)"
    • addedInput schema / properties / sessionToken
      Added value: +{
      +  "description": "accessToken returned by horizon_signin_email or horizon_signin_anonymous for this user; sent as a Bearer session",
      +  "maxLength": 256,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / properties / userId / description
      Previous value: -"User ID (UUID)"New value: +"User ID (UUID) returned by a horizon_signup_* or horizon_signin_* tool"
    • changedInput schema / required
      Previous value: -[
      -  "userId",
      -  "data"
      -]New value: +[
      +  "userId",
      +  "data",
      +  "sessionToken"
      +]
  4. First observedv1.5.4

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond annotations (destructiveHint/idempotentHint are already declared) by specifying what is destroyed ('the old save is gone'), the single-slot model, the compare-and-swap behavior of expectedRevision, the no-op on identical data, and the tier size caps. Error handling (409/403/401/429 and what each means for retry) is spelled out, which is exactly the added context annotations cannot carry.

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?

Well front-loaded with labeled sections (Use when / Not for / Requires / Side effects / Returns / Errors), so an agent can scan to the relevant part. It is on the long side and the error paragraph packs several unrelated failures into one run-on block, but nearly every sentence carries actionable information rather than restating the schema.

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?

Covers a destructive mutation with no output schema by describing the return shape ({success, dataSizeBytes, revision}), the revision chaining requirement, dependency on HORIZON_API_KEY and a session token, size limits per tier, and each failure mode's remedy. Nothing an agent needs to call this safely 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% and each parameter is documented, so the schema does most of the work. The description still adds real meaning: it explains the expectedRevision round-trip ('pass the revision from load or last save'), the 0-for-empty-slot case, and how to recover from a 409. It does not add much for userId/sessionToken beyond what the schema says.

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 concrete verb+resource ('Stores a player's save game as one string ... on the server, replacing the player's previous save') and immediately contrasts with the read path via horizon_load_cloud_data. The single-slot replacement semantics are explicit, so an agent can distinguish it from every sibling.

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?

Has explicit 'Use when' and 'Not for' sections that name the alternatives (horizon_load_cloud_data for reading, horizon_submit_validated/horizon_get_state for server-owned currency that players must not edit). It also names the prerequisite sign-in tools, so selection and sequencing are unambiguous.

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

Deploy Server

Other Tools