@opencodehub/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 (210) hide show
  1. package/README.md +62 -0
  2. package/dist/analysis-bridge.d.ts +23 -0
  3. package/dist/analysis-bridge.d.ts.map +1 -0
  4. package/dist/analysis-bridge.js +83 -0
  5. package/dist/analysis-bridge.js.map +1 -0
  6. package/dist/connection-pool.d.ts +76 -0
  7. package/dist/connection-pool.d.ts.map +1 -0
  8. package/dist/connection-pool.js +179 -0
  9. package/dist/connection-pool.js.map +1 -0
  10. package/dist/error-envelope.d.ts +97 -0
  11. package/dist/error-envelope.d.ts.map +1 -0
  12. package/dist/error-envelope.js +75 -0
  13. package/dist/error-envelope.js.map +1 -0
  14. package/dist/group-resolver.d.ts +29 -0
  15. package/dist/group-resolver.d.ts.map +1 -0
  16. package/dist/group-resolver.js +100 -0
  17. package/dist/group-resolver.js.map +1 -0
  18. package/dist/index.d.ts +43 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +54 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/next-step-hints.d.ts +24 -0
  23. package/dist/next-step-hints.d.ts.map +1 -0
  24. package/dist/next-step-hints.js +41 -0
  25. package/dist/next-step-hints.js.map +1 -0
  26. package/dist/repo-resolver.d.ts +88 -0
  27. package/dist/repo-resolver.d.ts.map +1 -0
  28. package/dist/repo-resolver.js +211 -0
  29. package/dist/repo-resolver.js.map +1 -0
  30. package/dist/repo-uri-for-entry.d.ts +25 -0
  31. package/dist/repo-uri-for-entry.d.ts.map +1 -0
  32. package/dist/repo-uri-for-entry.js +64 -0
  33. package/dist/repo-uri-for-entry.js.map +1 -0
  34. package/dist/resources/repo-cluster.d.ts +19 -0
  35. package/dist/resources/repo-cluster.d.ts.map +1 -0
  36. package/dist/resources/repo-cluster.js +203 -0
  37. package/dist/resources/repo-cluster.js.map +1 -0
  38. package/dist/resources/repo-clusters.d.ts +14 -0
  39. package/dist/resources/repo-clusters.d.ts.map +1 -0
  40. package/dist/resources/repo-clusters.js +97 -0
  41. package/dist/resources/repo-clusters.js.map +1 -0
  42. package/dist/resources/repo-context.d.ts +12 -0
  43. package/dist/resources/repo-context.d.ts.map +1 -0
  44. package/dist/resources/repo-context.js +84 -0
  45. package/dist/resources/repo-context.js.map +1 -0
  46. package/dist/resources/repo-process.d.ts +19 -0
  47. package/dist/resources/repo-process.d.ts.map +1 -0
  48. package/dist/resources/repo-process.js +220 -0
  49. package/dist/resources/repo-process.js.map +1 -0
  50. package/dist/resources/repo-processes.d.ts +13 -0
  51. package/dist/resources/repo-processes.d.ts.map +1 -0
  52. package/dist/resources/repo-processes.js +99 -0
  53. package/dist/resources/repo-processes.js.map +1 -0
  54. package/dist/resources/repo-schema.d.ts +13 -0
  55. package/dist/resources/repo-schema.d.ts.map +1 -0
  56. package/dist/resources/repo-schema.js +99 -0
  57. package/dist/resources/repo-schema.js.map +1 -0
  58. package/dist/resources/repos.d.ts +20 -0
  59. package/dist/resources/repos.d.ts.map +1 -0
  60. package/dist/resources/repos.js +58 -0
  61. package/dist/resources/repos.js.map +1 -0
  62. package/dist/resources/store-helper.d.ts +28 -0
  63. package/dist/resources/store-helper.d.ts.map +1 -0
  64. package/dist/resources/store-helper.js +58 -0
  65. package/dist/resources/store-helper.js.map +1 -0
  66. package/dist/resources/yaml.d.ts +10 -0
  67. package/dist/resources/yaml.d.ts.map +1 -0
  68. package/dist/resources/yaml.js +16 -0
  69. package/dist/resources/yaml.js.map +1 -0
  70. package/dist/server.d.ts +46 -0
  71. package/dist/server.d.ts.map +1 -0
  72. package/dist/server.js +194 -0
  73. package/dist/server.js.map +1 -0
  74. package/dist/staleness.d.ts +19 -0
  75. package/dist/staleness.d.ts.map +1 -0
  76. package/dist/staleness.js +40 -0
  77. package/dist/staleness.js.map +1 -0
  78. package/dist/test-utils.d.ts +170 -0
  79. package/dist/test-utils.d.ts.map +1 -0
  80. package/dist/test-utils.js +473 -0
  81. package/dist/test-utils.js.map +1 -0
  82. package/dist/tools/api-impact.d.ts +47 -0
  83. package/dist/tools/api-impact.d.ts.map +1 -0
  84. package/dist/tools/api-impact.js +199 -0
  85. package/dist/tools/api-impact.js.map +1 -0
  86. package/dist/tools/confidence.d.ts +39 -0
  87. package/dist/tools/confidence.d.ts.map +1 -0
  88. package/dist/tools/confidence.js +58 -0
  89. package/dist/tools/confidence.js.map +1 -0
  90. package/dist/tools/context.d.ts +47 -0
  91. package/dist/tools/context.d.ts.map +1 -0
  92. package/dist/tools/context.js +577 -0
  93. package/dist/tools/context.js.map +1 -0
  94. package/dist/tools/dependencies.d.ts +29 -0
  95. package/dist/tools/dependencies.d.ts.map +1 -0
  96. package/dist/tools/dependencies.js +110 -0
  97. package/dist/tools/dependencies.js.map +1 -0
  98. package/dist/tools/detect-changes.d.ts +15 -0
  99. package/dist/tools/detect-changes.d.ts.map +1 -0
  100. package/dist/tools/detect-changes.js +78 -0
  101. package/dist/tools/detect-changes.js.map +1 -0
  102. package/dist/tools/group-contracts.d.ts +26 -0
  103. package/dist/tools/group-contracts.d.ts.map +1 -0
  104. package/dist/tools/group-contracts.js +251 -0
  105. package/dist/tools/group-contracts.js.map +1 -0
  106. package/dist/tools/group-cross-repo-links.d.ts +28 -0
  107. package/dist/tools/group-cross-repo-links.d.ts.map +1 -0
  108. package/dist/tools/group-cross-repo-links.js +128 -0
  109. package/dist/tools/group-cross-repo-links.js.map +1 -0
  110. package/dist/tools/group-list.d.ts +10 -0
  111. package/dist/tools/group-list.d.ts.map +1 -0
  112. package/dist/tools/group-list.js +74 -0
  113. package/dist/tools/group-list.js.map +1 -0
  114. package/dist/tools/group-query.d.ts +40 -0
  115. package/dist/tools/group-query.d.ts.map +1 -0
  116. package/dist/tools/group-query.js +209 -0
  117. package/dist/tools/group-query.js.map +1 -0
  118. package/dist/tools/group-status.d.ts +21 -0
  119. package/dist/tools/group-status.d.ts.map +1 -0
  120. package/dist/tools/group-status.js +121 -0
  121. package/dist/tools/group-status.js.map +1 -0
  122. package/dist/tools/group-sync.d.ts +23 -0
  123. package/dist/tools/group-sync.d.ts.map +1 -0
  124. package/dist/tools/group-sync.js +112 -0
  125. package/dist/tools/group-sync.js.map +1 -0
  126. package/dist/tools/impact.d.ts +36 -0
  127. package/dist/tools/impact.d.ts.map +1 -0
  128. package/dist/tools/impact.js +232 -0
  129. package/dist/tools/impact.js.map +1 -0
  130. package/dist/tools/license-audit.d.ts +34 -0
  131. package/dist/tools/license-audit.d.ts.map +1 -0
  132. package/dist/tools/license-audit.js +108 -0
  133. package/dist/tools/license-audit.js.map +1 -0
  134. package/dist/tools/list-dead-code.d.ts +26 -0
  135. package/dist/tools/list-dead-code.d.ts.map +1 -0
  136. package/dist/tools/list-dead-code.js +110 -0
  137. package/dist/tools/list-dead-code.js.map +1 -0
  138. package/dist/tools/list-findings-delta.d.ts +36 -0
  139. package/dist/tools/list-findings-delta.d.ts.map +1 -0
  140. package/dist/tools/list-findings-delta.js +274 -0
  141. package/dist/tools/list-findings-delta.js.map +1 -0
  142. package/dist/tools/list-findings.d.ts +30 -0
  143. package/dist/tools/list-findings.d.ts.map +1 -0
  144. package/dist/tools/list-findings.js +129 -0
  145. package/dist/tools/list-findings.js.map +1 -0
  146. package/dist/tools/list-repos.d.ts +17 -0
  147. package/dist/tools/list-repos.d.ts.map +1 -0
  148. package/dist/tools/list-repos.js +63 -0
  149. package/dist/tools/list-repos.js.map +1 -0
  150. package/dist/tools/owners.d.ts +23 -0
  151. package/dist/tools/owners.d.ts.map +1 -0
  152. package/dist/tools/owners.js +103 -0
  153. package/dist/tools/owners.js.map +1 -0
  154. package/dist/tools/pack-codebase.d.ts +76 -0
  155. package/dist/tools/pack-codebase.d.ts.map +1 -0
  156. package/dist/tools/pack-codebase.js +289 -0
  157. package/dist/tools/pack-codebase.js.map +1 -0
  158. package/dist/tools/project-profile.d.ts +28 -0
  159. package/dist/tools/project-profile.d.ts.map +1 -0
  160. package/dist/tools/project-profile.js +109 -0
  161. package/dist/tools/project-profile.js.map +1 -0
  162. package/dist/tools/query.d.ts +63 -0
  163. package/dist/tools/query.d.ts.map +1 -0
  164. package/dist/tools/query.js +662 -0
  165. package/dist/tools/query.js.map +1 -0
  166. package/dist/tools/remove-dead-code.d.ts +47 -0
  167. package/dist/tools/remove-dead-code.d.ts.map +1 -0
  168. package/dist/tools/remove-dead-code.js +258 -0
  169. package/dist/tools/remove-dead-code.js.map +1 -0
  170. package/dist/tools/rename.d.ts +21 -0
  171. package/dist/tools/rename.d.ts.map +1 -0
  172. package/dist/tools/rename.js +116 -0
  173. package/dist/tools/rename.js.map +1 -0
  174. package/dist/tools/risk-trends.d.ts +19 -0
  175. package/dist/tools/risk-trends.d.ts.map +1 -0
  176. package/dist/tools/risk-trends.js +73 -0
  177. package/dist/tools/risk-trends.js.map +1 -0
  178. package/dist/tools/route-map.d.ts +27 -0
  179. package/dist/tools/route-map.d.ts.map +1 -0
  180. package/dist/tools/route-map.js +119 -0
  181. package/dist/tools/route-map.js.map +1 -0
  182. package/dist/tools/scan.d.ts +27 -0
  183. package/dist/tools/scan.d.ts.map +1 -0
  184. package/dist/tools/scan.js +136 -0
  185. package/dist/tools/scan.js.map +1 -0
  186. package/dist/tools/shape-check.d.ts +53 -0
  187. package/dist/tools/shape-check.d.ts.map +1 -0
  188. package/dist/tools/shape-check.js +161 -0
  189. package/dist/tools/shape-check.js.map +1 -0
  190. package/dist/tools/shared.d.ts +101 -0
  191. package/dist/tools/shared.d.ts.map +1 -0
  192. package/dist/tools/shared.js +114 -0
  193. package/dist/tools/shared.js.map +1 -0
  194. package/dist/tools/signature.d.ts +38 -0
  195. package/dist/tools/signature.d.ts.map +1 -0
  196. package/dist/tools/signature.js +332 -0
  197. package/dist/tools/signature.js.map +1 -0
  198. package/dist/tools/sql.d.ts +34 -0
  199. package/dist/tools/sql.d.ts.map +1 -0
  200. package/dist/tools/sql.js +222 -0
  201. package/dist/tools/sql.js.map +1 -0
  202. package/dist/tools/tool-map.d.ts +24 -0
  203. package/dist/tools/tool-map.d.ts.map +1 -0
  204. package/dist/tools/tool-map.js +97 -0
  205. package/dist/tools/tool-map.js.map +1 -0
  206. package/dist/tools/verdict.d.ts +33 -0
  207. package/dist/tools/verdict.d.ts.map +1 -0
  208. package/dist/tools/verdict.js +102 -0
  209. package/dist/tools/verdict.js.map +1 -0
  210. package/package.json +76 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * `license_audit` — classify Dependency nodes by license risk tier.
