truss-code-review-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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +88 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/ai-review.d.ts +21 -0
  8. package/dist/lib/ai-review.d.ts.map +1 -0
  9. package/dist/lib/ai-review.js +185 -0
  10. package/dist/lib/ai-review.js.map +1 -0
  11. package/dist/lib/complexity.d.ts +20 -0
  12. package/dist/lib/complexity.d.ts.map +1 -0
  13. package/dist/lib/complexity.js +272 -0
  14. package/dist/lib/complexity.js.map +1 -0
  15. package/dist/lib/license.d.ts +15 -0
  16. package/dist/lib/license.d.ts.map +1 -0
  17. package/dist/lib/license.js +72 -0
  18. package/dist/lib/license.js.map +1 -0
  19. package/dist/lib/patterns.d.ts +27 -0
  20. package/dist/lib/patterns.d.ts.map +1 -0
  21. package/dist/lib/patterns.js +102 -0
  22. package/dist/lib/patterns.js.map +1 -0
  23. package/dist/tools/check-complexity.d.ts +6 -0
  24. package/dist/tools/check-complexity.d.ts.map +1 -0
  25. package/dist/tools/check-complexity.js +34 -0
  26. package/dist/tools/check-complexity.js.map +1 -0
  27. package/dist/tools/deep-review.d.ts +6 -0
  28. package/dist/tools/deep-review.d.ts.map +1 -0
  29. package/dist/tools/deep-review.js +58 -0
  30. package/dist/tools/deep-review.js.map +1 -0
  31. package/dist/tools/detect-antipatterns.d.ts +6 -0
  32. package/dist/tools/detect-antipatterns.d.ts.map +1 -0
  33. package/dist/tools/detect-antipatterns.js +44 -0
  34. package/dist/tools/detect-antipatterns.js.map +1 -0
  35. package/dist/tools/explain-code.d.ts +6 -0
  36. package/dist/tools/explain-code.d.ts.map +1 -0
  37. package/dist/tools/explain-code.js +56 -0
  38. package/dist/tools/explain-code.js.map +1 -0
  39. package/dist/tools/optimize-code.d.ts +6 -0
  40. package/dist/tools/optimize-code.d.ts.map +1 -0
  41. package/dist/tools/optimize-code.js +57 -0
  42. package/dist/tools/optimize-code.js.map +1 -0
  43. package/dist/tools/review-diff.d.ts +8 -0
  44. package/dist/tools/review-diff.d.ts.map +1 -0
  45. package/dist/tools/review-diff.js +333 -0
  46. package/dist/tools/review-diff.js.map +1 -0
  47. package/dist/tools/security-review.d.ts +6 -0
  48. package/dist/tools/security-review.d.ts.map +1 -0
  49. package/dist/tools/security-review.js +57 -0
  50. package/dist/tools/security-review.js.map +1 -0
  51. package/dist/tools/suggest-tests.d.ts +6 -0
  52. package/dist/tools/suggest-tests.d.ts.map +1 -0
  53. package/dist/tools/suggest-tests.js +78 -0
  54. package/dist/tools/suggest-tests.js.map +1 -0
  55. package/evals/eval-complexity.ts +202 -0
  56. package/evals/eval-review.ts +196 -0
  57. package/evals/run-evals.ts +51 -0
  58. package/glama.json +4 -0
  59. package/package.json +36 -0
  60. package/smithery.yaml +15 -0
  61. package/src/data/antipatterns/go.json +98 -0
  62. package/src/data/antipatterns/javascript.json +122 -0
  63. package/src/data/antipatterns/python.json +98 -0
  64. package/src/index.ts +109 -0
  65. package/src/lib/ai-review.ts +220 -0
  66. package/src/lib/complexity.ts +284 -0
  67. package/src/lib/license.ts +95 -0
  68. package/src/lib/patterns.ts +131 -0
  69. package/src/tools/check-complexity.ts +43 -0
  70. package/src/tools/deep-review.ts +67 -0
  71. package/src/tools/detect-antipatterns.ts +54 -0
  72. package/src/tools/explain-code.ts +65 -0
  73. package/src/tools/optimize-code.ts +66 -0
  74. package/src/tools/review-diff.ts +374 -0
  75. package/src/tools/security-review.ts +66 -0
  76. package/src/tools/suggest-tests.ts +90 -0
  77. package/tsconfig.json +19 -0
