@battlegrid/mcp-server 31.2.103 → 31.2.106

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,22 @@ 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 — v110.9 (the price zone reads the channel of the bars before)
28
+
29
+ **Served values move at v110.9; no schema moves.** v110.9 is the contract on top of v110.8. Nothing you send
30
+ is refused.
31
+
32
+ ### Behaviour behind unchanged schemas
33
+
34
+ - **`zone` (`PRICE_ZONE`) classifies the price against the channel of the 20 bars before the classified one**
35
+ (`DONCHIAN_UPPER_PRIOR` / `DONCHIAN_LOWER_PRIOR`). `breakout high` and `breakdown low` now hold on a close
36
+ beyond that channel: they are the label form of `dist_donchianHiPrior gt 0` and `dist_donchianLoPrior lt 0`.
37
+ Against the same-bar channel, which includes the bar's own high and low, they could never be read. A `zone`
38
+ clause's condition levels are the two prior rails.
39
+ - **`near high` and `near low` are the outer fifth of that channel by position**: at least 0.8 of the way from
40
+ the low to the high, or at most 0.2. Before, they meant within 1% of price of an edge. The nearer edge wins,
41
+ and the band widens with the channel. A channel with an absent rail or no width reads `null`.
42
+
27
43
  ## Contract history — v110.6 (the Donchian channel as of the bar before)
28
44
 
29
45
  **Additive at v110.6: two Donchian metric keys, and level-interaction labels judged against the level in
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.103";
52
+ export declare const PACKAGE_VERSION = "31.2.106";
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.103';
55
+ export const PACKAGE_VERSION = '31.2.106';
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.103",
3
+ "version": "31.2.106",
4
4
  "description": "BattleGrid MCP server — play crypto prediction games from AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "generator": "battlegrid-app/server/scripts/export-mcp-skills.mjs",
3
- "contractVersion": "110.4.0",
3
+ "contractVersion": "110.10.0",
4
4
  "files": {
5
- "battlegrid-agent-management/SKILL.md": "34a868f8068df189ce13af47c23011aabcf6a1f07128da4d4706066628cfaa5f",
5
+ "battlegrid-agent-management/SKILL.md": "9dc151c32c3578d06e8895c6752d7a64959bff6a6681a01d62ab65e1ea1590d1",
6
6
  "battlegrid-agent-management/references/agent-stage-examples.md": "d47555906ce8dedf4c17422f8f5d60187f2d6b3c0af5d9545617a10a5bdb59a1",
7
7
  "battlegrid-arena-play/SKILL.md": "88534714cdbaa31344e1798b2b3f18836bf543f5610d118d76095d1a0dbea502",
8
8
  "battlegrid-arena-play/references/entry-stage-examples.md": "3bc62f9faca7b5529d51a9794e162333216acb23f0d7f644d5180b9cbc696fca",
@@ -10,13 +10,13 @@
10
10
  "battlegrid-radar-deployment/SKILL.md": "652325c4923d79b9c9b78026a5493bfaaedf01f600641511438a9c4bf497c0b1",
11
11
  "battlegrid-radar-deployment/references/arena-stage-examples.md": "f605aaa266a291ef1b6d02a0e8885ad5df2fea88c800be2b6625cd629cd741f2",
12
12
  "battlegrid-radar-deployment/references/radar-stage-examples.md": "1ddad4a11f021dd65234ee65cc12d7d1561fe9acfd61cb021f4352080d4cecd5",
13
- "battlegrid-strategy-authoring/SKILL.md": "098308e69093796db3bb0a6dab64031128aaffbc108117b72393595564581da1",
13
+ "battlegrid-strategy-authoring/SKILL.md": "5ce41e11d50658226230cfccb70a5c5f08e52755ef737c528d98872f239b3d4e",
14
14
  "battlegrid-strategy-authoring/references/strategy-stage-examples.md": "9822cc2bcc8975a3e436c2a960b10e03c95e6e6b4b04bc2206e0ac90688cab66",
15
15
  "battlegrid-strategy-doctor/SKILL.md": "e34e055b0cc9b355bc1adeb5d49d464eaa0756ca3f48dc89ca2ccdda94e1311f",
16
- "battlegrid-strategy-examples/SKILL.md": "375a85a38b21a356291d05af3668a57949f11ba49968a4a53f08dcc590228375",
16
+ "battlegrid-strategy-examples/SKILL.md": "597ddacdfc00955fcfd5a1afcc40b5ea72a0f658acbbebc8264afeecc46d2306",
17
17
  "battlegrid-strategy-examples/references/playbooks.md": "2309eb7e8324f563c5b1b51e05da931b37c542484135a2be749eff6ef78aa40f",
18
18
  "battlegrid-strategy-examples/references/recipes.md": "635e03d163100f6de37cda1f6cc12928d5d36aa0ea883bf44fc72f17cbf3e98e",
19
- "battlegrid-strategy-examples/references/tradingview-ports.md": "1b9440bd7180330fb77c8e245e852cbe0b5a9f7df3448233199ecd341565b2b6",
19
+ "battlegrid-strategy-examples/references/tradingview-ports.md": "9eaa926cbe8606c6a09f91007a0606042afbfdc50173a5b13ae9336d2e9e9b08",
20
20
  "battlegrid-trade-analysis/SKILL.md": "3f927b4f9796178526fa1673a2043c5f14358c39aa955de33192ea58641f18fb",
21
21
  "battlegrid-trade-proposal/SKILL.md": "e761fc6bddc0d1db79fcb90046d03a18439562c8658de726ec286830edd6369b"
22
22
  }
