@homenshum/convex-mcp-nodebench 0.7.0 → 0.9.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/index.js +243 -2
- package/dist/tools/architectTools.d.ts +15 -0
- package/dist/tools/architectTools.js +526 -0
- package/dist/tools/qualityGateTools.d.ts +2 -0
- package/dist/tools/qualityGateTools.js +204 -0
- package/dist/tools/reportingTools.d.ts +2 -0
- package/dist/tools/reportingTools.js +240 -0
- package/dist/tools/schedulerTools.d.ts +2 -0
- package/dist/tools/schedulerTools.js +197 -0
- package/dist/tools/toolRegistry.js +117 -0
- package/dist/tools/vectorSearchTools.d.ts +2 -0
- package/dist/tools/vectorSearchTools.js +192 -0
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
16
16
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
|
-
import { ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
17
|
+
import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
18
18
|
import { getDb, seedGotchasIfEmpty } from "./db.js";
|
|
19
19
|
import { schemaTools } from "./tools/schemaTools.js";
|
|
20
20
|
import { functionTools } from "./tools/functionTools.js";
|
|
@@ -36,6 +36,11 @@ import { paginationTools } from "./tools/paginationTools.js";
|
|
|
36
36
|
import { dataModelingTools } from "./tools/dataModelingTools.js";
|
|
37
37
|
import { devSetupTools } from "./tools/devSetupTools.js";
|
|
38
38
|
import { migrationTools } from "./tools/migrationTools.js";
|
|
39
|
+
import { reportingTools } from "./tools/reportingTools.js";
|
|
40
|
+
import { vectorSearchTools } from "./tools/vectorSearchTools.js";
|
|
41
|
+
import { schedulerTools } from "./tools/schedulerTools.js";
|
|
42
|
+
import { qualityGateTools } from "./tools/qualityGateTools.js";
|
|
43
|
+
import { architectTools } from "./tools/architectTools.js";
|
|
39
44
|
import { CONVEX_GOTCHAS } from "./gotchaSeed.js";
|
|
40
45
|
import { REGISTRY } from "./tools/toolRegistry.js";
|
|
41
46
|
import { initEmbeddingIndex } from "./tools/embeddingProvider.js";
|
|
@@ -61,6 +66,11 @@ const ALL_TOOLS = [
|
|
|
61
66
|
...dataModelingTools,
|
|
62
67
|
...devSetupTools,
|
|
63
68
|
...migrationTools,
|
|
69
|
+
...reportingTools,
|
|
70
|
+
...vectorSearchTools,
|
|
71
|
+
...schedulerTools,
|
|
72
|
+
...qualityGateTools,
|
|
73
|
+
...architectTools,
|
|
64
74
|
];
|
|
65
75
|
const toolMap = new Map();
|
|
66
76
|
for (const tool of ALL_TOOLS) {
|
|
@@ -69,10 +79,12 @@ for (const tool of ALL_TOOLS) {
|
|
|
69
79
|
// ── Server setup ────────────────────────────────────────────────────
|
|
70
80
|
const server = new Server({
|
|
71
81
|
name: "convex-mcp-nodebench",
|
|
72
|
-
version: "0.
|
|
82
|
+
version: "0.9.0",
|
|
73
83
|
}, {
|
|
74
84
|
capabilities: {
|
|
75
85
|
tools: {},
|
|
86
|
+
resources: {},
|
|
87
|
+
prompts: {},
|
|
76
88
|
},
|
|
77
89
|
});
|
|
78
90
|
// ── Initialize DB + seed gotchas ────────────────────────────────────
|
|
@@ -169,6 +181,235 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
169
181
|
};
|
|
170
182
|
}
|
|
171
183
|
});
|
|
184
|
+
// ── MCP Resources ───────────────────────────────────────────────────
|
|
185
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
186
|
+
return {
|
|
187
|
+
resources: [
|
|
188
|
+
{
|
|
189
|
+
uri: "convex://project-health",
|
|
190
|
+
name: "Project Health Summary",
|
|
191
|
+
description: "Latest quality gate score, audit coverage, and issue counts across all audit types",
|
|
192
|
+
mimeType: "application/json",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
uri: "convex://recent-audits",
|
|
196
|
+
name: "Recent Audit Results",
|
|
197
|
+
description: "Summary of the 10 most recent audit runs with issue counts and timestamps",
|
|
198
|
+
mimeType: "application/json",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
uri: "convex://gotcha-db",
|
|
202
|
+
name: "Gotcha Knowledge Base",
|
|
203
|
+
description: "All stored Convex gotchas (seeded + user-recorded) with categories and severity",
|
|
204
|
+
mimeType: "application/json",
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
210
|
+
const uri = request.params.uri;
|
|
211
|
+
const db = getDb();
|
|
212
|
+
if (uri === "convex://project-health") {
|
|
213
|
+
// Aggregate across all projects
|
|
214
|
+
const audits = db.prepare("SELECT audit_type, issue_count, audited_at FROM audit_results ORDER BY audited_at DESC LIMIT 50").all();
|
|
215
|
+
const byType = {};
|
|
216
|
+
for (const a of audits) {
|
|
217
|
+
if (!byType[a.audit_type]) {
|
|
218
|
+
byType[a.audit_type] = { count: a.issue_count, latest: a.audited_at };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const totalIssues = Object.values(byType).reduce((s, v) => s + v.count, 0);
|
|
222
|
+
const auditTypes = Object.keys(byType).length;
|
|
223
|
+
const latestGate = db.prepare("SELECT findings FROM deploy_checks WHERE check_type = 'quality_gate' ORDER BY checked_at DESC LIMIT 1").get();
|
|
224
|
+
let gateResult = null;
|
|
225
|
+
if (latestGate?.findings) {
|
|
226
|
+
try {
|
|
227
|
+
gateResult = JSON.parse(latestGate.findings);
|
|
228
|
+
}
|
|
229
|
+
catch { /* skip */ }
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
contents: [{
|
|
233
|
+
uri,
|
|
234
|
+
mimeType: "application/json",
|
|
235
|
+
text: JSON.stringify({
|
|
236
|
+
totalIssues,
|
|
237
|
+
auditTypesRun: auditTypes,
|
|
238
|
+
issuesByType: byType,
|
|
239
|
+
latestQualityGate: gateResult ? { score: gateResult.score, grade: gateResult.grade, passed: gateResult.passed } : null,
|
|
240
|
+
toolCount: ALL_TOOLS.length,
|
|
241
|
+
}, null, 2),
|
|
242
|
+
}],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (uri === "convex://recent-audits") {
|
|
246
|
+
const audits = db.prepare("SELECT id, project_dir, audit_type, issue_count, audited_at FROM audit_results ORDER BY audited_at DESC LIMIT 10").all();
|
|
247
|
+
return {
|
|
248
|
+
contents: [{
|
|
249
|
+
uri,
|
|
250
|
+
mimeType: "application/json",
|
|
251
|
+
text: JSON.stringify({ audits }, null, 2),
|
|
252
|
+
}],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (uri === "convex://gotcha-db") {
|
|
256
|
+
const gotchas = db.prepare("SELECT key, category, severity, tags, source, updated_at FROM convex_gotchas ORDER BY updated_at DESC").all();
|
|
257
|
+
return {
|
|
258
|
+
contents: [{
|
|
259
|
+
uri,
|
|
260
|
+
mimeType: "application/json",
|
|
261
|
+
text: JSON.stringify({
|
|
262
|
+
totalGotchas: gotchas.length,
|
|
263
|
+
bySource: {
|
|
264
|
+
seed: gotchas.filter(g => g.source === "seed").length,
|
|
265
|
+
user: gotchas.filter(g => g.source === "user").length,
|
|
266
|
+
},
|
|
267
|
+
gotchas,
|
|
268
|
+
}, null, 2),
|
|
269
|
+
}],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
contents: [{
|
|
274
|
+
uri,
|
|
275
|
+
mimeType: "text/plain",
|
|
276
|
+
text: `Unknown resource: ${uri}`,
|
|
277
|
+
}],
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
// ── MCP Prompts ─────────────────────────────────────────────────────
|
|
281
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
282
|
+
return {
|
|
283
|
+
prompts: [
|
|
284
|
+
{
|
|
285
|
+
name: "full-audit",
|
|
286
|
+
description: "Run a complete Convex project audit: schema, functions, auth, queries, actions, type safety, transactions, storage, pagination, data modeling, dev setup, vectors, schedulers — then quality gate",
|
|
287
|
+
arguments: [
|
|
288
|
+
{
|
|
289
|
+
name: "projectDir",
|
|
290
|
+
description: "Absolute path to the project root",
|
|
291
|
+
required: true,
|
|
292
|
+
},
|
|
293
|
+
],
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: "pre-deploy-checklist",
|
|
297
|
+
description: "Step-by-step pre-deployment verification: audit critical issues, check env vars, review migration plan, run quality gate",
|
|
298
|
+
arguments: [
|
|
299
|
+
{
|
|
300
|
+
name: "projectDir",
|
|
301
|
+
description: "Absolute path to the project root",
|
|
302
|
+
required: true,
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: "security-review",
|
|
308
|
+
description: "Security-focused audit: authorization coverage, type safety, action safety, storage permissions",
|
|
309
|
+
arguments: [
|
|
310
|
+
{
|
|
311
|
+
name: "projectDir",
|
|
312
|
+
description: "Absolute path to the project root",
|
|
313
|
+
required: true,
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
321
|
+
const { name, arguments: promptArgs } = request.params;
|
|
322
|
+
const projectDir = promptArgs?.projectDir ?? ".";
|
|
323
|
+
if (name === "full-audit") {
|
|
324
|
+
return {
|
|
325
|
+
description: "Complete Convex project audit sequence",
|
|
326
|
+
messages: [
|
|
327
|
+
{
|
|
328
|
+
role: "user",
|
|
329
|
+
content: {
|
|
330
|
+
type: "text",
|
|
331
|
+
text: `Run a complete audit of the Convex project at "${projectDir}". Execute these tools in order:
|
|
332
|
+
|
|
333
|
+
1. convex_audit_schema — Check schema.ts for anti-patterns
|
|
334
|
+
2. convex_audit_functions — Audit function registration and compliance
|
|
335
|
+
3. convex_audit_authorization — Check auth coverage on public endpoints
|
|
336
|
+
4. convex_audit_query_efficiency — Find unbounded queries and missing indexes
|
|
337
|
+
5. convex_audit_actions — Validate action safety (no ctx.db, error handling)
|
|
338
|
+
6. convex_check_type_safety — Find as-any casts and type issues
|
|
339
|
+
7. convex_audit_transaction_safety — Detect race conditions
|
|
340
|
+
8. convex_audit_storage_usage — Check file storage patterns
|
|
341
|
+
9. convex_audit_pagination — Validate pagination implementations
|
|
342
|
+
10. convex_audit_data_modeling — Check schema design quality
|
|
343
|
+
11. convex_audit_vector_search — Validate vector search setup
|
|
344
|
+
12. convex_audit_schedulers — Check scheduled function safety
|
|
345
|
+
13. convex_audit_dev_setup — Verify project setup
|
|
346
|
+
14. convex_quality_gate — Run configurable quality gate across all results
|
|
347
|
+
|
|
348
|
+
After running all audits, summarize:
|
|
349
|
+
- Total issues by severity (critical/warning/info)
|
|
350
|
+
- Top 5 most impactful issues to fix first
|
|
351
|
+
- Quality gate score and grade
|
|
352
|
+
- Trend direction if previous audits exist (use convex_audit_diff)`,
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (name === "pre-deploy-checklist") {
|
|
359
|
+
return {
|
|
360
|
+
description: "Pre-deployment verification sequence",
|
|
361
|
+
messages: [
|
|
362
|
+
{
|
|
363
|
+
role: "user",
|
|
364
|
+
content: {
|
|
365
|
+
type: "text",
|
|
366
|
+
text: `Run pre-deployment checks for the Convex project at "${projectDir}":
|
|
367
|
+
|
|
368
|
+
1. convex_pre_deploy_gate — Structural checks (schema, auth config, initialization)
|
|
369
|
+
2. convex_check_env_vars — Verify all required env vars are set
|
|
370
|
+
3. convex_audit_authorization — Ensure auth coverage is adequate
|
|
371
|
+
4. convex_audit_actions — No ctx.db access in actions
|
|
372
|
+
5. convex_snapshot_schema — Capture current schema state
|
|
373
|
+
6. convex_schema_migration_plan — Compare against previous snapshot for breaking changes
|
|
374
|
+
7. convex_quality_gate — Final quality check with thresholds
|
|
375
|
+
|
|
376
|
+
Report: DEPLOY or DO NOT DEPLOY with specific blockers to fix.`,
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (name === "security-review") {
|
|
383
|
+
return {
|
|
384
|
+
description: "Security-focused audit sequence",
|
|
385
|
+
messages: [
|
|
386
|
+
{
|
|
387
|
+
role: "user",
|
|
388
|
+
content: {
|
|
389
|
+
type: "text",
|
|
390
|
+
text: `Run a security review of the Convex project at "${projectDir}":
|
|
391
|
+
|
|
392
|
+
1. convex_audit_authorization — Auth coverage on all public endpoints
|
|
393
|
+
2. convex_check_type_safety — Type safety bypasses (as any)
|
|
394
|
+
3. convex_audit_actions — Action safety (ctx.db, error handling, "use node")
|
|
395
|
+
4. convex_audit_storage_usage — Storage permission patterns
|
|
396
|
+
5. convex_audit_pagination — Unbounded numItems (DoS risk)
|
|
397
|
+
6. convex_audit_transaction_safety — Race condition risks
|
|
398
|
+
|
|
399
|
+
Focus on: unauthorized data access, unvalidated inputs, missing error boundaries, and potential data corruption vectors.`,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
description: "Unknown prompt",
|
|
407
|
+
messages: [{
|
|
408
|
+
role: "user",
|
|
409
|
+
content: { type: "text", text: `Unknown prompt: ${name}` },
|
|
410
|
+
}],
|
|
411
|
+
};
|
|
412
|
+
});
|
|
172
413
|
// ── Start server ────────────────────────────────────────────────────
|
|
173
414
|
async function main() {
|
|
174
415
|
const transport = new StdioServerTransport();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architect Tools — Structural code analysis for Convex projects.
|
|
3
|
+
*
|
|
4
|
+
* Convex-specific variant of the mcp-local architect tools. Instead of
|
|
5
|
+
* generic React/Express patterns, these scan for Convex function types,
|
|
6
|
+
* schema constructs, data access patterns, auth guards, storage usage,
|
|
7
|
+
* scheduler calls, and client-side hooks.
|
|
8
|
+
*
|
|
9
|
+
* 3 tools:
|
|
10
|
+
* - convex_scan_capabilities: Analyze a file for Convex structural patterns
|
|
11
|
+
* - convex_verify_concept: Check if a file has required code signatures
|
|
12
|
+
* - convex_generate_plan: Build a plan for missing signatures
|
|
13
|
+
*/
|
|
14
|
+
import type { McpTool } from "../types.js";
|
|
15
|
+
export declare const architectTools: McpTool[];
|