@battlegrid/mcp-server 31.2.49 → 31.2.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,6 +24,51 @@ Seeing package `31.x` alongside handshake `battlegrid@33.x` — the package **be
24
24
 
25
25
  **What this changes for you:** nothing about how you call anything. Upgrading the package no longer waits on a server deploy, and a server deploy no longer strands you on a package that names the wrong contract — reconnect and the announcement follows. **Contract breaking-change notes are no longer keyed to package versions**, since a contract move is no longer a release here; the v11-and-earlier notes below are kept as history, and the live vocabulary is always discovery.
26
26
 
27
+ ## Contract history — v69 (Radar multi-agent duty)
28
+
29
+ **Breaking: one input removed from two tools, three outputs reshaped.** A Radar policy carries no
30
+ timeframe. Every rule whose conditions match puts its agent on duty at once, and each rule's regime
31
+ condition is read at that agent's own regime timeframe. A coin still holds one position at a time: at
32
+ most one fire per coin per pass, offered in rule priority.
33
+
34
+ ### Rejected input — something you send is no longer accepted
35
+
36
+ - **`preview_radar_resolution`'s `SLOTS` request refuses `deploymentTimeframe`** as an unrecognized key.
37
+ Send `{ kind: "SLOTS", slots }`.
38
+ - **`stage_radar_deployment_draft` refuses the `DEPLOYMENT_TIMEFRAME` axis** the same way. Stage only
39
+ `RULES` and `DEFAULT_SLOT`.
40
+
41
+ ### Reshaped output — something you read has a new shape
42
+
43
+ - **`resolvesNow`** on `get_radar_deployment`, `list_radar_deployments` and `preview_radar_resolution` is
44
+ the coin's state (`section`, `isIdle`, `rotating`, one `reason`, the open-position owner) plus
45
+ **`onDuty`**: one row per agent on duty, in priority order. Each row carries its slot, its regime reading
46
+ at its own regime timeframe, its qualification verdict and gate, cooldown, block, `edgeSpent`, last flip
47
+ and fire, and its own `closeDecision`. The single-winner fields (`onDutyAgentId` and its display pair,
48
+ `matchedSlot*`, `regimeUsed`, and the per-agent fields the rows now carry) are gone. Render every row in
49
+ the order served, and never pick one yourself.
50
+ - **`preview_radar_resolution`'s `conditionReach`** is one flat list, each entry naming its `agentId` and
51
+ `agentDisplayName`.
52
+ - **Each deployment slot gains `agentRegimeTimeframe`**, the timeframe its rule's regime is read at.
53
+
54
+ ### Removed output — a field you read is gone
55
+
56
+ - **`deploymentTimeframe`** on a Radar policy, and the **`DEPLOYMENT_TIMEFRAME`** axis in the radar
57
+ draft's `content` and `axesMeta` on `get_radar_deployment_draft`, `list_radar_deployment_drafts` and the
58
+ stage result.
59
+
60
+ ### Wider enums — a value you may now receive
61
+
62
+ - **`closeDecision.outcome` gains `CLAIMED`**: the agent's close qualified, but a higher-priority agent
63
+ took the coin's one fire that pass. Its edge is preserved, and it fires at a later close only if it
64
+ still qualifies there.
65
+ - **`get_radar_activity` and `get_radar_activity_summary`** gain the events `ON_DUTY_JOINED` and
66
+ `ON_DUTY_LEFT` (duty is journaled per agent) and the fire disposition `EDGE_PRESERVED_COIN_CLAIMED`.
67
+ `curveDigest` describes the first agent on duty, named in `curveAgentName`.
68
+ - **`get_trade_conversation`** may carry the `close_claimed_by_radar` card.
69
+
70
+ The exported `battlegrid-radar-deployment` skill describes the v69 flow.
71
+
27
72
  ## Contract history — v68.1 (Arena regime sets)
28
73
 
