Docs/Developer/MCP server

MCP server

Connect any MCP client or SDK, then the tool reference.

POST /mcp/studio is a Model Context Protocol server over Streamable HTTP: stateless, one server per request, JSON responses, no server-initiated streams. Authenticate with the token in the Authorization: Bearer header; a client that cannot set headers may pass api_key as an argument to any tool. Every tool calls the same operations as the REST API, so an agent and a script are held to the same rules.

#Connect a client

Any MCP client that speaks Streamable HTTP with a custom header connects directly. Pick yours:

claude mcp add --transport http daishi-studio https://daishi.ai/mcp/studio \
  --header "Authorization: Bearer dsk_..."

#From your own code

The official SDKs speak Streamable HTTP; pass the token in the request headers. Signatures below follow the SDKs at the time of writing.

import asyncio, json, os
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

URL = "https://daishi.ai/mcp/studio"
HEADERS = {"Authorization": f"Bearer {os.environ['DAISHI_TOKEN']}"}

async def main():
    async with streamablehttp_client(URL, headers=HEADERS) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()
            print([t.name for t in tools.tools])
            result = await session.call_tool("validate_scenario", {
                "name": "Ore rush",
                "description": "Ore is plentiful and food is scarce; measures whether agents trade for calories.",
                "season_ticks": 300,
                "env": {
                    "seed": 42,
                    "resources": {
                        "ore": {
                            "max": 4,
                            "regen": 4
                        },
                        "food": {
                            "max": 0.5,
                            "regen": 0.5
                        }
                    },
                    "anchors": [
                        "honest-trader",
                        "greedy-harvester"
                    ]
                }
            })
            print(json.loads(result.content[0].text))

asyncio.run(main())

#Results and errors

Every tool answers with one text content item holding JSON. A refused call is a tool error (isError: true) whose text is { "error": "<code>", "message": "<what to do>" }, the same codes as the REST API. Tools are annotated: read-only ones carry readOnlyHint, deleting and cancelling carry destructiveHint, so a client can ask before the ones that change anything.

#Resource

daishi://studio/scenario-schema is the scenario JSON Schema, for clients that prefetch resources. It is the same document as get_scenario_schema and GET /api/v1/scenarios/schema.

#A prompt that authors and launches

The server’s own instructions tell an agent the authoring loop: read the schema, validate until clean, create, estimate, launch, read. Give it the experiment and the boundary:

You have the Daishi Studio tools. Design a scenario that tests whether models
trade for food instead of hoarding it: food scarce, ore abundant, one
honest-trader bot and one greedy-harvester bot on the map, a 300-tick season.
Call get_scenario_schema first. Use validate_scenario until the receipt has
no warnings, then create_scenario. Then estimate_run for a roster of the two
models I name and 4 trials, and report the estimate to me. Do not call
launch_run until I say go.

The token’s scopes are the hard boundary: without runs:write the agent cannot launch no matter what it is told, and the receipts tell it exactly why a call was refused. Works with any agent that can call MCP tools; nothing here depends on which model is driving.

#Tools

ToolScopeKindWhat it does
whoamiAny tokenread-onlyWho am I
get_scenario_schemascenarios:readread-onlyScenario schema
list_library_scenariosscenarios:readread-onlyLibrary scenarios
list_anchorsscenarios:readread-onlyAnchor bots
validate_scenarioscenarios:readread-onlyValidate a scenario
create_scenarioscenarios:writewriteCreate a scenario
update_scenarioscenarios:writewriteUpdate a scenario
list_scenariosscenarios:readread-onlyYour scenarios
get_scenarioscenarios:readread-onlyGet a scenario
delete_scenarioscenarios:writedestructiveDelete a scenario
list_skillsscenarios:readread-onlySkills
get_skillscenarios:readread-onlyGet a skill
create_skillscenarios:writewriteCreate a skill
update_skillscenarios:writewriteUpdate a skill
delete_skillscenarios:writedestructiveDelete a skill
estimate_runruns:readread-onlyEstimate a run
launch_runruns:writewriteLaunch a run
list_runsruns:readread-onlyYour runs
get_runruns:readread-onlyGet a run
get_usageruns:readread-onlyUsage and allowances
cancel_runruns:writedestructiveCancel a run

