@neurynae/toolcairn-mcp 0.10.4 → 0.10.6
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 +133 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -923,7 +923,7 @@ async function pollForToken(apiUrl, deviceCode, intervalSec) {
|
|
|
923
923
|
}
|
|
924
924
|
}
|
|
925
925
|
function sleep(ms) {
|
|
926
|
-
return new Promise((
|
|
926
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
927
927
|
}
|
|
928
928
|
|
|
929
929
|
// src/index.prod.ts
|
|
@@ -1001,8 +1001,10 @@ var suggestGraphUpdateSchema = {
|
|
|
1001
1001
|
tools: z.array(z.object({
|
|
1002
1002
|
tool_name: z.string().min(1),
|
|
1003
1003
|
github_url: z.string().url().optional(),
|
|
1004
|
-
description: z.string().optional()
|
|
1005
|
-
|
|
1004
|
+
description: z.string().optional(),
|
|
1005
|
+
ecosystem: z.string().min(1).optional()
|
|
1006
|
+
})).min(1).max(200).optional().describe('Batch of tools to stage for admin review. Use with suggestion_type="new_tool". Each entry may include `ecosystem` (npm/pypi/cargo/\u2026) so the engine can cross-check the authoritative github_url from the package registry. Overrides single-tool fields when present.'),
|
|
1007
|
+
ecosystem: z.string().min(1).optional(),
|
|
1006
1008
|
relationship: z.object({
|
|
1007
1009
|
source_tool: z.string(),
|
|
1008
1010
|
target_tool: z.string(),
|
|
@@ -1165,6 +1167,9 @@ var import_errors21 = __toESM(require_dist2(), 1);
|
|
|
1165
1167
|
// ../../packages/tools-local/dist/auto-init.js
|
|
1166
1168
|
init_esm_shims();
|
|
1167
1169
|
var import_errors20 = __toESM(require_dist2(), 1);
|
|
1170
|
+
import { readFile as readFile28 } from "fs/promises";
|
|
1171
|
+
import { resolve as resolve3 } from "path";
|
|
1172
|
+
import writeFileAtomic3 from "write-file-atomic";
|
|
1168
1173
|
|
|
1169
1174
|
// ../../packages/tools-local/dist/config-store/index.js
|
|
1170
1175
|
init_esm_shims();
|
|
@@ -4481,6 +4486,9 @@ function getOpenCodeMcpEntry(serverPath) {
|
|
|
4481
4486
|
|
|
4482
4487
|
// ../../packages/tools-local/dist/auto-init.js
|
|
4483
4488
|
var logger18 = (0, import_errors20.createMcpLogger)({ name: "@toolcairn/tools:auto-init" });
|
|
4489
|
+
var INSTRUCTION_SENTINEL = "## ToolCairn \u2014 Tool Intelligence MCP";
|
|
4490
|
+
var GITIGNORE_SENTINEL = "# ToolCairn";
|
|
4491
|
+
var GITIGNORE_BLOCK = "\n# ToolCairn\n.toolcairn/events.jsonl\n.toolcairn/audit-log.jsonl\n.toolcairn/audit-log.archive.jsonl\n.toolcairn/config.lock\n";
|
|
4484
4492
|
async function autoInitProject(input) {
|
|
4485
4493
|
const { projectRoot, agent, batchResolve, serverPath, reason } = input;
|
|
4486
4494
|
logger18.info({ projectRoot, agent }, "autoInitProject starting");
|
|
@@ -4546,10 +4554,23 @@ async function autoInitProject(input) {
|
|
|
4546
4554
|
step: 3,
|
|
4547
4555
|
action: "append",
|
|
4548
4556
|
file: ".gitignore",
|
|
4549
|
-
content:
|
|
4557
|
+
content: GITIGNORE_BLOCK,
|
|
4550
4558
|
note: "Ignore runtime/audit files. config.json should be committed so teammates share tool intelligence."
|
|
4551
4559
|
}
|
|
4552
4560
|
];
|
|
4561
|
+
const applied_steps = input.skipSetupFileWrites ? setupSteps.map((s) => ({
|
|
4562
|
+
file: s.file,
|
|
4563
|
+
action: s.action,
|
|
4564
|
+
applied: false,
|
|
4565
|
+
reason: "skipSetupFileWrites=true"
|
|
4566
|
+
})) : await applySetupFiles(projectRoot, {
|
|
4567
|
+
agent,
|
|
4568
|
+
instructionFile: instructions.file_path,
|
|
4569
|
+
instructionContent: instructions.content,
|
|
4570
|
+
mcpConfigFile,
|
|
4571
|
+
mcpConfigEntry,
|
|
4572
|
+
isOpenCode
|
|
4573
|
+
});
|
|
4553
4574
|
const tool_counts = {
|
|
4554
4575
|
total: config5.tools.confirmed.length,
|
|
4555
4576
|
indexed: config5.tools.confirmed.filter((t) => t.source === "toolcairn").length,
|
|
@@ -4564,6 +4585,7 @@ async function autoInitProject(input) {
|
|
|
4564
4585
|
events_path: ".toolcairn/events.jsonl",
|
|
4565
4586
|
mcp_config_entry: mcpConfigEntry,
|
|
4566
4587
|
setup_steps: setupSteps,
|
|
4588
|
+
applied_steps,
|
|
4567
4589
|
scan_summary: {
|
|
4568
4590
|
project_name: scan.name,
|
|
4569
4591
|
languages: scan.languages.map((l) => ({ name: l.name, file_count: l.file_count })),
|
|
@@ -4579,6 +4601,108 @@ async function autoInitProject(input) {
|
|
|
4579
4601
|
unknown_tools: undrained
|
|
4580
4602
|
};
|
|
4581
4603
|
}
|
|
4604
|
+
async function applySetupFiles(projectRoot, args) {
|
|
4605
|
+
const results = [];
|
|
4606
|
+
results.push(await applyInstructionFile(resolve3(projectRoot, args.instructionFile), args.instructionFile, args.instructionContent));
|
|
4607
|
+
results.push(await applyMcpConfig(resolve3(projectRoot, args.mcpConfigFile), args.mcpConfigFile, args.mcpConfigEntry, args.isOpenCode));
|
|
4608
|
+
results.push(await applyGitignore(resolve3(projectRoot, ".gitignore")));
|
|
4609
|
+
return results;
|
|
4610
|
+
}
|
|
4611
|
+
async function applyInstructionFile(abs, relPath, content) {
|
|
4612
|
+
try {
|
|
4613
|
+
const exists = await fileExists(abs);
|
|
4614
|
+
if (exists) {
|
|
4615
|
+
const current = await readFile28(abs, "utf-8");
|
|
4616
|
+
if (current.includes(INSTRUCTION_SENTINEL)) {
|
|
4617
|
+
return {
|
|
4618
|
+
file: relPath,
|
|
4619
|
+
action: "append-or-create",
|
|
4620
|
+
applied: false,
|
|
4621
|
+
reason: "ToolCairn rules block already present"
|
|
4622
|
+
};
|
|
4623
|
+
}
|
|
4624
|
+
const separator = current.endsWith("\n") ? "" : "\n";
|
|
4625
|
+
await writeFileAtomic3(abs, `${current}${separator}${content}`, "utf-8");
|
|
4626
|
+
return { file: relPath, action: "append-or-create", applied: true };
|
|
4627
|
+
}
|
|
4628
|
+
await writeFileAtomic3(abs, content, "utf-8");
|
|
4629
|
+
return { file: relPath, action: "append-or-create", applied: true };
|
|
4630
|
+
} catch (err) {
|
|
4631
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
4632
|
+
logger18.warn({ err, file: relPath }, "Failed to write instruction file");
|
|
4633
|
+
return { file: relPath, action: "append-or-create", applied: false, reason };
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
async function applyMcpConfig(abs, relPath, entry, isOpenCode) {
|
|
4637
|
+
try {
|
|
4638
|
+
const exists = await fileExists(abs);
|
|
4639
|
+
const topKey = isOpenCode ? "mcp" : "mcpServers";
|
|
4640
|
+
if (!exists) {
|
|
4641
|
+
const payload = { [topKey]: entry };
|
|
4642
|
+
await writeFileAtomic3(abs, `${JSON.stringify(payload, null, 2)}
|
|
4643
|
+
`, "utf-8");
|
|
4644
|
+
return { file: relPath, action: "merge-or-create", applied: true };
|
|
4645
|
+
}
|
|
4646
|
+
const raw = await readFile28(abs, "utf-8");
|
|
4647
|
+
let parsed;
|
|
4648
|
+
try {
|
|
4649
|
+
parsed = JSON.parse(raw);
|
|
4650
|
+
} catch {
|
|
4651
|
+
return {
|
|
4652
|
+
file: relPath,
|
|
4653
|
+
action: "merge-or-create",
|
|
4654
|
+
applied: false,
|
|
4655
|
+
reason: "existing file is not valid JSON \u2014 refusing to overwrite; fix manually"
|
|
4656
|
+
};
|
|
4657
|
+
}
|
|
4658
|
+
const existingServers = parsed[topKey] && typeof parsed[topKey] === "object" && !Array.isArray(parsed[topKey]) ? parsed[topKey] : {};
|
|
4659
|
+
if (existingServers.toolcairn !== void 0) {
|
|
4660
|
+
return {
|
|
4661
|
+
file: relPath,
|
|
4662
|
+
action: "merge-or-create",
|
|
4663
|
+
applied: false,
|
|
4664
|
+
reason: `${topKey}.toolcairn already present`
|
|
4665
|
+
};
|
|
4666
|
+
}
|
|
4667
|
+
const merged = {
|
|
4668
|
+
...parsed,
|
|
4669
|
+
[topKey]: { ...existingServers, ...entry }
|
|
4670
|
+
};
|
|
4671
|
+
await writeFileAtomic3(abs, `${JSON.stringify(merged, null, 2)}
|
|
4672
|
+
`, "utf-8");
|
|
4673
|
+
return { file: relPath, action: "merge-or-create", applied: true };
|
|
4674
|
+
} catch (err) {
|
|
4675
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
4676
|
+
logger18.warn({ err, file: relPath }, "Failed to write MCP config");
|
|
4677
|
+
return { file: relPath, action: "merge-or-create", applied: false, reason };
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
async function applyGitignore(abs) {
|
|
4681
|
+
const relPath = ".gitignore";
|
|
4682
|
+
try {
|
|
4683
|
+
const exists = await fileExists(abs);
|
|
4684
|
+
if (!exists) {
|
|
4685
|
+
await writeFileAtomic3(abs, GITIGNORE_BLOCK.replace(/^\n/, ""), "utf-8");
|
|
4686
|
+
return { file: relPath, action: "append", applied: true };
|
|
4687
|
+
}
|
|
4688
|
+
const current = await readFile28(abs, "utf-8");
|
|
4689
|
+
if (current.includes(GITIGNORE_SENTINEL)) {
|
|
4690
|
+
return {
|
|
4691
|
+
file: relPath,
|
|
4692
|
+
action: "append",
|
|
4693
|
+
applied: false,
|
|
4694
|
+
reason: "ToolCairn gitignore block already present"
|
|
4695
|
+
};
|
|
4696
|
+
}
|
|
4697
|
+
const separator = current.endsWith("\n") ? "" : "\n";
|
|
4698
|
+
await writeFileAtomic3(abs, `${current}${separator}${GITIGNORE_BLOCK}`, "utf-8");
|
|
4699
|
+
return { file: relPath, action: "append", applied: true };
|
|
4700
|
+
} catch (err) {
|
|
4701
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
4702
|
+
logger18.warn({ err, file: relPath }, "Failed to write .gitignore");
|
|
4703
|
+
return { file: relPath, action: "append", applied: false, reason };
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4582
4706
|
|
|
4583
4707
|
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
4584
4708
|
var logger19 = (0, import_errors21.createMcpLogger)({ name: "@toolcairn/tools:toolcairn-init" });
|
|
@@ -4984,7 +5108,11 @@ async function submitUnknownsToEngine(remote, pending) {
|
|
|
4984
5108
|
const res = await remote.suggestGraphUpdate({
|
|
4985
5109
|
suggestion_type: "new_tool",
|
|
4986
5110
|
data: {
|
|
4987
|
-
tools: pending.map((t) => ({
|
|
5111
|
+
tools: pending.map((t) => ({
|
|
5112
|
+
tool_name: t.name,
|
|
5113
|
+
github_url: t.github_url,
|
|
5114
|
+
ecosystem: t.ecosystem
|
|
5115
|
+
}))
|
|
4988
5116
|
},
|
|
4989
5117
|
confidence: 0.5
|
|
4990
5118
|
});
|