brakit 0.9.2 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,16 +27,14 @@ var DASHBOARD_API_SECURITY = `${DASHBOARD_PREFIX}/api/security`;
27
27
  var DASHBOARD_API_TAB = `${DASHBOARD_PREFIX}/api/tab`;
28
28
  var DASHBOARD_API_FINDINGS = `${DASHBOARD_PREFIX}/api/findings`;
29
29
  var DASHBOARD_API_FINDINGS_REPORT = `${DASHBOARD_PREFIX}/api/findings/report`;
30
+ var DASHBOARD_API_GRAPH = `${DASHBOARD_PREFIX}/api/graph`;
30
31
  var VALID_TABS_TUPLE = [
31
32
  "overview",
32
33
  "actions",
33
- "requests",
34
- "fetches",
35
- "queries",
36
- "errors",
37
- "logs",
34
+ "insights",
38
35
  "performance",
39
- "security"
36
+ "graph",
37
+ "explorer"
40
38
  ];
41
39
  var VALID_TABS = new Set(VALID_TABS_TUPLE);
42
40
 
@@ -51,7 +49,7 @@ var MAX_DISCOVERY_DEPTH = 5;
51
49
  var MAX_TIMELINE_EVENTS = 20;
52
50
  var MAX_RESOLVED_DISPLAY = 5;
53
51
  var ENRICHMENT_SEVERITY_FILTER = ["critical", "warning"];
54
- var MCP_SERVER_VERSION = "0.9.2";
52
+ var MCP_SERVER_VERSION = "0.10.1";
55
53
  var RECOVERY_WINDOW_MS = 5 * 60 * 1e3;
56
54
  var PORT_MIN = 1;
57
55
  var PORT_MAX = 65535;