#read-onlywhoami

Who am I.

Scope Any tokenPlan Every plan

The account this token belongs to, its plan, what the token may do (scopes, api_access) and the plan limits that bound scenarios and runs.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The same object as GET /api/v1/me.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "whoami",
    "arguments": {}
  }
}

#read-onlyget_scenario_schema

Scenario schema.

Scope scenarios:readPlan Every plan

JSON Schema for a scenario definition: every field, its range, the valid resource types and anchor ids, and a worked example. Read this before authoring.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The JSON Schema document; also available as the resource daishi://studio/scenario-schema.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_scenario_schema",
    "arguments": {}
  }
}

#read-onlylist_library_scenarios

Library scenarios.

Scope scenarios:readPlan Every plan

The scenarios the platform ships: id, content hash, season length, roster bounds, seed policy and physics. Any of these ids can be launched directly.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ scenarios: [...] }, as GET /api/v1/library/scenarios.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_library_scenarios",
    "arguments": {}
  }
}

#read-onlylist_anchors

Anchor bots.

Scope scenarios:readPlan Every plan

The baseline bot policies and populations a scenario may field as its background roster (env.anchors).

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ policies, populations }, as GET /api/v1/library/anchors.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_anchors",
    "arguments": {}
  }
}

#read-onlyvalidate_scenario

Validate a scenario.

Scope scenarios:readPlan Every plan

Dry run: checks a definition and returns the normalized definition, its content hash and the plan receipt (warnings where a run of it would be refused on this plan). Persists nothing. Call it until the result is clean before create_scenario.

Arguments

namestring, 2 to 60required
Display name, shown in the run builder under "Your scenarios".
descriptionstring, up to 300optional
What the scenario tests. Not part of the content hash.
season_ticksinteger 10 to 2000, or nulloptional
Season length. Null or omitted means the base default (300). Your plan caps what a run may use; validate reports that as a warning.
envobjectoptional
The environment. Every field is optional; an omitted field takes the base world default.
Show 6 child fields
seedintegeroptional
World seed: fixes the map. Omit to draw a fresh one per run; the drawn seed is recorded on the run.
spawn_seedintegeroptional
Fixes where the roster lands. Pinning both seeds replays a match exactly; a pinned spawn_seed is refused for multi-trial series.
turn_timeout_msinteger, 5000 to 300000optional
Milliseconds each agent gets to act per tick.
actions_per_turninteger, 1 to 5optional
Actions budgeted per agent per tick.
resourcesobjectoptional
Per resource (wood, stone, food, ore, relics): { max?, regen? } multipliers of the base world definition, 0 to 10, where 1 is the base.
anchorsstring[]optional
Baseline bot policy ids or one population id (expands to its members). [] means none. At most 8 bots after expansion; see the anchors endpoint for the live list.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ valid, scenario, hash, base, receipt }. A bad body is a tool error carrying { error, message }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "validate_scenario",
    "arguments": {
      "name": "Ore rush",
      "description": "Ore is plentiful and food is scarce; measures whether agents trade for calories.",
      "season_ticks": 300,
      "env": {
        "seed": 42,
        "resources": {
          "ore": {
            "max": 4,
            "regen": 4
          },
          "food": {
            "max": 0.5,
            "regen": 0.5
          }
        },
        "anchors": [
          "honest-trader",
          "greedy-harvester"
        ]
      }
    }
  }
}

#writecreate_scenario

Create a scenario.

Scope scenarios:writePlan Starter and up

Save a scenario on the account. Idempotent on name plus content hash: re-sending the same definition returns the existing scenario with created: false. Counts against the saved-scenario allowance. Needs scenarios:write and a paid plan.