29
74
  Purely additive in schema, with **one refusal behind unchanged ones.** An Arena rule's regime condition
package/dist/index.d.ts CHANGED
@@ -49,7 +49,7 @@ import { type Implementation, type Prompt, type Resource } from '@modelcontextpr
49
49
  * being asked. Move it for a change to THIS package — a proxy fix, a dependency bump, a docs
50
50
  * correction. Never move it to track the server.
51
51
  */
52
- export declare const PACKAGE_VERSION = "31.2.49";
52
+ export declare const PACKAGE_VERSION = "31.2.51";
53
53
  export declare const DEFAULT_URL = "https://mcp.battlegrid.trade/mcp";
54
54
  export interface EnvConfig {
55
55
  apiKeys: string[];
package/dist/index.js CHANGED
@@ -52,7 +52,7 @@ import { ListToolsRequestSchema, CallToolRequestSchema, ListPromptsRequestSchema
52
52
  * being asked. Move it for a change to THIS package — a proxy fix, a dependency bump, a docs
53
53
  * correction. Never move it to track the server.
54
54
  */
55
- export const PACKAGE_VERSION = '31.2.49';
55
+ export const PACKAGE_VERSION = '31.2.51';
56
56
  export const DEFAULT_URL = 'https://mcp.battlegrid.trade/mcp';
57
57
  const MAX_RETRIES = 3;
58
58
  const RETRY_DELAYS_MS = [2000, 4000, 8000];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@battlegrid/mcp-server",
3
- "version": "31.2.49",
3
+ "version": "31.2.51",
4
4
  "description": "BattleGrid MCP server — play crypto prediction games from AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "generator": "battlegrid-app/server/scripts/export-mcp-skills.mjs",
3
- "contractVersion": "68.0.0",
3
+ "contractVersion": "69.0.0",
4
4
  "files": {
5
5
  "battlegrid-agent-management/SKILL.md": "fbc602e9445d0f72353bfba23c30a364b478bd04a9cc6248418cfeec66717eb1",
6
6
  "battlegrid-arena-play/SKILL.md": "4cfaa92a8d0dcaf477b227abd774e7aa8642c185d72108dfd401be0cf8aecd7f",
7
7
  "battlegrid-market-analysis/SKILL.md": "22fde9c4eac0261c89a8056ab8b20b66fcbe1fd58447fa0ac84fd410b4d134d7",
8
- "battlegrid-radar-deployment/SKILL.md": "e2098ac23d80ab985eb93d46f6cc81c84b63dbba12b3bb3eb4cfdcef10ef3b82",
8
+ "battlegrid-radar-deployment/SKILL.md": "54d476e47dbdfb305a8d0d384c03eef6d6aaffba19552a7d2432a51b92d5418d",
9
9
  "battlegrid-strategy-authoring/SKILL.md": "95e91dd1ff36922b7ed0f5eb92c98def98fa39cce37c3d7447269aea1b5a017f",
10
10
  "battlegrid-strategy-doctor/SKILL.md": "d0b9e9e07648246d5a23b0c17183278b70b5bcbb5f472ac7da13d03e42a6c6c6",
11
11
  "battlegrid-strategy-examples/SKILL.md": "17e8cf8040813622bd5b82165c7af82e03287fee1f6aac974e0b6c584580dd27",
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: battlegrid-radar-deployment
3
- description: Deploy the player's agents to standing duty — per-coin Radar policies that fire real trades on confirmed regime flips, and per-preset Arena deployment policies that enter sessions automatically. Reads what is deployed now, stages a change into the player's draft, previews what it would actually resolve to, commits it only after the player has seen that preview, and un-deploys with the blast radius stated. Activate whenever the player wants an agent put on duty, wants to change or pause a deployment, asks what would fire right now or why nothing is firing, or wants to stop a coin or a preset being traded automatically.
3
+ description: Deploy the player's agents to standing duty — per-coin Radar policies that put every matching rule's agent on duty and fire real trades at confirmed closes, and per-preset Arena deployment policies that enter sessions automatically. Reads what is deployed now, stages a change into the player's draft, previews what it would actually resolve to, commits it only after the player has seen that preview, and un-deploys with the blast radius stated. Activate whenever the player wants an agent put on duty, wants to change or pause a deployment, asks what would fire right now or why nothing is firing, or wants to stop a coin or a preset being traded automatically.
4
4
  ---
5
5
 
6
6
  # Radar & Deployment
7
7
 
8
- You are handing an agent **standing authority**. A Radar policy fires real trades on confirmed
9
- regime flips with no further human action; a deployment policy enters real sessions the same way.
8
+ You are handing agents **standing authority**. A Radar policy puts EVERY rule whose conditions match
9
+ on duty at once — each rule's regime read at its own agent's regime timeframe — and fires real trades
10
+ at their confirmed closes with no further human action, at most one per coin per pass, offered in rule
11
+ priority; a deployment policy enters real sessions the same way.
10
12
  Nobody is watching when it happens — which is why the player has to see what a policy resolves to
11
13
  *before* it exists, not after.
12
14
 
@@ -18,7 +20,7 @@ and never describe them as one thing with two modes.
18
20
 
19
21
  1. **A write with no fresh preview.** *Cue: any `commit_radar_deployment_draft`,
20
22
  `resume_radar_deployment`, `commit_deployment_policy_draft` or `resume_deployment_policy`.* The preview is the only place the
21
- player sees which agent actually goes on duty and why. → steps 2–3.
23
+ player sees which agents actually go on duty and why. → steps 2–3.
22
24
  2. **A blind retry.** *Cue: a CONFLICT on a write.* Something moved under you — the stored policy,
23
25
  or the player's draft. Retrying overwrites an edit you never read. → step 3.
24
26
  3. **Previewing one thing and writing another.** *Cue: the player adjusts a slot, a bar, a window
@@ -69,22 +71,25 @@ If the question is *why did my radar agent not fire*, do not start from the jour
69
71
  **Radar** — the change goes into the player's draft of the coin, never straight to the policy:
70
72
 
71
73
  1. `stage_radar_deployment_draft` with `draftVersion` = the `version` you read (0 when there was
72
- no draft) and only the axes you are changing, each WHOLE: `DEPLOYMENT_TIMEFRAME`, `RULES` (the
73
- complete ordered rule list — first is highest priority) and `DEFAULT_SLOT` (the catch-all, or
74
- null for none). Staging writes nothing live and shows the change in the player's builder as a
75
- proposal. A refusal naming axes means the player changed them after your read: read again and
74
+ no draft) and only the axes you are changing, each WHOLE: `RULES` (the complete ordered rule list
75
+ — first is highest priority; every rule that matches is on duty, so priority decides only which
76
+ agent is offered the coin's one fire on a pass) and `DEFAULT_SLOT` (the catch-all, on duty only
77
+ when no rule is, or null for none). A Radar policy has **no timeframe**: each rule's regime
78
+ condition is read at its agent's own regime timeframe, which every slot reports as
79
+ `agentRegimeTimeframe`. Staging writes nothing live and shows the change in the player's builder as
80
+ a proposal. A refusal naming axes means the player changed them after your read: read again and
76
81
  propose against what they now have.
77
82
  2. `preview_radar_resolution` with `request: { kind: "DRAFT", draftVersion }` at the version staging
78
83
  returned. It composes the draft over the deployed policy **exactly as the commit will write it**.
79
84
 
80
- To try a slot set without touching the draft, preview `{ kind: "SLOTS", deploymentTimeframe, slots }` —
81
- it certifies nothing and cannot be committed.
85
+ To try a slot set without touching the draft, preview `{ kind: "SLOTS", slots }` — it certifies
86
+ nothing and cannot be committed.
82
87
 
83
88
  **Arena** — the same shape, keyed on `presetId`:
84
89
 
85
90
  1. `stage_deployment_policy_draft` with `draftVersion` = the `version` you read (0 when there was no
86
91
  draft) and only the axes you are changing, each WHOLE: `RULES` (the complete ordered rule list —
87
- first is highest priority, one regime per rule), `DEFAULT_SLOT` (the catch-all, or null for none)
92
+ first is highest priority; a rule's regime condition names a set), `DEFAULT_SLOT` (the catch-all, or null for none)
88
93
  and `REGIME_ANCHOR` (the anchor override, or null to inherit the arena's). Pausing is never staged.
89
94
  2. `preview_deployment_resolution` with `request: { kind: "DRAFT", draftVersion }` at the version
90
95
  staging returned.
@@ -96,19 +101,23 @@ Both previews run the **same resolver the live sweep runs**, so the preview is t
96
101
  an estimate. Neither writes anything and neither costs the player an LLM call — so previewing
97
102
  repeatedly while iterating is free and correct.
98
103
 
99
- Render the preview as a card and read it out: which agent goes on duty, which slot matched and at
100
- what priority, the regime and conviction used, the qualification verdict, and any typed idle or
101
- blocked reason. **Render `section` as the server sends it — never re-derive it.** A non-null reason
102
- does not mean idle (`ON_DUTY_BUT_POSITION_BLOCKED` carries a reason and is not idle), so deciding
103
- the headline yourself gets it wrong. `enabledAfterCommit` says whether the policy will play once
104
- committed — a paused policy stays paused, and a first Arena deployment always plays.
104
+ Render the preview as a card and read it out. For **Radar**: the coin's `section` and any typed idle
105
+ or blocked reason, then every row of `resolvesNow.onDuty` in the order served — each agent, the slot
106
+ and priority that put it on duty, its regime reading at its own `regimeTimeframe` with conviction, its
107
+ qualification verdict and its close clock — and, for a draft, `conditionReach`, which names each
108
+ on-duty agent's required conditions. For **Arena**: which agent goes on duty, which slot matched and at
109
+ what priority, the regime and conviction used, and the qualification verdict. **Render `section` as
110
+ the server sends it — never re-derive it, and never pick, rank or drop rows yourself.** A non-null
111
+ reason does not mean idle (`ON_DUTY_BUT_POSITION_BLOCKED` carries a reason and is not idle), so
112
+ deciding the headline yourself gets it wrong. `enabledAfterCommit` says whether the policy will play
113
+ once committed — a paused policy stays paused, and a first Arena deployment always plays.
105
114
 
106
115
  **If anything changes after a preview, re-preview.** A preview never vouches for what it did not
107
116
  resolve.
108
117
 
109
118
  ### 3. Confirm against the preview, then commit
110
119
 
111
- One confirmation whose question **references what the preview showed** — the agent it put on duty and
120
+ One confirmation whose question **references what the preview showed** — the agents it put on duty and
112
121
  the reason — and **names what the change does to the stored policy**, read from step 1:
113
122
 
114
123
  - every rule or slot the change **removes** (by agent and priority), because `RULES` and `slots` are
@@ -133,7 +142,7 @@ with the old one is refused again — only a fresh preview earns a new one.
133
142
 
134
143
  **Pause a coin's Radar** → `pause_radar_deployment({ coinId })`. No preview and no revision: stopping
135
144
  never waits on a read. The player's draft is kept. **Resume** → preview the deployed policy with
136
- `request: { kind: "COMMITTED" }`, tell the player what will go on duty again, and on their word
145
+ `request: { kind: "COMMITTED" }`, tell the player which agents will go on duty again, and on their word
137
146
  `resume_radar_deployment({ coinId, previewToken, confirm: true })` with the token that preview
138
147
  returned.
139
148
 
@@ -160,8 +169,8 @@ draft** of the coin or the arena. There is no preview here, and correctly so: th
160
169
  to preview once the policy is gone. The evidence is **the deployment's own read**, which supplies the
161
170
  `expectedRevision` the delete carries — and for Arena the `expectedPolicyId` beside it.
162
171
 
163
- State what stops, from that read: which agents were on duty or eligible, what the policy was
164
- firing on, and that the slots are not recoverable. Both tools carry a schema-level `confirm: true`.
172
+ State what stops, from that read: which agents were on duty (every row of `resolvesNow.onDuty`) or
173
+ eligible, what the policy was firing on, and that the slots are not recoverable. Both tools carry a schema-level `confirm: true`.
165
174
 
166
175
  **If the player wants to stop trading without losing the slots, that is not a delete** — it is
167
176
  `pause_radar_deployment` for Radar and `pause_deployment_policy` for Arena. Offer that
@@ -171,14 +180,18 @@ whenever the ask sounds like "pause", "stop for now", or "take it off duty for a
171
180
 
172
181
  Three reads, cheapest first. Stop as soon as the player's question is answered.
173
182
 
174
- 1. **`get_radar_deployment` → `resolvesNow`** for what is true **right now**: the section, the
175
- blocked reason and since when, the qualification block, the cooldown, the last fire, and which
176
- agent is on duty. Most "is it working?" questions end here.
183
+ 1. **`get_radar_deployment` → `resolvesNow`** for what is true **right now**: the coin's section and
184
+ reason, and one `onDuty` row per agent — its blocked reason and since when, its qualification
185
+ block, its cooldown, whether its edge is spent, its last fire and its close clock. A row whose last
186
+ close reads `CLAIMED` qualified but lost the coin's one fire that pass to a higher-priority agent;
187
+ its edge is preserved and it fires at a later close only if it still qualifies there. Most "is it
188
+ working?" questions end here.
177
189
  2. **`get_radar_activity_summary`** for everything else about "why is it quiet", in ONE call. It
178
190
  carries three parts and they answer three different questions, each on its own scope:
179
191
  - `groups` — which cause recurs and how often, over the window the response names. Quote the
180
192
  counts with that window; never sum them across calls.
181
- - `curveDigest` — how FAR the score sits from firing, over the on-duty agent's ring. This is what
193
+ - `curveDigest` — how FAR the score sits from firing, over the FIRST on-duty agent's ring (the
194
+ lowest-numbered slot on duty now, named in `curveAgentName`). This is what
182
195
  separates "lower the minimum two points and it fires" from "this strategy does not fit this
183
196
  coin": `bestUnqualifiedScorePercent` against `latestThresholdPercent`. Its `ringStartAt` /
184
197
  `ringEndAt` describe the ring, NOT the cause window above.
@@ -186,9 +199,12 @@ Three reads, cheapest first. Stop as soon as the player's question is answered.
186
199
  a pair quiet for longer returns no groups beside populated older rows. That is correct, not a
187
200
  contradiction; each row carries its own `occurredAt`.
188
201
 
189
- For about one sweep after an agent rotation the digest can name the incoming agent while the rows
190
- still show the outgoing one — the two halves are read from different stores. Say "just rotated"
191
- rather than reporting a contradiction.
202
+ The groups and rows span every on-duty agent — each row names its own — while the digest describes
203
+ the first one. For about one sweep after the on-duty set changes the digest can name the new first
204
+ agent while the rows still show the old one — the two halves are read from different stores. Say
205
+ "duty just changed" rather than reporting a contradiction. Joins and departures are journaled as
206
+ `ON_DUTY_JOINED` / `ON_DUTY_LEFT`, one row per agent, and a lost coin as
207
+ `EDGE_PRESERVED_COIN_CLAIMED`.
192
208
  3. **`get_radar_activity`** only for what step 2 cannot do: more rows than its ten, a FIRES-only
193
209
  view, paging back through history, or ONE occurrence's full margins. Rows are lean by default —
194
210
  pass `detail: 'FULL'` for the margin surface, and `includeCurve: true` only if something will