@@ -36,8 +36,8 @@ step named beside it before doing anything else.
36
36
  `list_strategies` and `get_strategy` are yours — the binding lookup is part of commissioning, and
37
37
  which strategy an agent is bound to is the agent's own STRATEGY_BINDING axis (step 4).
38
38
  `stage_strategy_draft`, `commit_strategy_draft`, `discard_strategy_draft`, `fork_strategy`,
39
- `archive_strategy` and `restore_strategy` are **not**, even though activating this skill makes them
40
- visible in the conversation.
39
+ `archive_strategy`, `restore_strategy`, `save_report_section` and `remove_saved_report_section` are
40
+ **not**, even though activating this skill makes them visible in the conversation.
41
41
 
42
42
  When the work is a strategy change, activate `strategy-authoring` and let its arc run — its
43
43
  evidence, spec-lock, stage-review and confirm rules bind from that point. Do not drive a strategy
@@ -103,6 +103,18 @@ anywhere; if the two ever disagree, you have created the exact ambiguity this st
103
103
  `list_strategy_categories` → `list_strategy_vocabulary` → `get_strategy_column_contract` and
104
104
  `get_strategy_section_template`.
105
105
 
106
+ The player's own saved sections are listed among the vocabulary's templates as `kind: "saved"`.
107
+ When the player names one, fetch it with `get_strategy_section_template` and place its title, note,
108
+ `benchmarkTicker` and columns in a new custom section — a copy, with no `sectionKey`.
109
+
110
+ **Keeping a section.** `save_report_section` keeps a custom section in the player's library: send its
111
+ title, note, `benchmarkTicker` and columns as `section`, dropping `kind` and `sectionKey`. Save only
112
+ when the player asks to keep one — offer it, never decide it. Before the save, say whether the
113
+ vocabulary already lists that title as `saved`; if it does, the save replaces that saved section's
114
+ note, subject and columns whole. `remove_saved_report_section` drops one by its `savedSectionId`:
115
+ before it, say the library entry goes with no other copy, and that strategies already carrying a
116
+ copy keep theirs. Each waits for the player's explicit confirming pick.
117
+
106
118
  Compose sections, columns and conditions **only** from vocabulary returned in this conversation. A
