@ia-qa/qa-discovery 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 (84) hide show
  1. package/README.md +378 -0
  2. package/ROADMAP.md +321 -0
  3. package/dist/ai/classify.d.ts +170 -0
  4. package/dist/ai/classify.js +431 -0
  5. package/dist/ai/classify.js.map +1 -0
  6. package/dist/browser/extractPage.d.ts +41 -0
  7. package/dist/browser/extractPage.js +427 -0
  8. package/dist/browser/extractPage.js.map +1 -0
  9. package/dist/browser/openables.d.ts +19 -0
  10. package/dist/browser/openables.js +127 -0
  11. package/dist/browser/openables.js.map +1 -0
  12. package/dist/capture/page.d.ts +128 -0
  13. package/dist/capture/page.js +78 -0
  14. package/dist/capture/page.js.map +1 -0
  15. package/dist/citations.d.ts +80 -0
  16. package/dist/citations.js +197 -0
  17. package/dist/citations.js.map +1 -0
  18. package/dist/classificationView.d.ts +118 -0
  19. package/dist/classificationView.js +178 -0
  20. package/dist/classificationView.js.map +1 -0
  21. package/dist/cli/args.d.ts +3 -0
  22. package/dist/cli/args.js +38 -0
  23. package/dist/cli/args.js.map +1 -0
  24. package/dist/cli/history.d.ts +1 -0
  25. package/dist/cli/history.js +35 -0
  26. package/dist/cli/history.js.map +1 -0
  27. package/dist/cli/index.d.ts +5 -0
  28. package/dist/cli/index.js +172 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/cli/login.d.ts +29 -0
  31. package/dist/cli/login.js +179 -0
  32. package/dist/cli/login.js.map +1 -0
  33. package/dist/cli/scan.d.ts +11 -0
  34. package/dist/cli/scan.js +246 -0
  35. package/dist/cli/scan.js.map +1 -0
  36. package/dist/cli-ai/index.d.ts +7 -0
  37. package/dist/cli-ai/index.js +360 -0
  38. package/dist/cli-ai/index.js.map +1 -0
  39. package/dist/config.d.ts +112 -0
  40. package/dist/config.js +178 -0
  41. package/dist/config.js.map +1 -0
  42. package/dist/diff.d.ts +12 -0
  43. package/dist/diff.js +43 -0
  44. package/dist/diff.js.map +1 -0
  45. package/dist/explore.d.ts +59 -0
  46. package/dist/explore.js +119 -0
  47. package/dist/explore.js.map +1 -0
  48. package/dist/healingLink.d.ts +30 -0
  49. package/dist/healingLink.js +127 -0
  50. package/dist/healingLink.js.map +1 -0
  51. package/dist/history.d.ts +38 -0
  52. package/dist/history.js +120 -0
  53. package/dist/history.js.map +1 -0
  54. package/dist/htmlReport.d.ts +2 -0
  55. package/dist/htmlReport.js +371 -0
  56. package/dist/htmlReport.js.map +1 -0
  57. package/dist/index.d.ts +24 -0
  58. package/dist/index.js +65 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/mcp/sandbox.d.ts +9 -0
  61. package/dist/mcp/sandbox.js +82 -0
  62. package/dist/mcp/sandbox.js.map +1 -0
  63. package/dist/mcp/server.d.ts +120 -0
  64. package/dist/mcp/server.js +315 -0
  65. package/dist/mcp/server.js.map +1 -0
  66. package/dist/network.d.ts +60 -0
  67. package/dist/network.js +99 -0
  68. package/dist/network.js.map +1 -0
  69. package/dist/overview.d.ts +40 -0
  70. package/dist/overview.js +370 -0
  71. package/dist/overview.js.map +1 -0
  72. package/dist/overviewFile.d.ts +31 -0
  73. package/dist/overviewFile.js +101 -0
  74. package/dist/overviewFile.js.map +1 -0
  75. package/dist/scan.d.ts +159 -0
  76. package/dist/scan.js +402 -0
  77. package/dist/scan.js.map +1 -0
  78. package/dist/sharedCalls.d.ts +28 -0
  79. package/dist/sharedCalls.js +61 -0
  80. package/dist/sharedCalls.js.map +1 -0
  81. package/dist/taxonomy.d.ts +77 -0
  82. package/dist/taxonomy.js +153 -0
  83. package/dist/taxonomy.js.map +1 -0
  84. package/package.json +61 -0
