@neurynae/toolcairn-mcp 0.8.3 → 0.8.5
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/bin/toolpilot-mcp.js +22 -3
- package/dist/index.js +123 -113
- package/dist/index.js.map +1 -1
- package/package.json +8 -13
- package/dist/chunk-B74KV6FC.js +0 -59
- package/dist/chunk-B74KV6FC.js.map +0 -1
- package/dist/dist-LZ2PMHGT.js +0 -6056
- package/dist/dist-LZ2PMHGT.js.map +0 -1
package/bin/toolpilot-mcp.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Entry point for `npx @
|
|
3
|
-
//
|
|
2
|
+
// Entry point for `npx @neurynae/toolcairn-mcp` or `toolcairn-mcp` CLI.
|
|
3
|
+
//
|
|
4
|
+
// Subcommands:
|
|
5
|
+
// (none) — start the MCP server (default)
|
|
6
|
+
// scan [dir] — scan project dependencies and check ToolCairn health status
|
|
7
|
+
// scan --json — same but output raw JSON
|
|
8
|
+
//
|
|
4
9
|
process.env.TOOLPILOT_MODE = process.env.TOOLPILOT_MODE ?? 'production';
|
|
5
|
-
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
|
|
13
|
+
if (args[0] === 'scan') {
|
|
14
|
+
// Stack scanner CLI — does NOT start the MCP server
|
|
15
|
+
import('../dist/cli/scan.js').then(({ runScan }) => {
|
|
16
|
+
return runScan(args.slice(1));
|
|
17
|
+
}).catch((err) => {
|
|
18
|
+
console.error('scan failed:', err.message);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
});
|
|
21
|
+
} else {
|
|
22
|
+
// Default: start the MCP server
|
|
23
|
+
import('../dist/index.js');
|
|
24
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { createRequire as __nodeCreateRequire } from 'module'; const require = __nodeCreateRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
+
}) : x)(function(x) {
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
14
|
+
var __esm = (fn, res) => function __init() {
|
|
15
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
|
+
};
|
|
17
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
18
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
|
|
37
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js
|
|
38
|
+
import path from "path";
|
|
39
|
+
import { fileURLToPath } from "url";
|
|
40
|
+
var init_esm_shims = __esm({
|
|
41
|
+
"../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js"() {
|
|
42
|
+
"use strict";
|
|
43
|
+
}
|
|
44
|
+
});
|
|
8
45
|
|
|
9
46
|
// ../../packages/config/dist/index.js
|
|
10
47
|
var require_dist = __commonJS({
|
|
@@ -15,34 +52,14 @@ var require_dist = __commonJS({
|
|
|
15
52
|
exports.config = void 0;
|
|
16
53
|
var zod_1 = __require("zod");
|
|
17
54
|
var configSchema = zod_1.z.object({
|
|
18
|
-
// ── Memgraph ──────────────────────────────────────────────────────────────
|
|
19
|
-
MEMGRAPH_URL: zod_1.z.string().default("bolt://localhost:7687"),
|
|
20
|
-
MEMGRAPH_USER: zod_1.z.string().default(""),
|
|
21
|
-
MEMGRAPH_PASSWORD: zod_1.z.string().default(""),
|
|
22
|
-
// ── Qdrant ────────────────────────────────────────────────────────────────
|
|
23
|
-
QDRANT_URL: zod_1.z.string().default("http://localhost:6333"),
|
|
24
|
-
QDRANT_API_KEY: zod_1.z.string().optional(),
|
|
25
|
-
// ── PostgreSQL ────────────────────────────────────────────────────────────
|
|
26
|
-
DATABASE_URL: zod_1.z.string().default("postgresql://toolpilot:toolpilot@localhost:5432/toolpilot"),
|
|
27
|
-
// ── Redis ─────────────────────────────────────────────────────────────────
|
|
28
|
-
REDIS_URL: zod_1.z.string().default("redis://localhost:6379"),
|
|
29
|
-
// ── Nomic Embed Code ──────────────────────────────────────────────────────
|
|
30
|
-
NOMIC_API_KEY: zod_1.z.string().optional(),
|
|
31
|
-
// ── GitHub (Indexer) ──────────────────────────────────────────────────────
|
|
32
|
-
GITHUB_TOKEN: zod_1.z.string().optional(),
|
|
33
55
|
// ── MCP Server ────────────────────────────────────────────────────────────
|
|
34
56
|
MCP_SERVER_PORT: zod_1.z.coerce.number().int().positive().default(3001),
|
|
35
57
|
MCP_SERVER_HOST: zod_1.z.string().default("0.0.0.0"),
|
|
36
|
-
// ── Web App ───────────────────────────────────────────────────────────────
|
|
37
|
-
NEXT_PUBLIC_APP_URL: zod_1.z.string().default("http://localhost:3000"),
|
|
38
|
-
ADMIN_SECRET: zod_1.z.string().default("change-me-in-production"),
|
|
39
58
|
// ── Deployment Mode ───────────────────────────────────────────────────────
|
|
40
59
|
/** dev: direct Docker DB connections | production: HTTP client to remote API */
|
|
41
60
|
TOOLPILOT_MODE: zod_1.z.enum(["dev", "staging", "production"]).default("dev"),
|
|
42
|
-
/** URL of the
|
|
61
|
+
/** URL of the ToolCairn HTTP API (used when TOOLPILOT_MODE=production) */
|
|
43
62
|
TOOLPILOT_API_URL: zod_1.z.string().default("https://api.neurynae.com"),
|
|
44
|
-
/** Secret shared between Cloudflare Worker and the API origin server */
|
|
45
|
-
ORIGIN_SECRET: zod_1.z.string().optional(),
|
|
46
63
|
// ── General ───────────────────────────────────────────────────────────────
|
|
47
64
|
NODE_ENV: zod_1.z.enum(["development", "test", "production"]).default("development"),
|
|
48
65
|
LOG_LEVEL: zod_1.z.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info")
|
|
@@ -62,7 +79,7 @@ var require_dist = __commonJS({
|
|
|
62
79
|
|
|
63
80
|
// src/index.prod.ts
|
|
64
81
|
init_esm_shims();
|
|
65
|
-
var
|
|
82
|
+
var import_config4 = __toESM(require_dist(), 1);
|
|
66
83
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
67
84
|
|
|
68
85
|
// ../../packages/remote/dist/index.js
|
|
@@ -132,9 +149,9 @@ var ToolCairnClient = class {
|
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
// ── Private ──────────────────────────────────────────────────────────────
|
|
135
|
-
async post(
|
|
152
|
+
async post(path2, body) {
|
|
136
153
|
try {
|
|
137
|
-
const res = await this.rawPost(
|
|
154
|
+
const res = await this.rawPost(path2, body);
|
|
138
155
|
const data = await res.json();
|
|
139
156
|
if (data && typeof data === "object" && "content" in data) {
|
|
140
157
|
return data;
|
|
@@ -159,7 +176,7 @@ var ToolCairnClient = class {
|
|
|
159
176
|
};
|
|
160
177
|
}
|
|
161
178
|
}
|
|
162
|
-
rawPost(
|
|
179
|
+
rawPost(path2, body) {
|
|
163
180
|
const headers = {
|
|
164
181
|
"Content-Type": "application/json",
|
|
165
182
|
"X-ToolCairn-Key": this.apiKey,
|
|
@@ -168,7 +185,7 @@ var ToolCairnClient = class {
|
|
|
168
185
|
if (this.accessToken) {
|
|
169
186
|
headers.Authorization = `Bearer ${this.accessToken}`;
|
|
170
187
|
}
|
|
171
|
-
return fetch(`${this.baseUrl}${
|
|
188
|
+
return fetch(`${this.baseUrl}${path2}`, {
|
|
172
189
|
method: "POST",
|
|
173
190
|
headers,
|
|
174
191
|
body: JSON.stringify(body),
|
|
@@ -857,13 +874,13 @@ async function createIfAbsent(filePath, content, label) {
|
|
|
857
874
|
|
|
858
875
|
// src/server.prod.ts
|
|
859
876
|
init_esm_shims();
|
|
860
|
-
var
|
|
877
|
+
var import_config2 = __toESM(require_dist(), 1);
|
|
861
878
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
862
879
|
|
|
863
|
-
// ../../packages/tools/dist/
|
|
880
|
+
// ../../packages/tools-local/dist/index.js
|
|
864
881
|
init_esm_shims();
|
|
865
882
|
|
|
866
|
-
// ../../packages/tools/dist/schemas.js
|
|
883
|
+
// ../../packages/tools-local/dist/schemas.js
|
|
867
884
|
init_esm_shims();
|
|
868
885
|
import { z } from "zod";
|
|
869
886
|
var searchToolsSchema = {
|
|
@@ -988,7 +1005,7 @@ var refineRequirementSchema = {
|
|
|
988
1005
|
}).optional()
|
|
989
1006
|
};
|
|
990
1007
|
|
|
991
|
-
// ../../packages/tools/dist/utils.js
|
|
1008
|
+
// ../../packages/tools-local/dist/utils.js
|
|
992
1009
|
init_esm_shims();
|
|
993
1010
|
function okResult(data) {
|
|
994
1011
|
return {
|
|
@@ -1002,10 +1019,10 @@ function errResult(error, message) {
|
|
|
1002
1019
|
};
|
|
1003
1020
|
}
|
|
1004
1021
|
|
|
1005
|
-
// ../../packages/tools/dist/handlers/classify-prompt.js
|
|
1022
|
+
// ../../packages/tools-local/dist/handlers/classify-prompt.js
|
|
1006
1023
|
init_esm_shims();
|
|
1007
1024
|
import pino2 from "pino";
|
|
1008
|
-
var logger2 = pino2({ name: "@
|
|
1025
|
+
var logger2 = pino2({ name: "@toolcairn/tools:classify-prompt" });
|
|
1009
1026
|
var TOOL_REQUIRED_CLASSIFICATIONS = [
|
|
1010
1027
|
"tool_discovery",
|
|
1011
1028
|
"stack_building",
|
|
@@ -1064,16 +1081,16 @@ Respond with ONLY 0 or 1.`;
|
|
|
1064
1081
|
}
|
|
1065
1082
|
}
|
|
1066
1083
|
|
|
1067
|
-
// ../../packages/tools/dist/handlers/
|
|
1084
|
+
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
1068
1085
|
init_esm_shims();
|
|
1069
1086
|
import pino3 from "pino";
|
|
1070
1087
|
|
|
1071
|
-
// ../../packages/tools/dist/templates/agent-instructions.js
|
|
1088
|
+
// ../../packages/tools-local/dist/templates/agent-instructions.js
|
|
1072
1089
|
init_esm_shims();
|
|
1073
1090
|
var TOOLPILOT_MCP_ENTRY = {
|
|
1074
1091
|
toolpilot: {
|
|
1075
1092
|
command: "npx",
|
|
1076
|
-
args: ["-y", "@
|
|
1093
|
+
args: ["-y", "@toolcairn/mcp@latest"]
|
|
1077
1094
|
}
|
|
1078
1095
|
};
|
|
1079
1096
|
var CORE_RULES = `
|
|
@@ -1204,13 +1221,13 @@ function getOpenCodeMcpEntry(serverPath) {
|
|
|
1204
1221
|
return {
|
|
1205
1222
|
toolpilot: {
|
|
1206
1223
|
type: "local",
|
|
1207
|
-
command: resolvedPath ? ["node", resolvedPath] : ["npx", "-y", "@
|
|
1224
|
+
command: resolvedPath ? ["node", resolvedPath] : ["npx", "-y", "@toolcairn/mcp@latest"],
|
|
1208
1225
|
enabled: true
|
|
1209
1226
|
}
|
|
1210
1227
|
};
|
|
1211
1228
|
}
|
|
1212
1229
|
|
|
1213
|
-
// ../../packages/tools/dist/templates/generate-tracker.js
|
|
1230
|
+
// ../../packages/tools-local/dist/templates/generate-tracker.js
|
|
1214
1231
|
init_esm_shims();
|
|
1215
1232
|
function generateTrackerHtml2(eventsPath) {
|
|
1216
1233
|
return `<!DOCTYPE html>
|
|
@@ -1615,9 +1632,9 @@ if (!EVENTS_PATH || EVENTS_PATH === 'null') {
|
|
|
1615
1632
|
</html>`;
|
|
1616
1633
|
}
|
|
1617
1634
|
|
|
1618
|
-
// ../../packages/tools/dist/handlers/
|
|
1619
|
-
var logger3 = pino3({ name: "@
|
|
1620
|
-
async function
|
|
1635
|
+
// ../../packages/tools-local/dist/handlers/toolcairn-init.js
|
|
1636
|
+
var logger3 = pino3({ name: "@toolcairn/tools:toolpilot-init" });
|
|
1637
|
+
async function handleToolcairnInit(args) {
|
|
1621
1638
|
try {
|
|
1622
1639
|
logger3.info({ agent: args.agent, project_root: args.project_root }, "toolpilot_init called");
|
|
1623
1640
|
const instructions = getInstructionsForAgent(args.agent);
|
|
@@ -1702,10 +1719,10 @@ async function handleToolpilotInit(args) {
|
|
|
1702
1719
|
}
|
|
1703
1720
|
}
|
|
1704
1721
|
|
|
1705
|
-
// ../../packages/tools/dist/handlers/init-project-config.js
|
|
1722
|
+
// ../../packages/tools-local/dist/handlers/init-project-config.js
|
|
1706
1723
|
init_esm_shims();
|
|
1707
1724
|
import pino4 from "pino";
|
|
1708
|
-
var logger4 = pino4({ name: "@
|
|
1725
|
+
var logger4 = pino4({ name: "@toolcairn/tools:init-project-config" });
|
|
1709
1726
|
async function handleInitProjectConfig(args) {
|
|
1710
1727
|
try {
|
|
1711
1728
|
logger4.info({ project: args.project_name }, "init_project_config called");
|
|
@@ -1718,7 +1735,7 @@ async function handleInitProjectConfig(args) {
|
|
|
1718
1735
|
chosen_reason: "Auto-detected from project files during toolpilot_init",
|
|
1719
1736
|
alternatives_considered: []
|
|
1720
1737
|
}));
|
|
1721
|
-
const
|
|
1738
|
+
const config5 = {
|
|
1722
1739
|
version: "1.0",
|
|
1723
1740
|
project: {
|
|
1724
1741
|
name: args.project_name,
|
|
@@ -1738,7 +1755,7 @@ async function handleInitProjectConfig(args) {
|
|
|
1738
1755
|
}
|
|
1739
1756
|
]
|
|
1740
1757
|
};
|
|
1741
|
-
const config_json = JSON.stringify(
|
|
1758
|
+
const config_json = JSON.stringify(config5, null, 2);
|
|
1742
1759
|
return okResult({
|
|
1743
1760
|
config_json,
|
|
1744
1761
|
file_path: ".toolpilot/config.json",
|
|
@@ -1752,10 +1769,10 @@ async function handleInitProjectConfig(args) {
|
|
|
1752
1769
|
}
|
|
1753
1770
|
}
|
|
1754
1771
|
|
|
1755
|
-
// ../../packages/tools/dist/handlers/read-project-config.js
|
|
1772
|
+
// ../../packages/tools-local/dist/handlers/read-project-config.js
|
|
1756
1773
|
init_esm_shims();
|
|
1757
1774
|
import pino5 from "pino";
|
|
1758
|
-
var logger5 = pino5({ name: "@
|
|
1775
|
+
var logger5 = pino5({ name: "@toolcairn/tools:read-project-config" });
|
|
1759
1776
|
var STALENESS_THRESHOLD_DAYS = 90;
|
|
1760
1777
|
function daysSince(isoDate) {
|
|
1761
1778
|
return (Date.now() - new Date(isoDate).getTime()) / (1e3 * 60 * 60 * 24);
|
|
@@ -1763,18 +1780,18 @@ function daysSince(isoDate) {
|
|
|
1763
1780
|
async function handleReadProjectConfig(args) {
|
|
1764
1781
|
try {
|
|
1765
1782
|
logger5.info("read_project_config called");
|
|
1766
|
-
let
|
|
1783
|
+
let config5;
|
|
1767
1784
|
try {
|
|
1768
|
-
|
|
1785
|
+
config5 = JSON.parse(args.config_content);
|
|
1769
1786
|
} catch {
|
|
1770
1787
|
return errResult("parse_error", "config_content is not valid JSON");
|
|
1771
1788
|
}
|
|
1772
|
-
if (
|
|
1773
|
-
return errResult("version_error", `Unsupported config version: ${
|
|
1789
|
+
if (config5.version !== "1.0") {
|
|
1790
|
+
return errResult("version_error", `Unsupported config version: ${config5.version}`);
|
|
1774
1791
|
}
|
|
1775
|
-
const confirmedToolNames =
|
|
1776
|
-
const pendingToolNames =
|
|
1777
|
-
const staleTools =
|
|
1792
|
+
const confirmedToolNames = config5.tools.confirmed.map((t) => t.name);
|
|
1793
|
+
const pendingToolNames = config5.tools.pending_evaluation.map((t) => t.name);
|
|
1794
|
+
const staleTools = config5.tools.confirmed.filter((t) => {
|
|
1778
1795
|
const date = t.last_verified ?? t.chosen_at ?? t.confirmed_at;
|
|
1779
1796
|
return date ? daysSince(date) > STALENESS_THRESHOLD_DAYS : true;
|
|
1780
1797
|
}).map((t) => {
|
|
@@ -1787,10 +1804,10 @@ async function handleReadProjectConfig(args) {
|
|
|
1787
1804
|
recommendation: "Consider using check_issue to verify no new known issues"
|
|
1788
1805
|
};
|
|
1789
1806
|
});
|
|
1790
|
-
const non_oss_tools =
|
|
1791
|
-
const toolpilot_indexed_tools =
|
|
1807
|
+
const non_oss_tools = config5.tools.confirmed.filter((t) => t.source === "non_oss").map((t) => t.name);
|
|
1808
|
+
const toolpilot_indexed_tools = config5.tools.confirmed.filter((t) => t.source === "toolpilot").map((t) => t.name);
|
|
1792
1809
|
return okResult({
|
|
1793
|
-
project:
|
|
1810
|
+
project: config5.project,
|
|
1794
1811
|
confirmed_tools: confirmedToolNames,
|
|
1795
1812
|
pending_tools: pendingToolNames,
|
|
1796
1813
|
non_oss_tools,
|
|
@@ -1798,9 +1815,9 @@ async function handleReadProjectConfig(args) {
|
|
|
1798
1815
|
stale_tools: staleTools,
|
|
1799
1816
|
total_confirmed: confirmedToolNames.length,
|
|
1800
1817
|
total_pending: pendingToolNames.length,
|
|
1801
|
-
last_audit_entry:
|
|
1818
|
+
last_audit_entry: config5.audit_log.at(-1) ?? null,
|
|
1802
1819
|
agent_instructions: [
|
|
1803
|
-
`Project: ${
|
|
1820
|
+
`Project: ${config5.project.name} (${config5.project.language}${config5.project.framework ? `, ${config5.project.framework}` : ""})`,
|
|
1804
1821
|
`Already confirmed tools: ${confirmedToolNames.join(", ") || "none"}`,
|
|
1805
1822
|
"When recommending tools, skip any already in confirmed_tools.",
|
|
1806
1823
|
non_oss_tools.length > 0 ? `Non-OSS tools in project (handle separately): ${non_oss_tools.join(", ")}` : "",
|
|
@@ -1813,16 +1830,16 @@ async function handleReadProjectConfig(args) {
|
|
|
1813
1830
|
}
|
|
1814
1831
|
}
|
|
1815
1832
|
|
|
1816
|
-
// ../../packages/tools/dist/handlers/update-project-config.js
|
|
1833
|
+
// ../../packages/tools-local/dist/handlers/update-project-config.js
|
|
1817
1834
|
init_esm_shims();
|
|
1818
1835
|
import pino6 from "pino";
|
|
1819
|
-
var logger6 = pino6({ name: "@
|
|
1836
|
+
var logger6 = pino6({ name: "@toolcairn/tools:update-project-config" });
|
|
1820
1837
|
async function handleUpdateProjectConfig(args) {
|
|
1821
1838
|
try {
|
|
1822
1839
|
logger6.info({ action: args.action, tool: args.tool_name }, "update_project_config called");
|
|
1823
|
-
let
|
|
1840
|
+
let config5;
|
|
1824
1841
|
try {
|
|
1825
|
-
|
|
1842
|
+
config5 = JSON.parse(args.current_config);
|
|
1826
1843
|
} catch {
|
|
1827
1844
|
return errResult("parse_error", "current_config is not valid JSON");
|
|
1828
1845
|
}
|
|
@@ -1830,8 +1847,8 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1830
1847
|
const data = args.data ?? {};
|
|
1831
1848
|
switch (args.action) {
|
|
1832
1849
|
case "add_tool": {
|
|
1833
|
-
|
|
1834
|
-
if (!
|
|
1850
|
+
config5.tools.pending_evaluation = config5.tools.pending_evaluation.filter((t) => t.name !== args.tool_name);
|
|
1851
|
+
if (!config5.tools.confirmed.some((t) => t.name === args.tool_name)) {
|
|
1835
1852
|
const newTool = {
|
|
1836
1853
|
name: args.tool_name,
|
|
1837
1854
|
source: data.source ?? "toolpilot",
|
|
@@ -1843,9 +1860,9 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1843
1860
|
query_id: data.query_id,
|
|
1844
1861
|
notes: data.notes
|
|
1845
1862
|
};
|
|
1846
|
-
|
|
1863
|
+
config5.tools.confirmed.push(newTool);
|
|
1847
1864
|
}
|
|
1848
|
-
|
|
1865
|
+
config5.audit_log.push({
|
|
1849
1866
|
action: "add_tool",
|
|
1850
1867
|
tool: args.tool_name,
|
|
1851
1868
|
timestamp: now,
|
|
@@ -1854,9 +1871,9 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1854
1871
|
break;
|
|
1855
1872
|
}
|
|
1856
1873
|
case "remove_tool": {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1874
|
+
config5.tools.confirmed = config5.tools.confirmed.filter((t) => t.name !== args.tool_name);
|
|
1875
|
+
config5.tools.pending_evaluation = config5.tools.pending_evaluation.filter((t) => t.name !== args.tool_name);
|
|
1876
|
+
config5.audit_log.push({
|
|
1860
1877
|
action: "remove_tool",
|
|
1861
1878
|
tool: args.tool_name,
|
|
1862
1879
|
timestamp: now,
|
|
@@ -1865,22 +1882,22 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1865
1882
|
break;
|
|
1866
1883
|
}
|
|
1867
1884
|
case "update_tool": {
|
|
1868
|
-
const idx =
|
|
1885
|
+
const idx = config5.tools.confirmed.findIndex((t) => t.name === args.tool_name);
|
|
1869
1886
|
if (idx === -1) {
|
|
1870
1887
|
return errResult("not_found", `Tool "${args.tool_name}" not found in confirmed tools`);
|
|
1871
1888
|
}
|
|
1872
|
-
const existing =
|
|
1889
|
+
const existing = config5.tools.confirmed[idx];
|
|
1873
1890
|
if (!existing) {
|
|
1874
1891
|
return errResult("not_found", `Tool "${args.tool_name}" not found`);
|
|
1875
1892
|
}
|
|
1876
|
-
|
|
1893
|
+
config5.tools.confirmed[idx] = {
|
|
1877
1894
|
...existing,
|
|
1878
1895
|
...data.version !== void 0 ? { version: data.version } : {},
|
|
1879
1896
|
...data.notes !== void 0 ? { notes: data.notes } : {},
|
|
1880
1897
|
...data.chosen_reason !== void 0 ? { chosen_reason: data.chosen_reason } : {},
|
|
1881
1898
|
...data.alternatives_considered !== void 0 ? { alternatives_considered: data.alternatives_considered } : {}
|
|
1882
1899
|
};
|
|
1883
|
-
|
|
1900
|
+
config5.audit_log.push({
|
|
1884
1901
|
action: "update_tool",
|
|
1885
1902
|
tool: args.tool_name,
|
|
1886
1903
|
timestamp: now,
|
|
@@ -1889,15 +1906,15 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1889
1906
|
break;
|
|
1890
1907
|
}
|
|
1891
1908
|
case "add_evaluation": {
|
|
1892
|
-
if (!
|
|
1909
|
+
if (!config5.tools.pending_evaluation.some((t) => t.name === args.tool_name) && !config5.tools.confirmed.some((t) => t.name === args.tool_name)) {
|
|
1893
1910
|
const pending = {
|
|
1894
1911
|
name: args.tool_name,
|
|
1895
1912
|
category: data.category ?? "other",
|
|
1896
1913
|
added_at: now
|
|
1897
1914
|
};
|
|
1898
|
-
|
|
1915
|
+
config5.tools.pending_evaluation.push(pending);
|
|
1899
1916
|
}
|
|
1900
|
-
|
|
1917
|
+
config5.audit_log.push({
|
|
1901
1918
|
action: "add_evaluation",
|
|
1902
1919
|
tool: args.tool_name,
|
|
1903
1920
|
timestamp: now,
|
|
@@ -1906,14 +1923,14 @@ async function handleUpdateProjectConfig(args) {
|
|
|
1906
1923
|
break;
|
|
1907
1924
|
}
|
|
1908
1925
|
}
|
|
1909
|
-
const updated_config_json = JSON.stringify(
|
|
1926
|
+
const updated_config_json = JSON.stringify(config5, null, 2);
|
|
1910
1927
|
return okResult({
|
|
1911
1928
|
updated_config_json,
|
|
1912
1929
|
file_path: ".toolpilot/config.json",
|
|
1913
1930
|
action_applied: args.action,
|
|
1914
1931
|
tool_name: args.tool_name,
|
|
1915
|
-
confirmed_count:
|
|
1916
|
-
pending_count:
|
|
1932
|
+
confirmed_count: config5.tools.confirmed.length,
|
|
1933
|
+
pending_count: config5.tools.pending_evaluation.length,
|
|
1917
1934
|
instructions: "Write updated_config_json to .toolpilot/config.json to persist this change."
|
|
1918
1935
|
});
|
|
1919
1936
|
} catch (e) {
|
|
@@ -1928,21 +1945,11 @@ import { z as z2 } from "zod";
|
|
|
1928
1945
|
|
|
1929
1946
|
// src/middleware/event-logger.ts
|
|
1930
1947
|
init_esm_shims();
|
|
1948
|
+
var import_config = __toESM(require_dist(), 1);
|
|
1931
1949
|
import { appendFile, mkdir as mkdir3 } from "fs/promises";
|
|
1932
1950
|
import { dirname } from "path";
|
|
1933
1951
|
import pino7 from "pino";
|
|
1934
1952
|
var logger7 = pino7({ name: "@toolcairn/mcp-server:event-logger" });
|
|
1935
|
-
var _prisma = null;
|
|
1936
|
-
async function getPrisma() {
|
|
1937
|
-
if (!_prisma) {
|
|
1938
|
-
try {
|
|
1939
|
-
const mod = await import("./dist-LZ2PMHGT.js");
|
|
1940
|
-
_prisma = new mod.PrismaClient();
|
|
1941
|
-
} catch {
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
return _prisma;
|
|
1945
|
-
}
|
|
1946
1953
|
function isTrackingEnabled() {
|
|
1947
1954
|
return process.env.TOOLCAIRN_TRACKING_ENABLED !== "false";
|
|
1948
1955
|
}
|
|
@@ -1989,23 +1996,26 @@ async function writeToFile(eventsPath, event) {
|
|
|
1989
1996
|
logger7.warn({ err: e, path: eventsPath }, "Failed to write event to JSONL file");
|
|
1990
1997
|
}
|
|
1991
1998
|
}
|
|
1992
|
-
async function
|
|
1999
|
+
async function sendToApi(event) {
|
|
1993
2000
|
try {
|
|
1994
|
-
const
|
|
1995
|
-
if (!
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
2001
|
+
const creds = await loadCredentials();
|
|
2002
|
+
if (!creds) return;
|
|
2003
|
+
const headers = { "Content-Type": "application/json" };
|
|
2004
|
+
if (creds.access_token) headers["Authorization"] = `Bearer ${creds.access_token}`;
|
|
2005
|
+
if (creds.client_id) headers["X-ToolCairn-Key"] = creds.client_id;
|
|
2006
|
+
await fetch(`${import_config.config.TOOLPILOT_API_URL}/v1/events`, {
|
|
2007
|
+
method: "POST",
|
|
2008
|
+
headers,
|
|
2009
|
+
body: JSON.stringify({
|
|
1999
2010
|
tool_name: event.tool_name,
|
|
2000
2011
|
query_id: event.query_id,
|
|
2001
2012
|
duration_ms: event.duration_ms,
|
|
2002
2013
|
status: event.status,
|
|
2003
|
-
metadata: event.metadata
|
|
2004
|
-
|
|
2005
|
-
}
|
|
2014
|
+
metadata: event.metadata
|
|
2015
|
+
})
|
|
2006
2016
|
});
|
|
2007
2017
|
} catch (e) {
|
|
2008
|
-
logger7.
|
|
2018
|
+
logger7.debug({ err: e }, "Failed to send event to API \u2014 non-fatal");
|
|
2009
2019
|
}
|
|
2010
2020
|
}
|
|
2011
2021
|
function withEventLogging(toolName, handler) {
|
|
@@ -2033,7 +2043,7 @@ function withEventLogging(toolName, handler) {
|
|
|
2033
2043
|
metadata: result ? extractMetadata(toolName, result) : null,
|
|
2034
2044
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2035
2045
|
};
|
|
2036
|
-
|
|
2046
|
+
sendToApi(event).catch(() => {
|
|
2037
2047
|
});
|
|
2038
2048
|
const eventsPath = getEventsPath();
|
|
2039
2049
|
if (eventsPath) {
|
|
@@ -2096,7 +2106,7 @@ async function addToolsToServer(server) {
|
|
|
2096
2106
|
throw new Error("ToolCairn: authentication required.");
|
|
2097
2107
|
}
|
|
2098
2108
|
const remote = new ToolCairnClient({
|
|
2099
|
-
baseUrl:
|
|
2109
|
+
baseUrl: import_config2.config.TOOLPILOT_API_URL,
|
|
2100
2110
|
apiKey: creds.client_id,
|
|
2101
2111
|
accessToken: creds.access_token
|
|
2102
2112
|
});
|
|
@@ -2115,7 +2125,7 @@ async function addToolsToServer(server) {
|
|
|
2115
2125
|
description: "Set up ToolCairn integration for the current project. Generates agent instruction content, MCP config entry, and project config initializer.",
|
|
2116
2126
|
inputSchema: toolpilotInitSchema
|
|
2117
2127
|
},
|
|
2118
|
-
withEventLogging("toolcairn_init", async (args) =>
|
|
2128
|
+
withEventLogging("toolcairn_init", async (args) => handleToolcairnInit(args))
|
|
2119
2129
|
);
|
|
2120
2130
|
server.registerTool(
|
|
2121
2131
|
"init_project_config",
|
|
@@ -2264,7 +2274,7 @@ async function addToolsToServer(server) {
|
|
|
2264
2274
|
};
|
|
2265
2275
|
}
|
|
2266
2276
|
try {
|
|
2267
|
-
const user = await startDeviceAuth(
|
|
2277
|
+
const user = await startDeviceAuth(import_config2.config.TOOLPILOT_API_URL);
|
|
2268
2278
|
return {
|
|
2269
2279
|
content: [
|
|
2270
2280
|
{
|
|
@@ -2299,7 +2309,7 @@ async function buildProdServer() {
|
|
|
2299
2309
|
|
|
2300
2310
|
// src/transport.ts
|
|
2301
2311
|
init_esm_shims();
|
|
2302
|
-
var
|
|
2312
|
+
var import_config3 = __toESM(require_dist(), 1);
|
|
2303
2313
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2304
2314
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2305
2315
|
function createTransport() {
|
|
@@ -2332,7 +2342,7 @@ async function main() {
|
|
|
2332
2342
|
userCode = pending.user_code;
|
|
2333
2343
|
logger9.info({ userCode }, "Resuming pending sign-in");
|
|
2334
2344
|
} else {
|
|
2335
|
-
const codeData = await requestDeviceCode(
|
|
2345
|
+
const codeData = await requestDeviceCode(import_config4.config.TOOLPILOT_API_URL);
|
|
2336
2346
|
verificationUri = codeData.verification_uri;
|
|
2337
2347
|
userCode = codeData.user_code;
|
|
2338
2348
|
logger9.info({ userCode }, "New sign-in started");
|
|
@@ -2369,7 +2379,7 @@ Open the URL, sign in, and confirm the code shown. All 14 tools will appear auto
|
|
|
2369
2379
|
]
|
|
2370
2380
|
})
|
|
2371
2381
|
);
|
|
2372
|
-
startDeviceAuth(
|
|
2382
|
+
startDeviceAuth(import_config4.config.TOOLPILOT_API_URL).then(async () => {
|
|
2373
2383
|
logger9.info("Sign-in complete \u2014 adding all tools to running server");
|
|
2374
2384
|
try {
|
|
2375
2385
|
await addToolsToServer(server);
|