nodebench-mcp 1.0.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/README.md +237 -0
- package/dist/__tests__/tools.test.d.ts +1 -0
- package/dist/__tests__/tools.test.js +402 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/db.d.ts +4 -0
- package/dist/db.js +198 -0
- package/dist/db.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +237 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/documentTools.d.ts +5 -0
- package/dist/tools/documentTools.js +524 -0
- package/dist/tools/documentTools.js.map +1 -0
- package/dist/tools/documentationTools.d.ts +12 -0
- package/dist/tools/documentationTools.js +647 -0
- package/dist/tools/documentationTools.js.map +1 -0
- package/dist/tools/evalTools.d.ts +6 -0
- package/dist/tools/evalTools.js +335 -0
- package/dist/tools/evalTools.js.map +1 -0
- package/dist/tools/financialTools.d.ts +10 -0
- package/dist/tools/financialTools.js +403 -0
- package/dist/tools/financialTools.js.map +1 -0
- package/dist/tools/flywheelTools.d.ts +6 -0
- package/dist/tools/flywheelTools.js +366 -0
- package/dist/tools/flywheelTools.js.map +1 -0
- package/dist/tools/githubTools.d.ts +12 -0
- package/dist/tools/githubTools.js +432 -0
- package/dist/tools/githubTools.js.map +1 -0
- package/dist/tools/learningTools.d.ts +6 -0
- package/dist/tools/learningTools.js +199 -0
- package/dist/tools/learningTools.js.map +1 -0
- package/dist/tools/memoryTools.d.ts +5 -0
- package/dist/tools/memoryTools.js +137 -0
- package/dist/tools/memoryTools.js.map +1 -0
- package/dist/tools/metaTools.d.ts +7 -0
- package/dist/tools/metaTools.js +837 -0
- package/dist/tools/metaTools.js.map +1 -0
- package/dist/tools/planningTools.d.ts +5 -0
- package/dist/tools/planningTools.js +147 -0
- package/dist/tools/planningTools.js.map +1 -0
- package/dist/tools/qualityGateTools.d.ts +6 -0
- package/dist/tools/qualityGateTools.js +347 -0
- package/dist/tools/qualityGateTools.js.map +1 -0
- package/dist/tools/reconTools.d.ts +8 -0
- package/dist/tools/reconTools.js +729 -0
- package/dist/tools/reconTools.js.map +1 -0
- package/dist/tools/searchTools.d.ts +5 -0
- package/dist/tools/searchTools.js +145 -0
- package/dist/tools/searchTools.js.map +1 -0
- package/dist/tools/uiCaptureTools.d.ts +8 -0
- package/dist/tools/uiCaptureTools.js +339 -0
- package/dist/tools/uiCaptureTools.js.map +1 -0
- package/dist/tools/verificationTools.d.ts +6 -0
- package/dist/tools/verificationTools.js +472 -0
- package/dist/tools/verificationTools.js.map +1 -0
- package/dist/tools/visionTools.d.ts +12 -0
- package/dist/tools/visionTools.js +553 -0
- package/dist/tools/visionTools.js.map +1 -0
- package/dist/tools/webTools.d.ts +12 -0
- package/dist/tools/webTools.js +443 -0
- package/dist/tools/webTools.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub tools — Repository search and analysis.
|
|
3
|
+
* Enables agents to discover and analyze GitHub repositories for learning patterns,
|
|
4
|
+
* finding prior art, and understanding tech stacks.
|
|
5
|
+
*
|
|
6
|
+
* - search_github: Search repositories by topic, language, stars
|
|
7
|
+
* - analyze_repo: Analyze a repo's structure, tech stack, and patterns
|
|
8
|
+
*
|
|
9
|
+
* Uses GitHub REST API. GITHUB_TOKEN optional but recommended for higher rate limits.
|
|
10
|
+
*/
|
|
11
|
+
// ─── GitHub API helpers ───────────────────────────────────────────────────────
|
|
12
|
+
function getHeaders() {
|
|
13
|
+
const headers = {
|
|
14
|
+
Accept: "application/vnd.github+json",
|
|
15
|
+
"User-Agent": "NodeBench-MCP/1.0",
|
|
16
|
+
};
|
|
17
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
18
|
+
if (token) {
|
|
19
|
+
headers.Authorization = `Bearer ${token}`;
|
|
20
|
+
}
|
|
21
|
+
return headers;
|
|
22
|
+
}
|
|
23
|
+
async function githubFetch(endpoint) {
|
|
24
|
+
const url = endpoint.startsWith("http")
|
|
25
|
+
? endpoint
|
|
26
|
+
: `https://api.github.com${endpoint}`;
|
|
27
|
+
const response = await fetch(url, { headers: getHeaders() });
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
const error = await response.text();
|
|
30
|
+
throw new Error(`GitHub API error ${response.status}: ${error}`);
|
|
31
|
+
}
|
|
32
|
+
return response.json();
|
|
33
|
+
}
|
|
34
|
+
// ─── Repo URL parsing ─────────────────────────────────────────────────────────
|
|
35
|
+
function parseRepoUrl(url) {
|
|
36
|
+
// Handle: https://github.com/owner/repo, github.com/owner/repo, owner/repo
|
|
37
|
+
const patterns = [
|
|
38
|
+
/github\.com\/([^/]+)\/([^/]+)/,
|
|
39
|
+
/^([^/]+)\/([^/]+)$/,
|
|
40
|
+
];
|
|
41
|
+
for (const pattern of patterns) {
|
|
42
|
+
const match = url.match(pattern);
|
|
43
|
+
if (match) {
|
|
44
|
+
return {
|
|
45
|
+
owner: match[1],
|
|
46
|
+
repo: match[2].replace(/\.git$/, ""),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function detectDependencies(files) {
|
|
53
|
+
const deps = {
|
|
54
|
+
dependencies: [],
|
|
55
|
+
devDependencies: [],
|
|
56
|
+
frameworks: [],
|
|
57
|
+
};
|
|
58
|
+
// Check package.json
|
|
59
|
+
const packageJson = files.get("package.json");
|
|
60
|
+
if (packageJson) {
|
|
61
|
+
try {
|
|
62
|
+
const pkg = JSON.parse(packageJson);
|
|
63
|
+
deps.dependencies = Object.keys(pkg.dependencies ?? {});
|
|
64
|
+
deps.devDependencies = Object.keys(pkg.devDependencies ?? {});
|
|
65
|
+
// Detect frameworks
|
|
66
|
+
const allDeps = [...deps.dependencies, ...deps.devDependencies];
|
|
67
|
+
if (allDeps.includes("next"))
|
|
68
|
+
deps.frameworks.push("Next.js");
|
|
69
|
+
if (allDeps.includes("react"))
|
|
70
|
+
deps.frameworks.push("React");
|
|
71
|
+
if (allDeps.includes("vue"))
|
|
72
|
+
deps.frameworks.push("Vue");
|
|
73
|
+
if (allDeps.includes("svelte"))
|
|
74
|
+
deps.frameworks.push("Svelte");
|
|
75
|
+
if (allDeps.includes("express"))
|
|
76
|
+
deps.frameworks.push("Express");
|
|
77
|
+
if (allDeps.includes("fastify"))
|
|
78
|
+
deps.frameworks.push("Fastify");
|
|
79
|
+
if (allDeps.includes("hono"))
|
|
80
|
+
deps.frameworks.push("Hono");
|
|
81
|
+
if (allDeps.includes("convex"))
|
|
82
|
+
deps.frameworks.push("Convex");
|
|
83
|
+
if (allDeps.includes("prisma") || allDeps.includes("@prisma/client"))
|
|
84
|
+
deps.frameworks.push("Prisma");
|
|
85
|
+
if (allDeps.includes("drizzle-orm"))
|
|
86
|
+
deps.frameworks.push("Drizzle");
|
|
87
|
+
if (allDeps.includes("@tanstack/react-query"))
|
|
88
|
+
deps.frameworks.push("TanStack Query");
|
|
89
|
+
if (allDeps.includes("tailwindcss"))
|
|
90
|
+
deps.frameworks.push("Tailwind CSS");
|
|
91
|
+
if (allDeps.includes("@modelcontextprotocol/sdk"))
|
|
92
|
+
deps.frameworks.push("MCP SDK");
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Invalid JSON
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Check requirements.txt
|
|
99
|
+
const requirements = files.get("requirements.txt");
|
|
100
|
+
if (requirements) {
|
|
101
|
+
const pythonDeps = requirements
|
|
102
|
+
.split("\n")
|
|
103
|
+
.map((line) => line.split("==")[0].split(">=")[0].trim())
|
|
104
|
+
.filter(Boolean);
|
|
105
|
+
deps.dependencies.push(...pythonDeps);
|
|
106
|
+
if (pythonDeps.includes("fastapi"))
|
|
107
|
+
deps.frameworks.push("FastAPI");
|
|
108
|
+
if (pythonDeps.includes("django"))
|
|
109
|
+
deps.frameworks.push("Django");
|
|
110
|
+
if (pythonDeps.includes("flask"))
|
|
111
|
+
deps.frameworks.push("Flask");
|
|
112
|
+
if (pythonDeps.includes("langchain"))
|
|
113
|
+
deps.frameworks.push("LangChain");
|
|
114
|
+
if (pythonDeps.includes("openai"))
|
|
115
|
+
deps.frameworks.push("OpenAI Python");
|
|
116
|
+
}
|
|
117
|
+
// Check Cargo.toml
|
|
118
|
+
const cargoToml = files.get("Cargo.toml");
|
|
119
|
+
if (cargoToml) {
|
|
120
|
+
const depMatch = cargoToml.match(/\[dependencies\]([\s\S]*?)(\[|$)/);
|
|
121
|
+
if (depMatch) {
|
|
122
|
+
const rustDeps = depMatch[1]
|
|
123
|
+
.split("\n")
|
|
124
|
+
.map((line) => line.split("=")[0].trim())
|
|
125
|
+
.filter(Boolean);
|
|
126
|
+
deps.dependencies.push(...rustDeps);
|
|
127
|
+
if (rustDeps.includes("axum"))
|
|
128
|
+
deps.frameworks.push("Axum");
|
|
129
|
+
if (rustDeps.includes("actix-web"))
|
|
130
|
+
deps.frameworks.push("Actix");
|
|
131
|
+
if (rustDeps.includes("tokio"))
|
|
132
|
+
deps.frameworks.push("Tokio");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return deps;
|
|
136
|
+
}
|
|
137
|
+
function detectPatterns(tree) {
|
|
138
|
+
const patterns = {
|
|
139
|
+
hasTests: false,
|
|
140
|
+
hasCi: false,
|
|
141
|
+
hasReadme: false,
|
|
142
|
+
hasDocs: false,
|
|
143
|
+
hasTypes: false,
|
|
144
|
+
hasDocker: false,
|
|
145
|
+
hasLicense: false,
|
|
146
|
+
testFramework: null,
|
|
147
|
+
ciPlatform: null,
|
|
148
|
+
};
|
|
149
|
+
for (const path of tree) {
|
|
150
|
+
const lower = path.toLowerCase();
|
|
151
|
+
// Tests
|
|
152
|
+
if (lower.includes("test") ||
|
|
153
|
+
lower.includes("__tests__") ||
|
|
154
|
+
lower.includes("spec")) {
|
|
155
|
+
patterns.hasTests = true;
|
|
156
|
+
if (lower.includes("vitest"))
|
|
157
|
+
patterns.testFramework = "Vitest";
|
|
158
|
+
else if (lower.includes("jest"))
|
|
159
|
+
patterns.testFramework = "Jest";
|
|
160
|
+
else if (lower.includes("pytest"))
|
|
161
|
+
patterns.testFramework = "pytest";
|
|
162
|
+
else if (lower.includes("mocha"))
|
|
163
|
+
patterns.testFramework = "Mocha";
|
|
164
|
+
}
|
|
165
|
+
// CI/CD
|
|
166
|
+
if (lower.includes(".github/workflows")) {
|
|
167
|
+
patterns.hasCi = true;
|
|
168
|
+
patterns.ciPlatform = "GitHub Actions";
|
|
169
|
+
}
|
|
170
|
+
else if (lower.includes(".circleci")) {
|
|
171
|
+
patterns.hasCi = true;
|
|
172
|
+
patterns.ciPlatform = "CircleCI";
|
|
173
|
+
}
|
|
174
|
+
else if (lower.includes("gitlab-ci")) {
|
|
175
|
+
patterns.hasCi = true;
|
|
176
|
+
patterns.ciPlatform = "GitLab CI";
|
|
177
|
+
}
|
|
178
|
+
// Docs
|
|
179
|
+
if (lower === "readme.md" || lower === "readme")
|
|
180
|
+
patterns.hasReadme = true;
|
|
181
|
+
if (lower.includes("docs/") || lower.includes("documentation/"))
|
|
182
|
+
patterns.hasDocs = true;
|
|
183
|
+
if (lower === "license" || lower === "license.md")
|
|
184
|
+
patterns.hasLicense = true;
|
|
185
|
+
// Types
|
|
186
|
+
if (lower.endsWith(".d.ts") || lower === "tsconfig.json")
|
|
187
|
+
patterns.hasTypes = true;
|
|
188
|
+
// Docker
|
|
189
|
+
if (lower.includes("dockerfile") || lower.includes("docker-compose"))
|
|
190
|
+
patterns.hasDocker = true;
|
|
191
|
+
}
|
|
192
|
+
return patterns;
|
|
193
|
+
}
|
|
194
|
+
// ─── Tools ────────────────────────────────────────────────────────────────────
|
|
195
|
+
export const githubTools = [
|
|
196
|
+
{
|
|
197
|
+
name: "search_github",
|
|
198
|
+
description: "Search GitHub repositories by query, topic, language, and star count. Useful for discovering libraries, frameworks, prior art, and learning from existing implementations. Returns repo metadata including stars, forks, description, and topics. GITHUB_TOKEN optional but recommended for higher rate limits.",
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: "object",
|
|
201
|
+
properties: {
|
|
202
|
+
query: {
|
|
203
|
+
type: "string",
|
|
204
|
+
description: "Search query (e.g., 'mcp server', 'ai agents', 'typescript sdk')",
|
|
205
|
+
},
|
|
206
|
+
language: {
|
|
207
|
+
type: "string",
|
|
208
|
+
description: "Filter by programming language (e.g., 'typescript', 'python', 'rust')",
|
|
209
|
+
},
|
|
210
|
+
topic: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "Filter by GitHub topic (e.g., 'mcp', 'ai-agents', 'llm')",
|
|
213
|
+
},
|
|
214
|
+
minStars: {
|
|
215
|
+
type: "number",
|
|
216
|
+
description: "Minimum star count (default: 10)",
|
|
217
|
+
},
|
|
218
|
+
sort: {
|
|
219
|
+
type: "string",
|
|
220
|
+
enum: ["stars", "updated", "relevance"],
|
|
221
|
+
description: "Sort order: 'stars' (most popular), 'updated' (recently active), 'relevance' (best match). Default: 'stars'.",
|
|
222
|
+
},
|
|
223
|
+
maxResults: {
|
|
224
|
+
type: "number",
|
|
225
|
+
description: "Maximum results to return (default: 10, max: 30)",
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ["query"],
|
|
229
|
+
},
|
|
230
|
+
handler: async (args) => {
|
|
231
|
+
const query = args.query;
|
|
232
|
+
const language = args.language;
|
|
233
|
+
const topic = args.topic;
|
|
234
|
+
const minStars = args.minStars ?? 10;
|
|
235
|
+
const sort = args.sort ?? "stars";
|
|
236
|
+
const maxResults = Math.min(args.maxResults ?? 10, 30);
|
|
237
|
+
// Build GitHub search query
|
|
238
|
+
const queryParts = [query];
|
|
239
|
+
if (language)
|
|
240
|
+
queryParts.push(`language:${language}`);
|
|
241
|
+
if (topic)
|
|
242
|
+
queryParts.push(`topic:${topic}`);
|
|
243
|
+
if (minStars > 0)
|
|
244
|
+
queryParts.push(`stars:>=${minStars}`);
|
|
245
|
+
const searchQuery = encodeURIComponent(queryParts.join(" "));
|
|
246
|
+
const sortParam = sort === "relevance" ? "" : `&sort=${sort}`;
|
|
247
|
+
try {
|
|
248
|
+
const data = await githubFetch(`/search/repositories?q=${searchQuery}${sortParam}&per_page=${maxResults}`);
|
|
249
|
+
const repos = (data.items ?? []).map((item) => ({
|
|
250
|
+
name: item.name,
|
|
251
|
+
fullName: item.full_name,
|
|
252
|
+
description: item.description ?? "",
|
|
253
|
+
url: item.html_url,
|
|
254
|
+
stars: item.stargazers_count,
|
|
255
|
+
forks: item.forks_count,
|
|
256
|
+
language: item.language,
|
|
257
|
+
topics: item.topics ?? [],
|
|
258
|
+
updatedAt: item.updated_at,
|
|
259
|
+
license: item.license?.spdx_id ?? null,
|
|
260
|
+
isArchived: item.archived,
|
|
261
|
+
openIssues: item.open_issues_count,
|
|
262
|
+
}));
|
|
263
|
+
return {
|
|
264
|
+
query,
|
|
265
|
+
filters: { language, topic, minStars, sort },
|
|
266
|
+
repos,
|
|
267
|
+
totalCount: data.total_count,
|
|
268
|
+
resultCount: repos.length,
|
|
269
|
+
hasGitHubToken: !!(process.env.GITHUB_TOKEN || process.env.GH_TOKEN),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
return {
|
|
274
|
+
error: true,
|
|
275
|
+
query,
|
|
276
|
+
message: `GitHub search failed: ${err.message}`,
|
|
277
|
+
suggestion: "Check network connectivity. Set GITHUB_TOKEN for higher rate limits (60/hour without, 5000/hour with).",
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "analyze_repo",
|
|
284
|
+
description: "Analyze a GitHub repository's structure, tech stack, dependencies, and development patterns. Fetches repo metadata, file tree, and key configuration files (package.json, requirements.txt, etc.) to understand the project. No cloning required — uses GitHub API. Useful for learning from implementations, evaluating libraries, and understanding architectures.",
|
|
285
|
+
inputSchema: {
|
|
286
|
+
type: "object",
|
|
287
|
+
properties: {
|
|
288
|
+
repoUrl: {
|
|
289
|
+
type: "string",
|
|
290
|
+
description: "GitHub repository URL or owner/repo (e.g., 'https://github.com/anthropics/claude-code', 'anthropics/claude-code')",
|
|
291
|
+
},
|
|
292
|
+
depth: {
|
|
293
|
+
type: "string",
|
|
294
|
+
enum: ["shallow", "standard", "deep"],
|
|
295
|
+
description: "Analysis depth: 'shallow' (metadata only), 'standard' (+ file tree + key files), 'deep' (+ more files). Default: 'standard'.",
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
required: ["repoUrl"],
|
|
299
|
+
},
|
|
300
|
+
handler: async (args) => {
|
|
301
|
+
const repoUrl = args.repoUrl;
|
|
302
|
+
const depth = args.depth ?? "standard";
|
|
303
|
+
const parsed = parseRepoUrl(repoUrl);
|
|
304
|
+
if (!parsed) {
|
|
305
|
+
return {
|
|
306
|
+
error: true,
|
|
307
|
+
repoUrl,
|
|
308
|
+
message: "Invalid repository URL format",
|
|
309
|
+
suggestion: "Use format: 'owner/repo' or 'https://github.com/owner/repo'",
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
const { owner, repo } = parsed;
|
|
313
|
+
try {
|
|
314
|
+
// Fetch repo metadata
|
|
315
|
+
const repoData = await githubFetch(`/repos/${owner}/${repo}`);
|
|
316
|
+
const result = {
|
|
317
|
+
repo: {
|
|
318
|
+
name: repoData.name,
|
|
319
|
+
fullName: repoData.full_name,
|
|
320
|
+
description: repoData.description,
|
|
321
|
+
url: repoData.html_url,
|
|
322
|
+
stars: repoData.stargazers_count,
|
|
323
|
+
forks: repoData.forks_count,
|
|
324
|
+
language: repoData.language,
|
|
325
|
+
topics: repoData.topics ?? [],
|
|
326
|
+
createdAt: repoData.created_at,
|
|
327
|
+
updatedAt: repoData.updated_at,
|
|
328
|
+
pushedAt: repoData.pushed_at,
|
|
329
|
+
defaultBranch: repoData.default_branch,
|
|
330
|
+
license: repoData.license?.spdx_id ?? null,
|
|
331
|
+
isArchived: repoData.archived,
|
|
332
|
+
openIssues: repoData.open_issues_count,
|
|
333
|
+
},
|
|
334
|
+
depth,
|
|
335
|
+
analyzedAt: new Date().toISOString(),
|
|
336
|
+
};
|
|
337
|
+
if (depth === "shallow") {
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
// Fetch file tree
|
|
341
|
+
const defaultBranch = repoData.default_branch ?? "main";
|
|
342
|
+
const treeData = await githubFetch(`/repos/${owner}/${repo}/git/trees/${defaultBranch}?recursive=1`);
|
|
343
|
+
const tree = (treeData.tree ?? [])
|
|
344
|
+
.filter((item) => item.type === "blob")
|
|
345
|
+
.map((item) => item.path);
|
|
346
|
+
// Analyze structure
|
|
347
|
+
const directories = new Set();
|
|
348
|
+
for (const path of tree) {
|
|
349
|
+
const parts = path.split("/");
|
|
350
|
+
for (let i = 1; i < parts.length; i++) {
|
|
351
|
+
directories.add(parts.slice(0, i).join("/"));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const keyFiles = tree.filter((path) => {
|
|
355
|
+
const name = path.toLowerCase();
|
|
356
|
+
return (name === "readme.md" ||
|
|
357
|
+
name === "package.json" ||
|
|
358
|
+
name === "tsconfig.json" ||
|
|
359
|
+
name === "requirements.txt" ||
|
|
360
|
+
name === "cargo.toml" ||
|
|
361
|
+
name === "go.mod" ||
|
|
362
|
+
name === "dockerfile" ||
|
|
363
|
+
name.includes("docker-compose") ||
|
|
364
|
+
name === ".env.example" ||
|
|
365
|
+
name === "agents.md");
|
|
366
|
+
});
|
|
367
|
+
result.structure = {
|
|
368
|
+
directories: Array.from(directories).slice(0, 50),
|
|
369
|
+
keyFiles,
|
|
370
|
+
fileCount: tree.length,
|
|
371
|
+
truncated: treeData.truncated ?? false,
|
|
372
|
+
};
|
|
373
|
+
// Detect patterns
|
|
374
|
+
result.patterns = detectPatterns(tree);
|
|
375
|
+
// Fetch key files for dependency analysis
|
|
376
|
+
const filesToFetch = ["package.json", "requirements.txt", "Cargo.toml"];
|
|
377
|
+
const fetchedFiles = new Map();
|
|
378
|
+
for (const filename of filesToFetch) {
|
|
379
|
+
if (tree.includes(filename)) {
|
|
380
|
+
try {
|
|
381
|
+
const fileData = await githubFetch(`/repos/${owner}/${repo}/contents/${filename}`);
|
|
382
|
+
if (fileData.content) {
|
|
383
|
+
const content = Buffer.from(fileData.content, "base64").toString("utf-8");
|
|
384
|
+
fetchedFiles.set(filename, content);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch {
|
|
388
|
+
// File not accessible
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Detect tech stack
|
|
393
|
+
const deps = detectDependencies(fetchedFiles);
|
|
394
|
+
result.techStack = {
|
|
395
|
+
primaryLanguage: repoData.language,
|
|
396
|
+
languages: {}, // Would need languages API call
|
|
397
|
+
dependencies: deps.dependencies.slice(0, 30),
|
|
398
|
+
devDependencies: deps.devDependencies.slice(0, 20),
|
|
399
|
+
frameworksDetected: deps.frameworks,
|
|
400
|
+
};
|
|
401
|
+
// Generate recommendation
|
|
402
|
+
const recommendations = [];
|
|
403
|
+
if (!result.patterns.hasReadme)
|
|
404
|
+
recommendations.push("Add a README.md");
|
|
405
|
+
if (!result.patterns.hasTests)
|
|
406
|
+
recommendations.push("Add tests");
|
|
407
|
+
if (!result.patterns.hasCi)
|
|
408
|
+
recommendations.push("Set up CI/CD");
|
|
409
|
+
if (!result.patterns.hasTypes && repoData.language === "TypeScript")
|
|
410
|
+
recommendations.push("Ensure TypeScript types are exported");
|
|
411
|
+
if (!result.patterns.hasLicense)
|
|
412
|
+
recommendations.push("Add a license");
|
|
413
|
+
result.recommendation =
|
|
414
|
+
recommendations.length > 0
|
|
415
|
+
? `Suggestions: ${recommendations.join(", ")}`
|
|
416
|
+
: "Repository follows good practices (README, tests, CI, license detected).";
|
|
417
|
+
return result;
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
return {
|
|
421
|
+
error: true,
|
|
422
|
+
repoUrl,
|
|
423
|
+
owner,
|
|
424
|
+
repo,
|
|
425
|
+
message: `Repository analysis failed: ${err.message}`,
|
|
426
|
+
suggestion: "Check that the repository exists and is public. Set GITHUB_TOKEN for private repos or higher rate limits.",
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
];
|
|
432
|
+
//# sourceMappingURL=githubTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubTools.js","sourceRoot":"","sources":["../../src/tools/githubTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning tools — persistent edge case / gotcha / pattern store backed by SQLite FTS5.
|
|
3
|
+
* Reframed from generic "agent memory" to development learnings that prevent repeating mistakes.
|
|
4
|
+
*/
|
|
5
|
+
import type { McpTool } from "../types.js";
|
|
6
|
+
export declare const learningTools: McpTool[];
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning tools — persistent edge case / gotcha / pattern store backed by SQLite FTS5.
|
|
3
|
+
* Reframed from generic "agent memory" to development learnings that prevent repeating mistakes.
|
|
4
|
+
*/
|
|
5
|
+
import { getDb } from "../db.js";
|
|
6
|
+
export const learningTools = [
|
|
7
|
+
{
|
|
8
|
+
name: "record_learning",
|
|
9
|
+
description: "Store an edge case, gotcha, pattern, or regression discovered during verification. Learnings are searchable via full-text search and prevent repeating the same mistakes. Always record learnings at the end of a verification cycle.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
key: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Short identifier (e.g. 'convex-use-node-export-restriction', 'stooq-crypto-suffix')",
|
|
16
|
+
},
|
|
17
|
+
content: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "The learning: what happened, why, and how to avoid it",
|
|
20
|
+
},
|
|
21
|
+
category: {
|
|
22
|
+
type: "string",
|
|
23
|
+
enum: ["edge_case", "gotcha", "pattern", "regression", "convention"],
|
|
24
|
+
description: "Type of learning",
|
|
25
|
+
},
|
|
26
|
+
tags: {
|
|
27
|
+
type: "array",
|
|
28
|
+
items: { type: "string" },
|
|
29
|
+
description: "Searchable tags",
|
|
30
|
+
},
|
|
31
|
+
sourceCycle: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Verification cycle ID that produced this learning (optional)",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["key", "content", "category"],
|
|
37
|
+
},
|
|
38
|
+
handler: async (args) => {
|
|
39
|
+
const { key, content, category, tags, sourceCycle } = args;
|
|
40
|
+
if (!key || !content)
|
|
41
|
+
throw new Error("Key and content are required");
|
|
42
|
+
const db = getDb();
|
|
43
|
+
const now = new Date().toISOString();
|
|
44
|
+
const tagsJson = tags ? JSON.stringify(tags) : null;
|
|
45
|
+
db.prepare(`
|
|
46
|
+
INSERT INTO learnings (key, content, category, tags, source_cycle, created_at, updated_at)
|
|
47
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
48
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
49
|
+
content = excluded.content,
|
|
50
|
+
category = excluded.category,
|
|
51
|
+
tags = excluded.tags,
|
|
52
|
+
source_cycle = excluded.source_cycle,
|
|
53
|
+
updated_at = excluded.updated_at
|
|
54
|
+
`).run(key, content, category, tagsJson, sourceCycle ?? null, now, now);
|
|
55
|
+
const row = db
|
|
56
|
+
.prepare("SELECT id FROM learnings WHERE key = ?")
|
|
57
|
+
.get(key);
|
|
58
|
+
return {
|
|
59
|
+
success: true,
|
|
60
|
+
learningId: row?.id,
|
|
61
|
+
key,
|
|
62
|
+
category,
|
|
63
|
+
message: `Learning recorded. It will surface in future searches.`,
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "search_learnings",
|
|
69
|
+
description: "Search past learnings before making changes. This prevents repeating known mistakes. Always search learnings at the start of a verification cycle or before implementing a fix.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
query: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: "What you are about to work on (e.g. 'convex http routing', 'crypto price API')",
|
|
76
|
+
},
|
|
77
|
+
category: {
|
|
78
|
+
type: "string",
|
|
79
|
+
enum: ["edge_case", "gotcha", "pattern", "regression", "convention"],
|
|
80
|
+
description: "Filter by category (optional)",
|
|
81
|
+
},
|
|
82
|
+
limit: {
|
|
83
|
+
type: "number",
|
|
84
|
+
description: "Max results (default 10)",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
required: ["query"],
|
|
88
|
+
},
|
|
89
|
+
handler: async (args) => {
|
|
90
|
+
const db = getDb();
|
|
91
|
+
const limit = args.limit ?? 10;
|
|
92
|
+
const query = args.query;
|
|
93
|
+
let results;
|
|
94
|
+
if (args.category) {
|
|
95
|
+
results = db
|
|
96
|
+
.prepare(`
|
|
97
|
+
SELECT l.id, l.key, l.content, l.category, l.tags, l.source_cycle, l.created_at,
|
|
98
|
+
rank
|
|
99
|
+
FROM learnings_fts
|
|
100
|
+
JOIN learnings l ON l.id = learnings_fts.rowid
|
|
101
|
+
WHERE learnings_fts MATCH ?
|
|
102
|
+
AND l.category = ?
|
|
103
|
+
ORDER BY rank
|
|
104
|
+
LIMIT ?
|
|
105
|
+
`)
|
|
106
|
+
.all(query, args.category, limit);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
results = db
|
|
110
|
+
.prepare(`
|
|
111
|
+
SELECT l.id, l.key, l.content, l.category, l.tags, l.source_cycle, l.created_at,
|
|
112
|
+
rank
|
|
113
|
+
FROM learnings_fts
|
|
114
|
+
JOIN learnings l ON l.id = learnings_fts.rowid
|
|
115
|
+
WHERE learnings_fts MATCH ?
|
|
116
|
+
ORDER BY rank
|
|
117
|
+
LIMIT ?
|
|
118
|
+
`)
|
|
119
|
+
.all(query, limit);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
query,
|
|
123
|
+
count: results.length,
|
|
124
|
+
learnings: results.map((r) => ({
|
|
125
|
+
key: r.key,
|
|
126
|
+
content: r.content,
|
|
127
|
+
category: r.category,
|
|
128
|
+
tags: r.tags ? JSON.parse(r.tags) : [],
|
|
129
|
+
sourceCycle: r.source_cycle,
|
|
130
|
+
createdAt: r.created_at,
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "list_learnings",
|
|
137
|
+
description: "List all stored learnings, optionally filtered by category. Use this to review the knowledge base.",
|
|
138
|
+
inputSchema: {
|
|
139
|
+
type: "object",
|
|
140
|
+
properties: {
|
|
141
|
+
category: {
|
|
142
|
+
type: "string",
|
|
143
|
+
enum: ["edge_case", "gotcha", "pattern", "regression", "convention"],
|
|
144
|
+
description: "Filter by category (optional)",
|
|
145
|
+
},
|
|
146
|
+
limit: {
|
|
147
|
+
type: "number",
|
|
148
|
+
description: "Max results (default 50)",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
handler: async (args) => {
|
|
153
|
+
const db = getDb();
|
|
154
|
+
const limit = args.limit ?? 50;
|
|
155
|
+
const rows = args.category
|
|
156
|
+
? db
|
|
157
|
+
.prepare("SELECT * FROM learnings WHERE category = ? ORDER BY created_at DESC LIMIT ?")
|
|
158
|
+
.all(args.category, limit)
|
|
159
|
+
: db
|
|
160
|
+
.prepare("SELECT * FROM learnings ORDER BY created_at DESC LIMIT ?")
|
|
161
|
+
.all(limit);
|
|
162
|
+
return {
|
|
163
|
+
count: rows.length,
|
|
164
|
+
learnings: rows.map((r) => ({
|
|
165
|
+
key: r.key,
|
|
166
|
+
content: r.content,
|
|
167
|
+
category: r.category,
|
|
168
|
+
tags: r.tags ? JSON.parse(r.tags) : [],
|
|
169
|
+
sourceCycle: r.source_cycle,
|
|
170
|
+
createdAt: r.created_at,
|
|
171
|
+
})),
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "delete_learning",
|
|
177
|
+
description: "Delete a learning by key. Use when a learning is outdated or incorrect.",
|
|
178
|
+
inputSchema: {
|
|
179
|
+
type: "object",
|
|
180
|
+
properties: {
|
|
181
|
+
key: { type: "string", description: "Key of the learning to delete" },
|
|
182
|
+
},
|
|
183
|
+
required: ["key"],
|
|
184
|
+
},
|
|
185
|
+
handler: async (args) => {
|
|
186
|
+
const db = getDb();
|
|
187
|
+
const result = db
|
|
188
|
+
.prepare("DELETE FROM learnings WHERE key = ?")
|
|
189
|
+
.run(args.key);
|
|
190
|
+
if (result.changes === 0)
|
|
191
|
+
throw new Error(`No learning found for key: ${args.key}`);
|
|
192
|
+
return {
|
|
193
|
+
success: true,
|
|
194
|
+
message: `Deleted learning '${args.key}'`,
|
|
195
|
+
};
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
//# sourceMappingURL=learningTools.js.map
|