package/dist/index.js ADDED
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collect = exports.validate = exports.parseClassifications = exports.buildPrompt = exports.entryPointsOf = exports.classifyPage = exports.taxonomyForPrompt = exports.securityToolsFor = exports.isSensitivity = exports.isIntent = exports.TAXONOMY_VERSION = exports.UNKNOWN_INTENT = exports.SENSITIVITY_IDS = exports.INTENT_IDS = exports.SENSITIVITIES = exports.INTENTS = exports.SHARED_REF = exports.loadCaptureIndex = exports.verifyClaim = exports.verifyCitation = exports.DEFAULT_SAFE_QUERY_PARAMS = exports.apiCallFingerprint = exports.normalizeApiUrl = exports.SESSION_FILENAME = exports.CONFIG_DIR = exports.resolveSession = exports.sessionTarget = exports.sessionPath = exports.configPath = exports.captureDir = exports.setBaseDir = exports.baseDir = exports.configExists = exports.saveConfig = exports.loadConfig = exports.renderScanReport = exports.OVERVIEW_FILENAME = exports.renderOverview = exports.compareCaptures = exports.SHARED_CALLS_SCHEMA = exports.PAGE_CAPTURE_SCHEMA = exports.capturePage = exports.HISTORY_LIMIT = exports.historyPath = exports.appendHistory = exports.readHistory = exports.SURFACE_SCHEMA = exports.scanApp = void 0;
4
+ var scan_1 = require("./scan");
5
+ Object.defineProperty(exports, "scanApp", { enumerable: true, get: function () { return scan_1.scanApp; } });
6
+ var scan_2 = require("./scan");
7
+ Object.defineProperty(exports, "SURFACE_SCHEMA", { enumerable: true, get: function () { return scan_2.SURFACE_SCHEMA; } });
8
+ var history_1 = require("./history");
9
+ Object.defineProperty(exports, "readHistory", { enumerable: true, get: function () { return history_1.readHistory; } });
10
+ Object.defineProperty(exports, "appendHistory", { enumerable: true, get: function () { return history_1.appendHistory; } });
11
+ Object.defineProperty(exports, "historyPath", { enumerable: true, get: function () { return history_1.historyPath; } });
12
+ Object.defineProperty(exports, "HISTORY_LIMIT", { enumerable: true, get: function () { return history_1.HISTORY_LIMIT; } });
13
+ var page_1 = require("./capture/page");
14
+ Object.defineProperty(exports, "capturePage", { enumerable: true, get: function () { return page_1.capturePage; } });
15
+ Object.defineProperty(exports, "PAGE_CAPTURE_SCHEMA", { enumerable: true, get: function () { return page_1.PAGE_CAPTURE_SCHEMA; } });
16
+ var sharedCalls_1 = require("./sharedCalls");
17
+ Object.defineProperty(exports, "SHARED_CALLS_SCHEMA", { enumerable: true, get: function () { return sharedCalls_1.SHARED_CALLS_SCHEMA; } });
18
+ var diff_1 = require("./diff");
19
+ Object.defineProperty(exports, "compareCaptures", { enumerable: true, get: function () { return diff_1.compareCaptures; } });
20
+ var overview_1 = require("./overview");
21
+ Object.defineProperty(exports, "renderOverview", { enumerable: true, get: function () { return overview_1.renderOverview; } });
22
+ Object.defineProperty(exports, "OVERVIEW_FILENAME", { enumerable: true, get: function () { return overview_1.OVERVIEW_FILENAME; } });
23
+ var htmlReport_1 = require("./htmlReport");
24
+ Object.defineProperty(exports, "renderScanReport", { enumerable: true, get: function () { return htmlReport_1.renderScanReport; } });
25
+ var config_1 = require("./config");
26
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
27
+ Object.defineProperty(exports, "saveConfig", { enumerable: true, get: function () { return config_1.saveConfig; } });
28
+ Object.defineProperty(exports, "configExists", { enumerable: true, get: function () { return config_1.configExists; } });
29
+ Object.defineProperty(exports, "baseDir", { enumerable: true, get: function () { return config_1.baseDir; } });
30
+ Object.defineProperty(exports, "setBaseDir", { enumerable: true, get: function () { return config_1.setBaseDir; } });
31
+ Object.defineProperty(exports, "captureDir", { enumerable: true, get: function () { return config_1.captureDir; } });
32
+ Object.defineProperty(exports, "configPath", { enumerable: true, get: function () { return config_1.configPath; } });
33
+ Object.defineProperty(exports, "sessionPath", { enumerable: true, get: function () { return config_1.sessionPath; } });
34
+ Object.defineProperty(exports, "sessionTarget", { enumerable: true, get: function () { return config_1.sessionTarget; } });
35
+ Object.defineProperty(exports, "resolveSession", { enumerable: true, get: function () { return config_1.resolveSession; } });
36
+ Object.defineProperty(exports, "CONFIG_DIR", { enumerable: true, get: function () { return config_1.CONFIG_DIR; } });
37
+ Object.defineProperty(exports, "SESSION_FILENAME", { enumerable: true, get: function () { return config_1.SESSION_FILENAME; } });
38
+ var network_1 = require("./network");
39
+ Object.defineProperty(exports, "normalizeApiUrl", { enumerable: true, get: function () { return network_1.normalizeApiUrl; } });
40
+ Object.defineProperty(exports, "apiCallFingerprint", { enumerable: true, get: function () { return network_1.apiCallFingerprint; } });
41
+ Object.defineProperty(exports, "DEFAULT_SAFE_QUERY_PARAMS", { enumerable: true, get: function () { return network_1.DEFAULT_SAFE_QUERY_PARAMS; } });
42
+ var citations_1 = require("./citations");
43
+ Object.defineProperty(exports, "verifyCitation", { enumerable: true, get: function () { return citations_1.verifyCitation; } });
44
+ Object.defineProperty(exports, "verifyClaim", { enumerable: true, get: function () { return citations_1.verifyClaim; } });
45
+ Object.defineProperty(exports, "loadCaptureIndex", { enumerable: true, get: function () { return citations_1.loadCaptureIndex; } });
46
+ Object.defineProperty(exports, "SHARED_REF", { enumerable: true, get: function () { return citations_1.SHARED_REF; } });
47
+ var taxonomy_1 = require("./taxonomy");
48
+ Object.defineProperty(exports, "INTENTS", { enumerable: true, get: function () { return taxonomy_1.INTENTS; } });
49
+ Object.defineProperty(exports, "SENSITIVITIES", { enumerable: true, get: function () { return taxonomy_1.SENSITIVITIES; } });
50
+ Object.defineProperty(exports, "INTENT_IDS", { enumerable: true, get: function () { return taxonomy_1.INTENT_IDS; } });
51
+ Object.defineProperty(exports, "SENSITIVITY_IDS", { enumerable: true, get: function () { return taxonomy_1.SENSITIVITY_IDS; } });
52
+ Object.defineProperty(exports, "UNKNOWN_INTENT", { enumerable: true, get: function () { return taxonomy_1.UNKNOWN_INTENT; } });
53
+ Object.defineProperty(exports, "TAXONOMY_VERSION", { enumerable: true, get: function () { return taxonomy_1.TAXONOMY_VERSION; } });
54
+ Object.defineProperty(exports, "isIntent", { enumerable: true, get: function () { return taxonomy_1.isIntent; } });
55
+ Object.defineProperty(exports, "isSensitivity", { enumerable: true, get: function () { return taxonomy_1.isSensitivity; } });
56
+ Object.defineProperty(exports, "securityToolsFor", { enumerable: true, get: function () { return taxonomy_1.securityToolsFor; } });
57
+ Object.defineProperty(exports, "taxonomyForPrompt", { enumerable: true, get: function () { return taxonomy_1.taxonomyForPrompt; } });
58
+ var classify_1 = require("./ai/classify");
59
+ Object.defineProperty(exports, "classifyPage", { enumerable: true, get: function () { return classify_1.classifyPage; } });
60
+ Object.defineProperty(exports, "entryPointsOf", { enumerable: true, get: function () { return classify_1.entryPointsOf; } });
61
+ Object.defineProperty(exports, "buildPrompt", { enumerable: true, get: function () { return classify_1.buildPrompt; } });
62
+ Object.defineProperty(exports, "parseClassifications", { enumerable: true, get: function () { return classify_1.parseClassifications; } });
63
+ Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return classify_1.validate; } });
64
+ Object.defineProperty(exports, "collect", { enumerable: true, get: function () { return classify_1.collect; } });
65
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+BAAiC;AAAxB,+FAAA,OAAO,OAAA;AAEhB,+BAAwC;AAA/B,sGAAA,cAAc,OAAA;AAEvB,qCAAmF;AAA1E,sGAAA,WAAW,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,wGAAA,aAAa,OAAA;AAG/D,uCAAkE;AAAzD,mGAAA,WAAW,OAAA;AAAE,2GAAA,mBAAmB,OAAA;AAGzC,6CAAoD;AAA3C,kHAAA,mBAAmB,OAAA;AAG5B,+BAAyC;AAAhC,uGAAA,eAAe,OAAA;AAGxB,uCAA+D;AAAtD,0GAAA,cAAc,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AAE1C,2CAAgD;AAAvC,8GAAA,gBAAgB,OAAA;AAEzB,mCAakB;AAZhB,oGAAA,UAAU,OAAA;AACV,oGAAA,UAAU,OAAA;AACV,sGAAA,YAAY,OAAA;AACZ,iGAAA,OAAO,OAAA;AACP,oGAAA,UAAU,OAAA;AACV,oGAAA,UAAU,OAAA;AACV,oGAAA,UAAU,OAAA;AACV,qGAAA,WAAW,OAAA;AACX,uGAAA,aAAa,OAAA;AACb,wGAAA,cAAc,OAAA;AACd,oGAAA,UAAU,OAAA;AACV,0GAAA,gBAAgB,OAAA;AAIlB,qCAA2F;AAAlF,0GAAA,eAAe,OAAA;AAAE,6GAAA,kBAAkB,OAAA;AAAE,oHAAA,yBAAyB,OAAA;AAGvE,yCAAwF;AAA/E,2GAAA,cAAc,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,uGAAA,UAAU,OAAA;AAGlE,uCAAiL;AAAxK,mGAAA,OAAO,OAAA;AAAE,yGAAA,aAAa,OAAA;AAAE,sGAAA,UAAU,OAAA;AAAE,2GAAA,eAAe,OAAA;AAAE,0GAAA,cAAc,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,oGAAA,QAAQ,OAAA;AAAE,yGAAA,aAAa,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,6GAAA,iBAAiB,OAAA;AAG5J,0CAAkH;AAAzG,wGAAA,YAAY,OAAA;AAAE,yGAAA,aAAa,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,gHAAA,oBAAoB,OAAA;AAAE,oGAAA,QAAQ,OAAA;AAAE,mGAAA,OAAO,OAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Refuse any path that resolves outside the project root, and any URL that
3
+ * isn't same-origin with the configured baseUrl. Mirrors
4
+ * `@ia-qa/self-healing`'s `mcp/sandbox.ts`: MCP arguments come from an agent,
5
+ * potentially steered by third-party content (prompt injection), unlike a CLI
6
+ * typed by a human in their own shell.
7
+ */
8
+ export declare function assertInsideProject(candidate: string, label: string, root?: string): string;
9
+ export declare function assertUrlAllowed(url: string, baseUrl?: string): void;
@@ -0,0 +1,82 @@
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.assertInsideProject = assertInsideProject;
37
+ exports.assertUrlAllowed = assertUrlAllowed;
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Refuse any path that resolves outside the project root, and any URL that
41
+ * isn't same-origin with the configured baseUrl. Mirrors
42
+ * `@ia-qa/self-healing`'s `mcp/sandbox.ts`: MCP arguments come from an agent,
43
+ * potentially steered by third-party content (prompt injection), unlike a CLI
44
+ * typed by a human in their own shell.
45
+ */
46
+ function assertInsideProject(candidate, label, root = process.cwd()) {
47
+ if (process.env.IAQA_ALLOW_OUTSIDE_PATHS === '1') {
48
+ return path.resolve(root, candidate);
49
+ }
50
+ const resolved = path.resolve(root, candidate);
51
+ const rootWithSep = root.endsWith(path.sep) ? root : root + path.sep;
52
+ if (resolved !== root && !resolved.startsWith(rootWithSep)) {
53
+ throw new Error(`${label} "${candidate}" resolves to "${resolved}", outside the project root "${root}". ` +
54
+ `Refusing for safety — an MCP tool call can originate from agent-interpreted content, not just ` +
55
+ `a trusted human shell. Set IAQA_ALLOW_OUTSIDE_PATHS=1 to override if this is intentional.`);
56
+ }
57
+ return resolved;
58
+ }
59
+ function assertUrlAllowed(url, baseUrl) {
60
+ if (process.env.IAQA_ALLOW_ANY_URL === '1' || !baseUrl)
61
+ return;
62
+ let target, base;
63
+ try {
64
+ target = new URL(url);
65
+ }
66
+ catch {
67
+ throw new Error(`scan_app: "${url}" is not a valid URL.`);
68
+ }
69
+ try {
70
+ base = new URL(baseUrl);
71
+ }
72
+ catch {
73
+ return;
74
+ }
75
+ if (target.origin !== base.origin) {
76
+ throw new Error(`scan_app refused "${url}": not same-origin as the configured baseUrl "${baseUrl}". ` +
77
+ `This guards against an agent being steered (prompt injection) toward an internal-only ` +
78
+ `endpoint reachable from this machine. Set IAQA_ALLOW_ANY_URL=1 to lift this for legitimate ` +
79
+ `multi-origin apps.`);
80
+ }
81
+ }
82
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/mcp/sandbox.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,kDAcC;AAED,4CAqBC;AA9CD,2CAA6B;AAE7B;;;;;;GAMG;AACH,SAAgB,mBAAmB,CAAC,SAAiB,EAAE,KAAa,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACxF,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACrE,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,KAAK,SAAS,kBAAkB,QAAQ,gCAAgC,IAAI,KAAK;YACvF,gGAAgG;YAChG,2FAA2F,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAgB,gBAAgB,CAAC,GAAW,EAAE,OAAgB;IAC5D,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,GAAG,IAAI,CAAC,OAAO;QAAE,OAAO;IAC/D,IAAI,MAAW,EAAE,IAAS,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,uBAAuB,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,qBAAqB,GAAG,iDAAiD,OAAO,KAAK;YACnF,wFAAwF;YACxF,6FAA6F;YAC7F,oBAAoB,CACvB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ declare const TOOLS: ({
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: string;
7
+ properties: {
8
+ url: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ max_depth: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ max_pages: {
17
+ type: string;
18
+ description: string;
19
+ };
20
+ reveal: {
21
+ type: string;
22
+ description: string;
23
+ };
24
+ session: {
25
+ type: string;
26
+ description: string;
27
+ };
28
+ network: {
29
+ type: string;
30
+ description: string;
31
+ };
32
+ network_threshold: {
33
+ type: string;
34
+ description: string;
35
+ };
36
+ out_dir: {
37
+ type: string;
38
+ description: string;
39
+ };
40
+ write: {
41
+ type: string;
42
+ description: string;
43
+ };
44
+ page?: undefined;
45
+ provider?: undefined;
46
+ model?: undefined;
47
+ api_key_env?: undefined;
48
+ limit?: undefined;
49
+ };
50
+ };
51
+ } | {
52
+ name: string;
53
+ description: string;
54
+ inputSchema: {
55
+ type: string;
56
+ properties: {
57
+ page: {
58
+ type: string;
59
+ description: string;
60
+ };
61
+ provider: {
62
+ type: string;
63
+ enum: string[];
64
+ description: string;
65
+ };
66
+ model: {
67
+ type: string;
68
+ description: string;
69
+ };
70
+ api_key_env: {
71
+ type: string;
72
+ description: string;
73
+ };
74
+ write: {
75
+ type: string;
76
+ description: string;
77
+ };
78
+ out_dir: {
79
+ type: string;
80
+ description: string;
81
+ };
82
+ url?: undefined;
83
+ max_depth?: undefined;
84
+ max_pages?: undefined;
85
+ reveal?: undefined;
86
+ session?: undefined;
87
+ network?: undefined;
88
+ network_threshold?: undefined;
89
+ limit?: undefined;
90
+ };
91
+ };
92
+ } | {
93
+ name: string;
94
+ description: string;
95
+ inputSchema: {
96
+ type: string;
97
+ properties: {
98
+ limit: {
99
+ type: string;
100
+ description: string;
101
+ };
102
+ url?: undefined;
103
+ max_depth?: undefined;
104
+ max_pages?: undefined;
105
+ reveal?: undefined;
106
+ session?: undefined;
107
+ network?: undefined;
108
+ network_threshold?: undefined;
109
+ out_dir?: undefined;
110
+ write?: undefined;
111
+ page?: undefined;
112
+ provider?: undefined;
113
+ model?: undefined;
114
+ api_key_env?: undefined;
115
+ };
116
+ };
117
+ })[];
118
+ export declare function callTool(name: string, args: any): Promise<string>;
119
+ declare function main(): void;
120
+ export { TOOLS, main };
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.TOOLS = void 0;
38
+ exports.callTool = callTool;
39
+ exports.main = main;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const scan_1 = require("../scan");
43
+ const history_1 = require("../history");
44
+ const config_1 = require("../config");
45
+ const citations_1 = require("../citations");
46
+ const classify_1 = require("../ai/classify");
47
+ const taxonomy_1 = require("../taxonomy");
48
+ const sandbox_1 = require("./sandbox");
49
+ /** Where each provider's key is looked up when nothing names one explicitly. */
50
+ const DEFAULT_KEY_ENV = {
51
+ anthropic: 'ANTHROPIC_API_KEY',
52
+ openai: 'OPENAI_API_KEY',
53
+ google: 'GEMINI_API_KEY',
54
+ };
55
+ /**
56
+ * @ia-qa/qa-discovery — local stdio MCP server.
57
+ *
58
+ * Dependency-free JSON-RPC 2.0 over stdio, same shape as
59
+ * `@ia-qa/self-healing`'s `mcp/server.ts` — runs on the end user's machine,
60
+ * launches its own headless Chromium, and exposes the SAME operation the CLI
61
+ * exposes (`scan`), so a human and an agent get an identical contract. Also
62
+ * corrects a gap in self-healing (its own `discover` has no MCP tool — this
63
+ * one does, from day one).
64
+ *
65
+ * `login` is deliberately NOT a tool here. It opens a visible browser and waits
66
+ * for a person at it, then at the keyboard — an agent cannot perform either
67
+ * step, and exposing it would hang the caller. When `scan_app` reports pages in
68
+ * `loginWall`, the answer is to ask the human to run `ia-qa-discover login` and
69
+ * then call `scan_app` again; a session can also be passed via `session`.
70
+ *
71
+ * stdout carries the protocol only; all logs go to stderr.
72
+ */
73
+ const PROTOCOL_VERSION = '2024-11-05';
74
+ const SERVER_INFO = { name: 'ia-qa-qa-discovery', version: require('../../package.json').version };
75
+ const TOOLS = [
76
+ {
77
+ name: 'scan_app',
78
+ description: "Crawl an app's same-origin pages from a URL (or the configured baseUrl) and capture each page's structural surface — title, meta description, heading hierarchy, forms, and observed same-/cross-origin API calls. Local headless browser; nothing leaves this machine. Deterministic, no LLM, no verdict — this is recon, not a gate. Diffs against the previous capture and returns a structured summary. IMPORTANT: check `loginWall` in the result before reporting coverage — pages listed there still show a login form, which means the scan measured the login wall rather than the app (an app whose catch-all route renders the login page answers HTTP 200 at every URL, so the page count alone looks like success). The fix is a human running `ia-qa-discover login` in their own terminal — you cannot run it, it waits for a person at a browser — or passing an existing storageState via `session`.",
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ url: { type: 'string', description: 'Start URL. Omit to reuse the saved baseUrl in .ia-qa-discovery/config.json.' },
83
+ max_depth: { type: 'integer', description: 'Crawl link-depth. Default 2.' },
84
+ max_pages: { type: 'integer', description: 'Hard cap on pages visited. Default 60.' },
85
+ reveal: { type: 'boolean', description: 'Open menus/dropdowns to harvest hidden links. Default true.' },
86
+ session: { type: 'string', description: 'Path to an existing Playwright storageState file to reuse (e.g. from `ia-qa-heal login`).' },
87
+ network: { type: 'boolean', description: 'Observe API/network calls per page. Default true.' },
88
+ network_threshold: { type: 'number', description: 'Fraction of pages (0-1) a call must appear on to be promoted as shared. Default 0.6.' },
89
+ out_dir: { type: 'string', description: 'Resolve .ia-qa-discovery/ under this directory instead of the current one.' },
90
+ write: { type: 'boolean', description: 'Persist capture/ + history.jsonl to disk. Default true — set false for an in-memory preview.' },
91
+ },
92
+ },
93
+ },
94
+ {
95
+ name: 'classify_app',
96
+ description: "OPTIONAL, BYOK. Classify the entry points in a capture that scan_app already wrote: what each one is FOR (authentication, payment, search, data-entry…) and how sensitive what it handles is. Reads the capture offline — no browser, your app is never touched. \"Offline\" here means no browser, NOT that nothing leaves: this is the only tool on this server that sends anything anywhere. What goes to the model provider is each page's full URL, title, description, headings, the observed API calls (method, normalised path, status) and each form field's name, type, label and selector — live text from the user's app, including any `q=` search value. Page HTML, cookies and the session file never leave. Tell the user that before you call it on an app that is private or authenticated. Every classification carries a sentence a human reads AND a path into the capture that this server resolves and CHECKS before keeping it; a claim citing something that does not exist, or misdescribing what it cites, is dropped and the drop is reported. That check proves the premise, never the conclusion — a model can cite a real password field and still call the page a checkout, so present the `why` and the `confidence`, never the label alone. Entry points under `refused` are ones the model declined to label: that is an answer needing a person, not a retry. IMPORTANT: if `failed` is set on a page, the model call did not succeed — say so; it is not a finding about the app. The API key is read from an environment variable on THIS machine (api_key_env) — do NOT pass a raw key in the call. This is not a gate and produces no verdict.",
97
+ inputSchema: {
98
+ type: 'object',
99
+ properties: {
100
+ page: { type: 'string', description: 'Classify just this page from the capture. Omit for all of them.' },
101
+ provider: { type: 'string', enum: ['anthropic', 'openai', 'google'], description: 'Overrides the "ai" block in config.json. Omit to use what the project already configured.' },
102
+ model: { type: 'string', description: 'Pinned model id, e.g. claude-haiku-4-5, gpt-4o-mini. Runs at temperature 0.' },
103
+ api_key_env: { type: 'string', description: 'Name of the environment variable on this machine holding the API key. The raw key is never passed through a tool call.' },
104
+ write: { type: 'boolean', description: 'Persist .ia-qa-discovery/classification.json. Default true.' },
105
+ out_dir: { type: 'string', description: 'Resolve .ia-qa-discovery/ under this directory instead of the current one.' },
106
+ },
107
+ },
108
+ },
109
+ {
110
+ name: 'discovery_history',
111
+ description: 'Read-only. The recon trend no single scan can reconstruct — pages/forms/API-surface over time, what changed run over run. Reads .ia-qa-discovery/history.jsonl, written by every scan_app call that persists.',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ limit: { type: 'integer', description: 'How many recorded runs to read back, newest last. Default 500.' },
116
+ },
117
+ },
118
+ },
119
+ ];
120
+ exports.TOOLS = TOOLS;
121
+ async function callTool(name, args) {
122
+ if (name === 'scan_app') {
123
+ const outDir = args?.out_dir;
124
+ if (outDir)
125
+ (0, config_1.setBaseDir)((0, sandbox_1.assertInsideProject)(outDir, 'out_dir'));
126
+ try {
127
+ if (args?.session)
128
+ (0, sandbox_1.assertInsideProject)(args.session, 'session');
129
+ if (args?.url) {
130
+ const configuredBaseUrl = (0, config_1.configExists)() ? (0, config_1.loadConfig)().baseUrl : undefined;
131
+ (0, sandbox_1.assertUrlAllowed)(args.url, configuredBaseUrl);
132
+ }
133
+ const result = await (0, scan_1.scanApp)({
134
+ url: args?.url,
135
+ maxDepth: args?.max_depth,
136
+ maxPages: args?.max_pages,
137
+ reveal: args?.reveal,
138
+ session: args?.session,
139
+ network: args?.network,
140
+ networkThreshold: args?.network_threshold,
141
+ write: args?.write,
142
+ });
143
+ return JSON.stringify(result, null, 2);
144
+ }
145
+ finally {
146
+ if (outDir)
147
+ (0, config_1.setBaseDir)(null);
148
+ }
149
+ }
150
+ if (name === 'classify_app') {
151
+ const outDir = args?.out_dir;
152
+ if (outDir)
153
+ (0, config_1.setBaseDir)((0, sandbox_1.assertInsideProject)(outDir, 'out_dir'));
154
+ try {
155
+ const index = (0, citations_1.loadCaptureIndex)();
156
+ if (index.pages.size === 0) {
157
+ throw new Error('No capture to classify. Run scan_app first — this reads what that wrote, it does not make one.');
158
+ }
159
+ // Config first, arguments as override. An agent on a configured project
160
+ // calls this with no arguments at all.
161
+ const configured = ((0, config_1.configExists)() ? (0, config_1.loadConfig)().ai : undefined) ?? {};
162
+ const provider = (args?.provider ?? configured.provider);
163
+ const model = args?.model ?? configured.model;
164
+ if (!provider || !model) {
165
+ throw new Error('No model to call. Either add an "ai" block to .ia-qa-discovery/config.json, or pass provider + model + api_key_env. ' +
166
+ 'The deterministic tools (scan_app, discovery_history) work fully without any of this.');
167
+ }
168
+ // The key is read here, from this machine's environment. It is never an
169
+ // argument: a tool call can be logged, replayed, or composed by an agent
170
+ // acting on third-party content.
171
+ const keyEnv = args?.api_key_env ??
172
+ (configured.apiKey?.source === 'env' ? configured.apiKey.key : undefined) ??
173
+ DEFAULT_KEY_ENV[provider];
174
+ const apiKey = process.env[keyEnv];
175
+ if (!apiKey) {
176
+ throw new Error(`Environment variable "${keyEnv}" is not set on this machine, so there is no key to call ${provider} with.`);
177
+ }
178
+ const pages = [...index.pages.values()].filter((p) => !args?.page || p.page === args.page);
179
+ if (pages.length === 0) {
180
+ throw new Error(`No page "${args.page}" in the capture. Have: ${[...index.pages.keys()].join(', ')}`);
181
+ }
182
+ const perPage = {};
183
+ let kept = 0;
184
+ let refused = 0;
185
+ let dropped = 0;
186
+ const failures = [];
187
+ for (const page of pages) {
188
+ if ((0, classify_1.entryPointsOf)(page).length === 0)
189
+ continue; // takes no input; not sent at all
190
+ const result = await (0, classify_1.classifyPage)(page, index, { provider, model, apiKey });
191
+ perPage[page.page] = result;
192
+ kept += result.kept.length;
193
+ refused += result.refused.length;
194
+ dropped += result.dropped.length;
195
+ if (result.failed)
196
+ failures.push(`${page.page}: ${result.failed.reason}`);
197
+ }
198
+ const document = {
199
+ schema: classify_1.CLASSIFICATION_SCHEMA,
200
+ taxonomyVersion: taxonomy_1.TAXONOMY_VERSION,
201
+ classifiedAt: new Date().toISOString(),
202
+ model: `${provider}/${model}`,
203
+ totals: { kept, refused, dropped },
204
+ // Named at the top level so a caller cannot summarise the totals without
205
+ // meeting it: zero kept because the call failed is not zero kept.
206
+ ...(failures.length > 0
207
+ ? { failed: failures, note: 'Some pages could not be classified at all — the model call did not succeed. This says nothing about the app.' }
208
+ : {}),
209
+ pages: perPage,
210
+ };
211
+ if (args?.write !== false) {
212
+ const file = path.join((0, config_1.baseDir)(), config_1.CONFIG_DIR, classify_1.CLASSIFICATION_FILENAME);
213
+ fs.mkdirSync(path.dirname(file), { recursive: true });
214
+ fs.writeFileSync(file, JSON.stringify(document, null, 2) + '\n', 'utf8');
215
+ }
216
+ return JSON.stringify(document, null, 2);
217
+ }
218
+ finally {
219
+ if (outDir)
220
+ (0, config_1.setBaseDir)(null);
221
+ }
222
+ }
223
+ if (name === 'discovery_history') {
224
+ const entries = (0, history_1.readHistory)(typeof args?.limit === 'number' ? args.limit : undefined);
225
+ return JSON.stringify(entries, null, 2);
226
+ }
227
+ throw new Error(`Unknown tool "${name}". Call tools/list to see available tools.`);
228
+ }
229
+ function send(message) {
230
+ process.stdout.write(JSON.stringify(message) + '\n');
231
+ }
232
+ function reply(id, result) {
233
+ send({ jsonrpc: '2.0', id, result });
234
+ }
235
+ function replyError(id, code, message) {
236
+ send({ jsonrpc: '2.0', id, error: { code, message } });
237
+ }
238
+ async function handle(req) {
239
+ const { id, method, params } = req;
240
+ const isNotification = id === undefined || id === null;
241
+ try {
242
+ if (method === 'initialize') {
243
+ reply(id, {
244
+ protocolVersion: params?.protocolVersion || PROTOCOL_VERSION,
245
+ capabilities: { tools: {} },
246
+ serverInfo: SERVER_INFO,
247
+ });
248
+ return;
249
+ }
250
+ if (method === 'notifications/initialized' || method === 'initialized') {
251
+ return; // notification, no response
252
+ }
253
+ if (method === 'ping') {
254
+ reply(id, {});
255
+ return;
256
+ }
257
+ if (method === 'tools/list') {
258
+ reply(id, { tools: TOOLS });
259
+ return;
260
+ }
261
+ if (method === 'tools/call') {
262
+ const toolName = params?.name;
263
+ try {
264
+ const text = await callTool(toolName, params?.arguments || {});
265
+ reply(id, { content: [{ type: 'text', text }] });
266
+ }
267
+ catch (err) {
268
+ const message = err instanceof Error ? err.message : String(err);
269
+ reply(id, { content: [{ type: 'text', text: `Error: ${message}` }], isError: true });
270
+ }
271
+ return;
272
+ }
273
+ if (!isNotification)
274
+ replyError(id, -32601, `Method not found: ${method}`);
275
+ }
276
+ catch (err) {
277
+ const message = err instanceof Error ? err.message : String(err);
278
+ if (!isNotification)
279
+ replyError(id, -32603, message);
280
+ else
281
+ process.stderr.write(`[ia-qa-qa-discovery] error handling ${method}: ${message}\n`);
282
+ }
283
+ }
284
+ function main() {
285
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
286
+ process.stdout.write(SERVER_INFO.version + '\n');
287
+ process.exit(0);
288
+ }
289
+ process.stderr.write('[ia-qa-qa-discovery] MCP server ready (stdio)\n');
290
+ let buffer = '';
291
+ process.stdin.setEncoding('utf8');
292
+ process.stdin.on('data', (chunk) => {
293
+ buffer += chunk;
294
+ let nl;
295
+ while ((nl = buffer.indexOf('\n')) !== -1) {
296
+ const line = buffer.slice(0, nl).trim();
297
+ buffer = buffer.slice(nl + 1);
298
+ if (!line)
299
+ continue;
300
+ let req;
301
+ try {
302
+ req = JSON.parse(line);
303
+ }
304
+ catch {
305
+ process.stderr.write(`[ia-qa-qa-discovery] non-JSON line ignored: ${line.slice(0, 80)}\n`);
306
+ continue;
307
+ }
308
+ void handle(req);
309
+ }
310
+ });
311
+ process.stdin.on('end', () => process.exit(0));
312
+ }
313
+ if (require.main === module)
314
+ main();
315
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}