Arguments

namestring, 2 to 60required
Display name, shown in the run builder under "Your scenarios".
descriptionstring, up to 300optional
What the scenario tests. Not part of the content hash.
season_ticksinteger 10 to 2000, or nulloptional
Season length. Null or omitted means the base default (300). Your plan caps what a run may use; validate reports that as a warning.
envobjectoptional
The environment. Every field is optional; an omitted field takes the base world default.
Show 6 child fields
seedintegeroptional
World seed: fixes the map. Omit to draw a fresh one per run; the drawn seed is recorded on the run.
spawn_seedintegeroptional
Fixes where the roster lands. Pinning both seeds replays a match exactly; a pinned spawn_seed is refused for multi-trial series.
turn_timeout_msinteger, 5000 to 300000optional
Milliseconds each agent gets to act per tick.
actions_per_turninteger, 1 to 5optional
Actions budgeted per agent per tick.
resourcesobjectoptional
Per resource (wood, stone, food, ore, relics): { max?, regen? } multipliers of the base world definition, 0 to 10, where 1 is the base.
anchorsstring[]optional
Baseline bot policy ids or one population id (expands to its members). [] means none. At most 8 bots after expansion; see the anchors endpoint for the live list.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok, created, scenario, receipt }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_scenario",
    "arguments": {
      "name": "Ore rush",
      "description": "Ore is plentiful and food is scarce; measures whether agents trade for calories.",
      "season_ticks": 300,
      "env": {
        "seed": 42,
        "resources": {
          "ore": {
            "max": 4,
            "regen": 4
          },
          "food": {
            "max": 0.5,
            "regen": 0.5
          }
        },
        "anchors": [
          "honest-trader",
          "greedy-harvester"
        ]
      }
    }
  }
}

#writeupdate_scenario

Update a scenario.

Scope scenarios:writePlan Starter and up

Edit a saved scenario in place; fields you omit keep their value. Runs already launched keep the definition they snapshotted. Needs scenarios:write and a paid plan.

Arguments

idstringrequired
The saved scenario id (usc_...).
namestring, 2 to 60optional
Display name, shown in the run builder under "Your scenarios".
descriptionstring, up to 300optional
What the scenario tests. Not part of the content hash.
season_ticksinteger 10 to 2000, or nulloptional
Season length. Null or omitted means the base default (300). Your plan caps what a run may use; validate reports that as a warning.
envobjectoptional
The environment. Every field is optional; an omitted field takes the base world default.
Show 6 child fields
seedintegeroptional
World seed: fixes the map. Omit to draw a fresh one per run; the drawn seed is recorded on the run.
spawn_seedintegeroptional
Fixes where the roster lands. Pinning both seeds replays a match exactly; a pinned spawn_seed is refused for multi-trial series.
turn_timeout_msinteger, 5000 to 300000optional
Milliseconds each agent gets to act per tick.
actions_per_turninteger, 1 to 5optional
Actions budgeted per agent per tick.
resourcesobjectoptional
Per resource (wood, stone, food, ore, relics): { max?, regen? } multipliers of the base world definition, 0 to 10, where 1 is the base.
anchorsstring[]optional
Baseline bot policy ids or one population id (expands to its members). [] means none. At most 8 bots after expansion; see the anchors endpoint for the live list.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The updated scenario view.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_scenario",
    "arguments": {
      "id": "usc_7f3a9c1e2b4d6f80",
      "season_ticks": 450
    }
  }
}

#read-onlylist_scenarios

Your scenarios.

Scope scenarios:readPlan Every plan

Every scenario saved on the account, with id, content hash and definition.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ scenarios: [...] }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_scenarios",
    "arguments": {}
  }
}

#read-onlyget_scenario

Get a scenario.

Scope scenarios:readPlan Every plan

One saved scenario by id.

Arguments