@@ -0,0 +1,6 @@
1
+ /**
2
+ * detect_antipatterns — Language-specific anti-pattern detection (Free tier)
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerDetectAntipatterns(server: McpServer): void;
6
+ //# sourceMappingURL=detect-antipatterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-antipatterns.d.ts","sourceRoot":"","sources":["../../src/tools/detect-antipatterns.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6ClE"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * detect_antipatterns — Language-specific anti-pattern detection (Free tier)
3
+ */
4
+ import { z } from 'zod';
5
+ import { detectAntiPatterns, getSupportedLanguages, isLanguageSupported } from '../lib/patterns.js';
6
+ export function registerDetectAntipatterns(server) {
7
+ server.tool('detect_antipatterns', 'Detect common anti-patterns per language. Includes: JS/TS (var, ==, any, eval, innerHTML, sync I/O), Python (bare except, mutable defaults, wildcard imports), Go (ignored errors, goroutine leaks, mutex without defer). Free tier.', {
8
+ code: z.string().describe('Source code to analyze'),
9
+ language: z.string().describe('Programming language (javascript, typescript, python, go)'),
10
+ }, async ({ code, language }) => {
11
+ if (!isLanguageSupported(language)) {
12
+ return {
13
+ content: [{
14
+ type: 'text',
15
+ text: JSON.stringify({
16
+ error: `Language "${language}" is not supported.`,
17
+ supported: getSupportedLanguages(),
18
+ }, null, 2),
19
+ }],
20
+ };
21
+ }
22
+ const matches = detectAntiPatterns(code, language);
23
+ const output = {
24
+ language,
25
+ total_findings: matches.length,
26
+ by_severity: {
27
+ error: matches.filter(m => m.severity === 'error').length,
28
+ warning: matches.filter(m => m.severity === 'warning').length,
29
+ info: matches.filter(m => m.severity === 'info').length,
30
+ },
31
+ findings: matches.map(m => ({
32
+ pattern: m.pattern,
33
+ description: m.description,
34
+ location: m.location,
35
+ severity: m.severity,
36
+ fix: m.fix,
37
+ })),
38
+ };
39
+ return {
40
+ content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=detect-antipatterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-antipatterns.js","sourceRoot":"","sources":["../../src/tools/detect-antipatterns.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEpG,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,sOAAsO,EACtO;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACnD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;KAC3F,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,aAAa,QAAQ,qBAAqB;4BACjD,SAAS,EAAE,qBAAqB,EAAE;yBACnC,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAG;YACb,QAAQ;YACR,cAAc,EAAE,OAAO,CAAC,MAAM;YAC9B,WAAW,EAAE;gBACX,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;gBACzD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;gBAC7D,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM;aACxD;YACD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC1B,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,GAAG,EAAE,CAAC,CAAC,GAAG;aACX,CAAC,CAAC;SACJ,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * explain_code — Generate documentation for complex code (Pro tier)
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerExplainCode(server: McpServer): void;
6
+ //# sourceMappingURL=explain-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain-code.d.ts","sourceRoot":"","sources":["../../src/tools/explain-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuD3D"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * explain_code — Generate documentation for complex code (Pro tier)
3
+ */
4
+ import { z } from 'zod';
5
+ import { requirePro, requireAiKey } from '../lib/license.js';
6
+ import { aiReview, EXPLAIN_CODE_SYSTEM } from '../lib/ai-review.js';
7
+ export function registerExplainCode(server) {
8
+ server.tool('explain_code', 'Generate documentation for complex code. Produces high-level explanation, function docstrings, data flow analysis, and design notes. Pro tier.', {
9
+ code: z.string().describe('Source code to explain'),
10
+ language: z.string().describe('Programming language'),
11
+ }, async ({ code, language }) => {
12
+ await requirePro();
13
+ requireAiKey();
14
+ const userPrompt = [
15
+ `Language: ${language}`,
16
+ '',
17
+ '```',
18
+ code,
19
+ '```',
20
+ ].join('\n');
21
+ try {
22
+ const result = await aiReview(EXPLAIN_CODE_SYSTEM, userPrompt);
23
+ let parsed;
24
+ try {
25
+ parsed = JSON.parse(result.content);
26
+ }
27
+ catch {
28
+ parsed = { explanation: result.content };
29
+ }
30
+ return {
31
+ content: [{
32
+ type: 'text',
33
+ text: JSON.stringify({
34
+ documentation: parsed,
35
+ meta: {
36
+ model: result.model,
37
+ provider: result.provider,
38
+ tokens: result.tokensUsed,
39
+ },
40
+ }, null, 2),
41
+ }],
42
+ };
43
+ }
44
+ catch (err) {
45
+ return {
46
+ content: [{
47
+ type: 'text',
48
+ text: JSON.stringify({
49
+ error: err instanceof Error ? err.message : String(err),
50
+ }),
51
+ }],
52
+ };
53
+ }
54
+ });
55
+ }
56
+ //# sourceMappingURL=explain-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain-code.js","sourceRoot":"","sources":["../../src/tools/explain-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEpE,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,cAAc,EACd,gJAAgJ,EAChJ;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACnD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACtD,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,MAAM,UAAU,EAAE,CAAC;QACnB,YAAY,EAAE,CAAC;QAEf,MAAM,UAAU,GAAG;YACjB,aAAa,QAAQ,EAAE;YACvB,EAAE;YACF,KAAK;YACL,IAAI;YACJ,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;YAE/D,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YAC3C,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,aAAa,EAAE,MAAM;4BACrB,IAAI,EAAE;gCACJ,KAAK,EAAE,MAAM,CAAC,KAAK;gCACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gCACzB,MAAM,EAAE,MAAM,CAAC,UAAU;6BAC1B;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * optimize_code — Performance optimization suggestions (Pro tier)
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerOptimizeCode(server: McpServer): void;
6
+ //# sourceMappingURL=optimize-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimize-code.d.ts","sourceRoot":"","sources":["../../src/tools/optimize-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwD5D"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * optimize_code — Performance optimization suggestions (Pro tier)
3
+ */
4
+ import { z } from 'zod';
5
+ import { requirePro, requireAiKey } from '../lib/license.js';
6
+ import { aiReview, OPTIMIZE_CODE_SYSTEM } from '../lib/ai-review.js';
7
+ export function registerOptimizeCode(server) {
8
+ server.tool('optimize_code', 'Performance optimization suggestions with before/after code and expected impact. Covers algorithmic complexity, memory usage, I/O efficiency, caching, and language-specific optimizations. Pro tier.', {
9
+ code: z.string().describe('Source code to optimize'),
10
+ language: z.string().describe('Programming language'),
11
+ }, async ({ code, language }) => {
12
+ await requirePro();
13
+ requireAiKey();
14
+ const userPrompt = [
15
+ `Language: ${language}`,
16
+ '',
17
+ 'Analyze this code for performance optimization opportunities:',
18
+ '```',
19
+ code,
20
+ '```',
21
+ ].join('\n');
22
+ try {
23
+ const result = await aiReview(OPTIMIZE_CODE_SYSTEM, userPrompt);
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(result.content);
27
+ }
28
+ catch {
29
+ parsed = { raw_review: result.content };
30
+ }
31
+ return {
32
+ content: [{
33
+ type: 'text',
34
+ text: JSON.stringify({
35
+ optimizations: parsed,
36
+ meta: {
37
+ model: result.model,
38
+ provider: result.provider,
39
+ tokens: result.tokensUsed,
40
+ },
41
+ }, null, 2),
42
+ }],
43
+ };
44
+ }
45
+ catch (err) {
46
+ return {
47
+ content: [{
48
+ type: 'text',
49
+ text: JSON.stringify({
50
+ error: err instanceof Error ? err.message : String(err),
51
+ }),
52
+ }],
53
+ };
54
+ }
55
+ });
56
+ }
57
+ //# sourceMappingURL=optimize-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimize-code.js","sourceRoot":"","sources":["../../src/tools/optimize-code.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,uMAAuM,EACvM;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACpD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACtD,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,MAAM,UAAU,EAAE,CAAC;QACnB,YAAY,EAAE,CAAC;QAEf,MAAM,UAAU,GAAG;YACjB,aAAa,QAAQ,EAAE;YACvB,EAAE;YACF,+DAA+D;YAC/D,KAAK;YACL,IAAI;YACJ,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC;YAEhE,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,aAAa,EAAE,MAAM;4BACrB,IAAI,EAAE;gCACJ,KAAK,EAAE,MAAM,CAAC,KAAK;gCACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gCACzB,MAAM,EAAE,MAAM,CAAC,UAAU;6BAC1B;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * review_diff — Rule-based diff analysis (Free tier)
3
+ * Checks for common issues: large files, debug statements, TODO without tickets,
4
+ * commented-out code, import ordering, sensitive data, etc.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ export declare function registerReviewDiff(server: McpServer): void;
8
+ //# sourceMappingURL=review-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-diff.d.ts","sourceRoot":"","sources":["../../src/tools/review-diff.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyUpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsC1D"}
@@ -0,0 +1,333 @@
1
+ /**
2
+ * review_diff — Rule-based diff analysis (Free tier)
3
+ * Checks for common issues: large files, debug statements, TODO without tickets,
4
+ * commented-out code, import ordering, sensitive data, etc.
5
+ */
6
+ import { z } from 'zod';
7
+ import { readFileSync } from 'node:fs';
8
+ import { execSync } from 'node:child_process';
9
+ // ── Rule checks ─────────────────────────────────────────────────────
10
+ function checkLargeFile(lines, filename) {
11
+ const addedLines = lines.filter(l => l.startsWith('+')).length;
12
+ const comments = [];
13
+ if (addedLines > 500) {
14
+ comments.push({
15
+ file: filename,
16
+ line: null,
17
+ severity: 'warning',
18
+ message: `Large change: ${addedLines} lines added. Consider breaking into smaller PRs.`,
19
+ suggestion: 'Split into focused, reviewable chunks of <300 lines each.',
20
+ });
21
+ }
22
+ return comments;
23
+ }
24
+ function checkDebugStatements(lines, filename) {
25
+ const comments = [];
26
+ const debugPatterns = [
27
+ { pattern: /console\.(log|debug|info|warn|error)\s*\(/, message: 'console.log left in code' },
28
+ { pattern: /\bprint\s*\((?!.*#.*noqa)/, message: 'print() statement (Python debug?)' },
29
+ { pattern: /\bfmt\.Print(ln|f)?\s*\(/, message: 'fmt.Print statement (Go debug?)' },
30
+ { pattern: /\bdebugger\b/, message: 'debugger statement' },
31
+ { pattern: /\bpdb\.set_trace\b/, message: 'pdb breakpoint' },
32
+ { pattern: /\bbreakpoint\s*\(\)/, message: 'Python breakpoint()' },
33
+ { pattern: /\bDDLog\b|\bNSLog\s*\(/, message: 'Debug log statement' },
34
+ ];
35
+ let lineNum = 0;
36
+ for (const line of lines) {
37
+ if (line.startsWith('@@')) {
38
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
39
+ if (match)
40
+ lineNum = parseInt(match[1], 10) - 1;
41
+ continue;
42
+ }
43
+ if (line.startsWith('+') && !line.startsWith('+++')) {
44
+ lineNum++;
45
+ const content = line.slice(1);
46
+ for (const dp of debugPatterns) {
47
+ if (dp.pattern.test(content)) {
48
+ comments.push({
49
+ file: filename,
50
+ line: lineNum,
51
+ severity: 'warning',
52
+ message: dp.message,
53
+ suggestion: 'Remove debug statements before merging, or use a proper logger.',
54
+ });
55
+ }
56
+ }
57
+ }
58
+ else if (line.startsWith(' ')) {
59
+ lineNum++;
60
+ }
61
+ }
62
+ return comments;
63
+ }
64
+ function checkTodoWithoutTicket(lines, filename) {
65
+ const comments = [];
66
+ const todoPattern = /\b(TODO|FIXME|HACK|XXX|TEMP)\b(?!.*(?:[A-Z]+-\d+|#\d+|https?:))/i;
67
+ let lineNum = 0;
68
+ for (const line of lines) {
69
+ if (line.startsWith('@@')) {
70
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
71
+ if (match)
72
+ lineNum = parseInt(match[1], 10) - 1;
73
+ continue;
74
+ }
75
+ if (line.startsWith('+') && !line.startsWith('+++')) {
76
+ lineNum++;
77
+ if (todoPattern.test(line.slice(1))) {
78
+ comments.push({
79
+ file: filename,
80
+ line: lineNum,
81
+ severity: 'info',
82
+ message: 'TODO/FIXME without a ticket reference.',
83
+ suggestion: 'Add a ticket reference: TODO(PROJ-123) or TODO(#456) to track this work.',
84
+ });
85
+ }
86
+ }
87
+ else if (line.startsWith(' ')) {
88
+ lineNum++;
89
+ }
90
+ }
91
+ return comments;
92
+ }
93
+ function checkCommentedOutCode(lines, filename) {
94
+ const comments = [];
95
+ // Detect commented-out code (lines that look like code, not natural language comments)
96
+ const codePatterns = [
97
+ /^\s*\/\/\s*(if|for|while|return|const|let|var|function|class|import)\b/,
98
+ /^\s*#\s*(if|for|while|return|def|class|import|from)\b/,
99
+ /^\s*\/\/\s*\w+\s*[=({[\]]/,
100
+ /^\s*#\s*\w+\s*[=({[\]]/,
101
+ ];
102
+ let lineNum = 0;
103
+ let consecutiveCommentedCode = 0;
104
+ let blockStart = 0;
105
+ for (const line of lines) {
106
+ if (line.startsWith('@@')) {
107
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
108
+ if (match)
109
+ lineNum = parseInt(match[1], 10) - 1;
110
+ consecutiveCommentedCode = 0;
111
+ continue;
112
+ }
113
+ if (line.startsWith('+') && !line.startsWith('+++')) {
114
+ lineNum++;
115
+ const content = line.slice(1);
116
+ const isCommentedCode = codePatterns.some(p => p.test(content));
117
+ if (isCommentedCode) {
118
+ if (consecutiveCommentedCode === 0)
119
+ blockStart = lineNum;
120
+ consecutiveCommentedCode++;
121
+ }
122
+ else {
123
+ if (consecutiveCommentedCode >= 3) {
124
+ comments.push({
125
+ file: filename,
126
+ line: blockStart,
127
+ severity: 'info',
128
+ message: `${consecutiveCommentedCode} lines of commented-out code.`,
129
+ suggestion: 'Remove commented-out code. Use version control to recover old code if needed.',
130
+ });
131
+ }
132
+ consecutiveCommentedCode = 0;
133
+ }
134
+ }
135
+ else if (line.startsWith(' ')) {
136
+ lineNum++;
137
+ if (consecutiveCommentedCode >= 3) {
138
+ comments.push({
139
+ file: filename,
140
+ line: blockStart,
141
+ severity: 'info',
142
+ message: `${consecutiveCommentedCode} lines of commented-out code.`,
143
+ suggestion: 'Remove commented-out code. Use version control to recover old code if needed.',
144
+ });
145
+ }
146
+ consecutiveCommentedCode = 0;
147
+ }
148
+ }
149
+ // Flush final block
150
+ if (consecutiveCommentedCode >= 3) {
151
+ comments.push({
152
+ file: filename,
153
+ line: blockStart,
154
+ severity: 'info',
155
+ message: `${consecutiveCommentedCode} lines of commented-out code.`,
156
+ suggestion: 'Remove commented-out code. Use version control to recover old code if needed.',
157
+ });
158
+ }
159
+ return comments;
160
+ }
161
+ function checkSensitiveData(lines, filename) {
162
+ const comments = [];
163
+ const sensitivePatterns = [
164
+ { pattern: /(?:password|passwd|secret|api[_-]?key|apikey|token|auth)\s*[:=]\s*['"]\w{8,}/i, message: 'Possible hardcoded credential' },
165
+ { pattern: /-----BEGIN (?:RSA |DSA |EC )?PRIVATE KEY-----/, message: 'Private key in code' },
166
+ { pattern: /\b[A-Za-z0-9+/]{40,}\b(?=\s|$|['"`;])/, message: 'Possible base64-encoded secret (long random string)' },
167
+ { pattern: /\bsk[-_](?:live|test)[-_]\w{20,}/, message: 'Possible Stripe secret key' },
168
+ { pattern: /\bghp_\w{36}\b/, message: 'Possible GitHub personal access token' },
169
+ { pattern: /\bAKIA\w{16}\b/, message: 'Possible AWS access key ID' },
170
+ ];
171
+ let lineNum = 0;
172
+ for (const line of lines) {
173
+ if (line.startsWith('@@')) {
174
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
175
+ if (match)
176
+ lineNum = parseInt(match[1], 10) - 1;
177
+ continue;
178
+ }
179
+ if (line.startsWith('+') && !line.startsWith('+++')) {
180
+ lineNum++;
181
+ const content = line.slice(1);
182
+ for (const sp of sensitivePatterns) {
183
+ if (sp.pattern.test(content)) {
184
+ comments.push({
185
+ file: filename,
186
+ line: lineNum,
187
+ severity: 'error',
188
+ message: sp.message,
189
+ suggestion: 'Move secrets to environment variables or a secrets manager. Never commit credentials.',
190
+ });
191
+ break; // One finding per line is enough
192
+ }
193
+ }
194
+ }
195
+ else if (line.startsWith(' ')) {
196
+ lineNum++;
197
+ }
198
+ }
199
+ return comments;
200
+ }
201
+ function checkImportOrdering(lines, filename) {
202
+ const comments = [];
203
+ const importLines = [];
204
+ let lineNum = 0;
205
+ for (const line of lines) {
206
+ if (line.startsWith('@@')) {
207
+ const match = line.match(/@@ -\d+(?:,\d+)? \+(\d+)/);
208
+ if (match)
209
+ lineNum = parseInt(match[1], 10) - 1;
210
+ continue;
211
+ }
212
+ if (line.startsWith('+') && !line.startsWith('+++')) {
213
+ lineNum++;
214
+ const content = line.slice(1).trim();
215
+ // JS/TS imports
216
+ const jsImport = content.match(/^import\s+.*\s+from\s+['"]([^'"]+)['"]/);
217
+ if (jsImport) {
218
+ const pkg = jsImport[1];
219
+ importLines.push({
220
+ line: lineNum,
221
+ text: content,
222
+ isThirdParty: !pkg.startsWith('.') && !pkg.startsWith('/'),
223
+ isRelative: pkg.startsWith('.'),
224
+ });
225
+ }
226
+ }
227
+ else if (line.startsWith(' ')) {
228
+ lineNum++;
229
+ }
230
+ }
231
+ // Check if third-party and relative imports are intermixed
232
+ if (importLines.length >= 2) {
233
+ let lastWasThirdParty = null;
234
+ let switchCount = 0;
235
+ for (const imp of importLines) {
236
+ if (lastWasThirdParty !== null && imp.isThirdParty !== lastWasThirdParty) {
237
+ switchCount++;
238
+ }
239
+ lastWasThirdParty = imp.isThirdParty;
240
+ }
241
+ if (switchCount > 1) {
242
+ comments.push({
243
+ file: filename,
244
+ line: importLines[0].line,
245
+ severity: 'info',
246
+ message: 'Import ordering: third-party and relative imports are intermixed.',
247
+ suggestion: 'Group imports: 1) built-in/node modules, 2) third-party packages, 3) relative imports. Separate groups with a blank line.',
248
+ });
249
+ }
250
+ }
251
+ return comments;
252
+ }
253
+ function parseDiff(diff) {
254
+ const files = [];
255
+ const parts = diff.split(/^diff --git /m);
256
+ for (const part of parts) {
257
+ if (!part.trim())
258
+ continue;
259
+ const headerMatch = part.match(/a\/(.+?)\s+b\/(.+)/);
260
+ if (!headerMatch)
261
+ continue;
262
+ const filename = headerMatch[2];
263
+ const lines = part.split('\n');
264
+ files.push({ filename, lines });
265
+ }
266
+ // If no diff headers found, treat the whole thing as a single file diff
267
+ if (files.length === 0 && diff.trim()) {
268
+ files.push({ filename: 'unknown', lines: diff.split('\n') });
269
+ }
270
+ return files;
271
+ }
272
+ function getDiffContent(input) {
273
+ if (input.diff)
274
+ return input.diff;
275
+ if (input.file_path) {
276
+ try {
277
+ // Try to get git diff for the file
278
+ const diff = execSync(`git diff HEAD -- "${input.file_path}"`, {
279
+ encoding: 'utf-8',
280
+ timeout: 10000,
281
+ });
282
+ if (diff.trim())
283
+ return diff;
284
+ // If no diff, try staged
285
+ const staged = execSync(`git diff --cached -- "${input.file_path}"`, {
286
+ encoding: 'utf-8',
287
+ timeout: 10000,
288
+ });
289
+ if (staged.trim())
290
+ return staged;
291
+ // Fall back to reading the file and creating a synthetic diff
292
+ const content = readFileSync(input.file_path, 'utf-8');
293
+ return `diff --git a/${input.file_path} b/${input.file_path}\n--- a/${input.file_path}\n+++ b/${input.file_path}\n@@ -0,0 +1,${content.split('\n').length} @@\n${content.split('\n').map(l => '+' + l).join('\n')}`;
294
+ }
295
+ catch {
296
+ throw new Error(`Cannot read diff or file at: ${input.file_path}`);
297
+ }
298
+ }
299
+ throw new Error('Provide either "diff" or "file_path".');
300
+ }
301
+ // ── Tool registration ───────────────────────────────────────────────
302
+ export function registerReviewDiff(server) {
303
+ server.tool('review_diff', 'Analyze a git diff for common issues: large files, debug statements, TODO without tickets, commented-out code, import ordering, sensitive data. Free tier — no API key needed.', {
304
+ diff: z.string().optional().describe('Raw git diff content'),
305
+ file_path: z.string().optional().describe('Path to file (will run git diff on it)'),
306
+ }, async (input) => {
307
+ const diffContent = getDiffContent(input);
308
+ const files = parseDiff(diffContent);
309
+ const allComments = [];
310
+ for (const file of files) {
311
+ allComments.push(...checkLargeFile(file.lines, file.filename));
312
+ allComments.push(...checkDebugStatements(file.lines, file.filename));
313
+ allComments.push(...checkTodoWithoutTicket(file.lines, file.filename));
314
+ allComments.push(...checkCommentedOutCode(file.lines, file.filename));
315
+ allComments.push(...checkSensitiveData(file.lines, file.filename));
316
+ allComments.push(...checkImportOrdering(file.lines, file.filename));
317
+ }
318
+ const summary = {
319
+ files_reviewed: files.length,
320
+ total_issues: allComments.length,
321
+ by_severity: {
322
+ error: allComments.filter(c => c.severity === 'error').length,
323
+ warning: allComments.filter(c => c.severity === 'warning').length,
324
+ info: allComments.filter(c => c.severity === 'info').length,
325
+ },
326
+ comments: allComments,
327
+ };
328
+ return {
329
+ content: [{ type: 'text', text: JSON.stringify(summary, null, 2) }],
330
+ };
331
+ });
332
+ }
333
+ //# sourceMappingURL=review-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-diff.js","sourceRoot":"","sources":["../../src/tools/review-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * security_review — Focused security analysis using OWASP patterns + AI (Pro tier)
3
+ */
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ export declare function registerSecurityReview(server: McpServer): void;
6
+ //# sourceMappingURL=security-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-review.d.ts","sourceRoot":"","sources":["../../src/tools/security-review.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwD9D"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * security_review — Focused security analysis using OWASP patterns + AI (Pro tier)
3
+ */
4
+ import { z } from 'zod';
5
+ import { requirePro, requireAiKey } from '../lib/license.js';
6
+ import { aiReview, SECURITY_REVIEW_SYSTEM } from '../lib/ai-review.js';
7
+ export function registerSecurityReview(server) {
8
+ server.tool('security_review', 'Focused security analysis using OWASP Top 10 patterns + AI. Identifies vulnerabilities with CWE references, attack scenarios, and specific remediation. Pro tier.', {
9
+ code: z.string().describe('Source code to review for security issues'),
10
+ language: z.string().describe('Programming language'),
11
+ }, async ({ code, language }) => {
12
+ await requirePro();
13
+ requireAiKey();
14
+ const userPrompt = [
15
+ `Language: ${language}`,
16
+ '',
17
+ 'Review this code for security vulnerabilities:',
18
+ '```',
19
+ code,
20
+ '```',
21
+ ].join('\n');
22
+ try {
23
+ const result = await aiReview(SECURITY_REVIEW_SYSTEM, userPrompt);
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(result.content);
27
+ }
28
+ catch {
29
+ parsed = { raw_review: result.content };
30
+ }
31
+ return {
32
+ content: [{
33
+ type: 'text',
34
+ text: JSON.stringify({
35
+ security_review: parsed,
36
+ meta: {
37
+ model: result.model,
38
+ provider: result.provider,
39
+ tokens: result.tokensUsed,
40
+ },
41
+ }, null, 2),
42
+ }],
43
+ };
44
+ }
45
+ catch (err) {
46
+ return {
47
+ content: [{
48
+ type: 'text',
49
+ text: JSON.stringify({
50
+ error: err instanceof Error ? err.message : String(err),
51
+ }),
52
+ }],
53
+ };
54
+ }
55
+ });
56
+ }
57
+ //# sourceMappingURL=security-review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-review.js","sourceRoot":"","sources":["../../src/tools/security-review.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,mKAAmK,EACnK;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QACtE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACtD,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,MAAM,UAAU,EAAE,CAAC;QACnB,YAAY,EAAE,CAAC;QAEf,MAAM,UAAU,GAAG;YACjB,aAAa,QAAQ,EAAE;YACvB,EAAE;YACF,gDAAgD;YAChD,KAAK;YACL,IAAI;YACJ,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAC;YAElE,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,eAAe,EAAE,MAAM;4BACvB,IAAI,EAAE;gCACJ,KAAK,EAAE,MAAM,CAAC,KAAK;gCACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gCACzB,MAAM,EAAE,MAAM,CAAC,UAAU;6BAC1B;yBACF,EAAE,IAAI,EAAE,CAAC,CAAC;qBACZ,CAAC;aACH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,CAAC;wBACR,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;yBACxD,CAAC;qBACH,CAAC;aACH,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}