@securecode-ai/mcp 0.1.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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/api/client.d.ts +22 -0
  4. package/dist/api/client.js +141 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/api/types.d.ts +129 -0
  7. package/dist/api/types.js +3 -0
  8. package/dist/api/types.js.map +1 -0
  9. package/dist/approval/auditLog.d.ts +3 -0
  10. package/dist/approval/auditLog.js +67 -0
  11. package/dist/approval/auditLog.js.map +1 -0
  12. package/dist/approval/broker.d.ts +11 -0
  13. package/dist/approval/broker.js +252 -0
  14. package/dist/approval/broker.js.map +1 -0
  15. package/dist/approval/types.d.ts +26 -0
  16. package/dist/approval/types.js +58 -0
  17. package/dist/approval/types.js.map +1 -0
  18. package/dist/attack/agentLoop.d.ts +21 -0
  19. package/dist/attack/agentLoop.js +148 -0
  20. package/dist/attack/agentLoop.js.map +1 -0
  21. package/dist/attack/executor.d.ts +17 -0
  22. package/dist/attack/executor.js +162 -0
  23. package/dist/attack/executor.js.map +1 -0
  24. package/dist/attack/policy.d.ts +26 -0
  25. package/dist/attack/policy.js +73 -0
  26. package/dist/attack/policy.js.map +1 -0
  27. package/dist/attack/protocol.d.ts +64 -0
  28. package/dist/attack/protocol.js +3 -0
  29. package/dist/attack/protocol.js.map +1 -0
  30. package/dist/attack/report.d.ts +16 -0
  31. package/dist/attack/report.js +54 -0
  32. package/dist/attack/report.js.map +1 -0
  33. package/dist/auth/credentialStore.d.ts +20 -0
  34. package/dist/auth/credentialStore.js +148 -0
  35. package/dist/auth/credentialStore.js.map +1 -0
  36. package/dist/auth/keychain.d.ts +14 -0
  37. package/dist/auth/keychain.js +267 -0
  38. package/dist/auth/keychain.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +170 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/mcp/server.d.ts +2 -0
  43. package/dist/mcp/server.js +183 -0
  44. package/dist/mcp/server.js.map +1 -0
  45. package/dist/mcp/tools.d.ts +2 -0
  46. package/dist/mcp/tools.js +120 -0
  47. package/dist/mcp/tools.js.map +1 -0
  48. package/dist/mcp/types.d.ts +26 -0
  49. package/dist/mcp/types.js +3 -0
  50. package/dist/mcp/types.js.map +1 -0
  51. package/dist/project-map/astHelpers.d.ts +89 -0
  52. package/dist/project-map/astHelpers.js +468 -0
  53. package/dist/project-map/astHelpers.js.map +1 -0
  54. package/dist/project-map/cache.d.ts +11 -0
  55. package/dist/project-map/cache.js +86 -0
  56. package/dist/project-map/cache.js.map +1 -0
  57. package/dist/project-map/confidence.d.ts +50 -0
  58. package/dist/project-map/confidence.js +87 -0
  59. package/dist/project-map/confidence.js.map +1 -0
  60. package/dist/project-map/crossFile.d.ts +73 -0
  61. package/dist/project-map/crossFile.js +33 -0
  62. package/dist/project-map/crossFile.js.map +1 -0
  63. package/dist/project-map/detectors.d.ts +83 -0
  64. package/dist/project-map/detectors.js +376 -0
  65. package/dist/project-map/detectors.js.map +1 -0
  66. package/dist/project-map/layer1.d.ts +74 -0
  67. package/dist/project-map/layer1.js +928 -0
  68. package/dist/project-map/layer1.js.map +1 -0
  69. package/dist/project-map/layer2.d.ts +30 -0
  70. package/dist/project-map/layer2.js +249 -0
  71. package/dist/project-map/layer2.js.map +1 -0
  72. package/dist/project-map/mapBuilder.d.ts +17 -0
  73. package/dist/project-map/mapBuilder.js +164 -0
  74. package/dist/project-map/mapBuilder.js.map +1 -0
  75. package/dist/project-map/parserLoader.d.ts +61 -0
  76. package/dist/project-map/parserLoader.js +175 -0
  77. package/dist/project-map/parserLoader.js.map +1 -0
  78. package/dist/project-map/schemas.d.ts +28 -0
  79. package/dist/project-map/schemas.js +131 -0
  80. package/dist/project-map/schemas.js.map +1 -0
  81. package/dist/project-map/types.d.ts +232 -0
  82. package/dist/project-map/types.js +61 -0
  83. package/dist/project-map/types.js.map +1 -0
  84. package/dist/tools/attack.d.ts +2 -0
  85. package/dist/tools/attack.js +80 -0
  86. package/dist/tools/attack.js.map +1 -0
  87. package/dist/tools/fix.d.ts +2 -0
  88. package/dist/tools/fix.js +60 -0
  89. package/dist/tools/fix.js.map +1 -0
  90. package/dist/tools/map.d.ts +2 -0
  91. package/dist/tools/map.js +46 -0
  92. package/dist/tools/map.js.map +1 -0
  93. package/dist/tools/scan.d.ts +2 -0
  94. package/dist/tools/scan.js +55 -0
  95. package/dist/tools/scan.js.map +1 -0
  96. package/dist/utils/files.d.ts +8 -0
  97. package/dist/utils/files.js +79 -0
  98. package/dist/utils/files.js.map +1 -0
  99. package/package.json +53 -0
  100. package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
  101. package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
  102. package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
  103. package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolAttack = toolAttack;
