@battlegrid/mcp-server 31.1.0 → 31.2.0
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 +223 -2
- package/dist/index.d.ts +60 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +183 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/battlegrid-strategy-studio/SKILL.md +57 -4
- package/skills/battlegrid-strategy-studio/references/recipes.md +42 -1
- package/skills/battlegrid-strategy-studio/references/tradingview-ports.md +38 -17
package/README.md
CHANGED
|
@@ -24,6 +24,195 @@ 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 — v37 → v48.1
|
|
28
|
+
|
|
29
|
+
Eleven majors reached authors while this section stopped at v36. That gap is the mechanism, not an
|
|
30
|
+
oversight: since v31 a contract move needs no release here, so nothing forced a note to be written —
|
|
31
|
+
and the documentation ships inside the tarball, so a note written but unpublished reaches nobody.
|
|
32
|
+
Both halves are now closed by a rule keyed to the *served* contract rather than to a release of this
|
|
33
|
+
package.
|
|
34
|
+
|
|
35
|
+
### Changed meaning, unchanged shape
|
|
36
|
+
|
|
37
|
+
- **Three tools serve different values for identical input** (47.3.0, `derive-scan-fetch-from-report`).
|
|
38
|
+
The radar scan leg now derives its timeframe fetch from the strategy's **report** rather than the
|
|
39
|
+
on-duty agent's three perception rungs, so a required condition addressing an absolute timeframe
|
|
40
|
+
outside those rungs — never evaluated at scan before — now is. No field moves; the values do:
|
|
41
|
+
|
|
42
|
+
| Tool | What moves |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `preview_radar_resolution` | `conditionReach[].reachReason` goes `AGENT_TIMEFRAME` → `null` |
|
|
45
|
+
| `get_radar_activity` | `scanReachReason` moves the same way, **on new rows only** — rows already written keep what they were recorded with |
|
|
46
|
+
| `get_agent_coin_qualification` | `reachReason` moves the same way; its sibling `verdict` moves `UNMEASURABLE` → a decided verdict |
|
|
47
|
+
|
|
48
|
+
**Read the last one carefully:** a client treating `UNMEASURABLE` as "this gate is switched off"
|
|
49
|
+
will now see that gate **BLOCK**. `AGENT_TIMEFRAME` keeps its member and narrows to the one cause
|
|
50
|
+
no fetch can discharge. Nothing in the payload tells you this moved.
|
|
51
|
+
|
|
52
|
+
### Rejected input — something you author is no longer accepted
|
|
53
|
+
|
|
54
|
+
- **A benchmark-bound section no longer accepts crowd metrics or rank transforms** (49.0.0,
|
|
55
|
+
`fix-benchmark-legality-save-path`). On a custom section carrying a non-null `benchmarkTicker`, a
|
|
56
|
+
column whose metric is enrichment-stage (the `CROWD_*` family, `FLOW_ALIGN`, `SMART_RETAIL`,
|
|
57
|
+
`CAPTAIN_CONF`, `CONFIDENCE`, `SETTLED_AT`, the `PERP_SPOT_*` trio) is refused with
|
|
58
|
+
`REPORT_COLUMN_BENCHMARK_METRIC_UNSUPPORTED`, and one carrying a `rank` transform in either the
|
|
59
|
+
direct or the chained position with `REPORT_COLUMN_BENCHMARK_TRANSFORM_UNSUPPORTED`. Every tool
|
|
60
|
+
accepting a section array is affected, and no other byte of your body changes.
|
|
61
|
+
|
|
62
|
+
**Fix it by moving the column, not by retrying.** Both readings are defined *relative to the
|
|
63
|
+
cohort being evaluated* — a crowd reading is what this session's players did, a rank is a position
|
|
64
|
+
among the coins under evaluation — and a benchmark is deliberately outside that cohort. Neither
|
|
65
|
+
has a value there, which is why such a column could never render. Put it on an ordinary section
|
|
66
|
+
(`benchmarkTicker: null`), or drop it.
|
|
67
|
+
|
|
68
|
+
**This is a fix, not a new rule.** The restriction shipped with benchmark sections and was already
|
|
69
|
+
enforced by the column builder, by report materialization, and by `get_strategy_column_contract` —
|
|
70
|
+
so an author who checked a column against discovery first has been seeing this refusal all along.
|
|
71
|
+
What changed is that the SAVE path now asks the same question. Previously it did not, so such a
|
|
72
|
+
section persisted and then failed at every evaluation instead of at authoring.
|
|
73
|
+
|
|
74
|
+
- **A custom report section no longer accepts `timeframe`** (48.0.0,
|
|
75
|
+
`remove-section-anchor-override`). The per-section anchor override is gone. Every tool accepting a
|
|
76
|
+
section array — `compile_strategy_plan`, `preview_strategy_report`, `derive_strategy_rule_view`,
|
|
77
|
+
and `apply_strategy_plan` — refuses a section carrying it: `sections[N]: Unrecognized key(s)`,
|
|
78
|
+
with no other byte of your body changing. Drop the key. A section's columns resolve against the
|
|
79
|
+
**strategy** timeframe, and a column reaches any other timeframe by pinning it on the column
|
|
80
|
+
(`timeframe: { abs: '4h' }`) — which it could always do. Relative column references
|
|
81
|
+
(`anchor`/`lower`/`regime`) are untouched, and are the point: they track the strategy.
|
|
82
|
+
|
|
83
|
+
- **A custom report section requires `notes`** (43.0.0, `add-authored-section-notes`). Every tool
|
|
84
|
+
accepting a section array — `compile_strategy_plan`, `preview_strategy_report`,
|
|
85
|
+
`derive_strategy_rule_view` — refuses a section without it: `sections[N].notes: Required`, with no
|
|
86
|
+
byte of your body changing. Send explicit `null` for "no note". It is required rather than optional
|
|
87
|
+
because these payloads are a FULL REPLACE: an omitted key and an explicit `null` would be the same
|
|
88
|
+
request on the wire, so every rebuild site would silently clear a note its author wrote.
|
|
89
|
+
`benchmarkTicker` carries the same required-nullable discipline for the same reason.
|
|
90
|
+
|
|
91
|
+
- **Every condition requires `clock` and `closes`** (44.0.0, `add-condition-clock`), and **`exit`**
|
|
92
|
+
arrives with them. A condition entry now carries eight keys, not five. `clock` is `"LIVE"` (the
|
|
93
|
+
previous behaviour — the forming bar) or `"CLOSE"` (settled bars); `closes` is how many consecutive
|
|
94
|
+
closed bars must read true, 1–5, and is always `1` under LIVE. No wire default, for the same
|
|
95
|
+
whole-set-replacement reason as `notes`: a defaulted key would let an unrelated re-save silently
|
|
96
|
+
un-clock an enforced money gate back to forming-bar evidence.
|
|
97
|
+
|
|
98
|
+
A `CLOSE` clock is accepted only where a closed frame can change the reading — the clause must
|
|
99
|
+
resolve from the coin's own candle series at offset 0. Frame-inert operands (perp-payload scalars,
|
|
100
|
+
published rolling changes, ranks, zone entities, regime labels, enrichment metrics, session
|
|
101
|
+
scalars) are refused with `CONDITION_CLOCK_OPERAND_ILLEGAL` naming the header and the remedy: split
|
|
102
|
+
that clause into its own LIVE condition and `conditionRef` it. `exit: true` is legal only under
|
|
103
|
+
`clock: "CLOSE"` — an exit fired on a forming bar is an intrabar exit.
|
|
104
|
+
|
|
105
|
+
- **A strategy requires a seven-key `entry` object** (44.0.0 for four keys, 47.0.0 for three more —
|
|
106
|
+
`add-entry-on-close`, `add-level-trigger-execution`). Required on every CREATE, on
|
|
107
|
+
`compile_strategy_plan`, `apply_strategy_plan` and `update_intelligence_agent`. A client sending
|
|
108
|
+
44.0.0's four-key object is refused under 47 with `entry.levelSource: Required` without one byte of
|
|
109
|
+
it changing.
|
|
110
|
+
|
|
111
|
+
```jsonc
|
|
112
|
+
"entry": {
|
|
113
|
+
"trigger": "AT_SIGNAL", // | ON_CANDLE_CLOSE | STOP_THROUGH_LEVEL | ON_RETEST
|
|
114
|
+
"confirmTf": "4h", // the strategy timeframe or the rung below it — nothing else
|
|
115
|
+
"closes": 1, // 1–5; must be 1 unless ON_CANDLE_CLOSE
|
|
116
|
+
"bandAtrMultiple": 1.0, // > 0, and <= the platform's entry-deviation gate
|
|
117
|
+
"levelSource": "SWING_HIGH", // | SWING_LOW | BOLLINGER_UPPER | BOLLINGER_LOWER
|
|
118
|
+
"levelOffsetAtrMultiple": 0, // 0–2, UNSIGNED; must be 0 unless a level trigger
|
|
119
|
+
"validForBars": 4 // 1–24 of the strategy's own bars
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`AT_SIGNAL` with those values is byte-identical to pre-44 behaviour. The legality matrix runs one
|
|
124
|
+
way: all seven keys are always present, so a MEANINGFUL value under a trigger that ignores it is
|
|
125
|
+
refused rather than accepted-and-dropped — a dial never silently does nothing.
|
|
126
|
+
|
|
127
|
+
- **A `strategyTimeframe` the platform does not ingest is refused** (39.0.0,
|
|
128
|
+
`move-renderer-to-rendered-section`) on `get_coin_market_context`, where it was previously
|
|
129
|
+
accepted. The number is the only signal a client gets.
|
|
130
|
+
|
|
131
|
+
- **`eventType` gains `ENTRY_EXPIRED_UNCONFIRMED`** (48.1.0, `fix-entry-arming-lifecycle`) on
|
|
132
|
+
`get_radar_activity` and `get_radar_activity_summary` — an armed entry that reached its episode
|
|
133
|
+
lifetime without ever receiving a confirming close. A client holding its own closed copy of that
|
|
134
|
+
enum rejects the new member; one that switches exhaustively on it needs the branch.
|
|
135
|
+
|
|
136
|
+
`entryVoidCause` is deliberately **unchanged** and still carries exactly `BAND`, `CONDITIONS`,
|
|
137
|
+
`STRUCTURAL`. Each of those is a measurement taken *at* a close, so an episode that reached no
|
|
138
|
+
close gets its own event type rather than a fourth cause — `ENTRY_VOIDED` means "called off at the
|
|
139
|
+
close", a claim this outcome must not make.
|
|
140
|
+
|
|
141
|
+
The authoring boundary also gains a refusal with **no schema change**: a strategy declaring an
|
|
142
|
+
arming trigger whose `required` conditions read the `LIVE` clock is rejected on the existing
|
|
143
|
+
`VALIDATION_ERROR` code, naming the offending condition key. Same code, same shape, new reason —
|
|
144
|
+
so nothing in the published schema tells you it can now happen.
|
|
145
|
+
|
|
146
|
+
### Removed — no alias exists
|
|
147
|
+
|
|
148
|
+
- **`get_coin_market_context` is REMOVED** (40.0.0, `retire-get-coin-market-context`). Calling it
|
|
149
|
+
returns an unknown-tool error. There is deliberately **no alias**: a silent redirect would hide a
|
|
150
|
+
payload shape change from a client that never asked for one. Use `get_market_context`.
|
|
151
|
+
|
|
152
|
+
- **`get_macd_heatmap` leaves the published surface** (41.0.0). Same shape of break, same absence of
|
|
153
|
+
an alias.
|
|
154
|
+
|
|
155
|
+
- **`isPrimary` is removed from every published `EvaluatedSignal`** (38.0.0) — `get_signal_log`,
|
|
156
|
+
`get_public_agent_signal_log_detail`, and every other tool returning a signal scorecard. Reading it
|
|
157
|
+
now finds the key absent rather than false.
|
|
158
|
+
|
|
159
|
+
### Reshaped output — the same call returns a different shape
|
|
160
|
+
|
|
161
|
+
- **The normalized report section loses `timeframe`** (48.0.0, `remove-section-anchor-override`), on
|
|
162
|
+
every tool that publishes a strategy: `get_strategy`, `fork_strategy`, `archive_strategy`,
|
|
163
|
+
`restore_strategy`, `update_strategy_signal_rule`, `apply_strategy_plan`, and
|
|
164
|
+
`compile_strategy_plan`'s post-state. A strict parser rejects the shorter object; a lenient one
|
|
165
|
+
reads a section whose anchor is the strategy timeframe, which it now always is.
|
|
166
|
+
|
|
167
|
+
- **`get_strategy_column_contract` renames its anchor, both ways** (48.0.0). The request field
|
|
168
|
+
`sectionTimeframe` becomes `anchorTimeframe` — same meaning, and still optional. On the response,
|
|
169
|
+
`timeframe.requiresSectionTimeframe` becomes `requiresAnchorTimeframe`, and
|
|
170
|
+
`timeframe.sectionTimeframeOverrideAllowed` is **removed**: it published whether a column could go
|
|
171
|
+
in an anchor-overridden section, and no section can be overridden. One call also stops being
|
|
172
|
+
refused — a timeframe-inert metric supplied with an anchor now compiles.
|
|
173
|
+
`REPORT_COLUMN_SECTION_TIMEFRAME_UNSUPPORTED` leaves the `authoringCode` vocabulary.
|
|
174
|
+
|
|
175
|
+
- **`RenderedSection.notes` stops carrying provenance** (42.0.0, `separate-section-facts-from-read`),
|
|
176
|
+
on `preview_strategy_report`, `compile_strategy_plan` and `get_market_context`. A new REQUIRED
|
|
177
|
+
`provenance: string[]` carries it instead. A client reading provenance out of `notes` now reads an
|
|
178
|
+
author's prose, or nothing — which is a silent misread, not an error.
|
|
179
|
+
|
|
180
|
+
- **`preview_strategy_report.renderedSections[]` gains `authoredNote`** (43.0.0), the author's read
|
|
181
|
+
for a custom row and `null` on a platform row. Additive, but published on a `.strict()` shape.
|
|
182
|
+
|
|
183
|
+
- **`get_radar_activity` serves its evaluation curve on the FIRST PAGE ONLY** (37.0.0), and
|
|
184
|
+
`get_radar_activity_summary` is added. A client reading the curve off a later page finds it absent.
|
|
185
|
+
|
|
186
|
+
### Widened enum — new members your own copy rejects
|
|
187
|
+
|
|
188
|
+
- **The authorable metric vocabulary widens by 29 keys** (46.1.0, `add-indicator-catalog-coverage`):
|
|
189
|
+
Keltner (`KC_UPPER`/`KC_MID`/`KC_LOWER`), Supertrend (`ST_LINE`/`ST_DIR`), Hull (`HMA20`),
|
|
190
|
+
WaveTrend (`WT1`/`WT2`), QQE (`QQE_RSI_MA`/`QQE_STOP`), Parabolic SAR (`PSAR`), Ichimoku
|
|
191
|
+
(`ICHI_CONV`/`ICHI_BASE`/`ICHI_SPAN_A`/`ICHI_SPAN_B`/`ICHI_LAG`), Williams %R (`WILLR14`),
|
|
192
|
+
Stochastic RSI (`STOCH_RSI14`), session pivots (`PIVOT_P`/`PIVOT_R1`–`R3`/`PIVOT_S1`–`S3`), plus
|
|
193
|
+
four already-published fields that became addressable: `BB_UPPER`, `BB_LOWER`, `DI_PLUS`,
|
|
194
|
+
`DI_MINUS`.
|
|
195
|
+
|
|
196
|
+
Additive on the wire — every request you can send today is still accepted. It is called out here
|
|
197
|
+
because a client holding its own closed copy of the metric enum rejects the new members, and
|
|
198
|
+
because **an agent holding a cached belief that these are inexpressible will substitute for a
|
|
199
|
+
primitive the platform now serves**. That failure raises no error at all: the author is simply told
|
|
200
|
+
a strategy cannot be built.
|
|
201
|
+
|
|
202
|
+
- **`EntryTrigger` gains `STOP_THROUGH_LEVEL` and `ON_RETEST`, and `EntryLevelSource` is published
|
|
203
|
+
for the first time** with four members (47.0.0). Additive on their own; the required keys above are
|
|
204
|
+
what make that bump a major.
|
|
205
|
+
|
|
206
|
+
- **Each signal-checklist item's `measured` object gains a required `triggered` boolean** (47.2.0,
|
|
207
|
+
`fix-entry-prompt-signal-evidence`) on `get_signal_log` and `get_public_agent_signal_log_detail`,
|
|
208
|
+
on the `numeric` and `categorical` arms. Additive and MINOR — a client ignoring it is unaffected —
|
|
209
|
+
but it is named here because a client parsing that output strictly rejects the new key, and because
|
|
210
|
+
leaving 47.2 unlisted would make a reader wonder what happened to it.
|
|
211
|
+
|
|
212
|
+
The `unavailable` arm deliberately does **not** carry `triggered`: "the claim could not be joined to
|
|
213
|
+
a stored result" and "the signal did not fire" are different states, and leaving the key off that
|
|
214
|
+
arm makes conflating them a type error rather than a convention.
|
|
215
|
+
|
|
27
216
|
## Contract history — v12 → v36
|
|
28
217
|
|
|
29
218
|
> **The number in this heading is a CONTRACT version, not this package's version.** The npm badge at the top
|
|
@@ -176,6 +365,38 @@ Nothing in the proxy changes. No configuration, no environment variable, no call
|
|
|
176
365
|
|
|
177
366
|
### Additive in the same span
|
|
178
367
|
|
|
368
|
+
- **`get_regime_snapshot` publishes the evidence behind the verdict** (47.1.0,
|
|
369
|
+
`publish-regime-classification-evidence`). The snapshot gains `evidence`: the quantities the
|
|
370
|
+
classifier read, the gates it tested them against, the signed margin to the gate deciding whether
|
|
371
|
+
the current label survives, and the two decision facts only the classifier holds — `gateState`
|
|
372
|
+
(`cleared` / `held` / `dropped`) and `directionSource` (`di` / `ema`). Nothing narrows; a client
|
|
373
|
+
that ignores the field is unaffected.
|
|
374
|
+
|
|
375
|
+
Read `gateState` before you trust a trend label: **`held` means the ADX hysteresis buffer is
|
|
376
|
+
carrying the PREVIOUS bar's label rather than this bar re-confirming it** — a materially weaker
|
|
377
|
+
claim wearing the same word, and one no client could previously detect. `directionSource: 'ema'`
|
|
378
|
+
is the same shape of warning: the direction came from the fallback that fires precisely when the
|
|
379
|
+
DI spread is indecisive. The margin is signed so **positive always means "the current label
|
|
380
|
+
survives by this much"**, in every gate state, so it is safe to branch on its sign.
|
|
381
|
+
|
|
382
|
+
`conviction` is a BRANCH DISCRIMINATOR, not a confidence: it encodes *which* rule in the priority
|
|
383
|
+
ladder matched, not how comfortably it matched. The margins carry comfort. A client reading
|
|
384
|
+
conviction as a strength score is reading it wrong, and always was — this release just makes the
|
|
385
|
+
alternative available.
|
|
386
|
+
|
|
387
|
+
- **Thirteen metric keys join the catalog** (47.1.0) — the `regime` family gains `REGIME_STATE`,
|
|
388
|
+
`REGIME_CONVICTION`, `REGIME_RUN_BARS`, `REGIME_TREND_GATE`, `REGIME_TREND_MARGIN`,
|
|
389
|
+
`REGIME_TREND_SOURCE`, `REGIME_DI_SPREAD`, `REGIME_VOL_ATR_RATIO`, `REGIME_VOL_BBW_RATIO`,
|
|
390
|
+
`REGIME_MOM_BULL_VOTES`, `REGIME_MOM_BEAR_VOTES`, `REGIME_CRASH_MARGIN` and `REGIME_CRASH_LATCH`,
|
|
391
|
+
making the composite regime and its evidence addressable in a report column or condition for the
|
|
392
|
+
first time. Only a client that switches exhaustively on `MetricKey` needs new branches.
|
|
393
|
+
|
|
394
|
+
Not a contract change, but worth knowing if you author conditions: the report grammar's regime
|
|
395
|
+
metrics now resolve from the **confirmed close** on every path. They previously resolved from the
|
|
396
|
+
forming bar when a report was rendered and the confirmed close when the scan swept, so the same
|
|
397
|
+
condition could read differently in preview than in production. Same wire shape; same bar
|
|
398
|
+
everywhere now.
|
|
399
|
+
|
|
179
400
|
`27.1.0` exit-policy authoring input on `compile_strategy_plan` · `19.2.0` `get_account_state` account identity · `19.1.0` Standing Orders marker authoring · `18.4.0` `list_gate_blocks` summary groups · `18.3.0` radar maintenance pause · `18.1.0` protection geometry · `17.2.0` break-even/trailing status · `17.1.0` `get_signal_log` condition evaluation · `13.1.0` four owner-scoped read tools · `12.1.0` cross-venue spot price metrics · `11.1.0` discoverable rate limit.
|
|
180
401
|
|
|
181
402
|
## v11 and earlier — contract history (v6 → v11)
|
|
@@ -484,7 +705,7 @@ Tools, prompts, and resources are **discovered live** from the connected server
|
|
|
484
705
|
|
|
485
706
|
- **The announced contract is relayed, not declared.** The proxy reads the upstream server's identity from the handshake it just completed and re-announces it verbatim to the local client. A local client therefore always reads the contract it will actually reach, and the package version is free to mean only what it should: this proxy's own code. **There is no pairing rule to keep, and no publish-time deploy gate** — a released package makes no claim about the server, so there is no ordering between a release here and a deploy there. This replaces the `MAJOR.MINOR` pairing that held through v11; see [v12](#v12--the-announced-contract-is-read-from-the-server-not-declared-here).
|
|
486
707
|
- **Fails closed, never falls back.** If a connected server announced no `serverInfo` — a protocol violation, since it is required in a successful `initialize` result — the proxy refuses to start rather than substituting its own version. There is no honest number to announce in that case, and announcing a dishonest one silently is the failure this design removes.
|
|
487
|
-
- **Rediscover after a server cutover.**
|
|
708
|
+
- **Rediscover after a server cutover.** The proxy resolves its catalog on first use and then caches it for the life of the process; a resolution that *failed* is retried on the next request, but a server deploy is never noticed. Package publication does not refresh it either. Restart/reconnect the proxy and re-run `tools/list`, `prompts/list`, and `resources/list` after the server deploys.
|
|
488
709
|
- **Restart after key rotation.** API keys are read once at process startup; rotate a key, then restart the proxy.
|
|
489
710
|
|
|
490
711
|
| Version | Changes |
|
|
@@ -577,7 +798,7 @@ Also confirm npm's Trusted Publisher for `@battlegrid/mcp-server` is GitHub Acti
|
|
|
577
798
|
|
|
578
799
|
Two things do still need doing, neither of them a release:
|
|
579
800
|
|
|
580
|
-
- **Reconnect** to pick up the new contract — the announcement and the capability snapshot
|
|
801
|
+
- **Reconnect** to pick up the new contract — the announcement is read once from the handshake at startup, and the capability snapshot is resolved on first use and cached thereafter (see [Rediscovery & versioning](#rediscovery--versioning)).
|
|
581
802
|
- **Document the break** where the contract is documented, in `battlegrid-app`. Contract breaking-change notes are no longer keyed to package versions in this README, because a contract move is no longer a release here.
|
|
582
803
|
|
|
583
804
|
### Verify publication
|
package/dist/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
*/
|
|
38
38
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
39
39
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
40
|
-
import { type Implementation } from '@modelcontextprotocol/sdk/types.js';
|
|
40
|
+
import { type Implementation, type Prompt, type Resource } from '@modelcontextprotocol/sdk/types.js';
|
|
41
41
|
/**
|
|
42
42
|
* This package's own version — the proxy's code, and nothing else.
|
|
43
43
|
*
|
|
@@ -49,7 +49,7 @@ import { type Implementation } from '@modelcontextprotocol/sdk/types.js';
|
|
|
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.
|
|
52
|
+
export declare const PACKAGE_VERSION = "31.2.0";
|
|
53
53
|
export declare const DEFAULT_URL = "https://mcp.battlegrid.trade/mcp";
|
|
54
54
|
export interface EnvConfig {
|
|
55
55
|
apiKeys: string[];
|
|
@@ -106,26 +106,73 @@ export declare function injectAccountParam(tools: ToolDefinition[], accountNames
|
|
|
106
106
|
*/
|
|
107
107
|
export declare function announcedIdentityOf(serverInfo: Implementation | undefined): Implementation;
|
|
108
108
|
export interface CreateProxyServerOptions {
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
/**
|
|
110
|
+
* The operator's FIRST configured key — used for the announcing handshake, the prompt and
|
|
111
|
+
* resource surfaces, and single-account routing. Deliberately not derived from whichever
|
|
112
|
+
* identity lookups happened to succeed: that made a mistyped first key silently promote the
|
|
113
|
+
* second, relocating every unqualified call to a different account.
|
|
114
|
+
*/
|
|
115
|
+
primaryKey: string;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a tool call must name an account. Derived from the CONFIGURED key count, so the guard
|
|
118
|
+
* is armed before any network call. Deriving it from resolved identities would let a transient
|
|
119
|
+
* identity failure convert a multi-account proxy into a single-account one and route an
|
|
120
|
+
* unqualified money-moving call to the primary.
|
|
121
|
+
*/
|
|
122
|
+
isMultiAccount: boolean;
|
|
123
|
+
/** Connect (or reuse) a remote MCP client for a given API key. */
|
|
112
124
|
connect: (apiKey: string) => Promise<Client>;
|
|
125
|
+
/** Resolve account identities. Awaited lazily, on the first request that needs the catalog. */
|
|
126
|
+
resolveIdentities: () => Promise<AccountIdentity[]>;
|
|
113
127
|
}
|
|
114
|
-
|
|
115
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Everything the catalog resolution produces, resolved together as one shared value.
|
|
130
|
+
*
|
|
131
|
+
* The account selector published on every tool schema and the membership check applied to an
|
|
132
|
+
* incoming call are one rule at two altitudes, so `accountNames` and `keyByAccount` are members
|
|
133
|
+
* here rather than re-derived at each handler.
|
|
134
|
+
*/
|
|
135
|
+
export interface ProxyCatalog {
|
|
136
|
+
identities: AccountIdentity[];
|
|
137
|
+
accountNames: string[];
|
|
138
|
+
keyByAccount: Map<string, string>;
|
|
139
|
+
tools: ToolDefinition[];
|
|
140
|
+
prompts: Prompt[];
|
|
141
|
+
resources: Resource[];
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* What a completed warm-up reports back to `main()`, which owns every startup diagnostic.
|
|
145
|
+
*
|
|
146
|
+
* Carries `accountNames` as well as the counts because the account-roster line is the only surface
|
|
147
|
+
* naming which accounts actually resolved — the signal a dangling primary or a silent single-account
|
|
148
|
+
* collapse would otherwise hide.
|
|
149
|
+
*/
|
|
150
|
+
export interface WarmSummary {
|
|
151
|
+
accountNames: string[];
|
|
116
152
|
toolCount: number;
|
|
117
153
|
promptCount: number;
|
|
118
154
|
resourceCount: number;
|
|
119
|
-
|
|
120
|
-
|
|
155
|
+
}
|
|
156
|
+
export interface ProxyServer {
|
|
157
|
+
server: Server;
|
|
121
158
|
/** The upstream identity relayed downstream — the contract a local client will actually reach. */
|
|
122
159
|
announced: Implementation;
|
|
160
|
+
/**
|
|
161
|
+
* Resolve the catalog, returning its counts. Returns the SAME memoized resolution a request
|
|
162
|
+
* triggers — it starts nothing of its own, so warm-up and a first request never resolve twice.
|
|
163
|
+
*/
|
|
164
|
+
warm: () => Promise<WarmSummary>;
|
|
123
165
|
}
|
|
124
166
|
/**
|
|
125
|
-
* Build the local stdio-facing MCP server that proxies to the remote BattleGrid
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
167
|
+
* Build the local stdio-facing MCP server that proxies to the remote BattleGrid server.
|
|
168
|
+
*
|
|
169
|
+
* ORDERING IS THE POINT. Exactly one upstream operation happens here: the handshake that yields the
|
|
170
|
+
* identity this proxy relays. `serverInfo` is captured by the SDK at `Server` construction and read
|
|
171
|
+
* when `initialize` is answered, with no setter, so relaying the upstream's identity verbatim makes
|
|
172
|
+
* one round trip inherent. Everything else — identity discovery and the three catalog calls —
|
|
173
|
+
* resolves lazily, after the caller has bound the transport, because none of it is needed to answer
|
|
174
|
+
* `initialize` and every unit of work placed ahead of the bind is paid by every client on every
|
|
175
|
+
* start.
|
|
129
176
|
*/
|
|
130
177
|
export declare function createProxyServer(options: CreateProxyServerOptions): Promise<ProxyServer>;
|
|
131
178
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAOL,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -52,10 +52,16 @@ 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.
|
|
55
|
+
export const PACKAGE_VERSION = '31.2.0';
|
|
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];
|
|
59
|
+
// One rule, two expressions. Asserted here so the delay table genuinely bounds the attempt count,
|
|
60
|
+
// which is what lets connectWithRetry index it without a fallback.
|
|
61
|
+
if (RETRY_DELAYS_MS.length !== MAX_RETRIES) {
|
|
62
|
+
throw new Error(`Retry budget disagrees with itself: MAX_RETRIES=${MAX_RETRIES} but RETRY_DELAYS_MS carries ` +
|
|
63
|
+
`${RETRY_DELAYS_MS.length} delays. Reconcile them at their declaration.`);
|
|
64
|
+
}
|
|
59
65
|
// --- Environment validation (exported for testing) ---
|
|
60
66
|
export function validateEnv(env) {
|
|
61
67
|
const apiUrl = env.BATTLEGRID_API_URL || DEFAULT_URL;
|
|
@@ -133,7 +139,8 @@ function isAuthError(error) {
|
|
|
133
139
|
function sleep(ms) {
|
|
134
140
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
135
141
|
}
|
|
136
|
-
async function connectWithRetry(client, transport, apiUrl) {
|
|
142
|
+
async function connectWithRetry(client, transport, apiUrl, apiKey) {
|
|
143
|
+
const keyPrefix = apiKey.substring(0, 12);
|
|
137
144
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
138
145
|
try {
|
|
139
146
|
await client.connect(transport);
|
|
@@ -146,7 +153,7 @@ async function connectWithRetry(client, transport, apiUrl) {
|
|
|
146
153
|
: undefined;
|
|
147
154
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
148
155
|
if (isAuthError(error)) {
|
|
149
|
-
throw new Error(`Authentication failed (HTTP ${errorCode ?? 'unknown'}): ${errorMessage}\n` +
|
|
156
|
+
throw new Error(`Authentication failed for key ${keyPrefix} (HTTP ${errorCode ?? 'unknown'}): ${errorMessage}\n` +
|
|
150
157
|
'This means the server rejected your API key. Possible causes:\n' +
|
|
151
158
|
' 1. Key was revoked (a new key invalidates all previous keys)\n' +
|
|
152
159
|
' 2. Key was corrupted during copy-paste\n' +
|
|
@@ -154,12 +161,13 @@ async function connectWithRetry(client, transport, apiUrl) {
|
|
|
154
161
|
'Create a new key at: https://battlegrid.trade → Profile → MCP tab');
|
|
155
162
|
}
|
|
156
163
|
if (attempt === MAX_RETRIES) {
|
|
157
|
-
throw new Error(`Cannot connect to BattleGrid server at ${apiUrl}
|
|
164
|
+
throw new Error(`Cannot connect to BattleGrid server at ${apiUrl} with key ${keyPrefix} after ` +
|
|
165
|
+
`${MAX_RETRIES + 1} attempts.\n` +
|
|
158
166
|
`Last error: ${errorMessage}\n` +
|
|
159
167
|
`Check your internet connection or verify the server is running.\n` +
|
|
160
168
|
`Health check: ${apiUrl.replace('/mcp', '')}/health`);
|
|
161
169
|
}
|
|
162
|
-
const delay = RETRY_DELAYS_MS[attempt]
|
|
170
|
+
const delay = RETRY_DELAYS_MS[attempt];
|
|
163
171
|
process.stderr.write(`Connection attempt ${attempt + 1} failed (${errorMessage}), retrying in ${delay / 1000}s...\n`);
|
|
164
172
|
await sleep(delay);
|
|
165
173
|
}
|
|
@@ -222,64 +230,153 @@ export function announcedIdentityOf(serverInfo) {
|
|
|
222
230
|
return serverInfo;
|
|
223
231
|
}
|
|
224
232
|
/**
|
|
225
|
-
* Build the local stdio-facing MCP server that proxies to the remote BattleGrid
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
233
|
+
* Build the local stdio-facing MCP server that proxies to the remote BattleGrid server.
|
|
234
|
+
*
|
|
235
|
+
* ORDERING IS THE POINT. Exactly one upstream operation happens here: the handshake that yields the
|
|
236
|
+
* identity this proxy relays. `serverInfo` is captured by the SDK at `Server` construction and read
|
|
237
|
+
* when `initialize` is answered, with no setter, so relaying the upstream's identity verbatim makes
|
|
238
|
+
* one round trip inherent. Everything else — identity discovery and the three catalog calls —
|
|
239
|
+
* resolves lazily, after the caller has bound the transport, because none of it is needed to answer
|
|
240
|
+
* `initialize` and every unit of work placed ahead of the bind is paid by every client on every
|
|
241
|
+
* start.
|
|
229
242
|
*/
|
|
230
243
|
export async function createProxyServer(options) {
|
|
231
|
-
const {
|
|
232
|
-
|
|
233
|
-
const accountNames = identities.map(id => id.username);
|
|
234
|
-
// Build lookup: username → apiKey
|
|
235
|
-
const keyByAccount = new Map();
|
|
236
|
-
for (const id of identities) {
|
|
237
|
-
keyByAccount.set(id.username, id.apiKey);
|
|
238
|
-
}
|
|
239
|
-
// Primary client (first key) is used for capability discovery and non-tool proxying.
|
|
240
|
-
const primaryKey = identities[0].apiKey;
|
|
244
|
+
const { primaryKey, isMultiAccount, connect, resolveIdentities } = options;
|
|
245
|
+
// The one retained pre-bind round trip.
|
|
241
246
|
const primaryClient = await connect(primaryKey);
|
|
242
247
|
// What this proxy announces downstream is what the upstream just announced to it — read here,
|
|
243
248
|
// from the completed handshake, so it can never be a stale constant.
|
|
244
249
|
const announced = announcedIdentityOf(primaryClient.getServerVersion());
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
primaryClient.listResources(),
|
|
250
|
-
]);
|
|
251
|
-
// Augment tools with account parameter if multi-account
|
|
252
|
-
const exposedTools = isMultiAccount
|
|
253
|
-
? injectAccountParam(toolsResult.tools, accountNames)
|
|
254
|
-
: toolsResult.tools;
|
|
255
|
-
// Create local stdio server, announcing the upstream's identity rather than one of our own.
|
|
250
|
+
// `listChanged` is declared HERE and can never be added later: registerCapabilities throws once a
|
|
251
|
+
// transport is connected, and a client only registers list-changed handlers for capabilities the
|
|
252
|
+
// server advertised. Without it, a client whose first tools/list failed holds an empty catalog for
|
|
253
|
+
// the life of the process — the symptom this lazy catalog exists to remove, made silent.
|
|
256
254
|
const localServer = new Server(announced, {
|
|
257
255
|
capabilities: {
|
|
258
|
-
tools: {},
|
|
259
|
-
prompts: {},
|
|
260
|
-
resources: {},
|
|
256
|
+
tools: { listChanged: true },
|
|
257
|
+
prompts: { listChanged: true },
|
|
258
|
+
resources: { listChanged: true },
|
|
261
259
|
},
|
|
262
260
|
});
|
|
263
|
-
//
|
|
261
|
+
// Pool of PROMISES, not clients: concurrent callers for one key share one in-flight connect
|
|
262
|
+
// rather than each building a transport that is never closed. A rejection is removed so the next
|
|
263
|
+
// caller retries.
|
|
264
264
|
const clientPool = new Map();
|
|
265
|
-
clientPool.set(primaryKey, primaryClient);
|
|
266
|
-
|
|
265
|
+
clientPool.set(primaryKey, Promise.resolve(primaryClient));
|
|
266
|
+
function getClientForKey(apiKey) {
|
|
267
267
|
const existing = clientPool.get(apiKey);
|
|
268
268
|
if (existing)
|
|
269
269
|
return existing;
|
|
270
|
-
const
|
|
271
|
-
clientPool.set(apiKey,
|
|
272
|
-
|
|
270
|
+
const pending = connect(apiKey);
|
|
271
|
+
clientPool.set(apiKey, pending);
|
|
272
|
+
pending.catch(() => {
|
|
273
|
+
if (clientPool.get(apiKey) === pending)
|
|
274
|
+
clientPool.delete(apiKey);
|
|
275
|
+
});
|
|
276
|
+
return pending;
|
|
277
|
+
}
|
|
278
|
+
let catalogMemo = null;
|
|
279
|
+
let servedCatalogError = false;
|
|
280
|
+
async function announceListsChanged() {
|
|
281
|
+
try {
|
|
282
|
+
await Promise.all([
|
|
283
|
+
localServer.sendToolListChanged(),
|
|
284
|
+
localServer.sendPromptListChanged(),
|
|
285
|
+
localServer.sendResourceListChanged(),
|
|
286
|
+
]);
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
290
|
+
process.stderr.write(`Warning: could not notify client that the catalog recovered: ${message}\n`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async function buildCatalog() {
|
|
294
|
+
const identities = await resolveIdentities();
|
|
295
|
+
// The declared primary must be in the resolved roster. Identity discovery is a single unretried
|
|
296
|
+
// request while the handshake retries three times, so a primary can complete the handshake and
|
|
297
|
+
// still be missing here — which would serve prompts and resources as an account that appears in
|
|
298
|
+
// no selector and no log line.
|
|
299
|
+
if (!identities.some((identity) => identity.apiKey === primaryKey)) {
|
|
300
|
+
throw new Error(`Primary key (${primaryKey.substring(0, 12)}) is absent from the resolved account roster, ` +
|
|
301
|
+
'so every call routed to it would execute as an account this proxy never resolved.');
|
|
302
|
+
}
|
|
303
|
+
const accountNames = identities.map((identity) => identity.username);
|
|
304
|
+
const keyByAccount = new Map();
|
|
305
|
+
for (const identity of identities) {
|
|
306
|
+
if (keyByAccount.has(identity.username)) {
|
|
307
|
+
throw new Error(`Two configured accounts resolved to the display name "${identity.username}", so an ` +
|
|
308
|
+
'account selection cannot name one of them unambiguously.');
|
|
309
|
+
}
|
|
310
|
+
keyByAccount.set(identity.username, identity.apiKey);
|
|
311
|
+
}
|
|
312
|
+
const [toolsResult, promptsResult, resourcesResult] = await Promise.all([
|
|
313
|
+
primaryClient.listTools(),
|
|
314
|
+
primaryClient.listPrompts(),
|
|
315
|
+
primaryClient.listResources(),
|
|
316
|
+
]);
|
|
317
|
+
const discovered = toolsResult.tools;
|
|
318
|
+
return {
|
|
319
|
+
identities,
|
|
320
|
+
accountNames,
|
|
321
|
+
keyByAccount,
|
|
322
|
+
tools: isMultiAccount ? injectAccountParam(discovered, accountNames) : discovered,
|
|
323
|
+
prompts: promptsResult.prompts,
|
|
324
|
+
resources: resourcesResult.resources,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* The catalog, resolved at most once and shared by every caller.
|
|
329
|
+
*
|
|
330
|
+
* The clear-on-failure is identity-guarded deliberately. The obvious shape — an async IIFE whose
|
|
331
|
+
* inner catch nulls the memo — poisons it permanently when the body throws before its first
|
|
332
|
+
* `await`: that catch runs during the synchronous prefix and the outer assignment then
|
|
333
|
+
* re-installs the rejected promise. Guarding on identity is correct for both timings and also
|
|
334
|
+
* cannot discard a newer resolution another request installed.
|
|
335
|
+
*/
|
|
336
|
+
function resolveCatalog() {
|
|
337
|
+
const existing = catalogMemo;
|
|
338
|
+
if (existing)
|
|
339
|
+
return existing;
|
|
340
|
+
const pending = buildCatalog();
|
|
341
|
+
catalogMemo = pending;
|
|
342
|
+
pending.catch(() => {
|
|
343
|
+
if (catalogMemo === pending)
|
|
344
|
+
catalogMemo = null;
|
|
345
|
+
});
|
|
346
|
+
void pending.then(() => {
|
|
347
|
+
if (!servedCatalogError)
|
|
348
|
+
return;
|
|
349
|
+
servedCatalogError = false;
|
|
350
|
+
void announceListsChanged();
|
|
351
|
+
}, () => undefined);
|
|
352
|
+
return pending;
|
|
353
|
+
}
|
|
354
|
+
/** Resolve the catalog, remembering that a failure was served so a later recovery can be announced. */
|
|
355
|
+
async function catalogOrThrow() {
|
|
356
|
+
try {
|
|
357
|
+
return await resolveCatalog();
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
servedCatalogError = true;
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
273
363
|
}
|
|
274
364
|
// --- Proxy: tools ---
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
365
|
+
// Throws on rejection: ListToolsResult carries only `tools`, so the tools/call in-band
|
|
366
|
+
// `{content, isError}` shape would ship as a SUCCESSFUL result that fails the client's own parse.
|
|
367
|
+
// The SDK maps a thrown handler error to a proper JSON-RPC error.
|
|
368
|
+
localServer.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
369
|
+
const catalog = await catalogOrThrow();
|
|
370
|
+
return { tools: catalog.tools };
|
|
371
|
+
});
|
|
278
372
|
localServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
279
373
|
try {
|
|
280
374
|
let targetKey = primaryKey;
|
|
281
375
|
const args = { ...request.params.arguments };
|
|
376
|
+
// Read from the constructor option, never from the catalog: the guard must be armed even
|
|
377
|
+
// while the account set is still unknown.
|
|
282
378
|
if (isMultiAccount) {
|
|
379
|
+
const { keyByAccount, accountNames } = await catalogOrThrow();
|
|
283
380
|
const selectedAccount = args.account;
|
|
284
381
|
if (!selectedAccount || !keyByAccount.has(selectedAccount)) {
|
|
285
382
|
return {
|
|
@@ -308,9 +405,10 @@ export async function createProxyServer(options) {
|
|
|
308
405
|
}
|
|
309
406
|
});
|
|
310
407
|
// --- Proxy: prompts ---
|
|
311
|
-
localServer.setRequestHandler(ListPromptsRequestSchema, async () =>
|
|
312
|
-
|
|
313
|
-
|
|
408
|
+
localServer.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
409
|
+
const catalog = await catalogOrThrow();
|
|
410
|
+
return { prompts: catalog.prompts };
|
|
411
|
+
});
|
|
314
412
|
localServer.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
315
413
|
return await primaryClient.getPrompt({
|
|
316
414
|
name: request.params.name,
|
|
@@ -318,9 +416,10 @@ export async function createProxyServer(options) {
|
|
|
318
416
|
});
|
|
319
417
|
});
|
|
320
418
|
// --- Proxy: resources ---
|
|
321
|
-
localServer.setRequestHandler(ListResourcesRequestSchema, async () =>
|
|
322
|
-
|
|
323
|
-
|
|
419
|
+
localServer.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
420
|
+
const catalog = await catalogOrThrow();
|
|
421
|
+
return { resources: catalog.resources };
|
|
422
|
+
});
|
|
324
423
|
localServer.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
325
424
|
return await primaryClient.readResource({
|
|
326
425
|
uri: request.params.uri,
|
|
@@ -328,12 +427,16 @@ export async function createProxyServer(options) {
|
|
|
328
427
|
});
|
|
329
428
|
return {
|
|
330
429
|
server: localServer,
|
|
331
|
-
toolCount: toolsResult.tools.length,
|
|
332
|
-
promptCount: promptsResult.prompts.length,
|
|
333
|
-
resourceCount: resourcesResult.resources.length,
|
|
334
|
-
isMultiAccount,
|
|
335
|
-
accountNames,
|
|
336
430
|
announced,
|
|
431
|
+
warm: async () => {
|
|
432
|
+
const catalog = await resolveCatalog();
|
|
433
|
+
return {
|
|
434
|
+
accountNames: catalog.accountNames,
|
|
435
|
+
toolCount: catalog.tools.length,
|
|
436
|
+
promptCount: catalog.prompts.length,
|
|
437
|
+
resourceCount: catalog.resources.length,
|
|
438
|
+
};
|
|
439
|
+
},
|
|
337
440
|
};
|
|
338
441
|
}
|
|
339
442
|
// --- Main ---
|
|
@@ -352,27 +455,25 @@ async function main() {
|
|
|
352
455
|
const hashPrefix = createHash('sha256').update(key).digest('hex').substring(0, 16);
|
|
353
456
|
process.stderr.write(`BattleGrid MCP: Key #${i + 1} prefix=${key.substring(0, 12)} hashPrefix=${hashPrefix} len=${key.length}\n`);
|
|
354
457
|
}
|
|
355
|
-
//
|
|
356
|
-
let identities;
|
|
357
|
-
try {
|
|
358
|
-
identities = await discoverIdentities(config.apiKeys, config.apiUrl);
|
|
359
|
-
}
|
|
360
|
-
catch (error) {
|
|
361
|
-
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
362
|
-
process.exit(1);
|
|
363
|
-
}
|
|
364
|
-
process.stderr.write(`BattleGrid MCP: ${identities.length} account(s) discovered — ${identities.map(id => id.username).join(', ')}\n`);
|
|
365
|
-
// Lazily connect a remote MCP client per API key, with retry + auth diagnostics.
|
|
458
|
+
// Connect a remote MCP client for a given API key, with retry + auth diagnostics.
|
|
366
459
|
const connect = async (apiKey) => {
|
|
367
460
|
const transport = new StreamableHTTPClientTransport(new URL(config.apiUrl), { requestInit: { headers: { Authorization: `Bearer ${apiKey}` } } });
|
|
368
461
|
// Upstream is told which proxy build is calling — the one question PACKAGE_VERSION answers.
|
|
369
462
|
const client = new Client({ name: 'battlegrid-proxy', version: PACKAGE_VERSION }, { capabilities: {} });
|
|
370
|
-
await connectWithRetry(client, transport, config.apiUrl);
|
|
463
|
+
await connectWithRetry(client, transport, config.apiUrl, apiKey);
|
|
371
464
|
return client;
|
|
372
465
|
};
|
|
373
466
|
let proxy;
|
|
374
467
|
try {
|
|
375
|
-
proxy = await createProxyServer({
|
|
468
|
+
proxy = await createProxyServer({
|
|
469
|
+
// The operator's declared first key, chosen before discovery so an unreachable one fails
|
|
470
|
+
// loudly here instead of silently promoting the second.
|
|
471
|
+
primaryKey: config.apiKeys[0],
|
|
472
|
+
// Armed by configuration, so a later identity failure cannot stand the account guard down.
|
|
473
|
+
isMultiAccount: config.apiKeys.length > 1,
|
|
474
|
+
connect,
|
|
475
|
+
resolveIdentities: () => discoverIdentities(config.apiKeys, config.apiUrl),
|
|
476
|
+
});
|
|
376
477
|
}
|
|
377
478
|
catch (error) {
|
|
378
479
|
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
@@ -383,11 +484,25 @@ async function main() {
|
|
|
383
484
|
// unnoticed for ten days.
|
|
384
485
|
process.stderr.write(`BattleGrid MCP: announcing ${proxy.announced.name}@${proxy.announced.version} ` +
|
|
385
486
|
`(server contract, read from the upstream handshake) — proxy ${PACKAGE_VERSION}\n`);
|
|
386
|
-
|
|
387
|
-
//
|
|
487
|
+
// --- Start stdio transport, BEFORE any catalog work ---
|
|
488
|
+
//
|
|
489
|
+
// Everything above is the single upstream handshake the relayed serverInfo requires. From here the
|
|
490
|
+
// process answers `initialize`; identity discovery and the three catalog calls happen behind it.
|
|
388
491
|
const stdioTransport = new StdioServerTransport();
|
|
389
492
|
await proxy.server.connect(stdioTransport);
|
|
390
493
|
process.stderr.write('BattleGrid MCP server running on stdio\n');
|
|
494
|
+
// Warm the catalog so the first tools/list joins an in-flight resolution rather than starting one.
|
|
495
|
+
// Deliberately NOT awaited, and the rejection handler is the whole of the guarantee that a
|
|
496
|
+
// background failure cannot kill a process that has already answered `initialize`. The failure is
|
|
497
|
+
// reported and absorbed; the next request that needs the catalog retries it.
|
|
498
|
+
void proxy.warm().then((summary) => {
|
|
499
|
+
process.stderr.write(`BattleGrid MCP: ${summary.accountNames.length} account(s) discovered — ${summary.accountNames.join(', ')}\n`);
|
|
500
|
+
process.stderr.write(`BattleGrid MCP: ${summary.toolCount} tools, ${summary.promptCount} prompts, ${summary.resourceCount} resources\n`);
|
|
501
|
+
}, (error) => {
|
|
502
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
503
|
+
process.stderr.write(`Warning: catalog warm-up failed (${message}). The proxy is connected; the next request ` +
|
|
504
|
+
'that needs the catalog will retry it.\n');
|
|
505
|
+
});
|
|
391
506
|
}
|
|
392
507
|
// Only run when executed directly (not when imported for testing)
|
|
393
508
|
const isDirectExecution = process.argv[1] &&
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -88,14 +88,22 @@ values instead of the evaluated coin's — the standard way to gate a whole book
|
|
|
88
88
|
regime. `benchmarkTicker` is required-nullable on every custom section: send `null` for an
|
|
89
89
|
ordinary section, never omit it.
|
|
90
90
|
|
|
91
|
+
A bound section takes **indicator** columns only. Crowd/session metrics (the `CROWD_*` family,
|
|
92
|
+
`FLOW_ALIGN`, `SMART_RETAIL`, `CAPTAIN_CONF`, `CONFIDENCE`, `SETTLED_AT`, `PERP_SPOT_*`) and any
|
|
93
|
+
`rank` transform are refused there (contract 49), because both are defined relative to the cohort
|
|
94
|
+
being evaluated and a benchmark sits outside it — a crowd reading is what this session's players
|
|
95
|
+
did, a rank is a position among the coins under evaluation. Neither has a value for BTC-as-yardstick.
|
|
96
|
+
Put those columns on an ordinary section and `conditionRef` across.
|
|
97
|
+
|
|
91
98
|
Budgets are served by discovery (validated today: 32 sections, 32 custom columns, 8 distinct
|
|
92
99
|
timeframes, 16 conditions, 16 clauses, 16k estimated report tokens). `preview_strategy_report`
|
|
93
100
|
echoes your usage against each cap.
|
|
94
101
|
|
|
95
102
|
## Conditions — deterministic logic over your own report
|
|
96
103
|
|
|
97
|
-
Each condition: `{ conditionKey, name, definition, verdict, required }` —
|
|
98
|
-
|
|
104
|
+
Each condition: `{ conditionKey, name, definition, verdict, required, exit, clock, closes }` —
|
|
105
|
+
all eight required, no defaults. The conditions axis saves by whole-set replacement, so an omitted
|
|
106
|
+
key would silently un-clock a money gate on the next unrelated edit rather than be refused.
|
|
99
107
|
|
|
100
108
|
- **Clauses** compare one column: numeric/rank headers take `lt|lte|gte|gt|between`;
|
|
101
109
|
classification/direction/event headers take `is|in` with the column's exact vocabulary
|
|
@@ -106,8 +114,11 @@ Each condition: `{ conditionKey, name, definition, verdict, required }` — all
|
|
|
106
114
|
rejected, forward references are legal.
|
|
107
115
|
- **Column addressing**: `{sectionKey, header}`. `sectionKey: null` is authoring sugar for a
|
|
108
116
|
header unique across the whole report; a duplicated header (e.g. `ADX` in two sections) must
|
|
109
|
-
be section-qualified.
|
|
110
|
-
|
|
117
|
+
be section-qualified. On a **CREATE you omit `sectionKey` entirely** — the server derives it
|
|
118
|
+
from the section itself, so the same submitted section yields the same key on every compile, and
|
|
119
|
+
minting a `custom:<uuid>` yourself is refused. On an UPDATE or RESTORE, send back the keys
|
|
120
|
+
`get_strategy` returned. To qualify a duplicated header, read the key from a preview's
|
|
121
|
+
`conditionColumns` or from the candidates a `CONDITION_COLUMN_AMBIGUOUS` refusal offers.
|
|
111
122
|
- **Verdict**: `UP` | `DOWN` | `NEITHER` on deciding conditions, explicit `null` on building
|
|
112
123
|
blocks. Declaration order is precedence: the first TRUE condition with a non-null verdict
|
|
113
124
|
decides the coin's verdict. Put the more specific carrier first.
|
|
@@ -116,6 +127,48 @@ Each condition: `{ conditionKey, name, definition, verdict, required }` — all
|
|
|
116
127
|
use it for liquidity floors, regime vetoes, and "never fight the HTF" rules.
|
|
117
128
|
- Evaluation is three-valued: `UNRESOLVED` (missing input) is never collapsed to FALSE, and
|
|
118
129
|
outcomes read from a still-forming bar are marked provisional.
|
|
130
|
+
- **The evidence clock.** `clock: "LIVE"` reads the forming bar; `clock: "CLOSE"` reads settled
|
|
131
|
+
bars, and `closes` (1–5) is how many consecutive closed bars must read TRUE — always `1` under
|
|
132
|
+
LIVE, which has exactly one frame. A CLOSE clock is legal **only** over a header resolved from
|
|
133
|
+
the coin's own candle series at offset 0; frame-inert operands (perp-payload scalars, published
|
|
134
|
+
rolling changes, ranks, zone entities, regime labels, enrichment metrics, session scalars) are
|
|
135
|
+
refused with `CONDITION_CLOCK_OPERAND_ILLEGAL`. The remedy is a split, not a re-clock: move that
|
|
136
|
+
clause into its own LIVE condition and `conditionRef` it.
|
|
137
|
+
- **The exit role.** `exit: true` makes a settled TRUE reading close open positions its verdict
|
|
138
|
+
opposes — UP exits SHORTs, DOWN exits LONGs, a `NEITHER` or `null` verdict exits both. Legal only
|
|
139
|
+
under `clock: "CLOSE"`, because an exit fired on a forming bar is an intrabar exit. Orthogonal to
|
|
140
|
+
`required`: the two act on disjoint lifecycles, pre-entry versus open.
|
|
141
|
+
|
|
142
|
+
## Entry — when, and where, an entry is taken
|
|
143
|
+
|
|
144
|
+
`{ trigger, confirmTf, closes, bandAtrMultiple, levelSource, levelOffsetAtrMultiple, validForBars }`
|
|
145
|
+
— all seven required on every CREATE, no defaults. Replaced WHOLE on save, so an omitted key
|
|
146
|
+
reverts an author's discipline silently rather than being refused.
|
|
147
|
+
|
|
148
|
+
| `trigger` | What it does |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `AT_SIGNAL` | Fire on the qualification flip, at whatever bar is on the tape. The platform's flat wall-clock entry window applies. |
|
|
151
|
+
| `ON_CANDLE_CLOSE` | The flip ARMS the pair; entry is taken only after a `confirmTf` close that still reads the conditions true and has not displaced beyond the band. |
|
|
152
|
+
| `STOP_THROUGH_LEVEL` | A TRIGGER order rests at the level ± offset; the exchange book is the watcher. |
|
|
153
|
+
| `ON_RETEST` | A LIMIT order rests at the broken level. Not filling is a correct outcome, not a failure. |
|
|
154
|
+
|
|
155
|
+
- `confirmTf` — exactly two values are legal: the strategy's own timeframe and the rung below it
|
|
156
|
+
(one only, at the ladder floor). Not the authorable main-candle set.
|
|
157
|
+
- `closes` — 1–5 consecutive confirming closes. Must be `1` under any trigger but `ON_CANDLE_CLOSE`.
|
|
158
|
+
- `bandAtrMultiple` — the veto width. The entry is VOIDED when the confirming close moved at or
|
|
159
|
+
beyond that many ATR against the armed verdict. Strictly `> 0` (zero voids on any adverse move,
|
|
160
|
+
which is a filter, not "off"), and at or below the platform's own entry-deviation gate — read it
|
|
161
|
+
from `get_trading_config_catalog`.
|
|
162
|
+
- `levelSource` — `SWING_HIGH` | `SWING_LOW` | `BOLLINGER_UPPER` | `BOLLINGER_LOWER`, resolved once
|
|
163
|
+
at decision time.
|
|
164
|
+
- `levelOffsetAtrMultiple` — 0–2, UNSIGNED. Direction is implied by the trigger and the verdict, so
|
|
165
|
+
a signed value would invert the trigger's meaning. Must be `0` under a non-level trigger.
|
|
166
|
+
- `validForBars` — 1–24 of the strategy's OWN bars, not minutes: a 1h setup waiting for a retest has
|
|
167
|
+
not failed after fifteen minutes.
|
|
168
|
+
|
|
169
|
+
The legality matrix runs **one way**: all seven keys are always present, so the question is never
|
|
170
|
+
"is it set" but "is it set to something that MEANS anything under this trigger". Leave a dial at its
|
|
171
|
+
inert value rather than setting one the platform will ignore.
|
|
119
172
|
|
|
120
173
|
## Signal weights — the scorecard is a weighted average, budget it
|
|
121
174
|
|
|
@@ -54,10 +54,16 @@ before any billing or LLM call:
|
|
|
54
54
|
|
|
55
55
|
```json
|
|
56
56
|
{ "conditionKey": "NO_EVENT_RISK", "name": "No liquidation tape", "verdict": null, "required": true,
|
|
57
|
+
"exit": false, "clock": "LIVE", "closes": 1,
|
|
57
58
|
"definition": { "kind": "group", "op": "NOT", "members": [
|
|
58
59
|
{ "kind": "clause", "column": { "sectionKey": null, "header": "oiRegime" }, "op": "is", "label": "long liquidation" } ] } }
|
|
59
60
|
```
|
|
60
61
|
|
|
62
|
+
All eight keys are required on every condition — `exit`, `clock` and `closes` included. `clock`
|
|
63
|
+
selects the evidence frame (`LIVE` reads the forming bar, `CLOSE` reads settled bars) and `closes`
|
|
64
|
+
(1–5) is how many consecutive closed bars must hold; `closes` is always `1` under `LIVE`. `exit:
|
|
65
|
+
true` closes open positions the verdict opposes and is legal only under `clock: "CLOSE"`.
|
|
66
|
+
|
|
61
67
|
**Quorum (N_OF).** Robust confirmation instead of a brittle ALL:
|
|
62
68
|
|
|
63
69
|
```json
|
|
@@ -72,11 +78,42 @@ directional carriers; the first TRUE carrier **in declaration order** decides
|
|
|
72
78
|
most-specific first.
|
|
73
79
|
|
|
74
80
|
**Benchmark gate.** Read regime off a `benchmarkTicker` section (all rows are the benchmark's
|
|
75
|
-
values) and `conditionRef` it from every carrier — one place to flip the book risk-on/off.
|
|
81
|
+
values) and `conditionRef` it from every carrier — one place to flip the book risk-on/off. Keep that
|
|
82
|
+
section to indicators: crowd/session metrics and `rank` transforms are refused on a bound section
|
|
83
|
+
(contract 49) — rank the coins on an ordinary section and `conditionRef` the two together.
|
|
76
84
|
|
|
77
85
|
**Required-count trap.** `required: true` at `allocation: 0` on a *signal rule* is rejected
|
|
78
86
|
(contract 34). A required *condition* is independent of signal weights — the two gates stack.
|
|
79
87
|
|
|
88
|
+
## Entry discipline recipes
|
|
89
|
+
|
|
90
|
+
The `entry` object is required on every CREATE, all seven keys, no defaults.
|
|
91
|
+
|
|
92
|
+
| Intent | Object |
|
|
93
|
+
|---|---|
|
|
94
|
+
| Today's behaviour, unchanged | `{ "trigger": "AT_SIGNAL", "confirmTf": "<strategy tf>", "closes": 1, "bandAtrMultiple": 1.0, "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0, "validForBars": 4 }` |
|
|
95
|
+
| Wait for the bar to close, skip a runaway | `{ "trigger": "ON_CANDLE_CLOSE", "confirmTf": "<strategy tf>", "closes": 1, "bandAtrMultiple": 1.0, … }` |
|
|
96
|
+
| Two-close confirmation on the lower rung | `{ "trigger": "ON_CANDLE_CLOSE", "confirmTf": "<lower rung>", "closes": 2, "bandAtrMultiple": 0.75, … }` |
|
|
97
|
+
| Break of the swing high, half an ATR through | `{ "trigger": "STOP_THROUGH_LEVEL", "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0.5, "validForBars": 8, "closes": 1, … }` |
|
|
98
|
+
| Buy the retest of the broken level | `{ "trigger": "ON_RETEST", "levelSource": "SWING_HIGH", "levelOffsetAtrMultiple": 0, "validForBars": 12, "closes": 1, … }` |
|
|
99
|
+
|
|
100
|
+
Bounds: `closes` 1–5 and `1` unless `ON_CANDLE_CLOSE`; `bandAtrMultiple` > 0 and ≤ the platform's
|
|
101
|
+
`defaultMaxEntryDeviationAtrMultiple`; `levelOffsetAtrMultiple` 0–2 unsigned and `0` unless a level
|
|
102
|
+
trigger; `validForBars` 1–24. `confirmTf` is the strategy timeframe or the rung below it, nothing
|
|
103
|
+
else. A meaningful value under a trigger that ignores it is REFUSED, not ignored — that is
|
|
104
|
+
deliberate, so a dial never silently does nothing.
|
|
105
|
+
|
|
106
|
+
## Custom section shape
|
|
107
|
+
|
|
108
|
+
`{ kind, sectionKey, title, benchmarkTicker, notes, columns }`. `benchmarkTicker` and
|
|
109
|
+
`notes` are **required-nullable** — send explicit `null` rather than omitting them, because the
|
|
110
|
+
section is rebuilt whole on save and an omitted key clears the value. **Omit `sectionKey` on a
|
|
111
|
+
CREATE**: the server derives it from the section.
|
|
112
|
+
|
|
113
|
+
A section carries **no `timeframe`** (48.0.0). Its relative columns resolve against the strategy
|
|
114
|
+
timeframe; a column reaches any other timeframe by pinning it — `timeframe: { abs: '4h' }` on the
|
|
115
|
+
column, which it could always do.
|
|
116
|
+
|
|
80
117
|
## Weight matrices (rules)
|
|
81
118
|
|
|
82
119
|
**Conviction pyramid (default).** 1–2 × Critical (the thesis signals, usually `required`),
|
|
@@ -107,6 +144,10 @@ send the full replacement object. Examples validated as canonical defaults: `vol
|
|
|
107
144
|
| Swing breakout (4h) | 0.75 – 1.75 | 2 | 1R | 1.2R, giveback 35, buffer 0.3 | off |
|
|
108
145
|
| Swing trend (4h) | 1.0 – 2.5 | 2 | 1R | 1.5R, giveback 45–55, buffer 0.3 | off |
|
|
109
146
|
|
|
147
|
+
Post-entry invalidation: `decisionInvalidationExitEnabled: true` closes a filled position when a
|
|
148
|
+
**closed** strategy-timeframe candle finishes beyond the decision's invalidation level, reduce-only.
|
|
149
|
+
Bar-close only — the protective stop still owns intrabar moves.
|
|
150
|
+
|
|
110
151
|
Bounds to respect (validated): break-even trigger 0.5–2R; trailing trigger 0–2R step 0.01
|
|
111
152
|
(0 = trail from entry); giveback 25–55%; buffer 0.01–1%; grace ≥ interval; stop-band floor <
|
|
112
153
|
ceiling ≤ the 3×ATR structural cap; RR within the catalog's served range (0.5–3 today). Wider
|
|
@@ -37,8 +37,8 @@ closes while stops, trailing, and time decay keep managing the position intraday
|
|
|
37
37
|
|
|
38
38
|
| TradingView script | Verdict | Port anchor |
|
|
39
39
|
|---|---|---|
|
|
40
|
-
| Squeeze Momentum [LazyBear] / TTM Squeeze |
|
|
41
|
-
| Supertrend / UT Bot Alerts |
|
|
40
|
+
| Squeeze Momentum [LazyBear] / TTM Squeeze | **Direct port** — Keltner is native | `BB_UPPER spread KC_UPPER`, `BB_LOWER spread KC_LOWER`, `bollinger_squeeze` |
|
|
41
|
+
| Supertrend / UT Bot Alerts | **Direct port** for the state; flip still substituted | `ST_LINE`, `ST_DIR`, `EMA5_13` for the flip, position-management trailing |
|
|
42
42
|
| Chandelier Exit | Direct port of the *mechanism* | trailing from entry (`trailingTriggerR: 0`) |
|
|
43
43
|
| MACD + 200 MA filter | Direct process port | `MACD_cross`, `dist_SMA200`, `macd_bull_cross` |
|
|
44
44
|
| Golden / Death Cross | Direct process port | `SMA50_SMA200_spread` + `_trend` |
|
|
@@ -46,7 +46,7 @@ closes while stops, trailing, and time decay keep managing the position intraday
|
|
|
46
46
|
| VWAP reversion | Direct process port | `dist_VWAP`, `dist_VWAP_rank_far` |
|
|
47
47
|
| Donchian / Turtle breakout | Process port (N-bar channel → swing structure) | `zone`, `dist_swingHi`, `sr_resistance_break` |
|
|
48
48
|
| ICT/SMC: FVG + Order Blocks | Direct process port of the zone logic | `STRUCT_ZONES` columns + `structure_*` signals |
|
|
49
|
-
| WaveTrend, QQE, Hull Suite, Ichimoku, Parabolic SAR, Keltner | **
|
|
49
|
+
| WaveTrend, QQE, Hull Suite, Ichimoku, Parabolic SAR, Keltner | **All native since contract 46.1** — port directly | `WT1`/`WT2`, `QQE_RSI_MA`/`QQE_STOP`, `HMA20`, `ICHI_*`, `PSAR`, `KC_*` |
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
@@ -55,7 +55,10 @@ closes while stops, trailing, and time decay keep managing the position intraday
|
|
|
55
55
|
**Source process.** Squeeze ON while Bollinger Bands sit inside Keltner Channels (volatility
|
|
56
56
|
coiled); wait; when the squeeze releases, enter in the direction of the momentum histogram.
|
|
57
57
|
|
|
58
|
-
**Port.** Keltner Channels are
|
|
58
|
+
**Port.** Keltner Channels are native (`KC_UPPER`/`KC_MID`/`KC_LOWER`), so the squeeze is the
|
|
59
|
+
source's own definition: `BB_UPPER spread KC_UPPER` negative AND `BB_LOWER spread KC_LOWER`
|
|
60
|
+
positive is bands-inside-Keltner. The board-relative proxy below remains serviceable but is no
|
|
61
|
+
longer the only option — it substitutes
|
|
59
62
|
*cross-sectional and absolute* Bollinger compression — a stricter, universe-aware read:
|
|
60
63
|
`bbWidthPct_rank_lo lte 10` AND `ADX lt 20` as the `SQUEEZE_ON` building block. Momentum
|
|
61
64
|
direction comes from the MACD histogram trajectory (`MACD_now gt 0` with `MACD_trend rising`
|
|
@@ -75,7 +78,10 @@ Pine script simulates with a plotted line, position management executes: enable
|
|
|
75
78
|
`trailingTriggerR: 0` (trail from entry — the Supertrend/UT Bot behavior), `giveback` as the
|
|
76
79
|
ATR-offset analog (30–40 tight like factor-2 Supertrend, 45–55 loose like factor-3), plus the
|
|
77
80
|
stop band (`minStopLossAtrMultiple`/`max…`) bounding the initial distance. The *flip entry*
|
|
78
|
-
|
|
81
|
+
is native: `ST_DIR` carries the direction and `ST_LINE` the plotted stop. **`ST_DIR` is a
|
|
82
|
+
persisting state, not a flip event** — it reads the same on every bar of a trend, so the FLIP
|
|
83
|
+
itself still needs an event column beside it. The named substitute for the flip is a trend-state
|
|
84
|
+
change:
|
|
79
85
|
`MAalign is "bullish"` (state) with the `EMA5_13 is "Bullish"` cross event as the trigger, and
|
|
80
86
|
`ma_ema_bull_cross` / `ma_ema_aligned_bull` Critical/Important-required in `rules`. Say the
|
|
81
87
|
substitution out loud when presenting the strategy.
|
|
@@ -139,7 +145,8 @@ the book out of single-name traps. Rules: `ma_sma200_above` 3 required, `ma_ema_
|
|
|
139
145
|
**Source process.** In an uptrend (close > 200 SMA), buy panic dips (RSI(2) < 10); exit fast
|
|
140
146
|
(cross of the 5-period average / a few bars).
|
|
141
147
|
|
|
142
|
-
**Port — named substitute.** The catalog carries
|
|
148
|
+
**Port — named substitute.** The catalog carries `RSI14` and `RSI7` only, so there is no `RSI2`;
|
|
149
|
+
`RSI7` is the fastest RSI series
|
|
143
150
|
and `lte 10` on it is a rarer, deeper panic — state that trade-off rather than hiding it.
|
|
144
151
|
`DIP_BUY` verdict UP = `dist_SMA200 gt 0` (ref a required `ABOVE_200`) AND `RSI7 lte 10`.
|
|
145
152
|
Rules: `rsi_oversold` 3 required `{"threshold": 25}` (RSI14 gate tuned toward the fast-dip
|
|
@@ -193,22 +200,36 @@ quorum (`N_OF(2)`: `buyPres gte 0.55`, `RVOL gte 1.2`, `closeChg gt 0`). Rules:
|
|
|
193
200
|
`structure_fvg_approach` / `structure_ob_approach` 3/2 required (their `proximityPct` params
|
|
194
201
|
are the "in the zone" dial), `structure_zone_confluence` 2, `sr_at_support` 2. Stops: tight
|
|
195
202
|
band (0.5–1.5 ATR) — the zone's far edge is the invalidation, and the studio places stops by
|
|
196
|
-
ATR/structure natively. **
|
|
203
|
+
ATR/structure natively. **A grammar limit, not a missing metric** — a clause compares one column
|
|
204
|
+
against a literal, so an ordered sequence of events has no expressible form at all: liquidity
|
|
205
|
+
sweeps, displacement legs,
|
|
197
206
|
killzone clocks, and Turtle-Soup false-break sequencing (ordering between events is outside
|
|
198
207
|
the grammar) — offer this zone-reaction port as the nearest expressible neighbor, labelled.
|
|
199
208
|
|
|
200
|
-
##
|
|
209
|
+
## Now native — do not substitute for these
|
|
201
210
|
|
|
202
|
-
|
|
211
|
+
WaveTrend (`WT1`/`WT2`), QQE (`QQE_RSI_MA`/`QQE_STOP`), Hull (`HMA20`), Ichimoku
|
|
212
|
+
(`ICHI_CONV`/`ICHI_BASE`/`ICHI_SPAN_A`/`ICHI_SPAN_B`/`ICHI_LAG`), Parabolic SAR (`PSAR`), Keltner
|
|
213
|
+
(`KC_UPPER`/`KC_MID`/`KC_LOWER`), daily pivots (`PIVOT_P`/`PIVOT_R1`–`R3`/`PIVOT_S1`–`S3`),
|
|
214
|
+
Williams %R (`WILLR14`), Stochastic RSI (`STOCH_RSI14`), Bollinger boundaries
|
|
215
|
+
(`BB_UPPER`/`BB_LOWER`), ADX components (`DI_PLUS`/`DI_MINUS`). All arrived with contract 46.1 —
|
|
216
|
+
every one of them was listed as inexpressible in this file before it.
|
|
217
|
+
|
|
218
|
+
## Not expressible — the catalog keys this needs
|
|
219
|
+
|
|
220
|
+
The one section where a claim that the catalog LACKS something may live, and every row names the key
|
|
221
|
+
it denies so the claim stays checkable. A claim about the grammar's SHAPE (a clause compares one
|
|
222
|
+
column against a literal; `distance` rejects an `offset`) is permanent and belongs in prose above.
|
|
223
|
+
A claim that a metric is absent belongs here, or nowhere.
|
|
224
|
+
|
|
225
|
+
| Script / primitive | Key the catalog would need | Nearest expressible neighbour |
|
|
203
226
|
|---|---|---|
|
|
204
|
-
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
| Pivot Points (daily) | session pivots | `VWAP` + `swingHi`/`swingLo` distances |
|
|
211
|
-
| Previous-day / previous-week high-low (PDH/PDL) | offset-able levels (`distance` takes no `offset`; clauses are column-vs-literal) | daily swing structure: `zone_1d is "breakout high"`, `dist_swingHi_1d` / `dist_swingLo_1d` |
|
|
227
|
+
| RSI-2 (Connors) | `RSI2` | `RSI7 lte 10` as a named fast-dip substitute |
|
|
228
|
+
|
|
229
|
+
**PDH/PDL** stays inexpressible for a different reason, and the distinction matters: `distance`
|
|
230
|
+
rejects an `offset` and a clause never compares two columns, so the *grammar* has no form for it.
|
|
231
|
+
No metric would fix that. Use the daily swing structure (`zone_1d`, `dist_swingHi_1d`) and name the
|
|
232
|
+
substitution.
|
|
212
233
|
|
|
213
234
|
Never compile a "port" of these under the source's name without the substitution note — a
|
|
214
235
|
player who asked for WaveTrend and silently got Stochastic has no way to learn otherwise.
|