Skip to main content
Glama

Set Player Profile

horizon_set_profile
DestructiveIdempotent

Replaces a player's entire profile to set avatar, frame, and up to three badges. Use after the player confirms a new look; pass current values for slots to keep.

Instructions

Sets a player's avatar, frame and displayed badges. This REPLACES THE WHOLE PROFILE: an omitted, null or empty slot is cleared. Use when: the player confirms a new look. Pass the current values from horizon_get_profile for the slots that should stay. Not for: reading the profile or the catalog (use horizon_get_profile). Requires: userId and the player's session: sign in with horizon_signin_email or horizon_signin_anonymous and pass its accessToken as sessionToken. Every ID must be in the API key's catalog, have the type of its slot and be free or unlocked for the player; at most 3 distinct badges. Side effects: overwrites all three slots; the same call again changes nothing more. The profile shows up in leaderboard entries. Returns: the same body as horizon_get_profile after the change. Errors: The error result names the stable code. 400 INVALID_BADGES, INVALID_COSMETIC_ID, COSMETIC_NOT_FOUND or COSMETIC_TYPE_MISMATCH: pick IDs of the right type from horizon_get_profile. 403 COSMETIC_LOCKED: the cosmetic is locked and the player has not unlocked it (unlocks come from gift code grants). 401 SESSION_REQUIRED for a missing or expired session: sign in again. 403 SESSION_FORBIDDEN for a session of another user: pass the userId that signed in. 404 PLAYER_NOT_FOUND for an unknown userId. 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

TableJSON Schema
NameRequiredDescriptionDefault
badgesNoBadge cosmetic IDs of type badge to display (0 to 3, distinct, order kept, each 1 to 32 characters: a-z, 0-9, ., _ and -). Omit or [] clears all badges.
userIdYesPlayer user ID (UUID) from horizon_signup_* or horizon_signin_*
frameIdNoCosmetic ID of type frame from the catalog (for example "frame.gold"). Omit, null or "" clears the frame slot.
avatarIdNoCosmetic ID of type avatar from the catalog (for example "avatar.gold"). Omit, null or "" clears the avatar slot.
sessionTokenYesaccessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv1.6.0

TDQS

A4.8/5.0
Behavior5/5

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

Although annotations already declare destructive=true and idempotent=true, the description goes well beyond them: it explains that omitted/null/empty clears slots, that the call replaces all three slots at once, the catalog/type/unlock constraints, the 3-badge cap, the leaderboard visibility, and a full error taxonomy (400 INVALID_BADGES, 403 COSMETIC_LOCKED, 401/403 SESSION_*, 404, 429 rate limit with retry advice). This is unusually rich disclosure and does not contradict the annotations.

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?

Long but dense and well-sectioned into Use when / Not for / Requires / Side effects / Returns / Errors, with the destructive replace-all semantics front-loaded. Every sentence carries actionable content, though the error-code enumeration makes it heavier than strictly necessary.

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?

A mutation tool with no output schema needs to explain side effects, auth, and failure modes; it does all three, including what is returned (the get_profile body) and the isError contract. Nothing an agent needs to call this 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: pass current values from horizon_get_profile for slots that should stay, every ID must belong to the API key's catalog with the type of its slot and be free or unlocked, and at most 3 distinct badges. These constraints are semantic rules not expressible in the JSON 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?

Opens with a specific verb and resource ("Sets a player's avatar, frame and displayed badges") and immediately names the sibling it is not (horizon_get_profile for reading). An agent can distinguish it from the ~30 siblings without opening the schema.

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?

Explicit "Use when: the player confirms a new look" plus a concrete instruction to seed unchanged slots from horizon_get_profile, and a "Not for:" clause naming the alternative. Both the when and the when-not are stated.

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