@@ -261,10 +259,27 @@ async function enrichFindings(client) {
261
259
  if (reqData.requests.length > 0) {
262
260
  const req = reqData.requests[0];
263
261
  if (req.id) {
264
- const activity = await client.getActivity(req.id);
265
- const queryCount = activity.counts?.queries ?? 0;
266
- const fetchCount = activity.counts?.fetches ?? 0;
267
- return `Request took ${req.durationMs}ms. ${queryCount} DB queries, ${fetchCount} fetches.`;
262
+ const [activity, queries, fetches] = await Promise.all([
263
+ client.getActivity(req.id),
264
+ client.getQueries(req.id),
265
+ client.getFetches(req.id)
266
+ ]);
267
+ const lines = [`Request took ${req.durationMs}ms.`];
268
+ if (queries.entries.length > 0) {
269
+ lines.push(`DB Queries (${queries.entries.length}):`);
270
+ for (const q of queries.entries.slice(0, 5)) {
271
+ const sql = q.sql ?? `${q.operation ?? ""} ${q.table ?? q.model ?? ""}`;
272
+ lines.push(` [${q.durationMs}ms] ${sql}`);
273
+ }
274
+ if (queries.entries.length > 5) lines.push(` ... and ${queries.entries.length - 5} more`);
275
+ }
276
+ if (fetches.entries.length > 0) {
277
+ lines.push(`Fetches (${fetches.entries.length}):`);
278
+ for (const f of fetches.entries.slice(0, 3)) {
279
+ lines.push(` [${f.durationMs}ms] ${f.method} ${f.url} \u2192 ${f.statusCode}`);
280
+ }
281
+ }
282
+ return lines.join("\n");
268
283
  }
269
284
  }
270
285
  } catch {
@@ -380,6 +395,9 @@ var getFindings = {
380
395
  return { content: [{ type: "text", text: `Invalid state "${state}". Use: open, fixing, resolved, stale, regressed.` }], isError: true };
381
396
  }
382
397
  let findings = await enrichFindings(client);
398
+ if (!state) {
399
+ findings = findings.filter((f) => f.aiStatus !== "wont_fix");
400
+ }
383
401
  if (severity) {
384
402
  findings = findings.filter((f) => f.severity === severity);
385
403
  }
@@ -391,21 +409,25 @@ var getFindings = {
391
409
  if (findings.length === 0) {
392
410
  return { content: [{ type: "text", text: "No findings detected. The application looks healthy." }] };
393
411
  }
394
- const lines = [`Found ${findings.length} issue(s):
395
- `];
412
+ const lines = [
413
+ `Found ${findings.length} issue(s). Full context included below \u2014 no need to call get_request_detail separately.`,
414
+ `After fixing, call report_fixes ONCE with all results.
415
+ `
416
+ ];
396
417
  for (const f of findings) {
397
418
  lines.push(`[${f.severity.toUpperCase()}] ${f.title}`);
398
419
  lines.push(` ID: ${f.findingId}`);
399
420
  lines.push(` Endpoint: ${f.endpoint}`);
400
421
  lines.push(` Issue: ${f.description}`);
401
- if (f.context) lines.push(` Context: ${f.context}`);
422
+ if (f.context) {
423
+ for (const ctxLine of f.context.split("\n")) {
424
+ lines.push(` ${ctxLine}`);
425
+ }
426
+ }
402
427
  lines.push(` Fix: ${f.hint}`);
403
428
  if (f.aiStatus === "fixed") {
404
429
  lines.push(` AI Status: fixed (awaiting verification)`);
405
430
  if (f.aiNotes) lines.push(` AI Notes: ${f.aiNotes}`);
406
- } else if (f.aiStatus === "wont_fix") {
407
- lines.push(` AI Status: won't fix`);
408
- if (f.aiNotes) lines.push(` AI Notes: ${f.aiNotes}`);
409
431
  }
410
432
  lines.push("");
411
433
  }
@@ -750,9 +772,65 @@ var reportFix = {
750
772
  }
751
773
  };
752
774
 
775
+ // src/mcp/tools/report-fixes.ts
776
+ var reportFixes = {
777
+ name: "report_fixes",
778
+ description: "Report results for multiple findings in a single call. Use this instead of calling report_fix repeatedly \u2014 it's faster and requires only one confirmation. Pass a JSON array string where each item has finding_id, status ('fixed' or 'wont_fix'), and summary.",
779
+ inputSchema: {
780
+ type: "object",
781
+ properties: {
782
+ fixes: {
783
+ type: "string",
784
+ description: 'JSON array of fix reports. Example: [{"finding_id":"abc123","status":"fixed","summary":"Added input validation"}]'
785
+ }
786
+ },
787
+ required: ["fixes"]
788
+ },
789
+ async handler(client, args) {
790
+ let fixes;
791
+ try {
792
+ const raw = typeof args.fixes === "string" ? JSON.parse(args.fixes) : args.fixes;
793
+ if (!Array.isArray(raw) || raw.length === 0) {
794
+ return { content: [{ type: "text", text: "fixes must be a non-empty JSON array." }], isError: true };
795
+ }
796
+ fixes = raw.filter(
797
+ (item) => typeof item === "object" && item !== null && typeof item.finding_id === "string" && typeof item.status === "string" && typeof item.summary === "string"
798
+ );
799
+ if (fixes.length === 0) {
800
+ return { content: [{ type: "text", text: "No valid fix entries found. Each entry needs finding_id, status, and summary." }], isError: true };
801
+ }
802
+ } catch {
803
+ return { content: [{ type: "text", text: "fixes must be valid JSON." }], isError: true };
804
+ }
805
+ const results = [];
806
+ let errors = 0;
807
+ for (const fix of fixes) {
808
+ if (!fix.finding_id || !isValidAiFixStatus(fix.status) || !fix.summary) {
809
+ results.push(`\u2717 Invalid entry: ${fix.finding_id || "missing ID"}`);
810
+ errors++;
811
+ continue;
812
+ }
813
+ const ok = await client.reportFix(fix.finding_id, fix.status, fix.summary);
814
+ if (ok) {
815
+ const label = fix.status === "fixed" ? "fixed" : "won't fix";
816
+ results.push(`\u2713 ${fix.finding_id} \u2192 ${label}`);
817
+ } else {
818
+ results.push(`\u2717 ${fix.finding_id} \u2192 not found`);
819
+ errors++;
820
+ }
821
+ }
822
+ const errorSuffix = errors > 0 ? ` (${errors} error${errors !== 1 ? "s" : ""})` : "";
823
+ const summary = `Processed ${fixes.length} finding(s)${errorSuffix}. Dashboard updated.`;
824
+ return {
825
+ content: [{ type: "text", text: summary + "\n\n" + results.join("\n") }],
826
+ ...errors > 0 ? { isError: true } : {}
827
+ };
828
+ }
829
+ };
830
+
753
831
  // src/mcp/tools/index.ts
754
832
  var TOOL_MAP = new Map(
755
- [getFindings, getEndpoints, getRequestDetail, verifyFix, getReport, clearFindings, reportFix].map((t) => [t.name, t])
833
+ [getFindings, getEndpoints, getRequestDetail, verifyFix, getReport, clearFindings, reportFix, reportFixes].map((t) => [t.name, t])
756
834
  );
757
835
  function getToolDefinitions() {
758
836
  return [...TOOL_MAP.values()].map((t) => ({
@@ -773,7 +851,7 @@ function handleToolCall(client, name, args) {
773
851
  }
774
852
 
775
853
  // src/mcp/prompts.ts
776
- var SERVER_INSTRUCTIONS = "Brakit is a dev tool that monitors your running app for security vulnerabilities, performance issues, and query problems. IMPORTANT: After fixing any brakit finding, always call the report_fix tool with the finding_id, status ('fixed' or 'wont_fix'), and a brief summary of what you did. This updates the dashboard in real-time so the developer can track AI-driven fixes.";
854
+ var SERVER_INSTRUCTIONS = "Brakit is a dev tool that monitors your running app for security vulnerabilities, performance issues, and query problems. IMPORTANT: After fixing brakit findings, call report_fixes (batch) with all results at once instead of calling report_fix individually. This is faster and requires only one confirmation.";
777
855
  var PROMPTS = [
778
856
  {
779
857
  name: "check-app",
@@ -785,8 +863,8 @@ var PROMPTS = [
785
863
  }
786
864
  ];
787
865
  var PROMPT_MESSAGES = {
788
- "check-app": "Check my running app for security and performance issues using brakit. First get all findings, then get the endpoint summary. For any critical or warning findings, get the request detail to understand the root cause. Give me a clear report of what's wrong and offer to fix each issue. After fixing any issue, call report_fix with the finding_id, status, and summary.",
789
- "fix-findings": "Get all open brakit findings. For each finding:\n1. Get the request detail to understand the exact issue\n2. Find the source code responsible and fix it\n3. Call report_fix with the finding_id, status ('fixed' or 'wont_fix'), and a brief summary of what you did\n4. Move to the next finding\n\nAfter all findings are processed, ask me to re-trigger the endpoints so brakit can verify the fixes."
866
+ "check-app": "Check my running app for security and performance issues using brakit. First get all findings, then get the endpoint summary. For any critical or warning findings, get the request detail to understand the root cause. Give me a clear report of what's wrong and offer to fix each issue. After fixing issues, call report_fixes once with all results.",
867
+ "fix-findings": "Get all open brakit findings. For each finding:\n1. Get the request detail to understand the exact issue\n2. Find the source code responsible and fix it\n3. Track the finding_id, status ('fixed' or 'wont_fix'), and a brief summary\n\nAfter processing ALL findings, call report_fixes ONCE with the full array of results. Do not call report_fix individually for each finding.\n\nAfter reporting, ask me to re-trigger the endpoints so brakit can verify the fixes."
790
868
  };
791
869
 
792
870
  // src/mcp/server.ts