@backendkit-labs/mcp-server 0.14.0
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/agent-server.d.ts +88 -0
- package/dist/agent-server.d.ts.map +1 -0
- package/dist/agent-server.js +149 -0
- package/dist/agent-server.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/graph-store.d.ts +48 -0
- package/dist/indexer/graph-store.d.ts.map +1 -0
- package/dist/indexer/graph-store.js +233 -0
- package/dist/indexer/graph-store.js.map +1 -0
- package/dist/indexer/indexer.d.ts +17 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +180 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/indexer/languages/go.d.ts +2 -0
- package/dist/indexer/languages/go.d.ts.map +1 -0
- package/dist/indexer/languages/go.js +36 -0
- package/dist/indexer/languages/go.js.map +1 -0
- package/dist/indexer/languages/index.d.ts +27 -0
- package/dist/indexer/languages/index.d.ts.map +1 -0
- package/dist/indexer/languages/index.js +25 -0
- package/dist/indexer/languages/index.js.map +1 -0
- package/dist/indexer/languages/java.d.ts +2 -0
- package/dist/indexer/languages/java.d.ts.map +1 -0
- package/dist/indexer/languages/java.js +39 -0
- package/dist/indexer/languages/java.js.map +1 -0
- package/dist/indexer/languages/python.d.ts +2 -0
- package/dist/indexer/languages/python.d.ts.map +1 -0
- package/dist/indexer/languages/python.js +41 -0
- package/dist/indexer/languages/python.js.map +1 -0
- package/dist/indexer/languages/rust.d.ts +2 -0
- package/dist/indexer/languages/rust.d.ts.map +1 -0
- package/dist/indexer/languages/rust.js +49 -0
- package/dist/indexer/languages/rust.js.map +1 -0
- package/dist/indexer/languages/typescript.d.ts +2 -0
- package/dist/indexer/languages/typescript.d.ts.map +1 -0
- package/dist/indexer/languages/typescript.js +47 -0
- package/dist/indexer/languages/typescript.js.map +1 -0
- package/dist/indexer/languages/utils.d.ts +2 -0
- package/dist/indexer/languages/utils.d.ts.map +1 -0
- package/dist/indexer/languages/utils.js +52 -0
- package/dist/indexer/languages/utils.js.map +1 -0
- package/dist/indexer/parser.d.ts +24 -0
- package/dist/indexer/parser.d.ts.map +1 -0
- package/dist/indexer/parser.js +136 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/stack-detector.d.ts +3 -0
- package/dist/indexer/stack-detector.d.ts.map +1 -0
- package/dist/indexer/stack-detector.js +63 -0
- package/dist/indexer/stack-detector.js.map +1 -0
- package/dist/indexer/watcher.d.ts +8 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +83 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +308 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/code/context.d.ts +23 -0
- package/dist/tools/code/context.d.ts.map +1 -0
- package/dist/tools/code/context.js +93 -0
- package/dist/tools/code/context.js.map +1 -0
- package/dist/tools/code/search.d.ts +15 -0
- package/dist/tools/code/search.d.ts.map +1 -0
- package/dist/tools/code/search.js +40 -0
- package/dist/tools/code/search.js.map +1 -0
- package/dist/tools/skills/install.d.ts +11 -0
- package/dist/tools/skills/install.d.ts.map +1 -0
- package/dist/tools/skills/install.js +33 -0
- package/dist/tools/skills/install.js.map +1 -0
- package/dist/tools/skills/list.d.ts +9 -0
- package/dist/tools/skills/list.d.ts.map +1 -0
- package/dist/tools/skills/list.js +34 -0
- package/dist/tools/skills/list.js.map +1 -0
- package/dist/tools/skills/search.d.ts +11 -0
- package/dist/tools/skills/search.d.ts.map +1 -0
- package/dist/tools/skills/search.js +44 -0
- package/dist/tools/skills/search.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.parseFile = parseFile;
|
|
40
|
+
const web_tree_sitter_1 = __importDefault(require("web-tree-sitter"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
let initPromise = null;
|
|
43
|
+
const languageCache = new Map();
|
|
44
|
+
async function ensureInit() {
|
|
45
|
+
if (!initPromise) {
|
|
46
|
+
initPromise = web_tree_sitter_1.default.init({
|
|
47
|
+
locateFile: (file) => path.join(path.dirname(require.resolve('web-tree-sitter')), file),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return initPromise;
|
|
51
|
+
}
|
|
52
|
+
async function loadLanguage(config) {
|
|
53
|
+
if (languageCache.has(config.name)) {
|
|
54
|
+
return languageCache.get(config.name);
|
|
55
|
+
}
|
|
56
|
+
await ensureInit();
|
|
57
|
+
const lang = await web_tree_sitter_1.default.Language.load(config.wasmFile);
|
|
58
|
+
languageCache.set(config.name, lang);
|
|
59
|
+
return lang;
|
|
60
|
+
}
|
|
61
|
+
function isExported(node) {
|
|
62
|
+
return node.parent?.type === 'export_statement';
|
|
63
|
+
}
|
|
64
|
+
function extractSignature(node, content) {
|
|
65
|
+
const lines = content.split('\n');
|
|
66
|
+
const firstLine = lines[node.startPosition.row] ?? '';
|
|
67
|
+
return firstLine.slice(node.startPosition.column).trim().slice(0, 120);
|
|
68
|
+
}
|
|
69
|
+
async function parseFile(content, config) {
|
|
70
|
+
const lang = await loadLanguage(config);
|
|
71
|
+
const parser = new web_tree_sitter_1.default();
|
|
72
|
+
parser.setLanguage(lang);
|
|
73
|
+
const tree = parser.parse(content);
|
|
74
|
+
const symbols = [];
|
|
75
|
+
const imports = [];
|
|
76
|
+
const calls = [];
|
|
77
|
+
// --- Symbols ---
|
|
78
|
+
const symbolQuery = lang.query(config.queries.symbols);
|
|
79
|
+
const symbolCaptures = symbolQuery.captures(tree.rootNode);
|
|
80
|
+
for (const cap of symbolCaptures) {
|
|
81
|
+
if (cap.name !== 'node')
|
|
82
|
+
continue;
|
|
83
|
+
let symbolName = '';
|
|
84
|
+
for (const nameCap of symbolCaptures) {
|
|
85
|
+
if (nameCap.name === 'name' &&
|
|
86
|
+
nameCap.node.startIndex >= cap.node.startIndex &&
|
|
87
|
+
nameCap.node.endIndex <= cap.node.endIndex) {
|
|
88
|
+
symbolName = nameCap.node.text;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!symbolName)
|
|
93
|
+
continue;
|
|
94
|
+
const kind = config.kindMap[cap.node.type] ?? 'variable';
|
|
95
|
+
symbols.push({
|
|
96
|
+
name: symbolName,
|
|
97
|
+
kind,
|
|
98
|
+
startLine: cap.node.startPosition.row + 1,
|
|
99
|
+
endLine: cap.node.endPosition.row + 1,
|
|
100
|
+
exported: isExported(cap.node),
|
|
101
|
+
signature: extractSignature(cap.node, content),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
symbolQuery.delete();
|
|
105
|
+
// --- Imports ---
|
|
106
|
+
const importQuery = lang.query(config.queries.imports);
|
|
107
|
+
for (const cap of importQuery.captures(tree.rootNode)) {
|
|
108
|
+
if (cap.name === 'source') {
|
|
109
|
+
imports.push({
|
|
110
|
+
source: cap.node.text,
|
|
111
|
+
line: cap.node.startPosition.row + 1,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
importQuery.delete();
|
|
116
|
+
// --- Calls ---
|
|
117
|
+
const callQuery = lang.query(config.queries.calls);
|
|
118
|
+
const seenCalls = new Set();
|
|
119
|
+
for (const cap of callQuery.captures(tree.rootNode)) {
|
|
120
|
+
if (cap.name === 'name') {
|
|
121
|
+
const key = `${cap.node.text}:${cap.node.startPosition.row}`;
|
|
122
|
+
if (!seenCalls.has(key)) {
|
|
123
|
+
seenCalls.add(key);
|
|
124
|
+
calls.push({
|
|
125
|
+
callee: cap.node.text,
|
|
126
|
+
line: cap.node.startPosition.row + 1,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
callQuery.delete();
|
|
132
|
+
tree.delete();
|
|
133
|
+
parser.delete();
|
|
134
|
+
return { symbols, imports, calls };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/indexer/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-detector.d.ts","sourceRoot":"","sources":["../../src/indexer/stack-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AA+DhD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAiBhE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectStackFromGraph = detectStackFromGraph;
|
|
4
|
+
const SIGNATURES = [
|
|
5
|
+
// Node / TypeScript
|
|
6
|
+
{ tech: 'nestjs', importPatterns: ['@nestjs/'] },
|
|
7
|
+
{ tech: 'express', importPatterns: ['express'] },
|
|
8
|
+
{ tech: 'fastify', importPatterns: ['fastify'] },
|
|
9
|
+
{ tech: 'typeorm', importPatterns: ['typeorm'] },
|
|
10
|
+
{ tech: 'prisma', importPatterns: ['@prisma/client', 'prisma'] },
|
|
11
|
+
{ tech: 'graphql', importPatterns: ['graphql', '@apollo/', 'apollo-server', 'type-graphql'] },
|
|
12
|
+
{ tech: 'mongoose', importPatterns: ['mongoose'] },
|
|
13
|
+
{ tech: 'sequelize', importPatterns: ['sequelize'] },
|
|
14
|
+
{ tech: 'react', importPatterns: ['react', 'react-dom', 'next'] },
|
|
15
|
+
{ tech: 'nextjs', importPatterns: ['next/', 'next/app', 'next/router'] },
|
|
16
|
+
{ tech: 'vue', importPatterns: ['vue', '@vue/'] },
|
|
17
|
+
{ tech: 'angular', importPatterns: ['@angular/'] },
|
|
18
|
+
{ tech: 'jest', importPatterns: ['jest', '@jest/'] },
|
|
19
|
+
{ tech: 'vitest', importPatterns: ['vitest'] },
|
|
20
|
+
{ tech: 'zod', importPatterns: ['zod'] },
|
|
21
|
+
{ tech: 'trpc', importPatterns: ['@trpc/'] },
|
|
22
|
+
{ tech: 'rxjs', importPatterns: ['rxjs'] },
|
|
23
|
+
// Python
|
|
24
|
+
{ tech: 'fastapi', importPatterns: ['fastapi'] },
|
|
25
|
+
{ tech: 'django', importPatterns: ['django'] },
|
|
26
|
+
{ tech: 'flask', importPatterns: ['flask'] },
|
|
27
|
+
{ tech: 'sqlalchemy', importPatterns: ['sqlalchemy'] },
|
|
28
|
+
{ tech: 'pydantic', importPatterns: ['pydantic'] },
|
|
29
|
+
{ tech: 'celery', importPatterns: ['celery'] },
|
|
30
|
+
{ tech: 'pytest', importPatterns: ['pytest'] },
|
|
31
|
+
// Go
|
|
32
|
+
{ tech: 'gin', importPatterns: ['gin-gonic/gin', 'github.com/gin-gonic'] },
|
|
33
|
+
{ tech: 'echo', importPatterns: ['labstack/echo'] },
|
|
34
|
+
{ tech: 'fiber', importPatterns: ['gofiber/fiber'] },
|
|
35
|
+
{ tech: 'gorm', importPatterns: ['gorm.io/gorm'] },
|
|
36
|
+
// Rust
|
|
37
|
+
{ tech: 'actix', importPatterns: ['actix-web', 'actix_web'] },
|
|
38
|
+
{ tech: 'axum', importPatterns: ['axum'] },
|
|
39
|
+
{ tech: 'tokio', importPatterns: ['tokio'] },
|
|
40
|
+
{ tech: 'diesel', importPatterns: ['diesel'] },
|
|
41
|
+
{ tech: 'serde', importPatterns: ['serde'] },
|
|
42
|
+
// Java
|
|
43
|
+
{ tech: 'spring', importPatterns: ['org.springframework'] },
|
|
44
|
+
{ tech: 'quarkus', importPatterns: ['io.quarkus'] },
|
|
45
|
+
{ tech: 'micronaut', importPatterns: ['io.micronaut'] },
|
|
46
|
+
{ tech: 'hibernate', importPatterns: ['org.hibernate'] },
|
|
47
|
+
{ tech: 'junit', importPatterns: ['org.junit'] },
|
|
48
|
+
];
|
|
49
|
+
function detectStackFromGraph(store) {
|
|
50
|
+
const stats = store.stats();
|
|
51
|
+
if (stats.nodes === 0)
|
|
52
|
+
return [];
|
|
53
|
+
// Gather all unique import sources from the index
|
|
54
|
+
const importSources = store.getAllImportSources();
|
|
55
|
+
const detected = new Set();
|
|
56
|
+
for (const sig of SIGNATURES) {
|
|
57
|
+
const found = sig.importPatterns.some(pattern => importSources.some(src => src.includes(pattern)));
|
|
58
|
+
if (found)
|
|
59
|
+
detected.add(sig.tech);
|
|
60
|
+
}
|
|
61
|
+
return [...detected];
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=stack-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stack-detector.js","sourceRoot":"","sources":["../../src/indexer/stack-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/indexer/watcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,qBAAa,WAAW;IACpB,OAAO,CAAC,OAAO,CAAkD;IACjE,OAAO,CAAC,MAAM,CAAoD;IAElE,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IA+B9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAKxB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.FileWatcher = void 0;
|
|
40
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const index_1 = require("./languages/index");
|
|
43
|
+
const DEBOUNCE_MS = 500;
|
|
44
|
+
class FileWatcher {
|
|
45
|
+
watcher = null;
|
|
46
|
+
timers = new Map();
|
|
47
|
+
start(dir, indexer) {
|
|
48
|
+
const extensions = (0, index_1.registeredExtensions)();
|
|
49
|
+
const glob = `**/*{${extensions.join(',')}}`;
|
|
50
|
+
this.watcher = chokidar_1.default.watch(path.join(dir, glob), {
|
|
51
|
+
ignored: [
|
|
52
|
+
/node_modules/,
|
|
53
|
+
/[/\\]\./,
|
|
54
|
+
/dist[/\\]/,
|
|
55
|
+
/build[/\\]/,
|
|
56
|
+
/coverage[/\\]/,
|
|
57
|
+
],
|
|
58
|
+
persistent: true,
|
|
59
|
+
ignoreInitial: true,
|
|
60
|
+
});
|
|
61
|
+
const schedule = (filePath, action) => {
|
|
62
|
+
const existing = this.timers.get(filePath);
|
|
63
|
+
if (existing)
|
|
64
|
+
clearTimeout(existing);
|
|
65
|
+
this.timers.set(filePath, setTimeout(() => {
|
|
66
|
+
this.timers.delete(filePath);
|
|
67
|
+
action();
|
|
68
|
+
}, DEBOUNCE_MS));
|
|
69
|
+
};
|
|
70
|
+
this.watcher
|
|
71
|
+
.on('add', f => schedule(f, () => indexer.indexFile(f)))
|
|
72
|
+
.on('change', f => schedule(f, () => indexer.indexFile(f)))
|
|
73
|
+
.on('unlink', f => schedule(f, () => indexer.removeFile(f)));
|
|
74
|
+
}
|
|
75
|
+
stop() {
|
|
76
|
+
for (const t of this.timers.values())
|
|
77
|
+
clearTimeout(t);
|
|
78
|
+
this.timers.clear();
|
|
79
|
+
return this.watcher?.close() ?? Promise.resolve();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.FileWatcher = FileWatcher;
|
|
83
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/indexer/watcher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wDAAgC;AAChC,2CAA6B;AAC7B,6CAAyD;AAGzD,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAa,WAAW;IACZ,OAAO,GAA6C,IAAI,CAAC;IACzD,MAAM,GAAG,IAAI,GAAG,EAAyC,CAAC;IAElE,KAAK,CAAC,GAAW,EAAE,OAAoB;QACnC,MAAM,UAAU,GAAG,IAAA,4BAAoB,GAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,QAAQ,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAE7C,IAAI,CAAC,OAAO,GAAG,kBAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;YAChD,OAAO,EAAE;gBACL,cAAc;gBACd,SAAS;gBACT,WAAW;gBACX,YAAY;gBACZ,eAAe;aAClB;YACD,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;SACtB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAE,MAAkB,EAAE,EAAE;YACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3C,IAAI,QAAQ;gBAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,EAAE;gBACtC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC7B,MAAM,EAAE,CAAC;YACb,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;QACrB,CAAC,CAAC;QAEF,IAAI,CAAC,OAAO;aACP,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aACvD,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aAC1D,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,IAAI;QACA,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACtD,CAAC;CACJ;AAxCD,kCAwCC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
38
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
39
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
40
|
+
const node_http_1 = require("node:http");
|
|
41
|
+
const node_crypto_1 = require("node:crypto");
|
|
42
|
+
const zod_1 = require("zod");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const agent_core_1 = require("@backendkit-labs/agent-core");
|
|
45
|
+
const search_js_1 = require("./tools/skills/search.js");
|
|
46
|
+
const install_js_1 = require("./tools/skills/install.js");
|
|
47
|
+
const list_js_1 = require("./tools/skills/list.js");
|
|
48
|
+
const search_js_2 = require("./tools/code/search.js");
|
|
49
|
+
const context_js_1 = require("./tools/code/context.js");
|
|
50
|
+
const graph_store_js_1 = require("./indexer/graph-store.js");
|
|
51
|
+
const indexer_js_1 = require("./indexer/indexer.js");
|
|
52
|
+
const watcher_js_1 = require("./indexer/watcher.js");
|
|
53
|
+
const stack_detector_js_1 = require("./indexer/stack-detector.js");
|
|
54
|
+
const APP_NAME = process.env.BK_APP_NAME ?? 'deepseek-code';
|
|
55
|
+
const CWD = process.env.BK_CWD ?? process.cwd();
|
|
56
|
+
// --- Code index setup ---
|
|
57
|
+
const dbPath = path.join((0, agent_core_1.getFrameworkDir)(APP_NAME), 'code-index', Buffer.from(CWD).toString('base64url').slice(0, 32) + '.db');
|
|
58
|
+
const store = new graph_store_js_1.GraphStore(dbPath);
|
|
59
|
+
const indexer = new indexer_js_1.CodeIndexer(store, CWD);
|
|
60
|
+
const watcher = new watcher_js_1.FileWatcher();
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Server factory — creates a fresh McpServer with all tools registered.
|
|
63
|
+
// Called once for stdio mode; called per-session in HTTP mode.
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
function buildServer() {
|
|
66
|
+
const srv = new mcp_js_1.McpServer({
|
|
67
|
+
name: '@backendkit-labs/mcp-server',
|
|
68
|
+
version: '0.2.0',
|
|
69
|
+
});
|
|
70
|
+
registerTools(srv);
|
|
71
|
+
return srv;
|
|
72
|
+
}
|
|
73
|
+
function registerTools(srv) {
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// stack_detect
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// @ts-expect-error: TS2589 — MCP SDK + zod generic depth limit, safe at runtime
|
|
78
|
+
srv.tool('stack_detect', 'Detect the technology stack of the current project using the code index (languages, frameworks, libraries).', {
|
|
79
|
+
cwd: zod_1.z.string().optional().describe('Project directory (defaults to server cwd)'),
|
|
80
|
+
}, async ({ cwd: _cwd }) => {
|
|
81
|
+
const graphTech = (0, stack_detector_js_1.detectStackFromGraph)(store);
|
|
82
|
+
const { SkillActivator } = await Promise.resolve().then(() => __importStar(require('@backendkit-labs/agent-core')));
|
|
83
|
+
const activator = new SkillActivator();
|
|
84
|
+
const fileTech = await activator.detectStack(CWD);
|
|
85
|
+
const all = [...new Set([...fileTech, ...graphTech])].sort();
|
|
86
|
+
return {
|
|
87
|
+
content: [{
|
|
88
|
+
type: 'text',
|
|
89
|
+
text: all.length
|
|
90
|
+
? `Detected stack: ${all.join(', ')}`
|
|
91
|
+
: 'No stack detected yet. Run code_index first.',
|
|
92
|
+
}],
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// skills_search
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
srv.tool('skills_search', 'Search available skills by query. Returns matching skills and whether they are active for the current project.', {
|
|
99
|
+
query: zod_1.z.string().describe('Search term — skill name, trigger keyword, or description'),
|
|
100
|
+
cwd: zod_1.z.string().optional().describe('Project directory to detect stack (defaults to server cwd)'),
|
|
101
|
+
}, async ({ query, cwd }) => {
|
|
102
|
+
// Merge file-based + graph-based stack detection
|
|
103
|
+
const { SkillActivator } = await Promise.resolve().then(() => __importStar(require('@backendkit-labs/agent-core')));
|
|
104
|
+
const activator = new SkillActivator();
|
|
105
|
+
const fileTech = await activator.detectStack(cwd ?? CWD);
|
|
106
|
+
const graphTech = (0, stack_detector_js_1.detectStackFromGraph)(store);
|
|
107
|
+
const enrichedStack = [...new Set([...fileTech, ...graphTech])];
|
|
108
|
+
const results = await (0, search_js_1.skillsSearch)(query, cwd ?? CWD, APP_NAME);
|
|
109
|
+
if (results.length === 0) {
|
|
110
|
+
return { content: [{ type: 'text', text: `No skills found matching "${query}".` }] };
|
|
111
|
+
}
|
|
112
|
+
const lines = results.map(s => {
|
|
113
|
+
const tags = [s.scope, ...(s.language ?? []), s.active ? 'ACTIVE' : ''].filter(Boolean);
|
|
114
|
+
const stackMatch = s.language?.some(l => enrichedStack.includes(l));
|
|
115
|
+
const marker = stackMatch ? ' ✓' : '';
|
|
116
|
+
return `- **${s.name}**${marker} [${tags.join(', ')}]\n ${s.description}`;
|
|
117
|
+
});
|
|
118
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
119
|
+
});
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// skills_install
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
srv.tool('skills_install', 'Install a skill pack from a GitHub repository or local path.', {
|
|
124
|
+
source: zod_1.z.string().describe('GitHub URL (https://github.com/org/repo) or local path'),
|
|
125
|
+
skill: zod_1.z.string().optional().describe('Install only this specific skill by name'),
|
|
126
|
+
pack: zod_1.z.string().optional().describe('Override the derived pack name'),
|
|
127
|
+
}, async ({ source, skill, pack }) => {
|
|
128
|
+
const result = await (0, install_js_1.skillsInstall)(source, APP_NAME, { skill, pack });
|
|
129
|
+
if (!result.ok) {
|
|
130
|
+
return {
|
|
131
|
+
content: [{ type: 'text', text: `Failed to install from "${source}":\n${result.error}` }],
|
|
132
|
+
isError: true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: `Installed pack "${result.pack}" with ${result.skillsInstalled} skill(s).` }],
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// skills_list
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
srv.tool('skills_list', 'List all installed skill packs including builtin packs.', {}, async () => {
|
|
143
|
+
const packs = await (0, list_js_1.skillsList)(APP_NAME);
|
|
144
|
+
const lines = packs.map(p => {
|
|
145
|
+
const tag = p.builtin ? 'builtin' : `installed ${p.installedAt.slice(0, 10)}`;
|
|
146
|
+
return `**${p.pack}** (${tag})\n Skills: ${p.skills.join(', ')}`;
|
|
147
|
+
});
|
|
148
|
+
return { content: [{ type: 'text', text: lines.join('\n\n') }] };
|
|
149
|
+
});
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// code_search
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// @ts-expect-error: TS2589 — MCP SDK + zod generic depth limit, safe at runtime
|
|
154
|
+
srv.tool('code_search', 'Search the codebase for symbols (functions, classes, interfaces, types) by name or keyword.', {
|
|
155
|
+
query: zod_1.z.string().describe('Symbol name or keyword to search for'),
|
|
156
|
+
limit: zod_1.z.number().optional().describe('Max results to return (default 20)'),
|
|
157
|
+
}, ({ query, limit }) => {
|
|
158
|
+
const results = (0, search_js_2.codeSearch)(query, store, limit ?? 20);
|
|
159
|
+
if (results.length === 0) {
|
|
160
|
+
return { content: [{ type: 'text', text: `No symbols found matching "${query}".` }] };
|
|
161
|
+
}
|
|
162
|
+
const lines = results.map(r => `**${r.name}** (${r.kind}) — ${r.filePath}:${r.startLine}\n ${r.signature}`);
|
|
163
|
+
return { content: [{ type: 'text', text: lines.join('\n\n') }] };
|
|
164
|
+
});
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// code_context
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
srv.tool('code_context', 'Get relevant code context for a task — finds the symbols most related to the task and returns their code, callers, and callees.', {
|
|
169
|
+
task: zod_1.z.string().describe('Task or feature description to find context for'),
|
|
170
|
+
max_symbols: zod_1.z.number().optional().describe('Max symbols to return (default 10)'),
|
|
171
|
+
}, async ({ task, max_symbols }) => {
|
|
172
|
+
const ctx = await (0, context_js_1.codeContext)(task, store, max_symbols ?? 10);
|
|
173
|
+
if (ctx.symbols.length === 0) {
|
|
174
|
+
return { content: [{ type: 'text', text: `No relevant code found for: "${task}"` }] };
|
|
175
|
+
}
|
|
176
|
+
const parts = ctx.symbols.map(s => {
|
|
177
|
+
const location = `${s.filePath}:${s.startLine}-${s.endLine}`;
|
|
178
|
+
const relations = [
|
|
179
|
+
s.calledBy.length ? `calledBy: ${s.calledBy.slice(0, 5).join(', ')}` : '',
|
|
180
|
+
s.calls.length ? `calls: ${s.calls.slice(0, 5).join(', ')}` : '',
|
|
181
|
+
].filter(Boolean).join(' | ');
|
|
182
|
+
return [
|
|
183
|
+
`### ${s.name} (${s.kind}) — ${location}`,
|
|
184
|
+
relations ? `> ${relations}` : '',
|
|
185
|
+
'```' + s.language,
|
|
186
|
+
s.snippet,
|
|
187
|
+
'```',
|
|
188
|
+
].filter(Boolean).join('\n');
|
|
189
|
+
});
|
|
190
|
+
return { content: [{ type: 'text', text: parts.join('\n\n') }] };
|
|
191
|
+
});
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// code_index (trigger manual re-index)
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
srv.tool('code_index', 'Trigger a full re-index of the project codebase. Run this after installing new files or if search results seem stale.', {
|
|
196
|
+
cwd: zod_1.z.string().optional().describe('Directory to index (defaults to server cwd)'),
|
|
197
|
+
}, async ({ cwd }) => {
|
|
198
|
+
const dir = cwd ?? CWD;
|
|
199
|
+
const result = await indexer.indexDirectory(dir);
|
|
200
|
+
const stats = store.stats();
|
|
201
|
+
return {
|
|
202
|
+
content: [{
|
|
203
|
+
type: 'text',
|
|
204
|
+
text: `Indexed ${result.files} files, ${result.symbols} new symbols.\nTotal: ${stats.nodes} nodes, ${stats.edges} edges across ${stats.files} files.`,
|
|
205
|
+
}],
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
} // end registerTools
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Start
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
// ── CLI args ─────────────────────────────────────────────────────────────────
|
|
213
|
+
const args = process.argv.slice(2);
|
|
214
|
+
const HTTP_MODE = args.includes('--http');
|
|
215
|
+
const portEq = args.find(a => a.startsWith('--port='))?.split('=')[1];
|
|
216
|
+
const portSpace = args[args.indexOf('--port') + 1];
|
|
217
|
+
const HTTP_PORT = parseInt(portEq ?? portSpace ?? '3001', 10);
|
|
218
|
+
const MCP_PATH = '/mcp';
|
|
219
|
+
async function main() {
|
|
220
|
+
// Index on startup (non-blocking)
|
|
221
|
+
indexer.indexDirectory(CWD).catch(() => undefined);
|
|
222
|
+
watcher.start(CWD, indexer);
|
|
223
|
+
process.on('SIGINT', async () => {
|
|
224
|
+
await watcher.stop();
|
|
225
|
+
store.close();
|
|
226
|
+
process.exit(0);
|
|
227
|
+
});
|
|
228
|
+
if (HTTP_MODE) {
|
|
229
|
+
await startHttp();
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
await startStdio();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function startStdio() {
|
|
236
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
237
|
+
await buildServer().connect(transport);
|
|
238
|
+
}
|
|
239
|
+
async function startHttp() {
|
|
240
|
+
// Stateful mode — each client gets a session ID; the McpServer is shared but
|
|
241
|
+
// each transport instance tracks its own protocol state independently.
|
|
242
|
+
const sessions = new Map();
|
|
243
|
+
async function parseBody(req) {
|
|
244
|
+
const chunks = [];
|
|
245
|
+
for await (const chunk of req)
|
|
246
|
+
chunks.push(chunk);
|
|
247
|
+
const raw = Buffer.concat(chunks).toString('utf-8');
|
|
248
|
+
if (!raw)
|
|
249
|
+
return undefined;
|
|
250
|
+
return JSON.parse(raw);
|
|
251
|
+
}
|
|
252
|
+
const httpServer = (0, node_http_1.createServer)(async (req, res) => {
|
|
253
|
+
if (req.url !== MCP_PATH) {
|
|
254
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
255
|
+
res.end(JSON.stringify({ error: `Use POST/GET ${MCP_PATH}` }));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
260
|
+
// Existing session
|
|
261
|
+
if (sessionId && sessions.has(sessionId)) {
|
|
262
|
+
const body = req.method === 'POST' ? await parseBody(req) : undefined;
|
|
263
|
+
await sessions.get(sessionId).handleRequest(req, res, body);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// New session — only allowed on POST (initialize request)
|
|
267
|
+
if (req.method !== 'POST') {
|
|
268
|
+
res.writeHead(400);
|
|
269
|
+
res.end('Session ID required for GET');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const body = await parseBody(req);
|
|
273
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
274
|
+
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
|
275
|
+
});
|
|
276
|
+
// Connect a fresh McpServer per session so each session has
|
|
277
|
+
// isolated protocol state (initialized, tool list, etc.)
|
|
278
|
+
const sessionServer = buildServer();
|
|
279
|
+
await sessionServer.connect(transport);
|
|
280
|
+
// handleRequest processes the initialize message and sets transport.sessionId
|
|
281
|
+
await transport.handleRequest(req, res, body);
|
|
282
|
+
// Store AFTER handleRequest so the session ID is available
|
|
283
|
+
if (transport.sessionId) {
|
|
284
|
+
sessions.set(transport.sessionId, transport);
|
|
285
|
+
transport.onclose = () => sessions.delete(transport.sessionId);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
if (!res.headersSent) {
|
|
290
|
+
res.writeHead(500);
|
|
291
|
+
res.end(String(err));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
await new Promise((resolve, reject) => {
|
|
296
|
+
httpServer.once('error', reject);
|
|
297
|
+
httpServer.listen(HTTP_PORT, '127.0.0.1', () => {
|
|
298
|
+
process.stderr.write(`[bk-mcp] HTTP server listening on http://127.0.0.1:${HTTP_PORT}${MCP_PATH}\n` +
|
|
299
|
+
`[bk-mcp] cwd=${CWD} app=${APP_NAME}\n`);
|
|
300
|
+
resolve();
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
main().catch(err => {
|
|
305
|
+
process.stderr.write(`[bk-mcp] Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=server.js.map
|