107
119
  field you remember from another strategy is not discovery.
108
120
 
@@ -351,9 +363,9 @@ the other verbs writes content.
351
363
  the restored revision. To change the content as it comes back, stage the change into the
352
364
  strategy's draft and commit it — that commit restores it, and its read says `operation: RESTORE`.
353
365
 
354
- **Your `ask_user` is the approval, and the server does not repeat it.** No strategy verb takes a
355
- confirmation flag. So never call `commit_strategy_draft`, `archive_strategy`, `restore_strategy` or
356
- `discard_strategy_draft` on a turn where the player has not made an explicit confirming pick —
366
+ **Your `ask_user` is the approval, and the server does not repeat it.** No verb here takes a
367
+ confirmation flag. So never call `commit_strategy_draft`, `archive_strategy`, `restore_strategy`,
368
+ `discard_strategy_draft`, `save_report_section` or `remove_saved_report_section` on a turn where the player has not made an explicit confirming pick —
357
369
  never because you judged the change safe. Free text typed while a confirmation is open is not
358
370
  consent: answer it, then present the same confirmation again. That covers words typed into the
359
371
  form's own answer box as well as words sent in chat — a confirming pick is one of the options you
@@ -153,6 +153,16 @@ Recipes — each one clause:
153
153
  - **Squeeze released** — `kcSqueeze exits "on"`, over a `KC_SQUEEZE` value column.
154
154
  - **New 20-bar high** — `donchianHi increased`, over a `DONCHIAN_UPPER` value column: the 20-bar
155
155
  upper channel rises exactly when the decided bar's high exceeds every high of the 20 bars before it.
156
+ - **Close above the prior 20-bar high (Donchian / Turtle breakout)** — `dist_donchianHiPrior crossesAbove 0`,
157
+ over a `DONCHIAN_UPPER_PRIOR × distance` column: Pine's `ta.crossover(close, ta.highest(high, 20)[1])`,
158
+ TRUE on the first close of a breakout run. `dist_donchianHiPrior gt 0` is Pine's
159
+ `close > ta.highest(high, 20)[1]` and holds on every close of the run. Mirror with
160
+ `dist_donchianLoPrior crossesBelow 0` / `lt 0` over `DONCHIAN_LOWER_PRIOR`.
161
+ - **Failed breakout of the prior 20-bar high** — `donchianHiPrior_lvl is "reject_from_below"`, over a
162
+ `DONCHIAN_UPPER_PRIOR × levelInteraction` column: the high pierced the prior 20-bar high and the close
163
+ came back under it. `dist_donchianHiPrior crossesBelow 0` is NOT "fell back into the channel": the rail
164
+ rises to each breakout bar's high, so it fires once on the first bar of a breakout run that does not
165
+ close above the raised rail — the run of new closing highs ended.
156
166
  - **RSI crossed above 50 within the last 3 closes** — `RSI14_now crossesAbove 50` holding
157
167
  `{ "atLeast": 1, "of": 3 }`.
158
168
 
@@ -371,9 +381,12 @@ column: it takes a timeframe reference and the Confirmed / Developing selector l
371
381
 
372
382
  **`levelInteraction` — what the bar did at a level.** It classifies the newest bar of the column as
373
383
  one of five labels: `touch_from_below`, `touch_from_above`, `reject_from_below`, `reject_from_above`,
374
- `none`. The side is where the PRIOR close stood against the PRIOR bar's level — from below when it
375
- closed at or under it — so a level that moved between the two bars is judged on the bar it stood at.
376
- From below: a bar that closes through the level is a break and reads `none`; a bar whose high
384
+ `none`. The side is where the PRIOR close stood against the level IN FORCE WHEN THE BAR OPENED — from
385
+ below when it closed at or under it. For a level computed from its own bar (a band, `VWAP`, a moving
386
+ average, `ST_LINE`, `PSAR`, the Ichimoku conversion and base lines) that is the prior bar's level, so a
387
+ level that moved between the two bars is judged on the bar it stood at; for a level whose price was fixed
388
+ before the bar (a prior-bar Donchian rail, the break memory, a swing level, the displaced Ichimoku lines, a
389
+ prior-session level or pivot) it is the bar's own level. From below: a bar that closes through the level is a break and reads `none`; a bar whose high
377
390
  reached the level and whose close came back under it is `reject_from_below`; a bar whose high came
