@n24q02m/mcp-core 1.10.0 → 1.11.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/build/auth/credential-form.d.ts +38 -0
- package/build/auth/credential-form.d.ts.map +1 -1
- package/build/auth/credential-form.js +13 -0
- package/build/auth/credential-form.js.map +1 -1
- package/build/auth/local-oauth-app.d.ts +24 -1
- package/build/auth/local-oauth-app.d.ts.map +1 -1
- package/build/auth/local-oauth-app.js +110 -1
- package/build/auth/local-oauth-app.js.map +1 -1
- package/build/lifecycle/lock.d.ts +76 -12
- package/build/lifecycle/lock.d.ts.map +1 -1
- package/build/lifecycle/lock.js +190 -34
- package/build/lifecycle/lock.js.map +1 -1
- package/build/relay/session.d.ts +12 -0
- package/build/relay/session.d.ts.map +1 -0
- package/build/relay/session.js +55 -0
- package/build/relay/session.js.map +1 -0
- package/build/relay/tool-helpers.d.ts +56 -0
- package/build/relay/tool-helpers.d.ts.map +1 -0
- package/build/relay/tool-helpers.js +60 -0
- package/build/relay/tool-helpers.js.map +1 -0
- package/build/storage/config-file.js +1 -1
- package/build/storage/config-file.js.map +1 -1
- package/build/storage/session-lock.js +1 -1
- package/build/storage/session-lock.js.map +1 -1
- package/build/transport/cache.d.ts +19 -0
- package/build/transport/cache.d.ts.map +1 -0
- package/build/transport/cache.js +67 -0
- package/build/transport/cache.js.map +1 -0
- package/build/transport/smart-stdio.d.ts +64 -0
- package/build/transport/smart-stdio.d.ts.map +1 -1
- package/build/transport/smart-stdio.js +170 -0
- package/build/transport/smart-stdio.js.map +1 -1
- package/package.json +1 -1
package/build/lifecycle/lock.js
CHANGED
|
@@ -1,30 +1,106 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lock-file lifecycle helpers
|
|
2
|
+
* Lock-file lifecycle helpers (D9 — hybrid TTL extension).
|
|
3
3
|
*
|
|
4
|
-
* The lock file written by `runLocalServer`
|
|
4
|
+
* The lock file written by `runLocalServer` may contain 4 lines (legacy
|
|
5
|
+
* v1) or 6 lines (D9 modern):
|
|
5
6
|
*
|
|
6
7
|
* ```
|
|
7
8
|
* {pid}
|
|
8
9
|
* {port}
|
|
9
10
|
* {token}
|
|
10
|
-
* {
|
|
11
|
+
* {spawnedAt_iso8601_utc}
|
|
12
|
+
* {credState} # "configured" | "unconfigured" (D9)
|
|
13
|
+
* {lastActivityAt_iso8601_utc} # bumped by daemon refresh loop (D9)
|
|
11
14
|
* ```
|
|
12
15
|
*
|
|
13
16
|
* Stale locks are detected when *any* of:
|
|
14
17
|
* - file has legacy 3-line format (no timestamp) → migrate by deletion
|
|
15
|
-
* - timestamp older than
|
|
18
|
+
* - timestamp older than the applicable TTL
|
|
19
|
+
* - configured credState → 24h
|
|
20
|
+
* - unconfigured credState → 30 min
|
|
16
21
|
* - writing PID does not exist on this host
|
|
17
22
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
23
|
+
* Dead-PID locks are reaped immediately. Past-TTL idle setup daemons
|
|
24
|
+
* (unconfigured) are terminated; configured daemons past TTL get their
|
|
25
|
+
* lock unlinked but the process is left alone (parity with pre-D9 sweep
|
|
26
|
+
* behavior so a long-running daemon never gets SIGKILL'd by a sweep
|
|
27
|
+
* race).
|
|
28
|
+
*
|
|
29
|
+
* TypeScript port of core-py's `mcp_core.lifecycle.lock`. Behaviour and
|
|
30
|
+
* TTL constants kept identical for cross-language parity.
|
|
20
31
|
*/
|
|
21
32
|
import { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
22
33
|
import { homedir } from 'node:os';
|
|
23
34
|
import { join } from 'node:path';
|
|
35
|
+
// Self-import so `sweepStaleLocks` can resolve `lockDir`/`isAlive`/
|
|
36
|
+
// `terminateDaemon` through the module namespace at call time. This
|
|
37
|
+
// makes `vi.spyOn(lockModule, '<name>').mockReturnValue(...)` actually
|
|
38
|
+
// intercept the helper from inside the sweep loop — without this
|
|
39
|
+
// indirection, the closure-captured local binding ignores spies and
|
|
40
|
+
// test mocks become silent no-ops.
|
|
41
|
+
import * as self from './lock.js';
|
|
24
42
|
export const DEFAULT_LOCK_TTL_HOURS = 24;
|
|
43
|
+
/** D9 hybrid TTL constants — selected by `credState` in `sweepStaleLocks`. */
|
|
44
|
+
export const LIFECYCLE_TTL_CONFIGURED_MS = 24 * 3600 * 1000;
|
|
45
|
+
export const LIFECYCLE_TTL_UNCONFIGURED_MS = 30 * 60 * 1000;
|
|
25
46
|
export function locksDir(root) {
|
|
26
47
|
return root ?? join(homedir(), '.config', 'mcp', 'locks');
|
|
27
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* No-arg lock-dir resolver — D9 sweep tests `vi.spyOn(lockModule, 'lockDir')`
|
|
51
|
+
* to redirect into a temp directory without threading a `root` arg.
|
|
52
|
+
*/
|
|
53
|
+
export function lockDir() {
|
|
54
|
+
return locksDir();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Serialize `LockMetadata` to the 6-line on-disk format. Trailing
|
|
58
|
+
* newline included so writes always end in `\n` and the parser's
|
|
59
|
+
* `lines.length` checks behave deterministically.
|
|
60
|
+
*/
|
|
61
|
+
export function serializeLock(meta) {
|
|
62
|
+
return [
|
|
63
|
+
String(meta.pid),
|
|
64
|
+
String(meta.port),
|
|
65
|
+
meta.token,
|
|
66
|
+
meta.spawnedAt.toISOString(),
|
|
67
|
+
meta.credState,
|
|
68
|
+
meta.lastActivityAt.toISOString(),
|
|
69
|
+
''
|
|
70
|
+
].join('\n');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse the textual lock payload into `LockMetadata`. Accepts 4-line
|
|
74
|
+
* legacy, 5-line transitional, and 6-line D9 modern formats. Throws on
|
|
75
|
+
* fewer than 4 lines or unparseable timestamp / pid / port.
|
|
76
|
+
*/
|
|
77
|
+
export function parseLock(raw) {
|
|
78
|
+
const lines = raw.replace(/\n+$/, '').split('\n');
|
|
79
|
+
if (lines.length < 4)
|
|
80
|
+
throw new Error(`lock file too few lines: ${lines.length}`);
|
|
81
|
+
const pid = Number(lines[0]);
|
|
82
|
+
const port = Number(lines[1]);
|
|
83
|
+
if (!Number.isInteger(pid) || !Number.isInteger(port)) {
|
|
84
|
+
throw new Error(`lock file has non-integer pid/port`);
|
|
85
|
+
}
|
|
86
|
+
const token = lines[2];
|
|
87
|
+
const spawnedAt = new Date(lines[3]);
|
|
88
|
+
if (Number.isNaN(spawnedAt.getTime())) {
|
|
89
|
+
throw new Error(`lock file has unparseable spawnedAt`);
|
|
90
|
+
}
|
|
91
|
+
let credState = 'configured';
|
|
92
|
+
let lastActivityAt = spawnedAt;
|
|
93
|
+
if (lines.length >= 6) {
|
|
94
|
+
credState = lines[4];
|
|
95
|
+
lastActivityAt = new Date(lines[5]);
|
|
96
|
+
if (Number.isNaN(lastActivityAt.getTime()))
|
|
97
|
+
lastActivityAt = spawnedAt;
|
|
98
|
+
}
|
|
99
|
+
else if (lines.length === 5) {
|
|
100
|
+
credState = lines[4];
|
|
101
|
+
}
|
|
102
|
+
return { pid, port, token, spawnedAt, credState, lastActivityAt, createdAt: spawnedAt };
|
|
103
|
+
}
|
|
28
104
|
export function parseLockMetadata(path) {
|
|
29
105
|
if (!existsSync(path))
|
|
30
106
|
return null;
|
|
@@ -36,34 +112,29 @@ export function parseLockMetadata(path) {
|
|
|
36
112
|
return null;
|
|
37
113
|
}
|
|
38
114
|
const lines = content.trim().split('\n');
|
|
115
|
+
// Pre-D9 callers expect null for legacy 3-line format. The new
|
|
116
|
+
// `parseLock` instead throws — adapter logic here keeps both
|
|
117
|
+
// contracts: legacy / corrupt -> null; valid 4/5/6-line -> populated.
|
|
39
118
|
if (lines.length < 4)
|
|
40
119
|
return null;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (pidStr === undefined || portStr === undefined || tsStr === undefined)
|
|
46
|
-
return null;
|
|
47
|
-
const pid = Number(pidStr);
|
|
48
|
-
const port = Number(portStr);
|
|
49
|
-
if (!Number.isInteger(pid) || !Number.isInteger(port))
|
|
50
|
-
return null;
|
|
51
|
-
const createdAt = new Date(tsStr);
|
|
52
|
-
if (Number.isNaN(createdAt.getTime()))
|
|
120
|
+
try {
|
|
121
|
+
return parseLock(content);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
53
124
|
return null;
|
|
54
|
-
|
|
125
|
+
}
|
|
55
126
|
}
|
|
56
127
|
export function isLockExpired(path, ttlHours = DEFAULT_LOCK_TTL_HOURS) {
|
|
57
128
|
const md = parseLockMetadata(path);
|
|
58
129
|
if (md === null)
|
|
59
130
|
return true;
|
|
60
|
-
const ageMs = Date.now() - md.
|
|
131
|
+
const ageMs = Date.now() - md.spawnedAt.getTime();
|
|
61
132
|
return ageMs > ttlHours * 3600 * 1000;
|
|
62
133
|
}
|
|
63
134
|
/**
|
|
64
135
|
* Cross-platform PID liveness check via `process.kill(pid, 0)`. Best-effort.
|
|
65
136
|
* Returns false on EPERM (different-user processes) so sweep does not steal
|
|
66
|
-
* locks owned by other users.
|
|
137
|
+
* locks owned by other users. Pre-D9 entry point — kept for backward compat.
|
|
67
138
|
*/
|
|
68
139
|
export function isPidAlive(pid) {
|
|
69
140
|
if (pid <= 0)
|
|
@@ -80,17 +151,60 @@ export function isPidAlive(pid) {
|
|
|
80
151
|
}
|
|
81
152
|
}
|
|
82
153
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
154
|
+
* Liveness check on a parsed `LockMetadata`. D9 sweep tests
|
|
155
|
+
* `vi.spyOn(lockModule, 'isAlive')` to control the alive/dead branch
|
|
156
|
+
* without needing a real PID. Wraps `isPidAlive` so the underlying
|
|
157
|
+
* cross-platform logic stays in one place.
|
|
158
|
+
*/
|
|
159
|
+
export function isAlive(meta) {
|
|
160
|
+
return isPidAlive(meta.pid);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Kill the lock owner. D9 sweep tests `vi.spyOn(lockModule, 'terminateDaemon')`
|
|
164
|
+
* to assert the unconfigured-TTL branch invokes termination, without
|
|
165
|
+
* killing real PIDs. Used by `sweepStaleLocks` when an unconfigured
|
|
166
|
+
* daemon's idle TTL elapses.
|
|
167
|
+
*/
|
|
168
|
+
export function terminateDaemon(pid) {
|
|
169
|
+
if (pid <= 0)
|
|
170
|
+
return;
|
|
171
|
+
try {
|
|
172
|
+
process.kill(pid, 'SIGKILL');
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
/* ignore */
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Refresh `spawnedAt` of an existing lock file. Silent no-op on legacy /
|
|
180
|
+
* malformed files so callers don't need try/except.
|
|
85
181
|
*
|
|
86
182
|
* Padded to 512 bytes so on-disk size stays stable while a Windows
|
|
87
183
|
* byte-range lock is held past the metadata region (parity with core-py).
|
|
184
|
+
* Preserves the on-disk line count: a 4-line legacy lock stays 4-line
|
|
185
|
+
* after refresh; a 6-line modern lock stays 6-line (with both `spawnedAt`
|
|
186
|
+
* and `lastActivityAt` bumped).
|
|
88
187
|
*/
|
|
89
188
|
export function refreshLockTimestamp(path) {
|
|
90
189
|
const md = parseLockMetadata(path);
|
|
91
190
|
if (md === null)
|
|
92
191
|
return;
|
|
93
|
-
|
|
192
|
+
let raw;
|
|
193
|
+
try {
|
|
194
|
+
raw = readFileSync(path, { encoding: 'utf-8' });
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const lineCount = raw.trim().split('\n').length;
|
|
200
|
+
const now = new Date().toISOString();
|
|
201
|
+
let payload;
|
|
202
|
+
if (lineCount >= 6) {
|
|
203
|
+
payload = `${md.pid}\n${md.port}\n${md.token}\n${now}\n${md.credState}\n${now}\n`;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
payload = `${md.pid}\n${md.port}\n${md.token}\n${now}\n`;
|
|
207
|
+
}
|
|
94
208
|
try {
|
|
95
209
|
writeFileSync(path, payload.padEnd(512, ' '), { encoding: 'utf-8' });
|
|
96
210
|
}
|
|
@@ -99,14 +213,18 @@ export function refreshLockTimestamp(path) {
|
|
|
99
213
|
}
|
|
100
214
|
}
|
|
101
215
|
/**
|
|
102
|
-
* Remove stale lock files for `serverName
|
|
216
|
+
* Remove stale lock files for `serverName` (D9 hybrid TTL). Returns count removed.
|
|
103
217
|
*
|
|
104
218
|
* Called by `runLocalServer` at daemon startup before writing its own lock,
|
|
105
219
|
* preventing pile-up of dozens of `<server>-<port>.lock` files when daemons
|
|
106
220
|
* exit abnormally (Windows OOM, taskkill, signal).
|
|
221
|
+
*
|
|
222
|
+
* Backward-compat: the legacy signature `(serverName, ttlHours, root)` is
|
|
223
|
+
* preserved for pre-D9 callers. New D9 callers pass just `serverName` and
|
|
224
|
+
* rely on the hybrid TTL plus the `lockDir()` lookup (mockable in tests).
|
|
107
225
|
*/
|
|
108
|
-
export function sweepStaleLocks(serverName, ttlHours
|
|
109
|
-
const dir =
|
|
226
|
+
export function sweepStaleLocks(serverName, ttlHours, root) {
|
|
227
|
+
const dir = root !== undefined ? root : self.lockDir();
|
|
110
228
|
if (!existsSync(dir))
|
|
111
229
|
return 0;
|
|
112
230
|
let removed = 0;
|
|
@@ -119,36 +237,74 @@ export function sweepStaleLocks(serverName, ttlHours = DEFAULT_LOCK_TTL_HOURS, r
|
|
|
119
237
|
}
|
|
120
238
|
const prefix = `${serverName}-`;
|
|
121
239
|
const suffix = '.lock';
|
|
240
|
+
const now = Date.now();
|
|
241
|
+
const configuredTtlMs = (ttlHours ?? DEFAULT_LOCK_TTL_HOURS) * 3600 * 1000;
|
|
122
242
|
for (const entry of entries) {
|
|
123
243
|
if (!entry.startsWith(prefix) || !entry.endsWith(suffix))
|
|
124
244
|
continue;
|
|
125
245
|
const full = join(dir, entry);
|
|
126
|
-
|
|
127
|
-
|
|
246
|
+
let raw;
|
|
247
|
+
try {
|
|
248
|
+
raw = readFileSync(full, { encoding: 'utf-8' });
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
try {
|
|
252
|
+
unlinkSync(full);
|
|
253
|
+
removed += 1;
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
/* ignore */
|
|
257
|
+
}
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
let meta;
|
|
261
|
+
try {
|
|
262
|
+
meta = parseLock(raw);
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
128
265
|
try {
|
|
129
266
|
unlinkSync(full);
|
|
130
267
|
removed += 1;
|
|
131
268
|
}
|
|
132
269
|
catch {
|
|
133
|
-
|
|
270
|
+
/* ignore */
|
|
134
271
|
}
|
|
135
272
|
continue;
|
|
136
273
|
}
|
|
137
|
-
if (
|
|
274
|
+
if (!self.isAlive(meta)) {
|
|
275
|
+
try {
|
|
276
|
+
unlinkSync(full);
|
|
277
|
+
removed += 1;
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
/* ignore */
|
|
281
|
+
}
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const ttlMs = meta.credState === 'configured' ? configuredTtlMs : LIFECYCLE_TTL_UNCONFIGURED_MS;
|
|
285
|
+
const lastActivityMs = meta.lastActivityAt.getTime();
|
|
286
|
+
if (now - lastActivityMs > ttlMs) {
|
|
287
|
+
// Only terminate idle setup daemons aggressively; preserve pre-D9
|
|
288
|
+
// behavior of unlink-only for configured daemons past TTL.
|
|
289
|
+
if (meta.credState === 'unconfigured') {
|
|
290
|
+
self.terminateDaemon(meta.pid);
|
|
291
|
+
}
|
|
138
292
|
try {
|
|
139
293
|
unlinkSync(full);
|
|
140
294
|
removed += 1;
|
|
141
295
|
}
|
|
142
296
|
catch {
|
|
143
|
-
|
|
297
|
+
/* ignore */
|
|
144
298
|
}
|
|
145
299
|
}
|
|
146
300
|
}
|
|
147
301
|
return removed;
|
|
148
302
|
}
|
|
149
303
|
/**
|
|
150
|
-
* Write the 4-line lock payload (pid, port, token, ISO timestamp) padded
|
|
151
|
-
* 512 bytes. Used by `runLocalServer` after the OS file lock is
|
|
304
|
+
* Write the 4-line lock payload (pid, port, token, ISO timestamp) padded
|
|
305
|
+
* to 512 bytes. Used by `runLocalServer` after the OS file lock is
|
|
306
|
+
* acquired. Continues to write 4-line for backward compat — D9 sweep
|
|
307
|
+
* treats 4-line as `credState='configured'` so behavior is equivalent.
|
|
152
308
|
*
|
|
153
309
|
* Returns the absolute path to the lock file.
|
|
154
310
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/lifecycle/lock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/lifecycle/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ActiveFormSession {
|
|
2
|
+
token: string;
|
|
3
|
+
clientId: string;
|
|
4
|
+
startedAt: Date;
|
|
5
|
+
expiresAt: Date;
|
|
6
|
+
}
|
|
7
|
+
export declare function claimSession(clientId: string): ActiveFormSession;
|
|
8
|
+
export declare function releaseSession(): void;
|
|
9
|
+
export declare function isSessionActive(): boolean;
|
|
10
|
+
export declare function validateSessionToken(token: string): boolean;
|
|
11
|
+
export declare function getActiveSession(): ActiveFormSession | null;
|
|
12
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/relay/session.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,CAAA;CAChB;AAQD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAYhE;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAU3D;AAED,wBAAgB,gBAAgB,IAAI,iBAAiB,GAAG,IAAI,CAO3D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
const SESSION_TTL_MS = 30 * 60 * 1000;
|
|
3
|
+
const TOKEN_BYTES = 32;
|
|
4
|
+
let state = null;
|
|
5
|
+
function now() {
|
|
6
|
+
return new Date();
|
|
7
|
+
}
|
|
8
|
+
export function claimSession(clientId) {
|
|
9
|
+
if (state !== null && state.expiresAt > now()) {
|
|
10
|
+
return state;
|
|
11
|
+
}
|
|
12
|
+
const startedAt = now();
|
|
13
|
+
state = {
|
|
14
|
+
token: randomBytes(TOKEN_BYTES).toString('base64url'),
|
|
15
|
+
clientId,
|
|
16
|
+
startedAt,
|
|
17
|
+
expiresAt: new Date(startedAt.getTime() + SESSION_TTL_MS)
|
|
18
|
+
};
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
export function releaseSession() {
|
|
22
|
+
state = null;
|
|
23
|
+
}
|
|
24
|
+
export function isSessionActive() {
|
|
25
|
+
if (state === null)
|
|
26
|
+
return false;
|
|
27
|
+
if (state.expiresAt <= now()) {
|
|
28
|
+
state = null;
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
export function validateSessionToken(token) {
|
|
34
|
+
if (state === null)
|
|
35
|
+
return false;
|
|
36
|
+
if (state.expiresAt <= now()) {
|
|
37
|
+
state = null;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const a = Buffer.from(state.token);
|
|
41
|
+
const b = Buffer.from(token);
|
|
42
|
+
if (a.length !== b.length)
|
|
43
|
+
return false;
|
|
44
|
+
return timingSafeEqual(a, b);
|
|
45
|
+
}
|
|
46
|
+
export function getActiveSession() {
|
|
47
|
+
if (state === null)
|
|
48
|
+
return null;
|
|
49
|
+
if (state.expiresAt <= now()) {
|
|
50
|
+
state = null;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return state;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/relay/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE1D,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AACrC,MAAM,WAAW,GAAG,EAAE,CAAA;AAStB,IAAI,KAAK,GAA6B,IAAI,CAAA;AAE1C,SAAS,GAAG;IACV,OAAO,IAAI,IAAI,EAAE,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,EAAE,CAAA;IACvB,KAAK,GAAG;QACN,KAAK,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;QACrD,QAAQ;QACR,SAAS;QACT,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,cAAc,CAAC;KAC1D,CAAA;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,KAAK,GAAG,IAAI,CAAA;AACd,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAChC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,EAAE,CAAC;QAC7B,KAAK,GAAG,IAAI,CAAA;QACZ,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAChC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,EAAE,CAAC;QAC7B,KAAK,GAAG,IAAI,CAAA;QACZ,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC5B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACvC,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC/B,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,EAAE,CAAC;QAC7B,KAAK,GAAG,IAAI,CAAA;QACZ,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper to register `config__open_relay` MCP tool — D6 (Task 1.8).
|
|
3
|
+
*
|
|
4
|
+
* Each consumer server calls `registerOpenRelayTool(mcp, SERVER_NAME, SCHEMA)`
|
|
5
|
+
* to get the standard tool registered into its MCP server instance. The tool,
|
|
6
|
+
* when invoked by the LLM, returns the relay form URL and attempts to open
|
|
7
|
+
* the user's browser. If the daemon is dead it auto-respawns; if a relay
|
|
8
|
+
* session is already active in another Claude Code window, the handler
|
|
9
|
+
* returns `session_active` status without auto-opening a second browser tab.
|
|
10
|
+
*/
|
|
11
|
+
export interface OpenRelayResult {
|
|
12
|
+
url: string;
|
|
13
|
+
browserOpened: boolean;
|
|
14
|
+
status: 'configured' | 'unconfigured' | 'expired' | 'session_active';
|
|
15
|
+
}
|
|
16
|
+
export interface OpenRelaySchema {
|
|
17
|
+
server: string;
|
|
18
|
+
fields: Array<{
|
|
19
|
+
name: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
secret?: boolean;
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
}>;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the `open_relay` handler closure. Separated out for testability —
|
|
29
|
+
* tests can call `buildOpenRelayHandler('demo', SCHEMA)` directly without
|
|
30
|
+
* needing a real MCP server instance.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildOpenRelayHandler(serverName: string, _schema: OpenRelaySchema | unknown): () => Promise<OpenRelayResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Minimal shape we require from the MCP server instance to register the
|
|
35
|
+
* tool. Both `@modelcontextprotocol/sdk`'s `McpServer.tool` and the
|
|
36
|
+
* FastMCP-style helpers used in consumer servers conform to this surface.
|
|
37
|
+
*/
|
|
38
|
+
export interface ToolRegistrar {
|
|
39
|
+
tool: (config: {
|
|
40
|
+
name: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
}, handler: () => Promise<OpenRelayResult>) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Register `config__open_relay` on the given MCP server instance.
|
|
46
|
+
*
|
|
47
|
+
* Consumer servers add this single line in their tool registry after the
|
|
48
|
+
* other `config__*` registrations:
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { registerOpenRelayTool } from '@n24q02m/mcp-core'
|
|
52
|
+
* registerOpenRelayTool(mcp, SERVER_NAME, RELAY_SCHEMA)
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function registerOpenRelayTool(mcp: ToolRegistrar, serverName: string, schema: OpenRelaySchema | unknown): void;
|
|
56
|
+
//# sourceMappingURL=tool-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-helpers.d.ts","sourceRoot":"","sources":["../../src/relay/tool-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,EAAE,YAAY,GAAG,cAAc,GAAG,SAAS,GAAG,gBAAgB,CAAA;CACrE;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAC,CAAA;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAeD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,GAAG,OAAO,GACjC,MAAM,OAAO,CAAC,eAAe,CAAC,CAYhC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;CACxG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,GAAG,IAAI,CASrH"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper to register `config__open_relay` MCP tool — D6 (Task 1.8).
|
|
3
|
+
*
|
|
4
|
+
* Each consumer server calls `registerOpenRelayTool(mcp, SERVER_NAME, SCHEMA)`
|
|
5
|
+
* to get the standard tool registered into its MCP server instance. The tool,
|
|
6
|
+
* when invoked by the LLM, returns the relay form URL and attempts to open
|
|
7
|
+
* the user's browser. If the daemon is dead it auto-respawns; if a relay
|
|
8
|
+
* session is already active in another Claude Code window, the handler
|
|
9
|
+
* returns `session_active` status without auto-opening a second browser tab.
|
|
10
|
+
*/
|
|
11
|
+
import { daemonCredState, daemonIsAlive, daemonRelayUrl, daemonRespawn } from '../transport/smart-stdio.js';
|
|
12
|
+
import { tryOpenBrowser } from './browser.js';
|
|
13
|
+
import { isSessionActive } from './session.js';
|
|
14
|
+
/**
|
|
15
|
+
* Per-server session probe.
|
|
16
|
+
*
|
|
17
|
+
* The current session module tracks one global active form session at a
|
|
18
|
+
* time (Task 1.5), so the server name is currently ignored. Kept as a
|
|
19
|
+
* one-arg helper to give vi.spyOn hooks a single, server-aware seam that
|
|
20
|
+
* future per-server session tracking can implement without refactoring
|
|
21
|
+
* callers.
|
|
22
|
+
*/
|
|
23
|
+
function isSessionActiveForServer(_serverName) {
|
|
24
|
+
return isSessionActive();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build the `open_relay` handler closure. Separated out for testability —
|
|
28
|
+
* tests can call `buildOpenRelayHandler('demo', SCHEMA)` directly without
|
|
29
|
+
* needing a real MCP server instance.
|
|
30
|
+
*/
|
|
31
|
+
export function buildOpenRelayHandler(serverName, _schema) {
|
|
32
|
+
return async function openRelay() {
|
|
33
|
+
const url = daemonIsAlive(serverName) ? daemonRelayUrl(serverName) : daemonRespawn(serverName);
|
|
34
|
+
const credState = daemonCredState(serverName);
|
|
35
|
+
if (isSessionActiveForServer(serverName)) {
|
|
36
|
+
return { url, browserOpened: false, status: 'session_active' };
|
|
37
|
+
}
|
|
38
|
+
const opened = await tryOpenBrowser(url);
|
|
39
|
+
return { url, browserOpened: !!opened, status: credState };
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register `config__open_relay` on the given MCP server instance.
|
|
44
|
+
*
|
|
45
|
+
* Consumer servers add this single line in their tool registry after the
|
|
46
|
+
* other `config__*` registrations:
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { registerOpenRelayTool } from '@n24q02m/mcp-core'
|
|
50
|
+
* registerOpenRelayTool(mcp, SERVER_NAME, RELAY_SCHEMA)
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function registerOpenRelayTool(mcp, serverName, schema) {
|
|
54
|
+
const handler = buildOpenRelayHandler(serverName, schema);
|
|
55
|
+
mcp.tool({
|
|
56
|
+
name: 'config__open_relay',
|
|
57
|
+
description: `Open the relay configuration form for ${serverName} in the user's browser.`
|
|
58
|
+
}, handler);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=tool-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-helpers.js","sourceRoot":"","sources":["../../src/relay/tool-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3G,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAoB9C;;;;;;;;GAQG;AACH,SAAS,wBAAwB,CAAC,WAAmB;IACnD,OAAO,eAAe,EAAE,CAAA;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,OAAkC;IAElC,OAAO,KAAK,UAAU,SAAS;QAC7B,MAAM,GAAG,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;QAC9F,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAA8B,CAAA;QAE1E,IAAI,wBAAwB,CAAC,UAAU,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAA;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAA;QACxC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;IAC5D,CAAC,CAAA;AACH,CAAC;AAWD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAkB,EAAE,UAAkB,EAAE,MAAiC;IAC7G,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;IACzD,GAAG,CAAC,IAAI,CACN;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,yCAAyC,UAAU,yBAAyB;KAC1F,EACD,OAAO,CACR,CAAA;AACH,CAAC"}
|
|
@@ -108,7 +108,7 @@ async function saveStore(store) {
|
|
|
108
108
|
}
|
|
109
109
|
const key = await getKey();
|
|
110
110
|
const encrypted = await encryptData(key, JSON.stringify(store));
|
|
111
|
-
await withRetry(() => writeFile(configPath, encrypted));
|
|
111
|
+
await withRetry(() => writeFile(configPath, encrypted, { mode: 0o600 }));
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
114
|
* Schedule a process exit so an MCP client can respawn the server and pick up
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/storage/config-file.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config-file.js","sourceRoot":"","sources":["../../src/storage/config-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,QAAQ,MAAM,WAAW,CAAA;AAChC,OAAO,EACL,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AAC7C,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AAO5D,SAAS,YAAY,CAAC,MAA+B;IACnD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAA;AAC1E,CAAC;AAED,SAAS,cAAc,CAAC,MAAe;IACrC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACvD,OAAO,YAAY,CAAC,MAAiC,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,cAAc,CAAC,IAAa;IACnC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACnD,MAAM,CAAC,GAAG,IAA+B,CAAA;IACzC,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACjC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAE7D,MAAM,OAAO,GAAG,CAAC,CAAC,OAAkC,CAAA;IACpD,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAC3E,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,2CAA2C;AAC3C,IAAI,kBAAkB,GAAkB,IAAI,CAAA;AAE5C,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,kBAAkB,GAAG,IAAI,CAAA;AAC3B,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,kBAAkB,IAAI,mBAAmB,CAAA;AAClD,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,CAAA;AACrB,MAAM,aAAa,GAAG,GAAG,CAAA;AAEzB,KAAK,UAAU,SAAS,CAAI,EAAoB;IAC9C,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAA;QACnB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAK,GAA6B,CAAC,IAAI,KAAK,OAAO,CAAA;YACzG,IAAI,CAAC,QAAQ,IAAI,OAAO,KAAK,WAAW,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAA;YACvD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAA;AAChC,CAAC;AAED,8FAA8F;AAC9F,0FAA0F;AAC1F,IAAI,SAAS,GAAqB,IAAI,CAAA;AAEtC,MAAM,UAAU,uBAAuB;IACrC,SAAS,GAAG,IAAI,CAAA;AAClB,CAAC;AAED,KAAK,UAAU,MAAM;IACnB,IAAI,SAAS;QAAE,OAAO,SAAS,CAAA;IAC/B,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;IAChF,SAAS,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACpD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;IACpC,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;IAChF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAA;IAEvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,EAAE,CAAA;QAC1B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;QAC1C,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,QAAQ,EAAE,wBAAwB,CAAC,CAAA;YACpF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;YAC1C,CAAC;YACD,qCAAqC;YACrC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAA;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,KAAkB;IACzC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,MAAM,EAAE,CAAA;IAC1B,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/D,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AAC1E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAClE,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,CAAA;IACjD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,CAAA;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,MAA8B;IAClF,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAA;IAClC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAEhC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAA;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,MAAM,QAAQ,GAAG,CAAC,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAA;IACrD,QAAQ,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAA;IACrC,MAAM,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAA;IACjD,OAAO,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB,EAAE,IAAY;IACjE,IAAI,IAAY,CAAA;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAA;QACpE,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAA;YACjF,IAAI,GAAG,MAAM,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAA;IAC/B,2CAA2C;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA;IAC9B,CAAC;IACD,MAAM,SAAS,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC"}
|
|
@@ -77,7 +77,7 @@ export async function writeSessionLock(serverName, info) {
|
|
|
77
77
|
};
|
|
78
78
|
// Write atomically via temp file + rename
|
|
79
79
|
const tmpPath = `${path}.tmp`;
|
|
80
|
-
await writeFile(tmpPath, JSON.stringify(data), 'utf-8');
|
|
80
|
+
await writeFile(tmpPath, JSON.stringify(data), { encoding: 'utf-8', mode: 0o600 });
|
|
81
81
|
await rename(tmpPath, path);
|
|
82
82
|
}
|
|
83
83
|
export async function releaseSessionLock(serverName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-lock.js","sourceRoot":"","sources":["../../src/storage/session-lock.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"session-lock.js","sourceRoot":"","sources":["../../src/storage/session-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tools-list cache with version-aware key (D10) — TS parity with core-py.
|
|
3
|
+
*
|
|
4
|
+
* Cache filename: ``<server>-<port>-<srvVersion>-<coreVersion>.tools.json``.
|
|
5
|
+
* A mismatch on either ``srvVersion`` (the upstream MCP server's version) or
|
|
6
|
+
* ``coreVersion`` (mcp-core itself) invalidates the cache, so an upgrade on
|
|
7
|
+
* either side never serves a stale tool surface.
|
|
8
|
+
*
|
|
9
|
+
* ``persistToolsCache`` writes via ``.tmp`` + ``rename`` (Windows-safe) and
|
|
10
|
+
* suppresses all filesystem errors with a debug log. This is the D10
|
|
11
|
+
* root-cause fix for ``Failed to persist capabilities cache`` hard-failures
|
|
12
|
+
* (crg #384).
|
|
13
|
+
*/
|
|
14
|
+
export declare function cacheDir(): string;
|
|
15
|
+
export declare function cacheFilename(serverName: string, port: number, srvVersion: string, coreVersion: string): string;
|
|
16
|
+
export declare function atomicWrite(path: string, content: string): void;
|
|
17
|
+
export declare function persistToolsCache(serverName: string, port: number, srvVersion: string, coreVersion: string, tools: unknown[]): void;
|
|
18
|
+
export declare function loadToolsCache(serverName: string, port: number, srvVersion: string, coreVersion: string): unknown[] | null;
|
|
19
|
+
//# sourceMappingURL=cache.d.ts.map
|