3
+ *
4
+ * Walks every Dependency node the ingestion pipeline produced and sorts
5
+ * each one into three buckets:
6
+ *
7
+ * - copyleft — names matching GPL/AGPL/SSPL/EUPL/CPAL/OSL/RPL. These
8
+ * are redistribution-contagious licenses that the host
9
+ * project (Apache-2.0) cannot safely link against.
10
+ * - proprietary — explicit "PROPRIETARY" declarations.
11
+ * - unknown — missing licenses or the `"UNKNOWN"` sentinel emitted
12
+ * by the dependency phase when a manifest parser could
13
+ * not recover a declared license. A later release will
14
+ * populate real licenses from ecosystem metadata;
15
+ * until then most audits WILL return tier=WARN.
16
+ *
17
+ * Tier assignment:
18
+ * BLOCK — any copyleft OR any proprietary dep.
19
+ * WARN — no copyleft/proprietary, at least one unknown.
20
+ * OK — nothing flagged.
21
+ *
22
+ * Annotations are {readOnly, closedWorld, idempotent} — the tool only
23
+ * queries the graph.
24
+ */
25
+ // biome-ignore-all lint/complexity/useLiteralKeys: dot-access disallowed on Record index signatures
26
+ import { classifyDependencies } from "@opencodehub/analysis";
27
+ import { toolErrorFromUnknown } from "../error-envelope.js";
28
+ import { withNextSteps } from "../next-step-hints.js";
29
+ import { stalenessFromMeta } from "../staleness.js";
30
+ import { fromToolResult, repoArgShape, toToolResult, withStore, } from "./shared.js";
31
+ const LicenseAuditInput = {
32
+ ...repoArgShape,
33
+ };
34
+ export async function runLicenseAudit(ctx, args) {
35
+ const call = await withStore(ctx, args, async (store, resolved) => {
36
+ try {
37
+ const all = await store.graph.listDependencies();
38
+ const deps = all.map((d) => ({
39
+ id: d.id,
40
+ name: d.name,
41
+ version: stringOr(d.version, "UNKNOWN"),
42
+ ecosystem: stringOr(d.ecosystem, "unknown"),
43
+ license: stringOr(d.license, "UNKNOWN"),
44
+ lockfileSource: stringOr(d.lockfileSource, d.filePath),
45
+ }));
46
+ const result = classifyDependencies(deps);
47
+ const header = `License audit for ${resolved.name}: tier=${result.tier} (${result.summary.okCount}/${result.summary.total} ok, ${result.summary.flaggedCount} flagged)`;
48
+ const bodyLines = [];
49
+ if (result.flagged.copyleft.length > 0) {
50
+ bodyLines.push(`Copyleft (${result.flagged.copyleft.length}):`, ...result.flagged.copyleft.map((d) => ` - [${d.ecosystem}] ${d.name}@${d.version} — ${d.license}`));
51
+ }
52
+ if (result.flagged.proprietary.length > 0) {
53
+ bodyLines.push(`Proprietary (${result.flagged.proprietary.length}):`, ...result.flagged.proprietary.map((d) => ` - [${d.ecosystem}] ${d.name}@${d.version} — ${d.license}`));
54
+ }
55
+ if (result.flagged.unknown.length > 0) {
56
+ bodyLines.push(`Unknown/missing (${result.flagged.unknown.length}):`, ...result.flagged.unknown
57
+ .slice(0, 25)
58
+ .map((d) => ` - [${d.ecosystem}] ${d.name}@${d.version}`));
59
+ if (result.flagged.unknown.length > 25) {
60
+ bodyLines.push(` ... ${result.flagged.unknown.length - 25} more (see structuredContent.flagged.unknown)`);
61
+ }
62
+ }
63
+ if (bodyLines.length === 0) {
64
+ bodyLines.push("All licenses cleared.");
65
+ }
66
+ const nextSteps = [];
67
+ if (result.tier === "BLOCK") {
68
+ nextSteps.push("review the copyleft/proprietary deps above — each must be replaced or explicitly approved by legal", "call `dependencies` with the offending ecosystem filter to see the full record");
69
+ }
70
+ else if (result.tier === "WARN") {
71
+ nextSteps.push("populate missing licenses: re-index with `codehub analyze --force` once the license-detection follow-up lands", "call `dependencies` to inspect the raw Dependency rows");
72
+ }
73
+ else {
74
+ nextSteps.push("no action required — re-run after bumping any dependency", "call `dependencies` to inspect the full list");
75
+ }
76
+ return withNextSteps([header, ...bodyLines].join("\n"), {
77
+ tier: result.tier,
78
+ flagged: result.flagged,
79
+ summary: result.summary,
80
+ }, nextSteps, stalenessFromMeta(resolved.meta));
81
+ }
82
+ catch (err) {
83
+ return toolErrorFromUnknown(err);
84
+ }
85
+ });
86
+ return toToolResult(call);
87
+ }
88
+ export function registerLicenseAuditTool(server, ctx) {
89
+ server.registerTool("license_audit", {
90
+ title: "Audit dependency licenses",
91
+ description: "Classify every Dependency node by license risk: copyleft (GPL/AGPL/SSPL/EUPL/CPAL/OSL/RPL), proprietary, unknown. Returns tier=BLOCK if any copyleft or proprietary dep, WARN if only unknowns, OK otherwise. Note: until per-ecosystem license detection lands, most Dependency nodes carry license='UNKNOWN', so most audits will return tier=WARN until that follow-up ships.",
92
+ inputSchema: LicenseAuditInput,
93
+ annotations: {
94
+ readOnlyHint: true,
95
+ destructiveHint: false,
96
+ openWorldHint: false,
97
+ idempotentHint: true,
98
+ },
99
+ }, async (args) => fromToolResult(await runLicenseAudit(ctx, args)));
100
+ }
101
+ function stringOr(v, fallback) {
102
+ if (typeof v === "string")
103
+ return v;
104
+ if (typeof v === "number" || typeof v === "boolean")
105
+ return String(v);
106
+ return fallback;
107
+ }
108
+ //# sourceMappingURL=license-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license-audit.js","sourceRoot":"","sources":["../../src/tools/license-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `list_dead_code` — enumerate dead and unreachable-export symbols.
3
+ *
4
+ * Thin wrapper over {@link classifyDeadness} from `@opencodehub/analysis`.
5
+ * Reports:
6
+ * - `dead` symbols: non-exported, no inbound referrers.
7
+ * - `unreachableExports` (opt-in): exported symbols with no cross-module
8
+ * referrer.
9
+ * - `ghostCommunities`: Leiden communities whose every member is non-live.
10
+ *
11
+ * Read-only, closed-world, idempotent — consuming the classifier twice with
12
+ * the same inputs returns an identical result.
13
+ */
14
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
+ import { type ToolContext, type ToolResult } from "./shared.js";
16
+ interface ListDeadCodeArgs {
17
+ readonly repo?: string | undefined;
18
+ readonly repo_uri?: string | undefined;
19
+ readonly includeUnreachableExports?: boolean | undefined;
20
+ readonly limit?: number | undefined;
21
+ readonly filePathPattern?: string | undefined;
22
+ }
23
+ export declare function runListDeadCode(ctx: ToolContext, args: ListDeadCodeArgs): Promise<ToolResult>;
24
+ export declare function registerListDeadCodeTool(server: McpServer, ctx: ToolContext): void;
25
+ export {};
26
+ //# sourceMappingURL=list-dead-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dead-code.d.ts","sourceRoot":"","sources":["../../src/tools/list-dead-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAC;AAuBrB,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,UAAU,CAAC,CA8ErB;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAiBlF"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * `list_dead_code` — enumerate dead and unreachable-export symbols.
3
+ *
4
+ * Thin wrapper over {@link classifyDeadness} from `@opencodehub/analysis`.
5
+ * Reports:
6
+ * - `dead` symbols: non-exported, no inbound referrers.
7
+ * - `unreachableExports` (opt-in): exported symbols with no cross-module
8
+ * referrer.
9
+ * - `ghostCommunities`: Leiden communities whose every member is non-live.
10
+ *
11
+ * Read-only, closed-world, idempotent — consuming the classifier twice with
12
+ * the same inputs returns an identical result.
13
+ */
14
+ import { classifyDeadness } from "@opencodehub/analysis";
15
+ import { z } from "zod";
16
+ import { toolErrorFromUnknown } from "../error-envelope.js";
17
+ import { withNextSteps } from "../next-step-hints.js";
18
+ import { stalenessFromMeta } from "../staleness.js";
19
+ import { fromToolResult, repoArgShape, toToolResult, withStore, } from "./shared.js";
20
+ const ListDeadCodeInput = {
21
+ ...repoArgShape,
22
+ includeUnreachableExports: z
23
+ .boolean()
24
+ .optional()
25
+ .describe("When true, include exported symbols with no cross-module referrer in the `symbols` list. Default false."),
26
+ limit: z
27
+ .number()
28
+ .int()
29
+ .positive()
30
+ .max(10_000)
31
+ .optional()
32
+ .describe("Maximum number of symbols to return (default 100, max 10000)."),
33
+ filePathPattern: z
34
+ .string()
35
+ .optional()
36
+ .describe("Substring filter applied to each symbol's file path."),
37
+ };
38
+ export async function runListDeadCode(ctx, args) {
39
+ const limit = args.limit ?? 100;
40
+ const includeUnreachable = args.includeUnreachableExports ?? false;
41
+ const pattern = args.filePathPattern;
42
+ const call = await withStore(ctx, args, async (store, resolved) => {
43
+ try {
44
+ const result = await classifyDeadness(store.graph);
45
+ const filterByPath = (s) => pattern === undefined || s.filePath.includes(pattern);
46
+ const dead = result.dead.filter(filterByPath);
47
+ const unreachable = result.unreachableExports.filter(filterByPath);
48
+ const combined = includeUnreachable ? [...dead, ...unreachable] : [...dead];
49
+ const truncated = combined.slice(0, limit);
50
+ const summary = {
51
+ dead: result.dead.length,
52
+ unreachableExports: result.unreachableExports.length,
53
+ ghostCommunities: result.ghostCommunities.length,
54
+ };
55
+ const header = `Dead code in ${resolved.name}: ${summary.dead} dead · ${summary.unreachableExports} unreachable exports · ${summary.ghostCommunities} ghost communities.`;
56
+ const lines = [header];
57
+ if (truncated.length === 0) {
58
+ lines.push("(no non-live symbols match the filter)");
59
+ }
60
+ else {
61
+ lines.push(`Showing ${truncated.length} of ${combined.length}${pattern ? ` · filePath~${pattern}` : ""}:`);
62
+ for (const s of truncated) {
63
+ lines.push(` • [${s.deadness}] ${s.name} [${s.kind}] — ${s.filePath}:${s.startLine}`);
64
+ }
65
+ }
66
+ if (result.ghostCommunities.length > 0) {
67
+ lines.push(`Ghost communities (${result.ghostCommunities.length}):`);
68
+ for (const c of result.ghostCommunities.slice(0, 20)) {
69
+ lines.push(` ⊿ ${c}`);
70
+ }
71
+ }
72
+ const next = [];
73
+ if (summary.dead > 0) {
74
+ next.push("call `remove_dead_code` with dryRun=true to preview the deletion edit plan");
75
+ }
76
+ if (!includeUnreachable && summary.unreachableExports > 0) {
77
+ next.push("re-run with includeUnreachableExports=true to inspect exported-but-unreferenced symbols");
78
+ }
79
+ if (summary.ghostCommunities > 0) {
80
+ next.push("use `context` on a ghost community member to confirm it is truly unreferenced before deletion");
81
+ }
82
+ if (next.length === 0) {
83
+ next.push("graph is clean — no dead code detected");
84
+ }
85
+ return withNextSteps(lines.join("\n"), {
86
+ summary,
87
+ symbols: truncated,
88
+ ghostCommunities: [...result.ghostCommunities],
89
+ }, next, stalenessFromMeta(resolved.meta));
90
+ }
91
+ catch (err) {
92
+ return toolErrorFromUnknown(err);
93
+ }
94
+ });
95
+ return toToolResult(call);
96
+ }
97
+ export function registerListDeadCodeTool(server, ctx) {
98
+ server.registerTool("list_dead_code", {
99
+ title: "List dead and unreachable-export symbols",
100
+ description: "Classify every callable / type in the indexed graph as live, dead, or unreachable-export and return the non-live set. Also surfaces ghost communities — Leiden clusters whose every member is classified non-live.",
101
+ inputSchema: ListDeadCodeInput,
102
+ annotations: {
103
+ readOnlyHint: true,
104
+ destructiveHint: false,
105
+ idempotentHint: true,
106
+ openWorldHint: false,
107
+ },
108
+ }, async (args) => fromToolResult(await runListDeadCode(ctx, args)));
109
+ }
110
+ //# sourceMappingURL=list-dead-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dead-code.js","sourceRoot":"","sources":["../../src/tools/list-dead-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `list_findings_delta` — expose the SARIF baseline diff as an MCP tool.
3
+ *
4
+ * The SARIF baseline snapshot lives at `<repo>/.codehub/baseline.sarif`
5
+ * (frozen via `codehub baseline freeze`); the latest scan lives at
6
+ * `<repo>/.codehub/scan.sarif` (written by `codehub scan` / the `scan`
7
+ * tool). This tool reads both, runs {@link diffSarif}, and returns the
8
+ * four buckets (`new`, `fixed`, `unchanged`, `updated`) reshaped into an
9
+ * agent-friendly per-finding view keyed on the `opencodehub/v1` partial
10
+ * fingerprint.
11
+ *
12
+ * Annotation rationale:
13
+ * readOnlyHint = true — reads two SARIF files; writes nothing.
14
+ * destructiveHint = false — no mutations.
15
+ * openWorldHint = false — no external processes or network.
16
+ * idempotentHint = true — same inputs → same buckets every call.
17
+ *
18
+ * Error handling:
19
+ * - Missing `.codehub/scan.sarif` → tool-level error with a "run
20
+ * `codehub scan` first" hint.
21
+ * - Missing baseline → every current finding bucketed as `new` with a
22
+ * `warning` surfaced alongside the payload so the agent knows the
23
+ * baseline has never been frozen.
24
+ * - Corrupt SARIF JSON / schema violation → `SCHEMA_MISMATCH` envelope.
25
+ */
26
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
27
+ import { type ToolContext, type ToolResult } from "./shared.js";
28
+ interface ListFindingsDeltaArgs {
29
+ readonly repo?: string | undefined;
30
+ readonly repo_uri?: string | undefined;
31
+ readonly baseline?: string | undefined;
32
+ }
33
+ export declare function runListFindingsDelta(ctx: ToolContext, args: ListFindingsDeltaArgs): Promise<ToolResult>;
34
+ export declare function registerListFindingsDeltaTool(server: McpServer, ctx: ToolContext): void;
35
+ export {};
36
+ //# sourceMappingURL=list-findings-delta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-findings-delta.d.ts","sourceRoot":"","sources":["../../src/tools/list-findings-delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAC;AA8CrB,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAiHrB;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAiBvF"}
@@ -0,0 +1,274 @@
1
+ /**
2
+ * `list_findings_delta` — expose the SARIF baseline diff as an MCP tool.
3
+ *
4
+ * The SARIF baseline snapshot lives at `<repo>/.codehub/baseline.sarif`
5
+ * (frozen via `codehub baseline freeze`); the latest scan lives at
6
+ * `<repo>/.codehub/scan.sarif` (written by `codehub scan` / the `scan`
7
+ * tool). This tool reads both, runs {@link diffSarif}, and returns the
8
+ * four buckets (`new`, `fixed`, `unchanged`, `updated`) reshaped into an
9
+ * agent-friendly per-finding view keyed on the `opencodehub/v1` partial
10
+ * fingerprint.
11
+ *
12
+ * Annotation rationale:
13
+ * readOnlyHint = true — reads two SARIF files; writes nothing.
14
+ * destructiveHint = false — no mutations.
15
+ * openWorldHint = false — no external processes or network.
16
+ * idempotentHint = true — same inputs → same buckets every call.
17
+ *
18
+ * Error handling:
19
+ * - Missing `.codehub/scan.sarif` → tool-level error with a "run
20
+ * `codehub scan` first" hint.
21
+ * - Missing baseline → every current finding bucketed as `new` with a
22
+ * `warning` surfaced alongside the payload so the agent knows the
23
+ * baseline has never been frozen.
24
+ * - Corrupt SARIF JSON / schema violation → `SCHEMA_MISMATCH` envelope.
25
+ */
26
+ // biome-ignore-all lint/complexity/useLiteralKeys: dot-access disallowed on Record index signatures
27
+ import { readFile } from "node:fs/promises";
28
+ import { resolve } from "node:path";
29
+ import { diffSarif, SarifLogSchema, } from "@opencodehub/sarif";
30
+ import { resolveRepoMetaDir } from "@opencodehub/storage";
31
+ import { z } from "zod";
32
+ import { toolError, toolErrorFromUnknown } from "../error-envelope.js";
33
+ import { withNextSteps } from "../next-step-hints.js";
34
+ import { stalenessFromMeta } from "../staleness.js";
35
+ import { fromToolResult, repoArgShape, toToolResult, withStore, } from "./shared.js";
36
+ const ListFindingsDeltaInput = {
37
+ ...repoArgShape,
38
+ baseline: z
39
+ .string()
40
+ .optional()
41
+ .describe("Custom path to a baseline SARIF log. When omitted, defaults to `<repo>/.codehub/baseline.sarif`."),
42
+ };
43
+ const OPENCODEHUB_FINGERPRINT_KEY = "opencodehub/v1";
44
+ const EMPTY_SARIF_LOG = {
45
+ version: "2.1.0",
46
+ runs: [],
47
+ };
48
+ export async function runListFindingsDelta(ctx, args) {
49
+ const call = await withStore(ctx, args, async (_store, resolved) => {
50
+ try {
51
+ const metaDir = resolveRepoMetaDir(resolved.repoPath);
52
+ const currentPath = resolve(`${metaDir}/scan.sarif`);
53
+ const baselinePath = resolve(args.baseline ?? `${metaDir}/baseline.sarif`);
54
+ const currentRead = await readSarif(currentPath);
55
+ if (currentRead.kind === "missing") {
56
+ return toolError("NOT_FOUND", `No scan log found at ${currentPath}`, "Run `codehub scan` (or the `scan` MCP tool) in the target repo to generate .codehub/scan.sarif before diffing.");
57
+ }
58
+ if (currentRead.kind === "invalid") {
59
+ return toolError("SCHEMA_MISMATCH", `scan.sarif at ${currentPath} failed SARIF 2.1.0 validation: ${currentRead.message}`, "Regenerate the scan log with `codehub scan`; the existing file may be truncated or from an older format.");
60
+ }
61
+ const baselineRead = await readSarif(baselinePath);
62
+ const warnings = [];
63
+ let diff;
64
+ // Fast path: the current log already carries per-result
65
+ // `baselineState` tags (written by `codehub scan --baseline` and
66
+ // mirrored to the `baseline_state` column by `codehub ingest-sarif`).
67
+ // Reuse them instead of re-running the diff — the SARIF on disk is
68
+ // the source of truth for the `baseline_state` column, so reading
69
+ // from it is equivalent to reading from the column.
70
+ const tagged = reuseStoredBaselineStates(currentRead.log);
71
+ if (tagged !== undefined) {
72
+ diff = tagged;
73
+ if (baselineRead.kind === "missing") {
74
+ warnings.push(`No baseline found at ${baselinePath}; returning baselineState tags already written by the most recent scan.`);
75
+ }
76
+ }
77
+ else if (baselineRead.kind === "missing") {
78
+ warnings.push(`No baseline found at ${baselinePath}; treating every current finding as new. Run \`codehub baseline freeze\` to establish a baseline.`);
79
+ diff = diffSarif(EMPTY_SARIF_LOG, currentRead.log);
80
+ }
81
+ else if (baselineRead.kind === "invalid") {
82
+ return toolError("SCHEMA_MISMATCH", `baseline.sarif at ${baselinePath} failed SARIF 2.1.0 validation: ${baselineRead.message}`, "Re-freeze the baseline with `codehub baseline freeze`; the existing file may be truncated or from an older format.");
83
+ }
84
+ else {
85
+ diff = diffSarif(baselineRead.log, currentRead.log);
86
+ }
87
+ const findings = {
88
+ new: diff.new.map((r) => toRow(r, "new")),
89
+ fixed: diff.fixed.map((r) => toRow(r, "fixed")),
90
+ unchanged: diff.unchanged.map((r) => toRow(r, "unchanged")),
91
+ updated: diff.updated.map((r) => toRow(r, "updated")),
92
+ };
93
+ const summary = {
94
+ new: findings.new.length,
95
+ fixed: findings.fixed.length,
96
+ unchanged: findings.unchanged.length,
97
+ updated: findings.updated.length,
98
+ };
99
+ const header = `Findings delta for ${resolved.name}: ${summary.new} new · ${summary.fixed} fixed · ${summary.unchanged} unchanged · ${summary.updated} updated`;
100
+ const lines = [header];
101
+ if (warnings.length > 0) {
102
+ for (const w of warnings)
103
+ lines.push(`Warning: ${w}`);
104
+ }
105
+ if (summary.new > 0) {
106
+ lines.push("New findings:");
107
+ for (const row of findings.new.slice(0, 25)) {
108
+ lines.push(formatRow(row));
109
+ }
110
+ if (findings.new.length > 25) {
111
+ lines.push(` … and ${findings.new.length - 25} more`);
112
+ }
113
+ }
114
+ const next = summary.new > 0
115
+ ? [
116
+ "call `context` with a new finding's filePath for caller/callee neighbours",
117
+ "call `verdict` to see how the delta maps to a PR decision",
118
+ ]
119
+ : summary.fixed > 0
120
+ ? ["call `baseline freeze` via the CLI to adopt the improved state as the new baseline"]
121
+ : [
122
+ "call `list_findings` for the full non-delta finding list",
123
+ "call `scan` to refresh .codehub/scan.sarif",
124
+ ];
125
+ return withNextSteps(lines.join("\n"), {
126
+ summary,
127
+ findings,
128
+ baselinePath,
129
+ currentPath,
130
+ warnings,
131
+ }, next, stalenessFromMeta(resolved.meta));
132
+ }
133
+ catch (err) {
134
+ return toolErrorFromUnknown(err);
135
+ }
136
+ });
137
+ return toToolResult(call);
138
+ }
139
+ export function registerListFindingsDeltaTool(server, ctx) {
140
+ server.registerTool("list_findings_delta", {
141
+ title: "Diff SARIF findings against baseline",
142
+ description: "Diff the latest scan (`.codehub/scan.sarif`) against the frozen baseline (`.codehub/baseline.sarif` by default) and return findings bucketed into new / fixed / unchanged / updated, keyed on `partialFingerprints['opencodehub/v1']`. Read-only: reads SARIF files, writes nothing.",
143
+ inputSchema: ListFindingsDeltaInput,
144
+ annotations: {
145
+ readOnlyHint: true,
146
+ destructiveHint: false,
147
+ openWorldHint: false,
148
+ idempotentHint: true,
149
+ },
150
+ }, async (args) => fromToolResult(await runListFindingsDelta(ctx, args)));
151
+ }
152
+ async function readSarif(path) {
153
+ let raw;
154
+ try {
155
+ raw = await readFile(path, "utf8");
156
+ }
157
+ catch (err) {
158
+ if (err.code === "ENOENT")
159
+ return { kind: "missing" };
160
+ throw err;
161
+ }
162
+ let parsedJson;
163
+ try {
164
+ parsedJson = JSON.parse(raw);
165
+ }
166
+ catch (err) {
167
+ const message = err instanceof Error ? err.message : String(err);
168
+ return { kind: "invalid", message: `JSON parse error: ${message}` };
169
+ }
170
+ const validated = SarifLogSchema.safeParse(parsedJson);
171
+ if (!validated.success) {
172
+ return { kind: "invalid", message: validated.error.message };
173
+ }
174
+ return { kind: "ok", log: validated.data };
175
+ }
176
+ function toRow(result, state) {
177
+ const physical = result.locations?.[0]?.physicalLocation;
178
+ const uri = typeof physical?.artifactLocation.uri === "string" ? physical.artifactLocation.uri : "";
179
+ const startLine = physical?.region?.startLine;
180
+ const severity = typeof result.level === "string" ? result.level : "none";
181
+ const messageText = typeof result.message?.text === "string" ? result.message.text : "";
182
+ const fingerprint = fingerprintOf(result);
183
+ const scannerId = scannerIdOf(result);
184
+ const row = {
185
+ ruleId: typeof result.ruleId === "string" ? result.ruleId : "",
186
+ severity,
187
+ scannerId,
188
+ message: messageText,
189
+ filePath: uri,
190
+ baselineState: state,
191
+ ...(typeof startLine === "number" && Number.isFinite(startLine) ? { startLine } : {}),
192
+ ...(fingerprint !== undefined ? { fingerprint } : {}),
193
+ };
194
+ return row;
195
+ }
196
+ function fingerprintOf(result) {
197
+ const pf = result.partialFingerprints;
198
+ if (pf === undefined || pf === null)
199
+ return undefined;
200
+ const candidate = pf[OPENCODEHUB_FINGERPRINT_KEY];
201
+ return typeof candidate === "string" && candidate.length > 0 ? candidate : undefined;
202
+ }
203
+ /**
204
+ * Extract a scanner id for display purposes. SARIF does not carry a
205
+ * per-result scanner name (only per-run). We check the result properties
206
+ * bag first (opencodehub enrichment stashes the source tool there) and
207
+ * fall back to the rule id's prefix when that is absent.
208
+ */
209
+ function scannerIdOf(result) {
210
+ const props = result.properties;
211
+ if (props !== undefined && props !== null) {
212
+ const ocProps = props["opencodehub"];
213
+ if (ocProps !== null && typeof ocProps === "object") {
214
+ const scannerId = ocProps["scannerId"];
215
+ if (typeof scannerId === "string" && scannerId.length > 0)
216
+ return scannerId;
217
+ }
218
+ const flat = props["scannerId"];
219
+ if (typeof flat === "string" && flat.length > 0)
220
+ return flat;
221
+ }
222
+ const ruleId = typeof result.ruleId === "string" ? result.ruleId : "";
223
+ const dot = ruleId.indexOf(".");
224
+ if (dot > 0)
225
+ return ruleId.slice(0, dot);
226
+ return "unknown";
227
+ }
228
+ function formatRow(row) {
229
+ const loc = row.startLine !== undefined ? `${row.filePath}:${row.startLine}` : row.filePath;
230
+ const msg = row.message ? ` — ${row.message}` : "";
231
+ return ` - [${row.severity}] ${row.scannerId}:${row.ruleId} at ${loc}${msg}`;
232
+ }
233
+ /**
234
+ * Walk every SARIF result in `log`; if at least one result carries a
235
+ * `baselineState` tag, rebuild a {@link DiffResult} directly from those
236
+ * tags without re-running the diff. Returns `undefined` when no tags are
237
+ * present so the caller can fall back to the full diff path.
238
+ *
239
+ * Baseline-only findings (`fixed`) aren't re-emitted by the scanner path,
240
+ * so the `fixed` bucket is always empty here — consumers that need it
241
+ * must still run the full diff against a frozen baseline.
242
+ */
243
+ function reuseStoredBaselineStates(log) {
244
+ const newR = [];
245
+ const unchanged = [];
246
+ const updated = [];
247
+ let anyTagged = false;
248
+ for (const run of log.runs) {
249
+ const results = run.results;
250
+ if (!Array.isArray(results))
251
+ continue;
252
+ for (const r of results) {
253
+ if (r === undefined)
254
+ continue;
255
+ const tag = r.baselineState;
256
+ if (tag === "new") {
257
+ newR.push(r);
258
+ anyTagged = true;
259
+ }
260
+ else if (tag === "unchanged") {
261
+ unchanged.push(r);
262
+ anyTagged = true;
263
+ }
264
+ else if (tag === "updated") {
265
+ updated.push(r);
266
+ anyTagged = true;
267
+ }
268
+ }
269
+ }
270
+ if (!anyTagged)
271
+ return undefined;
272
+ return { new: newR, fixed: [], unchanged, updated };
273
+ }
274
+ //# sourceMappingURL=list-findings-delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-findings-delta.js","sourceRoot":"","sources":["../../src/tools/list-findings-delta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `list_findings` — enumerate Finding nodes for an indexed repo.
3
+ *
4
+ * Finding nodes are produced by `codehub ingest-sarif` (or `codehub scan`
5
+ * via its built-in ingestion step). Every node carries `scanner_id`,
6
+ * `rule_id`, `severity`, and `message` plus a flat `properties_bag`
7
+ * JSON string for the scanner's custom properties.
8
+ *
9
+ * Filters (all optional):
10
+ * - `severity` — restrict to one SARIF level.
11
+ * - `scanner` — restrict to a single scanner id.
12
+ * - `ruleId` — restrict to a single rule id.
13
+ * - `filePath` — substring match against `file_path`.
14
+ * - `limit` — row cap (default 500, max 10_000).
15
+ */
16
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
17
+ import { type ToolContext, type ToolResult } from "./shared.js";
18
+ interface ListFindingsArgs {
19
+ readonly repo?: string | undefined;
20
+ readonly repo_uri?: string | undefined;
21
+ readonly severity?: "error" | "warning" | "note" | "none" | undefined;
22
+ readonly scanner?: string | undefined;
23
+ readonly ruleId?: string | undefined;
24
+ readonly filePath?: string | undefined;
25
+ readonly limit?: number | undefined;
26
+ }
27
+ export declare function runListFindings(ctx: ToolContext, args: ListFindingsArgs): Promise<ToolResult>;
28
+ export declare function registerListFindingsTool(server: McpServer, ctx: ToolContext): void;
29
+ export {};
30
+ //# sourceMappingURL=list-findings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-findings.d.ts","sourceRoot":"","sources":["../../src/tools/list-findings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAC;AAsCrB,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,UAAU,CAAC,CAqFrB;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAiBlF"}