@neurynae/toolcairn-mcp 0.10.0 → 0.10.1
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/index.js +849 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -336,8 +336,8 @@ var require_logger = __commonJS({
|
|
|
336
336
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
337
337
|
};
|
|
338
338
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
339
|
-
exports.createMcpLogger =
|
|
340
|
-
exports.createLogger =
|
|
339
|
+
exports.createMcpLogger = createMcpLogger24;
|
|
340
|
+
exports.createLogger = createMcpLogger24;
|
|
341
341
|
var node_os_1 = __require("os");
|
|
342
342
|
var node_path_1 = __require("path");
|
|
343
343
|
var pino_1 = __importDefault(__require("pino"));
|
|
@@ -361,7 +361,7 @@ var require_logger = __commonJS({
|
|
|
361
361
|
"*.apiKey",
|
|
362
362
|
"*.api_key"
|
|
363
363
|
];
|
|
364
|
-
function
|
|
364
|
+
function createMcpLogger24(opts) {
|
|
365
365
|
const level = opts.level ?? process.env.LOG_LEVEL ?? (process.env.NODE_ENV !== "production" ? "debug" : "info");
|
|
366
366
|
const pinoOpts = {
|
|
367
367
|
name: opts.name,
|
|
@@ -407,14 +407,14 @@ var require_mcp_error_wrapper = __commonJS({
|
|
|
407
407
|
exports.withErrorHandling = withErrorHandling2;
|
|
408
408
|
var error_codes_js_1 = require_error_codes();
|
|
409
409
|
var errors_js_1 = require_errors();
|
|
410
|
-
function withErrorHandling2(toolName,
|
|
410
|
+
function withErrorHandling2(toolName, logger24, handler) {
|
|
411
411
|
return async (args) => {
|
|
412
412
|
try {
|
|
413
413
|
return await handler(args);
|
|
414
414
|
} catch (err) {
|
|
415
415
|
if (err instanceof errors_js_1.AppError) {
|
|
416
416
|
const logLevel = err.severity === "critical" || err.severity === "high" ? "error" : "warn";
|
|
417
|
-
|
|
417
|
+
logger24[logLevel]({ err, tool: toolName }, `Tool ${toolName} failed: ${err.message}`);
|
|
418
418
|
return {
|
|
419
419
|
content: [
|
|
420
420
|
{
|
|
@@ -429,7 +429,7 @@ var require_mcp_error_wrapper = __commonJS({
|
|
|
429
429
|
isError: true
|
|
430
430
|
};
|
|
431
431
|
}
|
|
432
|
-
|
|
432
|
+
logger24.error({ err, tool: toolName }, `Unexpected error in tool ${toolName}`);
|
|
433
433
|
return {
|
|
434
434
|
content: [
|
|
435
435
|
{
|
|
@@ -512,7 +512,7 @@ var require_dist2 = __commonJS({
|
|
|
512
512
|
// src/index.prod.ts
|
|
513
513
|
init_esm_shims();
|
|
514
514
|
var import_config4 = __toESM(require_dist(), 1);
|
|
515
|
-
var
|
|
515
|
+
var import_errors25 = __toESM(require_dist2(), 1);
|
|
516
516
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
517
517
|
|
|
518
518
|
// ../../packages/remote/dist/index.js
|
|
@@ -814,13 +814,13 @@ var import_errors2 = __toESM(require_dist2(), 1);
|
|
|
814
814
|
async function openBrowser(url) {
|
|
815
815
|
const { spawn } = await import("child_process");
|
|
816
816
|
try {
|
|
817
|
-
const
|
|
817
|
+
const platform3 = process.platform;
|
|
818
818
|
let cmd;
|
|
819
819
|
let args;
|
|
820
|
-
if (
|
|
820
|
+
if (platform3 === "win32") {
|
|
821
821
|
cmd = "cmd";
|
|
822
822
|
args = ["/c", "start", "", url];
|
|
823
|
-
} else if (
|
|
823
|
+
} else if (platform3 === "darwin") {
|
|
824
824
|
cmd = "open";
|
|
825
825
|
args = [url];
|
|
826
826
|
} else {
|
|
@@ -1393,7 +1393,7 @@ async function createIfAbsent(filePath, content, label) {
|
|
|
1393
1393
|
// src/server.prod.ts
|
|
1394
1394
|
init_esm_shims();
|
|
1395
1395
|
var import_config2 = __toESM(require_dist(), 1);
|
|
1396
|
-
var
|
|
1396
|
+
var import_errors24 = __toESM(require_dist2(), 1);
|
|
1397
1397
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1398
1398
|
|
|
1399
1399
|
// ../../packages/tools-local/dist/index.js
|
|
@@ -1602,7 +1602,7 @@ Respond with ONLY 0 or 1.`;
|
|
|
1602
1602
|
|
|
1603
1603
|
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
1604
1604
|
init_esm_shims();
|
|
1605
|
-
var
|
|
1605
|
+
var import_errors20 = __toESM(require_dist2(), 1);
|
|
1606
1606
|
|
|
1607
1607
|
// ../../packages/tools-local/dist/config-store/index.js
|
|
1608
1608
|
init_esm_shims();
|
|
@@ -1915,8 +1915,8 @@ init_esm_shims();
|
|
|
1915
1915
|
|
|
1916
1916
|
// ../../packages/tools-local/dist/discovery/scan-project.js
|
|
1917
1917
|
init_esm_shims();
|
|
1918
|
-
var
|
|
1919
|
-
import { readFile as
|
|
1918
|
+
var import_errors19 = __toESM(require_dist2(), 1);
|
|
1919
|
+
import { readFile as readFile27 } from "fs/promises";
|
|
1920
1920
|
import { basename, resolve } from "path";
|
|
1921
1921
|
|
|
1922
1922
|
// ../../packages/tools-local/dist/discovery/ecosystem-detect.js
|
|
@@ -3415,10 +3415,754 @@ var PARSERS = {
|
|
|
3415
3415
|
"swift-pm": parseSwift
|
|
3416
3416
|
};
|
|
3417
3417
|
|
|
3418
|
+
// ../../packages/tools-local/dist/discovery/resolvers/index.js
|
|
3419
|
+
init_esm_shims();
|
|
3420
|
+
|
|
3421
|
+
// ../../packages/tools-local/dist/discovery/resolvers/cargo.js
|
|
3422
|
+
init_esm_shims();
|
|
3423
|
+
var import_errors9 = __toESM(require_dist2(), 1);
|
|
3424
|
+
import { readFile as readFile16, readdir as readdir5 } from "fs/promises";
|
|
3425
|
+
import { homedir as homedir2 } from "os";
|
|
3426
|
+
import { join as join19 } from "path";
|
|
3427
|
+
import { parse as parseToml3 } from "smol-toml";
|
|
3428
|
+
|
|
3429
|
+
// ../../packages/tools-local/dist/discovery/resolvers/url-normalise.js
|
|
3430
|
+
init_esm_shims();
|
|
3431
|
+
function normaliseGitHubUrl(raw) {
|
|
3432
|
+
if (!raw)
|
|
3433
|
+
return void 0;
|
|
3434
|
+
let s = raw.trim();
|
|
3435
|
+
if (!s)
|
|
3436
|
+
return void 0;
|
|
3437
|
+
if (s.startsWith("git+"))
|
|
3438
|
+
s = s.slice(4);
|
|
3439
|
+
if (s.startsWith("github:")) {
|
|
3440
|
+
s = `https://github.com/${s.slice(7)}`;
|
|
3441
|
+
}
|
|
3442
|
+
if (/^[A-Za-z0-9_.\-]+\/[A-Za-z0-9_.\-]+$/.test(s)) {
|
|
3443
|
+
s = `https://github.com/${s}`;
|
|
3444
|
+
}
|
|
3445
|
+
s = s.replace(/^git@github\.com:/, "https://github.com/");
|
|
3446
|
+
s = s.replace(/^ssh:\/\/git@github\.com\//, "https://github.com/");
|
|
3447
|
+
s = s.replace(/^http:\/\//, "https://");
|
|
3448
|
+
if (!/^https:\/\/github\.com\//.test(s))
|
|
3449
|
+
return void 0;
|
|
3450
|
+
s = s.replace(/\.git$/, "");
|
|
3451
|
+
s = s.replace(/\/$/, "");
|
|
3452
|
+
const match = s.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)/);
|
|
3453
|
+
if (!match)
|
|
3454
|
+
return void 0;
|
|
3455
|
+
return `https://github.com/${match[1]}/${match[2]}`;
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
// ../../packages/tools-local/dist/discovery/resolvers/cargo.js
|
|
3459
|
+
var logger7 = (0, import_errors9.createMcpLogger)({ name: "@toolcairn/tools:resolver:cargo" });
|
|
3460
|
+
async function findCachedCrate(name, preferredVersion) {
|
|
3461
|
+
const registryRoot = join19(homedir2(), ".cargo", "registry", "src");
|
|
3462
|
+
if (!await isDir(registryRoot))
|
|
3463
|
+
return null;
|
|
3464
|
+
let indexHosts;
|
|
3465
|
+
try {
|
|
3466
|
+
indexHosts = await readdir5(registryRoot);
|
|
3467
|
+
} catch {
|
|
3468
|
+
return null;
|
|
3469
|
+
}
|
|
3470
|
+
const matches = [];
|
|
3471
|
+
for (const host of indexHosts) {
|
|
3472
|
+
const hostDir = join19(registryRoot, host);
|
|
3473
|
+
if (!await isDir(hostDir))
|
|
3474
|
+
continue;
|
|
3475
|
+
let entries;
|
|
3476
|
+
try {
|
|
3477
|
+
entries = await readdir5(hostDir);
|
|
3478
|
+
} catch {
|
|
3479
|
+
continue;
|
|
3480
|
+
}
|
|
3481
|
+
for (const entry of entries) {
|
|
3482
|
+
if (!entry.startsWith(`${name}-`))
|
|
3483
|
+
continue;
|
|
3484
|
+
if (preferredVersion && entry !== `${name}-${preferredVersion}`)
|
|
3485
|
+
continue;
|
|
3486
|
+
const manifestPath = join19(hostDir, entry, "Cargo.toml");
|
|
3487
|
+
if (await fileExists(manifestPath))
|
|
3488
|
+
matches.push(manifestPath);
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
if (matches.length === 0)
|
|
3492
|
+
return null;
|
|
3493
|
+
matches.sort();
|
|
3494
|
+
return matches[matches.length - 1] ?? null;
|
|
3495
|
+
}
|
|
3496
|
+
async function resolveCargoIdentity(_workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
3497
|
+
const manifestPath = await findCachedCrate(depName, hints.resolved_version);
|
|
3498
|
+
if (!manifestPath)
|
|
3499
|
+
return {};
|
|
3500
|
+
try {
|
|
3501
|
+
const raw = await readFile16(manifestPath, "utf-8");
|
|
3502
|
+
const doc = parseToml3(raw);
|
|
3503
|
+
const pkg = doc.package;
|
|
3504
|
+
if (!pkg)
|
|
3505
|
+
return {};
|
|
3506
|
+
const out = {};
|
|
3507
|
+
if (pkg.name && pkg.name !== depName)
|
|
3508
|
+
out.canonical_package_name = pkg.name;
|
|
3509
|
+
if (pkg.version)
|
|
3510
|
+
out.resolved_version = pkg.version;
|
|
3511
|
+
const normalised = normaliseGitHubUrl(pkg.repository ?? pkg.homepage);
|
|
3512
|
+
if (normalised)
|
|
3513
|
+
out.github_url = normalised;
|
|
3514
|
+
return out;
|
|
3515
|
+
} catch (err) {
|
|
3516
|
+
logger7.debug({ err: err instanceof Error ? err.message : String(err), manifestPath }, "Failed to parse cached Cargo.toml");
|
|
3517
|
+
return {};
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
// ../../packages/tools-local/dist/discovery/resolvers/composer.js
|
|
3522
|
+
init_esm_shims();
|
|
3523
|
+
var import_errors10 = __toESM(require_dist2(), 1);
|
|
3524
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
3525
|
+
import { join as join20 } from "path";
|
|
3526
|
+
var logger8 = (0, import_errors10.createMcpLogger)({ name: "@toolcairn/tools:resolver:composer" });
|
|
3527
|
+
async function resolveComposerIdentity(workspaceAbs, _projectRoot, depName) {
|
|
3528
|
+
const path2 = join20(workspaceAbs, "vendor", depName, "composer.json");
|
|
3529
|
+
if (!await fileExists(path2))
|
|
3530
|
+
return {};
|
|
3531
|
+
try {
|
|
3532
|
+
const pkg = JSON.parse(await readFile17(path2, "utf-8"));
|
|
3533
|
+
const out = {};
|
|
3534
|
+
if (pkg.name && pkg.name !== depName)
|
|
3535
|
+
out.canonical_package_name = pkg.name;
|
|
3536
|
+
if (pkg.version)
|
|
3537
|
+
out.resolved_version = pkg.version;
|
|
3538
|
+
const candidateUrl = pkg.source?.url ?? pkg.support?.source ?? pkg.homepage;
|
|
3539
|
+
const normalised = normaliseGitHubUrl(candidateUrl);
|
|
3540
|
+
if (normalised)
|
|
3541
|
+
out.github_url = normalised;
|
|
3542
|
+
return out;
|
|
3543
|
+
} catch (err) {
|
|
3544
|
+
logger8.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse installed composer.json");
|
|
3545
|
+
return {};
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
|
|
3549
|
+
// ../../packages/tools-local/dist/discovery/resolvers/go.js
|
|
3550
|
+
init_esm_shims();
|
|
3551
|
+
function resolveGoIdentity(_workspaceAbs, _projectRoot, depName) {
|
|
3552
|
+
if (!depName.startsWith("github.com/"))
|
|
3553
|
+
return {};
|
|
3554
|
+
const tail = depName.slice("github.com/".length);
|
|
3555
|
+
const parts = tail.split("/");
|
|
3556
|
+
if (parts.length < 2 || !parts[0] || !parts[1])
|
|
3557
|
+
return {};
|
|
3558
|
+
const owner = parts[0];
|
|
3559
|
+
let repo = parts[1];
|
|
3560
|
+
repo = repo.replace(/\.git$/, "");
|
|
3561
|
+
const url = normaliseGitHubUrl(`https://github.com/${owner}/${repo}`);
|
|
3562
|
+
return url ? { github_url: url } : {};
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
// ../../packages/tools-local/dist/discovery/resolvers/gradle.js
|
|
3566
|
+
init_esm_shims();
|
|
3567
|
+
import { readdir as readdir6 } from "fs/promises";
|
|
3568
|
+
import { homedir as homedir3 } from "os";
|
|
3569
|
+
import { join as join21 } from "path";
|
|
3570
|
+
|
|
3571
|
+
// ../../packages/tools-local/dist/discovery/resolvers/pom-shared.js
|
|
3572
|
+
init_esm_shims();
|
|
3573
|
+
var import_errors11 = __toESM(require_dist2(), 1);
|
|
3574
|
+
import { readFile as readFile18 } from "fs/promises";
|
|
3575
|
+
import { XMLParser as XMLParser3 } from "fast-xml-parser";
|
|
3576
|
+
var logger9 = (0, import_errors11.createMcpLogger)({ name: "@toolcairn/tools:resolver:pom" });
|
|
3577
|
+
async function parsePomIdentity(path2, depName) {
|
|
3578
|
+
if (!await fileExists(path2))
|
|
3579
|
+
return {};
|
|
3580
|
+
try {
|
|
3581
|
+
const raw = await readFile18(path2, "utf-8");
|
|
3582
|
+
const parser = new XMLParser3({ ignoreAttributes: true, parseTagValue: true });
|
|
3583
|
+
const doc = parser.parse(raw);
|
|
3584
|
+
const project = doc.project;
|
|
3585
|
+
if (!project)
|
|
3586
|
+
return {};
|
|
3587
|
+
const out = {};
|
|
3588
|
+
const canonical = project.groupId && project.artifactId ? `${project.groupId}:${project.artifactId}` : void 0;
|
|
3589
|
+
if (canonical && canonical !== depName)
|
|
3590
|
+
out.canonical_package_name = canonical;
|
|
3591
|
+
if (project.version)
|
|
3592
|
+
out.resolved_version = project.version;
|
|
3593
|
+
const candidateUrls = [
|
|
3594
|
+
project.scm?.url,
|
|
3595
|
+
project.scm?.connection,
|
|
3596
|
+
project.scm?.developerConnection,
|
|
3597
|
+
project.url
|
|
3598
|
+
];
|
|
3599
|
+
for (const u of candidateUrls) {
|
|
3600
|
+
const normalised = normaliseGitHubUrl(u);
|
|
3601
|
+
if (normalised) {
|
|
3602
|
+
out.github_url = normalised;
|
|
3603
|
+
break;
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
return out;
|
|
3607
|
+
} catch (err) {
|
|
3608
|
+
logger9.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse .pom");
|
|
3609
|
+
return {};
|
|
3610
|
+
}
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
// ../../packages/tools-local/dist/discovery/resolvers/gradle.js
|
|
3614
|
+
async function findGradlePom(groupId, artifactId, preferredVersion) {
|
|
3615
|
+
const base = join21(homedir3(), ".gradle", "caches", "modules-2", "files-2.1", groupId, artifactId);
|
|
3616
|
+
if (!await isDir(base))
|
|
3617
|
+
return null;
|
|
3618
|
+
let versions;
|
|
3619
|
+
try {
|
|
3620
|
+
versions = await readdir6(base);
|
|
3621
|
+
} catch {
|
|
3622
|
+
return null;
|
|
3623
|
+
}
|
|
3624
|
+
const chosen = preferredVersion && versions.includes(preferredVersion) ? preferredVersion : versions.sort().at(-1);
|
|
3625
|
+
if (!chosen)
|
|
3626
|
+
return null;
|
|
3627
|
+
const versionDir = join21(base, chosen);
|
|
3628
|
+
let hashDirs;
|
|
3629
|
+
try {
|
|
3630
|
+
hashDirs = await readdir6(versionDir);
|
|
3631
|
+
} catch {
|
|
3632
|
+
return null;
|
|
3633
|
+
}
|
|
3634
|
+
for (const hash of hashDirs) {
|
|
3635
|
+
const candidate = join21(versionDir, hash, `${artifactId}-${chosen}.pom`);
|
|
3636
|
+
return candidate;
|
|
3637
|
+
}
|
|
3638
|
+
return null;
|
|
3639
|
+
}
|
|
3640
|
+
async function resolveGradleIdentity(_workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
3641
|
+
const colon = depName.indexOf(":");
|
|
3642
|
+
if (colon < 0)
|
|
3643
|
+
return {};
|
|
3644
|
+
const groupId = depName.slice(0, colon);
|
|
3645
|
+
const artifactId = depName.slice(colon + 1);
|
|
3646
|
+
if (!groupId || !artifactId)
|
|
3647
|
+
return {};
|
|
3648
|
+
const pomPath = await findGradlePom(groupId, artifactId, hints.resolved_version);
|
|
3649
|
+
if (!pomPath)
|
|
3650
|
+
return {};
|
|
3651
|
+
return parsePomIdentity(pomPath, depName);
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
// ../../packages/tools-local/dist/discovery/resolvers/hex.js
|
|
3655
|
+
init_esm_shims();
|
|
3656
|
+
var import_errors12 = __toESM(require_dist2(), 1);
|
|
3657
|
+
import { readFile as readFile19 } from "fs/promises";
|
|
3658
|
+
import { join as join22 } from "path";
|
|
3659
|
+
var logger10 = (0, import_errors12.createMcpLogger)({ name: "@toolcairn/tools:resolver:hex" });
|
|
3660
|
+
function extractHexMetadataUrl(raw) {
|
|
3661
|
+
let match = raw.match(/<<"GitHub">>\s*,\s*<<"([^"]+)">>/i);
|
|
3662
|
+
if (match?.[1])
|
|
3663
|
+
return match[1];
|
|
3664
|
+
match = raw.match(/<<"[^"]*github[^"]*">>\s*,\s*<<"(https?:\/\/[^"]+)">>/i);
|
|
3665
|
+
if (match?.[1])
|
|
3666
|
+
return match[1];
|
|
3667
|
+
return void 0;
|
|
3668
|
+
}
|
|
3669
|
+
function extractMixExsUrl(raw) {
|
|
3670
|
+
const atMatch = raw.match(/@source_url\s*\(?\s*["']([^"']+)["']/);
|
|
3671
|
+
if (atMatch?.[1])
|
|
3672
|
+
return atMatch[1];
|
|
3673
|
+
const kwMatch = raw.match(/\bsource_url\s*:\s*["']([^"']+)["']/);
|
|
3674
|
+
if (kwMatch?.[1])
|
|
3675
|
+
return kwMatch[1];
|
|
3676
|
+
return void 0;
|
|
3677
|
+
}
|
|
3678
|
+
async function resolveHexIdentity(workspaceAbs, _projectRoot, depName) {
|
|
3679
|
+
const depDir = join22(workspaceAbs, "deps", depName);
|
|
3680
|
+
const out = {};
|
|
3681
|
+
const metaPath = join22(depDir, "hex_metadata.config");
|
|
3682
|
+
if (await fileExists(metaPath)) {
|
|
3683
|
+
try {
|
|
3684
|
+
const raw = await readFile19(metaPath, "utf-8");
|
|
3685
|
+
const url = extractHexMetadataUrl(raw);
|
|
3686
|
+
const normalised = normaliseGitHubUrl(url);
|
|
3687
|
+
if (normalised)
|
|
3688
|
+
out.github_url = normalised;
|
|
3689
|
+
} catch (err) {
|
|
3690
|
+
logger10.debug({ err: err instanceof Error ? err.message : String(err), metaPath }, "Failed to read hex_metadata.config");
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
if (!out.github_url) {
|
|
3694
|
+
const mixPath = join22(depDir, "mix.exs");
|
|
3695
|
+
if (await fileExists(mixPath)) {
|
|
3696
|
+
try {
|
|
3697
|
+
const raw = await readFile19(mixPath, "utf-8");
|
|
3698
|
+
const url = extractMixExsUrl(raw);
|
|
3699
|
+
const normalised = normaliseGitHubUrl(url);
|
|
3700
|
+
if (normalised)
|
|
3701
|
+
out.github_url = normalised;
|
|
3702
|
+
} catch {
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
return out;
|
|
3707
|
+
}
|
|
3708
|
+
|
|
3709
|
+
// ../../packages/tools-local/dist/discovery/resolvers/maven.js
|
|
3710
|
+
init_esm_shims();
|
|
3711
|
+
import { readdir as readdir7 } from "fs/promises";
|
|
3712
|
+
import { homedir as homedir4 } from "os";
|
|
3713
|
+
import { join as join23 } from "path";
|
|
3714
|
+
async function findMavenPom(groupId, artifactId, preferredVersion) {
|
|
3715
|
+
const groupPath = groupId.replace(/\./g, "/");
|
|
3716
|
+
const base = join23(homedir4(), ".m2", "repository", groupPath, artifactId);
|
|
3717
|
+
if (!await isDir(base))
|
|
3718
|
+
return null;
|
|
3719
|
+
let versions;
|
|
3720
|
+
try {
|
|
3721
|
+
versions = await readdir7(base);
|
|
3722
|
+
} catch {
|
|
3723
|
+
return null;
|
|
3724
|
+
}
|
|
3725
|
+
let chosen;
|
|
3726
|
+
if (preferredVersion && versions.includes(preferredVersion)) {
|
|
3727
|
+
chosen = preferredVersion;
|
|
3728
|
+
} else {
|
|
3729
|
+
versions.sort();
|
|
3730
|
+
chosen = versions[versions.length - 1];
|
|
3731
|
+
}
|
|
3732
|
+
if (!chosen)
|
|
3733
|
+
return null;
|
|
3734
|
+
return join23(base, chosen, `${artifactId}-${chosen}.pom`);
|
|
3735
|
+
}
|
|
3736
|
+
async function resolveMavenIdentity(_workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
3737
|
+
const colon = depName.indexOf(":");
|
|
3738
|
+
if (colon < 0)
|
|
3739
|
+
return {};
|
|
3740
|
+
const groupId = depName.slice(0, colon);
|
|
3741
|
+
const artifactId = depName.slice(colon + 1);
|
|
3742
|
+
if (!groupId || !artifactId)
|
|
3743
|
+
return {};
|
|
3744
|
+
const pomPath = await findMavenPom(groupId, artifactId, hints.resolved_version);
|
|
3745
|
+
if (!pomPath)
|
|
3746
|
+
return {};
|
|
3747
|
+
return parsePomIdentity(pomPath, depName);
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3750
|
+
// ../../packages/tools-local/dist/discovery/resolvers/npm.js
|
|
3751
|
+
init_esm_shims();
|
|
3752
|
+
var import_errors13 = __toESM(require_dist2(), 1);
|
|
3753
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
3754
|
+
import { join as join24 } from "path";
|
|
3755
|
+
var logger11 = (0, import_errors13.createMcpLogger)({ name: "@toolcairn/tools:resolver:npm" });
|
|
3756
|
+
function extractRepoUrl(pkg) {
|
|
3757
|
+
const r = pkg.repository;
|
|
3758
|
+
if (!r)
|
|
3759
|
+
return void 0;
|
|
3760
|
+
if (typeof r === "string")
|
|
3761
|
+
return r;
|
|
3762
|
+
return r.url;
|
|
3763
|
+
}
|
|
3764
|
+
async function findInstalledManifest(workspaceAbs, projectRoot, depKey) {
|
|
3765
|
+
let cursor = workspaceAbs;
|
|
3766
|
+
const stopAt = projectRoot;
|
|
3767
|
+
for (let i = 0; i < 10; i++) {
|
|
3768
|
+
const candidate = join24(cursor, "node_modules", depKey, "package.json");
|
|
3769
|
+
if (await fileExists(candidate))
|
|
3770
|
+
return candidate;
|
|
3771
|
+
if (cursor === stopAt)
|
|
3772
|
+
break;
|
|
3773
|
+
const parent = join24(cursor, "..");
|
|
3774
|
+
if (parent === cursor)
|
|
3775
|
+
break;
|
|
3776
|
+
cursor = parent;
|
|
3777
|
+
}
|
|
3778
|
+
return null;
|
|
3779
|
+
}
|
|
3780
|
+
async function resolveNpmIdentity(workspaceAbs, projectRoot, depKey) {
|
|
3781
|
+
const manifestPath = await findInstalledManifest(workspaceAbs, projectRoot, depKey);
|
|
3782
|
+
if (!manifestPath)
|
|
3783
|
+
return {};
|
|
3784
|
+
let pkg;
|
|
3785
|
+
try {
|
|
3786
|
+
pkg = JSON.parse(await readFile20(manifestPath, "utf-8"));
|
|
3787
|
+
} catch (err) {
|
|
3788
|
+
logger11.debug({ err: err instanceof Error ? err.message : String(err), manifestPath }, "Failed to parse installed package.json \u2014 skipping url resolution");
|
|
3789
|
+
return {};
|
|
3790
|
+
}
|
|
3791
|
+
const out = {};
|
|
3792
|
+
if (pkg.name && pkg.name !== depKey) {
|
|
3793
|
+
out.canonical_package_name = pkg.name;
|
|
3794
|
+
}
|
|
3795
|
+
if (pkg.version) {
|
|
3796
|
+
out.resolved_version = pkg.version;
|
|
3797
|
+
}
|
|
3798
|
+
const url = extractRepoUrl(pkg);
|
|
3799
|
+
const normalised = normaliseGitHubUrl(url);
|
|
3800
|
+
if (normalised)
|
|
3801
|
+
out.github_url = normalised;
|
|
3802
|
+
return out;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
// ../../packages/tools-local/dist/discovery/resolvers/nuget.js
|
|
3806
|
+
init_esm_shims();
|
|
3807
|
+
var import_errors14 = __toESM(require_dist2(), 1);
|
|
3808
|
+
import { readFile as readFile21, readdir as readdir8 } from "fs/promises";
|
|
3809
|
+
import { homedir as homedir5 } from "os";
|
|
3810
|
+
import { join as join25 } from "path";
|
|
3811
|
+
import { XMLParser as XMLParser4 } from "fast-xml-parser";
|
|
3812
|
+
var logger12 = (0, import_errors14.createMcpLogger)({ name: "@toolcairn/tools:resolver:nuget" });
|
|
3813
|
+
async function findNuspec(depName, preferredVersion) {
|
|
3814
|
+
const pkgRoot = join25(homedir5(), ".nuget", "packages", depName.toLowerCase());
|
|
3815
|
+
if (!await isDir(pkgRoot))
|
|
3816
|
+
return null;
|
|
3817
|
+
let versions;
|
|
3818
|
+
try {
|
|
3819
|
+
versions = await readdir8(pkgRoot);
|
|
3820
|
+
} catch {
|
|
3821
|
+
return null;
|
|
3822
|
+
}
|
|
3823
|
+
const chosen = preferredVersion && versions.includes(preferredVersion) ? preferredVersion : versions.sort().at(-1);
|
|
3824
|
+
if (!chosen)
|
|
3825
|
+
return null;
|
|
3826
|
+
const path2 = join25(pkgRoot, chosen, `${depName.toLowerCase()}.nuspec`);
|
|
3827
|
+
return await fileExists(path2) ? path2 : null;
|
|
3828
|
+
}
|
|
3829
|
+
async function resolveNugetIdentity(_workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
3830
|
+
const path2 = await findNuspec(depName, hints.resolved_version);
|
|
3831
|
+
if (!path2)
|
|
3832
|
+
return {};
|
|
3833
|
+
try {
|
|
3834
|
+
const raw = await readFile21(path2, "utf-8");
|
|
3835
|
+
const parser = new XMLParser4({ ignoreAttributes: false });
|
|
3836
|
+
const doc = parser.parse(raw);
|
|
3837
|
+
const meta = doc.package?.metadata;
|
|
3838
|
+
if (!meta)
|
|
3839
|
+
return {};
|
|
3840
|
+
const out = {};
|
|
3841
|
+
if (meta.id && meta.id !== depName)
|
|
3842
|
+
out.canonical_package_name = meta.id;
|
|
3843
|
+
if (meta.version)
|
|
3844
|
+
out.resolved_version = meta.version;
|
|
3845
|
+
const repoUrl = meta.repository?.["@_url"] ?? meta.repository?.url;
|
|
3846
|
+
const candidate = normaliseGitHubUrl(repoUrl ?? meta.projectUrl);
|
|
3847
|
+
if (candidate)
|
|
3848
|
+
out.github_url = candidate;
|
|
3849
|
+
return out;
|
|
3850
|
+
} catch (err) {
|
|
3851
|
+
logger12.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse .nuspec");
|
|
3852
|
+
return {};
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
// ../../packages/tools-local/dist/discovery/resolvers/pub.js
|
|
3857
|
+
init_esm_shims();
|
|
3858
|
+
var import_errors15 = __toESM(require_dist2(), 1);
|
|
3859
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
3860
|
+
import { homedir as homedir6, platform as platform2 } from "os";
|
|
3861
|
+
import { join as join26 } from "path";
|
|
3862
|
+
import { parse as parseYaml3 } from "yaml";
|
|
3863
|
+
var logger13 = (0, import_errors15.createMcpLogger)({ name: "@toolcairn/tools:resolver:pub" });
|
|
3864
|
+
function pubCacheRoot() {
|
|
3865
|
+
if (platform2() === "win32") {
|
|
3866
|
+
const local = process.env.LOCALAPPDATA;
|
|
3867
|
+
if (local)
|
|
3868
|
+
return join26(local, "Pub", "Cache", "hosted", "pub.dev");
|
|
3869
|
+
}
|
|
3870
|
+
return join26(homedir6(), ".pub-cache", "hosted", "pub.dev");
|
|
3871
|
+
}
|
|
3872
|
+
async function findPubspec(depName, version) {
|
|
3873
|
+
const root = pubCacheRoot();
|
|
3874
|
+
if (version) {
|
|
3875
|
+
const direct = join26(root, `${depName}-${version}`, "pubspec.yaml");
|
|
3876
|
+
return await fileExists(direct) ? direct : null;
|
|
3877
|
+
}
|
|
3878
|
+
try {
|
|
3879
|
+
const { readdir: readdir12 } = await import("fs/promises");
|
|
3880
|
+
const entries = await readdir12(root);
|
|
3881
|
+
const matches = entries.filter((e) => e.startsWith(`${depName}-`)).sort();
|
|
3882
|
+
const chosen = matches.at(-1);
|
|
3883
|
+
if (!chosen)
|
|
3884
|
+
return null;
|
|
3885
|
+
const candidate = join26(root, chosen, "pubspec.yaml");
|
|
3886
|
+
return await fileExists(candidate) ? candidate : null;
|
|
3887
|
+
} catch {
|
|
3888
|
+
return null;
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
async function resolvePubIdentity(_workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
3892
|
+
const path2 = await findPubspec(depName, hints.resolved_version);
|
|
3893
|
+
if (!path2)
|
|
3894
|
+
return {};
|
|
3895
|
+
try {
|
|
3896
|
+
const raw = await readFile22(path2, "utf-8");
|
|
3897
|
+
const pkg = parseYaml3(raw);
|
|
3898
|
+
const out = {};
|
|
3899
|
+
if (pkg.name && pkg.name !== depName)
|
|
3900
|
+
out.canonical_package_name = pkg.name;
|
|
3901
|
+
if (pkg.version)
|
|
3902
|
+
out.resolved_version = pkg.version;
|
|
3903
|
+
const candidate = normaliseGitHubUrl(pkg.repository ?? pkg.homepage);
|
|
3904
|
+
if (candidate)
|
|
3905
|
+
out.github_url = candidate;
|
|
3906
|
+
return out;
|
|
3907
|
+
} catch (err) {
|
|
3908
|
+
logger13.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse pubspec.yaml");
|
|
3909
|
+
return {};
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
// ../../packages/tools-local/dist/discovery/resolvers/pypi.js
|
|
3914
|
+
init_esm_shims();
|
|
3915
|
+
var import_errors16 = __toESM(require_dist2(), 1);
|
|
3916
|
+
import { readFile as readFile23, readdir as readdir9 } from "fs/promises";
|
|
3917
|
+
import { join as join27 } from "path";
|
|
3918
|
+
var logger14 = (0, import_errors16.createMcpLogger)({ name: "@toolcairn/tools:resolver:pypi" });
|
|
3919
|
+
async function findSitePackagesDirs(workspaceAbs) {
|
|
3920
|
+
const candidates = [];
|
|
3921
|
+
const venvs = [".venv", "venv", ".virtualenv"];
|
|
3922
|
+
for (const venv of venvs) {
|
|
3923
|
+
const venvDir = join27(workspaceAbs, venv);
|
|
3924
|
+
if (!await isDir(venvDir))
|
|
3925
|
+
continue;
|
|
3926
|
+
const winSite = join27(venvDir, "Lib", "site-packages");
|
|
3927
|
+
if (await isDir(winSite))
|
|
3928
|
+
candidates.push(winSite);
|
|
3929
|
+
const libDir = join27(venvDir, "lib");
|
|
3930
|
+
if (await isDir(libDir)) {
|
|
3931
|
+
try {
|
|
3932
|
+
for (const entry of await readdir9(libDir)) {
|
|
3933
|
+
if (!entry.startsWith("python"))
|
|
3934
|
+
continue;
|
|
3935
|
+
const sp = join27(libDir, entry, "site-packages");
|
|
3936
|
+
if (await isDir(sp))
|
|
3937
|
+
candidates.push(sp);
|
|
3938
|
+
}
|
|
3939
|
+
} catch {
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
return candidates;
|
|
3944
|
+
}
|
|
3945
|
+
function normalisePypiName(name) {
|
|
3946
|
+
return name.toLowerCase().replace(/[._]+/g, "-");
|
|
3947
|
+
}
|
|
3948
|
+
async function findMetadataPath(siteDir, depName) {
|
|
3949
|
+
const normalised = normalisePypiName(depName);
|
|
3950
|
+
let entries;
|
|
3951
|
+
try {
|
|
3952
|
+
entries = await readdir9(siteDir);
|
|
3953
|
+
} catch {
|
|
3954
|
+
return null;
|
|
3955
|
+
}
|
|
3956
|
+
for (const entry of entries) {
|
|
3957
|
+
if (!entry.endsWith(".dist-info"))
|
|
3958
|
+
continue;
|
|
3959
|
+
const base = entry.replace(/-[^-]+\.dist-info$/, "");
|
|
3960
|
+
if (normalisePypiName(base) === normalised) {
|
|
3961
|
+
const metadataPath = join27(siteDir, entry, "METADATA");
|
|
3962
|
+
if (await fileExists(metadataPath))
|
|
3963
|
+
return metadataPath;
|
|
3964
|
+
}
|
|
3965
|
+
}
|
|
3966
|
+
return null;
|
|
3967
|
+
}
|
|
3968
|
+
function parseMetadata(raw) {
|
|
3969
|
+
const urls = [];
|
|
3970
|
+
let name;
|
|
3971
|
+
let version;
|
|
3972
|
+
const lines = raw.split("\n");
|
|
3973
|
+
for (const line of lines) {
|
|
3974
|
+
if (line.trim() === "")
|
|
3975
|
+
break;
|
|
3976
|
+
const colon = line.indexOf(":");
|
|
3977
|
+
if (colon < 0)
|
|
3978
|
+
continue;
|
|
3979
|
+
const key = line.slice(0, colon).trim();
|
|
3980
|
+
const val = line.slice(colon + 1).trim();
|
|
3981
|
+
if (key === "Name" && !name)
|
|
3982
|
+
name = val;
|
|
3983
|
+
else if (key === "Version" && !version)
|
|
3984
|
+
version = val;
|
|
3985
|
+
else if (key === "Home-page")
|
|
3986
|
+
urls.push(val);
|
|
3987
|
+
else if (key === "Project-URL") {
|
|
3988
|
+
const comma = val.indexOf(",");
|
|
3989
|
+
if (comma >= 0)
|
|
3990
|
+
urls.push(val.slice(comma + 1).trim());
|
|
3991
|
+
else
|
|
3992
|
+
urls.push(val);
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
return { name, version, urls };
|
|
3996
|
+
}
|
|
3997
|
+
async function resolvePypiIdentity(workspaceAbs, _projectRoot, depName) {
|
|
3998
|
+
const siteDirs = await findSitePackagesDirs(workspaceAbs);
|
|
3999
|
+
for (const siteDir of siteDirs) {
|
|
4000
|
+
const path2 = await findMetadataPath(siteDir, depName);
|
|
4001
|
+
if (!path2)
|
|
4002
|
+
continue;
|
|
4003
|
+
try {
|
|
4004
|
+
const raw = await readFile23(path2, "utf-8");
|
|
4005
|
+
const { name, version, urls } = parseMetadata(raw);
|
|
4006
|
+
const out = {};
|
|
4007
|
+
if (name && normalisePypiName(name) !== normalisePypiName(depName)) {
|
|
4008
|
+
out.canonical_package_name = name;
|
|
4009
|
+
}
|
|
4010
|
+
if (version)
|
|
4011
|
+
out.resolved_version = version;
|
|
4012
|
+
for (const u of urls) {
|
|
4013
|
+
const normalised = normaliseGitHubUrl(u);
|
|
4014
|
+
if (normalised) {
|
|
4015
|
+
out.github_url = normalised;
|
|
4016
|
+
break;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
return out;
|
|
4020
|
+
} catch (err) {
|
|
4021
|
+
logger14.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse METADATA");
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
return {};
|
|
4025
|
+
}
|
|
4026
|
+
|
|
4027
|
+
// ../../packages/tools-local/dist/discovery/resolvers/ruby.js
|
|
4028
|
+
init_esm_shims();
|
|
4029
|
+
var import_errors17 = __toESM(require_dist2(), 1);
|
|
4030
|
+
import { readFile as readFile24, readdir as readdir10 } from "fs/promises";
|
|
4031
|
+
import { homedir as homedir7 } from "os";
|
|
4032
|
+
import { join as join28 } from "path";
|
|
4033
|
+
var logger15 = (0, import_errors17.createMcpLogger)({ name: "@toolcairn/tools:resolver:ruby" });
|
|
4034
|
+
async function findGemspec(workspaceAbs, depName, preferredVersion) {
|
|
4035
|
+
const specsDirs = [];
|
|
4036
|
+
const bundleRubyDir = join28(workspaceAbs, "vendor", "bundle", "ruby");
|
|
4037
|
+
if (await isDir(bundleRubyDir)) {
|
|
4038
|
+
try {
|
|
4039
|
+
for (const entry of await readdir10(bundleRubyDir)) {
|
|
4040
|
+
const dir = join28(bundleRubyDir, entry, "specifications");
|
|
4041
|
+
if (await isDir(dir))
|
|
4042
|
+
specsDirs.push(dir);
|
|
4043
|
+
}
|
|
4044
|
+
} catch {
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
const homeSpecs = join28(homedir7(), ".gem", "specifications");
|
|
4048
|
+
if (await isDir(homeSpecs))
|
|
4049
|
+
specsDirs.push(homeSpecs);
|
|
4050
|
+
for (const dir of specsDirs) {
|
|
4051
|
+
let entries;
|
|
4052
|
+
try {
|
|
4053
|
+
entries = await readdir10(dir);
|
|
4054
|
+
} catch {
|
|
4055
|
+
continue;
|
|
4056
|
+
}
|
|
4057
|
+
const matches = entries.filter((e) => e.endsWith(".gemspec") && e.startsWith(`${depName}-`)).filter((e) => {
|
|
4058
|
+
if (!preferredVersion)
|
|
4059
|
+
return true;
|
|
4060
|
+
return e === `${depName}-${preferredVersion}.gemspec`;
|
|
4061
|
+
}).sort();
|
|
4062
|
+
const chosen = matches.at(-1);
|
|
4063
|
+
if (chosen) {
|
|
4064
|
+
const path2 = join28(dir, chosen);
|
|
4065
|
+
if (await fileExists(path2))
|
|
4066
|
+
return path2;
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
return null;
|
|
4070
|
+
}
|
|
4071
|
+
function extractGemspecFields(raw) {
|
|
4072
|
+
const out = {};
|
|
4073
|
+
const pick = (pattern) => {
|
|
4074
|
+
const m = raw.match(pattern);
|
|
4075
|
+
return m ? m[1] : void 0;
|
|
4076
|
+
};
|
|
4077
|
+
out.name = pick(/(?:s|spec)\.name\s*=\s*(['"])([^'"]+)\1/) ? raw.match(/(?:s|spec)\.name\s*=\s*['"]([^'"]+)['"]/)?.[1] : void 0;
|
|
4078
|
+
out.version = raw.match(/(?:s|spec)\.version\s*=\s*['"]([^'"]+)['"]/)?.[1];
|
|
4079
|
+
out.homepage = raw.match(/(?:s|spec)\.homepage\s*=\s*['"]([^'"]+)['"]/)?.[1];
|
|
4080
|
+
out.source_code_uri = raw.match(/["']source_code_uri["']\s*=>\s*["']([^'"]+)["']/)?.[1];
|
|
4081
|
+
return out;
|
|
4082
|
+
}
|
|
4083
|
+
async function resolveRubyIdentity(workspaceAbs, _projectRoot, depName, hints = {}) {
|
|
4084
|
+
const path2 = await findGemspec(workspaceAbs, depName, hints.resolved_version);
|
|
4085
|
+
if (!path2)
|
|
4086
|
+
return {};
|
|
4087
|
+
try {
|
|
4088
|
+
const raw = await readFile24(path2, "utf-8");
|
|
4089
|
+
const fields = extractGemspecFields(raw);
|
|
4090
|
+
const out = {};
|
|
4091
|
+
if (fields.name && fields.name !== depName)
|
|
4092
|
+
out.canonical_package_name = fields.name;
|
|
4093
|
+
if (fields.version)
|
|
4094
|
+
out.resolved_version = fields.version;
|
|
4095
|
+
const candidate = normaliseGitHubUrl(fields.source_code_uri ?? fields.homepage);
|
|
4096
|
+
if (candidate)
|
|
4097
|
+
out.github_url = candidate;
|
|
4098
|
+
return out;
|
|
4099
|
+
} catch (err) {
|
|
4100
|
+
logger15.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to read/parse gemspec");
|
|
4101
|
+
return {};
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
|
|
4105
|
+
// ../../packages/tools-local/dist/discovery/resolvers/swift-pm.js
|
|
4106
|
+
init_esm_shims();
|
|
4107
|
+
var import_errors18 = __toESM(require_dist2(), 1);
|
|
4108
|
+
import { readFile as readFile25 } from "fs/promises";
|
|
4109
|
+
import { join as join29 } from "path";
|
|
4110
|
+
var logger16 = (0, import_errors18.createMcpLogger)({ name: "@toolcairn/tools:resolver:swift-pm" });
|
|
4111
|
+
async function resolveSwiftPmIdentity(workspaceAbs, _projectRoot, depName) {
|
|
4112
|
+
const path2 = join29(workspaceAbs, "Package.resolved");
|
|
4113
|
+
if (!await fileExists(path2))
|
|
4114
|
+
return {};
|
|
4115
|
+
try {
|
|
4116
|
+
const raw = await readFile25(path2, "utf-8");
|
|
4117
|
+
const doc = JSON.parse(raw);
|
|
4118
|
+
const out = {};
|
|
4119
|
+
for (const pin of doc.pins ?? []) {
|
|
4120
|
+
if (pin.identity === depName) {
|
|
4121
|
+
if (pin.state?.version)
|
|
4122
|
+
out.resolved_version = pin.state.version;
|
|
4123
|
+
const normalised = normaliseGitHubUrl(pin.location);
|
|
4124
|
+
if (normalised)
|
|
4125
|
+
out.github_url = normalised;
|
|
4126
|
+
return out;
|
|
4127
|
+
}
|
|
4128
|
+
}
|
|
4129
|
+
for (const pin of doc.object?.pins ?? []) {
|
|
4130
|
+
if (pin.package === depName) {
|
|
4131
|
+
if (pin.state?.version)
|
|
4132
|
+
out.resolved_version = pin.state.version;
|
|
4133
|
+
const normalised = normaliseGitHubUrl(pin.repositoryURL);
|
|
4134
|
+
if (normalised)
|
|
4135
|
+
out.github_url = normalised;
|
|
4136
|
+
return out;
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
return {};
|
|
4140
|
+
} catch (err) {
|
|
4141
|
+
logger16.debug({ err: err instanceof Error ? err.message : String(err), path: path2 }, "Failed to parse Package.resolved during resolve");
|
|
4142
|
+
return {};
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
|
|
4146
|
+
// ../../packages/tools-local/dist/discovery/resolvers/index.js
|
|
4147
|
+
var RESOLVERS = {
|
|
4148
|
+
npm: resolveNpmIdentity,
|
|
4149
|
+
pypi: resolvePypiIdentity,
|
|
4150
|
+
cargo: resolveCargoIdentity,
|
|
4151
|
+
go: (w, p, n) => resolveGoIdentity(w, p, n),
|
|
4152
|
+
rubygems: resolveRubyIdentity,
|
|
4153
|
+
maven: resolveMavenIdentity,
|
|
4154
|
+
gradle: resolveGradleIdentity,
|
|
4155
|
+
composer: resolveComposerIdentity,
|
|
4156
|
+
hex: resolveHexIdentity,
|
|
4157
|
+
pub: resolvePubIdentity,
|
|
4158
|
+
nuget: resolveNugetIdentity,
|
|
4159
|
+
"swift-pm": resolveSwiftPmIdentity
|
|
4160
|
+
};
|
|
4161
|
+
|
|
3418
4162
|
// ../../packages/tools-local/dist/discovery/workspaces/glob.js
|
|
3419
4163
|
init_esm_shims();
|
|
3420
|
-
import { readdir as
|
|
3421
|
-
import { join as
|
|
4164
|
+
import { readdir as readdir11 } from "fs/promises";
|
|
4165
|
+
import { join as join30, relative as relative3, sep as sep2 } from "path";
|
|
3422
4166
|
async function expandWorkspaceGlobs(rootDir, patterns) {
|
|
3423
4167
|
const excluded = /* @__PURE__ */ new Set();
|
|
3424
4168
|
const included = /* @__PURE__ */ new Set();
|
|
@@ -3454,11 +4198,11 @@ async function walkPattern(rootDir, currentDir, parts, index, out) {
|
|
|
3454
4198
|
if (segment === "**") {
|
|
3455
4199
|
await walkPattern(rootDir, currentDir, parts, index + 1, out);
|
|
3456
4200
|
try {
|
|
3457
|
-
const entries = await
|
|
4201
|
+
const entries = await readdir11(currentDir, { withFileTypes: true });
|
|
3458
4202
|
for (const entry of entries) {
|
|
3459
4203
|
if (!entry.isDirectory() || IGNORED_DIRS.has(entry.name))
|
|
3460
4204
|
continue;
|
|
3461
|
-
await walkPattern(rootDir,
|
|
4205
|
+
await walkPattern(rootDir, join30(currentDir, entry.name), parts, index, out);
|
|
3462
4206
|
}
|
|
3463
4207
|
} catch {
|
|
3464
4208
|
}
|
|
@@ -3467,19 +4211,19 @@ async function walkPattern(rootDir, currentDir, parts, index, out) {
|
|
|
3467
4211
|
if (segment.includes("*")) {
|
|
3468
4212
|
const re = globSegmentToRegex(segment);
|
|
3469
4213
|
try {
|
|
3470
|
-
const entries = await
|
|
4214
|
+
const entries = await readdir11(currentDir, { withFileTypes: true });
|
|
3471
4215
|
for (const entry of entries) {
|
|
3472
4216
|
if (!entry.isDirectory() || IGNORED_DIRS.has(entry.name))
|
|
3473
4217
|
continue;
|
|
3474
4218
|
if (re.test(entry.name)) {
|
|
3475
|
-
await walkPattern(rootDir,
|
|
4219
|
+
await walkPattern(rootDir, join30(currentDir, entry.name), parts, index + 1, out);
|
|
3476
4220
|
}
|
|
3477
4221
|
}
|
|
3478
4222
|
} catch {
|
|
3479
4223
|
}
|
|
3480
4224
|
return;
|
|
3481
4225
|
}
|
|
3482
|
-
await walkPattern(rootDir,
|
|
4226
|
+
await walkPattern(rootDir, join30(currentDir, segment), parts, index + 1, out);
|
|
3483
4227
|
}
|
|
3484
4228
|
function globSegmentToRegex(segment) {
|
|
3485
4229
|
const escaped = segment.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
@@ -3492,10 +4236,10 @@ function toRelPosix(projectRoot, absPath) {
|
|
|
3492
4236
|
|
|
3493
4237
|
// ../../packages/tools-local/dist/discovery/workspaces/walker.js
|
|
3494
4238
|
init_esm_shims();
|
|
3495
|
-
import { readFile as
|
|
3496
|
-
import { join as
|
|
3497
|
-
import { parse as
|
|
3498
|
-
import { parse as
|
|
4239
|
+
import { readFile as readFile26 } from "fs/promises";
|
|
4240
|
+
import { join as join31 } from "path";
|
|
4241
|
+
import { parse as parseToml4 } from "smol-toml";
|
|
4242
|
+
import { parse as parseYaml4 } from "yaml";
|
|
3499
4243
|
async function discoverWorkspaces(projectRoot, maxDepth = 5) {
|
|
3500
4244
|
const warnings = [];
|
|
3501
4245
|
const discovered = /* @__PURE__ */ new Set([projectRoot]);
|
|
@@ -3521,10 +4265,10 @@ async function discoverWorkspaces(projectRoot, maxDepth = 5) {
|
|
|
3521
4265
|
}
|
|
3522
4266
|
async function readWorkspaceGlobs(dir, warnings) {
|
|
3523
4267
|
const globs = [];
|
|
3524
|
-
const pnpmPath =
|
|
4268
|
+
const pnpmPath = join31(dir, "pnpm-workspace.yaml");
|
|
3525
4269
|
if (await fileExists(pnpmPath)) {
|
|
3526
4270
|
try {
|
|
3527
|
-
const doc =
|
|
4271
|
+
const doc = parseYaml4(await readFile26(pnpmPath, "utf-8"));
|
|
3528
4272
|
if (Array.isArray(doc.packages))
|
|
3529
4273
|
globs.push(...doc.packages);
|
|
3530
4274
|
} catch (err) {
|
|
@@ -3535,10 +4279,10 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3535
4279
|
});
|
|
3536
4280
|
}
|
|
3537
4281
|
}
|
|
3538
|
-
const pkgPath =
|
|
4282
|
+
const pkgPath = join31(dir, "package.json");
|
|
3539
4283
|
if (await fileExists(pkgPath)) {
|
|
3540
4284
|
try {
|
|
3541
|
-
const doc = JSON.parse(await
|
|
4285
|
+
const doc = JSON.parse(await readFile26(pkgPath, "utf-8"));
|
|
3542
4286
|
if (Array.isArray(doc.workspaces)) {
|
|
3543
4287
|
globs.push(...doc.workspaces);
|
|
3544
4288
|
} else if (doc.workspaces && Array.isArray(doc.workspaces.packages)) {
|
|
@@ -3552,10 +4296,10 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3552
4296
|
});
|
|
3553
4297
|
}
|
|
3554
4298
|
}
|
|
3555
|
-
const cargoPath =
|
|
4299
|
+
const cargoPath = join31(dir, "Cargo.toml");
|
|
3556
4300
|
if (await fileExists(cargoPath)) {
|
|
3557
4301
|
try {
|
|
3558
|
-
const doc =
|
|
4302
|
+
const doc = parseToml4(await readFile26(cargoPath, "utf-8"));
|
|
3559
4303
|
if (Array.isArray(doc.workspace?.members))
|
|
3560
4304
|
globs.push(...doc.workspace.members);
|
|
3561
4305
|
} catch (err) {
|
|
@@ -3566,10 +4310,10 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3566
4310
|
});
|
|
3567
4311
|
}
|
|
3568
4312
|
}
|
|
3569
|
-
const goWorkPath =
|
|
4313
|
+
const goWorkPath = join31(dir, "go.work");
|
|
3570
4314
|
if (await fileExists(goWorkPath)) {
|
|
3571
4315
|
try {
|
|
3572
|
-
const raw = await
|
|
4316
|
+
const raw = await readFile26(goWorkPath, "utf-8");
|
|
3573
4317
|
const useMatch = raw.match(/use\s*\(([^)]*)\)/s);
|
|
3574
4318
|
if (useMatch?.[1]) {
|
|
3575
4319
|
for (const line of useMatch[1].split("\n")) {
|
|
@@ -3592,10 +4336,10 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3592
4336
|
});
|
|
3593
4337
|
}
|
|
3594
4338
|
}
|
|
3595
|
-
const lernaPath =
|
|
4339
|
+
const lernaPath = join31(dir, "lerna.json");
|
|
3596
4340
|
if (await fileExists(lernaPath)) {
|
|
3597
4341
|
try {
|
|
3598
|
-
const doc = JSON.parse(await
|
|
4342
|
+
const doc = JSON.parse(await readFile26(lernaPath, "utf-8"));
|
|
3599
4343
|
if (Array.isArray(doc.packages))
|
|
3600
4344
|
globs.push(...doc.packages);
|
|
3601
4345
|
} catch (err) {
|
|
@@ -3606,10 +4350,10 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3606
4350
|
});
|
|
3607
4351
|
}
|
|
3608
4352
|
}
|
|
3609
|
-
const nxPath =
|
|
4353
|
+
const nxPath = join31(dir, "nx.json");
|
|
3610
4354
|
if (await fileExists(nxPath)) {
|
|
3611
4355
|
try {
|
|
3612
|
-
const doc = JSON.parse(await
|
|
4356
|
+
const doc = JSON.parse(await readFile26(nxPath, "utf-8"));
|
|
3613
4357
|
const base = doc.workspaceLayout?.projectsDir ?? "packages";
|
|
3614
4358
|
globs.push(`${base}/*`);
|
|
3615
4359
|
} catch (err) {
|
|
@@ -3624,13 +4368,13 @@ async function readWorkspaceGlobs(dir, warnings) {
|
|
|
3624
4368
|
}
|
|
3625
4369
|
|
|
3626
4370
|
// ../../packages/tools-local/dist/discovery/scan-project.js
|
|
3627
|
-
var
|
|
4371
|
+
var logger17 = (0, import_errors19.createMcpLogger)({ name: "@toolcairn/tools:scan-project" });
|
|
3628
4372
|
async function scanProject(projectRoot, options = {}) {
|
|
3629
4373
|
const start = Date.now();
|
|
3630
4374
|
const { batchResolve, maxDepth = 5 } = options;
|
|
3631
4375
|
const absRoot = resolve(projectRoot);
|
|
3632
4376
|
const warnings = [];
|
|
3633
|
-
|
|
4377
|
+
logger17.info({ projectRoot: absRoot }, "Starting project scan");
|
|
3634
4378
|
const { paths: workspaceAbs, warnings: wsWarnings } = await discoverWorkspaces(absRoot, maxDepth);
|
|
3635
4379
|
warnings.push(...wsWarnings);
|
|
3636
4380
|
const allDetected = [];
|
|
@@ -3688,9 +4432,41 @@ async function scanProject(projectRoot, options = {}) {
|
|
|
3688
4432
|
mergedMap.set(key, { name: dep.name, ecosystem: dep.ecosystem, locations: [location] });
|
|
3689
4433
|
}
|
|
3690
4434
|
}
|
|
4435
|
+
await Promise.all([...mergedMap.values()].map(async (entry) => {
|
|
4436
|
+
const resolver = RESOLVERS[entry.ecosystem];
|
|
4437
|
+
if (!resolver)
|
|
4438
|
+
return;
|
|
4439
|
+
for (const loc of entry.locations) {
|
|
4440
|
+
const workspaceAbs2 = resolve(absRoot, loc.workspace_path);
|
|
4441
|
+
const hints = { resolved_version: loc.resolved_version };
|
|
4442
|
+
try {
|
|
4443
|
+
const identity = await resolver(workspaceAbs2, absRoot, entry.name, hints);
|
|
4444
|
+
if (identity.canonical_package_name) {
|
|
4445
|
+
entry.canonical_package_name = identity.canonical_package_name;
|
|
4446
|
+
}
|
|
4447
|
+
if (identity.github_url) {
|
|
4448
|
+
entry.local_github_url = identity.github_url;
|
|
4449
|
+
}
|
|
4450
|
+
if (identity.canonical_package_name || identity.github_url)
|
|
4451
|
+
break;
|
|
4452
|
+
} catch (err) {
|
|
4453
|
+
logger17.debug({
|
|
4454
|
+
ecosystem: entry.ecosystem,
|
|
4455
|
+
name: entry.name,
|
|
4456
|
+
workspace: loc.workspace_path,
|
|
4457
|
+
err: err instanceof Error ? err.message : String(err)
|
|
4458
|
+
}, "Resolver threw \u2014 skipping this location");
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
}));
|
|
3691
4462
|
const workspaceRels = workspaceAbs.map((abs) => toRelPosix(absRoot, abs));
|
|
3692
4463
|
const languages = await detectLanguages(absRoot, workspaceRels);
|
|
3693
|
-
const resolveInputs = [...mergedMap.values()].map(({ name: name2, ecosystem }) => ({
|
|
4464
|
+
const resolveInputs = [...mergedMap.values()].map(({ name: name2, ecosystem, canonical_package_name, local_github_url }) => ({
|
|
4465
|
+
name: name2,
|
|
4466
|
+
ecosystem,
|
|
4467
|
+
canonical_package_name,
|
|
4468
|
+
github_url: local_github_url
|
|
4469
|
+
}));
|
|
3694
4470
|
const resolved = /* @__PURE__ */ new Map();
|
|
3695
4471
|
const methods = /* @__PURE__ */ new Map();
|
|
3696
4472
|
const githubUrls = /* @__PURE__ */ new Map();
|
|
@@ -3722,7 +4498,7 @@ async function scanProject(projectRoot, options = {}) {
|
|
|
3722
4498
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3723
4499
|
const confirmed = [];
|
|
3724
4500
|
let toolsResolvedCount = 0;
|
|
3725
|
-
for (const { name: name2, ecosystem, locations } of mergedMap.values()) {
|
|
4501
|
+
for (const { name: name2, ecosystem, locations, local_github_url } of mergedMap.values()) {
|
|
3726
4502
|
const key = `${ecosystem}:${name2}`;
|
|
3727
4503
|
const graph = resolved.get(key);
|
|
3728
4504
|
const matchMethod = methods.get(key) ?? "none";
|
|
@@ -3732,7 +4508,7 @@ async function scanProject(projectRoot, options = {}) {
|
|
|
3732
4508
|
const source = matched ? "toolcairn" : "non_oss";
|
|
3733
4509
|
const canonical = graph?.tool?.canonical_name;
|
|
3734
4510
|
const categories = graph?.tool?.categories;
|
|
3735
|
-
const github_url = githubUrls.get(key);
|
|
4511
|
+
const github_url = githubUrls.get(key) ?? local_github_url;
|
|
3736
4512
|
const version = locations.find((l) => l.resolved_version)?.resolved_version ?? locations[0]?.version_constraint;
|
|
3737
4513
|
confirmed.push({
|
|
3738
4514
|
name: name2,
|
|
@@ -3764,7 +4540,7 @@ async function scanProject(projectRoot, options = {}) {
|
|
|
3764
4540
|
duration_ms: Date.now() - start,
|
|
3765
4541
|
completed_at: now
|
|
3766
4542
|
};
|
|
3767
|
-
|
|
4543
|
+
logger17.info({
|
|
3768
4544
|
projectRoot: absRoot,
|
|
3769
4545
|
workspaces: workspaceAbs.length,
|
|
3770
4546
|
ecosystems: scan_metadata.ecosystems_scanned,
|
|
@@ -3816,7 +4592,7 @@ async function inferProjectName(projectRoot) {
|
|
|
3816
4592
|
const pkgPath = resolve(projectRoot, "package.json");
|
|
3817
4593
|
if (await fileExists(pkgPath)) {
|
|
3818
4594
|
try {
|
|
3819
|
-
const doc = JSON.parse(await
|
|
4595
|
+
const doc = JSON.parse(await readFile27(pkgPath, "utf-8"));
|
|
3820
4596
|
if (doc.name)
|
|
3821
4597
|
return doc.name;
|
|
3822
4598
|
} catch {
|
|
@@ -3998,10 +4774,10 @@ function getOpenCodeMcpEntry(serverPath) {
|
|
|
3998
4774
|
}
|
|
3999
4775
|
|
|
4000
4776
|
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
4001
|
-
var
|
|
4777
|
+
var logger18 = (0, import_errors20.createMcpLogger)({ name: "@toolcairn/tools:toolcairn-init" });
|
|
4002
4778
|
async function handleToolcairnInit(args, deps = {}) {
|
|
4003
4779
|
try {
|
|
4004
|
-
|
|
4780
|
+
logger18.info({ agent: args.agent, project_root: args.project_root }, "toolcairn_init called");
|
|
4005
4781
|
const scan = await scanProject(args.project_root, { batchResolve: deps.batchResolve });
|
|
4006
4782
|
const audit = {
|
|
4007
4783
|
action: "init",
|
|
@@ -4072,22 +4848,22 @@ async function handleToolcairnInit(args, deps = {}) {
|
|
|
4072
4848
|
next_steps: "Config written. Apply the setup_steps above (CLAUDE.md rules + .mcp.json merge + .gitignore). Then proceed with normal tool calls \u2014 the server owns .toolcairn/ going forward."
|
|
4073
4849
|
});
|
|
4074
4850
|
} catch (e) {
|
|
4075
|
-
|
|
4851
|
+
logger18.error({ err: e }, "toolcairn_init failed");
|
|
4076
4852
|
return errResult("init_error", e instanceof Error ? e.message : String(e));
|
|
4077
4853
|
}
|
|
4078
4854
|
}
|
|
4079
4855
|
|
|
4080
4856
|
// ../../packages/tools-local/dist/handlers/read-project-config.js
|
|
4081
4857
|
init_esm_shims();
|
|
4082
|
-
var
|
|
4083
|
-
var
|
|
4858
|
+
var import_errors21 = __toESM(require_dist2(), 1);
|
|
4859
|
+
var logger19 = (0, import_errors21.createMcpLogger)({ name: "@toolcairn/tools:read-project-config" });
|
|
4084
4860
|
var STALENESS_THRESHOLD_DAYS = 90;
|
|
4085
4861
|
function daysSince(isoDate) {
|
|
4086
4862
|
return (Date.now() - new Date(isoDate).getTime()) / (1e3 * 60 * 60 * 24);
|
|
4087
4863
|
}
|
|
4088
4864
|
async function handleReadProjectConfig(args) {
|
|
4089
4865
|
try {
|
|
4090
|
-
|
|
4866
|
+
logger19.info({ project_root: args.project_root }, "read_project_config called");
|
|
4091
4867
|
const { config: initial, corrupt_backup_path } = await readConfig(args.project_root);
|
|
4092
4868
|
if (!initial) {
|
|
4093
4869
|
return okResult({
|
|
@@ -4170,18 +4946,18 @@ async function handleReadProjectConfig(args) {
|
|
|
4170
4946
|
agent_instructions: instructions_lines.join("\n")
|
|
4171
4947
|
});
|
|
4172
4948
|
} catch (e) {
|
|
4173
|
-
|
|
4949
|
+
logger19.error({ err: e }, "read_project_config failed");
|
|
4174
4950
|
return errResult("read_config_error", e instanceof Error ? e.message : String(e));
|
|
4175
4951
|
}
|
|
4176
4952
|
}
|
|
4177
4953
|
|
|
4178
4954
|
// ../../packages/tools-local/dist/handlers/update-project-config.js
|
|
4179
4955
|
init_esm_shims();
|
|
4180
|
-
var
|
|
4181
|
-
var
|
|
4956
|
+
var import_errors22 = __toESM(require_dist2(), 1);
|
|
4957
|
+
var logger20 = (0, import_errors22.createMcpLogger)({ name: "@toolcairn/tools:update-project-config" });
|
|
4182
4958
|
async function handleUpdateProjectConfig(args) {
|
|
4183
4959
|
try {
|
|
4184
|
-
|
|
4960
|
+
logger20.info({ project_root: args.project_root, action: args.action, tool: args.tool_name }, "update_project_config called");
|
|
4185
4961
|
const data = args.data ?? {};
|
|
4186
4962
|
let notFound = false;
|
|
4187
4963
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4266,7 +5042,7 @@ async function handleUpdateProjectConfig(args) {
|
|
|
4266
5042
|
audit_log_path: ".toolcairn/audit-log.jsonl"
|
|
4267
5043
|
});
|
|
4268
5044
|
} catch (e) {
|
|
4269
|
-
|
|
5045
|
+
logger20.error({ err: e }, "update_project_config failed");
|
|
4270
5046
|
return errResult("update_config_error", e instanceof Error ? e.message : String(e));
|
|
4271
5047
|
}
|
|
4272
5048
|
}
|
|
@@ -4289,10 +5065,10 @@ import { z as z2 } from "zod";
|
|
|
4289
5065
|
// src/middleware/event-logger.ts
|
|
4290
5066
|
init_esm_shims();
|
|
4291
5067
|
var import_config = __toESM(require_dist(), 1);
|
|
4292
|
-
var
|
|
5068
|
+
var import_errors23 = __toESM(require_dist2(), 1);
|
|
4293
5069
|
import { appendFile as appendFile2, mkdir as mkdir6 } from "fs/promises";
|
|
4294
5070
|
import { dirname } from "path";
|
|
4295
|
-
var
|
|
5071
|
+
var logger21 = (0, import_errors23.createMcpLogger)({ name: "@toolcairn/mcp-server:event-logger" });
|
|
4296
5072
|
function isTrackingEnabled() {
|
|
4297
5073
|
return process.env.TOOLCAIRN_TRACKING_ENABLED !== "false";
|
|
4298
5074
|
}
|
|
@@ -4336,7 +5112,7 @@ async function writeToFile(eventsPath, event) {
|
|
|
4336
5112
|
await appendFile2(eventsPath, `${JSON.stringify(event)}
|
|
4337
5113
|
`, "utf-8");
|
|
4338
5114
|
} catch (e) {
|
|
4339
|
-
|
|
5115
|
+
logger21.warn({ err: e, path: eventsPath }, "Failed to write event to JSONL file");
|
|
4340
5116
|
}
|
|
4341
5117
|
}
|
|
4342
5118
|
async function sendToApi(event) {
|
|
@@ -4358,7 +5134,7 @@ async function sendToApi(event) {
|
|
|
4358
5134
|
})
|
|
4359
5135
|
});
|
|
4360
5136
|
} catch (e) {
|
|
4361
|
-
|
|
5137
|
+
logger21.debug({ err: e }, "Failed to send event to API \u2014 non-fatal");
|
|
4362
5138
|
}
|
|
4363
5139
|
}
|
|
4364
5140
|
function withEventLogging(toolName, handler) {
|
|
@@ -4399,7 +5175,7 @@ function withEventLogging(toolName, handler) {
|
|
|
4399
5175
|
}
|
|
4400
5176
|
|
|
4401
5177
|
// src/server.prod.ts
|
|
4402
|
-
var
|
|
5178
|
+
var logger22 = (0, import_errors24.createMcpLogger)({ name: "@toolcairn/mcp-server:prod" });
|
|
4403
5179
|
var SETUP_INSTRUCTIONS = `
|
|
4404
5180
|
# ToolCairn \u2014 Agent Setup Instructions
|
|
4405
5181
|
|
|
@@ -4465,9 +5241,9 @@ async function addToolsToServer(server) {
|
|
|
4465
5241
|
apiKey: creds.client_id,
|
|
4466
5242
|
accessToken: creds.access_token
|
|
4467
5243
|
});
|
|
4468
|
-
|
|
5244
|
+
logger22.info({ user: creds.user_email }, "Registering production tools");
|
|
4469
5245
|
function wrap(toolName, fn) {
|
|
4470
|
-
return withEventLogging(toolName, (0,
|
|
5246
|
+
return withEventLogging(toolName, (0, import_errors24.withErrorHandling)(toolName, logger22, fn));
|
|
4471
5247
|
}
|
|
4472
5248
|
server.registerTool(
|
|
4473
5249
|
"classify_prompt",
|
|
@@ -4687,14 +5463,14 @@ function createTransport() {
|
|
|
4687
5463
|
|
|
4688
5464
|
// src/index.prod.ts
|
|
4689
5465
|
process.env.TOOLPILOT_MODE = "production";
|
|
4690
|
-
var
|
|
5466
|
+
var logger23 = (0, import_errors25.createMcpLogger)({ name: "@toolcairn/mcp-server" });
|
|
4691
5467
|
async function main() {
|
|
4692
5468
|
await ensureProjectSetup();
|
|
4693
5469
|
const creds = await loadCredentials();
|
|
4694
5470
|
const authenticated = creds !== null && isTokenValid(creds);
|
|
4695
5471
|
let server;
|
|
4696
5472
|
if (authenticated) {
|
|
4697
|
-
|
|
5473
|
+
logger23.info({ user: creds.user_email }, "Authenticated \u2014 starting full server");
|
|
4698
5474
|
server = await buildProdServer();
|
|
4699
5475
|
} else {
|
|
4700
5476
|
let verificationUri = "https://toolcairn.neurynae.com/signup";
|
|
@@ -4704,15 +5480,15 @@ async function main() {
|
|
|
4704
5480
|
if (pending) {
|
|
4705
5481
|
verificationUri = pending.verification_uri;
|
|
4706
5482
|
userCode = pending.user_code;
|
|
4707
|
-
|
|
5483
|
+
logger23.info({ userCode }, "Resuming pending sign-in");
|
|
4708
5484
|
} else {
|
|
4709
5485
|
const codeData = await requestDeviceCode(import_config4.config.TOOLPILOT_API_URL);
|
|
4710
5486
|
verificationUri = codeData.verification_uri;
|
|
4711
5487
|
userCode = codeData.user_code;
|
|
4712
|
-
|
|
5488
|
+
logger23.info({ userCode }, "New sign-in started");
|
|
4713
5489
|
}
|
|
4714
5490
|
} catch (err) {
|
|
4715
|
-
|
|
5491
|
+
logger23.error({ err }, "Could not reach ToolCairn API \u2014 check your connection");
|
|
4716
5492
|
}
|
|
4717
5493
|
const instructions = userCode ? `# ToolCairn \u2014 Sign In Required
|
|
4718
5494
|
|
|
@@ -4744,23 +5520,23 @@ Open the URL, sign in, and confirm the code shown. All 14 tools will appear auto
|
|
|
4744
5520
|
})
|
|
4745
5521
|
);
|
|
4746
5522
|
startDeviceAuth(import_config4.config.TOOLPILOT_API_URL).then(async () => {
|
|
4747
|
-
|
|
5523
|
+
logger23.info("Sign-in complete \u2014 adding all tools to running server");
|
|
4748
5524
|
try {
|
|
4749
5525
|
await addToolsToServer(server);
|
|
4750
|
-
|
|
5526
|
+
logger23.info("All ToolCairn tools now available");
|
|
4751
5527
|
} catch (err) {
|
|
4752
|
-
|
|
5528
|
+
logger23.error({ err }, "Failed to add tools after sign-in \u2014 please reconnect");
|
|
4753
5529
|
}
|
|
4754
5530
|
}).catch((err) => {
|
|
4755
|
-
|
|
5531
|
+
logger23.error({ err }, "Sign-in failed \u2014 please try again");
|
|
4756
5532
|
});
|
|
4757
5533
|
}
|
|
4758
5534
|
const transport = createTransport();
|
|
4759
5535
|
await server.connect(transport);
|
|
4760
|
-
|
|
5536
|
+
logger23.info(authenticated ? "ToolCairn MCP ready" : "ToolCairn MCP ready (awaiting sign-in)");
|
|
4761
5537
|
}
|
|
4762
5538
|
main().catch((error) => {
|
|
4763
|
-
(0,
|
|
5539
|
+
(0, import_errors25.createMcpLogger)({ name: "@toolcairn/mcp-server" }).error(
|
|
4764
5540
|
{ err: error },
|
|
4765
5541
|
"Failed to start MCP server"
|
|
4766
5542
|
);
|