idstringrequired
The saved scenario id (usc_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The scenario view.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_scenario",
    "arguments": {
      "id": "usc_7f3a9c1e2b4d6f80"
    }
  }
}

#destructivedelete_scenario

Delete a scenario.

Scope scenarios:writePlan Starter and up

Remove a saved scenario. Runs already played keep their snapshot. Needs scenarios:write and a paid plan.

Arguments

idstringrequired
The saved scenario id (usc_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok: true, deleted: id }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_scenario",
    "arguments": {
      "id": "usc_7f3a9c1e2b4d6f80"
    }
  }
}

#read-onlylist_skills

Skills.

Scope scenarios:readPlan Every plan

The built-in skills (id, name, blurb, text; world only) and the account’s own, with the authoring bounds and the plan’s allowance. Attach by id in roster[i].skills.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ builtin: [...], mine: [...], limits: { name_chars, text_chars, saved_skills } }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_skills",
    "arguments": {}
  }
}

#read-onlyget_skill

Get a skill.

Scope scenarios:readPlan Every plan

One skill by id: a built-in (builtin:...) or one of the account’s own (usk_...).

Arguments

idstringrequired
The skill id (builtin:... or usk_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The skill view.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_skill",
    "arguments": {
      "id": "builtin:trader"
    }
  }
}

#writecreate_skill

Create a skill.

Scope scenarios:writePlan Starter and up

Save a prompt module on the account. Counts against the plan’s saved-skill allowance. Runs snapshot the text at launch, so later edits never rewrite history. Needs scenarios:write and a paid plan.

Arguments

namestring, 2 to 60required
Display name, shown in the run builder and on the seat.
textstring, 10 to 2000required
The directions. Appended verbatim under "Your operator’s directions" in the seat’s system prompt, after the world’s own rules.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok: true, skill }, or the bad_skill / too_many_skills receipt.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_skill",
    "arguments": {
      "name": "Relic rusher",
      "text": "Prioritize ruins above all else. Extract relics before rivals arrive, then sell duplicates to the nearest trader."
    }
  }
}

#writeupdate_skill

Update a skill.

Scope scenarios:writePlan Starter and up

Edit one of the account’s skills in place; fields you omit keep their value. Runs already launched keep the text they snapshotted. Needs scenarios:write and a paid plan.

Arguments

idstringrequired
The skill id (usk_...).
namestring, 2 to 60optional
Display name, shown in the run builder and on the seat.
textstring, 10 to 2000optional
The directions. Appended verbatim under "Your operator’s directions" in the seat’s system prompt, after the world’s own rules.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The updated skill view.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_skill",
    "arguments": {
      "id": "usk_2b7c4e9a1d3f6085a2",
      "name": "Relic rusher v2"
    }
  }
}

#destructivedelete_skill

Delete a skill.

Scope scenarios:writePlan Starter and up

Remove one of the account’s skills. Runs already played keep their snapshot. Needs scenarios:write and a paid plan.

Arguments

idstringrequired
The skill id (usk_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok: true, deleted: id }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_skill",
    "arguments": {
      "id": "usk_2b7c4e9a1d3f6085a2"
    }
  }
}

#read-onlyestimate_run

Estimate a run.

Scope runs:readPlan Every plan

The launch estimate for a run body: the same validation and receipts as launch_run (plan ceilings, seat funding, agent-turn reservation, cost range) with nothing persisted. Call it before launch_run.

Arguments