378
391
  within the buffer of the level is `touch_from_below`. From above is the mirror on the low.
379
392
 
@@ -385,18 +398,22 @@ within the buffer of the level is `touch_from_below`. From above is the mirror o
385
398
  - **A break is a crossing, never a label.** The break of a level is `distance` over the same level
386
399
  crossing 0: `dist_bbUpper crossesAbove 0` from below, `crossesBelow 0` from above. On the strategy's
387
400
  own rung a `…_from_below` label never holds on a bar where `crossesAbove 0` holds.
388
- - **Which levels take it.** A candle-homed level — a band (`BB_UPPER`, `BB_LOWER`, `KC_UPPER`,
389
- `KC_LOWER`), `VWAP`, a moving average (`SMA20`, `EMA20`, …), `ST_LINE`, `PSAR`, the Donchian break
390
- memory (`DONCHIAN_BROKEN_HI`, `DONCHIAN_BROKEN_LO`), the
391
- Ichimoku lines, the swing levels (`SWING_FRACTAL_HIGH`, `SWING_FRACTAL_LOW`) — reads its own value at
392
- each of the two bars. A prior-session level or pivot (`PDH`,
393
- `PDL`, `PDO`, `PIVOT_P`, `PRIOR_TPO_POC`, …) has one reading for the session, used as both bars' level;
394
- a clause over it is a single read with no hold, because the session profile keeps no earlier
395
- reading. A developing-session level (`TPO_POC`, `TPO_VAH`, …) and the naked points of control move
396
- between bars with no earlier reading kept, so they are not offered it; neither are the Donchian
397
- rails (`DONCHIAN_UPPER`, `DONCHIAN_LOWER`), each the extreme of the window ending at the very bar it
398
- would classify, which a close can never pass. A price fact (`CLOSE`, `HLC3`, `MARK`) is refused: it
399
- is the price, not a level.
401
+ - **Which levels take it.**
402
+ - **Offered:** a candle-homed level — a band (`BB_UPPER`, `BB_LOWER`, `KC_UPPER`, `KC_LOWER`),
403
+ `VWAP`, a moving average (`SMA20`, `EMA20`, …), `ST_LINE`, `PSAR`, the prior-bar Donchian rails
404
+ (`DONCHIAN_UPPER_PRIOR`, `DONCHIAN_LOWER_PRIOR`), the Donchian break memory (`DONCHIAN_BROKEN_HI`,
405
+ `DONCHIAN_BROKEN_LO`), the Ichimoku lines, the swing levels (`SWING_FRACTAL_HIGH`,
406
+ `SWING_FRACTAL_LOW`) — reads its own value at each bar. A prior-session level or pivot (`PDH`, `PDL`,
407
+ `PDO`, `PIVOT_P`, `PRIOR_TPO_POC`, …) has one reading for the session; a clause over it is a single
408
+ read with no hold, because the session profile keeps no earlier reading. On `PSAR` a wick that
409
+ trades through the SAR flips it on that bar, so a rejection needs the low (high) to meet the SAR
410
+ exactly and a touch needs a buffer; its flip is `dist_PSAR crossesAbove 0` / `crossesBelow 0`.
411
+ - **Not offered:** a developing-session level (`TPO_POC`, `TPO_VAH`, …), the naked points of
412
+ control and the single prints (`TPO_SINGLE_PRINT_ABOVE`/`_BELOW`, `NAKED_SINGLE_PRINT_ABOVE`/`_BELOW`),
413
+ which move between bars with no earlier reading kept; and the same-bar Donchian rails
414
+ (`DONCHIAN_UPPER`, `DONCHIAN_LOWER`), each the extreme of the window ending at the very bar it would
415
+ classify, which a close can never pass — read `DONCHIAN_UPPER_PRIOR` / `DONCHIAN_LOWER_PRIOR`. A
416
+ price fact (`CLOSE`, `HLC3`, `MARK`) is refused: it is the price, not a level.
400
417
  - **A higher-rung level reads that rung's completed bar.** `bbUpper_htf_lvl` classifies the last
