@kwonye/mcpx 0.1.87 → 0.1.90
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/dist/adapters/claude.d.ts.map +1 -1
- package/dist/{cli-bq7zsrv6.js → cli-btx8jwra.js} +20 -63
- package/dist/{cli-t81mwnff.js → cli-cvve840g.js} +116 -66
- package/dist/{cli-7k3vf6tg.js → cli-mzgjjdjt.js} +117 -67
- package/dist/{cli-dvj5waat.js → cli-qfvawh8e.js} +32 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +12 -17
- package/dist/{config-ajxqtkq6.js → config-nkgc4c4n.js} +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +5 -3
- package/dist/core/registry.d.ts +1 -0
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/status.d.ts.map +1 -1
- package/dist/core/sync.d.ts.map +1 -1
- package/dist/gateway/server.d.ts.map +1 -1
- package/dist/{registry-j53hz9d4.js → registry-vykv33et.js} +3 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
loadConfig,
|
|
3
3
|
loadMergedConfig,
|
|
4
4
|
saveConfig
|
|
5
|
-
} from "./cli-
|
|
5
|
+
} from "./cli-btx8jwra.js";
|
|
6
6
|
import {
|
|
7
7
|
SecretsManager,
|
|
8
8
|
ensureGatewayToken
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-qfvawh8e.js";
|
|
10
10
|
import {
|
|
11
11
|
ensureDir,
|
|
12
12
|
ensureParentDir,
|
|
@@ -290,6 +290,7 @@ function mapRegistryToSpec(_name, option, resolvedValues) {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
// src/adapters/claude.ts
|
|
293
|
+
import fs2 from "node:fs";
|
|
293
294
|
import path2 from "node:path";
|
|
294
295
|
import { z } from "zod";
|
|
295
296
|
|
|
@@ -352,6 +353,9 @@ function errorResult(clientId, configPath, message) {
|
|
|
352
353
|
message
|
|
353
354
|
};
|
|
354
355
|
}
|
|
356
|
+
function managedGatewayEntryName(serverName) {
|
|
357
|
+
return `${serverName} (mcpx)`;
|
|
358
|
+
}
|
|
355
359
|
function isManagedGatewayProjection(entryName) {
|
|
356
360
|
return entryName.endsWith(" (mcpx)");
|
|
357
361
|
}
|
|
@@ -419,6 +423,22 @@ function syncMcpExcludedArray(raw, managedNames, managedEntries) {
|
|
|
419
423
|
}
|
|
420
424
|
|
|
421
425
|
// src/adapters/claude.ts
|
|
426
|
+
function normalizeProjectKey(p) {
|
|
427
|
+
try {
|
|
428
|
+
return fs2.realpathSync(path2.resolve(p));
|
|
429
|
+
} catch {
|
|
430
|
+
return path2.resolve(p);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function syncProjectDisabledArray(project, managedNames, disabledForThisProject) {
|
|
434
|
+
const existingNonManaged = (project.disabledMcpServers ?? []).filter((name) => !managedNames.includes(name));
|
|
435
|
+
const combined = [...existingNonManaged, ...disabledForThisProject];
|
|
436
|
+
if (combined.length > 0) {
|
|
437
|
+
project.disabledMcpServers = combined;
|
|
438
|
+
} else {
|
|
439
|
+
delete project.disabledMcpServers;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
422
442
|
var stringMapSchema = z.record(z.string(), z.string());
|
|
423
443
|
var claudeEntrySchema = z.object({
|
|
424
444
|
type: z.string().optional(),
|
|
@@ -531,12 +551,26 @@ class ClaudeAdapter {
|
|
|
531
551
|
}
|
|
532
552
|
raw.mcpServers = topLevelServers;
|
|
533
553
|
syncDisabledMcpServersArray(raw, managedNames, options.managedEntries);
|
|
554
|
+
const scopeByNormalizedPath = new Map;
|
|
555
|
+
for (const scope of options.projectScopes ?? []) {
|
|
556
|
+
scopeByNormalizedPath.set(normalizeProjectKey(scope.path), scope.disabledServerNames);
|
|
557
|
+
}
|
|
534
558
|
const projects = raw.projects ?? {};
|
|
535
559
|
for (const projectPath of Object.keys(projects)) {
|
|
536
560
|
const project = projects[projectPath] ?? {};
|
|
537
|
-
|
|
561
|
+
const disabledForThis = scopeByNormalizedPath.get(normalizeProjectKey(projectPath)) ?? [];
|
|
562
|
+
syncProjectDisabledArray(project, managedNames, disabledForThis);
|
|
538
563
|
projects[projectPath] = project;
|
|
539
564
|
}
|
|
565
|
+
for (const scope of options.projectScopes ?? []) {
|
|
566
|
+
if (scope.disabledServerNames.length === 0)
|
|
567
|
+
continue;
|
|
568
|
+
const normalizedKey = normalizeProjectKey(scope.path);
|
|
569
|
+
const alreadyExists = Object.keys(projects).some((p) => normalizeProjectKey(p) === normalizedKey);
|
|
570
|
+
if (!alreadyExists) {
|
|
571
|
+
projects[scope.path] = { disabledMcpServers: [...scope.disabledServerNames] };
|
|
572
|
+
}
|
|
573
|
+
}
|
|
540
574
|
raw.projects = projects;
|
|
541
575
|
writeJsonAtomic(configPath, raw);
|
|
542
576
|
setManagedEntries(options.managedIndex, this.id, configPath, Object.fromEntries(Object.entries(serverEntries).map(([name, entry]) => [name, JSON.stringify(entry)])));
|
|
@@ -680,7 +714,7 @@ class ClaudeDesktopAdapter {
|
|
|
680
714
|
|
|
681
715
|
// src/adapters/codex.ts
|
|
682
716
|
import path4 from "node:path";
|
|
683
|
-
import
|
|
717
|
+
import fs3 from "node:fs";
|
|
684
718
|
import { parse, stringify } from "@iarna/toml";
|
|
685
719
|
import { z as z3 } from "zod";
|
|
686
720
|
var stringMapSchema3 = z3.preprocess((value) => {
|
|
@@ -711,10 +745,10 @@ class CodexAdapter {
|
|
|
711
745
|
scanForImports(_config, managedIndex) {
|
|
712
746
|
const configPath = this.detectConfigPath();
|
|
713
747
|
const result = emptyImportScan(this.id, configPath ?? undefined);
|
|
714
|
-
if (!configPath || !
|
|
748
|
+
if (!configPath || !fs3.existsSync(configPath)) {
|
|
715
749
|
return result;
|
|
716
750
|
}
|
|
717
|
-
const existing =
|
|
751
|
+
const existing = fs3.readFileSync(configPath, "utf8");
|
|
718
752
|
const doc = existing.trim().length > 0 ? parse(existing) : {};
|
|
719
753
|
const mcpServers = doc.mcp_servers ?? {};
|
|
720
754
|
for (const [name, rawEntry] of Object.entries(mcpServers)) {
|
|
@@ -769,7 +803,7 @@ class CodexAdapter {
|
|
|
769
803
|
return errorResult(this.id, undefined, "Unable to resolve Codex config.toml path.");
|
|
770
804
|
}
|
|
771
805
|
try {
|
|
772
|
-
const existing =
|
|
806
|
+
const existing = fs3.existsSync(configPath) ? fs3.readFileSync(configPath, "utf8") : "";
|
|
773
807
|
const doc = existing.trim().length > 0 ? parse(existing) : {};
|
|
774
808
|
const mcpServers = doc.mcp_servers ?? {};
|
|
775
809
|
removeSourceEntries(mcpServers, options.sourceEntriesToRemove);
|
|
@@ -790,10 +824,10 @@ class CodexAdapter {
|
|
|
790
824
|
mcpServers[name] = entry;
|
|
791
825
|
}
|
|
792
826
|
doc.mcp_servers = mcpServers;
|
|
793
|
-
|
|
827
|
+
fs3.mkdirSync(path4.dirname(configPath), { recursive: true });
|
|
794
828
|
const tmpPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
|
|
795
|
-
|
|
796
|
-
|
|
829
|
+
fs3.writeFileSync(tmpPath, stringify(doc), { mode: 384 });
|
|
830
|
+
fs3.renameSync(tmpPath, configPath);
|
|
797
831
|
setManagedEntries(options.managedIndex, this.id, configPath, Object.fromEntries(Object.entries(serverEntries).map(([name, entry]) => [name, JSON.stringify(entry)])));
|
|
798
832
|
return okResult(this.id, configPath);
|
|
799
833
|
} catch (error) {
|
|
@@ -933,7 +967,7 @@ class CursorAdapter {
|
|
|
933
967
|
|
|
934
968
|
// src/adapters/cline.ts
|
|
935
969
|
import path6 from "node:path";
|
|
936
|
-
import
|
|
970
|
+
import fs4 from "node:fs";
|
|
937
971
|
import { z as z5 } from "zod";
|
|
938
972
|
var stringMapSchema5 = z5.record(z5.string(), z5.string());
|
|
939
973
|
var clineEntrySchema = z5.object({
|
|
@@ -970,7 +1004,7 @@ class ClineAdapter {
|
|
|
970
1004
|
detectConfigPath() {
|
|
971
1005
|
const candidates = getCandidatePaths();
|
|
972
1006
|
for (const candidate of candidates) {
|
|
973
|
-
if (
|
|
1007
|
+
if (fs4.existsSync(candidate)) {
|
|
974
1008
|
return candidate;
|
|
975
1009
|
}
|
|
976
1010
|
}
|
|
@@ -982,7 +1016,7 @@ class ClineAdapter {
|
|
|
982
1016
|
scanForImports(_config, managedIndex) {
|
|
983
1017
|
const configPath = this.detectConfigPath();
|
|
984
1018
|
const result = emptyImportScan(this.id, configPath ?? undefined);
|
|
985
|
-
if (!configPath || !
|
|
1019
|
+
if (!configPath || !fs4.existsSync(configPath)) {
|
|
986
1020
|
return result;
|
|
987
1021
|
}
|
|
988
1022
|
const raw = readJsonFile(configPath, {});
|
|
@@ -1040,7 +1074,7 @@ class ClineAdapter {
|
|
|
1040
1074
|
if (!configPath) {
|
|
1041
1075
|
return errorResult(this.id, undefined, "Unable to resolve Cline MCP config path.");
|
|
1042
1076
|
}
|
|
1043
|
-
if (!
|
|
1077
|
+
if (!fs4.existsSync(configPath)) {
|
|
1044
1078
|
return okResult(this.id, configPath, "Cline config not found; skipping sync.");
|
|
1045
1079
|
}
|
|
1046
1080
|
try {
|
|
@@ -1080,7 +1114,7 @@ class ClineAdapter {
|
|
|
1080
1114
|
}
|
|
1081
1115
|
|
|
1082
1116
|
// src/adapters/kiro.ts
|
|
1083
|
-
import
|
|
1117
|
+
import fs5 from "node:fs";
|
|
1084
1118
|
import path7 from "node:path";
|
|
1085
1119
|
import { z as z6 } from "zod";
|
|
1086
1120
|
var stringMapSchema6 = z6.record(z6.string(), z6.string());
|
|
@@ -1198,22 +1232,22 @@ class KiroAdapter {
|
|
|
1198
1232
|
}
|
|
1199
1233
|
syncSkills(skills) {
|
|
1200
1234
|
const skillsDir = path7.join(homeDir(), ".kiro", "skills");
|
|
1201
|
-
if (!
|
|
1202
|
-
|
|
1235
|
+
if (!fs5.existsSync(skillsDir)) {
|
|
1236
|
+
fs5.mkdirSync(skillsDir, { recursive: true });
|
|
1203
1237
|
}
|
|
1204
|
-
const existingFiles =
|
|
1238
|
+
const existingFiles = fs5.readdirSync(skillsDir);
|
|
1205
1239
|
const managedIds = new Set(skills.map((s) => s.id));
|
|
1206
1240
|
for (const file of existingFiles) {
|
|
1207
1241
|
if (file.endsWith(".md")) {
|
|
1208
1242
|
const id = path7.basename(file, ".md");
|
|
1209
1243
|
if (!managedIds.has(id)) {
|
|
1210
|
-
|
|
1244
|
+
fs5.unlinkSync(path7.join(skillsDir, file));
|
|
1211
1245
|
}
|
|
1212
1246
|
}
|
|
1213
1247
|
}
|
|
1214
1248
|
for (const skill of skills) {
|
|
1215
1249
|
const targetPath = path7.join(skillsDir, `${skill.id}.md`);
|
|
1216
|
-
|
|
1250
|
+
fs5.writeFileSync(targetPath, skill.content, "utf-8");
|
|
1217
1251
|
}
|
|
1218
1252
|
}
|
|
1219
1253
|
}
|
|
@@ -1468,7 +1502,7 @@ class VsCodeAdapter {
|
|
|
1468
1502
|
}
|
|
1469
1503
|
|
|
1470
1504
|
// src/adapters/qwen.ts
|
|
1471
|
-
import
|
|
1505
|
+
import fs6 from "node:fs";
|
|
1472
1506
|
import path10 from "node:path";
|
|
1473
1507
|
import { z as z9 } from "zod";
|
|
1474
1508
|
var stringMapSchema9 = z9.record(z9.string(), z9.string());
|
|
@@ -1583,22 +1617,22 @@ class QwenAdapter {
|
|
|
1583
1617
|
}
|
|
1584
1618
|
syncSkills(skills) {
|
|
1585
1619
|
const skillsDir = path10.join(homeDir(), ".qwen", "skills");
|
|
1586
|
-
if (!
|
|
1587
|
-
|
|
1620
|
+
if (!fs6.existsSync(skillsDir)) {
|
|
1621
|
+
fs6.mkdirSync(skillsDir, { recursive: true });
|
|
1588
1622
|
}
|
|
1589
|
-
const existingFiles =
|
|
1623
|
+
const existingFiles = fs6.readdirSync(skillsDir);
|
|
1590
1624
|
const managedIds = new Set(skills.map((s) => s.id));
|
|
1591
1625
|
for (const file of existingFiles) {
|
|
1592
1626
|
if (file.endsWith(".md")) {
|
|
1593
1627
|
const id = path10.basename(file, ".md");
|
|
1594
1628
|
if (!managedIds.has(id)) {
|
|
1595
|
-
|
|
1629
|
+
fs6.unlinkSync(path10.join(skillsDir, file));
|
|
1596
1630
|
}
|
|
1597
1631
|
}
|
|
1598
1632
|
}
|
|
1599
1633
|
for (const skill of skills) {
|
|
1600
1634
|
const targetPath = path10.join(skillsDir, `${skill.id}.md`);
|
|
1601
|
-
|
|
1635
|
+
fs6.writeFileSync(targetPath, skill.content, "utf-8");
|
|
1602
1636
|
}
|
|
1603
1637
|
}
|
|
1604
1638
|
}
|
|
@@ -1643,6 +1677,13 @@ function saveManagedIndex(index, filePath = getManagedIndexPath()) {
|
|
|
1643
1677
|
function getGatewayUrl(config) {
|
|
1644
1678
|
return `http://127.0.0.1:${config.gateway.port}/mcp`;
|
|
1645
1679
|
}
|
|
1680
|
+
function buildProjectScopes(config) {
|
|
1681
|
+
const globallyEnabled = new Set(Object.entries(config.servers).filter(([, spec]) => isServerEnabled(spec)).map(([name]) => name));
|
|
1682
|
+
return Object.values(config.projects ?? {}).map((project) => {
|
|
1683
|
+
const disabledServerNames = (project.disabledServers ?? []).filter((name) => globallyEnabled.has(name)).map((name) => managedGatewayEntryName(name));
|
|
1684
|
+
return { path: project.path, disabledServerNames };
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1646
1687
|
function buildManagedEntries(config, gatewayUrl, localToken) {
|
|
1647
1688
|
const entries = Object.entries(config.servers);
|
|
1648
1689
|
return entries.map(([name, spec]) => ({
|
|
@@ -1752,7 +1793,8 @@ function syncAllClients(config, secrets, targetClients) {
|
|
|
1752
1793
|
managedEntries,
|
|
1753
1794
|
managedIndex,
|
|
1754
1795
|
managedIndexPath,
|
|
1755
|
-
sourceEntriesToRemove: Array.from(sourceEntriesToRemove.get(adapter.id) ?? [])
|
|
1796
|
+
sourceEntriesToRemove: Array.from(sourceEntriesToRemove.get(adapter.id) ?? []),
|
|
1797
|
+
projectScopes: buildProjectScopes(config)
|
|
1756
1798
|
});
|
|
1757
1799
|
results.push(result);
|
|
1758
1800
|
}
|
|
@@ -1887,11 +1929,11 @@ function maybePrefixBearer(target, value, raw = false) {
|
|
|
1887
1929
|
// src/core/spawn-env.ts
|
|
1888
1930
|
import os from "node:os";
|
|
1889
1931
|
import path11 from "node:path";
|
|
1890
|
-
import
|
|
1932
|
+
import fs7 from "node:fs";
|
|
1891
1933
|
function existingNvmCurrentBin() {
|
|
1892
1934
|
const nvmDir = process.env.NVM_DIR ?? path11.join(os.homedir(), ".nvm");
|
|
1893
1935
|
const current = path11.join(nvmDir, "current", "bin");
|
|
1894
|
-
return
|
|
1936
|
+
return fs7.existsSync(current) ? current : null;
|
|
1895
1937
|
}
|
|
1896
1938
|
function buildEnrichedPath(current = process.env.PATH ?? "") {
|
|
1897
1939
|
const candidates = [
|
|
@@ -2208,10 +2250,10 @@ async function getOAuthAccessToken(serverName, spec, secrets, options = {}) {
|
|
|
2208
2250
|
}
|
|
2209
2251
|
|
|
2210
2252
|
// src/version.ts
|
|
2211
|
-
var APP_VERSION = "0.1.
|
|
2253
|
+
var APP_VERSION = "0.1.90";
|
|
2212
2254
|
|
|
2213
2255
|
// src/core/update.ts
|
|
2214
|
-
import
|
|
2256
|
+
import fs8 from "node:fs";
|
|
2215
2257
|
import path12 from "node:path";
|
|
2216
2258
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
2217
2259
|
function compareVersions(a, b) {
|
|
@@ -2251,17 +2293,17 @@ async function checkForUpdates() {
|
|
|
2251
2293
|
}
|
|
2252
2294
|
function getStagedUpdate() {
|
|
2253
2295
|
const stagedPath = getStagedVersionPath();
|
|
2254
|
-
if (!
|
|
2296
|
+
if (!fs8.existsSync(stagedPath)) {
|
|
2255
2297
|
return null;
|
|
2256
2298
|
}
|
|
2257
2299
|
try {
|
|
2258
|
-
const raw =
|
|
2300
|
+
const raw = fs8.readFileSync(stagedPath, "utf8");
|
|
2259
2301
|
const info = JSON.parse(raw);
|
|
2260
2302
|
if (!info.version || !info.cliPath) {
|
|
2261
2303
|
return null;
|
|
2262
2304
|
}
|
|
2263
2305
|
const absoluteCliPath = path12.isAbsolute(info.cliPath) ? info.cliPath : path12.join(getUpdatesDir(), info.cliPath);
|
|
2264
|
-
if (!
|
|
2306
|
+
if (!fs8.existsSync(absoluteCliPath)) {
|
|
2265
2307
|
return null;
|
|
2266
2308
|
}
|
|
2267
2309
|
return {
|
|
@@ -2280,15 +2322,15 @@ function stageUpdate(version, cliPath) {
|
|
|
2280
2322
|
cliPath: path12.isAbsolute(cliPath) ? path12.relative(updatesDir, cliPath) : cliPath,
|
|
2281
2323
|
stagedAt: new Date().toISOString()
|
|
2282
2324
|
};
|
|
2283
|
-
|
|
2325
|
+
fs8.writeFileSync(getStagedVersionPath(), JSON.stringify(stagedInfo, null, 2), "utf8");
|
|
2284
2326
|
}
|
|
2285
2327
|
function shouldUseStagedCli(stagedVersion, currentVersion) {
|
|
2286
2328
|
return compareVersions(stagedVersion, currentVersion) > 0;
|
|
2287
2329
|
}
|
|
2288
2330
|
function clearStagedUpdate() {
|
|
2289
2331
|
const stagedPath = getStagedVersionPath();
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2332
|
+
if (fs8.existsSync(stagedPath)) {
|
|
2333
|
+
fs8.unlinkSync(stagedPath);
|
|
2292
2334
|
}
|
|
2293
2335
|
}
|
|
2294
2336
|
function getStagedCliPath() {
|
|
@@ -2297,10 +2339,10 @@ function getStagedCliPath() {
|
|
|
2297
2339
|
}
|
|
2298
2340
|
function removeOldVersions(keepCount = 2) {
|
|
2299
2341
|
const updatesDir = getUpdatesDir();
|
|
2300
|
-
if (!
|
|
2342
|
+
if (!fs8.existsSync(updatesDir)) {
|
|
2301
2343
|
return;
|
|
2302
2344
|
}
|
|
2303
|
-
const entries =
|
|
2345
|
+
const entries = fs8.readdirSync(updatesDir, { withFileTypes: true });
|
|
2304
2346
|
const versionDirs = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith("v")).map((entry) => entry.name).sort((a, b) => compareVersions(b.slice(1), a.slice(1)));
|
|
2305
2347
|
if (versionDirs.length <= keepCount) {
|
|
2306
2348
|
return;
|
|
@@ -2308,20 +2350,20 @@ function removeOldVersions(keepCount = 2) {
|
|
|
2308
2350
|
for (const oldVersion of versionDirs.slice(keepCount)) {
|
|
2309
2351
|
const oldPath = path12.join(updatesDir, oldVersion);
|
|
2310
2352
|
try {
|
|
2311
|
-
|
|
2353
|
+
fs8.rmSync(oldPath, { recursive: true, force: true });
|
|
2312
2354
|
} catch {}
|
|
2313
2355
|
}
|
|
2314
2356
|
}
|
|
2315
2357
|
|
|
2316
2358
|
// src/core/update-manager.ts
|
|
2317
|
-
import
|
|
2359
|
+
import fs9 from "node:fs";
|
|
2318
2360
|
import path13 from "node:path";
|
|
2319
2361
|
import { execSync, spawn } from "node:child_process";
|
|
2320
2362
|
function acquireLock() {
|
|
2321
2363
|
const lockPath = getUpdateLockPath();
|
|
2322
2364
|
try {
|
|
2323
2365
|
ensureDir(path13.dirname(lockPath));
|
|
2324
|
-
|
|
2366
|
+
fs9.writeFileSync(lockPath, `${process.pid}
|
|
2325
2367
|
`, { flag: "wx" });
|
|
2326
2368
|
return true;
|
|
2327
2369
|
} catch {
|
|
@@ -2331,25 +2373,25 @@ function acquireLock() {
|
|
|
2331
2373
|
function releaseLock() {
|
|
2332
2374
|
const lockPath = getUpdateLockPath();
|
|
2333
2375
|
try {
|
|
2334
|
-
|
|
2376
|
+
fs9.unlinkSync(lockPath);
|
|
2335
2377
|
} catch {}
|
|
2336
2378
|
}
|
|
2337
2379
|
function isUpdateInProgress() {
|
|
2338
2380
|
const lockPath = getUpdateLockPath();
|
|
2339
|
-
if (!
|
|
2381
|
+
if (!fs9.existsSync(lockPath)) {
|
|
2340
2382
|
return false;
|
|
2341
2383
|
}
|
|
2342
2384
|
try {
|
|
2343
|
-
const raw =
|
|
2385
|
+
const raw = fs9.readFileSync(lockPath, "utf8").trim();
|
|
2344
2386
|
const pid = Number(raw);
|
|
2345
2387
|
if (!Number.isFinite(pid) || pid <= 0) {
|
|
2346
|
-
|
|
2388
|
+
fs9.unlinkSync(lockPath);
|
|
2347
2389
|
return false;
|
|
2348
2390
|
}
|
|
2349
2391
|
process.kill(pid, 0);
|
|
2350
2392
|
return true;
|
|
2351
2393
|
} catch {
|
|
2352
|
-
|
|
2394
|
+
fs9.unlinkSync(lockPath);
|
|
2353
2395
|
return false;
|
|
2354
2396
|
}
|
|
2355
2397
|
}
|
|
@@ -2361,7 +2403,7 @@ async function downloadAndStageUpdate() {
|
|
|
2361
2403
|
const targetVersion = updateStatus.latestVersion;
|
|
2362
2404
|
const updatesDir = getUpdatesDir();
|
|
2363
2405
|
const versionDir = path13.join(updatesDir, `v${targetVersion}`);
|
|
2364
|
-
if (
|
|
2406
|
+
if (fs9.existsSync(versionDir)) {
|
|
2365
2407
|
const existingStaged = getStagedUpdate();
|
|
2366
2408
|
if (existingStaged?.version === targetVersion) {
|
|
2367
2409
|
return { success: false, error: `Version ${targetVersion} already staged` };
|
|
@@ -2374,7 +2416,7 @@ async function downloadAndStageUpdate() {
|
|
|
2374
2416
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2375
2417
|
});
|
|
2376
2418
|
const tarballPath = path13.join(versionDir, `kwonye-mcpx-${targetVersion}.tgz`);
|
|
2377
|
-
if (!
|
|
2419
|
+
if (!fs9.existsSync(tarballPath)) {
|
|
2378
2420
|
throw new Error("Downloaded tarball not found");
|
|
2379
2421
|
}
|
|
2380
2422
|
execSync(`tar -xzf ${tarballPath} --strip-components=1`, {
|
|
@@ -2386,7 +2428,7 @@ async function downloadAndStageUpdate() {
|
|
|
2386
2428
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2387
2429
|
});
|
|
2388
2430
|
const cliPath = path13.join(versionDir, "dist", "cli.js");
|
|
2389
|
-
if (!
|
|
2431
|
+
if (!fs9.existsSync(cliPath)) {
|
|
2390
2432
|
throw new Error("CLI entry point not found in downloaded package");
|
|
2391
2433
|
}
|
|
2392
2434
|
stageUpdate(targetVersion, cliPath);
|
|
@@ -2394,7 +2436,7 @@ async function downloadAndStageUpdate() {
|
|
|
2394
2436
|
return { success: true, version: targetVersion };
|
|
2395
2437
|
} catch (error) {
|
|
2396
2438
|
try {
|
|
2397
|
-
|
|
2439
|
+
fs9.rmSync(versionDir, { recursive: true, force: true });
|
|
2398
2440
|
} catch {}
|
|
2399
2441
|
return {
|
|
2400
2442
|
success: false,
|
|
@@ -2472,7 +2514,7 @@ function performRollback() {
|
|
|
2472
2514
|
}
|
|
2473
2515
|
|
|
2474
2516
|
// src/core/daemon.ts
|
|
2475
|
-
import
|
|
2517
|
+
import fs10 from "node:fs";
|
|
2476
2518
|
import net from "node:net";
|
|
2477
2519
|
import { spawn as spawn2 } from "node:child_process";
|
|
2478
2520
|
|
|
@@ -2665,7 +2707,8 @@ async function getUpstreamTokenCounts(config, secrets, runtime) {
|
|
|
2665
2707
|
const fingerprint = specFingerprint(upstream.spec);
|
|
2666
2708
|
const cached = runtime.tokenCache.get(upstream.name);
|
|
2667
2709
|
if (cached?.fingerprint === fingerprint) {
|
|
2668
|
-
|
|
2710
|
+
const runtimeError2 = runtime.upstreamErrors?.get(upstream.name);
|
|
2711
|
+
results[upstream.name] = runtimeError2 ? { ...cached.count, runtimeError: runtimeError2 } : cached.count;
|
|
2669
2712
|
continue;
|
|
2670
2713
|
}
|
|
2671
2714
|
let toolsCount = 0;
|
|
@@ -2707,7 +2750,8 @@ async function getUpstreamTokenCounts(config, secrets, runtime) {
|
|
|
2707
2750
|
if (errors.length === 0) {
|
|
2708
2751
|
runtime.tokenCache.set(upstream.name, { fingerprint, count: countObj });
|
|
2709
2752
|
}
|
|
2710
|
-
|
|
2753
|
+
const runtimeError = runtime.upstreamErrors?.get(upstream.name);
|
|
2754
|
+
results[upstream.name] = runtimeError ? { ...countObj, runtimeError } : countObj;
|
|
2711
2755
|
}
|
|
2712
2756
|
return results;
|
|
2713
2757
|
}
|
|
@@ -3043,11 +3087,13 @@ async function routeNamespacedCall(config, method, params, id, secrets, runtime,
|
|
|
3043
3087
|
};
|
|
3044
3088
|
try {
|
|
3045
3089
|
const result = await callUpstream(upstream2, method, upstreamParams2, id, secrets, runtime, clientAuthorizationHeader);
|
|
3090
|
+
runtime.upstreamErrors?.delete(upstream2.name);
|
|
3046
3091
|
return makeResult(id, result);
|
|
3047
3092
|
} catch (error) {
|
|
3048
3093
|
if (isAuthChallenge(error)) {
|
|
3049
3094
|
throw error;
|
|
3050
3095
|
}
|
|
3096
|
+
runtime.upstreamErrors?.set(upstream2.name, error.message);
|
|
3051
3097
|
return makeError(id, -32000, error.message);
|
|
3052
3098
|
}
|
|
3053
3099
|
}
|
|
@@ -3074,11 +3120,13 @@ async function routeNamespacedCall(config, method, params, id, secrets, runtime,
|
|
|
3074
3120
|
};
|
|
3075
3121
|
try {
|
|
3076
3122
|
const result = await callUpstream(upstream2, method, upstreamParams2, id, secrets, runtime, clientAuthorizationHeader);
|
|
3123
|
+
runtime.upstreamErrors?.delete(upstream2.name);
|
|
3077
3124
|
return makeResult(id, result);
|
|
3078
3125
|
} catch (error) {
|
|
3079
3126
|
if (isAuthChallenge(error)) {
|
|
3080
3127
|
throw error;
|
|
3081
3128
|
}
|
|
3129
|
+
runtime.upstreamErrors?.set(upstream2.name, error.message);
|
|
3082
3130
|
return makeError(id, -32000, error.message);
|
|
3083
3131
|
}
|
|
3084
3132
|
}
|
|
@@ -3104,11 +3152,13 @@ async function routeNamespacedCall(config, method, params, id, secrets, runtime,
|
|
|
3104
3152
|
};
|
|
3105
3153
|
try {
|
|
3106
3154
|
const result = await callUpstream(upstream, method, upstreamParams, id, secrets, runtime, clientAuthorizationHeader);
|
|
3155
|
+
runtime.upstreamErrors?.delete(upstream.name);
|
|
3107
3156
|
return makeResult(id, result);
|
|
3108
3157
|
} catch (error) {
|
|
3109
3158
|
if (isAuthChallenge(error)) {
|
|
3110
3159
|
throw error;
|
|
3111
3160
|
}
|
|
3161
|
+
runtime.upstreamErrors?.set(upstream.name, error.message);
|
|
3112
3162
|
return makeError(id, -32000, error.message);
|
|
3113
3163
|
}
|
|
3114
3164
|
}
|
|
@@ -3416,10 +3466,10 @@ function createGatewayServer(options) {
|
|
|
3416
3466
|
|
|
3417
3467
|
// src/core/daemon.ts
|
|
3418
3468
|
function readPidFromFile(pidPath = getPidPath()) {
|
|
3419
|
-
if (!
|
|
3469
|
+
if (!fs10.existsSync(pidPath)) {
|
|
3420
3470
|
return null;
|
|
3421
3471
|
}
|
|
3422
|
-
const raw =
|
|
3472
|
+
const raw = fs10.readFileSync(pidPath, "utf8").trim();
|
|
3423
3473
|
if (!raw) {
|
|
3424
3474
|
return null;
|
|
3425
3475
|
}
|
|
@@ -3521,7 +3571,7 @@ async function startDaemon(config, cliPath, secrets) {
|
|
|
3521
3571
|
};
|
|
3522
3572
|
}
|
|
3523
3573
|
try {
|
|
3524
|
-
|
|
3574
|
+
fs10.unlinkSync(getPidPath());
|
|
3525
3575
|
} catch {}
|
|
3526
3576
|
}
|
|
3527
3577
|
const port = await resolveGatewayPort(config);
|
|
@@ -3530,7 +3580,7 @@ async function startDaemon(config, cliPath, secrets) {
|
|
|
3530
3580
|
const logPath = getLogPath();
|
|
3531
3581
|
ensureParentDir(pidPath);
|
|
3532
3582
|
ensureParentDir(logPath);
|
|
3533
|
-
const logFd =
|
|
3583
|
+
const logFd = fs10.openSync(logPath, "a", 384);
|
|
3534
3584
|
const child = spawn2(process.execPath, [cliPath, "daemon", "run", "--port", String(port)], {
|
|
3535
3585
|
detached: true,
|
|
3536
3586
|
stdio: ["ignore", logFd, logFd],
|
|
@@ -3540,7 +3590,7 @@ async function startDaemon(config, cliPath, secrets) {
|
|
|
3540
3590
|
}
|
|
3541
3591
|
});
|
|
3542
3592
|
child.unref();
|
|
3543
|
-
|
|
3593
|
+
fs10.writeFileSync(pidPath, `${child.pid}
|
|
3544
3594
|
`, { mode: 384 });
|
|
3545
3595
|
startBackgroundUpdateCheck();
|
|
3546
3596
|
await waitForGatewayReady(port, token);
|
|
@@ -3564,7 +3614,7 @@ function stopDaemon() {
|
|
|
3564
3614
|
process.kill(pid, "SIGTERM");
|
|
3565
3615
|
} catch {}
|
|
3566
3616
|
try {
|
|
3567
|
-
|
|
3617
|
+
fs10.unlinkSync(pidPath);
|
|
3568
3618
|
} catch {}
|
|
3569
3619
|
return {
|
|
3570
3620
|
stopped: true,
|
|
@@ -3577,10 +3627,10 @@ async function restartDaemon(config, cliPath, secrets) {
|
|
|
3577
3627
|
}
|
|
3578
3628
|
function readDaemonLogs(maxLines = 200) {
|
|
3579
3629
|
const logPath = getLogPath();
|
|
3580
|
-
if (!
|
|
3630
|
+
if (!fs10.existsSync(logPath)) {
|
|
3581
3631
|
return "";
|
|
3582
3632
|
}
|
|
3583
|
-
const lines =
|
|
3633
|
+
const lines = fs10.readFileSync(logPath, "utf8").split(`
|
|
3584
3634
|
`);
|
|
3585
3635
|
return lines.slice(Math.max(lines.length - maxLines, 0)).join(`
|
|
3586
3636
|
`);
|
|
@@ -3697,11 +3747,11 @@ async function buildStatusReport(config, managedIndex, daemon = getDaemonStatus(
|
|
|
3697
3747
|
tokenCount
|
|
3698
3748
|
};
|
|
3699
3749
|
if (serverEntry.enabled && tokenCount) {
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3750
|
+
totalGlobalTokens += tokenCount.total;
|
|
3751
|
+
for (const projectEntry of projectEntries) {
|
|
3752
|
+
if (!(projectEntry.disabledServers ?? []).includes(name)) {
|
|
3753
|
+
totalProjectTokens[projectEntry.path] = (totalProjectTokens[projectEntry.path] ?? 0) + tokenCount.total;
|
|
3754
|
+
}
|
|
3705
3755
|
}
|
|
3706
3756
|
}
|
|
3707
3757
|
return serverEntry;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
writeJsonAtomic
|
|
8
8
|
} from "./cli-zbbeadz8.js";
|
|
9
9
|
import {
|
|
10
|
+
isServerEnabled,
|
|
10
11
|
normalizeServerSpecEnabled
|
|
11
12
|
} from "./cli-s4gspqdf.js";
|
|
12
13
|
|
|
@@ -88,15 +89,41 @@ function registerProject(globalConfig, projectPath, name) {
|
|
|
88
89
|
if (!globalConfig.projects) {
|
|
89
90
|
globalConfig.projects = {};
|
|
90
91
|
}
|
|
91
|
-
const
|
|
92
|
-
|
|
92
|
+
const resolvedPath = path.resolve(projectPath);
|
|
93
|
+
const projectName = name?.trim() || path.basename(resolvedPath);
|
|
94
|
+
const existing = globalConfig.projects[resolvedPath];
|
|
95
|
+
globalConfig.projects[resolvedPath] = {
|
|
93
96
|
name: projectName,
|
|
94
|
-
path:
|
|
97
|
+
path: resolvedPath,
|
|
98
|
+
disabledServers: existing?.disabledServers ?? []
|
|
95
99
|
};
|
|
96
100
|
}
|
|
97
101
|
function unregisterProject(globalConfig, projectPath) {
|
|
98
102
|
if (globalConfig.projects) {
|
|
99
|
-
delete globalConfig.projects[projectPath];
|
|
103
|
+
delete globalConfig.projects[path.resolve(projectPath)];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function setProjectServerEnabled(globalConfig, projectPath, serverName, enabled) {
|
|
107
|
+
if (!globalConfig.projects)
|
|
108
|
+
globalConfig.projects = {};
|
|
109
|
+
const resolvedPath = path.resolve(projectPath);
|
|
110
|
+
const project = globalConfig.projects[resolvedPath];
|
|
111
|
+
if (!project) {
|
|
112
|
+
throw new Error(`Project "${resolvedPath}" is not registered.`);
|
|
113
|
+
}
|
|
114
|
+
if (!project.disabledServers) {
|
|
115
|
+
project.disabledServers = [];
|
|
116
|
+
}
|
|
117
|
+
if (enabled) {
|
|
118
|
+
project.disabledServers = project.disabledServers.filter((s) => s !== serverName);
|
|
119
|
+
const serverSpec = globalConfig.servers[serverName];
|
|
120
|
+
if (serverSpec && !isServerEnabled(serverSpec)) {
|
|
121
|
+
globalConfig.servers[serverName] = { ...serverSpec, enabled: true };
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
if (!project.disabledServers.includes(serverName)) {
|
|
125
|
+
project.disabledServers.push(serverName);
|
|
126
|
+
}
|
|
100
127
|
}
|
|
101
128
|
}
|
|
102
129
|
|
|
@@ -233,4 +260,4 @@ function readSecretValueFromStdin() {
|
|
|
233
260
|
return content;
|
|
234
261
|
}
|
|
235
262
|
|
|
236
|
-
export { SecretsManager, readSecretValueFromStdin, validateServerName, addServer, removeServer, updateServer, setServerEnabled, getGatewayTokenSecretName, ensureGatewayToken, rotateGatewayToken, registerProject, unregisterProject };
|
|
263
|
+
export { SecretsManager, readSecretValueFromStdin, validateServerName, addServer, removeServer, updateServer, setServerEnabled, getGatewayTokenSecretName, ensureGatewayToken, rotateGatewayToken, registerProject, unregisterProject, setProjectServerEnabled };
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA80DA,wBAAsB,MAAM,CAAC,IAAI,WAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE/D"}
|