@homenshum/convex-mcp-nodebench 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -79,7 +79,7 @@ for (const tool of ALL_TOOLS) {
79
79
  // ── Server setup ────────────────────────────────────────────────────
80
80
  const server = new Server({
81
81
  name: "convex-mcp-nodebench",
82
- version: "0.9.0",
82
+ version: "0.9.1",
83
83
  }, {
84
84
  capabilities: {
85
85
  tools: {},
@@ -444,24 +444,15 @@ function inferConvexStrategy(signature) {
444
444
  return "Wrap optional fields with v.optional() — avoids runtime errors on missing fields";
445
445
  if (/v\.union/i.test(lower))
446
446
  return "Use v.union() for discriminated types — add a 'type' field as discriminator for type safety";
447
- // Function types
448
- if (/internalmutation/i.test(lower))
449
- return "Create internalMutation — only callable by other server functions, not from client. Import from _generated/server";
450
- if (/internalaction/i.test(lower))
451
- return "Create internalAction — for server-side-only work like API calls. Cannot access ctx.db directly, use ctx.runMutation/ctx.runQuery";
452
- if (/internalquery/i.test(lower))
453
- return "Create internalQuery — server-side-only reads. Not subscribable from client";
454
- if (/httpaction/i.test(lower))
455
- return "Create httpAction in http.ts — register with httpRouter.route({ method, path, handler })";
456
- if (/mutation\b/i.test(lower))
457
- return "Create public mutation — add args validator, return validator, and auth check (ctx.auth.getUserIdentity)";
458
- if (/action\b/i.test(lower))
459
- return "Create public action — for external API calls. Wrap in try/catch, use ctx.runMutation for DB writes";
460
- if (/query\b/i.test(lower))
461
- return "Create public query — reactive subscription from client. Must be deterministic, no side effects";
462
- // Data access
447
+ // Data access (BEFORE generic function types — ctx.db.query must match before query)
463
448
  if (/ctx\.db\.query/i.test(lower))
464
449
  return "Add ctx.db.query('table') — chain .withIndex() for indexed lookups (avoid full-table .filter())";
450
+ if (/ctx\.db\.insert/i.test(lower))
451
+ return "Use ctx.db.insert('table', { ...fields }) — within a mutation for transactional guarantee";
452
+ if (/ctx\.db\.patch/i.test(lower))
453
+ return "Use ctx.db.patch(id, { ...fields }) — partial update, only specified fields change";
454
+ if (/ctx\.db\.delete/i.test(lower))
455
+ return "Use ctx.db.delete(id) — remember to clean up related records and storage files";
465
456
  if (/withindex/i.test(lower))
466
457
  return "Use .withIndex('indexName', q => q.eq('field', value)) — ensure index exists in schema.ts first";
467
458
  if (/withsearchindex/i.test(lower))
@@ -470,30 +461,31 @@ function inferConvexStrategy(signature) {
470
461
  return "Add .collect() to get all results — WARNING: add .take(limit) for bounded queries to avoid scanning entire table";
471
462
  if (/\.paginate\b/i.test(lower))
472
463
  return "Use .paginate(opts) with paginationOptsValidator in args — return { page, isDone, continueCursor }";
473
- if (/ctx\.db\.insert/i.test(lower))
474
- return "Use ctx.db.insert('table', { ...fields }) — within a mutation for transactional guarantee";
475
- if (/ctx\.db\.patch/i.test(lower))
476
- return "Use ctx.db.patch(id, { ...fields }) — partial update, only specified fields change";
477
- if (/ctx\.db\.delete/i.test(lower))
478
- return "Use ctx.db.delete(id) — remember to clean up related records and storage files";
479
- // Auth
464
+ // Cross-function calls (BEFORE generic function types — ctx.runMutation must match before mutation)
465
+ if (/ctx\.runmutation|runmutation/i.test(lower))
466
+ return "Use ctx.runMutation(internal.module.functionName, args) — prefer internal functions for server-to-server mutation calls";
467
+ if (/ctx\.runquery|runquery/i.test(lower))
468
+ return "Use ctx.runQuery(internal.module.functionName, args) — prefer internal functions for server-to-server query calls";
469
+ if (/ctx\.runaction|runaction/i.test(lower))
470
+ return "Use ctx.runAction(internal.module.functionName, args) — prefer internal functions for server-to-server action calls";
471
+ // Auth (BEFORE generic function types)
480
472
  if (/getuseridentity/i.test(lower))
481
473
  return "Add `const identity = await ctx.auth.getUserIdentity()` — throw if null for protected endpoints";
482
474
  if (/identity.*check|if.*identity/i.test(lower))
483
475
  return "Add identity null check after getUserIdentity() — return 401/throw for unauthenticated users";
484
- // Scheduler
476
+ // Scheduler (BEFORE generic function types)
485
477
  if (/scheduler.*runafter/i.test(lower))
486
478
  return "Add ctx.scheduler.runAfter(delayMs, api.module.functionName, args) — use at least 1s delay for retries, add termination condition for loops";
487
479
  if (/scheduler.*runat/i.test(lower))
488
480
  return "Add ctx.scheduler.runAt(timestamp, api.module.functionName, args) — use for one-time future execution";
489
- // Storage
481
+ // Storage (BEFORE generic function types)
482
+ if (/storage.*generateuploadurl/i.test(lower))
483
+ return "Use ctx.storage.generateUploadUrl() in a mutation — return URL to client for direct upload";
490
484
  if (/storage.*store/i.test(lower))
491
485
  return "Use ctx.storage.store(blob) — returns storageId, save it to a document for later retrieval";
492
486
  if (/storage.*geturl/i.test(lower))
493
487
  return "Use ctx.storage.getUrl(storageId) — returns URL or null, always null-check the result";
494
- if (/storage.*generateuploadurl/i.test(lower))
495
- return "Use ctx.storage.generateUploadUrl() in a mutation — return URL to client for direct upload";
496
- // Client-side
488
+ // Client-side (BEFORE generic function types — useQuery before query)
497
489
  if (/usequery/i.test(lower))
498
490
  return "Add useQuery(api.module.queryName, args) — reactive subscription, re-renders on data change";
499
491
  if (/usemutation/i.test(lower))
@@ -502,9 +494,21 @@ function inferConvexStrategy(signature) {
502
494
  return "Add useAction(api.module.actionName) — returns async function, use for external API calls";
503
495
  if (/convexprovider|convexreactclient/i.test(lower))
504
496
  return "Wrap app with <ConvexProvider client={convex}> — create client with new ConvexReactClient(url)";
505
- // Cross-function calls
506
- if (/runmutation|runquery|runaction/i.test(lower))
507
- return "Use ctx.runMutation/ctx.runQuery/ctx.runAction for cross-function calls prefer internal functions for server-to-server";
497
+ // Function types (GENERIC — must come AFTER all specific patterns above)
498
+ if (/internalmutation/i.test(lower))
499
+ return "Create internalMutation only callable by other server functions, not from client. Import from _generated/server";
500
+ if (/internalaction/i.test(lower))
501
+ return "Create internalAction — for server-side-only work like API calls. Cannot access ctx.db directly, use ctx.runMutation/ctx.runQuery";
502
+ if (/internalquery/i.test(lower))
503
+ return "Create internalQuery — server-side-only reads. Not subscribable from client";
504
+ if (/httpaction/i.test(lower))
505
+ return "Create httpAction in http.ts — register with httpRouter.route({ method, path, handler })";
506
+ if (/mutation\b/i.test(lower))
507
+ return "Create public mutation — add args validator, return validator, and auth check (ctx.auth.getUserIdentity)";
508
+ if (/action\b/i.test(lower))
509
+ return "Create public action — for external API calls. Wrap in try/catch, use ctx.runMutation for DB writes";
510
+ if (/query\b/i.test(lower))
511
+ return "Create public query — reactive subscription from client. Must be deterministic, no side effects";
508
512
  return "Inject this pattern into the appropriate Convex file — check existing patterns with convex_scan_capabilities first";
509
513
  }
510
514
  function inferTargetFile(signature) {
@@ -75,7 +75,7 @@ function buildSarif(projectDir, auditTypes, limit) {
75
75
  tool: {
76
76
  driver: {
77
77
  name: "convex-mcp-nodebench",
78
- version: "0.9.0",
78
+ version: "0.9.1",
79
79
  informationUri: "https://www.npmjs.com/package/@homenshum/convex-mcp-nodebench",
80
80
  rules: [...rulesMap.values()],
81
81
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homenshum/convex-mcp-nodebench",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Convex-specific MCP server applying NodeBench self-instruct diligence patterns to Convex development. Schema audit, function compliance, deployment gates, persistent gotcha DB, and methodology guidance. Complements Context7 (raw docs) and official Convex MCP (deployment introspection) with structured verification workflows.",
5
5
  "type": "module",
6
6
  "bin": {