401
418
  completed regime-rung bar from its own high, low and close, never the strategy bar's price — so
402
419
  compose its break on the same rung, `dist_bbUpper_htf crossesAbove 0`.
@@ -479,8 +496,8 @@ its side replaces it.
479
496
  clause over it reads FALSE.
480
497
  - **A swing level does not remember a broken level.** Two to four bars after a break the level steps
481
498
  to the next swing, so a retest of the BROKEN level is not a swing-level read.
482
- - **The two levels take what every candle level takes** — `distance`, `spread`, `aggregate`,
483
- `trajectory`, `efficiency` and `levelInteraction` — and both rank across the board
499
+ - **The two levels take** `distance`, `spread`, `aggregate`, `trajectory`, `efficiency` and
500
+ `levelInteraction`, and both rank across the board
484
501
  (`dist_fractalHi_rank_near`: the coins closest to their own last swing high).
485
502
  - **The break is the crossing toward the level.** `dist_fractalHi crossesAbove 0` is a close through the
486
503
  last swing high and never fires when the level steps onto a new swing, because the bar that confirms
@@ -60,10 +60,15 @@ rules about the columns themselves, not about porting — they live in the skill
60
60
  - **VWAP reversion** → `dist_VWAP` band + `dist_VWAP_rank_far lte 5` for board-relative
61
61
  stretch; required `NOT [ADX_state in ["trending","extreme"]]` veto; scalp geometry +
62
62
  aggressive timeDecay (VWAP anchors daily at 00:00 UTC).
63
- - **Donchian / Turtle breakout** → `zone is "breakout high"` + `dist_donchianHi gte 0` +
64
- `RVOL gte 1.5`; turtle exits = trend preset (trail from
65
- 1R, giveback 50). Mirror with `"breakdown low"`. **Daily-breakout variant on any anchor:**
66
- pin the structure at 1d — `zone_1d is "breakout high"`, `dist_donchianHi_1d gte 0` (validated).
63
+ - **Donchian / Turtle breakout** (`close > ta.highest(high, 20)[1]`) → `dist_donchianHiPrior crossesAbove 0`
64
+ over `DONCHIAN_UPPER_PRIOR × distance` (the breakout bar; `dist_donchianHiPrior gt 0` holds on every
65
+ close of the run) + `RVOL gte 1.5`; turtle exits = trend preset (trail from 1R, giveback 50). Mirror with
66
+ `dist_donchianLoPrior crossesBelow 0`. The same-bar rail (`dist_donchianHi`) includes the breakout bar's
67
+ own high, so it can never confirm a close-based break — do not AND it in. `zone is "breakout high"` reads
68
+ the prior-bar rail: it is the label form of the `dist_donchianHiPrior gt 0` state, holds on every close of
69
+ the run, and adds nothing to the crossing; `"breakdown low"` mirrors it.
70
+ **Daily-breakout variant on any anchor:** pin the rail at 1d — `dist_donchianHiPrior_1d crossesAbove 0`
71
+ (`gt 0` for the held state).
67
72
  **Literal previous-day levels are native**: `dist_PDH gte 0` composes directly. They are TIMELESS
68
73
  and take `{rel: 'anchor'}` — see `## Header grammar` in the skill body.
69
74
  - **ICT / SMC (FVG + order blocks)** → `STRUCT_ZONES` is the native zone engine: