@tasksai/install 0.1.14 → 0.1.15

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +28 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tasksai/install",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Shared TasksAI MCP installer CLI",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -10,7 +10,7 @@ import { spawnSync } from "node:child_process";
10
10
  import { stdin as input, stdout as output } from "node:process";
11
11
  import { fileURLToPath } from "node:url";
12
12
 
13
- const INSTALLER_VERSION = "0.1.14";
13
+ const INSTALLER_VERSION = "0.1.15";
14
14
  const INSTALLER_DIR = path.dirname(fileURLToPath(import.meta.url));
15
15
  const BUNDLED_RUNTIME_DIR = path.resolve(INSTALLER_DIR, "..", "runtime");
16
16
  const DEFAULT_SOURCES = {
@@ -20,6 +20,11 @@ const DEFAULT_SOURCES = {
20
20
  teacher: "https://github.com/TasksAI-Official/tasksai-mcp-wrappers/tree/main/verticals/teacher",
21
21
  priorauthai: "https://github.com/laudoluxDev/priorauthai-mcp"
22
22
  };
23
+ const LEGACY_MCP_SERVER_IDS = {
24
+ farmer: ["farmertasksai"],
25
+ realtor: ["realtortasksai"],
26
+ teacher: ["teachertasksai"]
27
+ };
23
28
 
24
29
  const CLIENTS = {
25
30
  "claude-desktop": {
@@ -268,23 +273,23 @@ async function uninstall(options) {
268
273
  }
269
274
 
270
275
  await withLock(`${configPath}.lock`, async () => {
271
- const key = options.productId;
276
+ const keys = mcpServerKeysForProduct(options.productId);
272
277
  if (client.configFormat === "toml") {
273
278
  const text = await fsp.readFile(configPath, "utf8");
274
- if (!tomlHasMcpServer(text, key)) {
275
- console.log(`${client.displayName} does not have a ${key} MCP entry.`);
279
+ if (!tomlHasAnyMcpServer(text, keys)) {
280
+ console.log(`${client.displayName} does not have a ${options.productId} MCP entry.`);
276
281
  return;
277
282
  }
278
283
  await backupFile(configPath);
279
- await atomicWriteText(configPath, removeTomlSections(text, [`mcp_servers.${key}`, `mcp_servers.${key}.env`]));
284
+ await atomicWriteText(configPath, removeTomlSections(text, tomlSectionNamesForProduct(options.productId)));
280
285
  } else {
281
286
  const config = await readJson(configPath);
282
- if (!config.mcpServers?.[key]) {
283
- console.log(`${client.displayName} does not have a ${key} MCP entry.`);
287
+ if (!keys.some((key) => config.mcpServers?.[key])) {
288
+ console.log(`${client.displayName} does not have a ${options.productId} MCP entry.`);
284
289
  return;
285
290
  }
286
291
  await backupFile(configPath);
287
- delete config.mcpServers[key];
292
+ for (const key of keys) delete config.mcpServers[key];
288
293
  await atomicWriteJson(configPath, config);
289
294
  }
290
295
  });
@@ -313,6 +318,7 @@ async function configureMcpClient({ client, vertical, installDir, runtimeDir, ve
313
318
 
314
319
  const config = fs.existsSync(configPath) ? await readJson(configPath) : {};
315
320
  if (!config.mcpServers || typeof config.mcpServers !== "object") config.mcpServers = {};
321
+ for (const key of mcpServerKeysForProduct(vertical.product_id)) delete config.mcpServers[key];
316
322
  config.mcpServers[vertical.product_id] = serverConfig;
317
323
  await atomicWriteJson(configPath, config);
318
324
  });
@@ -346,6 +352,11 @@ function tomlHasMcpServer(text, productId) {
346
352
  return getTomlSectionNames(text).includes(`mcp_servers.${productId}`);
347
353
  }
348
354
 
355
+ function tomlHasAnyMcpServer(text, productIds) {
356
+ const sections = new Set(getTomlSectionNames(text));
357
+ return productIds.some((productId) => sections.has(`mcp_servers.${productId}`));
358
+ }
359
+
349
360
  function getTomlSectionNames(text) {
350
361
  return text
351
362
  .split(/\r?\n/)
@@ -357,11 +368,19 @@ function getTomlSectionNames(text) {
357
368
  }
358
369
 
359
370
  function upsertCodexMcpServer(text, productId, serverConfig) {
360
- const withoutServer = removeTomlSections(text, [`mcp_servers.${productId}`, `mcp_servers.${productId}.env`]).trimEnd();
371
+ const withoutServer = removeTomlSections(text, tomlSectionNamesForProduct(productId)).trimEnd();
361
372
  const block = formatCodexMcpServer(productId, serverConfig);
362
373
  return `${withoutServer ? `${withoutServer}\n\n` : ""}${block}\n`;
363
374
  }
364
375
 
376
+ function mcpServerKeysForProduct(productId) {
377
+ return [...new Set([productId, ...(LEGACY_MCP_SERVER_IDS[productId] || [])])];
378
+ }
379
+
380
+ function tomlSectionNamesForProduct(productId) {
381
+ return mcpServerKeysForProduct(productId).flatMap((key) => [`mcp_servers.${key}`, `mcp_servers.${key}.env`]);
382
+ }
383
+
365
384
  function removeTomlSections(text, sectionNames) {
366
385
  const sections = new Set(sectionNames);
367
386
  const lines = text.split(/\r?\n/);