@battlegrid/mcp-server 32.0.36 → 32.0.38
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
|
@@ -38,6 +38,57 @@ Seeing package `31.x` alongside handshake `battlegrid@33.x` — the package **be
|
|
|
38
38
|
|
|
39
39
|
**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.
|
|
40
40
|
|
|
41
|
+
## Contract history — v136.1 (spot facts per bar: each venue's close and buy share, the composite's flow, and Bybit)
|
|
42
|
+
|
|
43
|
+
**Additive at v136.1: six metrics and a study, and served values move.** v136.1 is the contract on top of v136.
|
|
44
|
+
Nothing a client sends is refused that v136 accepted. Reconnect the proxy, or restart it, so discovery reads the widened
|
|
45
|
+
vocabulary.
|
|
46
|
+
|
|
47
|
+
### Widened input — new metrics and a study
|
|
48
|
+
|
|
49
|
+
- **`SPOT_CLOSE_BYB`** (`bybClose`): Bybit's spot close, USDT-quoted, in the coin's own unit.
|
|
50
|
+
- **`BUY_PRES_CB`, `BUY_PRES_BN` and `BUY_PRES_BYB`** (`cbBuyPres`, `bnBuyPres`, `bybBuyPres`): each venue's buy share
|
|
51
|
+
of its spot volume in the bar's period (0–1), from the venue's taker sides.
|
|
52
|
+
- **`SPOT_AVG_TRADE`** (`spotAvgTrade`): the composite spot volume per trade. **`SPOT_DOMINANCE`** (`spotDom`): the
|
|
53
|
+
composite spot volume as a share of composite spot plus the bar's perp volume. Both are absent where a listed venue
|
|
54
|
+
did not cover the period.
|
|
55
|
+
- **The `spotFlow` study** joins the vocabulary and carries `SPOT_CVD` with them. The metric-key enum widens on every
|
|
56
|
+
input and output that carries it.
|
|
57
|
+
|
|
58
|
+
### Widened construction — spot reads are per bar
|
|
59
|
+
|
|
60
|
+
- **`SPOT_CLOSE_CB`, `SPOT_CLOSE_BN` and `SPOT_CVD` read each bar's spot facts at the column's rung**, where they read
|
|
61
|
+
one value per frame, so each takes a trajectory and a relational operand: `CLOSE × spread(SPOT_CLOSE_CB)` →
|
|
62
|
+
`trajectory` constructs.
|
|
63
|
+
- **A composite read** (`SPOT_AVG_TRADE`, `SPOT_DOMINANCE`, `SPOT_CVD`) reads completed bars only, and its column says
|
|
64
|
+
so.
|
|
65
|
+
- **The per-venue buy shares and `SPOT_DOMINANCE` rank exchange-wide**, as do five declared venue spreads:
|
|
66
|
+
`SPOT_CLOSE_CB × spread(SPOT_CLOSE_BN)`, `CLOSE × spread(SPOT_CLOSE_CB)`, `CLOSE × spread(SPOT_CLOSE_BN)`,
|
|
67
|
+
`CLOSE × spread(SPOT_CLOSE_BYB)` and `BUY_PRES_CB × spread(BUY_PRES_BN)`.
|
|
68
|
+
|
|
69
|
+
### Widened output enum
|
|
70
|
+
|
|
71
|
+
- **`BarFamily` gains `SPOT_COMPOSITE`** on every output that names the family of an input a decision waited on or
|
|
72
|
+
missed: a decision's spot read stands on the coin's composite at its due bar. A coin whose data profile withholds the
|
|
73
|
+
spot tape stands its spot conditions on its own bar, so they decide `INSTRUMENT` rather than wait.
|
|
74
|
+
|
|
75
|
+
### Changed values — the same schema serves a different number
|
|
76
|
+
|
|
77
|
+
- **A venue close reads the column rung's bar close**, where it read the newest `1m` close within 15 minutes.
|
|
78
|
+
Confirmed reads the closed bar's close; Developing reads the venue's forming bar, absent once it is older than the
|
|
79
|
+
coin's spot-tape freshness target; a venue that did not cover the period reads null.
|
|
80
|
+
- **`SPOT_CVD`'s `value` is the same number at the anchor.** Its `trajectory` and `efficiency` read per-bar values at
|
|
81
|
+
the rung where they read `1m` samples; a thousand-unit ticker such as `kPEPE` reads in its own unit (÷1000); and a
|
|
82
|
+
span every listed venue covered without a trade reads `0` where it read null.
|
|
83
|
+
- **`PERP_SPOT_*` read the composite `cvd` at the two newest closed anchor bars**, both halves on one clock.
|
|
84
|
+
- **No perp metric, settled indicator or stored header moves**; `cbClose_bnClose_spread` keeps its header.
|
|
85
|
+
`toolCount` stays 149.
|
|
86
|
+
|
|
87
|
+
### Digest move
|
|
88
|
+
|
|
89
|
+
- **`vocabularyDigest` and the authoring catalog digest move** with the six metrics and the study. A client caching
|
|
90
|
+
vocabulary against either re-reads `list_strategy_vocabulary`.
|
|
91
|
+
|
|
41
92
|
## Contract history — v136 (one ranked universe: rank within a category, select coins by a ranked metric)
|
|
42
93
|
|
|
43
94
|
**Breaking at v136: `get_top_ranked_coins` is retired, and one value moves.** v136 is the contract on top of v135.2.
|
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.
|
|
50
|
+
export declare const PACKAGE_VERSION = "32.0.38";
|
|
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.
|
|
52
|
+
export const PACKAGE_VERSION = '32.0.38';
|
|
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
package/skills/EXPORT.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generator": "battlegrid-app/server/scripts/export-mcp-skills.mjs",
|
|
3
|
-
"contractVersion": "
|
|
3
|
+
"contractVersion": "136.1.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
|
-
"battlegrid-market-analysis/SKILL.md": "
|
|
9
|
+
"battlegrid-market-analysis/SKILL.md": "e50a63492c635af9e8748561148efd7e1d9aafdfb843acc657e557670b2f55e4",
|
|
10
10
|
"battlegrid-officers/SKILL.md": "0e5b4fd7a11fc1b6643eecd0008dfe1528b915ee00d0a99be9aca1e3934d57f7",
|
|
11
11
|
"battlegrid-officers/references/officer-stage-examples.md": "ef46ba26f4b36c9964b5bde95fdf98e5952c3786b77be5f136056cac792f0aec",
|
|
12
12
|
"battlegrid-radar-deployment/SKILL.md": "cd058d887e1342f42ce855708178d5f746400835a204e92238b63ec1fe57bf30",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"battlegrid-strategy-doctor/SKILL.md": "24c2208cf6832f1fc34e1b1c52acd8dae10f56b9860aaf27b450a62a9fb74634",
|
|
18
18
|
"battlegrid-strategy-examples/SKILL.md": "cbbc7a7271aaa9f530a11d91511f4bf35a9632aa3ab67ecd996975c65ae72625",
|
|
19
19
|
"battlegrid-strategy-examples/references/playbooks.md": "59996c37eea08e7ce398e49304171939e55c968400a1603597d6737faf9e1771",
|
|
20
|
-
"battlegrid-strategy-examples/references/recipes.md": "
|
|
20
|
+
"battlegrid-strategy-examples/references/recipes.md": "e1fbd1a3d1b2ef1408fef8642032c3e131954aedec6bdcefa3af6a655948e392",
|
|
21
21
|
"battlegrid-strategy-examples/references/tradingview-ports.md": "00f2ba287ff8fadf356273f61ad19630cceb3a706018c2088be40570ff1a899d",
|
|
22
22
|
"battlegrid-trade-analysis/SKILL.md": "140d847f24e98845736d4f0c2e72b318a4d235413f72f072d2fe6d0daa5f64db",
|
|
23
23
|
"battlegrid-trade-proposal/SKILL.md": "bf8f3794478cdecc989020bd775c3c91744f72b440b1a90f88f6700c9a61ca24"
|
|
@@ -27,8 +27,14 @@ Run these in order. Skip a step only when the player's question makes it irrelev
|
|
|
27
27
|
2. **Market context.** `get_market_context` — this carries the breadth, funding and open-interest
|
|
28
28
|
picture. Funding and OI are the two figures most often skipped and most often decisive: crowded
|
|
29
29
|
positioning is the difference between "trend" and "trend about to be squeezed". Report both.
|
|
30
|
-
3. **Leaders and laggards.**
|
|
31
|
-
|
|
30
|
+
3. **Leaders and laggards.** One ranked `preview_strategy_report` per end, each returning the coins
|
|
31
|
+
with their rows, so no per-coin follow-up is needed: `coinSelection: { mode: "ranked", limit: 10,
|
|
32
|
+
category: "ALL", rankBy: { metric: "ROC12", ordering: "hi" } }` for the leaders and `ordering: "lo"`
|
|
33
|
+
for the laggards, with `detail: "concise"` and `source: { kind: "FIELDS", timeframe, sections:
|
|
34
|
+
[{ kind: "platform", sectionKey: "includeRelativeStrength" }] }`. `CLOSE_CHANGE` under `"far"` names
|
|
35
|
+
the biggest movers in either direction. Omit `category` and the cohort is crypto only. Name the
|
|
36
|
+
actual coins at both ends, not just "strength in majors". A laggard list is as informative as a
|
|
37
|
+
leader list and is usually omitted.
|
|
32
38
|
3b. **Many coins on the same indicators — one call, not one per coin.** When the answer needs the
|
|
33
39
|
indicator modules ACROSS a set of coins (comparing RSI, funding or volatility over the leaders,
|
|
34
40
|
over a category, over the session pool), use `preview_strategy_report`: one section JSON per
|
|
@@ -15,6 +15,7 @@ rather than events all live there. This document assumes them.
|
|
|
15
15
|
**Contents**
|
|
16
16
|
- Column recipes
|
|
17
17
|
- Cross detection
|
|
18
|
+
- Recency and structure
|
|
18
19
|
- Board-relative rank recipes
|
|
19
20
|
- Cross-venue and perp/spot basis
|
|
20
21
|
- Crowd positioning
|
|
@@ -48,6 +49,85 @@ An event column is a trigger inside a carrier, never a standing state; pair it w
|
|
|
48
49
|
state for regime. The skill body's `## Header grammar` states that rule and is the authority on it —
|
|
49
50
|
a condition that reads a `crossDetect` column as a state reads FALSE on nearly every bar, because a null reads FALSE.
|
|
50
51
|
|
|
52
|
+
## Recency and structure
|
|
53
|
+
|
|
54
|
+
"How long since", "the first time in N bars" and "how many lower highs" are holds over a clause — no
|
|
55
|
+
transform counts bars since an event, and no column is built over a condition. Each recipe below is a
|
|
56
|
+
whole condition; adapt its clause, its numbers and its `required`, and keep its shape.
|
|
57
|
+
|
|
58
|
+
**Counting.** Bars since A counts the bar being decided as 0, so "A within n" — the clause held
|
|
59
|
+
`{ "atLeast": 1, "of": n }` — is "bars since A is at most n − 1". This counts bars since a clause read
|
|
60
|
+
TRUE; it is not a swing pivot's age, which `fractalHiAgo` / `fractalLoAgo` count differently (see
|
|
61
|
+
`tradingview-ports.md`).
|
|
62
|
+
|
|
63
|
+
**Absence.** A read that ran and found no value reads FALSE (the skill body, `## Conditions`), so a `NOT`
|
|
64
|
+
over it reads TRUE on a coin with no value — a listing younger than its indicator's warm-up, for one.
|
|
65
|
+
Every recipe that holds a `NOT` therefore sits inside an `ALL` with a member that needs the value, so a
|
|
66
|
+
recipe copied as a required gate reads FALSE, never TRUE, when the value is missing.
|
|
67
|
+
|
|
68
|
+
**Bars since A is under n** — RSI was oversold within the last 5 closes:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{ "conditionKey": "OVERSOLD_WITHIN_5", "name": "Oversold within 5 closes", "verdict": null, "required": true, "exitSide": null,
|
|
72
|
+
"definition": { "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 1, "of": 5 } } }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Bars since A is at least n** — RSI has not been oversold for 5 closes. The `NOT` alone would read TRUE
|
|
76
|
+
on a coin with no RSI, so `RSI14_now gte 0` requires the value to be there:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "conditionKey": "NOT_OVERSOLD_FOR_5", "name": "Not oversold for 5 closes", "verdict": null, "required": true, "exitSide": null,
|
|
80
|
+
"definition": { "kind": "group", "op": "ALL", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
81
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "gte", "value": 0, "hold": { "atLeast": 1, "of": 1 } },
|
|
82
|
+
{ "kind": "group", "op": "NOT", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
83
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 1, "of": 5 } } ] } ] } }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Bars since A is between a and b** — RSI was last oversold 3 to 6 closes ago: within `b + 1` = 7, and
|
|
87
|
+
not within `a` = 3. The `NOT` reads TRUE with no value, and the first member then reads FALSE:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{ "conditionKey": "OVERSOLD_3_TO_6_BARS_AGO", "name": "Oversold 3 to 6 closes ago", "verdict": null, "required": true, "exitSide": null,
|
|
91
|
+
"definition": { "kind": "group", "op": "ALL", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
92
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 1, "of": 7 } },
|
|
93
|
+
{ "kind": "group", "op": "NOT", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
94
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 1, "of": 3 } } ] } ] } }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**The first cross above L in N bars** — RSI crossed above 50 on the decided bar, and read at or below 50
|
|
98
|
+
on the 5 closes before it: the cross, and `lte 50` on at least `N − 1` of the newest `N` = 6 closes (the
|
|
99
|
+
decided bar itself reads above 50). A cross is an edge, so it holds Once; the level clause carries the
|
|
100
|
+
count:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{ "conditionKey": "FIRST_CROSS_ABOVE_50_IN_6", "name": "First cross above 50 in 6 closes", "verdict": null, "required": true, "exitSide": null,
|
|
104
|
+
"definition": { "kind": "group", "op": "ALL", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
105
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "crossesAbove", "value": 50, "hold": { "atLeast": 1, "of": 1 } },
|
|
106
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lte", "value": 50, "hold": { "atLeast": 5, "of": 6 } } ] } }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**The first A in N bars, for an A that is not an edge** — RSI is oversold now and was not oversold on 2
|
|
110
|
+
or more of the newest 6 closes, so this is its first oversold close in 6. With no value the first member
|
|
111
|
+
reads FALSE:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{ "conditionKey": "FIRST_OVERSOLD_IN_6", "name": "First oversold close in 6", "verdict": null, "required": true, "exitSide": null,
|
|
115
|
+
"definition": { "kind": "group", "op": "ALL", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
116
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 1, "of": 1 } },
|
|
117
|
+
{ "kind": "group", "op": "NOT", "hold": { "atLeast": 1, "of": 1 }, "members": [
|
|
118
|
+
{ "kind": "clause", "column": { "sectionKey": null, "header": "RSI14_now" }, "op": "lt", "value": 30, "hold": { "atLeast": 2, "of": 6 } } ] } ] } }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**k lower highs in N bars** — the published swing high stepped down on at least 2 of the newest 8 closes,
|
|
122
|
+
over a `{ "metric": "SWING_FRACTAL_HIGH", "transformId": "value", "timeframe": { "rel": "anchor" } }`
|
|
123
|
+
column (header `fractalHi`). `decreased` is not an edge, so it counts like any clause; it counts each
|
|
124
|
+
step down of the decided pivot, which is a lower high against the pivot before it:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{ "conditionKey": "TWO_LOWER_HIGHS_IN_8", "name": "Two lower highs in 8 closes", "verdict": null, "required": true, "exitSide": null,
|
|
128
|
+
"definition": { "kind": "clause", "column": { "sectionKey": null, "header": "fractalHi" }, "op": "decreased", "hold": { "atLeast": 2, "of": 8 } } }
|
|
129
|
+
```
|
|
130
|
+
|
|
51
131
|
## Board-relative rank recipes
|
|
52
132
|
|
|
53
133
|
`rank` turns any column into an ordinal across the scanned board. Ordering semantics: `hi` most
|