@ai-ecoverse/mcpcat 0.14.0 → 0.14.2

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.
@@ -167,6 +167,101 @@ var init_node_stub = __esm({
167
167
  }
168
168
  });
169
169
 
170
+ // src/config/lock.ts
171
+ var lock_exports = {};
172
+ __export(lock_exports, {
173
+ acquireLock: () => acquireLock
174
+ });
175
+ function isEexist(err) {
176
+ if (err instanceof Error && "code" in err)
177
+ return err.code === "EEXIST";
178
+ if (err instanceof Error) return err.message.includes("EEXIST");
179
+ return false;
180
+ }
181
+ async function removeStaleLockDir(fs, lockPath) {
182
+ try {
183
+ const s = await fs.stat(lockPath);
184
+ if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
185
+ try {
186
+ await fs.rmdir(lockPath);
187
+ } catch {
188
+ }
189
+ return true;
190
+ }
191
+ } catch {
192
+ }
193
+ return false;
194
+ }
195
+ async function removeStaleLockFile(fs, lockPath) {
196
+ try {
197
+ const s = await fs.stat(lockPath);
198
+ if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
199
+ try {
200
+ await fs.unlink(lockPath);
201
+ } catch {
202
+ }
203
+ return true;
204
+ }
205
+ } catch {
206
+ }
207
+ return false;
208
+ }
209
+ async function acquireLock(fs, configPath) {
210
+ const useFile = typeof fs.createExclusive === "function";
211
+ const lockPath = `${configPath}.lock`;
212
+ const start = Date.now();
213
+ const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
214
+ if (parentDir) {
215
+ try {
216
+ await fs.mkdir(parentDir);
217
+ } catch {
218
+ }
219
+ }
220
+ while (true) {
221
+ try {
222
+ if (useFile) {
223
+ await fs.createExclusive(lockPath);
224
+ } else {
225
+ await fs.mkdirExclusive(lockPath);
226
+ }
227
+ break;
228
+ } catch (err) {
229
+ if (!isEexist(err)) throw err;
230
+ if (useFile) {
231
+ await removeStaleLockFile(fs, lockPath);
232
+ } else {
233
+ await removeStaleLockDir(fs, lockPath);
234
+ }
235
+ }
236
+ if (Date.now() - start > LOCK_MAX_WAIT_MS) {
237
+ throw new Error(`mcpcat: could not acquire lock ${lockPath} within ${LOCK_MAX_WAIT_MS}ms`);
238
+ }
239
+ await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
240
+ }
241
+ let released = false;
242
+ return async () => {
243
+ if (released) return;
244
+ released = true;
245
+ try {
246
+ if (useFile && fs.unlink) {
247
+ await fs.unlink(lockPath);
248
+ } else {
249
+ await fs.rmdir(lockPath);
250
+ }
251
+ } catch {
252
+ }
253
+ };
254
+ }
255
+ var LOCK_STALE_MS, LOCK_POLL_MS, LOCK_MAX_WAIT_MS;
256
+ var init_lock = __esm({
257
+ "src/config/lock.ts"() {
258
+ "use strict";
259
+ LOCK_STALE_MS = 1e4;
260
+ LOCK_POLL_MS = 50;
261
+ LOCK_MAX_WAIT_MS = 5e3;
262
+ }
263
+ });
264
+
170
265
  // node_modules/@earendil-works/pi-codemode/dist/identifier.js
