mcp-context-cost 0.7.0 → 0.9.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 +24 -16
- package/dist/cli.js +27 -12
- package/dist/core/cross-check.d.ts +93 -0
- package/dist/core/cross-check.js +176 -0
- package/dist/sweep/cross-check.d.ts +31 -0
- package/dist/sweep/cross-check.js +342 -0
- package/dist/sweep/docker.d.ts +55 -0
- package/dist/sweep/docker.js +94 -1
- package/dist/sweep/published-stats.d.ts +114 -0
- package/dist/sweep/published-stats.js +383 -0
- package/dist/sweep/regen.js +13 -0
- package/dist/sweep/report.d.ts +9 -0
- package/dist/sweep/report.js +50 -4
- package/dist/sweep/run.js +35 -6
- package/dist/sweep/sweep-all.js +41 -9
- package/package.json +2 -1
package/dist/sweep/sweep-all.js
CHANGED
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
import { readFileSync } from 'node:fs';
|
|
15
15
|
import { parse } from 'yaml';
|
|
16
16
|
import { measureServer } from './run.js';
|
|
17
|
+
import { DockerHarnessFault } from './docker.js';
|
|
17
18
|
import { writeLeaderboard } from './report.js';
|
|
18
19
|
import { appendHistory } from './history.js';
|
|
19
|
-
import { snapshot, verdict, restore } from './harness-guard.js';
|
|
20
|
+
import { FAULT_RATIO, MIN_REGRESSIONS, snapshot, verdict, restore } from './harness-guard.js';
|
|
20
21
|
import { selectShard, shardIndexForDate } from './shard.js';
|
|
21
22
|
function arg(name) {
|
|
22
23
|
const i = process.argv.indexOf(`--${name}`);
|
|
@@ -64,17 +65,31 @@ const prior = snapshot(entries.map((e) => e.name));
|
|
|
64
65
|
const queue = [...entries];
|
|
65
66
|
const summary = {};
|
|
66
67
|
const statuses = new Map();
|
|
68
|
+
// Servers docker itself failed to run — never a measurement (measureServer
|
|
69
|
+
// throws before persisting), so each one's previous record simply stands.
|
|
70
|
+
const dockerFaults = new Map();
|
|
67
71
|
async function worker() {
|
|
68
72
|
for (let e = queue.shift(); e; e = queue.shift()) {
|
|
69
73
|
const started = Date.now();
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
let m;
|
|
75
|
+
try {
|
|
76
|
+
m = await measureServer(e.name, e.command, {
|
|
77
|
+
timeoutMs: (e.timeoutSeconds ?? defaultTimeout) * 1000,
|
|
78
|
+
docker,
|
|
79
|
+
dockerImage: e.dockerImage,
|
|
80
|
+
dummyEnv: e.env ?? [],
|
|
81
|
+
dummyEnvValues: e.envValues,
|
|
82
|
+
needsGit: e.needsGit,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (!(err instanceof DockerHarnessFault))
|
|
87
|
+
throw err;
|
|
88
|
+
dockerFaults.set(e.name, err.message);
|
|
89
|
+
summary[e.name] = 'docker harness fault — not measured; previous record untouched';
|
|
90
|
+
console.log(` ${e.name}: ${summary[e.name]}`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
78
93
|
const secs = ((Date.now() - started) / 1000).toFixed(0);
|
|
79
94
|
statuses.set(e.name, m.status);
|
|
80
95
|
summary[e.name] =
|
|
@@ -85,6 +100,19 @@ async function worker() {
|
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
102
|
await Promise.all(Array.from({ length: Math.max(1, concurrency) }, () => worker()));
|
|
103
|
+
// A docker fault on most of the slice is the harness-fault story with an
|
|
104
|
+
// earlier symptom — the guard below can't see it (nothing regressed on disk;
|
|
105
|
+
// the throws happened before anything was written), so it is judged here by
|
|
106
|
+
// the guard's own thresholds. Below them, the sweep publishes what it did
|
|
107
|
+
// measure and the faulted servers wait for the next cycle.
|
|
108
|
+
if (dockerFaults.size >= MIN_REGRESSIONS && dockerFaults.size / entries.length >= FAULT_RATIO) {
|
|
109
|
+
console.error(`\nHARNESS FAULT — docker could not run for ${dockerFaults.size} of ${entries.length} servers; ` +
|
|
110
|
+
`refusing to publish this sweep.\n` +
|
|
111
|
+
[...dockerFaults].map(([n, msg]) => ` ${n}: ${msg}`).join('\n') +
|
|
112
|
+
`\n Nothing was overwritten — every previous record stands. ` +
|
|
113
|
+
`Check the Docker daemon and registry path, then re-run.`);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
88
116
|
// Before publishing anything: is this sweep a statement about the servers, or
|
|
89
117
|
// about the machine that measured them?
|
|
90
118
|
const v = verdict(prior, statuses);
|
|
@@ -105,4 +133,8 @@ if (v.fault) {
|
|
|
105
133
|
writeLeaderboard(doc.servers);
|
|
106
134
|
const h = appendHistory();
|
|
107
135
|
const measured = Object.values(summary).filter((s) => s.includes('tokens')).length;
|
|
136
|
+
if (dockerFaults.size > 0) {
|
|
137
|
+
console.warn(`\nDOCKER FAULT on ${[...dockerFaults.keys()].join(', ')} — not measured this sweep; ` +
|
|
138
|
+
`previous records untouched. The next cycle re-attempts ${dockerFaults.size === 1 ? 'it' : 'them'}.`);
|
|
139
|
+
}
|
|
108
140
|
console.log(`done: ${measured}/${entries.length} measured; leaderboard + history (${h.rows} rows) regenerated`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-context-cost",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Measure what your MCP servers cost in context tokens — audit your own config, or badge the server you publish",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"test:badge": "./upstream/tests/badge-test.sh",
|
|
39
39
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.tools.json",
|
|
40
40
|
"adoption": "tsx tools/measure-adoption.ts",
|
|
41
|
+
"cross-check": "tsx src/sweep/cross-check.ts",
|
|
41
42
|
"divergence": "tsx tools/measure-divergence.ts",
|
|
42
43
|
"session-start": "tsx src/sweep/session-start.ts",
|
|
43
44
|
"sweep": "tsx src/sweep/run.ts",
|