codeloop-mcp-server 0.1.38 → 0.1.40

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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Versions at or above which CodeLoop considers itself "safe" for a
3
+ * given concern (security, data-loss, correctness). If the running
4
+ * MCP server's version is BELOW any entry's `min_version`, the update
5
+ * notice escalates to CRITICAL and tells the agent to surface the
6
+ * notice to the user immediately.
7
+ *
8
+ * How to add an entry
9
+ * -------------------
10
+ * When you ship a release that fixes a security issue, a workspace-
11
+ * level data-loss bug, a privacy regression, or anything else that
12
+ * users running an older version absolutely need to pick up TODAY,
13
+ * append a new entry here in the SAME commit that bumps the package
14
+ * version. Keep the reason short (single sentence, present tense) —
15
+ * it surfaces verbatim in the user-facing notice.
16
+ *
17
+ * Examples:
18
+ * { min_version: "0.1.35", reason: "Refuses to bootstrap into the user's home directory" },
19
+ * { min_version: "0.1.37", reason: "design_compare skips corrupt PNG screenshots" },
20
+ *
21
+ * What NOT to put here
22
+ * --------------------
23
+ * Non-critical features (new tool, faster perf, nicer prose) belong
24
+ * in the changelog only. Critical floors are reserved for "you have
25
+ * a known bad behaviour right now" — they appear on EVERY tool
26
+ * response until the user updates, so over-listing dilutes the
27
+ * signal.
28
+ */
29
+ export interface CriticalFloor {
30
+ /** Versions BELOW this are flagged as critical-outdated. */
31
+ min_version: string;
32
+ /** One-line reason that surfaces in the user notice. */
33
+ reason: string;
34
+ }
35
+ /**
36
+ * The canonical list. Order is not significant — every entry is
37
+ * checked against the running version independently.
38
+ *
39
+ * Keep this list short. Roll up old entries into the most recent
40
+ * floor once everyone has had a reasonable upgrade window
41
+ * (~6 months), so we don't permanently nag users who are running
42
+ * a version that's only a few releases behind the current latest.
43
+ */
44
+ export declare const CRITICAL_FLOORS: CriticalFloor[];
45
+ //# sourceMappingURL=critical_floors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical_floors.d.ts","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAS1C,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Versions at or above which CodeLoop considers itself "safe" for a
3
+ * given concern (security, data-loss, correctness). If the running
4
+ * MCP server's version is BELOW any entry's `min_version`, the update
5
+ * notice escalates to CRITICAL and tells the agent to surface the
6
+ * notice to the user immediately.
7
+ *
8
+ * How to add an entry
9
+ * -------------------
10
+ * When you ship a release that fixes a security issue, a workspace-
11
+ * level data-loss bug, a privacy regression, or anything else that
12
+ * users running an older version absolutely need to pick up TODAY,
13
+ * append a new entry here in the SAME commit that bumps the package
14
+ * version. Keep the reason short (single sentence, present tense) —
15
+ * it surfaces verbatim in the user-facing notice.
16
+ *
17
+ * Examples:
18
+ * { min_version: "0.1.35", reason: "Refuses to bootstrap into the user's home directory" },
19
+ * { min_version: "0.1.37", reason: "design_compare skips corrupt PNG screenshots" },
20
+ *
21
+ * What NOT to put here
22
+ * --------------------
23
+ * Non-critical features (new tool, faster perf, nicer prose) belong
24
+ * in the changelog only. Critical floors are reserved for "you have
25
+ * a known bad behaviour right now" — they appear on EVERY tool
26
+ * response until the user updates, so over-listing dilutes the
27
+ * signal.
28
+ */
29
+ /**
30
+ * The canonical list. Order is not significant — every entry is
31
+ * checked against the running version independently.
32
+ *
33
+ * Keep this list short. Roll up old entries into the most recent
34
+ * floor once everyone has had a reasonable upgrade window
35
+ * (~6 months), so we don't permanently nag users who are running
36
+ * a version that's only a few releases behind the current latest.
37
+ */
38
+ export const CRITICAL_FLOORS = [
39
+ {
40
+ min_version: "0.1.35",
41
+ reason: "Workspace detection fix — pre-0.1.35 builds could silently scaffold CodeLoop into the user's home directory on Windows and misclassify the project as 'node'",
42
+ },
43
+ {
44
+ min_version: "0.1.37",
45
+ reason: "design_compare PNG-corruption fix + gate_check schema fix — pre-0.1.37 builds reported 15/18 design screens at 0% from one corrupt cached PNG, and rejected codeloop_gate_check calls without spec_path/acceptance_path",
46
+ },
47
+ ];
48
+ //# sourceMappingURL=critical_floors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"critical_floors.js","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,8JAA8J;KACvK;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,yNAAyN;KAClO;CACF,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { type CriticalFloor } from "./critical_floors.js";
2
+ export interface UpdateInfo {
3
+ /** Currently-running MCP server version (from package.json). */
4
+ current: string;
5
+ /** Latest version published to npm @latest. */
6
+ latest: string;
7
+ /** True when `latest > current`. */
8
+ is_outdated: boolean;
9
+ /** True when current is below at least one CRITICAL_FLOORS entry. */
10
+ is_critical: boolean;
11
+ /** Combined reason string when is_critical (joined floor reasons). */
12
+ critical_reasons: string[];
13
+ /** Unix ms timestamp of when the check was performed. */
14
+ checked_at: number;
15
+ }
16
+ /**
17
+ * Tiny semver compare. Returns -1 if a < b, 0 if equal, 1 if a > b.
18
+ * Accepts plain semver (X.Y.Z) and ignores pre-release tags — close
19
+ * enough for "is the running server outdated" decisions. Avoids
20
+ * pulling in a dependency.
21
+ */
22
+ export declare function compareSemver(a: string, b: string): number;
23
+ /**
24
+ * Which CRITICAL_FLOORS entries the running version falls below.
25
+ * Exported for tests.
26
+ */
27
+ export declare function findCriticalShortfalls(current: string, floors?: CriticalFloor[]): CriticalFloor[];
28
+ /**
29
+ * Run a single check. Updates the module cache. Exported so tests can
30
+ * call it directly without waiting for the interval.
31
+ */
32
+ export declare function refreshUpdateInfo(): Promise<UpdateInfo | null>;
33
+ /**
34
+ * Synchronous accessor used by the tool-response wrapper. Returns
35
+ * `null` when no check has completed yet (server just booted, or
36
+ * opted out, or every fetch has failed so far) — the wrapper then
37
+ * adds no notice and tool responses look unchanged.
38
+ */
39
+ export declare function getUpdateInfo(): UpdateInfo | null;
40
+ /**
41
+ * Format the user-facing notice block. Two flavours:
42
+ *
43
+ * - Critical: prepended to EVERY tool response. Includes the
44
+ * specific floor reasons so the agent can surface "why this
45
+ * matters" to the user (security fix, data-loss fix, etc.).
46
+ *
47
+ * - Non-critical: a softer notice that still tells the user a
48
+ * newer version is available and how to install it.
49
+ *
50
+ * Returns null when there's nothing to say (up-to-date, or no info
51
+ * yet). The caller is expected to handle a null gracefully.
52
+ */
53
+ export declare function formatUpdateNotice(info?: UpdateInfo | null): string | null;
54
+ /**
55
+ * Wire up the background check from the MCP server entry point. Fire
56
+ * a check now and then every hour. Both timers are unref'd so the
57
+ * process can still exit naturally — they exist only to keep the
58
+ * cached info fresh while the server is alive.
59
+ */
60
+ export declare function startUpdateCheck(): void;
61
+ /**
62
+ * Test hook: clear cached state. Production code should not call this.
63
+ */
64
+ export declare function _resetForTests(): void;
65
+ //# sourceMappingURL=update_check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update_check.d.ts","sourceRoot":"","sources":["../../src/auth/update_check.ts"],"names":[],"mappings":"AA0CA,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAM3E,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,WAAW,EAAE,OAAO,CAAC;IACrB,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACpB;AAkDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAY1D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,aAAa,EAAoB,GAAG,aAAa,EAAE,CAElH;AA0BD;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAmBpE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,UAAU,GAAG,IAAa,GAAG,MAAM,GAAG,IAAI,CAalF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAYvC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAMrC"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Background update checker for the MCP server.
3
+ *
4
+ * Problem
5
+ * -------
6
+ * `mcp.json` spawns the server with `npx -y codeloop-mcp-server@latest`,
7
+ * which resolves the version AT SPAWN TIME. Once Cursor / Claude Code
8
+ * has booted the server, that process stays alive for the lifetime of
9
+ * the IDE session — which is often days. A critical fix shipped to npm
10
+ * mid-session is invisible to the user until they happen to restart
11
+ * their editor.
12
+ *
13
+ * Solution
14
+ * --------
15
+ * On MCP server startup, kick off a background fetch against the npm
16
+ * registry for `codeloop-mcp-server@latest`. Compare the published
17
+ * version against `process.env.npm_package_version` (set by npm when
18
+ * the binary runs) or the package.json read directly. Cache the
19
+ * result in module state with a 1-hour TTL. Tool response wrappers
20
+ * (see `withUpdateNotice` in index.ts) sync-read the cache and
21
+ * prepend a notice to every tool response when the server is
22
+ * outdated. The notice is escalated to CRITICAL when the running
23
+ * version is below any entry in CRITICAL_FLOORS, which lets us call
24
+ * out security / correctness fixes specifically and instruct the
25
+ * agent to surface them to the user immediately.
26
+ *
27
+ * Design rules
28
+ * ------------
29
+ * 1. NEVER block server startup. Fetch is fire-and-forget.
30
+ * 2. NEVER log to stdout (MCP uses stdout for the JSON-RPC channel).
31
+ * Diagnostics go to stderr only.
32
+ * 3. Best-effort: any error is swallowed; the worst case is no notice
33
+ * surfaces. The MCP server keeps working regardless of network.
34
+ * 4. Respect opt-outs: CI=true, NO_UPDATE_NOTIFIER=1,
35
+ * CODELOOP_SKIP_UPDATE_CHECK=1 all disable the check. Mirror the
36
+ * conventions used by cli_cache_warmer.ts and version-check.ts.
37
+ * 5. Hourly background refresh via setInterval, unref'd so it never
38
+ * holds the process open past its natural lifetime.
39
+ */
40
+ import { readFileSync, existsSync } from "node:fs";
41
+ import { join, dirname } from "node:path";
42
+ import { fileURLToPath } from "node:url";
43
+ import { CRITICAL_FLOORS } from "./critical_floors.js";
44
+ const NPM_REGISTRY_URL = "https://registry.npmjs.org/codeloop-mcp-server/latest";
45
+ const FETCH_TIMEOUT_MS = 5_000;
46
+ const REFRESH_MS = 60 * 60 * 1_000; // 1 hour
47
+ let cached = null;
48
+ let refreshTimer = null;
49
+ /**
50
+ * True when one of the canonical opt-out signals is set. Matches the
51
+ * convention used by cli_cache_warmer.ts so users only have to learn
52
+ * one set of env vars to silence ALL CodeLoop background activity.
53
+ */
54
+ function isOptedOut() {
55
+ if (process.env.CODELOOP_SKIP_UPDATE_CHECK === "1")
56
+ return true;
57
+ if (process.env.NO_UPDATE_NOTIFIER === "1")
58
+ return true;
59
+ if (process.env.CI === "true")
60
+ return true;
61
+ return false;
62
+ }
63
+ /**
64
+ * Read the current MCP-server version from the SAME package.json that
65
+ * ships with the binary. We climb out of `auth/` to find it, but
66
+ * accept failure silently — a misplaced binary should never crash the
67
+ * server.
68
+ */
69
+ function readCurrentVersion() {
70
+ if (process.env.npm_package_version) {
71
+ return process.env.npm_package_version;
72
+ }
73
+ try {
74
+ const here = dirname(fileURLToPath(import.meta.url));
75
+ // Walk up looking for the package.json that owns this file. We
76
+ // try a couple of plausible relative paths so the lookup works
77
+ // whether the binary is being executed from `dist/auth/` (npm
78
+ // install layout) or `src/auth/` (local dev / vitest).
79
+ const candidates = [
80
+ join(here, "..", "..", "package.json"),
81
+ join(here, "..", "..", "..", "package.json"),
82
+ ];
83
+ for (const p of candidates) {
84
+ if (!existsSync(p))
85
+ continue;
86
+ const pkg = JSON.parse(readFileSync(p, "utf-8"));
87
+ if (typeof pkg?.name === "string" && pkg.name === "codeloop-mcp-server" && typeof pkg.version === "string") {
88
+ return pkg.version;
89
+ }
90
+ }
91
+ }
92
+ catch {
93
+ /* swallow — best-effort */
94
+ }
95
+ return null;
96
+ }
97
+ /**
98
+ * Tiny semver compare. Returns -1 if a < b, 0 if equal, 1 if a > b.
99
+ * Accepts plain semver (X.Y.Z) and ignores pre-release tags — close
100
+ * enough for "is the running server outdated" decisions. Avoids
101
+ * pulling in a dependency.
102
+ */
103
+ export function compareSemver(a, b) {
104
+ const parse = (v) => {
105
+ const clean = v.replace(/^v/, "").split(/[-+]/)[0];
106
+ const parts = clean.split(".").map((n) => Number.parseInt(n, 10));
107
+ return [parts[0] || 0, parts[1] || 0, parts[2] || 0];
108
+ };
109
+ const [aMaj, aMin, aPat] = parse(a);
110
+ const [bMaj, bMin, bPat] = parse(b);
111
+ if (aMaj !== bMaj)
112
+ return aMaj < bMaj ? -1 : 1;
113
+ if (aMin !== bMin)
114
+ return aMin < bMin ? -1 : 1;
115
+ if (aPat !== bPat)
116
+ return aPat < bPat ? -1 : 1;
117
+ return 0;
118
+ }
119
+ /**
120
+ * Which CRITICAL_FLOORS entries the running version falls below.
121
+ * Exported for tests.
122
+ */
123
+ export function findCriticalShortfalls(current, floors = CRITICAL_FLOORS) {
124
+ return floors.filter((floor) => compareSemver(current, floor.min_version) < 0);
125
+ }
126
+ /**
127
+ * One-shot fetch against npm registry. Returns the latest version
128
+ * string or null on any failure (network down, registry 5xx, JSON
129
+ * malformed, timeout). The caller treats null as "no notice this
130
+ * cycle" — never crashes.
131
+ */
132
+ async function fetchLatestVersion() {
133
+ const controller = new AbortController();
134
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
135
+ try {
136
+ const res = await fetch(NPM_REGISTRY_URL, {
137
+ headers: { Accept: "application/json" },
138
+ signal: controller.signal,
139
+ });
140
+ if (!res.ok)
141
+ return null;
142
+ const body = (await res.json());
143
+ return typeof body.version === "string" ? body.version : null;
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ finally {
149
+ clearTimeout(timer);
150
+ }
151
+ }
152
+ /**
153
+ * Run a single check. Updates the module cache. Exported so tests can
154
+ * call it directly without waiting for the interval.
155
+ */
156
+ export async function refreshUpdateInfo() {
157
+ if (isOptedOut())
158
+ return null;
159
+ const current = readCurrentVersion();
160
+ if (!current)
161
+ return null;
162
+ const latest = await fetchLatestVersion();
163
+ if (!latest)
164
+ return null;
165
+ const isOutdated = compareSemver(current, latest) < 0;
166
+ const shortfalls = findCriticalShortfalls(current);
167
+ const info = {
168
+ current,
169
+ latest,
170
+ is_outdated: isOutdated,
171
+ is_critical: isOutdated && shortfalls.length > 0,
172
+ critical_reasons: shortfalls.map((s) => `${s.min_version}: ${s.reason}`),
173
+ checked_at: Date.now(),
174
+ };
175
+ cached = info;
176
+ return info;
177
+ }
178
+ /**
179
+ * Synchronous accessor used by the tool-response wrapper. Returns
180
+ * `null` when no check has completed yet (server just booted, or
181
+ * opted out, or every fetch has failed so far) — the wrapper then
182
+ * adds no notice and tool responses look unchanged.
183
+ */
184
+ export function getUpdateInfo() {
185
+ return cached;
186
+ }
187
+ /**
188
+ * Format the user-facing notice block. Two flavours:
189
+ *
190
+ * - Critical: prepended to EVERY tool response. Includes the
191
+ * specific floor reasons so the agent can surface "why this
192
+ * matters" to the user (security fix, data-loss fix, etc.).
193
+ *
194
+ * - Non-critical: a softer notice that still tells the user a
195
+ * newer version is available and how to install it.
196
+ *
197
+ * Returns null when there's nothing to say (up-to-date, or no info
198
+ * yet). The caller is expected to handle a null gracefully.
199
+ */
200
+ export function formatUpdateNotice(info = cached) {
201
+ if (!info || !info.is_outdated)
202
+ return null;
203
+ if (info.is_critical) {
204
+ return [
205
+ `⚠️ [CodeLoop] CRITICAL UPDATE AVAILABLE — current ${info.current}, latest ${info.latest}.`,
206
+ `Reasons: ${info.critical_reasons.join("; ")}.`,
207
+ "RESTART Cursor / Claude Code now to pick up the fix (the MCP server is spawned with `npx -y codeloop-mcp-server@latest`, so a clean restart fetches the new version automatically). Tell the user to restart their IDE before continuing — this is not optional for critical fixes.",
208
+ ].join("\n");
209
+ }
210
+ return [
211
+ `[CodeLoop] Update available: ${info.current} → ${info.latest}.`,
212
+ "Restart Cursor / Claude Code at your next break to pick up the new version (the MCP server uses `npx -y codeloop-mcp-server@latest` so a clean restart auto-updates). See https://www.npmjs.com/package/codeloop-mcp-server for the changelog.",
213
+ ].join("\n");
214
+ }
215
+ /**
216
+ * Wire up the background check from the MCP server entry point. Fire
217
+ * a check now and then every hour. Both timers are unref'd so the
218
+ * process can still exit naturally — they exist only to keep the
219
+ * cached info fresh while the server is alive.
220
+ */
221
+ export function startUpdateCheck() {
222
+ if (isOptedOut())
223
+ return;
224
+ // Kick off immediately (don't wait for the first hour).
225
+ void refreshUpdateInfo();
226
+ if (refreshTimer)
227
+ return;
228
+ refreshTimer = setInterval(() => {
229
+ void refreshUpdateInfo();
230
+ }, REFRESH_MS);
231
+ // Don't hold the process open just to keep checking for updates.
232
+ if (typeof refreshTimer.unref === "function") {
233
+ refreshTimer.unref();
234
+ }
235
+ }
236
+ /**
237
+ * Test hook: clear cached state. Production code should not call this.
238
+ */
239
+ export function _resetForTests() {
240
+ cached = null;
241
+ if (refreshTimer) {
242
+ clearInterval(refreshTimer);
243
+ refreshTimer = null;
244
+ }
245
+ }
246
+ //# sourceMappingURL=update_check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update_check.js","sourceRoot":"","sources":["../../src/auth/update_check.ts"],"names":[],"mappings":"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"}