171
266
  function toCodemodeIdentifier(name) {
172
267
  let identifier = "";
@@ -5966,7 +6061,7 @@ var McpOAuthProvider = class {
5966
6061
  };
5967
6062
 
5968
6063
  // src/auth/jerk-token-source.ts
5969
- var MIN_VERSION = [0, 13, 0];
6064
+ var MIN_VERSION = [0, 14, 1];
5970
6065
  var VERSION_TIMEOUT_MS = 2e3;
5971
6066
  var cachedAvailable;
5972
6067
  function parseVersion(raw) {
@@ -6092,6 +6187,192 @@ var JerkTokenSource = class {
6092
6187
  }
6093
6188
  };
6094
6189
 
6190
+ // src/auth/pi-store.ts
6191
+ init_lock();
6192
+
6193
+ // src/config/paths.ts
6194
+ function userConfigDir(platform2) {
6195
+ const piDir = platform2.env.PI_CODING_AGENT_DIR;
6196
+ if (piDir) return piDir;
6197
+ const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
6198
+ return `${home}/.pi/agent`;
6199
+ }
6200
+ function userConfigPath(platform2) {
6201
+ return `${userConfigDir(platform2)}/mcp.json`;
6202
+ }
6203
+ function projectConfigPath(platform2) {
6204
+ return `${platform2.cwd}/.pi/mcp.json`;
6205
+ }
6206
+ function stateDir(platform2) {
6207
+ if (platform2.env.XDG_STATE_HOME) return `${platform2.env.XDG_STATE_HOME}/mcpcat`;
6208
+ const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
6209
+ if (platform2.env.LOCALAPPDATA) return `${platform2.env.LOCALAPPDATA}\\mcpcat\\state`;
6210
+ if (platform2.env.SLICC_KERNEL) return `${home}/.local/state/mcpcat`;
6211
+ return `${home}/Library/Application Support/mcpcat`;
6212
+ }
6213
+
6214
+ // src/auth/token-source.ts
6215
+ function mcpNamespace(server) {
6216
+ return `mcp__${server.replace(/-/g, "_")}`;
6217
+ }
6218
+ function storeKey(name, serverUrl) {
6219
+ const ns = mcpNamespace(name);
6220
+ const url = String(new URL(serverUrl));
6221
+ return `${ns}|${url}`;
6222
+ }
6223
+ function isKernel(platform2) {
6224
+ return platform2.kind === "kernel";
6225
+ }
6226
+
6227
+ // src/auth/pi-store.ts
6228
+ var AUTH_FILE = "mcp-auth.json";
6229
+ var FILE_MODE = 384;
6230
+ var DIR_MODE = 448;
6231
+ function parseStates(raw) {
6232
+ if (!raw?.trim()) return {};
6233
+ const parsed = JSON.parse(raw);
6234
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
6235
+ }
6236
+ function serializeStates(states) {
6237
+ return `${JSON.stringify(states, null, 2)}
6238
+ `;
6239
+ }
6240
+ function legacyKey(serverUrl) {
6241
+ return String(new URL(serverUrl));
6242
+ }
6243
+ var PiFileTokenSource = class {
6244
+ platform;
6245
+ authPath;
6246
+ dirPath;
6247
+ constructor(platform2) {
6248
+ this.platform = platform2;
6249
+ this.dirPath = userConfigDir(platform2);
6250
+ this.authPath = `${this.dirPath}/${AUTH_FILE}`;
6251
+ }
6252
+ get path() {
6253
+ return this.authPath;
6254
+ }
6255
+ async loadWithoutLock(name, serverUrl) {
6256
+ const key = storeKey(name, serverUrl);
6257
+ const legacy = legacyKey(serverUrl);
6258
+ try {
6259
+ const raw = await this.readRaw();
6260
+ const states = parseStates(raw);
6261
+ return states[key] ?? states[legacy];
6262
+ } catch {
6263
+ return void 0;
6264
+ }
6265
+ }
6266
+ async getToken(name, serverUrl) {
6267
+ const state = await this.load(name, serverUrl);
6268
+ if (!state?.tokens?.access_token) return void 0;
6269
+ return {
6270
+ accessToken: state.tokens.access_token,
6271
+ expiresAt: state.tokensExpireAt
6272
+ };
6273
+ }
6274
+ async load(name, serverUrl) {
6275
+ const key = storeKey(name, serverUrl);
6276
+ const legacy = legacyKey(serverUrl);
6277
+ const release = await this.acquireLock();
6278
+ try {
6279
+ const raw = await this.readRaw();
6280
+ const states = parseStates(raw);
6281
+ if (states[key]) return states[key];
6282
+ if (states[legacy]) {
6283
+ states[key] = states[legacy];
6284
+ delete states[legacy];
6285
+ await this.writeStates(states);
6286
+ return states[key];
6287
+ }
6288
+ return void 0;
6289
+ } finally {
6290
+ await release();
6291
+ }
6292
+ }
6293
+ async save(name, serverUrl, state) {
6294
+ const key = storeKey(name, serverUrl);
6295
+ const release = await this.acquireLock();
6296
+ try {
6297
+ const raw = await this.readRaw();
6298
+ const states = parseStates(raw);
6299
+ states[key] = state;
6300
+ await this.writeStates(states);
6301
+ } finally {
6302
+ await release();
6303
+ }
6304
+ }
6305
+ async remove(name, serverUrl) {
6306
+ const key = storeKey(name, serverUrl);
6307
+ const legacy = legacyKey(serverUrl);
6308
+ const release = await this.acquireLock();
6309
+ try {
6310
+ const raw = await this.readRaw();
6311
+ const states = parseStates(raw);
6312
+ const stored = key in states ? key : legacy in states ? legacy : void 0;
6313
+ if (!stored) return false;
6314
+ delete states[stored];
6315
+ await this.writeStates(states);
6316
+ return true;
6317
+ } finally {
6318
+ await release();
6319
+ }
6320
+ }
6321
+ async acquireLock() {
6322
+ await this.ensureDir();
6323
+ return acquireLock(this.platform.fs, this.authPath);
6324
+ }
6325
+ async ensureDir() {
6326
+ const fs = this.platform.fs;
6327
+ try {
6328
+ await fs.mkdir(this.dirPath, { mode: DIR_MODE });
6329
+ } catch {
6330
+ }
6331
+ if (fs.chmod) {
6332
+ try {
6333
+ await fs.chmod(this.dirPath, DIR_MODE);
6334
+ } catch {
6335
+ }
6336
+ const piDir = this.dirPath.slice(0, this.dirPath.lastIndexOf("/"));
6337
+ if (piDir) {
6338
+ try {
6339
+ await fs.chmod(piDir, DIR_MODE);
6340
+ } catch {
6341
+ }
6342
+ }
6343
+ }
6344
+ }
6345
+ async readRaw() {
6346
+ try {
6347
+ const data = await this.platform.fs.readFile(this.authPath);
6348
+ return new TextDecoder().decode(data);
6349
+ } catch {
6350
+ return void 0;
6351
+ }
6352
+ }
6353
+ async writeStates(states) {
6354
+ const fs = this.platform.fs;
6355
+ const content = serializeStates(states);
6356
+ const tmpPath = `${this.authPath}.tmp.${Date.now()}`;
6357
+ try {
6358
+ await fs.writeFile(tmpPath, content, { mode: FILE_MODE });
6359
+ await fs.rename(tmpPath, this.authPath);
6360
+ } catch (renameErr) {
6361
+ try {
6362
+ if (fs.unlink) await fs.unlink(tmpPath);
6363
+ } catch {
6364
+ }
6365
+ throw renameErr;
6366
+ }
6367
+ if (fs.chmod) {
6368
+ try {
6369
+ await fs.chmod(this.authPath, FILE_MODE);
6370
+ } catch {
6371
+ }
6372
+ }
6373
+ }
6374
+ };
6375
+
6095
6376
  // src/auth/auth-provider.ts
6096
6377
  var CIMD_URL = "https://mcpcat.sliccy.ai/oauth/client.json";
6097
6378
  var CLIENT_NAME = "mcpcat";
@@ -6113,10 +6394,12 @@ var SourceBackedStore = class {
6113
6394
  source;
6114
6395
  name;
6115
6396
  serverUrl;
6116
- constructor(source, name, serverUrl) {
6397
+ platform;
6398
+ constructor(source, name, serverUrl, platform2) {
6117
6399
  this.source = source;
6118
6400
  this.name = name;
6119
6401
  this.serverUrl = serverUrl;
6402
+ this.platform = platform2;
6120
6403
  }
6121
6404
  async load() {
6122
6405
  return this.source.load(this.name, this.serverUrl);
@@ -6124,6 +6407,17 @@ var SourceBackedStore = class {
6124
6407
  async save(state) {
6125
6408
  await this.source.save(this.name, this.serverUrl, state);
6126
6409
  }
6410
+ async withRefreshLock(fn) {
6411
+ if (!(this.source instanceof PiFileTokenSource)) return fn();
6412
+ const refreshPath = `${this.source.path}.refresh`;
6413
+ const { acquireLock: acquireLock2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
6414
+ const release = await acquireLock2(this.platform.fs, refreshPath);
6415
+ try {
6416
+ return await fn();
6417
+ } finally {
6418
+ await release();
6419
+ }
6420
+ }
6127
6421
  };
6128
6422
  function cimdFn(redirectUrl) {
6129
6423
  return (metadata) => {
@@ -6152,10 +6446,9 @@ function createMcpAuthProvider(options) {
6152
6446
  function createJerkAuthProvider(options) {
6153
6447
  const { name, serverUrl, source } = options;
6154
6448
  let currentToken;
6449
+ const _fetched = false;
6155
6450
  return {
6156
6451
  async token() {
6157
- const result = await source.getToken(name, serverUrl);
6158
- currentToken = result?.accessToken;
6159
6452
  return currentToken;
6160
6453
  },
6161
6454
  async onUnauthorized(context) {
@@ -6186,10 +6479,10 @@ function createJerkAuthProvider(options) {
6186
6479
  }
6187
6480
  function createPiAuthProvider(options) {
6188
6481
  const { name, serverUrl, source, oauth, platform: platform2 } = options;
6189
- const store = new SourceBackedStore(source, name, serverUrl);
6482
+ const store = new SourceBackedStore(source, name, serverUrl, platform2);
6190
6483
  let refreshing;
6191
6484
  const refresh = async (staleToken) => {
6192
- refreshing ??= (async () => {
6485
+ refreshing ??= store.withRefreshLock(async () => {
6193
6486
  const state = await store.load();
6194
6487
  if (state?.tokens?.access_token !== staleToken) return;
6195
6488
  if (!state?.tokens?.refresh_token) throw new McpOAuthAuthorizationRequiredError();
@@ -6212,7 +6505,7 @@ function createPiAuthProvider(options) {
6212
6505
  fetch: timedFetch(platform2.fetch)
6213
6506
  });
6214
6507
  if (result === "REDIRECT") throw new McpOAuthAuthorizationRequiredError();
6215
- })().finally(() => {
6508
+ }).finally(() => {
6216
6509
  refreshing = void 0;
6217
6510
  });
6218
6511
  return refreshing;
@@ -9192,27 +9485,6 @@ async function loadConfig(input) {
9192
9485
  };
9193
9486
  }
9194
9487
 
9195
- // src/config/paths.ts
9196
- function userConfigDir(platform2) {
9197
- const piDir = platform2.env.PI_CODING_AGENT_DIR;
9198
- if (piDir) return piDir;
9199
- const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
9200
- return `${home}/.pi/agent`;
9201
- }
9202
- function userConfigPath(platform2) {
9203
- return `${userConfigDir(platform2)}/mcp.json`;
9204
- }
9205
- function projectConfigPath(platform2) {
9206
- return `${platform2.cwd}/.pi/mcp.json`;
9207
- }
9208
- function stateDir(platform2) {
9209
- if (platform2.env.XDG_STATE_HOME) return `${platform2.env.XDG_STATE_HOME}/mcpcat`;
9210
- const home = platform2.env.HOME ?? platform2.env.USERPROFILE ?? "/";
9211
- if (platform2.env.LOCALAPPDATA) return `${platform2.env.LOCALAPPDATA}\\mcpcat\\state`;
9212
- if (platform2.env.SLICC_KERNEL) return `${home}/.local/state/mcpcat`;
9213
- return `${home}/Library/Application Support/mcpcat`;
9214
- }
9215
-
9216
9488
  // src/config/index.ts
9217
9489
  var MergedConfigSource = class _MergedConfigSource {
9218
9490
  entries;
@@ -9252,65 +9524,8 @@ var MergedConfigSource = class _MergedConfigSource {
9252
9524
  }
9253
9525
  };
9254
9526
 
9255
- // src/config/lock.ts
9256
- var LOCK_STALE_MS = 1e4;
9257
- var LOCK_POLL_MS = 50;
9258
- var LOCK_MAX_WAIT_MS = 5e3;
9259
- function isEexist(err) {
9260
- if (err instanceof Error && "code" in err)
9261
- return err.code === "EEXIST";
9262
- if (err instanceof Error) return err.message.includes("EEXIST");
9263
- return false;
9264
- }
9265
- async function removeStaleLock(fs, lockPath) {
9266
- try {
9267
- const s = await fs.stat(lockPath);
9268
- if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
9269
- try {
9270
- await fs.rmdir(lockPath);
9271
- } catch {
9272
- }
9273
- return true;
9274
- }
9275
- } catch {
9276
- }
9277
- return false;
9278
- }
9279
- async function acquireLock(fs, configPath) {
9280
- const lockPath = `${configPath}.lock`;
9281
- const start = Date.now();
9282
- const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
9283
- if (parentDir) {
9284
- try {
9285
- await fs.mkdir(parentDir);
9286
- } catch {
9287
- }
9288
- }
9289
- while (true) {
9290
- try {
9291
- await fs.mkdirExclusive(lockPath);
9292
- break;
9293
- } catch (err) {
9294
- if (!isEexist(err)) throw err;
9295
- await removeStaleLock(fs, lockPath);
9296
- }
9297
- if (Date.now() - start > LOCK_MAX_WAIT_MS) {
9298
- throw new Error(`mcpcat: could not acquire lock ${lockPath} within ${LOCK_MAX_WAIT_MS}ms`);
9299
- }
9300
- await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
9301
- }
9302
- let released = false;
9303
- return async () => {
9304
- if (released) return;
9305
- released = true;
9306
- try {
9307
- await fs.rmdir(lockPath);
9308
- } catch {
9309
- }
9310
- };
9311
- }
9312
-
9313
9527
  // src/config/edit.ts
9528
+ init_lock();
9314
9529
  function isRecord2(value) {
9315
9530
  return typeof value === "object" && value !== null && !Array.isArray(value);
9316
9531
  }
@@ -12555,124 +12770,6 @@ async function signIn(options) {
12555
12770
  }
12556
12771
  }
12557
12772
 
12558
- // src/auth/token-source.ts
12559
- function mcpNamespace(server) {
12560
- return `mcp__${server.replace(/-/g, "_")}`;
12561
- }
12562
- function storeKey(name, serverUrl) {
12563
- const ns = mcpNamespace(name);
12564
- const url = String(new URL(serverUrl));
12565
- return `${ns}|${url}`;
12566
- }
12567
- function isKernel(platform2) {
12568
- return platform2.kind === "kernel";
12569
- }
12570
-
12571
- // src/auth/pi-store.ts
12572
- var AUTH_FILE = "mcp-auth.json";
12573
- var FILE_MODE = 384;
12574
- function parseStates(raw) {
12575
- if (!raw?.trim()) return {};
12576
- const parsed = JSON.parse(raw);
12577
- return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
12578
- }
12579
- function serializeStates(states) {
12580
- return `${JSON.stringify(states, null, 2)}
12581
- `;
12582
- }
12583
- function legacyKey(serverUrl) {
12584
- return String(new URL(serverUrl));
12585
- }
12586
- var PiFileTokenSource = class {
12587
- platform;
12588
- authPath;
12589
- dirPath;
12590
- constructor(platform2) {
12591
- this.platform = platform2;
12592
- this.dirPath = userConfigDir(platform2);
12593
- this.authPath = `${this.dirPath}/${AUTH_FILE}`;
12594
- }
12595
- get path() {
12596
- return this.authPath;
12597
- }
12598
- async getToken(name, serverUrl) {
12599
- const state = await this.load(name, serverUrl);
12600
- if (!state?.tokens?.access_token) return void 0;
12601
- return {
12602
- accessToken: state.tokens.access_token,
12603
- expiresAt: state.tokensExpireAt
12604
- };
12605
- }
12606
- async load(name, serverUrl) {
12607
- const key = storeKey(name, serverUrl);
12608
- const legacy = legacyKey(serverUrl);
12609
- const release = await this.acquireLock();
12610
- try {
12611
- const raw = await this.readRaw();
12612
- const states = parseStates(raw);
12613
- if (states[key]) return states[key];
12614
- if (states[legacy]) {
12615
- states[key] = states[legacy];
12616
- delete states[legacy];
12617
- await this.writeStates(states);
12618
- return states[key];
12619
- }
12620
- return void 0;
12621
- } finally {
12622
- await release();
12623
- }
12624
- }
12625
- async save(name, serverUrl, state) {
12626
- const key = storeKey(name, serverUrl);
12627
- const release = await this.acquireLock();
12628
- try {
12629
- const raw = await this.readRaw();
12630
- const states = parseStates(raw);
12631
- states[key] = state;
12632
- await this.writeStates(states);
12633
- } finally {
12634
- await release();
12635
- }
12636
- }
12637
- async remove(name, serverUrl) {
12638
- const key = storeKey(name, serverUrl);
12639
- const legacy = legacyKey(serverUrl);
12640
- const release = await this.acquireLock();
12641
- try {
12642
- const raw = await this.readRaw();
12643
- const states = parseStates(raw);
12644
- const stored = key in states ? key : legacy in states ? legacy : void 0;
12645
- if (!stored) return false;
12646
- delete states[stored];
12647
- await this.writeStates(states);
12648
- return true;
12649
- } finally {
12650
- await release();
12651
- }
12652
- }
12653
- async acquireLock() {
12654
- await this.ensureDir();
12655
- return acquireLock(this.platform.fs, this.authPath);
12656
- }
12657
- async ensureDir() {
12658
- try {
12659
- await this.platform.fs.mkdir(this.dirPath);
12660
- } catch {
12661
- }
12662
- }
12663
- async readRaw() {
12664
- try {
12665
- const data = await this.platform.fs.readFile(this.authPath);
12666
- return new TextDecoder().decode(data);
12667
- } catch {
12668
- return void 0;
12669
- }
12670
- }
12671
- async writeStates(states) {
12672
- await this.platform.fs.writeFile(this.authPath, serializeStates(states), { mode: FILE_MODE });
12673
- }
12674
- };
12675
-
12676
12773
  // src/cli/auth-verbs.ts
12677
12774
  var resolvedSource;
12678
12775
  async function createTokenSource(platform2) {
@@ -14366,6 +14463,17 @@ async function runCall(platform2, conn, toolName, dataArg, toolArgs, opts) {
14366
14463
  return EXIT_USAGE;
14367
14464
  }
14368
14465
  fin = mergeArgs(base, c.value);
14466
+ } else if (!dataArg && !opts.noValidate) {
14467
+ const tools = await conn.listTools();
14468
+ const tool = tools.find((t) => t.name === toolName);
14469
+ const schema = tool?.inputSchema;
14470
+ const required = Array.isArray(schema?.required) ? schema.required : [];
14471
+ for (const r of required) {
14472
+ if (!Object.hasOwn(base, r)) {
14473
+ await writeErr(platform2, opts.json ?? false, "usage", `missing required flag --${r}`);
14474
+ return EXIT_USAGE;
14475
+ }
14476
+ }
14369
14477
  }
14370
14478
  return renderCallResult(
14371
14479
  platform2,
@@ -14583,7 +14691,10 @@ async function probeServer(_name, config, platform2) {
14583
14691
  const opts = { version: "probe" };
14584
14692
  if ("url" in config && config.url) {
14585
14693
  opts.url = config.url;
14586
- if ("headers" in config) opts.headers = config.headers;
14694
+ if ("headers" in config) {
14695
+ const expanded = expandHeaders(config.headers, platform2.env);
14696
+ if (expanded) opts.headers = expanded;
14697
+ }
14587
14698
  } else if ("command" in config && config.command) {
14588
14699
  opts.command = config.command;
14589
14700
  if ("args" in config) opts.args = config.args;
@@ -14945,11 +15056,25 @@ function classifyError(err) {
14945
15056
  }
14946
15057
  async function resolveAuthProvider(platform2, hasAuthHeader, url, target, config) {
14947
15058
  if (hasAuthHeader || !url) return void 0;
14948
- const source = await createTokenSource(platform2);
15059
+ const piSource = new PiFileTokenSource(platform2);
14949
15060
  const entry = config.entry(target);
14950
15061
  const oauth = entry && "url" in entry.config ? entry.config.oauth : void 0;
14951
15062
  const name = entry ? target : `url:${new URL(url).origin}${new URL(url).pathname}`;
14952
- return createMcpAuthProvider({ name, serverUrl: url, source, oauth, platform: platform2 });
15063
+ const provider = createMcpAuthProvider({
15064
+ name,
15065
+ serverUrl: url,
15066
+ source: piSource,
15067
+ oauth,
15068
+ platform: platform2
15069
+ });
15070
+ const credentialSecrets = [];
15071
+ const state = await piSource.loadWithoutLock(name, url);
15072
+ if (state?.tokens?.access_token) credentialSecrets.push(state.tokens.access_token);
15073
+ if (state?.tokens?.refresh_token) credentialSecrets.push(state.tokens.refresh_token);
15074
+ if (state?.clientInformation && "client_secret" in state.clientInformation && state.clientInformation.client_secret) {
15075
+ credentialSecrets.push(state.clientInformation.client_secret);
15076
+ }
15077
+ return { provider, credentialSecrets };
14953
15078
  }
14954
15079
  function classifyConnectionError(err, target, interrupted) {
14955
15080
  if (err instanceof McpAuthError || err instanceof AuthStepUpError || err instanceof JerkSignInRequiredError) {
@@ -14995,7 +15120,7 @@ async function handleInputRequired(platform2, conn, err, respondData, json) {
14995
15120
  `);
14996
15121
  return EXIT_INPUT_REQUIRED;
14997
15122
  }
14998
- const isTty = platform2.isatty(0);
15123
+ const isTty = platform2.isatty(0) && platform2.isatty(2);
14999
15124
  const elicitResult = await handleElicitation(platform2, inputReq, isTty, respondData);
15000
15125
  if ("exitCode" in elicitResult) {
15001
15126
  await platform2.write(2, `${err.requestJson}
@@ -15088,13 +15213,20 @@ async function runClientVerb(platform2, version, parsed) {
15088
15213
  };
15089
15214
  const mergedHeaders = { ...configHeaders, ...expanded };
15090
15215
  const hasAuthHeader = "Authorization" in mergedHeaders;
15091
- const authProvider = await resolveAuthProvider(
15216
+ const authResolved = await resolveAuthProvider(
15092
15217
  platform2,
15093
15218
  hasAuthHeader,
15094
15219
  resolved.url,
15095
15220
  target,
15096
15221
  config
15097
15222
  );
15223
+ const authProvider = authResolved?.provider;
15224
+ if (authResolved?.credentialSecrets) {
15225
+ for (const s of authResolved.credentialSecrets) {
15226
+ allSecrets.add(s);
15227
+ verbose.secrets.add(s);
15228
+ }
15229
+ }
15098
15230
  const roots = buildRoots(parsed.roots, !!resolved.command, platform2.cwd);
15099
15231
  let respondData;
15100
15232
  if (parsed.respondArg) {
@@ -15211,7 +15343,12 @@ function kernelFs(ctx) {
15211
15343
  }
15212
15344
  },
15213
15345
  rmdir: (path) => ctx.fs.rm(path),
15214
- unlink: (path) => ctx.fs.unlink(path)
15346
+ unlink: (path) => ctx.fs.unlink(path),
15347
+ async createExclusive(path) {
15348
+ const f = await ctx.open(path, { create: true, exclusive: true, write: true });
15349
+ await f.close();
15350
+ },
15351
+ chmod: ctx.fs.chmod ? (path, mode) => ctx.fs.chmod(path, mode) : void 0
15215
15352
  };
15216
15353
  }
15217
15354
  async function kernelSpawn(ctx, options) {
@@ -15455,7 +15592,7 @@ async function main(ctx) {
15455
15592
  packageDir: "/node_modules/@ai-ecoverse/mcpcat"
15456
15593
  });
15457
15594
  const args = ctx.argv.slice(1);
15458
- return run(platform2, "0.14.0", args);
15595
+ return run(platform2, "0.14.2", args);
15459
15596
  }
15460
15597
  export {
15461
15598
  main as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/mcpcat",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "description": "A curl for the Model Context Protocol",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -56,7 +56,7 @@
56
56
  "trust:dry": "npx fledgling sync --dry-run -y --skip-publish"
57
57
  },
58
58
  "devDependencies": {
59
- "@ai-ecoverse/slicc-kernel": "1.73.3",
59
+ "@ai-ecoverse/slicc-kernel": "1.75.0",
60
60
  "@ai-ecoverse/slicc-shared-web": "1.13.1",
61
61
  "@biomejs/biome": "2.5.15",
62
62
  "@earendil-works/pi-codemode": "1.2.0",