canli-validation-mcp 0.2.0 → 0.3.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 +23 -0
- package/package.json +1 -1
- package/src/server.mjs +21 -2
package/README.md
CHANGED
|
@@ -58,6 +58,29 @@ original SEC response and the record's own boundary sentence: these are accounti
|
|
|
58
58
|
reported to the SEC, not market prices, returns or a recommendation. Companies and concepts
|
|
59
59
|
outside the current release return an error with the available concepts listed.
|
|
60
60
|
|
|
61
|
+
## Compact context (0.3.0)
|
|
62
|
+
|
|
63
|
+
An agent pays for every token a tool returns, including whitespace it never reads. Since 0.3.0
|
|
64
|
+
every result is minified JSON, and a company history returns its observations as one `columns`
|
|
65
|
+
header and one row per observation, with a unit shared by every row stated once. No field is
|
|
66
|
+
dropped: every boundary sentence, accession number, form, filed date and source hash is still in
|
|
67
|
+
the result, and `columns` + `rows` rebuild each observation exactly.
|
|
68
|
+
|
|
69
|
+
Measured with `bench/token_cost.py` on live records (tokenizer: tiktoken `o200k_base`; other
|
|
70
|
+
tokenizers give different absolute counts), 20 observations each:
|
|
71
|
+
|
|
72
|
+
| Record | 0.2.0 (indented) | minified | 0.3.0 (minified, columnar) |
|
|
73
|
+
| --- | ---: | ---: | ---: |
|
|
74
|
+
| Apple, StockholdersEquity | 2,214 | 1,560 (−29.5%) | 1,060 (−52.1%) |
|
|
75
|
+
| Microsoft, CashAndCashEquivalentsAtCarryingValue | 2,231 | 1,574 (−29.4%) | 1,065 (−52.3%) |
|
|
76
|
+
|
|
77
|
+
The validation tools gain the minification only: the live `service_status` envelope measured 593
|
|
78
|
+
tokens indented and 475 minified (−19.9%); their boundary sentences are kept word for word. These
|
|
79
|
+
are measurements of these results, not a claim about any other server.
|
|
80
|
+
|
|
81
|
+
**Breaking change from 0.2.0:** `history.observations` is now `{unit?, columns, rows}` instead of
|
|
82
|
+
an array of objects.
|
|
83
|
+
|
|
61
84
|
## Configuration
|
|
62
85
|
|
|
63
86
|
| Variable | Default | Meaning |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "canli-validation-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server for canlicapital.com's free validation API: deflated Sharpe, CSCV overfitting, paper-evidence conformance, and breadth ceiling, each returned as the full API envelope so the boundary language cannot be dropped.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
package/src/server.mjs
CHANGED
|
@@ -73,11 +73,30 @@ async function callApi(session, { path, method = "GET", body }) {
|
|
|
73
73
|
return { envelope, failed: res.status >= 400 || Boolean(envelope?.error) };
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// Compact context (0.3.0): minified JSON. Indentation is whitespace an agent pays for in tokens and
|
|
77
|
+
// never reads; every field, boundary sentence and provenance value is kept. Measured on the live
|
|
78
|
+
// Apple StockholdersEquity record (README, "Compact context"): 2,214 -> 1,560 tokens minified,
|
|
79
|
+
// 1,056 with the columnar history below.
|
|
76
80
|
const asText = (envelope, failed = false) => ({
|
|
77
|
-
content: [{ type: "text", text: JSON.stringify(envelope
|
|
81
|
+
content: [{ type: "text", text: JSON.stringify(envelope) }],
|
|
78
82
|
...(failed ? { isError: true } : {}),
|
|
79
83
|
});
|
|
80
84
|
|
|
85
|
+
// A history's observations as one header and one row each, instead of every field name repeated
|
|
86
|
+
// on every observation. The column order is fixed so a row can be read without its keys; a unit
|
|
87
|
+
// shared by every row is stated once.
|
|
88
|
+
export const OBSERVATION_COLUMNS = ["end", "val", "accn", "fy", "fp", "form", "filed", "unit"];
|
|
89
|
+
|
|
90
|
+
export function columnarObservations(observations) {
|
|
91
|
+
const units = [...new Set(observations.map((o) => o.unit))];
|
|
92
|
+
const columns = units.length === 1 ? OBSERVATION_COLUMNS.filter((c) => c !== "unit") : OBSERVATION_COLUMNS;
|
|
93
|
+
return {
|
|
94
|
+
...(units.length === 1 ? { unit: units[0] } : {}),
|
|
95
|
+
columns,
|
|
96
|
+
rows: observations.map((o) => columns.map((c) => o[c] ?? null)),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
81
100
|
export async function toolGetKey(session, args) {
|
|
82
101
|
const { label } = parseOrThrow(getKeyInput, args, "get_key");
|
|
83
102
|
if (session.envKey) {
|
|
@@ -199,7 +218,7 @@ export async function toolCompanyFinancialHistory(session, args) {
|
|
|
199
218
|
units: [...new Set((history.observations ?? []).map((o) => o.unit))],
|
|
200
219
|
total_observations: history.observations?.length ?? 0,
|
|
201
220
|
returned: observations.length,
|
|
202
|
-
observations,
|
|
221
|
+
observations: columnarObservations(observations),
|
|
203
222
|
},
|
|
204
223
|
});
|
|
205
224
|
}
|