4
+ const broker_1 = require("../approval/broker");
5
+ const agentLoop_1 = require("../attack/agentLoop");
6
+ const cache_1 = require("../project-map/cache");
7
+ const files_1 = require("../utils/files");
8
+ async function toolAttack(ctx, args) {
9
+ let code = args.code;
10
+ let language = args.language;
11
+ const filePath = args.filePath;
12
+ if (!code && filePath) {
13
+ const file = (0, files_1.readFileFromWorkspace)(ctx.workspaceRoot, filePath);
14
+ code = file.code;
15
+ language = language || file.language;
16
+ }
17
+ if (!code) {
18
+ return {
19
+ applied: false,
20
+ note: 'Provide code or filePath for the endpoint to attack.',
21
+ };
22
+ }
23
+ if (!language) {
24
+ return {
25
+ applied: false,
26
+ note: 'Could not determine language. Provide language or filePath with a known extension.',
27
+ };
28
+ }
29
+ const map = (0, cache_1.readCache)(ctx.workspaceRoot);
30
+ if (!map || !map.endpoints || map.endpoints.length === 0) {
31
+ return {
32
+ applied: false,
33
+ note: 'No Project Map found or no endpoints mapped. Run securecode.map with action "build" first.',
34
+ };
35
+ }
36
+ let endpoint;
37
+ if (filePath) {
38
+ const relPath = filePath.replace(/\\/g, '/').replace(/^\.\//, '');
39
+ endpoint = map.endpoints.find((e) => {
40
+ const sf = (e.sourceFile || '').replace(/\\/g, '/');
41
+ return sf === relPath || sf.endsWith('/' + relPath) || sf.endsWith(relPath);
42
+ });
43
+ }
44
+ if (!endpoint) {
45
+ endpoint = map.endpoints[0];
46
+ }
47
+ const port = args.port || args.targetPort || 3000;
48
+ const targetHost = args.targetHost || '127.0.0.1';
49
+ const summary = `Attack endpoint ${endpoint.method} ${endpoint.path} from ${endpoint.sourceFile}\n` +
50
+ `Target: ${targetHost}:${port}\n` +
51
+ `Vulnerability: ${args.vulnerabilityType || '(auto-detected)'}\n` +
52
+ `Budget: max ${12} steps, 90s wall clock`;
53
+ const broker = new broker_1.ApprovalBroker();
54
+ await broker.start();
55
+ try {
56
+ const result = await broker.requestApproval('securecode.attack', summary, [endpoint.path, targetHost, port, code, args.vulnerabilityType], 60_000);
57
+ if (!result.approved) {
58
+ return {
59
+ applied: false,
60
+ reason: result.reason,
61
+ requestId: result.requestId,
62
+ };
63
+ }
64
+ const attackResult = await (0, agentLoop_1.runAttack)(ctx, { method: endpoint.method, path: endpoint.path, sourceFile: endpoint.sourceFile, handlerName: endpoint.handlerName }, code, language, {
65
+ targetPort: port,
66
+ targetHost,
67
+ signal: undefined,
68
+ });
69
+ return {
70
+ applied: true,
71
+ status: attackResult.status,
72
+ report: attackResult.report,
73
+ error: attackResult.error,
74
+ };
75
+ }
76
+ finally {
77
+ await broker.stop();
78
+ }
79
+ }
80
+ //# sourceMappingURL=attack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attack.js","sourceRoot":"","sources":["../../src/tools/attack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ServerContext } from '../mcp/types';
2
+ export declare function toolFix(ctx: ServerContext, args: any): Promise<unknown>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolFix = toolFix;
4
+ const client_1 = require("../api/client");
5
+ const files_1 = require("../utils/files");
6
+ const broker_1 = require("../approval/broker");
7
+ async function toolFix(ctx, args) {
8
+ const client = new client_1.ApiClient({ baseUrl: ctx.apiUrl, token: ctx.apiToken });
9
+ let code = args.code;
10
+ const language = args.language;
11
+ if (!code && args.filePath) {
12
+ const file = (0, files_1.readFileFromWorkspace)(ctx.workspaceRoot, args.filePath);
13
+ code = file.code;
14
+ }
15
+ if (!code) {
16
+ throw Object.assign(new Error('Provide code or filePath.'), { code: -32602 });
17
+ }
18
+ const summary = `Fix ${args.vulnerabilityType} at line ${args.lineStart}-${args.lineEnd}\n\nEvidence: ${args.evidenceSnippet?.substring(0, 200) || '(not provided)'}`;
19
+ const broker = new broker_1.ApprovalBroker();
20
+ await broker.start();
21
+ try {
22
+ const result = await broker.requestApproval('securecode.fix', summary, [code, language, args.vulnerabilityType, args.lineStart, args.lineEnd, args.evidenceSnippet], 60_000);
23
+ if (!result.approved) {
24
+ return {
25
+ applied: false,
26
+ reason: result.reason,
27
+ requestId: result.requestId,
28
+ };
29
+ }
30
+ const data = await client.postJson('/fix', {
31
+ code,
32
+ language,
33
+ vulnerability: {
34
+ type: args.vulnerabilityType,
35
+ line_start: args.lineStart,
36
+ line_end: args.lineEnd,
37
+ evidence_snippet: args.evidenceSnippet,
38
+ },
39
+ ...(args.framework ? { framework: args.framework } : {}),
40
+ });
41
+ return {
42
+ applied: false,
43
+ fix: {
44
+ fixedCode: data.fixed_code,
45
+ diff: data.diff,
46
+ summary: data.fix_summary,
47
+ securityNotes: data.security_notes,
48
+ whySecure: data.why_secure,
49
+ importsNeeded: data.imports_needed,
50
+ confidence: data.confidence,
51
+ },
52
+ note: 'Patch returned for human review. Apply in your editor — do not auto-apply.',
53
+ approvedBy: result.requestId,
54
+ };
55
+ }
56
+ finally {
57
+ await broker.stop();
58
+ }
59
+ }
60
+ //# sourceMappingURL=fix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.js","sourceRoot":"","sources":["../../src/tools/fix.ts"],"names":[],"mappings":";;AAMA,0BAiEC;AAvED,0CAA0C;AAG1C,0CAAuD;AACvD,+CAAoD;AAE7C,KAAK,UAAU,OAAO,CAAC,GAAkB,EAAE,IAAS;IACvD,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE3E,IAAI,IAAI,GAAW,IAAI,CAAC,IAAI,CAAC;IAC7B,MAAM,QAAQ,GAAW,IAAI,CAAC,QAAQ,CAAC;IAEvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAA,6BAAqB,EAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,iBAAiB,YAAY,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,iBAAiB,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,gBAAgB,EAAE,CAAC;IAEtK,MAAM,MAAM,GAAG,IAAI,uBAAc,EAAE,CAAC;IACpC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CACvC,gBAAgB,EAChB,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,EAC5F,MAAM,CACT,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,SAAS,EAAE,MAAM,CAAC,SAAS;aAC9B,CAAC;QACN,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAc,MAAM,EAAE;YACpD,IAAI;YACJ,QAAQ;YACR,aAAa,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,iBAAiB;gBAC5B,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,QAAQ,EAAE,IAAI,CAAC,OAAO;gBACtB,gBAAgB,EAAE,IAAI,CAAC,eAAe;aACzC;YACD,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CAAC,CAAC;QAEH,OAAO;YACH,OAAO,EAAE,KAAK;YACd,GAAG,EAAE;gBACD,SAAS,EAAE,IAAI,CAAC,UAAU;gBAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,WAAW;gBACzB,aAAa,EAAE,IAAI,CAAC,cAAc;gBAClC,SAAS,EAAE,IAAI,CAAC,UAAU;gBAC1B,aAAa,EAAE,IAAI,CAAC,cAAc;gBAClC,UAAU,EAAE,IAAI,CAAC,UAAU;aAC9B;YACD,IAAI,EAAE,4EAA4E;YAClF,UAAU,EAAE,MAAM,CAAC,SAAS;SAC/B,CAAC;IACN,CAAC;YAAS,CAAC;QACP,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ServerContext } from '../mcp/types';
2
+ export declare function toolMap(ctx: ServerContext, args: any): Promise<unknown>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolMap = toolMap;
4
+ const cache_1 = require("../project-map/cache");
5
+ const mapBuilder_1 = require("../project-map/mapBuilder");
6
+ async function toolMap(ctx, args) {
7
+ const action = args.action || 'endpoints';
8
+ if (action === 'build') {
9
+ const result = await (0, mapBuilder_1.buildProjectMap)({ workspaceRoot: ctx.workspaceRoot });
10
+ (0, cache_1.writeCache)(ctx.workspaceRoot, result.map);
11
+ return {
12
+ built: true,
13
+ endpoints: (result.map.endpoints || []).length,
14
+ filesProcessed: result.filesProcessed,
15
+ filesSkipped: result.filesSkipped,
16
+ errors: result.errors,
17
+ durationMs: result.durationMs,
18
+ builtAt: result.map.builtAt,
19
+ };
20
+ }
21
+ if (action === 'status') {
22
+ return (0, cache_1.cacheStatus)(ctx.workspaceRoot);
23
+ }
24
+ // Default: return endpoints (read from cache, or build if no cache)
25
+ let map = (0, cache_1.readCache)(ctx.workspaceRoot);
26
+ if (!map) {
27
+ const result = await (0, mapBuilder_1.buildProjectMap)({ workspaceRoot: ctx.workspaceRoot });
28
+ (0, cache_1.writeCache)(ctx.workspaceRoot, result.map);
29
+ map = result.map;
30
+ }
31
+ return {
32
+ endpoints: (map.endpoints || []).map((e) => ({
33
+ method: e.method,
34
+ path: e.path,
35
+ handler: e.handlerName,
36
+ sourceFile: e.sourceFile,
37
+ line: e.line,
38
+ authScheme: e.authScheme,
39
+ dataLayer: e.dataLayer,
40
+ confidence: e.confidence,
41
+ })),
42
+ builtAt: map.builtAt,
43
+ version: map.version,
44
+ };
45
+ }
46
+ //# sourceMappingURL=map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/tools/map.ts"],"names":[],"mappings":";;AAMA,0BA2CC;AA9CD,gDAA0E;AAC1E,0DAA4D;AAErD,KAAK,UAAU,OAAO,CAAC,GAAkB,EAAE,IAAS;IACvD,MAAM,MAAM,GAAI,IAAI,CAAC,MAAiB,IAAI,WAAW,CAAC;IAEtD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAe,EAAC,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;QAC3E,IAAA,kBAAU,EAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1C,OAAO;YACH,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM;YAC9C,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO;SAC9B,CAAC;IACN,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,IAAA,mBAAW,EAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAED,oEAAoE;IACpE,IAAI,GAAG,GAAG,IAAA,iBAAS,EAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAe,EAAC,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;QAC3E,IAAA,kBAAU,EAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1C,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACrB,CAAC;IAED,OAAO;QACH,SAAS,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzC,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,WAAW;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;SAC3B,CAAC,CAAC;QACH,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,OAAO,EAAE,GAAG,CAAC,OAAO;KACvB,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ServerContext } from '../mcp/types';
2
+ export declare function toolScan(ctx: ServerContext, args: any): Promise<unknown>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolScan = toolScan;
4
+ const client_1 = require("../api/client");
5
+ const files_1 = require("../utils/files");
6
+ async function toolScan(ctx, args) {
7
+ const client = new client_1.ApiClient({ baseUrl: ctx.apiUrl, token: ctx.apiToken });
8
+ let code = args.code;
9
+ let language = args.language;
10
+ const filePath = args.filePath;
11
+ if (!code && filePath) {
12
+ const file = (0, files_1.readFileFromWorkspace)(ctx.workspaceRoot, filePath);
13
+ code = file.code;
14
+ language = language || file.language;
15
+ }
16
+ if (!code) {
17
+ throw Object.assign(new Error('Provide code or filePath.'), { code: -32602 });
18
+ }
19
+ if (!language) {
20
+ throw Object.assign(new Error('Provide language or filePath with a known extension.'), { code: -32602 });
21
+ }
22
+ const data = await client.postJson('/scan', {
23
+ code,
24
+ language,
25
+ ...(filePath ? { filePath } : {}),
26
+ scanDepth: 'auto',
27
+ });
28
+ const findings = data.scanType === 'advanced' && data.finalFindings
29
+ ? data.finalFindings
30
+ : data.findings || [];
31
+ return {
32
+ scanType: data.scanType,
33
+ scanId: data.scanId,
34
+ findings: findings.map((f) => ({
35
+ type: f.type || f.check_id,
36
+ severity: f.severity || f.extra?.severity,
37
+ location: f.location || {
38
+ line_start: f.start?.line,
39
+ line_end: f.end?.line ?? f.start?.line,
40
+ },
41
+ message: f.message || f.extra?.message,
42
+ evidence: f.evidence_snippet,
43
+ confidence: f.confidence,
44
+ why: f.why_real,
45
+ fixStrategy: f.fix_strategy,
46
+ fixSnippet: f.fix_snippet,
47
+ })),
48
+ scanSummary: data.scanSummary,
49
+ degraded: data.degraded,
50
+ remainingScans: data.remainingAIScans,
51
+ plan: data.plan,
52
+ scanCredits: data.scanCredits,
53
+ };
54
+ }
55
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/tools/scan.ts"],"names":[],"mappings":";;AAOA,4BAuDC;AA5DD,0CAA0C;AAG1C,0CAAsE;AAE/D,KAAK,UAAU,QAAQ,CAAC,GAAkB,EAAE,IAAS;IACxD,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE3E,IAAI,IAAI,GAAuB,IAAI,CAAC,IAAI,CAAC;IACzC,IAAI,QAAQ,GAAuB,IAAI,CAAC,QAAQ,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA8B,CAAC;IAErD,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,IAAA,6BAAqB,EAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAChE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACjB,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sDAAsD,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7G,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAe,OAAO,EAAE;QACtD,IAAI;QACJ,QAAQ;QACR,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,SAAS,EAAE,MAAM;KACpB,CAAC,CAAC;IAEH,MAAM,QAAQ,GACV,IAAI,CAAC,QAAQ,KAAK,UAAU,IAAI,IAAI,CAAC,aAAa;QAC9C,CAAC,CAAC,IAAI,CAAC,aAAa;QACpB,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAE9B,OAAO;QACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ;YACzC,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI;gBACpB,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI;gBACzB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI;aACzC;YACD,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO;YACtC,QAAQ,EAAE,CAAC,CAAC,gBAAgB;YAC5B,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,GAAG,EAAE,CAAC,CAAC,QAAQ;YACf,WAAW,EAAE,CAAC,CAAC,YAAY;YAC3B,UAAU,EAAE,CAAC,CAAC,WAAW;SAC5B,CAAC,CAAC;QACH,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,cAAc,EAAE,IAAI,CAAC,gBAAgB;QACrC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;KAChC,CAAC;AACN,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function inferLanguage(filePath: string): string | undefined;
2
+ export declare function isSupportedFile(filePath: string): boolean;
3
+ export declare function resolveWorkspacePath(workspaceRoot: string, inputPath: string): string;
4
+ export declare function readFileFromWorkspace(workspaceRoot: string, inputPath: string): {
5
+ code: string;
6
+ language: string;
7
+ absolutePath: string;
8
+ };
@@ -0,0 +1,79 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.inferLanguage = inferLanguage;
37
+ exports.isSupportedFile = isSupportedFile;
38
+ exports.resolveWorkspacePath = resolveWorkspacePath;
39
+ exports.readFileFromWorkspace = readFileFromWorkspace;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const SUPPORTED_EXTENSIONS = {
43
+ '.js': 'javascript',
44
+ '.mjs': 'javascript',
45
+ '.cjs': 'javascript',
46
+ '.jsx': 'javascriptreact',
47
+ '.ts': 'typescript',
48
+ '.tsx': 'typescriptreact',
49
+ '.py': 'python',
50
+ '.php': 'php',
51
+ };
52
+ function inferLanguage(filePath) {
53
+ const ext = path.extname(filePath).toLowerCase();
54
+ return SUPPORTED_EXTENSIONS[ext];
55
+ }
56
+ function isSupportedFile(filePath) {
57
+ return inferLanguage(filePath) !== undefined;
58
+ }
59
+ function resolveWorkspacePath(workspaceRoot, inputPath) {
60
+ const resolved = path.resolve(workspaceRoot, inputPath);
61
+ const normalizedRoot = path.resolve(workspaceRoot);
62
+ if (!resolved.startsWith(normalizedRoot + path.sep) && resolved !== normalizedRoot) {
63
+ throw new Error(`Path '${inputPath}' is outside the workspace root. Only files within the workspace can be read.`);
64
+ }
65
+ return resolved;
66
+ }
67
+ function readFileFromWorkspace(workspaceRoot, inputPath) {
68
+ const absPath = resolveWorkspacePath(workspaceRoot, inputPath);
69
+ if (!fs.existsSync(absPath)) {
70
+ throw new Error(`File not found: ${inputPath}`);
71
+ }
72
+ const code = fs.readFileSync(absPath, 'utf8');
73
+ const language = inferLanguage(absPath);
74
+ if (!language) {
75
+ throw new Error(`Unsupported file type: ${path.extname(inputPath)}`);
76
+ }
77
+ return { code, language, absolutePath: absPath };
78
+ }
79
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,sCAGC;AAED,0CAEC;AAED,oDAOC;AAED,sDAWC;AA3CD,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,oBAAoB,GAA2B;IACjD,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,KAAK;CAChB,CAAC;AAEF,SAAgB,aAAa,CAAC,QAAgB;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,OAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,eAAe,CAAC,QAAgB;IAC5C,OAAO,aAAa,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC;AACjD,CAAC;AAED,SAAgB,oBAAoB,CAAC,aAAqB,EAAE,SAAiB;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,SAAS,SAAS,+EAA+E,CAAC,CAAC;IACvH,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,SAAgB,qBAAqB,CAAC,aAAqB,EAAE,SAAiB;IAC1E,MAAM,OAAO,GAAG,oBAAoB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC/D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,mBAAmB,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@securecode-ai/mcp",
3
+ "version": "0.1.0",
4
+ "description": "Standalone SecureCode MCP server — scan, map, fix, and attack tools for AI coding assistants. Works without the VS Code extension.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "securecode-mcp": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc -p ./",
11
+ "start": "node dist/index.js serve",
12
+ "test": "vitest run",
13
+ "test:watch": "vitest",
14
+ "typecheck": "tsc --noEmit",
15
+ "prepublishOnly": "npm run build && npm test"
16
+ },
17
+ "files": [
18
+ "dist/",
19
+ "resources/tree-sitter/"
20
+ ],
21
+ "keywords": [
22
+ "mcp",
23
+ "security",
24
+ "scanner",
25
+ "vulnerability",
26
+ "ai",
27
+ "code-analysis",
28
+ "securecode"
29
+ ],
30
+ "license": "MIT",
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/AhmedSleem06/SecureCode-mcp.git"
37
+ },
38
+ "homepage": "https://usesecurecode.tech",
39
+ "bugs": {
40
+ "url": "https://github.com/AhmedSleem06/SecureCode-mcp/issues"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "dependencies": {
46
+ "web-tree-sitter": "0.26.11"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^20.10.0",
50
+ "typescript": "^5.3.2",
51
+ "vitest": "^2.1.0"
52
+ }
53
+ }