@neurynae/toolcairn-mcp 0.8.9 → 0.9.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 +60 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1372,7 +1372,9 @@ var checkIssueSchema = {
|
|
|
1372
1372
|
};
|
|
1373
1373
|
var checkCompatibilitySchema = {
|
|
1374
1374
|
tool_a: z.string(),
|
|
1375
|
-
tool_b: z.string()
|
|
1375
|
+
tool_b: z.string(),
|
|
1376
|
+
tool_a_version: z.string().optional().describe('Specific version of tool_a to evaluate (e.g., "14.0.0"). Default: latest.'),
|
|
1377
|
+
tool_b_version: z.string().optional().describe('Specific version of tool_b to evaluate (e.g., "18.2.0"). Default: latest.')
|
|
1376
1378
|
};
|
|
1377
1379
|
var suggestGraphUpdateSchema = {
|
|
1378
1380
|
suggestion_type: z.enum(["new_tool", "new_edge", "update_health", "new_use_case"]),
|
|
@@ -1510,7 +1512,7 @@ ${args.prompt}
|
|
|
1510
1512
|
"""${projectToolsContext}
|
|
1511
1513
|
|
|
1512
1514
|
Your response (one category name only):`;
|
|
1513
|
-
const needs_tool_search_prompt = `Based on this classification, determine if
|
|
1515
|
+
const needs_tool_search_prompt = `Based on this classification, determine if ToolCairn tool search should be invoked.
|
|
1514
1516
|
Respond with 1 if the classification is one of: tool_discovery, stack_building, tool_comparison
|
|
1515
1517
|
Respond with 0 if the classification is: tool_configuration, debugging, general_coding
|
|
1516
1518
|
Respond with ONLY 0 or 1.`;
|
|
@@ -1526,7 +1528,7 @@ Respond with ONLY 0 or 1.`;
|
|
|
1526
1528
|
"general_coding"
|
|
1527
1529
|
],
|
|
1528
1530
|
tool_required_if: TOOL_REQUIRED_CLASSIFICATIONS,
|
|
1529
|
-
instructions: "Step 1: Send classification_prompt to the LLM and get a classification. Step 2: If classification is in tool_required_if, call refine_requirement with the classification. Otherwise, proceed without
|
|
1531
|
+
instructions: "Step 1: Send classification_prompt to the LLM and get a classification. Step 2: If classification is in tool_required_if, call refine_requirement with the classification. Otherwise, proceed without ToolCairn search."
|
|
1530
1532
|
});
|
|
1531
1533
|
} catch (e) {
|
|
1532
1534
|
logger2.error({ err: e }, "classify_prompt failed");
|
|
@@ -1540,29 +1542,29 @@ var import_errors5 = __toESM(require_dist2(), 1);
|
|
|
1540
1542
|
|
|
1541
1543
|
// ../../packages/tools-local/dist/templates/agent-instructions.js
|
|
1542
1544
|
init_esm_shims();
|
|
1543
|
-
var
|
|
1544
|
-
|
|
1545
|
+
var TOOLCAIRN_MCP_ENTRY = {
|
|
1546
|
+
toolcairn: {
|
|
1545
1547
|
command: "npx",
|
|
1546
|
-
args: ["-y", "@toolcairn
|
|
1548
|
+
args: ["-y", "@neurynae/toolcairn-mcp"]
|
|
1547
1549
|
}
|
|
1548
1550
|
};
|
|
1549
1551
|
var CORE_RULES = `
|
|
1550
|
-
##
|
|
1552
|
+
## ToolCairn \u2014 Tool Intelligence MCP
|
|
1551
1553
|
|
|
1552
|
-
|
|
1554
|
+
ToolCairn is your tool intelligence co-pilot. It has a graph database of 500+ indexed tools with health signals, compatibility data, and known issue tracking. Always use it before recommending any tool, library, or framework.
|
|
1553
1555
|
|
|
1554
1556
|
### Workflow for Tool Selection
|
|
1555
1557
|
|
|
1556
1558
|
1. **Before recommending any tool**: Always call \`search_tools\` first. Never recommend from training data alone.
|
|
1557
1559
|
2. **When user describes a use case**: Call \`classify_prompt\` first, then \`refine_requirement\` if tool selection is needed.
|
|
1558
|
-
3. **When starting a new project**: Call \`
|
|
1559
|
-
4. **When resuming work on a project**: Read .
|
|
1560
|
+
3. **When starting a new project**: Call \`toolcairn_init\` to set up .toolcairn/config.json.
|
|
1561
|
+
4. **When resuming work on a project**: Read .toolcairn/config.json via \`read_project_config\` to see confirmed tools.
|
|
1560
1562
|
5. **When a tool is selected**: Call \`update_project_config\` to persist the choice.
|
|
1561
1563
|
6. **When encountering an error with a tool**: Call \`check_issue\` before debugging \u2014 it may be a known issue with an open GitHub ticket.
|
|
1562
1564
|
7. **When user asks to compare tools**: Call \`compare_tools\` for a structured comparison with health data.
|
|
1563
1565
|
8. **When user chooses a non-indexed/proprietary tool**: Add it to config with source: "non_oss" via \`update_project_config\`.
|
|
1564
1566
|
|
|
1565
|
-
### Available
|
|
1567
|
+
### Available ToolCairn MCP Tools
|
|
1566
1568
|
|
|
1567
1569
|
| Tool | When to use |
|
|
1568
1570
|
|------|------------|
|
|
@@ -1575,17 +1577,17 @@ ToolPilot is your tool intelligence co-pilot. It has a graph database of 500+ in
|
|
|
1575
1577
|
| \`check_compatibility\` | Check if two tools work well together |
|
|
1576
1578
|
| \`compare_tools\` | Compare two tools with health and graph data |
|
|
1577
1579
|
| \`report_outcome\` | Report whether a recommended tool worked (improves future results) |
|
|
1578
|
-
| \`
|
|
1579
|
-
| \`init_project_config\` | Initialize .
|
|
1580
|
-
| \`read_project_config\` | Parse .
|
|
1581
|
-
| \`update_project_config\` | Add/remove/update tools in .
|
|
1582
|
-
| \`suggest_graph_update\` | Suggest a new tool or relationship for the
|
|
1580
|
+
| \`toolcairn_init\` | Set up ToolCairn for a new project |
|
|
1581
|
+
| \`init_project_config\` | Initialize .toolcairn/config.json |
|
|
1582
|
+
| \`read_project_config\` | Parse .toolcairn/config.json to get confirmed tools |
|
|
1583
|
+
| \`update_project_config\` | Add/remove/update tools in .toolcairn/config.json |
|
|
1584
|
+
| \`suggest_graph_update\` | Suggest a new tool or relationship for the ToolCairn graph |
|
|
1583
1585
|
|
|
1584
1586
|
### Rules
|
|
1585
1587
|
|
|
1586
|
-
- NEVER recommend a tool without first checking
|
|
1587
|
-
- Always check .
|
|
1588
|
-
- Prefer open-source tools from
|
|
1588
|
+
- NEVER recommend a tool without first checking ToolCairn unless the tool is already in .toolcairn/config.json
|
|
1589
|
+
- Always check .toolcairn/config.json at the start of a session if it exists
|
|
1590
|
+
- Prefer open-source tools from ToolCairn index; flag proprietary alternatives clearly
|
|
1589
1591
|
- After selecting a tool, always call \`update_project_config\` to persist it
|
|
1590
1592
|
- After using a tool successfully/unsuccessfully, call \`report_outcome\`
|
|
1591
1593
|
`;
|
|
@@ -1661,20 +1663,20 @@ function getInstructionsForAgent(agent) {
|
|
|
1661
1663
|
function getMcpConfigEntry(serverPath) {
|
|
1662
1664
|
if (serverPath) {
|
|
1663
1665
|
return {
|
|
1664
|
-
|
|
1666
|
+
toolcairn: {
|
|
1665
1667
|
command: "node",
|
|
1666
1668
|
args: [serverPath]
|
|
1667
1669
|
}
|
|
1668
1670
|
};
|
|
1669
1671
|
}
|
|
1670
|
-
return
|
|
1672
|
+
return TOOLCAIRN_MCP_ENTRY;
|
|
1671
1673
|
}
|
|
1672
1674
|
function getOpenCodeMcpEntry(serverPath) {
|
|
1673
1675
|
const resolvedPath = serverPath;
|
|
1674
1676
|
return {
|
|
1675
|
-
|
|
1677
|
+
toolcairn: {
|
|
1676
1678
|
type: "local",
|
|
1677
|
-
command: resolvedPath ? ["node", resolvedPath] : ["npx", "-y", "@toolcairn
|
|
1679
|
+
command: resolvedPath ? ["node", resolvedPath] : ["npx", "-y", "@neurynae/toolcairn-mcp"],
|
|
1678
1680
|
enabled: true
|
|
1679
1681
|
}
|
|
1680
1682
|
};
|
|
@@ -1688,7 +1690,7 @@ function generateTrackerHtml2(eventsPath) {
|
|
|
1688
1690
|
<head>
|
|
1689
1691
|
<meta charset="UTF-8" />
|
|
1690
1692
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1691
|
-
<title>
|
|
1693
|
+
<title>ToolCairn Tracker</title>
|
|
1692
1694
|
<style>
|
|
1693
1695
|
:root {
|
|
1694
1696
|
--bg: #0a0a0f;
|
|
@@ -1785,7 +1787,7 @@ function generateTrackerHtml2(eventsPath) {
|
|
|
1785
1787
|
<circle cx="10" cy="10" r="9" stroke="#7c5cfc" stroke-width="1.5"/>
|
|
1786
1788
|
<path d="M6 10h8M10 6v8" stroke="#7c5cfc" stroke-width="1.5" stroke-linecap="round"/>
|
|
1787
1789
|
</svg>
|
|
1788
|
-
<h1><span>Tool</span>
|
|
1790
|
+
<h1><span>Tool</span>Cairn Tracker</h1>
|
|
1789
1791
|
<div id="statusText" style="font-size:12px; color:var(--muted);">Loading...</div>
|
|
1790
1792
|
<div id="statusDot" class="status-dot paused"></div>
|
|
1791
1793
|
</header>
|
|
@@ -1814,7 +1816,7 @@ function generateTrackerHtml2(eventsPath) {
|
|
|
1814
1816
|
<div class="empty" id="emptyState">
|
|
1815
1817
|
<svg width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="18" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M13 20h14M20 13v14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1816
1818
|
<p>Waiting for MCP tool calls...</p>
|
|
1817
|
-
<code>Set
|
|
1819
|
+
<code>Set TOOLCAIRN_EVENTS_PATH in your MCP server env</code>
|
|
1818
1820
|
</div>
|
|
1819
1821
|
</div>
|
|
1820
1822
|
<div class="sidebar">
|
|
@@ -2076,7 +2078,7 @@ function renderAll() {
|
|
|
2076
2078
|
// \u2500\u2500\u2500 Boot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
2077
2079
|
if (!EVENTS_PATH || EVENTS_PATH === 'null') {
|
|
2078
2080
|
document.getElementById('statusText').textContent = 'No events path configured';
|
|
2079
|
-
document.getElementById('emptyState').querySelector('p').textContent = '
|
|
2081
|
+
document.getElementById('emptyState').querySelector('p').textContent = 'TOOLCAIRN_EVENTS_PATH not set in MCP server environment';
|
|
2080
2082
|
} else {
|
|
2081
2083
|
startPolling();
|
|
2082
2084
|
}
|
|
@@ -2086,19 +2088,19 @@ if (!EVENTS_PATH || EVENTS_PATH === 'null') {
|
|
|
2086
2088
|
}
|
|
2087
2089
|
|
|
2088
2090
|
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
2089
|
-
var logger3 = (0, import_errors5.createMcpLogger)({ name: "@toolcairn/tools:
|
|
2091
|
+
var logger3 = (0, import_errors5.createMcpLogger)({ name: "@toolcairn/tools:toolcairn-init" });
|
|
2090
2092
|
async function handleToolcairnInit(args) {
|
|
2091
2093
|
try {
|
|
2092
|
-
logger3.info({ agent: args.agent, project_root: args.project_root }, "
|
|
2094
|
+
logger3.info({ agent: args.agent, project_root: args.project_root }, "toolcairn_init called");
|
|
2093
2095
|
const instructions = getInstructionsForAgent(args.agent);
|
|
2094
2096
|
const isOpenCode = args.agent === "opencode";
|
|
2095
2097
|
const mcpConfigEntry = isOpenCode ? getOpenCodeMcpEntry(args.server_path) : getMcpConfigEntry(args.server_path);
|
|
2096
2098
|
const mcpConfigFile = isOpenCode ? "opencode.json" : ".mcp.json";
|
|
2097
2099
|
const hasMcpJson = args.detected_files?.some((f) => f === mcpConfigFile || f.endsWith(`/${mcpConfigFile}`));
|
|
2098
2100
|
const hasInstructionFile = args.detected_files?.some((f) => f.endsWith(instructions.file_path));
|
|
2099
|
-
const
|
|
2100
|
-
const hasTrackerHtml = args.detected_files?.some((f) => f.includes(".
|
|
2101
|
-
const eventsPath = `${args.project_root}/.
|
|
2101
|
+
const hasToolcairnConfig = args.detected_files?.some((f) => f.includes(".toolcairn/config.json"));
|
|
2102
|
+
const hasTrackerHtml = args.detected_files?.some((f) => f.includes(".toolcairn/tracker.html"));
|
|
2103
|
+
const eventsPath = `${args.project_root}/.toolcairn/events.jsonl`;
|
|
2102
2104
|
const setupSteps = [];
|
|
2103
2105
|
let step = 1;
|
|
2104
2106
|
setupSteps.push({
|
|
@@ -2109,7 +2111,7 @@ async function handleToolcairnInit(args) {
|
|
|
2109
2111
|
note: hasInstructionFile ? `Append the content to your existing ${instructions.file_path}` : `Create ${instructions.file_path} with the content`
|
|
2110
2112
|
});
|
|
2111
2113
|
const mcpContent = isOpenCode ? JSON.stringify({ mcp: mcpConfigEntry }, null, 2) : JSON.stringify({ mcpServers: mcpConfigEntry }, null, 2);
|
|
2112
|
-
const mcpMergeNote = isOpenCode ? `Merge the
|
|
2114
|
+
const mcpMergeNote = isOpenCode ? `Merge the toolcairn entry into your existing ${mcpConfigFile} under "mcp"` : `Merge the toolcairn entry into your existing ${mcpConfigFile} under "mcpServers"`;
|
|
2113
2115
|
const mcpCreateNote = isOpenCode ? `Create ${mcpConfigFile} with this content (OpenCode MCP config format)` : `Create ${mcpConfigFile} with this content`;
|
|
2114
2116
|
setupSteps.push({
|
|
2115
2117
|
step: step++,
|
|
@@ -2118,29 +2120,29 @@ async function handleToolcairnInit(args) {
|
|
|
2118
2120
|
content: mcpContent,
|
|
2119
2121
|
note: hasMcpJson ? mcpMergeNote : mcpCreateNote
|
|
2120
2122
|
});
|
|
2121
|
-
if (!
|
|
2123
|
+
if (!hasToolcairnConfig) {
|
|
2122
2124
|
setupSteps.push({
|
|
2123
2125
|
step: step++,
|
|
2124
2126
|
action: "create",
|
|
2125
|
-
file: ".
|
|
2126
|
-
note: "Call init_project_config to generate the config content, then write to .
|
|
2127
|
+
file: ".toolcairn/config.json",
|
|
2128
|
+
note: "Call init_project_config to generate the config content, then write to .toolcairn/config.json"
|
|
2127
2129
|
});
|
|
2128
2130
|
}
|
|
2129
2131
|
if (!hasTrackerHtml) {
|
|
2130
2132
|
setupSteps.push({
|
|
2131
2133
|
step: step++,
|
|
2132
2134
|
action: "create",
|
|
2133
|
-
file: ".
|
|
2135
|
+
file: ".toolcairn/tracker.html",
|
|
2134
2136
|
content: generateTrackerHtml2(eventsPath),
|
|
2135
|
-
note: `Open .
|
|
2137
|
+
note: `Open .toolcairn/tracker.html in your browser to monitor MCP tool calls in real time. Set TOOLCAIRN_EVENTS_PATH=${eventsPath} in your MCP server environment to enable event logging.`
|
|
2136
2138
|
});
|
|
2137
2139
|
}
|
|
2138
2140
|
setupSteps.push({
|
|
2139
2141
|
step: step++,
|
|
2140
2142
|
action: "append",
|
|
2141
2143
|
file: ".gitignore",
|
|
2142
|
-
content: "\n#
|
|
2143
|
-
note: "Add .
|
|
2144
|
+
content: "\n# ToolCairn\n.toolcairn/events.jsonl\n",
|
|
2145
|
+
note: "Add .toolcairn/events.jsonl to .gitignore (the tracker event log)"
|
|
2144
2146
|
});
|
|
2145
2147
|
const agentFileLabel = {
|
|
2146
2148
|
claude: "CLAUDE.md",
|
|
@@ -2158,16 +2160,16 @@ async function handleToolcairnInit(args) {
|
|
|
2158
2160
|
mcp_config_entry: mcpConfigEntry,
|
|
2159
2161
|
events_path: eventsPath,
|
|
2160
2162
|
summary: [
|
|
2161
|
-
`
|
|
2163
|
+
`ToolCairn setup for ${args.agent} agent in ${args.project_root}`,
|
|
2162
2164
|
`Instructions will be added to: ${instructions.file_path}`,
|
|
2163
|
-
`MCP server entry:
|
|
2164
|
-
|
|
2165
|
-
hasTrackerHtml ? ".
|
|
2165
|
+
`MCP server entry: toolcairn \u2192 ${mcpConfigFile}`,
|
|
2166
|
+
hasToolcairnConfig ? ".toolcairn/config.json already exists \u2014 skipping init" : "Run init_project_config next to generate .toolcairn/config.json",
|
|
2167
|
+
hasTrackerHtml ? ".toolcairn/tracker.html already exists \u2014 skipping" : "Tracker dashboard: open .toolcairn/tracker.html in browser"
|
|
2166
2168
|
].join("\n"),
|
|
2167
|
-
next_steps:
|
|
2169
|
+
next_steps: hasToolcairnConfig ? "Setup complete. Open .toolcairn/tracker.html to monitor tool calls." : "After completing setup steps, call init_project_config to initialize .toolcairn/config.json."
|
|
2168
2170
|
});
|
|
2169
2171
|
} catch (e) {
|
|
2170
|
-
logger3.error({ err: e }, "
|
|
2172
|
+
logger3.error({ err: e }, "toolcairn_init failed");
|
|
2171
2173
|
return errResult("init_error", e instanceof Error ? e.message : String(e));
|
|
2172
2174
|
}
|
|
2173
2175
|
}
|
|
@@ -2185,7 +2187,7 @@ async function handleInitProjectConfig(args) {
|
|
|
2185
2187
|
source: t.source,
|
|
2186
2188
|
version: t.version,
|
|
2187
2189
|
chosen_at: now,
|
|
2188
|
-
chosen_reason: "Auto-detected from project files during
|
|
2190
|
+
chosen_reason: "Auto-detected from project files during toolcairn_init",
|
|
2189
2191
|
alternatives_considered: []
|
|
2190
2192
|
}));
|
|
2191
2193
|
const config5 = {
|
|
@@ -2211,8 +2213,8 @@ async function handleInitProjectConfig(args) {
|
|
|
2211
2213
|
const config_json = JSON.stringify(config5, null, 2);
|
|
2212
2214
|
return okResult({
|
|
2213
2215
|
config_json,
|
|
2214
|
-
file_path: ".
|
|
2215
|
-
instructions: "Create the directory .
|
|
2216
|
+
file_path: ".toolcairn/config.json",
|
|
2217
|
+
instructions: "Create the directory .toolcairn/ in your project root (if it does not exist), then write this config_json content to .toolcairn/config.json. Also add .toolcairn/ to .gitignore if not already present.",
|
|
2216
2218
|
confirmed_count: confirmedTools.length,
|
|
2217
2219
|
next_step: confirmedTools.length > 0 ? "Config initialized with auto-detected tools. Use search_tools to find any additional tools you need." : "Config initialized. Use classify_prompt \u2192 refine_requirement \u2192 search_tools to discover tools for your project."
|
|
2218
2220
|
});
|
|
@@ -2258,13 +2260,13 @@ async function handleReadProjectConfig(args) {
|
|
|
2258
2260
|
};
|
|
2259
2261
|
});
|
|
2260
2262
|
const non_oss_tools = config5.tools.confirmed.filter((t) => t.source === "non_oss").map((t) => t.name);
|
|
2261
|
-
const
|
|
2263
|
+
const toolcairn_indexed_tools = config5.tools.confirmed.filter((t) => t.source === "toolcairn" || t.source === "toolpilot").map((t) => t.name);
|
|
2262
2264
|
return okResult({
|
|
2263
2265
|
project: config5.project,
|
|
2264
2266
|
confirmed_tools: confirmedToolNames,
|
|
2265
2267
|
pending_tools: pendingToolNames,
|
|
2266
2268
|
non_oss_tools,
|
|
2267
|
-
|
|
2269
|
+
toolcairn_indexed_tools,
|
|
2268
2270
|
stale_tools: staleTools,
|
|
2269
2271
|
total_confirmed: confirmedToolNames.length,
|
|
2270
2272
|
total_pending: pendingToolNames.length,
|
|
@@ -2304,11 +2306,11 @@ async function handleUpdateProjectConfig(args) {
|
|
|
2304
2306
|
if (!config5.tools.confirmed.some((t) => t.name === args.tool_name)) {
|
|
2305
2307
|
const newTool = {
|
|
2306
2308
|
name: args.tool_name,
|
|
2307
|
-
source: data.source ?? "
|
|
2309
|
+
source: data.source ?? "toolcairn",
|
|
2308
2310
|
github_url: data.github_url,
|
|
2309
2311
|
version: data.version,
|
|
2310
2312
|
chosen_at: now,
|
|
2311
|
-
chosen_reason: data.chosen_reason ?? "Selected via
|
|
2313
|
+
chosen_reason: data.chosen_reason ?? "Selected via ToolCairn",
|
|
2312
2314
|
alternatives_considered: data.alternatives_considered ?? [],
|
|
2313
2315
|
query_id: data.query_id,
|
|
2314
2316
|
notes: data.notes
|
|
@@ -2319,7 +2321,7 @@ async function handleUpdateProjectConfig(args) {
|
|
|
2319
2321
|
action: "add_tool",
|
|
2320
2322
|
tool: args.tool_name,
|
|
2321
2323
|
timestamp: now,
|
|
2322
|
-
reason: data.chosen_reason ?? "Added via
|
|
2324
|
+
reason: data.chosen_reason ?? "Added via ToolCairn recommendation"
|
|
2323
2325
|
});
|
|
2324
2326
|
break;
|
|
2325
2327
|
}
|
|
@@ -2379,12 +2381,12 @@ async function handleUpdateProjectConfig(args) {
|
|
|
2379
2381
|
const updated_config_json = JSON.stringify(config5, null, 2);
|
|
2380
2382
|
return okResult({
|
|
2381
2383
|
updated_config_json,
|
|
2382
|
-
file_path: ".
|
|
2384
|
+
file_path: ".toolcairn/config.json",
|
|
2383
2385
|
action_applied: args.action,
|
|
2384
2386
|
tool_name: args.tool_name,
|
|
2385
2387
|
confirmed_count: config5.tools.confirmed.length,
|
|
2386
2388
|
pending_count: config5.tools.pending_evaluation.length,
|
|
2387
|
-
instructions: "Write updated_config_json to .
|
|
2389
|
+
instructions: "Write updated_config_json to .toolcairn/config.json to persist this change."
|
|
2388
2390
|
});
|
|
2389
2391
|
} catch (e) {
|
|
2390
2392
|
logger6.error({ err: e }, "update_project_config failed");
|
|
@@ -2640,7 +2642,7 @@ async function addToolsToServer(server) {
|
|
|
2640
2642
|
server.registerTool(
|
|
2641
2643
|
"get_stack",
|
|
2642
2644
|
{
|
|
2643
|
-
description: 'Build a complementary tool stack for a project use case. For best results, call refine_requirement first with classification "stack_building", evaluate its decomposition_prompt to get sub-needs, then pass each {sub_need_type, keyword_sentence} object as a sub_needs entry. This lets get_stack keyword-match per layer (e.g. "web-framework", "database", "auth") instead of one broad search. Falls back to balanced search when sub_needs is omitted.',
|
|
2645
|
+
description: 'Build a complementary tool stack for a project use case. For best results, call refine_requirement first with classification "stack_building", evaluate its decomposition_prompt to get sub-needs, then pass each {sub_need_type, keyword_sentence} object as a sub_needs entry. This lets get_stack keyword-match per layer (e.g. "web-framework", "database", "auth") instead of one broad search. Falls back to balanced search when sub_needs is omitted. Each tool in the returned stack also carries a `version` object with the recommended version that is cross-compatible with the rest of the stack (downgraded from latest if needed to satisfy peer constraints), plus a top-level `compatibility_matrix` + `stack_compatibility` summarising cross-tool version fit.',
|
|
2644
2646
|
inputSchema: getStackSchema
|
|
2645
2647
|
},
|
|
2646
2648
|
wrap("get_stack", async (args) => remote.getStack(args))
|
|
@@ -2648,7 +2650,7 @@ async function addToolsToServer(server) {
|
|
|
2648
2650
|
server.registerTool(
|
|
2649
2651
|
"check_compatibility",
|
|
2650
2652
|
{
|
|
2651
|
-
description:
|
|
2653
|
+
description: 'Check compatibility between two tools with version-aware matching. When both tools have declared dependency metadata (npm peerDependencies, PyPI requires_dist, etc.) the handler evaluates range constraints directly and returns a version_checks array plus runtime_requirements. Pass optional tool_a_version / tool_b_version to evaluate specific versions (e.g. "is next@14 compatible with react@17?"). Falls back to graph-edge + shared-neighbors inference when version metadata is unavailable. Response includes `source`: "declared_dependency" | "graph_edges" | "shared_neighbors".',
|
|
2652
2654
|
inputSchema: checkCompatibilitySchema
|
|
2653
2655
|
},
|
|
2654
2656
|
wrap("check_compatibility", async (args) => remote.checkCompatibility(args))
|