@battlegrid/mcp-server 32.0.29 → 32.0.31

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/dist/index.d.ts CHANGED
@@ -47,7 +47,7 @@ import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/cli
47
47
  * being asked. Move it for a change to THIS package — a proxy fix, a dependency bump, a docs
48
48
  * correction. Never move it to track the server.
49
49
  */
50
- export declare const PACKAGE_VERSION = "32.0.29";
50
+ export declare const PACKAGE_VERSION = "32.0.31";
51
51
  export declare const DEFAULT_URL = "https://mcp.battlegrid.trade/mcp";
52
52
  export interface EnvConfig {
53
53
  apiKeys: string[];
package/dist/index.js CHANGED
@@ -49,7 +49,7 @@ import { Client, SdkHttpError, StreamableHTTPClientTransport } from '@modelconte
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 const PACKAGE_VERSION = '32.0.29';
52
+ export const PACKAGE_VERSION = '32.0.31';
53
53
  export const DEFAULT_URL = 'https://mcp.battlegrid.trade/mcp';
54
54
  const MAX_RETRIES = 3;
55
55
  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": "32.0.29",
3
+ "version": "32.0.31",
4
4
  "description": "BattleGrid MCP server — play crypto prediction games from AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "generator": "battlegrid-app/server/scripts/export-mcp-skills.mjs",
3
- "contractVersion": "132.0.0",
3
+ "contractVersion": "135.0.0",
4
4
  "files": {
5
5
  "battlegrid-agent-management/SKILL.md": "91d1be4de1e33d54e1852c970af66ad176068fd16c30b4326e49053b7a35eb32",
6
6
  "battlegrid-agent-management/references/agent-stage-examples.md": "dffcc353d61dfc7b5bb6a2b3077fc6bf8c760a34c287cafb3b59b99306f24195",
7
7
  "battlegrid-arena-play/SKILL.md": "fdaabcd2e5ce3946ee96e553ce2e1931a822b84f91b0c94ce86a8bde0cc1d50f",
8
8
  "battlegrid-arena-play/references/entry-stage-examples.md": "0223f3743171ff213e943789d27590b2f65648398e85e10cd24938d5eb6af665",
9
9
  "battlegrid-market-analysis/SKILL.md": "fcbe98e30e1edce39bb170c224cdf20181934f62b5f3a26b293787c70eeb6229",
10
- "battlegrid-officers/SKILL.md": "3fd59ec301d1492c956fbdb4368fef61f29abd137f02f49a6172351c7a563309",
10
+ "battlegrid-officers/SKILL.md": "0e5b4fd7a11fc1b6643eecd0008dfe1528b915ee00d0a99be9aca1e3934d57f7",
11
11
  "battlegrid-officers/references/officer-stage-examples.md": "ef46ba26f4b36c9964b5bde95fdf98e5952c3786b77be5f136056cac792f0aec",
12
12
  "battlegrid-radar-deployment/SKILL.md": "42900772033d799ce8eeeea9a433d76dd54fb5b153c83951753f73859dcfc021",
13
13
  "battlegrid-radar-deployment/references/arena-stage-examples.md": "d27cfed1f4663f267c4a7ecebe4a6e65a450fc74bd14ce8987fb61af5bbf2ca5",
14
14
  "battlegrid-radar-deployment/references/radar-stage-examples.md": "13fc3f55d91d3da9754e1ed7fb27493b7b7ba4d40a6a7e8d1ee0365f90ea10de",
15
- "battlegrid-strategy-authoring/SKILL.md": "39cfa46b1f640e6800edb7e85a8f2c4b6b8786cddf71bb8244d172a44fc11d75",
15
+ "battlegrid-strategy-authoring/SKILL.md": "e2422b0e02de6d240bbab261ed1181b32d175bf877f499d7df556eca31ce5133",
16
16
  "battlegrid-strategy-authoring/references/strategy-stage-examples.md": "f10ecdc91f3660a708eee7a7bacefce2acbb46c9cf7e0ac1454bd54f839f39fd",
17
17
  "battlegrid-strategy-doctor/SKILL.md": "24c2208cf6832f1fc34e1b1c52acd8dae10f56b9860aaf27b450a62a9fb74634",
18
- "battlegrid-strategy-examples/SKILL.md": "9d18bf0e4bf85a28508e2881a4cdf77b823ec831e7cec5d82f82dc251402f41c",
19
- "battlegrid-strategy-examples/references/playbooks.md": "a9464789df2e762faf9dbd7845101564bc1847cd193f709f8ac4b6bff08f09dd",
20
- "battlegrid-strategy-examples/references/recipes.md": "806aae0b4842408f6e6ed3e108293073f4f31d1c27fa419ad57df9e1134f23e7",
21
- "battlegrid-strategy-examples/references/tradingview-ports.md": "c62ce72b741abe5a92e1dec6615f26b19a54959aa1d29542518cd9a189390b98",
18
+ "battlegrid-strategy-examples/SKILL.md": "0f652d0944b67bc8798d72779e98549ebbf5a3f183b16f1a79a549e6bb96e174",
19
+ "battlegrid-strategy-examples/references/playbooks.md": "59996c37eea08e7ce398e49304171939e55c968400a1603597d6737faf9e1771",
20
+ "battlegrid-strategy-examples/references/recipes.md": "95966649a68ec488a232b150328d94e9f80c45eff30be4da92caf305fba20fb0",
21
+ "battlegrid-strategy-examples/references/tradingview-ports.md": "de7be328c5cfada8fde700793b0c1c095a6660d9bf240cb57fe0026fcb56fea8",
22
22
  "battlegrid-trade-analysis/SKILL.md": "140d847f24e98845736d4f0c2e72b318a4d235413f72f072d2fe6d0daa5f64db",
23
23
  "battlegrid-trade-proposal/SKILL.md": "bf8f3794478cdecc989020bd775c3c91744f72b440b1a90f88f6700c9a61ca24"
24
24
  }
@@ -60,7 +60,8 @@ own model and brief, over the agents its scope covers that closed a decision or
60
60
  since its last review — and answers before any review starts:
61
61
 
62
62
  - `QUEUED` with `agentCount`: the reviews arrive in `list_officer_reviews` as each finishes;
63
- - `NOTHING_TO_REVIEW`: no agent is under review, and nothing is queued or billed;
63
+ - `NOTHING_TO_REVIEW`: no agent is under review, or the agents with something new are waiting on a proposal pushed
64
+ into the player's draft, and nothing is queued or billed;
64
65
  - `ALREADY_QUEUED`: a run of this officer is waiting or running.
65
66
 
66
67
  A run is per officer: to run two, call it for each. While one is waiting or running, `pendingRun` on `list_officers`
@@ -68,21 +69,25 @@ and `get_officer` names its state; read it again rather than calling `run_office
68
69
  `commanderAccess` from `get_account_state`, not `llmAccess`: show `deniedMessage` when it is not allowed. An
69
70
  archived officer is refused.
70
71
 
72
+ An officer waits on an agent whose review by it is pushed: the player is adopting that proposal in the draft, so the
73
+ officer reviews that agent again only once the draft is saved or discarded.
74
+
71
75
  **Never write a review.** The officer records its own; a second opinion on one of its reviews is your reading in
72
76
  the conversation, never a record.
73
77
 
74
78
  ## 3. Where each officer stands
75
79
 
76
80
  Read it, never compute it. `list_officers` serves each officer's `lastRunAt`, `nextRunAt` and `pendingRun`, and
77
- `list_officer_reviews` serves `openCountByOfficer`, each unarchived officer's open and pushed reviews. Quote them as
78
- served, through their display names.
81
+ `list_officer_reviews` serves `openCountByOfficer`, each unarchived officer's reviews awaiting the player. Quote
82
+ them as served, through their display names.
79
83
 
80
84
  ## 4. Work the inbox
81
85
 
82
86
  - **Read.** `list_officer_reviews`, by officer or by agent, newest first; `includeClosed` adds the applied,
83
87
  dismissed and superseded history. Show each review's verdict, findings, diff, impact and warnings exactly as
84
88
  served; `applyAvailable` says Apply is offered, `heldAxes` names every axis the target's draft holds and who wrote
85
- it, and `baseMoved` says the target was committed since the review.
89
+ it, and `baseMoved` says the target was committed since the review. `awaitingOwner` says the review waits on the
90
+ player; a review that proposes no change (lever `NONE`) is for their information and never waits.
86
91
  - **Apply** with `apply_officer_proposal` only after an `ask_user` confirmation naming the review, its target and
87
92
  its axis, and only on the confirming pick. A client with no `ask_user` asks in its reply and waits for the
88
93
  player's word. Apply publishes the proposal to the live target; it needs `mcp:wager`.
@@ -92,7 +97,8 @@ served, through their display names.
92
97
  - **A refusal names its recovery** through `details.nextAct`: `BASE_MOVED` — the target moved since the review,
93
98
  dismiss it for a re-review; `AXIS_HELD` and `DRAFT_NOT_EMPTY` — the target's draft already holds work, so the
94
99
  player saves or discards it, or pushes instead of applying; `TARGET_NOT_OWNED` and `PROPOSAL_INVALID` — the target
95
- no longer accepts the proposal, so dismiss it. A dismissed review is not run again until the agent closes a new
100
+ no longer accepts the proposal, so dismiss it. An action on a closed review is refused with its `reviewStatus`, and
101
+ a superseded one names its replacement as `supersededBy`: read that review instead. A dismissed review is not run again until the agent closes a new
96
102
  decision or the officer's setup changes.
97
103
 
98
104
  ## Reporting discipline
@@ -171,9 +171,13 @@ question you would otherwise guess — and a refusal you would otherwise earn:
171
171
  transform (and a chained transform) reads its series: the read shape, the window's unit, the price
172
172
  basis and what an absent bar does. `seriesHome` says where the metric's series is kept — `candle`,
173
173
  `history`, or `null` when the metric has no series, which is why a series transform does not
174
- compose on it. Window and offset carry a declared `minimum` and a served `maximum` on each metric's
175
- transform entry — the largest value whose read size fits the lookback cap, or `null` when none
176
- does. Stage at most that maximum.
174
+ compose on it. Window and offset carry a declared `minimum` and a served `maximum` on the transform
175
+ entry — the largest value whose read size fits the lookback cap, or `null` when none does. For a
176
+ chained column the outer's declaration is `chainOuterParameters[outer]` (served beside `metric`)
177
+ and its bound is `chainedOuters[outer].windowMaximum`. The window carries a `unit`
178
+ (`seriesElements`, `seriesChanges` for `efficiency`, which reads one bar more than its window, or
179
+ `priorElements` for `pctl`). Stage at most that maximum. A chained column's operands come from
180
+ `chainedOuters[outer].operands`, never from the metric's full `spreadOperands`.
177
181
  - `get_metric_construction_hints` → `rankOrderings`. Present only when rank is composable on that
178
182
  metric, already range-gated server-side — read the offered set rather than deriving one from
179
183
  the metric's native output.
@@ -38,8 +38,13 @@ Before committing a CREATE, every "no" here is a decision to state, not an omiss
38
38
  | `spread` | `<base>_<operand>_spread` | `mark_oracle_spread` |
39
39
  | `aggregate` wN | `<code>_mean<N>` | `rate_mean24` |
40
40
  | `rank` | `<code>_rank_<hi\|lo\|far\|near>` — ordinal, `lte N` = top-N | `bbWidthPct_rank_lo` |
41
- | `efficiency` wN | `<code>_er` (1 straight, ~0 chop) | `close_ltf_er` |
41
+ | `efficiency` wN | `<code>_er` (1 straight, ~0 chop) — N changes, reading N + 1 bars | `close_ltf_er` |
42
42
  | `maxShare` wN | `<code>_maxShare` | `volBase_ltf_maxShare` |
43
+ | `zscore` wN | `<code>_z<N>` (population σ; bands ±1, ±2) | `RSI14_z20` |
44
+ | `stddev` wN | `<code>_sd<N>` (population σ, the input's units) | `close_sd20` |
45
+ | `linregSlope` wN | `<code>_slope<N>` (least-squares slope per bar) | `EMA20_slope20` |
46
+ | `pctl` wN | `<code>_pctl<N>` (0–100 against the N prior bars) | `RSI14_pctl20` |
47
+ | `rollingMin` / `rollingMax` wN | `<code>_min<N>` / `<code>_max<N>` | `low_min20`, `high_max20` |
43
48
  | `classifyZone` / `classifyState` | `<code>_zone` / `<code>_state` | `RSI14_zone`, `ADX14_state` |
44
49
  | `levelInteraction` | `<code>_lvl`, `<code>_lvl_b<N>` at a buffer of N bps | `bbUpper20_lvl`, `bbUpper20_lvl_b25` |
45
50
  | any, stored `"bars": "all"` | `<code>_dev`, then the transform's suffix | `RSI14_dev_t1` |
@@ -69,7 +74,7 @@ columns only for entry timing and risk — daily inputs then move once per daily
69
74
  stops and time decay keep managing intraday. **Benchmark sections** (`benchmarkTicker: "BTC"`,
70
75
  required-nullable on every custom section) read the benchmark's values on every row — the
71
76
  standard market-leader regime gate. Platform `sectionKey`s are their literal keys
72
- (`includeMtfConfluence`). Custom `sectionKey`s are the **server's** to issue, and which of the two
77
+ (`includeHigherTimeframe`). Custom `sectionKey`s are the **server's** to issue, and which of the two
73
78
  things you do depends on the operation: on a **CREATE, omit `sectionKey` entirely** — supplying one
74
79
  is refused, since a new strategy owns no custom sections yet; on an **UPDATE or RESTORE, send back
75
80
  the keys `get_strategy` returned** for the sections you are keeping, and omit it on a section you
@@ -502,7 +507,8 @@ its side replaces it.
502
507
  clause over it reads FALSE.
503
508
  - **A swing level does not remember a broken level.** Two to four bars after a break the level steps
504
509
  to the next swing, so a retest of the BROKEN level is not a swing-level read.
505
- - **The two levels take** `distance`, `spread`, `aggregate`, `trajectory`, `efficiency` and
510
+ - **The two levels take** `distance`, `spread`, `aggregate`, `trajectory`, `efficiency`, the
511
+ statistics (`zscore`, `stddev`, `linregSlope`, `pctl`, `rollingMin`, `rollingMax`) and
506
512
  `levelInteraction`, and both rank across the board
507
513
  (`dist_fractalHi_rank_near`: the coins closest to their own last swing high).
508
514
  - **The break is the crossing toward the level.** `dist_fractalHi crossesAbove 0` is a close through the
@@ -61,13 +61,11 @@ every row reads BTC. Conditions: `BTC_RISK_ON` building block (`MAalign is "bull
61
61
  ATR floor 0.6%. PM: BE 1R; trail 1R giveback 45. Ranked cohort ≥ 40 —
62
62
  rank conditions need a cohort wider than their thresholds.
63
63
 
64
- ### 4 · HTF Trend Pullback — 1h, multi-timeframe confluence
64
+ ### 4 · HTF Trend Pullback — 1h, higher-timeframe context
65
65
 
66
- Platform `includeMtfConfluence` (`MAalign_ltf/…/_htf`, `RSI14_*_zone`, `ADX14_*_state` vocab
67
- weak/developing/trending/extreme), `includeMovingAverages` (`dist_EMA20`, …), `includeRsi`
68
- (`RSI14_now`, `RSI14_zone`). These three render `MAalign` and `RSI14_zone` twice between them, so
69
- every condition below reads a suffixed form — never bare `MAalign` or bare `RSI14_zone`, which
70
- would be ambiguous. Conditions: `HTF_UP` building block (`MAalign_htf is "bullish"` +
66
+ Platform `includeHigherTimeframe` (`MAalign_htf`, `RSI14_htf_zone`, `ADX14_htf_state` vocab
67
+ weak/developing/trending/extreme), `includeMovingAverages` (`dist_EMA20`, `MAalign`, …),
68
+ `includeRsi` (`RSI14_now`, `RSI14_zone`). Conditions: `HTF_UP` building block (`MAalign_htf is "bullish"` +
71
69
  `ADX14_htf_state in ["trending","extreme"]`); `HTF_DOWN` mirror; `TREND_PRESENT` **required**
72
70
  `ANY[ref HTF_UP, ref HTF_DOWN]` — chop blocks compose-trade entirely, before billing;
73
71
  `PULLBACK_LONG` verdict UP (ref HTF_UP + `RSI14_now between 35 55` +
@@ -30,7 +30,7 @@ rather than events all live there. This document assumes them.
30
30
  | Closed-bar-only trajectory | add `"bars": "closed"` to any trajectory | same, drawn from closed bars |
31
31
  | Extension from trend | `{ "metric": "SMA50", "transformId": "distance", "timeframe": { "rel": "anchor" } }` | `dist_SMA50` (signed %) |
32
32
  | Funding paid over a day | `{ "metric": "FUNDING_RATE", "transformId": "aggregate", "timeframe": { "rel": "anchor" }, "window": 24 }` | `rate_mean24` |
33
- | Chop filter on the entry rung | `{ "metric": "CLOSE", "transformId": "efficiency", "timeframe": { "rel": "lower" }, "window": 5, "bars": "closed" }` | `close_ltf_er` (≥0.6 directional) |
33
+ | Chop filter on the entry rung | `{ "metric": "CLOSE", "transformId": "efficiency", "timeframe": { "rel": "lower" }, "window": 4, "bars": "closed" }` | `close_ltf_er` (≥0.6 directional; 4 changes, the last 5 closes) |
34
34
  | One-bar volume concentration | `{ "metric": "VOLUME", "transformId": "maxShare", "timeframe": { "rel": "lower" }, "window": 4, "bars": "closed" }` | `volBase_ltf_maxShare` |
35
35
  | Room to structure | `{ "metric": "STRUCT_ZONES", "transformId": "nearestZoneDist", "timeframe": { "rel": "regime" }, "side": "resistance" }` | `zones_htf_resist_dist` |
36
36
  | Last **closed** daily read | `{ "metric": "RSI14", "transformId": "value", "timeframe": { "abs": "1d" }, "bars": "closed" }` | `RSI14_1d` — the newest completed daily bar |
@@ -15,6 +15,7 @@ engine) and names its substitutions where the catalog lacks a primitive.
15
15
  - Pivot highs / lows, HH-HL structure and break of structure
16
16
  - Chaikin Money Flow
17
17
  - Now native, formerly substituted
18
+ - Statistics over a series' own history
18
19
 
19
20
  ## TradingView ports — familiar processes, studio vocabulary
20
21
 
@@ -115,3 +116,20 @@ rules about the columns themselves, not about porting — they live in the skill
115
116
  `PRIOR_SWING_FRACTAL_HIGH`/`PRIOR_SWING_FRACTAL_LOW` and their ages
116
117
  `SWING_FRACTAL_HIGH_BARS_AGO`/`SWING_FRACTAL_LOW_BARS_AGO`), and Chaikin Money Flow (`CMF20`). Port
117
118
  these directly — do not offer a substitute for a primitive the catalog serves.
119
+ - **Statistics over a series' own history** — the windowed transforms port the common Pine idioms
120
+ one for one, over any metric with a series and over a `distance` or `spread`:
121
+ - the `er` function of the common Pine libraries, `math.abs(x - x[n]) / math.sum(math.abs(x - x[1]), n)`,
122
+ is `x × efficiency` at window `n` — the window counts CHANGES, so `er(close, 10)` is window 10 and
123
+ reads 11 bars;
124
+ - the z-score idiom `(x - ta.sma(x, n)) / ta.stdev(x, n)` is `x × zscore` at window `n`
125
+ (`RSI14_z20`), population σ as `ta.stdev` defaults to, banded at ±1 and ±2;
126
+ - `ta.stdev(x, n)` is `x × stddev` (`close_sd20`, in the input's own units);
127
+ - `ta.percentrank(x, n)` is `x × pctl` at window `n` — the `n` bars BEFORE the newest, ties at or below;
128
+ - `ta.highest(x, n)` / `ta.lowest(x, n)` are `x × rollingMax` / `x × rollingMin` (`high_max20`
129
+ is `DONCHIAN_UPPER`'s same-bar rail);
130
+ - a linear-regression slope over `n` bars (TA-Lib's `LINEARREG_SLOPE`) is `x × linregSlope`, the
131
+ least-squares slope per bar — not Pine's `ta.linreg(x, n, 0) - ta.linreg(x, n, 1)`, which differs
132
+ two fits.
133
+
134
+ Each reads null where its newest or oldest bar holds no value, or where fewer bars exist than the
135
+ window reads.