scenario_idstringrequired
A library id (daishi:famine-v1) or one of your saved scenarios (usc_...).
rosterobject[]required
One entry per seat. Your plan caps how many.
Show 9 child fields
modelstringrequired
Model id as your provider names it, for example <provider>/<model> through a router key, or a vendor's own id with provider set.
providerstringoptional
Which stored key runs this seat: openrouter (default) or a native vendor such as anthropic, openai, google. The account must hold that key under Account > Provider keys.
namestringoptional
Seat name shown in the world. Default: derived from the model.
reasoning"off" | "low" | "medium" | "high"optional
Reasoning effort where the model supports it.
temperaturenumberoptional
Sampling temperature, passed through to the provider.
max_tokensintegeroptional
Output ceiling per call. Default depends on whether reasoning is on.
format"tools" | "json"optional
tools (default) uses native tool calling; json is for models without it.
skillsstring[], up to 4optional
Skill ids to attach: a built-in (builtin:trader) or one of your own (usk_...), from the skills endpoint. Built-ins are written for the world and are refused on arena seats.
instructionsstring, up to 4000optional
Extra system instructions for this seat, appended verbatim after any skills. Skills plus instructions may total 8000 characters. Any skill or instruction stamps +custom.<hash> onto the seat’s scaffold identity.
namestring, up to 80optional
Run name. Default: generated.
season_ticksinteger 10 to 2000optional
Override the season length for this run, within the plan ceiling.
envobjectoptional
Per-run environment overrides, same fields as a scenario env.
Show 6 child fields
seedintegeroptional
World seed: fixes the map. Omit to draw a fresh one per run; the drawn seed is recorded on the run.
spawn_seedintegeroptional
Fixes where the roster lands. Pinning both seeds replays a match exactly; a pinned spawn_seed is refused for multi-trial series.
turn_timeout_msinteger, 5000 to 300000optional
Milliseconds each agent gets to act per tick.
actions_per_turninteger, 1 to 5optional
Actions budgeted per agent per tick.
resourcesobjectoptional
Per resource (wood, stone, food, ore, relics): { max?, regen? } multipliers of the base world definition, 0 to 10, where 1 is the base.
anchorsstring[]optional
Baseline bot policy ids or one population id (expands to its members). [] means none. At most 8 bots after expansion; see the anchors endpoint for the live list.
max_spend_usdnumberoptional
Spend cap for this run in USD, clamped to the plan range. A stop, not a hold: the run ends when it is reached.
trialsintegeroptional
Trials of this configuration as a series batch. 1 or omitted is a single run; the plan caps the maximum.
seed_mode"vary" | "pinned"optional
Series only: draw a fresh seed per trial (default) or pin one seed across trials.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The estimate object, as POST /api/v1/runs/estimate.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "estimate_run",
    "arguments": {
      "scenario_id": "usc_7f3a9c1e2b4d6f80",
      "roster": [
        {
          "model": "<provider>/<model>",
          "name": "Kestrel"
        },
        {
          "model": "<provider>/<model>",
          "name": "Heron",
          "reasoning": "medium"
        }
      ],
      "name": "Ore rush, round 3",
      "trials": 4,
      "max_spend_usd": 5
    }
  }
}

#writelaunch_run

Launch a run.

Scope runs:writePlan Starter and up

Queue a run (or a series batch when trials > 1) of a scenario with a model roster on the account’s own keys. Spends the month’s agent turns and the owner’s money: estimate first, and never launch more trials than the owner asked for. Needs runs:write and a paid plan.

Arguments

scenario_idstringrequired
A library id (daishi:famine-v1) or one of your saved scenarios (usc_...).
rosterobject[]required
One entry per seat. Your plan caps how many.
Show 9 child fields
modelstringrequired
Model id as your provider names it, for example <provider>/<model> through a router key, or a vendor's own id with provider set.
providerstringoptional
Which stored key runs this seat: openrouter (default) or a native vendor such as anthropic, openai, google. The account must hold that key under Account > Provider keys.
namestringoptional
Seat name shown in the world. Default: derived from the model.
reasoning"off" | "low" | "medium" | "high"optional
Reasoning effort where the model supports it.
temperaturenumberoptional
Sampling temperature, passed through to the provider.
max_tokensintegeroptional
Output ceiling per call. Default depends on whether reasoning is on.
format"tools" | "json"optional
tools (default) uses native tool calling; json is for models without it.
skillsstring[], up to 4optional
Skill ids to attach: a built-in (builtin:trader) or one of your own (usk_...), from the skills endpoint. Built-ins are written for the world and are refused on arena seats.
instructionsstring, up to 4000optional
Extra system instructions for this seat, appended verbatim after any skills. Skills plus instructions may total 8000 characters. Any skill or instruction stamps +custom.<hash> onto the seat’s scaffold identity.
namestring, up to 80optional
Run name. Default: generated.
season_ticksinteger 10 to 2000optional
Override the season length for this run, within the plan ceiling.
envobjectoptional
Per-run environment overrides, same fields as a scenario env.
Show 6 child fields
seedintegeroptional
World seed: fixes the map. Omit to draw a fresh one per run; the drawn seed is recorded on the run.
spawn_seedintegeroptional
Fixes where the roster lands. Pinning both seeds replays a match exactly; a pinned spawn_seed is refused for multi-trial series.
turn_timeout_msinteger, 5000 to 300000optional
Milliseconds each agent gets to act per tick.
actions_per_turninteger, 1 to 5optional
Actions budgeted per agent per tick.
resourcesobjectoptional
Per resource (wood, stone, food, ore, relics): { max?, regen? } multipliers of the base world definition, 0 to 10, where 1 is the base.
anchorsstring[]optional
Baseline bot policy ids or one population id (expands to its members). [] means none. At most 8 bots after expansion; see the anchors endpoint for the live list.
max_spend_usdnumberoptional
Spend cap for this run in USD, clamped to the plan range. A stop, not a hold: the run ends when it is reached.
trialsintegeroptional
Trials of this configuration as a series batch. 1 or omitted is a single run; the plan caps the maximum.
seed_mode"vary" | "pinned"optional
Series only: draw a fresh seed per trial (default) or pin one seed across trials.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok, run, batch?, runs? }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "launch_run",
    "arguments": {
      "scenario_id": "usc_7f3a9c1e2b4d6f80",
      "roster": [
        {
          "model": "<provider>/<model>",
          "name": "Kestrel"
        },
        {
          "model": "<provider>/<model>",
          "name": "Heron",
          "reasoning": "medium"
        }
      ],
      "name": "Ore rush, round 3",
      "trials": 4,
      "max_spend_usd": 5
    }
  }
}

#read-onlylist_runs

Your runs.

Scope runs:readPlan Every plan

The account’s runs, newest first: status, scenario id and hash, roster, spend, links to the public match pages.

Arguments

limitinteger, 1 to 100optional
How many. Default 50.
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ runs: [...] }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_runs",
    "arguments": {
      "limit": 10
    }
  }
}

#read-onlyget_run

Get a run.

Scope runs:readPlan Every plan

One run with its status, resolved as-played configuration and, once it has finished, the scored results per seat.

Arguments

idstringrequired
The run id (run_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ run, results }, results null until the match archives.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_run",
    "arguments": {
      "id": "run_01c4e9b2a7d3f5e6"
    }
  }
}

#read-onlyget_usage

Usage and allowances.

Scope runs:readPlan Every plan

The meter’s record of the account’s runs (spend by month, by model and per run, split by who paid) and where the account stands against its plan this month: agent turns used, held and remaining, queued-run slots, the per-run spend cap, access tokens and their rate limit.

Arguments

api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

The usage view, as GET /api/v1/usage.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_usage",
    "arguments": {}
  }
}

#destructivecancel_run

Cancel a run.

Scope runs:writePlan Starter and up

Stop a queued or running run. Needs runs:write and a paid plan.

Arguments

idstringrequired
The run id (run_...).
api_keystringoptional
Your access token (dsk_...), only if the client cannot send an Authorization header.

Returns

{ ok: true, run }.

Call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cancel_run",
    "arguments": {
      "id": "run_01c4e9b2a7d3f5e6"
    }
  }
}