hound-mcp 0.2.2 → 0.2.3
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.
- package/README.md +1 -1
- package/dist/index.js +44 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://github.com/tiluckdave/hound-mcp/actions/workflows/ci.yml)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[Hound MCP Deployment Diagram](https://github.com/user-attachments/assets/5b1908b8-2bdc-41c3-b95a-bb3677e6e5c3)
|
|
11
11
|
|
|
12
12
|
## Why Hound?
|
|
13
13
|
|
package/dist/index.js
CHANGED
|
@@ -153,7 +153,7 @@ var ECOSYSTEM_MAP = {
|
|
|
153
153
|
async function get(path) {
|
|
154
154
|
const url = `${BASE_URL}${path}`;
|
|
155
155
|
const res = await fetch(url, {
|
|
156
|
-
headers: { "User-Agent":
|
|
156
|
+
headers: { "User-Agent": `hound-mcp/${"0.2.3"}` }
|
|
157
157
|
});
|
|
158
158
|
if (!res.ok) {
|
|
159
159
|
const body = await res.text().catch(() => "");
|
|
@@ -218,7 +218,7 @@ async function post(path, body) {
|
|
|
218
218
|
method: "POST",
|
|
219
219
|
headers: {
|
|
220
220
|
"Content-Type": "application/json",
|
|
221
|
-
"User-Agent":
|
|
221
|
+
"User-Agent": `hound-mcp/${"0.2.3"}`
|
|
222
222
|
},
|
|
223
223
|
body: JSON.stringify(body)
|
|
224
224
|
});
|
|
@@ -263,7 +263,7 @@ async function queryVulnsBatch(packages) {
|
|
|
263
263
|
async function getVuln(vulnId) {
|
|
264
264
|
const url = `${BASE_URL2}/vulns/${encodeURIComponent(vulnId)}`;
|
|
265
265
|
const res = await fetch(url, {
|
|
266
|
-
headers: { "User-Agent":
|
|
266
|
+
headers: { "User-Agent": `hound-mcp/${"0.2.3"}` }
|
|
267
267
|
});
|
|
268
268
|
if (!res.ok) {
|
|
269
269
|
const text = await res.text().catch(() => "");
|
|
@@ -420,7 +420,11 @@ function register(server) {
|
|
|
420
420
|
|
|
421
421
|
// src/tools/inspect.ts
|
|
422
422
|
import { z as z5 } from "zod/v4";
|
|
423
|
+
|
|
424
|
+
// src/constants/ecosystems.ts
|
|
423
425
|
var ECOSYSTEM_VALUES = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
426
|
+
|
|
427
|
+
// src/tools/inspect.ts
|
|
424
428
|
function register2(server) {
|
|
425
429
|
return server.registerTool(
|
|
426
430
|
"hound_inspect",
|
|
@@ -522,7 +526,13 @@ function scorecardGrade(score) {
|
|
|
522
526
|
|
|
523
527
|
// src/tools/popular.ts
|
|
524
528
|
import { z as z6 } from "zod/v4";
|
|
525
|
-
|
|
529
|
+
|
|
530
|
+
// src/utils/getDefaultVersion.ts
|
|
531
|
+
function getDefaultVersion(versions) {
|
|
532
|
+
return versions.find((v) => v.isDefault) ?? versions.at(-1);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/tools/popular.ts
|
|
526
536
|
var POPULAR_DEFAULTS = {
|
|
527
537
|
npm: [
|
|
528
538
|
"express",
|
|
@@ -578,7 +588,7 @@ function register3(server) {
|
|
|
578
588
|
{
|
|
579
589
|
description: "Scan a list of popular (or user-specified) packages for known vulnerabilities. Quickly surface which widely-used packages in an ecosystem have open security issues.",
|
|
580
590
|
inputSchema: {
|
|
581
|
-
ecosystem: z6.enum(
|
|
591
|
+
ecosystem: z6.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)"),
|
|
582
592
|
packages: z6.array(z6.string()).optional().describe(
|
|
583
593
|
"Specific package names to check. If omitted, uses a curated list of popular packages for the ecosystem."
|
|
584
594
|
)
|
|
@@ -600,7 +610,7 @@ function register3(server) {
|
|
|
600
610
|
const packageResults = await Promise.allSettled(
|
|
601
611
|
names.map(async (name) => {
|
|
602
612
|
const pkg = await getPackage(eco, name);
|
|
603
|
-
const defaultVersion = pkg.versions
|
|
613
|
+
const defaultVersion = getDefaultVersion(pkg.versions);
|
|
604
614
|
return {
|
|
605
615
|
name,
|
|
606
616
|
version: defaultVersion?.versionKey.version ?? "unknown"
|
|
@@ -658,7 +668,6 @@ function register3(server) {
|
|
|
658
668
|
|
|
659
669
|
// src/tools/tree.ts
|
|
660
670
|
import { z as z7 } from "zod/v4";
|
|
661
|
-
var ECOSYSTEM_VALUES3 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
662
671
|
function register4(server) {
|
|
663
672
|
return server.registerTool(
|
|
664
673
|
"hound_tree",
|
|
@@ -667,7 +676,7 @@ function register4(server) {
|
|
|
667
676
|
inputSchema: {
|
|
668
677
|
name: z7.string().describe("Package name"),
|
|
669
678
|
version: z7.string().describe("Package version"),
|
|
670
|
-
ecosystem: z7.enum(
|
|
679
|
+
ecosystem: z7.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)"),
|
|
671
680
|
maxDepth: z7.number().int().min(1).max(10).default(3).describe("Maximum depth to display (default: 3, max: 10)")
|
|
672
681
|
}
|
|
673
682
|
},
|
|
@@ -741,7 +750,6 @@ function renderNode(lines, nodes, children, nodeIndex, depth, maxDepth, visited)
|
|
|
741
750
|
|
|
742
751
|
// src/tools/typosquat.ts
|
|
743
752
|
import { z as z8 } from "zod/v4";
|
|
744
|
-
var ECOSYSTEM_VALUES4 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
745
753
|
function generateTypos(name) {
|
|
746
754
|
const variants = /* @__PURE__ */ new Set();
|
|
747
755
|
for (let i = 0; i < name.length; i++) {
|
|
@@ -774,7 +782,7 @@ function register5(server) {
|
|
|
774
782
|
description: "Check if a package name looks like a typosquat of a popular package. Generates likely typo variants and checks which ones exist in the registry.",
|
|
775
783
|
inputSchema: {
|
|
776
784
|
name: z8.string().describe("Package name to check"),
|
|
777
|
-
ecosystem: z8.enum(
|
|
785
|
+
ecosystem: z8.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
778
786
|
}
|
|
779
787
|
},
|
|
780
788
|
async ({ name, ecosystem }) => {
|
|
@@ -1099,7 +1107,8 @@ ${icon} ${sev} (${group.length})`);
|
|
|
1099
1107
|
|
|
1100
1108
|
// src/tools/compare.ts
|
|
1101
1109
|
import { z as z10 } from "zod/v4";
|
|
1102
|
-
|
|
1110
|
+
|
|
1111
|
+
// src/constants/licenses.ts
|
|
1103
1112
|
var COPYLEFT_LICENSES = /* @__PURE__ */ new Set([
|
|
1104
1113
|
"GPL-2.0",
|
|
1105
1114
|
"GPL-2.0-only",
|
|
@@ -1121,11 +1130,20 @@ var COPYLEFT_LICENSES = /* @__PURE__ */ new Set([
|
|
|
1121
1130
|
"EPL-1.0",
|
|
1122
1131
|
"EPL-2.0"
|
|
1123
1132
|
]);
|
|
1133
|
+
var NETWORK_COPYLEFT = /* @__PURE__ */ new Set([
|
|
1134
|
+
"AGPL-3.0",
|
|
1135
|
+
"AGPL-3.0-only",
|
|
1136
|
+
"AGPL-3.0-or-later",
|
|
1137
|
+
"EUPL-1.1",
|
|
1138
|
+
"EUPL-1.2"
|
|
1139
|
+
]);
|
|
1140
|
+
|
|
1141
|
+
// src/tools/compare.ts
|
|
1124
1142
|
async function gatherPackageData(eco, name) {
|
|
1125
1143
|
let defaultVersion;
|
|
1126
1144
|
try {
|
|
1127
1145
|
const pkg = await getPackage(eco, name);
|
|
1128
|
-
const defaultV = pkg.versions
|
|
1146
|
+
const defaultV = getDefaultVersion(pkg.versions);
|
|
1129
1147
|
if (!defaultV) return null;
|
|
1130
1148
|
defaultVersion = defaultV.versionKey.version;
|
|
1131
1149
|
} catch {
|
|
@@ -1181,7 +1199,7 @@ function register7(server) {
|
|
|
1181
1199
|
inputSchema: {
|
|
1182
1200
|
package_a: z10.string().describe("First package name"),
|
|
1183
1201
|
package_b: z10.string().describe("Second package name"),
|
|
1184
|
-
ecosystem: z10.enum(
|
|
1202
|
+
ecosystem: z10.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
1185
1203
|
}
|
|
1186
1204
|
},
|
|
1187
1205
|
async ({ package_a, package_b, ecosystem }) => {
|
|
@@ -1290,28 +1308,6 @@ function register7(server) {
|
|
|
1290
1308
|
|
|
1291
1309
|
// src/tools/license-check.ts
|
|
1292
1310
|
import { z as z11 } from "zod/v4";
|
|
1293
|
-
var COPYLEFT_LICENSES2 = /* @__PURE__ */ new Set([
|
|
1294
|
-
"GPL-2.0",
|
|
1295
|
-
"GPL-2.0-only",
|
|
1296
|
-
"GPL-2.0-or-later",
|
|
1297
|
-
"GPL-3.0",
|
|
1298
|
-
"GPL-3.0-only",
|
|
1299
|
-
"GPL-3.0-or-later",
|
|
1300
|
-
"AGPL-3.0",
|
|
1301
|
-
"AGPL-3.0-only",
|
|
1302
|
-
"AGPL-3.0-or-later",
|
|
1303
|
-
"LGPL-2.0",
|
|
1304
|
-
"LGPL-2.1",
|
|
1305
|
-
"LGPL-3.0",
|
|
1306
|
-
"EUPL-1.1",
|
|
1307
|
-
"EUPL-1.2",
|
|
1308
|
-
"MPL-2.0",
|
|
1309
|
-
"OSL-3.0",
|
|
1310
|
-
"CDDL-1.0",
|
|
1311
|
-
"EPL-1.0",
|
|
1312
|
-
"EPL-2.0"
|
|
1313
|
-
]);
|
|
1314
|
-
var NETWORK_COPYLEFT = /* @__PURE__ */ new Set(["AGPL-3.0", "AGPL-3.0-only", "AGPL-3.0-or-later", "EUPL-1.1", "EUPL-1.2"]);
|
|
1315
1311
|
var POLICY_ALLOWLISTS = {
|
|
1316
1312
|
permissive: /* @__PURE__ */ new Set([
|
|
1317
1313
|
"MIT",
|
|
@@ -1354,7 +1350,7 @@ var POLICY_ALLOWLISTS = {
|
|
|
1354
1350
|
};
|
|
1355
1351
|
function classifyLicense(license) {
|
|
1356
1352
|
if (NETWORK_COPYLEFT.has(license)) return "network-copyleft";
|
|
1357
|
-
if (
|
|
1353
|
+
if (COPYLEFT_LICENSES.has(license)) {
|
|
1358
1354
|
if (license.startsWith("LGPL") || license === "MPL-2.0" || license === "EPL-1.0" || license === "EPL-2.0" || license === "CDDL-1.0") {
|
|
1359
1355
|
return "weak-copyleft";
|
|
1360
1356
|
}
|
|
@@ -1490,28 +1486,6 @@ Supported: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo
|
|
|
1490
1486
|
|
|
1491
1487
|
// src/tools/preinstall.ts
|
|
1492
1488
|
import { z as z12 } from "zod/v4";
|
|
1493
|
-
var ECOSYSTEM_VALUES6 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
1494
|
-
var COPYLEFT_LICENSES3 = /* @__PURE__ */ new Set([
|
|
1495
|
-
"GPL-2.0",
|
|
1496
|
-
"GPL-2.0-only",
|
|
1497
|
-
"GPL-2.0-or-later",
|
|
1498
|
-
"GPL-3.0",
|
|
1499
|
-
"GPL-3.0-only",
|
|
1500
|
-
"GPL-3.0-or-later",
|
|
1501
|
-
"AGPL-3.0",
|
|
1502
|
-
"AGPL-3.0-only",
|
|
1503
|
-
"AGPL-3.0-or-later",
|
|
1504
|
-
"LGPL-2.0",
|
|
1505
|
-
"LGPL-2.1",
|
|
1506
|
-
"LGPL-3.0",
|
|
1507
|
-
"EUPL-1.1",
|
|
1508
|
-
"EUPL-1.2",
|
|
1509
|
-
"MPL-2.0",
|
|
1510
|
-
"OSL-3.0",
|
|
1511
|
-
"CDDL-1.0",
|
|
1512
|
-
"EPL-1.0",
|
|
1513
|
-
"EPL-2.0"
|
|
1514
|
-
]);
|
|
1515
1489
|
function register9(server) {
|
|
1516
1490
|
return server.registerTool(
|
|
1517
1491
|
"hound_preinstall",
|
|
@@ -1520,7 +1494,7 @@ function register9(server) {
|
|
|
1520
1494
|
inputSchema: {
|
|
1521
1495
|
name: z12.string().describe("Package name"),
|
|
1522
1496
|
version: z12.string().optional().describe("Package version (defaults to latest)"),
|
|
1523
|
-
ecosystem: z12.enum(
|
|
1497
|
+
ecosystem: z12.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
1524
1498
|
}
|
|
1525
1499
|
},
|
|
1526
1500
|
async ({ name, version, ecosystem }) => {
|
|
@@ -1529,7 +1503,7 @@ function register9(server) {
|
|
|
1529
1503
|
if (!resolvedVersion) {
|
|
1530
1504
|
try {
|
|
1531
1505
|
const pkg2 = await getPackage(eco, name);
|
|
1532
|
-
const defaultV = pkg2.versions
|
|
1506
|
+
const defaultV = getDefaultVersion(pkg2.versions);
|
|
1533
1507
|
resolvedVersion = defaultV?.versionKey.version ?? "";
|
|
1534
1508
|
} catch {
|
|
1535
1509
|
return {
|
|
@@ -1617,7 +1591,7 @@ function register9(server) {
|
|
|
1617
1591
|
const licenses = pkg.licenses ?? [];
|
|
1618
1592
|
if (licenses.length === 0) {
|
|
1619
1593
|
issues.push({ level: "warn", message: "License unknown" });
|
|
1620
|
-
} else if (licenses.some((l) =>
|
|
1594
|
+
} else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {
|
|
1621
1595
|
issues.push({
|
|
1622
1596
|
level: "warn",
|
|
1623
1597
|
message: `Copyleft license detected: ${licenses.join(", ")}`
|
|
@@ -1679,28 +1653,6 @@ function register9(server) {
|
|
|
1679
1653
|
|
|
1680
1654
|
// src/tools/score.ts
|
|
1681
1655
|
import { z as z13 } from "zod/v4";
|
|
1682
|
-
var ECOSYSTEM_VALUES7 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
1683
|
-
var COPYLEFT_LICENSES4 = /* @__PURE__ */ new Set([
|
|
1684
|
-
"GPL-2.0",
|
|
1685
|
-
"GPL-2.0-only",
|
|
1686
|
-
"GPL-2.0-or-later",
|
|
1687
|
-
"GPL-3.0",
|
|
1688
|
-
"GPL-3.0-only",
|
|
1689
|
-
"GPL-3.0-or-later",
|
|
1690
|
-
"AGPL-3.0",
|
|
1691
|
-
"AGPL-3.0-only",
|
|
1692
|
-
"AGPL-3.0-or-later",
|
|
1693
|
-
"LGPL-2.0",
|
|
1694
|
-
"LGPL-2.1",
|
|
1695
|
-
"LGPL-3.0",
|
|
1696
|
-
"EUPL-1.1",
|
|
1697
|
-
"EUPL-1.2",
|
|
1698
|
-
"MPL-2.0",
|
|
1699
|
-
"OSL-3.0",
|
|
1700
|
-
"CDDL-1.0",
|
|
1701
|
-
"EPL-1.0",
|
|
1702
|
-
"EPL-2.0"
|
|
1703
|
-
]);
|
|
1704
1656
|
function letterGrade(score) {
|
|
1705
1657
|
if (score >= 90) return "A";
|
|
1706
1658
|
if (score >= 75) return "B";
|
|
@@ -1730,7 +1682,7 @@ function register10(server) {
|
|
|
1730
1682
|
inputSchema: {
|
|
1731
1683
|
name: z13.string().describe("Package name"),
|
|
1732
1684
|
version: z13.string().describe("Package version"),
|
|
1733
|
-
ecosystem: z13.enum(
|
|
1685
|
+
ecosystem: z13.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
1734
1686
|
}
|
|
1735
1687
|
},
|
|
1736
1688
|
async ({ name, version, ecosystem }) => {
|
|
@@ -1789,7 +1741,7 @@ function register10(server) {
|
|
|
1789
1741
|
const licenses = pkg.licenses ?? [];
|
|
1790
1742
|
if (licenses.length === 0) {
|
|
1791
1743
|
licenseScore = 5;
|
|
1792
|
-
} else if (licenses.some((l) =>
|
|
1744
|
+
} else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {
|
|
1793
1745
|
licenseScore = 8;
|
|
1794
1746
|
}
|
|
1795
1747
|
const total = vulnScore + scorecardScore + recencyScore + licenseScore;
|
|
@@ -1829,7 +1781,7 @@ function register10(server) {
|
|
|
1829
1781
|
lines.push(`\u{1F4C5} Published ${daysSince} days ago`);
|
|
1830
1782
|
if (licenses.length === 0) {
|
|
1831
1783
|
lines.push("\u26A0\uFE0F License unknown");
|
|
1832
|
-
} else if (licenses.some((l) =>
|
|
1784
|
+
} else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {
|
|
1833
1785
|
lines.push(`\u26A0\uFE0F Copyleft license: ${licenses.join(", ")}`);
|
|
1834
1786
|
} else {
|
|
1835
1787
|
lines.push(`\u2705 License: ${licenses.join(", ")}`);
|
|
@@ -1845,7 +1797,6 @@ function register10(server) {
|
|
|
1845
1797
|
|
|
1846
1798
|
// src/tools/upgrade.ts
|
|
1847
1799
|
import { z as z14 } from "zod/v4";
|
|
1848
|
-
var ECOSYSTEM_VALUES8 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
1849
1800
|
function parseVersion(v) {
|
|
1850
1801
|
return v.split(".").map((p) => parseInt(p.replace(/[^0-9]/g, ""), 10) || 0);
|
|
1851
1802
|
}
|
|
@@ -1866,7 +1817,7 @@ function register11(server) {
|
|
|
1866
1817
|
inputSchema: {
|
|
1867
1818
|
name: z14.string().describe("Package name (e.g. express, lodash)"),
|
|
1868
1819
|
version: z14.string().describe("Current vulnerable version (e.g. 4.17.20)"),
|
|
1869
|
-
ecosystem: z14.enum(
|
|
1820
|
+
ecosystem: z14.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
1870
1821
|
}
|
|
1871
1822
|
},
|
|
1872
1823
|
async ({ name, version, ecosystem }) => {
|
|
@@ -1903,7 +1854,7 @@ This may be the latest version already.`
|
|
|
1903
1854
|
toCheck.map((v) => ({ ecosystem: eco, name, version: v }))
|
|
1904
1855
|
);
|
|
1905
1856
|
const safeVersions = toCheck.filter((_, i) => (vulnResults[i]?.length ?? 0) === 0);
|
|
1906
|
-
const latestVersion = candidates
|
|
1857
|
+
const latestVersion = candidates.at(-1) ?? version;
|
|
1907
1858
|
const latestVulns = vulnResults[toCheck.indexOf(latestVersion)] ?? [];
|
|
1908
1859
|
const lines = [
|
|
1909
1860
|
`\u{1F50D} Safe upgrade finder: ${name} (${ecosystem})`,
|
|
@@ -1920,7 +1871,7 @@ This may be the latest version already.`
|
|
|
1920
1871
|
lines.push(" \u2022 Evaluating an alternative package via hound_compare");
|
|
1921
1872
|
} else {
|
|
1922
1873
|
const minimum = safeVersions[0] ?? "";
|
|
1923
|
-
const latest = safeVersions
|
|
1874
|
+
const latest = safeVersions.at(-1) ?? "";
|
|
1924
1875
|
lines.push(`\u2705 Safe upgrade available`);
|
|
1925
1876
|
lines.push("");
|
|
1926
1877
|
lines.push(` Minimum safe version: ${minimum}`);
|
|
@@ -1928,7 +1879,7 @@ This may be the latest version already.`
|
|
|
1928
1879
|
lines.push(` Latest safe version: ${latest}`);
|
|
1929
1880
|
}
|
|
1930
1881
|
lines.push("");
|
|
1931
|
-
if (latestVulns.length > 0 && safeVersions
|
|
1882
|
+
if (latestVulns.length > 0 && safeVersions.at(-1) !== latestVersion) {
|
|
1932
1883
|
lines.push(`\u26A0\uFE0F Latest version (${latestVersion}) still has ${latestVulns.length} known vuln(s).`);
|
|
1933
1884
|
lines.push(` Recommended: upgrade to ${latest}`);
|
|
1934
1885
|
} else {
|
|
@@ -1950,7 +1901,6 @@ This may be the latest version already.`
|
|
|
1950
1901
|
|
|
1951
1902
|
// src/tools/vulns.ts
|
|
1952
1903
|
import { z as z15 } from "zod/v4";
|
|
1953
|
-
var ECOSYSTEM_VALUES9 = ["npm", "pypi", "go", "maven", "cargo", "nuget", "rubygems"];
|
|
1954
1904
|
var SEVERITY_ICON2 = {
|
|
1955
1905
|
CRITICAL: "\u{1F534}",
|
|
1956
1906
|
HIGH: "\u{1F7E0}",
|
|
@@ -1966,7 +1916,7 @@ function register12(server) {
|
|
|
1966
1916
|
inputSchema: {
|
|
1967
1917
|
name: z15.string().describe("Package name (e.g. express, lodash)"),
|
|
1968
1918
|
version: z15.string().describe("Package version (e.g. 4.18.2)"),
|
|
1969
|
-
ecosystem: z15.enum(
|
|
1919
|
+
ecosystem: z15.enum(ECOSYSTEM_VALUES).default("npm").describe("Package ecosystem (default: npm)")
|
|
1970
1920
|
}
|
|
1971
1921
|
},
|
|
1972
1922
|
async ({ name, version, ecosystem }) => {
|
|
@@ -2044,7 +1994,7 @@ This checks the OSV database which covers GitHub Advisory Database, NVD, and mor
|
|
|
2044
1994
|
|
|
2045
1995
|
// src/server.ts
|
|
2046
1996
|
var SERVER_NAME = "hound-mcp";
|
|
2047
|
-
var SERVER_VERSION = "0.2.
|
|
1997
|
+
var SERVER_VERSION = "0.2.3";
|
|
2048
1998
|
function createServer() {
|
|
2049
1999
|
const server = new McpServer({
|
|
2050
2000
|
name: SERVER_NAME,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/prompts/package_evaluation.ts","../src/prompts/pre_release_check.ts","../src/prompts/security_audit.ts","../src/prompts/index.ts","../src/tools/advisories.ts","../src/api/depsdev.ts","../src/api/osv.ts","../src/tools/inspect.ts","../src/tools/popular.ts","../src/tools/tree.ts","../src/tools/typosquat.ts","../src/tools/audit.ts","../src/parsers/index.ts","../src/tools/compare.ts","../src/tools/license-check.ts","../src/tools/preinstall.ts","../src/tools/score.ts","../src/tools/upgrade.ts","../src/tools/vulns.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err: unknown) => {\n console.error(\"Fatal error:\", err);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerPrompts } from \"./prompts/index.js\";\nimport { register as registerAdvisories } from \"./tools/advisories.js\";\nimport { register as registerInspect } from \"./tools/inspect.js\";\nimport { register as registerPopular } from \"./tools/popular.js\";\nimport { register as registerTree } from \"./tools/tree.js\";\nimport { register as registerTyposquat } from \"./tools/typosquat.js\";\nimport { register as registerAudit } from \"./tools/audit.js\";\nimport { register as registerCompare } from \"./tools/compare.js\";\nimport { register as registerLicenseCheck } from \"./tools/license-check.js\";\nimport { register as registerPreinstall } from \"./tools/preinstall.js\";\nimport { register as registerScore } from \"./tools/score.js\";\nimport { register as registerUpgrade } from \"./tools/upgrade.js\";\nimport { register as registerVulns } from \"./tools/vulns.js\";\n\nconst SERVER_NAME = \"hound-mcp\";\nconst SERVER_VERSION = \"0.2.0\";\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: SERVER_NAME,\n version: SERVER_VERSION,\n });\n\n registerVulns(server);\n registerInspect(server);\n registerTree(server);\n registerTyposquat(server);\n registerAdvisories(server);\n registerPopular(server);\n registerAudit(server);\n registerCompare(server);\n registerLicenseCheck(server);\n registerPreinstall(server);\n registerScore(server);\n registerUpgrade(server);\n registerPrompts(server);\n\n return server;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function packageEvaluationRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"package_evaluation\",\n {\n description:\n \"Evaluate a package before adding it as a dependency. Returns a go/no-go recommendation with security, license, and health analysis.\",\n argsSchema: {\n package: z.string().describe(\"Package name to evaluate (e.g. express, requests, serde)\"),\n version: z\n .string()\n .optional()\n .describe(\"Specific version to evaluate. Uses latest stable if omitted.\"),\n ecosystem: z.string().optional().describe(\"Package ecosystem. Defaults to npm if omitted.\"),\n },\n },\n ({ package: pkg, version, ecosystem }) => {\n const eco = ecosystem ?? \"npm\";\n const versionNote = version ? `version ${version} of ` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `I'm considering adding ${versionNote}\\`${pkg}\\` (${eco}) as a dependency. Please evaluate it thoroughly.\n\nSteps:\n1. Use \\`hound_inspect\\` on \\`${pkg}\\`${version ? `@${version}` : \"\"} (ecosystem: ${eco}) to get the full health profile — licenses, vulnerabilities, OpenSSF Scorecard, GitHub stats.\n2. Use \\`hound_vulns\\` to get the full vulnerability list with fix versions.\n3. Use \\`hound_typosquat\\` to confirm this is the legitimate package and not a typosquat.\n4. Use \\`hound_tree\\` to check the transitive dependency count — packages with hundreds of transitive deps carry more supply chain risk.\n5. If any advisories are listed, use \\`hound_advisories\\` to get the details.\n\nGive me a clear **GO / NO-GO / CONDITIONAL** recommendation with reasoning. If conditional, state exactly what version or conditions would make it acceptable.`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function preReleaseCheckRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"pre_release_check\",\n {\n description:\n \"Run a pre-release dependency scan before shipping. Checks for vulnerabilities and license issues that could block a release.\",\n argsSchema: {\n version: z.string().optional().describe(\"The version you are about to release, e.g. 1.2.0\"),\n },\n },\n ({ version }) => {\n const versionNote = version ? ` (version ${version})` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `I'm about to release this project${versionNote}. Run a pre-release dependency check.\n\nSteps:\n1. Use \\`hound_popular\\` to scan all key packages in this project's ecosystem for known vulnerabilities.\n2. For any packages identified as critical to this project, use \\`hound_vulns\\` to check for vulnerabilities.\n3. Use \\`hound_inspect\\` on the top 5 dependencies by importance to verify licenses are compatible and no advisories are outstanding.\n4. Flag any HIGH or CRITICAL severity vulnerabilities as **release blockers**.\n5. Flag any copyleft licenses (GPL, AGPL, LGPL) that may conflict with the project's MIT license as **license blockers**.\n\nOutput a release checklist:\n- ✅ or ❌ Vulnerabilities (CRITICAL/HIGH)\n- ✅ or ❌ License compatibility\n- ✅ or ❌ No abandoned dependencies (last published >2 years ago)\n\nEnd with a clear **SAFE TO RELEASE** or **BLOCKED — fix these issues first** verdict.`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function securityAuditRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"security_audit\",\n {\n description:\n \"Run a full security audit on the current project's dependencies. Scans for vulnerabilities, license issues, and typosquat risks across your entire dependency tree.\",\n argsSchema: {\n ecosystem: z\n .string()\n .optional()\n .describe(\"Package ecosystem (npm, pypi, cargo, etc). Auto-detected if omitted.\"),\n },\n },\n ({ ecosystem }) => {\n const ecoNote = ecosystem ? ` The project uses ${ecosystem}.` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Please run a comprehensive security audit on this project's dependencies.${ecoNote}\n\nFollow these steps:\n1. Use \\`hound_popular\\` to check the most commonly used packages in this ecosystem for known vulnerabilities — this gives a quick baseline.\n2. For any specific packages you can identify in the project, use \\`hound_vulns\\` to check each one for CVEs and advisories.\n3. Use \\`hound_inspect\\` on the 3-5 most critical dependencies to check their licenses, OpenSSF Scorecard, and GitHub health.\n4. For any package names that look unusual or unfamiliar, use \\`hound_typosquat\\` to check for potential typosquatting.\n5. If any vulnerabilities are found, use \\`hound_advisories\\` to get full details and fix guidance.\n\nSummarize findings as:\n- **Critical / High** vulnerabilities that need immediate attention\n- **License risks** (copyleft licenses, unknown licenses)\n- **Health concerns** (abandoned packages, low Scorecard scores)\n- **Recommended actions** with specific version upgrades where available`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { packageEvaluationRegisterPrompt } from \"./package_evaluation.js\";\nimport { preReleaseCheckRegisterPrompt } from \"./pre_release_check.js\";\nimport { securityAuditRegisterPrompt } from \"./security_audit.js\";\n\nexport function registerPrompts(server: McpServer): void {\n securityAuditRegisterPrompt(server);\n packageEvaluationRegisterPrompt(server);\n preReleaseCheckRegisterPrompt(server);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getAdvisory } from \"../api/depsdev.js\";\nimport { getVuln } from \"../api/osv.js\";\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_advisories\",\n {\n description:\n \"Get full details for a security advisory by ID (GHSA, CVE, or OSV ID). Returns title, severity, affected versions, fix versions, and references.\",\n inputSchema: {\n id: z\n .string()\n .describe(\"Advisory ID — e.g. GHSA-rv95-896h-c2vc, CVE-2024-29041, or any OSV ID\"),\n },\n },\n async ({ id }) => {\n // Try OSV first (richer data), fall back to deps.dev advisory endpoint\n const [osvResult, depsdevResult] = await Promise.allSettled([getVuln(id), getAdvisory(id)]);\n\n const lines: string[] = [];\n\n if (osvResult.status === \"fulfilled\") {\n const vuln = osvResult.value;\n\n lines.push(`🔔 Advisory: ${vuln.id}`);\n lines.push(\"═\".repeat(50));\n lines.push(\"\");\n lines.push(`📋 Summary: ${vuln.summary}`);\n lines.push(`📅 Published: ${vuln.published.slice(0, 10)}`);\n lines.push(`🔄 Last modified: ${vuln.modified.slice(0, 10)}`);\n\n if (vuln.aliases && vuln.aliases.length > 0) {\n lines.push(`🔗 Also known as: ${vuln.aliases.join(\", \")}`);\n }\n\n const dbSeverity = vuln.database_specific?.severity;\n if (dbSeverity) {\n lines.push(`⚠️ Severity: ${dbSeverity}`);\n }\n\n if (vuln.database_specific?.cwe_ids && vuln.database_specific.cwe_ids.length > 0) {\n lines.push(`🏷️ CWE: ${vuln.database_specific.cwe_ids.join(\", \")}`);\n }\n\n if (vuln.affected.length > 0) {\n lines.push(\"\");\n lines.push(\"📦 Affected packages\");\n lines.push(\"─\".repeat(30));\n\n for (const affected of vuln.affected) {\n lines.push(` ${affected.package.ecosystem}: ${affected.package.name}`);\n\n for (const range of affected.ranges) {\n if (range.type === \"SEMVER\") {\n const introduced = range.events.find((e) => \"introduced\" in e);\n const fixed = range.events.find((e) => \"fixed\" in e);\n const introStr =\n introduced && \"introduced\" in introduced ? introduced.introduced : \"0\";\n if (fixed && \"fixed\" in fixed) {\n lines.push(` Affected: >= ${introStr}, fixed in ${fixed.fixed}`);\n } else {\n lines.push(` Affected: >= ${introStr} (no fix available)`);\n }\n }\n }\n }\n }\n\n if (vuln.details) {\n lines.push(\"\");\n lines.push(\"📝 Details\");\n lines.push(\"─\".repeat(30));\n // Trim details to a reasonable length\n const details =\n vuln.details.length > 500 ? `${vuln.details.slice(0, 500)}...` : vuln.details;\n lines.push(details);\n }\n\n if (vuln.references && vuln.references.length > 0) {\n lines.push(\"\");\n lines.push(\"🔗 References\");\n lines.push(\"─\".repeat(30));\n for (const ref of vuln.references.slice(0, 5)) {\n lines.push(` ${ref.url}`);\n }\n if (vuln.references.length > 5) {\n lines.push(` ... and ${vuln.references.length - 5} more`);\n }\n }\n\n lines.push(\"\");\n lines.push(`Source: https://osv.dev/vulnerability/${id}`);\n } else if (depsdevResult.status === \"fulfilled\") {\n // Fallback to deps.dev advisory data\n const advisory = depsdevResult.value;\n\n lines.push(`🔔 Advisory: ${advisory.advisoryKey.id}`);\n lines.push(\"═\".repeat(50));\n lines.push(\"\");\n lines.push(`📋 Title: ${advisory.title}`);\n\n if (advisory.aliases.length > 0) {\n lines.push(`🔗 Also known as: ${advisory.aliases.join(\", \")}`);\n }\n\n lines.push(`⚠️ CVSS v3 Score: ${advisory.cvss3Score}`);\n lines.push(`📐 CVSS Vector: ${advisory.cvss3Vector}`);\n lines.push(\"\");\n lines.push(`Source: ${advisory.url}`);\n } else {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find advisory \"${id}\". Check the ID format (e.g. GHSA-xxxx-xxxx-xxxx or CVE-YYYY-NNNNN).`,\n },\n ],\n };\n }\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","/**\n * Client for the deps.dev API (Google Open Source Insights).\n *\n * Base URL: https://api.deps.dev/v3/\n * Auth: none\n * Docs: https://deps.dev/about\n *\n * Ecosystem names in URLs must be uppercase (NPM, PYPI, GO, MAVEN, CARGO, NUGET, RUBYGEMS).\n * Project keys use %2F encoding for slashes (github.com%2Fowner%2Frepo).\n */\n\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst BASE_URL = \"https://api.deps.dev/v3\";\n\nconst ECOSYSTEM_MAP: Record<Ecosystem, string> = {\n npm: \"npm\",\n pypi: \"pypi\",\n go: \"go\",\n maven: \"maven\",\n cargo: \"cargo\",\n nuget: \"nuget\",\n rubygems: \"rubygems\",\n};\n\nexport interface DepsDevVersionKey {\n system: string;\n name: string;\n version: string;\n}\n\nexport interface DepsDevAdvisoryKey {\n id: string;\n}\n\nexport interface DepsDevLink {\n label: string;\n url: string;\n}\n\nexport interface DepsDevRelatedProject {\n projectKey: { id: string };\n relationProvenance: string;\n relationType: string;\n}\n\nexport interface DepsDevVersion {\n versionKey: DepsDevVersionKey;\n publishedAt: string;\n isDefault: boolean;\n licenses?: string[];\n advisoryKeys?: DepsDevAdvisoryKey[];\n links?: DepsDevLink[];\n relatedProjects?: DepsDevRelatedProject[];\n}\n\nexport interface DepsDevPackage {\n packageKey: { system: string; name: string };\n versions: {\n versionKey: DepsDevVersionKey;\n publishedAt: string;\n isDefault: boolean;\n }[];\n}\n\nexport interface DepsDevDepNode {\n versionKey: DepsDevVersionKey;\n bundled: boolean;\n relation: \"SELF\" | \"DIRECT\" | \"INDIRECT\";\n errors: string[];\n}\n\nexport interface DepsDevDepEdge {\n fromNode: number;\n toNode: number;\n requirement: string;\n}\n\nexport interface DepsDevDependencies {\n nodes: DepsDevDepNode[];\n edges: DepsDevDepEdge[];\n}\n\nexport interface DepsDevScorecardCheck {\n name: string;\n score: number;\n reason: string;\n details: string[];\n}\n\nexport interface DepsDevScorecard {\n date: string;\n repository: { name: string; commit: string };\n overallScore: number;\n checks: DepsDevScorecardCheck[];\n}\n\nexport interface DepsDevProject {\n projectKey: { id: string };\n openIssuesCount: number;\n starsCount: number;\n forksCount: number;\n license: string;\n description: string;\n homepage: string;\n scorecard: DepsDevScorecard | null;\n}\n\nexport interface DepsDevAdvisory {\n advisoryKey: { id: string };\n url: string;\n title: string;\n aliases: string[];\n cvss3Score: number;\n cvss3Vector: string;\n}\n\nasync function get<T>(path: string): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const res = await fetch(url, {\n headers: { \"User-Agent\": \"hound-mcp/0.1.0\" },\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new DepsDevError(res.status, url, body);\n }\n\n return res.json() as Promise<T>;\n}\n\nexport class DepsDevError extends Error {\n constructor(\n public readonly status: number,\n public readonly url: string,\n public readonly body: string,\n ) {\n super(`deps.dev API error ${status} for ${url}`);\n this.name = \"DepsDevError\";\n }\n}\n\n/**\n * Get metadata for a specific package version.\n * Includes licenses, advisory keys, and related project links.\n */\nexport async function getVersion(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<DepsDevVersion> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevVersion>(\n `/systems/${sys}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}`,\n );\n}\n\n/**\n * Get all versions of a package.\n * Useful for finding available upgrade targets.\n */\nexport async function getPackage(ecosystem: Ecosystem, name: string): Promise<DepsDevPackage> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevPackage>(`/systems/${sys}/packages/${encodeURIComponent(name)}`);\n}\n\n/**\n * Get the full resolved dependency graph for a package version.\n * Returns nodes (packages) and edges (dependency relationships).\n * relationType: SELF = the package itself, DIRECT = direct deps, INDIRECT = transitive deps.\n */\nexport async function getDependencies(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<DepsDevDependencies> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevDependencies>(\n `/systems/${sys}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}:dependencies`,\n );\n}\n\n/**\n * Get project metadata and OpenSSF Scorecard for a GitHub/GitLab project.\n * projectId format: \"github.com/owner/repo\"\n */\nexport async function getProject(projectId: string): Promise<DepsDevProject> {\n const encoded = projectId.replaceAll(\"/\", \"%2F\");\n return get<DepsDevProject>(`/projects/${encoded}`);\n}\n\n/**\n * Get full advisory details by advisory ID (e.g. \"GHSA-rv95-896h-c2vc\").\n */\nexport async function getAdvisory(advisoryId: string): Promise<DepsDevAdvisory> {\n return get<DepsDevAdvisory>(`/advisories/${encodeURIComponent(advisoryId)}`);\n}\n\n/**\n * Extract the GitHub/GitLab project ID from a version's relatedProjects list.\n * Returns the first SOURCE_REPO or ISSUE_TRACKER project ID found, or null.\n */\nexport function extractProjectId(version: DepsDevVersion): string | null {\n const related = version.relatedProjects ?? [];\n const sourceRepo = related.find(\n (r) => r.relationType === \"SOURCE_REPO\" || r.relationType === \"ISSUE_TRACKER\",\n );\n return sourceRepo?.projectKey.id ?? null;\n}\n","/**\n * Client for the OSV API (Google Open Source Vulnerabilities).\n *\n * Base URL: https://api.osv.dev/v1/\n * Auth: none\n * Docs: https://google.github.io/osv.dev/api/\n *\n * Ecosystem names use OSV convention (npm, PyPI, Go, Maven, crates.io, NuGet, RubyGems).\n */\n\nimport type { Ecosystem, Severity } from \"../types/index.js\";\n\nconst BASE_URL = \"https://api.osv.dev/v1\";\n\nconst ECOSYSTEM_MAP: Record<Ecosystem, string> = {\n npm: \"npm\",\n pypi: \"PyPI\",\n go: \"Go\",\n maven: \"Maven\",\n cargo: \"crates.io\",\n nuget: \"NuGet\",\n rubygems: \"RubyGems\",\n};\n\nexport interface OsvSeverityEntry {\n type: \"CVSS_V2\" | \"CVSS_V3\" | \"CVSS_V4\";\n score: string; // CVSS vector string e.g. \"CVSS:3.1/AV:N/...\"\n}\n\nexport interface OsvRange {\n type: \"SEMVER\" | \"ECOSYSTEM\" | \"GIT\";\n events: (\n | { introduced: string; fixed?: undefined; last_affected?: undefined }\n | { fixed: string; introduced?: undefined; last_affected?: undefined }\n | { last_affected: string; introduced?: undefined; fixed?: undefined }\n )[];\n}\n\nexport interface OsvAffected {\n package: {\n name: string;\n ecosystem: string;\n purl?: string;\n };\n ranges: OsvRange[];\n versions?: string[];\n database_specific?: Record<string, unknown>;\n}\n\nexport interface OsvDatabaseSpecific {\n severity?: string; // \"LOW\" | \"MODERATE\" | \"HIGH\" | \"CRITICAL\"\n nvd_published_at?: string;\n github_reviewed?: boolean;\n github_reviewed_at?: string;\n cwe_ids?: string[];\n}\n\nexport interface OsvVuln {\n id: string;\n summary: string;\n details?: string;\n aliases?: string[];\n modified: string;\n published: string;\n references?: { type: string; url: string }[];\n affected: OsvAffected[];\n severity?: OsvSeverityEntry[];\n database_specific?: OsvDatabaseSpecific;\n schema_version?: string;\n}\n\nexport interface OsvQueryResponse {\n vulns?: OsvVuln[];\n}\n\nexport interface OsvBatchResponse {\n results: OsvQueryResponse[];\n}\n\nasync function post<TResponse>(path: string, body: unknown): Promise<TResponse> {\n const url = `${BASE_URL}${path}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"hound-mcp/0.1.0\",\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new OsvError(res.status, url, text);\n }\n\n return res.json() as Promise<TResponse>;\n}\n\nexport class OsvError extends Error {\n constructor(\n public readonly status: number,\n public readonly url: string,\n public readonly body: string,\n ) {\n super(`OSV API error ${status} for ${url}`);\n this.name = \"OsvError\";\n }\n}\n\n/**\n * Query vulnerabilities for a single package@version.\n * Returns an empty array if no vulnerabilities are found.\n */\nexport async function queryVulns(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<OsvVuln[]> {\n const response = await post<OsvQueryResponse>(\"/query\", {\n version,\n package: {\n name,\n ecosystem: ECOSYSTEM_MAP[ecosystem],\n },\n });\n return response.vulns ?? [];\n}\n\n/**\n * Query vulnerabilities for multiple packages in a single API call.\n * Returns results in the same order as the input packages array.\n * Packages with no vulnerabilities return an empty array.\n */\nexport async function queryVulnsBatch(\n packages: { ecosystem: Ecosystem; name: string; version: string }[],\n): Promise<OsvVuln[][]> {\n if (packages.length === 0) return [];\n\n const response = await post<OsvBatchResponse>(\"/querybatch\", {\n queries: packages.map((pkg) => ({\n version: pkg.version,\n package: {\n name: pkg.name,\n ecosystem: ECOSYSTEM_MAP[pkg.ecosystem],\n },\n })),\n });\n\n return response.results.map((result) => result.vulns ?? []);\n}\n\n/**\n * Fetch full vulnerability details by OSV/GHSA ID.\n */\nexport async function getVuln(vulnId: string): Promise<OsvVuln> {\n const url = `${BASE_URL}/vulns/${encodeURIComponent(vulnId)}`;\n const res = await fetch(url, {\n headers: { \"User-Agent\": \"hound-mcp/0.1.0\" },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new OsvError(res.status, url, text);\n }\n\n return res.json() as Promise<OsvVuln>;\n}\n\n/**\n * Extract a human-readable severity level from an OSV vulnerability.\n * Prefers database_specific.severity, falls back to parsing CVSS score.\n */\nexport function extractSeverity(vuln: OsvVuln): Severity {\n // Prefer the GitHub advisory database severity label\n const dbSeverity = vuln.database_specific?.severity?.toUpperCase();\n if (dbSeverity === \"CRITICAL\") return \"CRITICAL\";\n if (dbSeverity === \"HIGH\") return \"HIGH\";\n if (dbSeverity === \"MODERATE\") return \"MODERATE\";\n if (dbSeverity === \"LOW\") return \"LOW\";\n\n // Fall back to CVSS score\n const cvssScore = extractCvssScore(vuln);\n if (cvssScore === null) return \"UNKNOWN\";\n if (cvssScore >= 9.0) return \"CRITICAL\";\n if (cvssScore >= 7.0) return \"HIGH\";\n if (cvssScore >= 4.0) return \"MODERATE\";\n return \"LOW\";\n}\n\n/**\n * Extract a numeric CVSS score from an OSV vulnerability.\n * Prefers CVSS_V3, falls back to V4, then V2.\n * Returns null if no CVSS score is available.\n */\nexport function extractCvssScore(vuln: OsvVuln): number | null {\n const entries = vuln.severity ?? [];\n const preferred = [\"CVSS_V3\", \"CVSS_V4\", \"CVSS_V2\"] as const;\n\n for (const type of preferred) {\n const entry = entries.find((e) => e.type === type);\n if (entry) {\n return parseCvssScore(entry.score);\n }\n }\n return null;\n}\n\n/**\n * Extract fix versions from an OSV affected range.\n * Returns a deduplicated list of versions that fix the vulnerability.\n */\nexport function extractFixVersions(vuln: OsvVuln, ecosystem: Ecosystem): string[] {\n const osvEcosystem = ECOSYSTEM_MAP[ecosystem];\n const fixed = new Set<string>();\n\n for (const affected of vuln.affected) {\n if (affected.package.ecosystem.toLowerCase() !== osvEcosystem.toLowerCase()) {\n continue;\n }\n for (const range of affected.ranges) {\n for (const event of range.events) {\n if (\"fixed\" in event && event.fixed) {\n fixed.add(event.fixed);\n }\n }\n }\n }\n\n return [...fixed];\n}\n\nfunction parseCvssScore(vector: string): number | null {\n // CVSS vectors look like \"CVSS:3.1/AV:N/AC:L/...\" — the base score is not\n // in the vector string itself. We can only get it if the API includes it\n // directly, which OSV doesn't. Return null and let callers use severity label.\n // This function is kept as a hook for future enrichment.\n void vector;\n return null;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_inspect\",\n {\n description:\n \"Get a comprehensive profile of a package version: licenses, vulnerabilities, OpenSSF scorecard, GitHub stats, and dependency count — all in one call.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [versionData, vulns] = await Promise.allSettled([\n getVersion(eco, name, version),\n queryVulns(eco, name, version),\n ]);\n\n if (versionData.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find ${name}@${version} in ${ecosystem}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const pkg = versionData.value;\n const vulnList = vulns.status === \"fulfilled\" ? vulns.value : [];\n\n // Try to fetch project info (scorecard, stars) — non-fatal if missing\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n const lines: string[] = [`📦 ${name}@${version} (${ecosystem})`, \"═\".repeat(50), \"\"];\n\n // Published date\n const published = pkg.publishedAt.slice(0, 10);\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n lines.push(`📅 Published: ${published} (${daysSince} days ago)`);\n\n // License\n const licenses =\n pkg.licenses && pkg.licenses.length > 0 ? pkg.licenses.join(\", \") : \"Unknown\";\n lines.push(`📄 License: ${licenses}`);\n\n // Vulnerabilities\n if (vulnList.length === 0) {\n lines.push(`🛡️ Vulnerabilities: None known`);\n } else {\n const counts: Record<string, number> = {};\n for (const v of vulnList) {\n const sev = extractSeverity(v);\n counts[sev] = (counts[sev] ?? 0) + 1;\n }\n const summary = Object.entries(counts)\n .map(([s, n]) => `${n} ${s.toLowerCase()}`)\n .join(\", \");\n lines.push(`⚠️ Vulnerabilities: ${vulnList.length} (${summary})`);\n }\n\n // Known advisories from deps.dev\n const advisoryCount = pkg.advisoryKeys?.length ?? 0;\n if (advisoryCount > 0) {\n const ids = pkg.advisoryKeys?.map((a) => a.id).join(\", \");\n lines.push(`🔔 Advisories: ${ids}`);\n }\n\n // GitHub / project info\n if (projectData !== null) {\n lines.push(\"\");\n lines.push(\"📊 Project Health\");\n lines.push(\"─\".repeat(30));\n lines.push(`⭐ Stars: ${projectData.starsCount.toLocaleString()}`);\n lines.push(`🍴 Forks: ${projectData.forksCount.toLocaleString()}`);\n lines.push(`🐛 Open issues: ${projectData.openIssuesCount.toLocaleString()}`);\n\n if (projectData.scorecard !== null) {\n const score = projectData.scorecard.overallScore.toFixed(1);\n const grade = scorecardGrade(projectData.scorecard.overallScore);\n lines.push(`🏆 OpenSSF Scorecard: ${score}/10 (${grade})`);\n\n const weak = [...projectData.scorecard.checks]\n .sort((a, b) => a.score - b.score)\n .slice(0, 3);\n if (weak.length > 0) {\n lines.push(\n ` Lowest checks: ${weak.map((c) => `${c.name} (${c.score}/10)`).join(\", \")}`,\n );\n }\n }\n }\n\n // Links\n const homepage = pkg.links?.find((l) => l.label === \"HOMEPAGE\");\n const sourceRepo = pkg.links?.find((l) => l.label === \"SOURCE_REPO\");\n if (homepage ?? sourceRepo) {\n lines.push(\"\");\n if (homepage) lines.push(`🌐 Homepage: ${homepage.url}`);\n if (sourceRepo) lines.push(`💻 Source: ${sourceRepo.url}`);\n }\n\n lines.push(\"\");\n lines.push(\n `🔗 deps.dev: https://deps.dev/${ecosystem}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}`,\n );\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n\nfunction scorecardGrade(score: number): string {\n if (score >= 9) return \"A\";\n if (score >= 7) return \"B\";\n if (score >= 5) return \"C\";\n if (score >= 3) return \"D\";\n return \"F\";\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport { queryVulnsBatch } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\n/**\n * Curated list of widely-used packages per ecosystem.\n * Used as defaults when the user doesn't specify a list.\n */\nconst POPULAR_DEFAULTS: Record<string, string[]> = {\n npm: [\n \"express\",\n \"lodash\",\n \"axios\",\n \"react\",\n \"typescript\",\n \"webpack\",\n \"eslint\",\n \"jest\",\n \"next\",\n \"vue\",\n ],\n pypi: [\n \"requests\",\n \"numpy\",\n \"pandas\",\n \"flask\",\n \"django\",\n \"fastapi\",\n \"sqlalchemy\",\n \"pytest\",\n \"boto3\",\n \"pydantic\",\n ],\n go: [\n \"github.com/gin-gonic/gin\",\n \"github.com/gorilla/mux\",\n \"github.com/stretchr/testify\",\n \"github.com/spf13/cobra\",\n \"go.uber.org/zap\",\n ],\n maven: [\n \"com.google.guava:guava\",\n \"org.springframework:spring-core\",\n \"org.apache.commons:commons-lang3\",\n \"com.fasterxml.jackson.core:jackson-databind\",\n \"org.slf4j:slf4j-api\",\n ],\n cargo: [\"serde\", \"tokio\", \"reqwest\", \"clap\", \"anyhow\", \"log\", \"rand\", \"regex\"],\n nuget: [\n \"Newtonsoft.Json\",\n \"Microsoft.Extensions.Logging\",\n \"Serilog\",\n \"AutoMapper\",\n \"FluentValidation\",\n ],\n rubygems: [\"rails\", \"devise\", \"rspec-core\", \"activerecord\", \"sidekiq\"],\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_popular\",\n {\n description:\n \"Scan a list of popular (or user-specified) packages for known vulnerabilities. Quickly surface which widely-used packages in an ecosystem have open security issues.\",\n inputSchema: {\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n packages: z\n .array(z.string())\n .optional()\n .describe(\n \"Specific package names to check. If omitted, uses a curated list of popular packages for the ecosystem.\",\n ),\n },\n },\n async ({ ecosystem, packages }) => {\n const eco = ecosystem as Ecosystem;\n const names = packages ?? POPULAR_DEFAULTS[ecosystem] ?? [];\n\n if (names.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No packages specified and no defaults available for ${ecosystem}.`,\n },\n ],\n };\n }\n\n const packageResults = await Promise.allSettled(\n names.map(async (name) => {\n const pkg = await getPackage(eco, name);\n const defaultVersion = pkg.versions.find((v) => v.isDefault) ?? pkg.versions[0];\n return {\n name,\n version: defaultVersion?.versionKey.version ?? \"unknown\",\n };\n }),\n );\n\n const resolved = packageResults\n .map((r, i) => ({\n name: names[i] ?? \"\",\n version: r.status === \"fulfilled\" ? r.value.version : null,\n }))\n .filter((p): p is { name: string; version: string } => p.version !== null);\n\n const failed = packageResults.filter((r) => r.status === \"rejected\").length;\n\n const vulnResults = await queryVulnsBatch(\n resolved.map((p) => ({ ecosystem: eco, name: p.name, version: p.version })),\n );\n\n const lines: string[] = [\n `🔍 Vulnerability scan: ${ecosystem} popular packages`,\n \"═\".repeat(50),\n `Checked ${resolved.length} packages`,\n \"\",\n ];\n\n // Sort: vulnerable first, then clean\n const withVulns = resolved\n .map((pkg, i) => ({ ...pkg, vulns: vulnResults[i] ?? [] }))\n .sort((a, b) => b.vulns.length - a.vulns.length);\n\n const vulnerableCount = withVulns.filter((p) => p.vulns.length > 0).length;\n\n if (vulnerableCount === 0) {\n lines.push(`✅ All ${resolved.length} packages are clean — no known vulnerabilities.`);\n lines.push(\"\");\n } else {\n lines.push(`⚠️ ${vulnerableCount} of ${resolved.length} packages have vulnerabilities:`);\n lines.push(\"\");\n }\n\n for (const pkg of withVulns) {\n if (pkg.vulns.length === 0) {\n lines.push(` ✅ ${pkg.name}@${pkg.version}`);\n } else {\n lines.push(` ⚠️ ${pkg.name}@${pkg.version} — ${pkg.vulns.length} vuln(s)`);\n // Show vuln IDs (up to 3)\n for (const v of pkg.vulns.slice(0, 3)) {\n lines.push(` ${v.id}: ${v.summary}`);\n }\n if (pkg.vulns.length > 3) {\n lines.push(` ... and ${pkg.vulns.length - 3} more`);\n }\n }\n }\n\n if (failed > 0) {\n lines.push(\"\");\n lines.push(`ℹ️ ${failed} package(s) could not be resolved in ${ecosystem}.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getDependencies } from \"../api/depsdev.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_tree\",\n {\n description:\n \"Show the full resolved dependency tree for a package version, including all transitive dependencies with their depth and relation type.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n maxDepth: z\n .number()\n .int()\n .min(1)\n .max(10)\n .default(3)\n .describe(\"Maximum depth to display (default: 3, max: 10)\"),\n },\n },\n async ({ name, version, ecosystem, maxDepth }) => {\n let deps: Awaited<ReturnType<typeof getDependencies>>;\n try {\n deps = await getDependencies(ecosystem as Ecosystem, name, version);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not fetch dependency tree for ${name}@${version}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const nodes = deps.nodes;\n const edges = deps.edges;\n\n const directCount = nodes.filter((n) => n.relation === \"DIRECT\").length;\n const indirectCount = nodes.filter((n) => n.relation === \"INDIRECT\").length;\n const totalCount = directCount + indirectCount;\n\n // Build adjacency: nodeIndex → children nodeIndexes\n const children = new Map<number, number[]>();\n for (const edge of edges) {\n if (!children.has(edge.fromNode)) children.set(edge.fromNode, []);\n children.get(edge.fromNode)?.push(edge.toNode);\n }\n\n const lines: string[] = [\n `🌳 Dependency tree for ${name}@${version} (${ecosystem})`,\n \"═\".repeat(50),\n `${totalCount} total dependencies (${directCount} direct, ${indirectCount} transitive)`,\n \"\",\n ];\n\n // Render tree recursively from node 0 (SELF)\n const rootNode = nodes[0];\n if (rootNode) {\n renderNode(lines, nodes, children, 0, 0, maxDepth, new Set());\n }\n\n if (maxDepth < 10 && indirectCount > 0) {\n lines.push(\"\");\n lines.push(`ℹ️ Showing up to depth ${maxDepth}. Use maxDepth to see deeper.`);\n }\n\n lines.push(\"\");\n lines.push(`Source: deps.dev`);\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n\nfunction renderNode(\n lines: string[],\n nodes: { versionKey: { name: string; version: string }; relation: string; errors: string[] }[],\n children: Map<number, number[]>,\n nodeIndex: number,\n depth: number,\n maxDepth: number,\n visited: Set<number>,\n): void {\n if (visited.has(nodeIndex)) return;\n visited.add(nodeIndex);\n\n const node = nodes[nodeIndex];\n if (!node) return;\n\n const indent = \" \".repeat(depth);\n const isRoot = depth === 0;\n const prefix = isRoot ? \"\" : \"├── \";\n const errorSuffix = node.errors.length > 0 ? \" ⚠️\" : \"\";\n lines.push(`${indent}${prefix}${node.versionKey.name}@${node.versionKey.version}${errorSuffix}`);\n\n if (depth >= maxDepth) {\n const childCount = children.get(nodeIndex)?.length ?? 0;\n if (childCount > 0) {\n lines.push(`${indent} └── ... (${childCount} more)`);\n }\n return;\n }\n\n for (const childIdx of children.get(nodeIndex) ?? []) {\n renderNode(lines, nodes, children, childIdx, depth + 1, maxDepth, visited);\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\n/**\n * Generate likely typosquatting variants of a package name.\n * Covers the most common attack patterns:\n * - character omission (lodsh)\n * - character transposition (lodasg)\n * - character substitution (1odash, l0dash)\n * - hyphen/underscore confusion (lo_dash, lo-dash)\n * - common prefix/suffix additions (node-lodash, lodash-js)\n */\nfunction generateTypos(name: string): string[] {\n const variants = new Set<string>();\n\n // Omit each character\n for (let i = 0; i < name.length; i++) {\n variants.add(name.slice(0, i) + name.slice(i + 1));\n }\n\n // Transpose adjacent characters\n for (let i = 0; i < name.length - 1; i++) {\n const a = name.charAt(i);\n const b = name.charAt(i + 1);\n variants.add(name.slice(0, i) + b + a + name.slice(i + 2));\n }\n\n // Hyphen/underscore confusion\n if (name.includes(\"-\")) {\n variants.add(name.replaceAll(\"-\", \"_\"));\n variants.add(name.replaceAll(\"-\", \"\"));\n }\n if (name.includes(\"_\")) {\n variants.add(name.replaceAll(\"_\", \"-\"));\n variants.add(name.replaceAll(\"_\", \"\"));\n }\n\n // Common prefix/suffix additions\n variants.add(`node-${name}`);\n variants.add(`${name}-js`);\n variants.add(`${name}js`);\n variants.add(`${name}-node`);\n\n // Remove the original name\n variants.delete(name);\n\n return [...variants];\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_typosquat\",\n {\n description:\n \"Check if a package name looks like a typosquat of a popular package. Generates likely typo variants and checks which ones exist in the registry.\",\n inputSchema: {\n name: z.string().describe(\"Package name to check\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n const variants = generateTypos(name);\n\n // Check which variants actually exist in the registry (in parallel, ignore errors)\n const results = await Promise.allSettled(\n variants.map(async (variant) => {\n const pkg = await getPackage(eco, variant);\n return { name: variant, versionCount: pkg.versions.length };\n }),\n );\n\n const existing = results\n .filter((r) => r.status === \"fulfilled\")\n .map((r) => (r as PromiseFulfilledResult<{ name: string; versionCount: number }>).value)\n .sort((a, b) => b.versionCount - a.versionCount);\n\n // Also fetch the target package itself to confirm it exists\n const targetExists = await getPackage(eco, name)\n .then((p) => p.versions.length)\n .catch(() => null);\n\n const lines: string[] = [`🔍 Typosquat check: ${name} (${ecosystem})`, \"═\".repeat(50), \"\"];\n\n if (targetExists === null) {\n lines.push(`⚠️ \"${name}\" does not exist in ${ecosystem}.`);\n lines.push(`This package name itself may be available — or it could be a typo.`);\n } else {\n lines.push(`✅ \"${name}\" exists (${targetExists} published versions)`);\n }\n\n lines.push(\"\");\n\n if (existing.length === 0) {\n lines.push(`✅ No typosquat variants found in ${ecosystem}.`);\n lines.push(`None of the ${variants.length} generated variants exist.`);\n } else {\n lines.push(`⚠️ Found ${existing.length} similar package(s) that exist in ${ecosystem}:`);\n lines.push(\"\");\n for (const pkg of existing) {\n lines.push(` 📦 ${pkg.name} (${pkg.versionCount} versions)`);\n }\n lines.push(\"\");\n lines.push(`If you meant to install \"${name}\", double-check you typed it correctly.`);\n lines.push(`If you are the author of \"${name}\", consider reserving these names.`);\n }\n\n lines.push(\"\");\n lines.push(\n `ℹ️ Checked ${variants.length} typo variants (omission, transposition, hyphen, affixes)`,\n );\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { parseLockfile } from \"../parsers/index.js\";\nimport { extractSeverity, queryVulnsBatch } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst MAX_BATCH = 100; // cap to avoid huge requests\n\nconst SEVERITY_ORDER = [\"CRITICAL\", \"HIGH\", \"MODERATE\", \"LOW\", \"UNKNOWN\"] as const;\n\nconst SEVERITY_ICON: Record<string, string> = {\n CRITICAL: \"🔴\",\n HIGH: \"🟠\",\n MODERATE: \"🟡\",\n LOW: \"🔵\",\n UNKNOWN: \"⚪\",\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_audit\",\n {\n description:\n \"Scan a project's lockfile for dependency risks. Parses package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, or go.sum and batch-queries OSV for vulnerabilities across all dependencies.\",\n inputSchema: {\n lockfile_content: z.string().describe(\"Full text content of the lockfile\"),\n lockfile_name: z\n .string()\n .describe(\n \"Filename to determine format: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum\",\n ),\n },\n },\n async ({ lockfile_content, lockfile_name }) => {\n const deps = parseLockfile(lockfile_name, lockfile_content);\n\n if (deps === null) {\n return {\n content: [\n {\n type: \"text\",\n text: `Unsupported lockfile format: ${lockfile_name}\\n\\nSupported formats: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum`,\n },\n ],\n };\n }\n\n if (deps.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No dependencies found in ${lockfile_name}. The file may be empty or malformed.`,\n },\n ],\n };\n }\n\n // Deduplicate by name@version\n const seen = new Set<string>();\n const unique = deps.filter((d) => {\n const key = `${d.name}@${d.version}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n const toCheck = unique.slice(0, MAX_BATCH);\n const truncated = unique.length > MAX_BATCH;\n\n // Batch query OSV\n const vulnResults = await queryVulnsBatch(\n toCheck.map((d) => ({ ecosystem: d.ecosystem as Ecosystem, name: d.name, version: d.version })),\n );\n\n // Build vulnerability findings\n interface Finding {\n name: string;\n version: string;\n severity: string;\n id: string;\n summary: string;\n }\n\n const findings: Finding[] = [];\n const vulnCounts: Partial<Record<string, number>> = {};\n\n for (let i = 0; i < toCheck.length; i++) {\n const dep = toCheck[i];\n const vulns = vulnResults[i] ?? [];\n if (!dep) continue;\n for (const v of vulns) {\n const sev = extractSeverity(v);\n vulnCounts[sev] = (vulnCounts[sev] ?? 0) + 1;\n findings.push({\n name: dep.name,\n version: dep.version,\n severity: sev,\n id: v.id,\n summary: v.summary,\n });\n }\n }\n\n const totalVulns = findings.length;\n const affectedPkgs = new Set(findings.map((f) => `${f.name}@${f.version}`)).size;\n\n // --- Report ---\n const lines: string[] = [\n \"📊 Hound Audit Report\",\n \"═\".repeat(50),\n `Lockfile: ${lockfile_name}`,\n `Scanned: ${toCheck.length} dependencies${truncated ? ` (capped at ${MAX_BATCH} of ${unique.length})` : \"\"}`,\n \"\",\n ];\n\n // Summary counts\n if (totalVulns === 0) {\n lines.push(\"✅ No known vulnerabilities found!\");\n } else {\n lines.push(`Found ${totalVulns} vulnerabilit${totalVulns === 1 ? \"y\" : \"ies\"} across ${affectedPkgs} package${affectedPkgs === 1 ? \"\" : \"s\"}:`);\n for (const sev of SEVERITY_ORDER) {\n const count = vulnCounts[sev] ?? 0;\n if (count > 0) {\n const icon = SEVERITY_ICON[sev] ?? \"⚪\";\n lines.push(` ${icon} ${count} ${sev.toLowerCase()}`);\n }\n }\n }\n\n lines.push(\"\");\n\n // Detailed findings grouped by severity\n if (findings.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"Vulnerable Packages\");\n lines.push(\"─\".repeat(50));\n\n for (const sev of SEVERITY_ORDER) {\n const group = findings.filter((f) => f.severity === sev);\n if (group.length === 0) continue;\n\n const icon = SEVERITY_ICON[sev] ?? \"⚪\";\n lines.push(`\\n${icon} ${sev} (${group.length})`);\n\n // Group by package\n const byPkg: Record<string, Finding[]> = {};\n for (const f of group) {\n const key = `${f.name}@${f.version}`;\n (byPkg[key] ??= []).push(f);\n }\n\n for (const [pkg, pkgFindings] of Object.entries(byPkg)) {\n lines.push(` ${pkg}`);\n for (const f of pkgFindings) {\n lines.push(` ${f.id}: ${f.summary}`);\n }\n }\n }\n\n lines.push(\"\");\n lines.push(\"─\".repeat(50));\n lines.push(\"💡 Run hound_upgrade <package> to find a safe version for each.\");\n lines.push(\"💡 Run hound_vulns <package> <version> for full advisory details.\");\n }\n\n if (truncated) {\n lines.push(\"\");\n lines.push(`⚠️ Only the first ${MAX_BATCH} of ${unique.length} dependencies were checked.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","export interface ParsedDep {\n name: string;\n version: string;\n ecosystem: \"npm\" | \"pypi\" | \"cargo\" | \"go\";\n}\n\n/**\n * Detect lockfile type from filename and parse dependencies.\n * Returns null if the format is unrecognised.\n */\nexport function parseLockfile(filename: string, content: string): ParsedDep[] | null {\n const base = filename.split(\"/\").pop() ?? filename;\n\n if (base === \"package-lock.json\") return parsePackageLock(content);\n if (base === \"yarn.lock\") return parseYarnLock(content);\n if (base === \"pnpm-lock.yaml\") return parsePnpmLock(content);\n if (base === \"requirements.txt\") return parseRequirements(content);\n if (base === \"Cargo.lock\") return parseCargoLock(content);\n if (base === \"go.sum\") return parseGoSum(content);\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// package-lock.json (npm v2/v3 — \"packages\" field)\n// ---------------------------------------------------------------------------\nfunction parsePackageLock(content: string): ParsedDep[] {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return [];\n }\n\n const deps: ParsedDep[] = [];\n\n // v2/v3 format: \"packages\" object with keys like \"node_modules/express\"\n const packages = json.packages as Record<string, { version?: string; dev?: boolean }> | undefined;\n if (packages) {\n for (const [key, val] of Object.entries(packages)) {\n if (!key || key === \"\") continue; // skip root entry\n if (!val.version) continue;\n // Extract package name from path like \"node_modules/foo\" or \"node_modules/@scope/foo\"\n const name = key.replace(/^.*node_modules\\//, \"\");\n if (name) deps.push({ name, version: val.version, ecosystem: \"npm\" });\n }\n return deps;\n }\n\n // v1 format: \"dependencies\" object (legacy)\n const dependencies = json.dependencies as\n | Record<string, { version?: string; requires?: unknown; dependencies?: unknown }>\n | undefined;\n if (dependencies) {\n collectNpmV1(dependencies, deps);\n }\n\n return deps;\n}\n\nfunction collectNpmV1(\n deps: Record<string, { version?: string; dependencies?: unknown }>,\n out: ParsedDep[],\n): void {\n for (const [name, val] of Object.entries(deps)) {\n if (val.version) out.push({ name, version: val.version, ecosystem: \"npm\" });\n if (val.dependencies) {\n collectNpmV1(\n val.dependencies as Record<string, { version?: string; dependencies?: unknown }>,\n out,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// yarn.lock (classic v1 format)\n// ---------------------------------------------------------------------------\nfunction parseYarnLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n const lines = content.split(\"\\n\");\n let currentName: string | null = null;\n\n for (const line of lines) {\n // Entry header: \"package-name@range, package-name@range2:\"\n if (!line.startsWith(\" \") && !line.startsWith(\"#\") && line.includes(\"@\") && line.endsWith(\":\")) {\n // Extract package name from first specifier before the @version part\n const first = line.split(\",\")[0]?.trim().replace(/:$/, \"\") ?? \"\";\n // Handle scoped packages: @scope/name@range\n if (first.startsWith(\"@\")) {\n const atIdx = first.indexOf(\"@\", 1);\n currentName = atIdx > 0 ? first.slice(0, atIdx) : null;\n } else {\n const atIdx = first.indexOf(\"@\");\n currentName = atIdx > 0 ? first.slice(0, atIdx) : null;\n }\n } else if (currentName) {\n const match = /^\\s+version\\s+\"(.+)\"/.exec(line);\n if (match?.[1]) {\n deps.push({ name: currentName, version: match[1], ecosystem: \"npm\" });\n currentName = null;\n }\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// pnpm-lock.yaml (v6/v9)\n// ---------------------------------------------------------------------------\nfunction parsePnpmLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n const lines = content.split(\"\\n\");\n\n // v9 format: packages section has lines like:\n // express@4.18.2:\n // v6 format: /express/4.18.2:\n for (const line of lines) {\n // v9: \" name@version:\" at top level under \"packages:\"\n const v9Match = /^ {2}((?:@[^@/]+\\/)?[^@/][^@]*)@([^:(@]+):/.exec(line);\n if (v9Match?.[1] && v9Match[2]) {\n deps.push({ name: v9Match[1], version: v9Match[2], ecosystem: \"npm\" });\n continue;\n }\n // v6: \" /name/version:\" or \" /@scope/name/version:\"\n const v6Match = /^ {2}\\/((?:@[^/]+\\/)?[^/]+)\\/([^/:(@]+):/.exec(line);\n if (v6Match?.[1] && v6Match[2]) {\n deps.push({ name: v6Match[1], version: v6Match[2], ecosystem: \"npm\" });\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// requirements.txt (pip)\n// ---------------------------------------------------------------------------\nfunction parseRequirements(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.split(\"#\")[0]?.trim() ?? \"\";\n if (!line || line.startsWith(\"-\")) continue;\n\n // name==version or name===version\n const eqMatch = /^([A-Za-z0-9_.-]+)==?=?([^\\s;]+)/.exec(line);\n if (eqMatch?.[1] && eqMatch[2]) {\n deps.push({ name: eqMatch[1].toLowerCase(), version: eqMatch[2], ecosystem: \"pypi\" });\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// Cargo.lock (TOML-like)\n// ---------------------------------------------------------------------------\nfunction parseCargoLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n let name: string | null = null;\n let version: string | null = null;\n let inPackage = false;\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"[[package]]\") {\n if (name && version) deps.push({ name, version, ecosystem: \"cargo\" });\n name = null;\n version = null;\n inPackage = true;\n } else if (inPackage) {\n const nameMatch = /^name\\s*=\\s*\"([^\"]+)\"/.exec(line);\n if (nameMatch?.[1]) name = nameMatch[1];\n const verMatch = /^version\\s*=\\s*\"([^\"]+)\"/.exec(line);\n if (verMatch?.[1]) version = verMatch[1];\n }\n }\n if (name && version) deps.push({ name, version, ecosystem: \"cargo\" });\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// go.sum\n// ---------------------------------------------------------------------------\nfunction parseGoSum(content: string): ParsedDep[] {\n const seen = new Set<string>();\n const deps: ParsedDep[] = [];\n\n for (const line of content.split(\"\\n\")) {\n // format: module/path v1.2.3 h1:hash=\n // or: module/path v1.2.3/go.mod h1:hash=\n const match = /^(\\S+)\\s+v([^\\s/]+)/.exec(line);\n if (match?.[1] && match[2]) {\n const key = `${match[1]}@${match[2]}`;\n if (!seen.has(key)) {\n seen.add(key);\n deps.push({ name: match[1], version: match[2], ecosystem: \"go\" });\n }\n }\n }\n\n return deps;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getPackage, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nconst COPYLEFT_LICENSES = new Set([\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\",\n \"EUPL-1.1\", \"EUPL-1.2\", \"MPL-2.0\", \"OSL-3.0\", \"CDDL-1.0\", \"EPL-1.0\", \"EPL-2.0\",\n]);\n\ninterface PackageData {\n name: string;\n version: string;\n vulnCounts: Record<string, number>;\n totalVulns: number;\n scorecardScore: number | null;\n stars: number | null;\n daysSince: number;\n licenses: string[];\n projectExists: boolean;\n}\n\nasync function gatherPackageData(eco: Ecosystem, name: string): Promise<PackageData | null> {\n // Get package to find default version\n let defaultVersion: string;\n try {\n const pkg = await getPackage(eco, name);\n const defaultV = pkg.versions.find((v) => v.isDefault) ?? pkg.versions[pkg.versions.length - 1];\n if (!defaultV) return null;\n defaultVersion = defaultV.versionKey.version;\n } catch {\n return null;\n }\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, defaultVersion),\n queryVulns(eco, name, defaultVersion),\n ]);\n\n if (versionResult.status === \"rejected\") return null;\n\n const version = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const vulnCounts: Record<string, number> = {};\n for (const v of vulns) {\n const sev = extractSeverity(v);\n vulnCounts[sev] = (vulnCounts[sev] ?? 0) + 1;\n }\n\n const projectId = extractProjectId(version);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n const daysSince = Math.floor(\n (Date.now() - new Date(version.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n\n return {\n name,\n version: defaultVersion,\n vulnCounts,\n totalVulns: vulns.length,\n scorecardScore: projectData?.scorecard?.overallScore ?? null,\n stars: projectData?.starsCount ?? null,\n projectExists: projectData !== null,\n daysSince,\n licenses: version.licenses ?? [],\n };\n}\n\nfunction licenseRisk(licenses: string[]): string {\n if (licenses.length === 0) return \"Unknown\";\n if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) return \"Copyleft\";\n return \"Permissive\";\n}\n\nfunction pad(s: string, n: number): string {\n return s.length >= n ? s : s + \" \".repeat(n - s.length);\n}\n\nfunction winner(a: number, b: number, higherIsBetter = true): [string, string] {\n if (a === b) return [\"\", \"\"];\n const aWins = higherIsBetter ? a > b : a < b;\n return aWins ? [\"✓\", \"\"] : [\"\", \"✓\"];\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_compare\",\n {\n description:\n \"Side-by-side comparison of two packages: vulnerabilities, OpenSSF Scorecard, GitHub stars, release recency, and license. Returns a recommendation.\",\n inputSchema: {\n package_a: z.string().describe(\"First package name\"),\n package_b: z.string().describe(\"Second package name\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ package_a, package_b, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [dataA, dataB] = await Promise.all([\n gatherPackageData(eco, package_a),\n gatherPackageData(eco, package_b),\n ]);\n\n if (!dataA && !dataB) {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find either ${package_a} or ${package_b} in ${ecosystem}.`,\n },\n ],\n };\n }\n if (!dataA) {\n return {\n content: [\n { type: \"text\", text: `Could not find ${package_a} in ${ecosystem}.` },\n ],\n };\n }\n if (!dataB) {\n return {\n content: [\n { type: \"text\", text: `Could not find ${package_b} in ${ecosystem}.` },\n ],\n };\n }\n\n const COL = 22;\n const header = (label: string) =>\n `${pad(label, 24)}${pad(dataA.name, COL)}${pad(dataB.name, COL)}`;\n\n const row = (label: string, valA: string, valB: string, wA = \"\", wB = \"\") =>\n ` ${pad(label, 22)}${pad(wA ? `${valA} ${wA}` : valA, COL)}${wB ? `${valB} ${wB}` : valB}`;\n\n const lines: string[] = [\n `⚖️ Package Comparison (${ecosystem})`,\n \"═\".repeat(70),\n header(\"\"),\n header(\"Metric\"),\n \"─\".repeat(70),\n ];\n\n // Version\n lines.push(row(\"Latest version\", dataA.version, dataB.version));\n\n // Vulnerabilities\n const vulnA = dataA.totalVulns === 0 ? \"None\" : `${dataA.totalVulns} vuln(s)`;\n const vulnB = dataB.totalVulns === 0 ? \"None\" : `${dataB.totalVulns} vuln(s)`;\n const [wVA, wVB] = winner(dataA.totalVulns, dataB.totalVulns, false);\n lines.push(row(\"Vulnerabilities\", vulnA, vulnB, wVA, wVB));\n\n // Critical/High breakdown if any vulns\n if (dataA.totalVulns > 0 || dataB.totalVulns > 0) {\n const critA = (dataA.vulnCounts.CRITICAL ?? 0) + (dataA.vulnCounts.HIGH ?? 0);\n const critB = (dataB.vulnCounts.CRITICAL ?? 0) + (dataB.vulnCounts.HIGH ?? 0);\n lines.push(row(\" Critical/High\", String(critA), String(critB)));\n }\n\n // Scorecard\n const scA = dataA.scorecardScore !== null ? dataA.scorecardScore.toFixed(1) : \"N/A\";\n const scB = dataB.scorecardScore !== null ? dataB.scorecardScore.toFixed(1) : \"N/A\";\n const [wSA, wSB] =\n dataA.scorecardScore !== null && dataB.scorecardScore !== null\n ? winner(dataA.scorecardScore, dataB.scorecardScore)\n : [\"\", \"\"];\n lines.push(row(\"OpenSSF Scorecard\", scA, scB, wSA, wSB));\n\n // Stars\n const stA = dataA.stars !== null ? dataA.stars.toLocaleString() : \"N/A\";\n const stB = dataB.stars !== null ? dataB.stars.toLocaleString() : \"N/A\";\n const [wStA, wStB] =\n dataA.stars !== null && dataB.stars !== null\n ? winner(dataA.stars, dataB.stars)\n : [\"\", \"\"];\n lines.push(row(\"GitHub stars\", stA, stB, wStA, wStB));\n\n // Recency\n const recA = `${dataA.daysSince}d ago`;\n const recB = `${dataB.daysSince}d ago`;\n const [wRA, wRB] = winner(dataA.daysSince, dataB.daysSince, false);\n lines.push(row(\"Last release\", recA, recB, wRA, wRB));\n\n // License\n const licA = dataA.licenses.length > 0 ? dataA.licenses.join(\", \") : \"Unknown\";\n const licB = dataB.licenses.length > 0 ? dataB.licenses.join(\", \") : \"Unknown\";\n lines.push(row(\"License\", licA, licB));\n lines.push(row(\"License risk\", licenseRisk(dataA.licenses), licenseRisk(dataB.licenses)));\n\n // Recommendation\n lines.push(\"\");\n lines.push(\"─\".repeat(70));\n lines.push(\"Recommendation\");\n lines.push(\"─\".repeat(30));\n\n let scoreA = 0;\n let scoreB = 0;\n\n // Fewer vulns is better\n if (dataA.totalVulns < dataB.totalVulns) scoreA += 2;\n else if (dataB.totalVulns < dataA.totalVulns) scoreB += 2;\n\n // Higher scorecard is better\n if (dataA.scorecardScore !== null && dataB.scorecardScore !== null) {\n if (dataA.scorecardScore > dataB.scorecardScore) scoreA++;\n else if (dataB.scorecardScore > dataA.scorecardScore) scoreB++;\n }\n\n // More stars is better\n if (dataA.stars !== null && dataB.stars !== null) {\n if (dataA.stars > dataB.stars) scoreA++;\n else if (dataB.stars > dataA.stars) scoreB++;\n }\n\n // More recent is better\n if (dataA.daysSince < dataB.daysSince) scoreA++;\n else if (dataB.daysSince < dataA.daysSince) scoreB++;\n\n // Permissive license is better\n const lrA = licenseRisk(dataA.licenses);\n const lrB = licenseRisk(dataB.licenses);\n if (lrA === \"Permissive\" && lrB !== \"Permissive\") scoreA++;\n else if (lrB === \"Permissive\" && lrA !== \"Permissive\") scoreB++;\n\n if (scoreA > scoreB) {\n lines.push(`✅ Prefer ${dataA.name} — leads on ${scoreA} of 6 criteria`);\n } else if (scoreB > scoreA) {\n lines.push(`✅ Prefer ${dataB.name} — leads on ${scoreB} of 6 criteria`);\n } else {\n lines.push(`🤝 Both packages are roughly equivalent (${scoreA}/${scoreB} criteria)`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getVersion } from \"../api/depsdev.js\";\nimport { parseLockfile } from \"../parsers/index.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst COPYLEFT_LICENSES = new Set([\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\",\n \"EUPL-1.1\", \"EUPL-1.2\", \"MPL-2.0\", \"OSL-3.0\", \"CDDL-1.0\", \"EPL-1.0\", \"EPL-2.0\",\n]);\n\nconst NETWORK_COPYLEFT = new Set([\"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\", \"EUPL-1.1\", \"EUPL-1.2\"]);\n\n// Licenses allowed under each policy\nconst POLICY_ALLOWLISTS: Record<\"permissive\" | \"copyleft\", Set<string>> = {\n permissive: new Set([\n \"MIT\", \"ISC\", \"BSD-2-Clause\", \"BSD-3-Clause\", \"Apache-2.0\", \"0BSD\",\n \"Unlicense\", \"CC0-1.0\", \"BlueOak-1.0.0\", \"Python-2.0\",\n ]),\n copyleft: new Set([\n \"MIT\", \"ISC\", \"BSD-2-Clause\", \"BSD-3-Clause\", \"Apache-2.0\", \"0BSD\",\n \"Unlicense\", \"CC0-1.0\", \"BlueOak-1.0.0\", \"Python-2.0\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\", \"MPL-2.0\", \"EPL-1.0\", \"EPL-2.0\",\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"CDDL-1.0\", \"OSL-3.0\",\n ]),\n};\n\nfunction classifyLicense(license: string): \"permissive\" | \"weak-copyleft\" | \"copyleft\" | \"network-copyleft\" | \"unknown\" {\n if (NETWORK_COPYLEFT.has(license)) return \"network-copyleft\";\n if (COPYLEFT_LICENSES.has(license)) {\n if (license.startsWith(\"LGPL\") || license === \"MPL-2.0\" || license === \"EPL-1.0\" || license === \"EPL-2.0\" || license === \"CDDL-1.0\") {\n return \"weak-copyleft\";\n }\n return \"copyleft\";\n }\n if (POLICY_ALLOWLISTS.permissive.has(license)) return \"permissive\";\n return \"unknown\";\n}\n\nconst MAX_FETCH = 50;\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_license_check\",\n {\n description:\n \"Scan a lockfile for license compliance. Resolves licenses for every dependency and flags packages that violate the chosen policy (permissive, copyleft, or none).\",\n inputSchema: {\n lockfile_content: z.string().describe(\"Full text content of the lockfile\"),\n lockfile_name: z\n .string()\n .describe(\"Filename: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum\"),\n policy: z\n .enum([\"permissive\", \"copyleft\", \"none\"])\n .default(\"permissive\")\n .describe(\n \"License policy to enforce: 'permissive' (MIT/Apache/BSD only), 'copyleft' (allows GPL but not AGPL), 'none' (report only, no violations)\",\n ),\n },\n },\n async ({ lockfile_content, lockfile_name, policy }) => {\n const deps = parseLockfile(lockfile_name, lockfile_content);\n\n if (deps === null) {\n return {\n content: [\n {\n type: \"text\",\n text: `Unsupported lockfile format: ${lockfile_name}\\n\\nSupported: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum`,\n },\n ],\n };\n }\n\n if (deps.length === 0) {\n return {\n content: [{ type: \"text\", text: `No dependencies found in ${lockfile_name}.` }],\n };\n }\n\n // Deduplicate\n const seen = new Set<string>();\n const unique = deps.filter((d) => {\n const key = `${d.name}@${d.version}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n const toFetch = unique.slice(0, MAX_FETCH);\n const truncated = unique.length > MAX_FETCH;\n\n // Fetch licenses in parallel (ignore failures)\n const licenseResults = await Promise.allSettled(\n toFetch.map((d) => getVersion(d.ecosystem as Ecosystem, d.name, d.version)),\n );\n\n interface LicenseResult {\n name: string;\n version: string;\n licenses: string[];\n classification: string;\n flagged: boolean;\n reason: string;\n }\n\n const allowlist = policy !== \"none\" ? POLICY_ALLOWLISTS[policy] : null;\n const results: LicenseResult[] = [];\n const licenseCount: Record<string, number> = {};\n\n for (let i = 0; i < toFetch.length; i++) {\n const dep = toFetch[i];\n if (!dep) continue;\n const result = licenseResults[i];\n const licenses =\n result?.status === \"fulfilled\" ? (result.value.licenses ?? []) : [];\n\n // Count each license\n for (const l of licenses) {\n licenseCount[l] = (licenseCount[l] ?? 0) + 1;\n }\n\n // Determine if flagged\n let flagged = false;\n let reason = \"\";\n\n if (licenses.length === 0) {\n flagged = policy !== \"none\";\n reason = \"License unknown\";\n } else if (allowlist) {\n const violating = licenses.filter((l) => !allowlist.has(l));\n if (violating.length > 0) {\n flagged = true;\n reason = `License not allowed under ${policy} policy: ${violating.join(\", \")}`;\n }\n }\n\n const classification = licenses.length === 0\n ? \"unknown\"\n : licenses.map(classifyLicense).join(\", \");\n\n if (flagged || licenses.some((l) => classifyLicense(l) !== \"permissive\")) {\n results.push({ name: dep.name, version: dep.version, licenses, classification, flagged, reason });\n }\n }\n\n const flagged = results.filter((r) => r.flagged);\n const infoOnly = results.filter((r) => !r.flagged);\n\n const lines: string[] = [\n \"🔏 Hound License Check\",\n \"═\".repeat(50),\n `Lockfile: ${lockfile_name}`,\n `Policy: ${policy}`,\n `Scanned: ${toFetch.length} packages${truncated ? ` (first ${MAX_FETCH} of ${unique.length})` : \"\"}`,\n \"\",\n ];\n\n if (flagged.length === 0) {\n lines.push(`✅ No license violations found`);\n if (policy !== \"none\") {\n lines.push(` All scanned packages comply with the ${policy} policy.`);\n }\n } else {\n lines.push(`⚠️ ${flagged.length} license violation${flagged.length === 1 ? \"\" : \"s\"} found`);\n lines.push(\"─\".repeat(50));\n for (const r of flagged) {\n const lic = r.licenses.length > 0 ? r.licenses.join(\", \") : \"unknown\";\n lines.push(` ${r.name}@${r.version}`);\n lines.push(` License: ${lic}`);\n lines.push(` ${r.reason}`);\n lines.push(\"\");\n }\n }\n\n if (infoOnly.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"Non-permissive licenses (not violations):\");\n for (const r of infoOnly) {\n const lic = r.licenses.join(\", \");\n lines.push(` ${r.name}@${r.version} ${lic}`);\n }\n lines.push(\"\");\n }\n\n // Top licenses summary\n const topLicenses = Object.entries(licenseCount)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 8);\n\n if (topLicenses.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"License distribution:\");\n for (const [lic, count] of topLicenses) {\n lines.push(` ${String(count).padStart(4)}× ${lic}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"Source: deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getPackage, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nconst COPYLEFT_LICENSES = new Set([\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\",\n \"EUPL-1.1\", \"EUPL-1.2\", \"MPL-2.0\", \"OSL-3.0\", \"CDDL-1.0\", \"EPL-1.0\", \"EPL-2.0\",\n]);\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_preinstall\",\n {\n description:\n \"Safety check before installing a package. Checks known vulnerabilities, typosquatting risk, abandonment, and license concerns. Returns a go/no-go verdict.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().optional().describe(\"Package version (defaults to latest)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n // Resolve version if not provided\n let resolvedVersion = version ?? \"\";\n if (!resolvedVersion) {\n try {\n const pkg = await getPackage(eco, name);\n const defaultV =\n pkg.versions.find((v) => v.isDefault) ?? pkg.versions[pkg.versions.length - 1];\n resolvedVersion = defaultV?.versionKey.version ?? \"\";\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `❌ Could not find package ${name} in ${ecosystem}. Check the package name.`,\n },\n ],\n };\n }\n }\n\n if (!resolvedVersion) {\n return {\n content: [\n { type: \"text\", text: `❌ Could not resolve a version for ${name} in ${ecosystem}.` },\n ],\n };\n }\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, resolvedVersion),\n queryVulns(eco, name, resolvedVersion),\n ]);\n\n if (versionResult.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `❌ Could not find ${name}@${resolvedVersion} in ${ecosystem}.`,\n },\n ],\n };\n }\n\n const pkg = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n // --- Checks ---\n const issues: { level: \"block\" | \"warn\" | \"info\"; message: string }[] = [];\n\n // 1. Vulnerabilities\n const criticalVulns = vulns.filter((v) => {\n const sev = extractSeverity(v);\n return sev === \"CRITICAL\" || sev === \"HIGH\";\n });\n if (criticalVulns.length > 0) {\n issues.push({\n level: \"block\",\n message: `${criticalVulns.length} CRITICAL/HIGH vulnerabilit${criticalVulns.length === 1 ? \"y\" : \"ies\"} known for this version`,\n });\n } else if (vulns.length > 0) {\n issues.push({\n level: \"warn\",\n message: `${vulns.length} moderate/low vulnerabilit${vulns.length === 1 ? \"y\" : \"ies\"} known for this version`,\n });\n }\n\n // 2. Typosquatting heuristics\n const typoReasons: string[] = [];\n if (/[0O1lI]/.test(name)) typoReasons.push(\"contains look-alike characters (0/O, 1/l/I)\");\n if (name.length <= 2) typoReasons.push(\"very short name\");\n if (/(.)\\1{2,}/.test(name)) typoReasons.push(\"repeated characters\");\n if (/[^a-z0-9@/._-]/.test(name)) typoReasons.push(\"unusual characters in name\");\n if (typoReasons.length >= 2) {\n issues.push({\n level: \"warn\",\n message: `Possible typosquatting risk: ${typoReasons.join(\"; \")}`,\n });\n }\n\n // 3. Abandonment — no update in >2 years + no scorecard\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n if (daysSince > 730) {\n issues.push({\n level: \"warn\",\n message: `Package version is ${Math.floor(daysSince / 365)} year(s) old — may be abandoned`,\n });\n }\n\n // 4. Low OpenSSF scorecard\n if (projectData?.scorecard != null && projectData.scorecard.overallScore < 3) {\n issues.push({\n level: \"warn\",\n message: `Low OpenSSF Scorecard score: ${projectData.scorecard.overallScore.toFixed(1)}/10`,\n });\n } else if (projectData === null) {\n issues.push({\n level: \"info\",\n message: \"No OpenSSF Scorecard data available\",\n });\n }\n\n // 5. License\n const licenses = pkg.licenses ?? [];\n if (licenses.length === 0) {\n issues.push({ level: \"warn\", message: \"License unknown\" });\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n issues.push({\n level: \"warn\",\n message: `Copyleft license detected: ${licenses.join(\", \")}`,\n });\n }\n\n // --- Verdict ---\n const blockers = issues.filter((i) => i.level === \"block\");\n const warnings = issues.filter((i) => i.level === \"warn\");\n const infos = issues.filter((i) => i.level === \"info\");\n\n const verdict = blockers.length > 0 ? \"NO-GO\" : warnings.length > 0 ? \"CAUTION\" : \"GO\";\n const verdictEmoji = verdict === \"GO\" ? \"✅\" : verdict === \"CAUTION\" ? \"⚠️\" : \"🚫\";\n\n const lines: string[] = [\n `${verdictEmoji} Pre-install check: ${name}@${resolvedVersion} (${ecosystem})`,\n \"═\".repeat(60),\n `Verdict: ${verdict}`,\n \"\",\n ];\n\n if (blockers.length > 0) {\n lines.push(\"🚫 Blockers\");\n lines.push(\"─\".repeat(30));\n for (const issue of blockers) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (warnings.length > 0) {\n lines.push(\"⚠️ Warnings\");\n lines.push(\"─\".repeat(30));\n for (const issue of warnings) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (infos.length > 0) {\n lines.push(\"ℹ️ Info\");\n lines.push(\"─\".repeat(30));\n for (const issue of infos) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (blockers.length === 0 && warnings.length === 0) {\n lines.push(\" No issues found — safe to install.\");\n lines.push(\"\");\n }\n\n if (vulns.length > 0) {\n lines.push(`💡 Run hound_vulns for full vulnerability details.`);\n }\n if (blockers.length > 0) {\n lines.push(`💡 Run hound_upgrade to find a safe version.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nconst COPYLEFT_LICENSES = new Set([\n \"GPL-2.0\",\n \"GPL-2.0-only\",\n \"GPL-2.0-or-later\",\n \"GPL-3.0\",\n \"GPL-3.0-only\",\n \"GPL-3.0-or-later\",\n \"AGPL-3.0\",\n \"AGPL-3.0-only\",\n \"AGPL-3.0-or-later\",\n \"LGPL-2.0\",\n \"LGPL-2.1\",\n \"LGPL-3.0\",\n \"EUPL-1.1\",\n \"EUPL-1.2\",\n \"MPL-2.0\",\n \"OSL-3.0\",\n \"CDDL-1.0\",\n \"EPL-1.0\",\n \"EPL-2.0\",\n]);\n\nfunction letterGrade(score: number): string {\n if (score >= 90) return \"A\";\n if (score >= 75) return \"B\";\n if (score >= 60) return \"C\";\n if (score >= 40) return \"D\";\n return \"F\";\n}\n\nfunction gradeEmoji(grade: string): string {\n switch (grade) {\n case \"A\": return \"🟢\";\n case \"B\": return \"🟡\";\n case \"C\": return \"🟠\";\n case \"D\": return \"🔴\";\n default: return \"💀\";\n }\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_score\",\n {\n description:\n \"Compute a 0-100 Hound Score for a package version combining vulnerability severity, OpenSSF Scorecard, release recency, and license risk. Returns a letter grade (A-F) with a breakdown.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, version),\n queryVulns(eco, name, version),\n ]);\n\n if (versionResult.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find ${name}@${version} in ${ecosystem}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const pkg = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n // --- Scoring components ---\n\n // 1. Vulnerability score (0-40 points)\n let vulnScore = 40;\n for (const v of vulns) {\n const sev = extractSeverity(v);\n switch (sev) {\n case \"CRITICAL\": vulnScore -= 20; break;\n case \"HIGH\": vulnScore -= 10; break;\n case \"MODERATE\": vulnScore -= 5; break;\n case \"LOW\": vulnScore -= 2; break;\n }\n }\n vulnScore = Math.max(0, vulnScore);\n\n // 2. OpenSSF Scorecard (0-25 points)\n let scorecardScore = 0;\n if (projectData?.scorecard != null) {\n scorecardScore = Math.round((projectData.scorecard.overallScore / 10) * 25);\n } else if (projectData !== null) {\n scorecardScore = 10; // project exists but no scorecard\n }\n\n // 3. Recency score (0-20 points) — penalize stale packages\n let recencyScore = 20;\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n if (daysSince > 730) recencyScore = 5; // >2 years\n else if (daysSince > 365) recencyScore = 10; // >1 year\n else if (daysSince > 180) recencyScore = 15; // >6 months\n\n // 4. License score (0-15 points)\n let licenseScore = 15;\n const licenses = pkg.licenses ?? [];\n if (licenses.length === 0) {\n licenseScore = 5; // unknown license\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n licenseScore = 8; // copyleft\n }\n\n const total = vulnScore + scorecardScore + recencyScore + licenseScore;\n const grade = letterGrade(total);\n const emoji = gradeEmoji(grade);\n\n const lines: string[] = [\n `${emoji} Hound Score: ${total}/100 — Grade ${grade}`,\n ` ${name}@${version} (${ecosystem})`,\n \"═\".repeat(50),\n \"\",\n \"Score Breakdown\",\n \"─\".repeat(30),\n ` Security (vulns) ${vulnScore.toString().padStart(3)}/40`,\n ` OpenSSF Scorecard ${scorecardScore.toString().padStart(3)}/25`,\n ` Release recency ${recencyScore.toString().padStart(3)}/20`,\n ` License ${licenseScore.toString().padStart(3)}/15`,\n ` ${\"─\".repeat(6)}`,\n ` Total ${total.toString().padStart(3)}/100`,\n \"\",\n ];\n\n // Details\n if (vulns.length > 0) {\n const counts: Record<string, number> = {};\n for (const v of vulns) {\n const sev = extractSeverity(v);\n counts[sev] = (counts[sev] ?? 0) + 1;\n }\n const summary = Object.entries(counts).map(([s, n]) => `${n} ${s.toLowerCase()}`).join(\", \");\n lines.push(`⚠️ ${vulns.length} known vuln(s): ${summary}`);\n } else {\n lines.push(\"✅ No known vulnerabilities\");\n }\n\n if (projectData?.scorecard != null) {\n lines.push(`🏆 OpenSSF Scorecard: ${projectData.scorecard.overallScore.toFixed(1)}/10`);\n } else if (projectData === null) {\n lines.push(\"ℹ️ No OpenSSF Scorecard data available\");\n }\n\n lines.push(`📅 Published ${daysSince} days ago`);\n\n if (licenses.length === 0) {\n lines.push(\"⚠️ License unknown\");\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n lines.push(`⚠️ Copyleft license: ${licenses.join(\", \")}`);\n } else {\n lines.push(`✅ License: ${licenses.join(\", \")}`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport { queryVulnsBatch } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nfunction parseVersion(v: string): number[] {\n return v.split(\".\").map((p) => parseInt(p.replace(/[^0-9]/g, \"\"), 10) || 0);\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = parseVersion(a);\n const pb = parseVersion(b);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_upgrade\",\n {\n description:\n \"Find the minimum version upgrade that resolves all known vulnerabilities for a package. Checks every published version and returns the nearest safe one.\",\n inputSchema: {\n name: z.string().describe(\"Package name (e.g. express, lodash)\"),\n version: z.string().describe(\"Current vulnerable version (e.g. 4.17.20)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n let pkg: Awaited<ReturnType<typeof getPackage>>;\n try {\n pkg = await getPackage(eco, name);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find package ${name} in ${ecosystem}. Check the package name.`,\n },\n ],\n };\n }\n\n // Filter to versions newer than current, sort ascending\n const candidates = pkg.versions\n .map((v) => v.versionKey.version)\n .filter((v) => compareVersions(v, version) > 0)\n .sort(compareVersions);\n\n if (candidates.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `⚠️ No newer versions of ${name} found in ${ecosystem}.\\nCurrent version: ${version}\\n\\nThis may be the latest version already.`,\n },\n ],\n };\n }\n\n // Batch query all candidates (up to 50 to avoid huge requests)\n const toCheck = candidates.slice(0, 50);\n const vulnResults = await queryVulnsBatch(\n toCheck.map((v) => ({ ecosystem: eco, name, version: v })),\n );\n\n const safeVersions = toCheck.filter((_, i) => (vulnResults[i]?.length ?? 0) === 0);\n const latestVersion = candidates[candidates.length - 1] ?? version;\n const latestVulns = vulnResults[toCheck.indexOf(latestVersion)] ?? [];\n\n const lines: string[] = [\n `🔍 Safe upgrade finder: ${name} (${ecosystem})`,\n \"═\".repeat(50),\n `Current version: ${version}`,\n `Candidates checked: ${toCheck.length} of ${candidates.length} newer versions`,\n \"\",\n ];\n\n if (safeVersions.length === 0) {\n lines.push(`❌ No safe upgrade found — all ${toCheck.length} newer versions have known vulnerabilities.`);\n lines.push(\"\");\n lines.push(\"Consider:\");\n lines.push(\" • Checking if a patch is in progress via hound_advisories\");\n lines.push(\" • Evaluating an alternative package via hound_compare\");\n } else {\n const minimum = safeVersions[0] ?? \"\";\n const latest = safeVersions[safeVersions.length - 1] ?? \"\";\n\n lines.push(`✅ Safe upgrade available`);\n lines.push(\"\");\n lines.push(` Minimum safe version: ${minimum}`);\n if (minimum !== latest) {\n lines.push(` Latest safe version: ${latest}`);\n }\n lines.push(\"\");\n\n if (latestVulns.length > 0 && safeVersions[safeVersions.length - 1] !== latestVersion) {\n lines.push(`⚠️ Latest version (${latestVersion}) still has ${latestVulns.length} known vuln(s).`);\n lines.push(` Recommended: upgrade to ${latest}`);\n } else {\n lines.push(`💡 Recommended: upgrade to ${latest}`);\n }\n\n // Show how many versions were skipped as unsafe\n const unsafeCount = toCheck.filter((_, i) => (vulnResults[i]?.length ?? 0) > 0).length;\n if (unsafeCount > 0) {\n lines.push(` (${unsafeCount} intermediate version(s) skipped — still vulnerable)`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractFixVersions, extractSeverity, queryVulns } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n\nconst SEVERITY_ICON: Record<string, string> = {\n CRITICAL: \"🔴\",\n HIGH: \"🟠\",\n MODERATE: \"🟡\",\n LOW: \"🔵\",\n UNKNOWN: \"⚪\",\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_vulns\",\n {\n description:\n \"List all known vulnerabilities for a specific package version, grouped by severity with fix versions and advisory links.\",\n inputSchema: {\n name: z.string().describe(\"Package name (e.g. express, lodash)\"),\n version: z.string().describe(\"Package version (e.g. 4.18.2)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n let vulns: Awaited<ReturnType<typeof queryVulns>>;\n try {\n vulns = await queryVulns(ecosystem as Ecosystem, name, version);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to query vulnerabilities for ${name}@${version}. The OSV API may be temporarily unavailable.`,\n },\n ],\n };\n }\n\n if (vulns.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `✅ No known vulnerabilities found for ${name}@${version} (${ecosystem}).\\n\\nThis checks the OSV database which covers GitHub Advisory Database, NVD, and more.`,\n },\n ],\n };\n }\n\n const bySeverity: Record<string, typeof vulns> = {\n CRITICAL: [],\n HIGH: [],\n MODERATE: [],\n LOW: [],\n UNKNOWN: [],\n };\n\n for (const vuln of vulns) {\n const sev = extractSeverity(vuln);\n bySeverity[sev]?.push(vuln);\n }\n\n const lines: string[] = [\n `🔍 Vulnerabilities in ${name}@${version} (${ecosystem})`,\n \"─\".repeat(50),\n `Found ${vulns.length} vulnerability${vulns.length === 1 ? \"\" : \"ies\"}`,\n \"\",\n ];\n\n for (const severity of [\"CRITICAL\", \"HIGH\", \"MODERATE\", \"LOW\", \"UNKNOWN\"]) {\n const group = bySeverity[severity] ?? [];\n if (group.length === 0) continue;\n\n const icon = SEVERITY_ICON[severity] ?? \"⚪\";\n lines.push(`${icon} ${severity} (${group.length})`);\n lines.push(\"─\".repeat(30));\n\n for (const vuln of group) {\n lines.push(` ${vuln.id}`);\n lines.push(` ${vuln.summary}`);\n\n const fixes = extractFixVersions(vuln, ecosystem as Ecosystem);\n if (fixes.length > 0) {\n lines.push(` Fix: upgrade to ${fixes.join(\" or \")}`);\n } else {\n lines.push(` Fix: no patched version available`);\n }\n\n if (vuln.aliases && vuln.aliases.length > 0) {\n lines.push(` Also known as: ${vuln.aliases.join(\", \")}`);\n }\n\n lines.push(` Published: ${vuln.published.slice(0, 10)}`);\n lines.push(\"\");\n }\n }\n\n lines.push(`Source: https://osv.dev`);\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n"],"mappings":"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","names":["z","z","z","BASE_URL","ECOSYSTEM_MAP","z","z","register","z","z","ECOSYSTEM_VALUES","register","z","z","ECOSYSTEM_VALUES","register","z","z","ECOSYSTEM_VALUES","register","z","z","register","z","z","ECOSYSTEM_VALUES","register","z","z","COPYLEFT_LICENSES","register","z","flagged","z","ECOSYSTEM_VALUES","COPYLEFT_LICENSES","register","z","pkg","z","ECOSYSTEM_VALUES","COPYLEFT_LICENSES","register","z","z","ECOSYSTEM_VALUES","register","z","z","ECOSYSTEM_VALUES","SEVERITY_ICON","register","z","register"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/prompts/package_evaluation.ts","../src/prompts/pre_release_check.ts","../src/prompts/security_audit.ts","../src/prompts/index.ts","../src/tools/advisories.ts","../src/api/depsdev.ts","../src/api/osv.ts","../src/tools/inspect.ts","../src/constants/ecosystems.ts","../src/tools/popular.ts","../src/utils/getDefaultVersion.ts","../src/tools/tree.ts","../src/tools/typosquat.ts","../src/tools/audit.ts","../src/parsers/index.ts","../src/tools/compare.ts","../src/constants/licenses.ts","../src/tools/license-check.ts","../src/tools/preinstall.ts","../src/tools/score.ts","../src/tools/upgrade.ts","../src/tools/vulns.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err: unknown) => {\n console.error(\"Fatal error:\", err);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerPrompts } from \"./prompts/index.js\";\nimport { register as registerAdvisories } from \"./tools/advisories.js\";\nimport { register as registerInspect } from \"./tools/inspect.js\";\nimport { register as registerPopular } from \"./tools/popular.js\";\nimport { register as registerTree } from \"./tools/tree.js\";\nimport { register as registerTyposquat } from \"./tools/typosquat.js\";\nimport { register as registerAudit } from \"./tools/audit.js\";\nimport { register as registerCompare } from \"./tools/compare.js\";\nimport { register as registerLicenseCheck } from \"./tools/license-check.js\";\nimport { register as registerPreinstall } from \"./tools/preinstall.js\";\nimport { register as registerScore } from \"./tools/score.js\";\nimport { register as registerUpgrade } from \"./tools/upgrade.js\";\nimport { register as registerVulns } from \"./tools/vulns.js\";\n\nconst SERVER_NAME = \"hound-mcp\";\nconst SERVER_VERSION = __APP_VERSION__;\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: SERVER_NAME,\n version: SERVER_VERSION,\n });\n\n registerVulns(server);\n registerInspect(server);\n registerTree(server);\n registerTyposquat(server);\n registerAdvisories(server);\n registerPopular(server);\n registerAudit(server);\n registerCompare(server);\n registerLicenseCheck(server);\n registerPreinstall(server);\n registerScore(server);\n registerUpgrade(server);\n registerPrompts(server);\n\n return server;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function packageEvaluationRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"package_evaluation\",\n {\n description:\n \"Evaluate a package before adding it as a dependency. Returns a go/no-go recommendation with security, license, and health analysis.\",\n argsSchema: {\n package: z.string().describe(\"Package name to evaluate (e.g. express, requests, serde)\"),\n version: z\n .string()\n .optional()\n .describe(\"Specific version to evaluate. Uses latest stable if omitted.\"),\n ecosystem: z.string().optional().describe(\"Package ecosystem. Defaults to npm if omitted.\"),\n },\n },\n ({ package: pkg, version, ecosystem }) => {\n const eco = ecosystem ?? \"npm\";\n const versionNote = version ? `version ${version} of ` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `I'm considering adding ${versionNote}\\`${pkg}\\` (${eco}) as a dependency. Please evaluate it thoroughly.\n\nSteps:\n1. Use \\`hound_inspect\\` on \\`${pkg}\\`${version ? `@${version}` : \"\"} (ecosystem: ${eco}) to get the full health profile — licenses, vulnerabilities, OpenSSF Scorecard, GitHub stats.\n2. Use \\`hound_vulns\\` to get the full vulnerability list with fix versions.\n3. Use \\`hound_typosquat\\` to confirm this is the legitimate package and not a typosquat.\n4. Use \\`hound_tree\\` to check the transitive dependency count — packages with hundreds of transitive deps carry more supply chain risk.\n5. If any advisories are listed, use \\`hound_advisories\\` to get the details.\n\nGive me a clear **GO / NO-GO / CONDITIONAL** recommendation with reasoning. If conditional, state exactly what version or conditions would make it acceptable.`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function preReleaseCheckRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"pre_release_check\",\n {\n description:\n \"Run a pre-release dependency scan before shipping. Checks for vulnerabilities and license issues that could block a release.\",\n argsSchema: {\n version: z.string().optional().describe(\"The version you are about to release, e.g. 1.2.0\"),\n },\n },\n ({ version }) => {\n const versionNote = version ? ` (version ${version})` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `I'm about to release this project${versionNote}. Run a pre-release dependency check.\n\nSteps:\n1. Use \\`hound_popular\\` to scan all key packages in this project's ecosystem for known vulnerabilities.\n2. For any packages identified as critical to this project, use \\`hound_vulns\\` to check for vulnerabilities.\n3. Use \\`hound_inspect\\` on the top 5 dependencies by importance to verify licenses are compatible and no advisories are outstanding.\n4. Flag any HIGH or CRITICAL severity vulnerabilities as **release blockers**.\n5. Flag any copyleft licenses (GPL, AGPL, LGPL) that may conflict with the project's MIT license as **license blockers**.\n\nOutput a release checklist:\n- ✅ or ❌ Vulnerabilities (CRITICAL/HIGH)\n- ✅ or ❌ License compatibility\n- ✅ or ❌ No abandoned dependencies (last published >2 years ago)\n\nEnd with a clear **SAFE TO RELEASE** or **BLOCKED — fix these issues first** verdict.`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\n\nexport function securityAuditRegisterPrompt(server: McpServer): void {\n server.registerPrompt(\n \"security_audit\",\n {\n description:\n \"Run a full security audit on the current project's dependencies. Scans for vulnerabilities, license issues, and typosquat risks across your entire dependency tree.\",\n argsSchema: {\n ecosystem: z\n .string()\n .optional()\n .describe(\"Package ecosystem (npm, pypi, cargo, etc). Auto-detected if omitted.\"),\n },\n },\n ({ ecosystem }) => {\n const ecoNote = ecosystem ? ` The project uses ${ecosystem}.` : \"\";\n return {\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `Please run a comprehensive security audit on this project's dependencies.${ecoNote}\n\nFollow these steps:\n1. Use \\`hound_popular\\` to check the most commonly used packages in this ecosystem for known vulnerabilities — this gives a quick baseline.\n2. For any specific packages you can identify in the project, use \\`hound_vulns\\` to check each one for CVEs and advisories.\n3. Use \\`hound_inspect\\` on the 3-5 most critical dependencies to check their licenses, OpenSSF Scorecard, and GitHub health.\n4. For any package names that look unusual or unfamiliar, use \\`hound_typosquat\\` to check for potential typosquatting.\n5. If any vulnerabilities are found, use \\`hound_advisories\\` to get full details and fix guidance.\n\nSummarize findings as:\n- **Critical / High** vulnerabilities that need immediate attention\n- **License risks** (copyleft licenses, unknown licenses)\n- **Health concerns** (abandoned packages, low Scorecard scores)\n- **Recommended actions** with specific version upgrades where available`,\n },\n },\n ],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { packageEvaluationRegisterPrompt } from \"./package_evaluation.js\";\nimport { preReleaseCheckRegisterPrompt } from \"./pre_release_check.js\";\nimport { securityAuditRegisterPrompt } from \"./security_audit.js\";\n\nexport function registerPrompts(server: McpServer): void {\n securityAuditRegisterPrompt(server);\n packageEvaluationRegisterPrompt(server);\n preReleaseCheckRegisterPrompt(server);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getAdvisory } from \"../api/depsdev.js\";\nimport { getVuln } from \"../api/osv.js\";\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_advisories\",\n {\n description:\n \"Get full details for a security advisory by ID (GHSA, CVE, or OSV ID). Returns title, severity, affected versions, fix versions, and references.\",\n inputSchema: {\n id: z\n .string()\n .describe(\"Advisory ID — e.g. GHSA-rv95-896h-c2vc, CVE-2024-29041, or any OSV ID\"),\n },\n },\n async ({ id }) => {\n // Try OSV first (richer data), fall back to deps.dev advisory endpoint\n const [osvResult, depsdevResult] = await Promise.allSettled([getVuln(id), getAdvisory(id)]);\n\n const lines: string[] = [];\n\n if (osvResult.status === \"fulfilled\") {\n const vuln = osvResult.value;\n\n lines.push(`🔔 Advisory: ${vuln.id}`);\n lines.push(\"═\".repeat(50));\n lines.push(\"\");\n lines.push(`📋 Summary: ${vuln.summary}`);\n lines.push(`📅 Published: ${vuln.published.slice(0, 10)}`);\n lines.push(`🔄 Last modified: ${vuln.modified.slice(0, 10)}`);\n\n if (vuln.aliases && vuln.aliases.length > 0) {\n lines.push(`🔗 Also known as: ${vuln.aliases.join(\", \")}`);\n }\n\n const dbSeverity = vuln.database_specific?.severity;\n if (dbSeverity) {\n lines.push(`⚠️ Severity: ${dbSeverity}`);\n }\n\n if (vuln.database_specific?.cwe_ids && vuln.database_specific.cwe_ids.length > 0) {\n lines.push(`🏷️ CWE: ${vuln.database_specific.cwe_ids.join(\", \")}`);\n }\n\n if (vuln.affected.length > 0) {\n lines.push(\"\");\n lines.push(\"📦 Affected packages\");\n lines.push(\"─\".repeat(30));\n\n for (const affected of vuln.affected) {\n lines.push(` ${affected.package.ecosystem}: ${affected.package.name}`);\n\n for (const range of affected.ranges) {\n if (range.type === \"SEMVER\") {\n const introduced = range.events.find((e) => \"introduced\" in e);\n const fixed = range.events.find((e) => \"fixed\" in e);\n const introStr =\n introduced && \"introduced\" in introduced ? introduced.introduced : \"0\";\n if (fixed && \"fixed\" in fixed) {\n lines.push(` Affected: >= ${introStr}, fixed in ${fixed.fixed}`);\n } else {\n lines.push(` Affected: >= ${introStr} (no fix available)`);\n }\n }\n }\n }\n }\n\n if (vuln.details) {\n lines.push(\"\");\n lines.push(\"📝 Details\");\n lines.push(\"─\".repeat(30));\n // Trim details to a reasonable length\n const details =\n vuln.details.length > 500 ? `${vuln.details.slice(0, 500)}...` : vuln.details;\n lines.push(details);\n }\n\n if (vuln.references && vuln.references.length > 0) {\n lines.push(\"\");\n lines.push(\"🔗 References\");\n lines.push(\"─\".repeat(30));\n for (const ref of vuln.references.slice(0, 5)) {\n lines.push(` ${ref.url}`);\n }\n if (vuln.references.length > 5) {\n lines.push(` ... and ${vuln.references.length - 5} more`);\n }\n }\n\n lines.push(\"\");\n lines.push(`Source: https://osv.dev/vulnerability/${id}`);\n } else if (depsdevResult.status === \"fulfilled\") {\n // Fallback to deps.dev advisory data\n const advisory = depsdevResult.value;\n\n lines.push(`🔔 Advisory: ${advisory.advisoryKey.id}`);\n lines.push(\"═\".repeat(50));\n lines.push(\"\");\n lines.push(`📋 Title: ${advisory.title}`);\n\n if (advisory.aliases.length > 0) {\n lines.push(`🔗 Also known as: ${advisory.aliases.join(\", \")}`);\n }\n\n lines.push(`⚠️ CVSS v3 Score: ${advisory.cvss3Score}`);\n lines.push(`📐 CVSS Vector: ${advisory.cvss3Vector}`);\n lines.push(\"\");\n lines.push(`Source: ${advisory.url}`);\n } else {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find advisory \"${id}\". Check the ID format (e.g. GHSA-xxxx-xxxx-xxxx or CVE-YYYY-NNNNN).`,\n },\n ],\n };\n }\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","/**\n * Client for the deps.dev API (Google Open Source Insights).\n *\n * Base URL: https://api.deps.dev/v3/\n * Auth: none\n * Docs: https://deps.dev/about\n *\n * Ecosystem names in URLs must be uppercase (NPM, PYPI, GO, MAVEN, CARGO, NUGET, RUBYGEMS).\n * Project keys use %2F encoding for slashes (github.com%2Fowner%2Frepo).\n */\n\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst BASE_URL = \"https://api.deps.dev/v3\";\n\nconst ECOSYSTEM_MAP: Record<Ecosystem, string> = {\n npm: \"npm\",\n pypi: \"pypi\",\n go: \"go\",\n maven: \"maven\",\n cargo: \"cargo\",\n nuget: \"nuget\",\n rubygems: \"rubygems\",\n};\n\nexport interface DepsDevVersionKey {\n system: string;\n name: string;\n version: string;\n}\n\nexport interface DepsDevAdvisoryKey {\n id: string;\n}\n\nexport interface DepsDevLink {\n label: string;\n url: string;\n}\n\nexport interface DepsDevRelatedProject {\n projectKey: { id: string };\n relationProvenance: string;\n relationType: string;\n}\n\nexport interface DepsDevVersion {\n versionKey: DepsDevVersionKey;\n publishedAt: string;\n isDefault: boolean;\n licenses?: string[];\n advisoryKeys?: DepsDevAdvisoryKey[];\n links?: DepsDevLink[];\n relatedProjects?: DepsDevRelatedProject[];\n}\n\nexport interface DepsDevPackage {\n packageKey: { system: string; name: string };\n versions: {\n versionKey: DepsDevVersionKey;\n publishedAt: string;\n isDefault: boolean;\n }[];\n}\n\nexport interface DepsDevDepNode {\n versionKey: DepsDevVersionKey;\n bundled: boolean;\n relation: \"SELF\" | \"DIRECT\" | \"INDIRECT\";\n errors: string[];\n}\n\nexport interface DepsDevDepEdge {\n fromNode: number;\n toNode: number;\n requirement: string;\n}\n\nexport interface DepsDevDependencies {\n nodes: DepsDevDepNode[];\n edges: DepsDevDepEdge[];\n}\n\nexport interface DepsDevScorecardCheck {\n name: string;\n score: number;\n reason: string;\n details: string[];\n}\n\nexport interface DepsDevScorecard {\n date: string;\n repository: { name: string; commit: string };\n overallScore: number;\n checks: DepsDevScorecardCheck[];\n}\n\nexport interface DepsDevProject {\n projectKey: { id: string };\n openIssuesCount: number;\n starsCount: number;\n forksCount: number;\n license: string;\n description: string;\n homepage: string;\n scorecard: DepsDevScorecard | null;\n}\n\nexport interface DepsDevAdvisory {\n advisoryKey: { id: string };\n url: string;\n title: string;\n aliases: string[];\n cvss3Score: number;\n cvss3Vector: string;\n}\n\nasync function get<T>(path: string): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const res = await fetch(url, {\n headers: { \"User-Agent\": `hound-mcp/${__APP_VERSION__}` },\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => \"\");\n throw new DepsDevError(res.status, url, body);\n }\n\n return res.json() as Promise<T>;\n}\n\nexport class DepsDevError extends Error {\n constructor(\n public readonly status: number,\n public readonly url: string,\n public readonly body: string,\n ) {\n super(`deps.dev API error ${status} for ${url}`);\n this.name = \"DepsDevError\";\n }\n}\n\n/**\n * Get metadata for a specific package version.\n * Includes licenses, advisory keys, and related project links.\n */\nexport async function getVersion(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<DepsDevVersion> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevVersion>(\n `/systems/${sys}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}`,\n );\n}\n\n/**\n * Get all versions of a package.\n * Useful for finding available upgrade targets.\n */\nexport async function getPackage(ecosystem: Ecosystem, name: string): Promise<DepsDevPackage> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevPackage>(`/systems/${sys}/packages/${encodeURIComponent(name)}`);\n}\n\n/**\n * Get the full resolved dependency graph for a package version.\n * Returns nodes (packages) and edges (dependency relationships).\n * relationType: SELF = the package itself, DIRECT = direct deps, INDIRECT = transitive deps.\n */\nexport async function getDependencies(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<DepsDevDependencies> {\n const sys = ECOSYSTEM_MAP[ecosystem];\n return get<DepsDevDependencies>(\n `/systems/${sys}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}:dependencies`,\n );\n}\n\n/**\n * Get project metadata and OpenSSF Scorecard for a GitHub/GitLab project.\n * projectId format: \"github.com/owner/repo\"\n */\nexport async function getProject(projectId: string): Promise<DepsDevProject> {\n const encoded = projectId.replaceAll(\"/\", \"%2F\");\n return get<DepsDevProject>(`/projects/${encoded}`);\n}\n\n/**\n * Get full advisory details by advisory ID (e.g. \"GHSA-rv95-896h-c2vc\").\n */\nexport async function getAdvisory(advisoryId: string): Promise<DepsDevAdvisory> {\n return get<DepsDevAdvisory>(`/advisories/${encodeURIComponent(advisoryId)}`);\n}\n\n/**\n * Extract the GitHub/GitLab project ID from a version's relatedProjects list.\n * Returns the first SOURCE_REPO or ISSUE_TRACKER project ID found, or null.\n */\nexport function extractProjectId(version: DepsDevVersion): string | null {\n const related = version.relatedProjects ?? [];\n const sourceRepo = related.find(\n (r) => r.relationType === \"SOURCE_REPO\" || r.relationType === \"ISSUE_TRACKER\",\n );\n return sourceRepo?.projectKey.id ?? null;\n}\n","/**\n * Client for the OSV API (Google Open Source Vulnerabilities).\n *\n * Base URL: https://api.osv.dev/v1/\n * Auth: none\n * Docs: https://google.github.io/osv.dev/api/\n *\n * Ecosystem names use OSV convention (npm, PyPI, Go, Maven, crates.io, NuGet, RubyGems).\n */\n\nimport type { Ecosystem, Severity } from \"../types/index.js\";\n\nconst BASE_URL = \"https://api.osv.dev/v1\";\n\nconst ECOSYSTEM_MAP: Record<Ecosystem, string> = {\n npm: \"npm\",\n pypi: \"PyPI\",\n go: \"Go\",\n maven: \"Maven\",\n cargo: \"crates.io\",\n nuget: \"NuGet\",\n rubygems: \"RubyGems\",\n};\n\nexport interface OsvSeverityEntry {\n type: \"CVSS_V2\" | \"CVSS_V3\" | \"CVSS_V4\";\n score: string; // CVSS vector string e.g. \"CVSS:3.1/AV:N/...\"\n}\n\nexport interface OsvRange {\n type: \"SEMVER\" | \"ECOSYSTEM\" | \"GIT\";\n events: (\n | { introduced: string; fixed?: undefined; last_affected?: undefined }\n | { fixed: string; introduced?: undefined; last_affected?: undefined }\n | { last_affected: string; introduced?: undefined; fixed?: undefined }\n )[];\n}\n\nexport interface OsvAffected {\n package: {\n name: string;\n ecosystem: string;\n purl?: string;\n };\n ranges: OsvRange[];\n versions?: string[];\n database_specific?: Record<string, unknown>;\n}\n\nexport interface OsvDatabaseSpecific {\n severity?: string; // \"LOW\" | \"MODERATE\" | \"HIGH\" | \"CRITICAL\"\n nvd_published_at?: string;\n github_reviewed?: boolean;\n github_reviewed_at?: string;\n cwe_ids?: string[];\n}\n\nexport interface OsvVuln {\n id: string;\n summary: string;\n details?: string;\n aliases?: string[];\n modified: string;\n published: string;\n references?: { type: string; url: string }[];\n affected: OsvAffected[];\n severity?: OsvSeverityEntry[];\n database_specific?: OsvDatabaseSpecific;\n schema_version?: string;\n}\n\nexport interface OsvQueryResponse {\n vulns?: OsvVuln[];\n}\n\nexport interface OsvBatchResponse {\n results: OsvQueryResponse[];\n}\n\nasync function post<TResponse>(path: string, body: unknown): Promise<TResponse> {\n const url = `${BASE_URL}${path}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": `hound-mcp/${__APP_VERSION__}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new OsvError(res.status, url, text);\n }\n\n return res.json() as Promise<TResponse>;\n}\n\nexport class OsvError extends Error {\n constructor(\n public readonly status: number,\n public readonly url: string,\n public readonly body: string,\n ) {\n super(`OSV API error ${status} for ${url}`);\n this.name = \"OsvError\";\n }\n}\n\n/**\n * Query vulnerabilities for a single package@version.\n * Returns an empty array if no vulnerabilities are found.\n */\nexport async function queryVulns(\n ecosystem: Ecosystem,\n name: string,\n version: string,\n): Promise<OsvVuln[]> {\n const response = await post<OsvQueryResponse>(\"/query\", {\n version,\n package: {\n name,\n ecosystem: ECOSYSTEM_MAP[ecosystem],\n },\n });\n return response.vulns ?? [];\n}\n\n/**\n * Query vulnerabilities for multiple packages in a single API call.\n * Returns results in the same order as the input packages array.\n * Packages with no vulnerabilities return an empty array.\n */\nexport async function queryVulnsBatch(\n packages: { ecosystem: Ecosystem; name: string; version: string }[],\n): Promise<OsvVuln[][]> {\n if (packages.length === 0) return [];\n\n const response = await post<OsvBatchResponse>(\"/querybatch\", {\n queries: packages.map((pkg) => ({\n version: pkg.version,\n package: {\n name: pkg.name,\n ecosystem: ECOSYSTEM_MAP[pkg.ecosystem],\n },\n })),\n });\n\n return response.results.map((result) => result.vulns ?? []);\n}\n\n/**\n * Fetch full vulnerability details by OSV/GHSA ID.\n */\nexport async function getVuln(vulnId: string): Promise<OsvVuln> {\n const url = `${BASE_URL}/vulns/${encodeURIComponent(vulnId)}`;\n const res = await fetch(url, {\n headers: { \"User-Agent\": `hound-mcp/${__APP_VERSION__}` },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new OsvError(res.status, url, text);\n }\n\n return res.json() as Promise<OsvVuln>;\n}\n\n/**\n * Extract a human-readable severity level from an OSV vulnerability.\n * Prefers database_specific.severity, falls back to parsing CVSS score.\n */\nexport function extractSeverity(vuln: OsvVuln): Severity {\n // Prefer the GitHub advisory database severity label\n const dbSeverity = vuln.database_specific?.severity?.toUpperCase();\n if (dbSeverity === \"CRITICAL\") return \"CRITICAL\";\n if (dbSeverity === \"HIGH\") return \"HIGH\";\n if (dbSeverity === \"MODERATE\") return \"MODERATE\";\n if (dbSeverity === \"LOW\") return \"LOW\";\n\n // Fall back to CVSS score\n const cvssScore = extractCvssScore(vuln);\n if (cvssScore === null) return \"UNKNOWN\";\n if (cvssScore >= 9.0) return \"CRITICAL\";\n if (cvssScore >= 7.0) return \"HIGH\";\n if (cvssScore >= 4.0) return \"MODERATE\";\n return \"LOW\";\n}\n\n/**\n * Extract a numeric CVSS score from an OSV vulnerability.\n * Prefers CVSS_V3, falls back to V4, then V2.\n * Returns null if no CVSS score is available.\n */\nexport function extractCvssScore(vuln: OsvVuln): number | null {\n const entries = vuln.severity ?? [];\n const preferred = [\"CVSS_V3\", \"CVSS_V4\", \"CVSS_V2\"] as const;\n\n for (const type of preferred) {\n const entry = entries.find((e) => e.type === type);\n if (entry) {\n return parseCvssScore(entry.score);\n }\n }\n return null;\n}\n\n/**\n * Extract fix versions from an OSV affected range.\n * Returns a deduplicated list of versions that fix the vulnerability.\n */\nexport function extractFixVersions(vuln: OsvVuln, ecosystem: Ecosystem): string[] {\n const osvEcosystem = ECOSYSTEM_MAP[ecosystem];\n const fixed = new Set<string>();\n\n for (const affected of vuln.affected) {\n if (affected.package.ecosystem.toLowerCase() !== osvEcosystem.toLowerCase()) {\n continue;\n }\n for (const range of affected.ranges) {\n for (const event of range.events) {\n if (\"fixed\" in event && event.fixed) {\n fixed.add(event.fixed);\n }\n }\n }\n }\n\n return [...fixed];\n}\n\nfunction parseCvssScore(vector: string): number | null {\n // CVSS vectors look like \"CVSS:3.1/AV:N/AC:L/...\" — the base score is not\n // in the vector string itself. We can only get it if the API includes it\n // directly, which OSV doesn't. Return null and let callers use severity label.\n // This function is kept as a hook for future enrichment.\n void vector;\n return null;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_inspect\",\n {\n description:\n \"Get a comprehensive profile of a package version: licenses, vulnerabilities, OpenSSF scorecard, GitHub stats, and dependency count — all in one call.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [versionData, vulns] = await Promise.allSettled([\n getVersion(eco, name, version),\n queryVulns(eco, name, version),\n ]);\n\n if (versionData.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find ${name}@${version} in ${ecosystem}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const pkg = versionData.value;\n const vulnList = vulns.status === \"fulfilled\" ? vulns.value : [];\n\n // Try to fetch project info (scorecard, stars) — non-fatal if missing\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n const lines: string[] = [`📦 ${name}@${version} (${ecosystem})`, \"═\".repeat(50), \"\"];\n\n // Published date\n const published = pkg.publishedAt.slice(0, 10);\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n lines.push(`📅 Published: ${published} (${daysSince} days ago)`);\n\n // License\n const licenses =\n pkg.licenses && pkg.licenses.length > 0 ? pkg.licenses.join(\", \") : \"Unknown\";\n lines.push(`📄 License: ${licenses}`);\n\n // Vulnerabilities\n if (vulnList.length === 0) {\n lines.push(`🛡️ Vulnerabilities: None known`);\n } else {\n const counts: Record<string, number> = {};\n for (const v of vulnList) {\n const sev = extractSeverity(v);\n counts[sev] = (counts[sev] ?? 0) + 1;\n }\n const summary = Object.entries(counts)\n .map(([s, n]) => `${n} ${s.toLowerCase()}`)\n .join(\", \");\n lines.push(`⚠️ Vulnerabilities: ${vulnList.length} (${summary})`);\n }\n\n // Known advisories from deps.dev\n const advisoryCount = pkg.advisoryKeys?.length ?? 0;\n if (advisoryCount > 0) {\n const ids = pkg.advisoryKeys?.map((a) => a.id).join(\", \");\n lines.push(`🔔 Advisories: ${ids}`);\n }\n\n // GitHub / project info\n if (projectData !== null) {\n lines.push(\"\");\n lines.push(\"📊 Project Health\");\n lines.push(\"─\".repeat(30));\n lines.push(`⭐ Stars: ${projectData.starsCount.toLocaleString()}`);\n lines.push(`🍴 Forks: ${projectData.forksCount.toLocaleString()}`);\n lines.push(`🐛 Open issues: ${projectData.openIssuesCount.toLocaleString()}`);\n\n if (projectData.scorecard !== null) {\n const score = projectData.scorecard.overallScore.toFixed(1);\n const grade = scorecardGrade(projectData.scorecard.overallScore);\n lines.push(`🏆 OpenSSF Scorecard: ${score}/10 (${grade})`);\n\n const weak = [...projectData.scorecard.checks]\n .sort((a, b) => a.score - b.score)\n .slice(0, 3);\n if (weak.length > 0) {\n lines.push(\n ` Lowest checks: ${weak.map((c) => `${c.name} (${c.score}/10)`).join(\", \")}`,\n );\n }\n }\n }\n\n // Links\n const homepage = pkg.links?.find((l) => l.label === \"HOMEPAGE\");\n const sourceRepo = pkg.links?.find((l) => l.label === \"SOURCE_REPO\");\n if (homepage ?? sourceRepo) {\n lines.push(\"\");\n if (homepage) lines.push(`🌐 Homepage: ${homepage.url}`);\n if (sourceRepo) lines.push(`💻 Source: ${sourceRepo.url}`);\n }\n\n lines.push(\"\");\n lines.push(\n `🔗 deps.dev: https://deps.dev/${ecosystem}/packages/${encodeURIComponent(name)}/versions/${encodeURIComponent(version)}`,\n );\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n\nfunction scorecardGrade(score: number): string {\n if (score >= 9) return \"A\";\n if (score >= 7) return \"B\";\n if (score >= 5) return \"C\";\n if (score >= 3) return \"D\";\n return \"F\";\n}\n","export const ECOSYSTEM_VALUES = [\"npm\", \"pypi\", \"go\", \"maven\", \"cargo\", \"nuget\", \"rubygems\"] as const;\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport { queryVulnsBatch } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\nimport { getDefaultVersion } from \"../utils/getDefaultVersion.js\";\n\n/**\n * Curated list of widely-used packages per ecosystem.\n * Used as defaults when the user doesn't specify a list.\n */\nconst POPULAR_DEFAULTS: Record<string, string[]> = {\n npm: [\n \"express\",\n \"lodash\",\n \"axios\",\n \"react\",\n \"typescript\",\n \"webpack\",\n \"eslint\",\n \"jest\",\n \"next\",\n \"vue\",\n ],\n pypi: [\n \"requests\",\n \"numpy\",\n \"pandas\",\n \"flask\",\n \"django\",\n \"fastapi\",\n \"sqlalchemy\",\n \"pytest\",\n \"boto3\",\n \"pydantic\",\n ],\n go: [\n \"github.com/gin-gonic/gin\",\n \"github.com/gorilla/mux\",\n \"github.com/stretchr/testify\",\n \"github.com/spf13/cobra\",\n \"go.uber.org/zap\",\n ],\n maven: [\n \"com.google.guava:guava\",\n \"org.springframework:spring-core\",\n \"org.apache.commons:commons-lang3\",\n \"com.fasterxml.jackson.core:jackson-databind\",\n \"org.slf4j:slf4j-api\",\n ],\n cargo: [\"serde\", \"tokio\", \"reqwest\", \"clap\", \"anyhow\", \"log\", \"rand\", \"regex\"],\n nuget: [\n \"Newtonsoft.Json\",\n \"Microsoft.Extensions.Logging\",\n \"Serilog\",\n \"AutoMapper\",\n \"FluentValidation\",\n ],\n rubygems: [\"rails\", \"devise\", \"rspec-core\", \"activerecord\", \"sidekiq\"],\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_popular\",\n {\n description:\n \"Scan a list of popular (or user-specified) packages for known vulnerabilities. Quickly surface which widely-used packages in an ecosystem have open security issues.\",\n inputSchema: {\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n packages: z\n .array(z.string())\n .optional()\n .describe(\n \"Specific package names to check. If omitted, uses a curated list of popular packages for the ecosystem.\",\n ),\n },\n },\n async ({ ecosystem, packages }) => {\n const eco = ecosystem as Ecosystem;\n const names = packages ?? POPULAR_DEFAULTS[ecosystem] ?? [];\n\n if (names.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No packages specified and no defaults available for ${ecosystem}.`,\n },\n ],\n };\n }\n\n const packageResults = await Promise.allSettled(\n names.map(async (name) => {\n const pkg = await getPackage(eco, name);\n const defaultVersion = getDefaultVersion(pkg.versions);\n return {\n name,\n version: defaultVersion?.versionKey.version ?? \"unknown\",\n };\n }),\n );\n\n const resolved = packageResults\n .map((r, i) => ({\n name: names[i] ?? \"\",\n version: r.status === \"fulfilled\" ? r.value.version : null,\n }))\n .filter((p): p is { name: string; version: string } => p.version !== null);\n\n const failed = packageResults.filter((r) => r.status === \"rejected\").length;\n\n const vulnResults = await queryVulnsBatch(\n resolved.map((p) => ({ ecosystem: eco, name: p.name, version: p.version })),\n );\n\n const lines: string[] = [\n `🔍 Vulnerability scan: ${ecosystem} popular packages`,\n \"═\".repeat(50),\n `Checked ${resolved.length} packages`,\n \"\",\n ];\n\n // Sort: vulnerable first, then clean\n const withVulns = resolved\n .map((pkg, i) => ({ ...pkg, vulns: vulnResults[i] ?? [] }))\n .sort((a, b) => b.vulns.length - a.vulns.length);\n\n const vulnerableCount = withVulns.filter((p) => p.vulns.length > 0).length;\n\n if (vulnerableCount === 0) {\n lines.push(`✅ All ${resolved.length} packages are clean — no known vulnerabilities.`);\n lines.push(\"\");\n } else {\n lines.push(`⚠️ ${vulnerableCount} of ${resolved.length} packages have vulnerabilities:`);\n lines.push(\"\");\n }\n\n for (const pkg of withVulns) {\n if (pkg.vulns.length === 0) {\n lines.push(` ✅ ${pkg.name}@${pkg.version}`);\n } else {\n lines.push(` ⚠️ ${pkg.name}@${pkg.version} — ${pkg.vulns.length} vuln(s)`);\n // Show vuln IDs (up to 3)\n for (const v of pkg.vulns.slice(0, 3)) {\n lines.push(` ${v.id}: ${v.summary}`);\n }\n if (pkg.vulns.length > 3) {\n lines.push(` ... and ${pkg.vulns.length - 3} more`);\n }\n }\n }\n\n if (failed > 0) {\n lines.push(\"\");\n lines.push(`ℹ️ ${failed} package(s) could not be resolved in ${ecosystem}.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { DepsDevVersionKey } from \"../api/depsdev.js\";\n\ninterface VersionEntry {\n versionKey: DepsDevVersionKey;\n isDefault: boolean;\n}\n\n/**\n * Pick the default version from a deps.dev versions array.\n * Prefers the entry with `isDefault: true`, falls back to the last entry.\n * Returns undefined if the array is empty.\n */\nexport function getDefaultVersion<T extends VersionEntry>(versions: T[]): T | undefined {\n return versions.find((v) => v.isDefault) ?? versions.at(-1);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getDependencies } from \"../api/depsdev.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_tree\",\n {\n description:\n \"Show the full resolved dependency tree for a package version, including all transitive dependencies with their depth and relation type.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n maxDepth: z\n .number()\n .int()\n .min(1)\n .max(10)\n .default(3)\n .describe(\"Maximum depth to display (default: 3, max: 10)\"),\n },\n },\n async ({ name, version, ecosystem, maxDepth }) => {\n let deps: Awaited<ReturnType<typeof getDependencies>>;\n try {\n deps = await getDependencies(ecosystem as Ecosystem, name, version);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not fetch dependency tree for ${name}@${version}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const nodes = deps.nodes;\n const edges = deps.edges;\n\n const directCount = nodes.filter((n) => n.relation === \"DIRECT\").length;\n const indirectCount = nodes.filter((n) => n.relation === \"INDIRECT\").length;\n const totalCount = directCount + indirectCount;\n\n // Build adjacency: nodeIndex → children nodeIndexes\n const children = new Map<number, number[]>();\n for (const edge of edges) {\n if (!children.has(edge.fromNode)) children.set(edge.fromNode, []);\n children.get(edge.fromNode)?.push(edge.toNode);\n }\n\n const lines: string[] = [\n `🌳 Dependency tree for ${name}@${version} (${ecosystem})`,\n \"═\".repeat(50),\n `${totalCount} total dependencies (${directCount} direct, ${indirectCount} transitive)`,\n \"\",\n ];\n\n // Render tree recursively from node 0 (SELF)\n const rootNode = nodes[0];\n if (rootNode) {\n renderNode(lines, nodes, children, 0, 0, maxDepth, new Set());\n }\n\n if (maxDepth < 10 && indirectCount > 0) {\n lines.push(\"\");\n lines.push(`ℹ️ Showing up to depth ${maxDepth}. Use maxDepth to see deeper.`);\n }\n\n lines.push(\"\");\n lines.push(`Source: deps.dev`);\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n\nfunction renderNode(\n lines: string[],\n nodes: { versionKey: { name: string; version: string }; relation: string; errors: string[] }[],\n children: Map<number, number[]>,\n nodeIndex: number,\n depth: number,\n maxDepth: number,\n visited: Set<number>,\n): void {\n if (visited.has(nodeIndex)) return;\n visited.add(nodeIndex);\n\n const node = nodes[nodeIndex];\n if (!node) return;\n\n const indent = \" \".repeat(depth);\n const isRoot = depth === 0;\n const prefix = isRoot ? \"\" : \"├── \";\n const errorSuffix = node.errors.length > 0 ? \" ⚠️\" : \"\";\n lines.push(`${indent}${prefix}${node.versionKey.name}@${node.versionKey.version}${errorSuffix}`);\n\n if (depth >= maxDepth) {\n const childCount = children.get(nodeIndex)?.length ?? 0;\n if (childCount > 0) {\n lines.push(`${indent} └── ... (${childCount} more)`);\n }\n return;\n }\n\n for (const childIdx of children.get(nodeIndex) ?? []) {\n renderNode(lines, nodes, children, childIdx, depth + 1, maxDepth, visited);\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\n/**\n * Generate likely typosquatting variants of a package name.\n * Covers the most common attack patterns:\n * - character omission (lodsh)\n * - character transposition (lodasg)\n * - character substitution (1odash, l0dash)\n * - hyphen/underscore confusion (lo_dash, lo-dash)\n * - common prefix/suffix additions (node-lodash, lodash-js)\n */\nfunction generateTypos(name: string): string[] {\n const variants = new Set<string>();\n\n // Omit each character\n for (let i = 0; i < name.length; i++) {\n variants.add(name.slice(0, i) + name.slice(i + 1));\n }\n\n // Transpose adjacent characters\n for (let i = 0; i < name.length - 1; i++) {\n const a = name.charAt(i);\n const b = name.charAt(i + 1);\n variants.add(name.slice(0, i) + b + a + name.slice(i + 2));\n }\n\n // Hyphen/underscore confusion\n if (name.includes(\"-\")) {\n variants.add(name.replaceAll(\"-\", \"_\"));\n variants.add(name.replaceAll(\"-\", \"\"));\n }\n if (name.includes(\"_\")) {\n variants.add(name.replaceAll(\"_\", \"-\"));\n variants.add(name.replaceAll(\"_\", \"\"));\n }\n\n // Common prefix/suffix additions\n variants.add(`node-${name}`);\n variants.add(`${name}-js`);\n variants.add(`${name}js`);\n variants.add(`${name}-node`);\n\n // Remove the original name\n variants.delete(name);\n\n return [...variants];\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_typosquat\",\n {\n description:\n \"Check if a package name looks like a typosquat of a popular package. Generates likely typo variants and checks which ones exist in the registry.\",\n inputSchema: {\n name: z.string().describe(\"Package name to check\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n const variants = generateTypos(name);\n\n // Check which variants actually exist in the registry (in parallel, ignore errors)\n const results = await Promise.allSettled(\n variants.map(async (variant) => {\n const pkg = await getPackage(eco, variant);\n return { name: variant, versionCount: pkg.versions.length };\n }),\n );\n\n const existing = results\n .filter((r) => r.status === \"fulfilled\")\n .map((r) => (r as PromiseFulfilledResult<{ name: string; versionCount: number }>).value)\n .sort((a, b) => b.versionCount - a.versionCount);\n\n // Also fetch the target package itself to confirm it exists\n const targetExists = await getPackage(eco, name)\n .then((p) => p.versions.length)\n .catch(() => null);\n\n const lines: string[] = [`🔍 Typosquat check: ${name} (${ecosystem})`, \"═\".repeat(50), \"\"];\n\n if (targetExists === null) {\n lines.push(`⚠️ \"${name}\" does not exist in ${ecosystem}.`);\n lines.push(`This package name itself may be available — or it could be a typo.`);\n } else {\n lines.push(`✅ \"${name}\" exists (${targetExists} published versions)`);\n }\n\n lines.push(\"\");\n\n if (existing.length === 0) {\n lines.push(`✅ No typosquat variants found in ${ecosystem}.`);\n lines.push(`None of the ${variants.length} generated variants exist.`);\n } else {\n lines.push(`⚠️ Found ${existing.length} similar package(s) that exist in ${ecosystem}:`);\n lines.push(\"\");\n for (const pkg of existing) {\n lines.push(` 📦 ${pkg.name} (${pkg.versionCount} versions)`);\n }\n lines.push(\"\");\n lines.push(`If you meant to install \"${name}\", double-check you typed it correctly.`);\n lines.push(`If you are the author of \"${name}\", consider reserving these names.`);\n }\n\n lines.push(\"\");\n lines.push(\n `ℹ️ Checked ${variants.length} typo variants (omission, transposition, hyphen, affixes)`,\n );\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { parseLockfile } from \"../parsers/index.js\";\nimport { extractSeverity, queryVulnsBatch } from \"../api/osv.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst MAX_BATCH = 100; // cap to avoid huge requests\n\nconst SEVERITY_ORDER = [\"CRITICAL\", \"HIGH\", \"MODERATE\", \"LOW\", \"UNKNOWN\"] as const;\n\nconst SEVERITY_ICON: Record<string, string> = {\n CRITICAL: \"🔴\",\n HIGH: \"🟠\",\n MODERATE: \"🟡\",\n LOW: \"🔵\",\n UNKNOWN: \"⚪\",\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_audit\",\n {\n description:\n \"Scan a project's lockfile for dependency risks. Parses package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, or go.sum and batch-queries OSV for vulnerabilities across all dependencies.\",\n inputSchema: {\n lockfile_content: z.string().describe(\"Full text content of the lockfile\"),\n lockfile_name: z\n .string()\n .describe(\n \"Filename to determine format: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum\",\n ),\n },\n },\n async ({ lockfile_content, lockfile_name }) => {\n const deps = parseLockfile(lockfile_name, lockfile_content);\n\n if (deps === null) {\n return {\n content: [\n {\n type: \"text\",\n text: `Unsupported lockfile format: ${lockfile_name}\\n\\nSupported formats: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum`,\n },\n ],\n };\n }\n\n if (deps.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No dependencies found in ${lockfile_name}. The file may be empty or malformed.`,\n },\n ],\n };\n }\n\n // Deduplicate by name@version\n const seen = new Set<string>();\n const unique = deps.filter((d) => {\n const key = `${d.name}@${d.version}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n const toCheck = unique.slice(0, MAX_BATCH);\n const truncated = unique.length > MAX_BATCH;\n\n // Batch query OSV\n const vulnResults = await queryVulnsBatch(\n toCheck.map((d) => ({ ecosystem: d.ecosystem as Ecosystem, name: d.name, version: d.version })),\n );\n\n // Build vulnerability findings\n interface Finding {\n name: string;\n version: string;\n severity: string;\n id: string;\n summary: string;\n }\n\n const findings: Finding[] = [];\n const vulnCounts: Partial<Record<string, number>> = {};\n\n for (let i = 0; i < toCheck.length; i++) {\n const dep = toCheck[i];\n const vulns = vulnResults[i] ?? [];\n if (!dep) continue;\n for (const v of vulns) {\n const sev = extractSeverity(v);\n vulnCounts[sev] = (vulnCounts[sev] ?? 0) + 1;\n findings.push({\n name: dep.name,\n version: dep.version,\n severity: sev,\n id: v.id,\n summary: v.summary,\n });\n }\n }\n\n const totalVulns = findings.length;\n const affectedPkgs = new Set(findings.map((f) => `${f.name}@${f.version}`)).size;\n\n // --- Report ---\n const lines: string[] = [\n \"📊 Hound Audit Report\",\n \"═\".repeat(50),\n `Lockfile: ${lockfile_name}`,\n `Scanned: ${toCheck.length} dependencies${truncated ? ` (capped at ${MAX_BATCH} of ${unique.length})` : \"\"}`,\n \"\",\n ];\n\n // Summary counts\n if (totalVulns === 0) {\n lines.push(\"✅ No known vulnerabilities found!\");\n } else {\n lines.push(`Found ${totalVulns} vulnerabilit${totalVulns === 1 ? \"y\" : \"ies\"} across ${affectedPkgs} package${affectedPkgs === 1 ? \"\" : \"s\"}:`);\n for (const sev of SEVERITY_ORDER) {\n const count = vulnCounts[sev] ?? 0;\n if (count > 0) {\n const icon = SEVERITY_ICON[sev] ?? \"⚪\";\n lines.push(` ${icon} ${count} ${sev.toLowerCase()}`);\n }\n }\n }\n\n lines.push(\"\");\n\n // Detailed findings grouped by severity\n if (findings.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"Vulnerable Packages\");\n lines.push(\"─\".repeat(50));\n\n for (const sev of SEVERITY_ORDER) {\n const group = findings.filter((f) => f.severity === sev);\n if (group.length === 0) continue;\n\n const icon = SEVERITY_ICON[sev] ?? \"⚪\";\n lines.push(`\\n${icon} ${sev} (${group.length})`);\n\n // Group by package\n const byPkg: Record<string, Finding[]> = {};\n for (const f of group) {\n const key = `${f.name}@${f.version}`;\n (byPkg[key] ??= []).push(f);\n }\n\n for (const [pkg, pkgFindings] of Object.entries(byPkg)) {\n lines.push(` ${pkg}`);\n for (const f of pkgFindings) {\n lines.push(` ${f.id}: ${f.summary}`);\n }\n }\n }\n\n lines.push(\"\");\n lines.push(\"─\".repeat(50));\n lines.push(\"💡 Run hound_upgrade <package> to find a safe version for each.\");\n lines.push(\"💡 Run hound_vulns <package> <version> for full advisory details.\");\n }\n\n if (truncated) {\n lines.push(\"\");\n lines.push(`⚠️ Only the first ${MAX_BATCH} of ${unique.length} dependencies were checked.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","export interface ParsedDep {\n name: string;\n version: string;\n ecosystem: \"npm\" | \"pypi\" | \"cargo\" | \"go\";\n}\n\n/**\n * Detect lockfile type from filename and parse dependencies.\n * Returns null if the format is unrecognised.\n */\nexport function parseLockfile(filename: string, content: string): ParsedDep[] | null {\n const base = filename.split(\"/\").pop() ?? filename;\n\n if (base === \"package-lock.json\") return parsePackageLock(content);\n if (base === \"yarn.lock\") return parseYarnLock(content);\n if (base === \"pnpm-lock.yaml\") return parsePnpmLock(content);\n if (base === \"requirements.txt\") return parseRequirements(content);\n if (base === \"Cargo.lock\") return parseCargoLock(content);\n if (base === \"go.sum\") return parseGoSum(content);\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// package-lock.json (npm v2/v3 — \"packages\" field)\n// ---------------------------------------------------------------------------\nfunction parsePackageLock(content: string): ParsedDep[] {\n let json: Record<string, unknown>;\n try {\n json = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return [];\n }\n\n const deps: ParsedDep[] = [];\n\n // v2/v3 format: \"packages\" object with keys like \"node_modules/express\"\n const packages = json.packages as Record<string, { version?: string; dev?: boolean }> | undefined;\n if (packages) {\n for (const [key, val] of Object.entries(packages)) {\n if (!key || key === \"\") continue; // skip root entry\n if (!val.version) continue;\n // Extract package name from path like \"node_modules/foo\" or \"node_modules/@scope/foo\"\n const name = key.replace(/^.*node_modules\\//, \"\");\n if (name) deps.push({ name, version: val.version, ecosystem: \"npm\" });\n }\n return deps;\n }\n\n // v1 format: \"dependencies\" object (legacy)\n const dependencies = json.dependencies as\n | Record<string, { version?: string; requires?: unknown; dependencies?: unknown }>\n | undefined;\n if (dependencies) {\n collectNpmV1(dependencies, deps);\n }\n\n return deps;\n}\n\nfunction collectNpmV1(\n deps: Record<string, { version?: string; dependencies?: unknown }>,\n out: ParsedDep[],\n): void {\n for (const [name, val] of Object.entries(deps)) {\n if (val.version) out.push({ name, version: val.version, ecosystem: \"npm\" });\n if (val.dependencies) {\n collectNpmV1(\n val.dependencies as Record<string, { version?: string; dependencies?: unknown }>,\n out,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// yarn.lock (classic v1 format)\n// ---------------------------------------------------------------------------\nfunction parseYarnLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n const lines = content.split(\"\\n\");\n let currentName: string | null = null;\n\n for (const line of lines) {\n // Entry header: \"package-name@range, package-name@range2:\"\n if (!line.startsWith(\" \") && !line.startsWith(\"#\") && line.includes(\"@\") && line.endsWith(\":\")) {\n // Extract package name from first specifier before the @version part\n const first = line.split(\",\")[0]?.trim().replace(/:$/, \"\") ?? \"\";\n // Handle scoped packages: @scope/name@range\n if (first.startsWith(\"@\")) {\n const atIdx = first.indexOf(\"@\", 1);\n currentName = atIdx > 0 ? first.slice(0, atIdx) : null;\n } else {\n const atIdx = first.indexOf(\"@\");\n currentName = atIdx > 0 ? first.slice(0, atIdx) : null;\n }\n } else if (currentName) {\n const match = /^\\s+version\\s+\"(.+)\"/.exec(line);\n if (match?.[1]) {\n deps.push({ name: currentName, version: match[1], ecosystem: \"npm\" });\n currentName = null;\n }\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// pnpm-lock.yaml (v6/v9)\n// ---------------------------------------------------------------------------\nfunction parsePnpmLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n const lines = content.split(\"\\n\");\n\n // v9 format: packages section has lines like:\n // express@4.18.2:\n // v6 format: /express/4.18.2:\n for (const line of lines) {\n // v9: \" name@version:\" at top level under \"packages:\"\n const v9Match = /^ {2}((?:@[^@/]+\\/)?[^@/][^@]*)@([^:(@]+):/.exec(line);\n if (v9Match?.[1] && v9Match[2]) {\n deps.push({ name: v9Match[1], version: v9Match[2], ecosystem: \"npm\" });\n continue;\n }\n // v6: \" /name/version:\" or \" /@scope/name/version:\"\n const v6Match = /^ {2}\\/((?:@[^/]+\\/)?[^/]+)\\/([^/:(@]+):/.exec(line);\n if (v6Match?.[1] && v6Match[2]) {\n deps.push({ name: v6Match[1], version: v6Match[2], ecosystem: \"npm\" });\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// requirements.txt (pip)\n// ---------------------------------------------------------------------------\nfunction parseRequirements(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.split(\"#\")[0]?.trim() ?? \"\";\n if (!line || line.startsWith(\"-\")) continue;\n\n // name==version or name===version\n const eqMatch = /^([A-Za-z0-9_.-]+)==?=?([^\\s;]+)/.exec(line);\n if (eqMatch?.[1] && eqMatch[2]) {\n deps.push({ name: eqMatch[1].toLowerCase(), version: eqMatch[2], ecosystem: \"pypi\" });\n }\n }\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// Cargo.lock (TOML-like)\n// ---------------------------------------------------------------------------\nfunction parseCargoLock(content: string): ParsedDep[] {\n const deps: ParsedDep[] = [];\n let name: string | null = null;\n let version: string | null = null;\n let inPackage = false;\n\n for (const raw of content.split(\"\\n\")) {\n const line = raw.trim();\n if (line === \"[[package]]\") {\n if (name && version) deps.push({ name, version, ecosystem: \"cargo\" });\n name = null;\n version = null;\n inPackage = true;\n } else if (inPackage) {\n const nameMatch = /^name\\s*=\\s*\"([^\"]+)\"/.exec(line);\n if (nameMatch?.[1]) name = nameMatch[1];\n const verMatch = /^version\\s*=\\s*\"([^\"]+)\"/.exec(line);\n if (verMatch?.[1]) version = verMatch[1];\n }\n }\n if (name && version) deps.push({ name, version, ecosystem: \"cargo\" });\n\n return deps;\n}\n\n// ---------------------------------------------------------------------------\n// go.sum\n// ---------------------------------------------------------------------------\nfunction parseGoSum(content: string): ParsedDep[] {\n const seen = new Set<string>();\n const deps: ParsedDep[] = [];\n\n for (const line of content.split(\"\\n\")) {\n // format: module/path v1.2.3 h1:hash=\n // or: module/path v1.2.3/go.mod h1:hash=\n const match = /^(\\S+)\\s+v([^\\s/]+)/.exec(line);\n if (match?.[1] && match[2]) {\n const key = `${match[1]}@${match[2]}`;\n if (!seen.has(key)) {\n seen.add(key);\n deps.push({ name: match[1], version: match[2], ecosystem: \"go\" });\n }\n }\n }\n\n return deps;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getPackage, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport { COPYLEFT_LICENSES } from \"../constants/licenses.js\";\nimport type { Ecosystem } from \"../types/index.js\";\nimport { getDefaultVersion } from \"../utils/getDefaultVersion.js\";\n\ninterface PackageData {\n name: string;\n version: string;\n vulnCounts: Record<string, number>;\n totalVulns: number;\n scorecardScore: number | null;\n stars: number | null;\n daysSince: number;\n licenses: string[];\n projectExists: boolean;\n}\n\nasync function gatherPackageData(eco: Ecosystem, name: string): Promise<PackageData | null> {\n // Get package to find default version\n let defaultVersion: string;\n try {\n const pkg = await getPackage(eco, name);\n const defaultV = getDefaultVersion(pkg.versions);\n if (!defaultV) return null;\n defaultVersion = defaultV.versionKey.version;\n } catch {\n return null;\n }\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, defaultVersion),\n queryVulns(eco, name, defaultVersion),\n ]);\n\n if (versionResult.status === \"rejected\") return null;\n\n const version = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const vulnCounts: Record<string, number> = {};\n for (const v of vulns) {\n const sev = extractSeverity(v);\n vulnCounts[sev] = (vulnCounts[sev] ?? 0) + 1;\n }\n\n const projectId = extractProjectId(version);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n const daysSince = Math.floor(\n (Date.now() - new Date(version.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n\n return {\n name,\n version: defaultVersion,\n vulnCounts,\n totalVulns: vulns.length,\n scorecardScore: projectData?.scorecard?.overallScore ?? null,\n stars: projectData?.starsCount ?? null,\n projectExists: projectData !== null,\n daysSince,\n licenses: version.licenses ?? [],\n };\n}\n\nfunction licenseRisk(licenses: string[]): string {\n if (licenses.length === 0) return \"Unknown\";\n if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) return \"Copyleft\";\n return \"Permissive\";\n}\n\nfunction pad(s: string, n: number): string {\n return s.length >= n ? s : s + \" \".repeat(n - s.length);\n}\n\nfunction winner(a: number, b: number, higherIsBetter = true): [string, string] {\n if (a === b) return [\"\", \"\"];\n const aWins = higherIsBetter ? a > b : a < b;\n return aWins ? [\"✓\", \"\"] : [\"\", \"✓\"];\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_compare\",\n {\n description:\n \"Side-by-side comparison of two packages: vulnerabilities, OpenSSF Scorecard, GitHub stars, release recency, and license. Returns a recommendation.\",\n inputSchema: {\n package_a: z.string().describe(\"First package name\"),\n package_b: z.string().describe(\"Second package name\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ package_a, package_b, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [dataA, dataB] = await Promise.all([\n gatherPackageData(eco, package_a),\n gatherPackageData(eco, package_b),\n ]);\n\n if (!dataA && !dataB) {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find either ${package_a} or ${package_b} in ${ecosystem}.`,\n },\n ],\n };\n }\n if (!dataA) {\n return {\n content: [\n { type: \"text\", text: `Could not find ${package_a} in ${ecosystem}.` },\n ],\n };\n }\n if (!dataB) {\n return {\n content: [\n { type: \"text\", text: `Could not find ${package_b} in ${ecosystem}.` },\n ],\n };\n }\n\n const COL = 22;\n const header = (label: string) =>\n `${pad(label, 24)}${pad(dataA.name, COL)}${pad(dataB.name, COL)}`;\n\n const row = (label: string, valA: string, valB: string, wA = \"\", wB = \"\") =>\n ` ${pad(label, 22)}${pad(wA ? `${valA} ${wA}` : valA, COL)}${wB ? `${valB} ${wB}` : valB}`;\n\n const lines: string[] = [\n `⚖️ Package Comparison (${ecosystem})`,\n \"═\".repeat(70),\n header(\"\"),\n header(\"Metric\"),\n \"─\".repeat(70),\n ];\n\n // Version\n lines.push(row(\"Latest version\", dataA.version, dataB.version));\n\n // Vulnerabilities\n const vulnA = dataA.totalVulns === 0 ? \"None\" : `${dataA.totalVulns} vuln(s)`;\n const vulnB = dataB.totalVulns === 0 ? \"None\" : `${dataB.totalVulns} vuln(s)`;\n const [wVA, wVB] = winner(dataA.totalVulns, dataB.totalVulns, false);\n lines.push(row(\"Vulnerabilities\", vulnA, vulnB, wVA, wVB));\n\n // Critical/High breakdown if any vulns\n if (dataA.totalVulns > 0 || dataB.totalVulns > 0) {\n const critA = (dataA.vulnCounts.CRITICAL ?? 0) + (dataA.vulnCounts.HIGH ?? 0);\n const critB = (dataB.vulnCounts.CRITICAL ?? 0) + (dataB.vulnCounts.HIGH ?? 0);\n lines.push(row(\" Critical/High\", String(critA), String(critB)));\n }\n\n // Scorecard\n const scA = dataA.scorecardScore !== null ? dataA.scorecardScore.toFixed(1) : \"N/A\";\n const scB = dataB.scorecardScore !== null ? dataB.scorecardScore.toFixed(1) : \"N/A\";\n const [wSA, wSB] =\n dataA.scorecardScore !== null && dataB.scorecardScore !== null\n ? winner(dataA.scorecardScore, dataB.scorecardScore)\n : [\"\", \"\"];\n lines.push(row(\"OpenSSF Scorecard\", scA, scB, wSA, wSB));\n\n // Stars\n const stA = dataA.stars !== null ? dataA.stars.toLocaleString() : \"N/A\";\n const stB = dataB.stars !== null ? dataB.stars.toLocaleString() : \"N/A\";\n const [wStA, wStB] =\n dataA.stars !== null && dataB.stars !== null\n ? winner(dataA.stars, dataB.stars)\n : [\"\", \"\"];\n lines.push(row(\"GitHub stars\", stA, stB, wStA, wStB));\n\n // Recency\n const recA = `${dataA.daysSince}d ago`;\n const recB = `${dataB.daysSince}d ago`;\n const [wRA, wRB] = winner(dataA.daysSince, dataB.daysSince, false);\n lines.push(row(\"Last release\", recA, recB, wRA, wRB));\n\n // License\n const licA = dataA.licenses.length > 0 ? dataA.licenses.join(\", \") : \"Unknown\";\n const licB = dataB.licenses.length > 0 ? dataB.licenses.join(\", \") : \"Unknown\";\n lines.push(row(\"License\", licA, licB));\n lines.push(row(\"License risk\", licenseRisk(dataA.licenses), licenseRisk(dataB.licenses)));\n\n // Recommendation\n lines.push(\"\");\n lines.push(\"─\".repeat(70));\n lines.push(\"Recommendation\");\n lines.push(\"─\".repeat(30));\n\n let scoreA = 0;\n let scoreB = 0;\n\n // Fewer vulns is better\n if (dataA.totalVulns < dataB.totalVulns) scoreA += 2;\n else if (dataB.totalVulns < dataA.totalVulns) scoreB += 2;\n\n // Higher scorecard is better\n if (dataA.scorecardScore !== null && dataB.scorecardScore !== null) {\n if (dataA.scorecardScore > dataB.scorecardScore) scoreA++;\n else if (dataB.scorecardScore > dataA.scorecardScore) scoreB++;\n }\n\n // More stars is better\n if (dataA.stars !== null && dataB.stars !== null) {\n if (dataA.stars > dataB.stars) scoreA++;\n else if (dataB.stars > dataA.stars) scoreB++;\n }\n\n // More recent is better\n if (dataA.daysSince < dataB.daysSince) scoreA++;\n else if (dataB.daysSince < dataA.daysSince) scoreB++;\n\n // Permissive license is better\n const lrA = licenseRisk(dataA.licenses);\n const lrB = licenseRisk(dataB.licenses);\n if (lrA === \"Permissive\" && lrB !== \"Permissive\") scoreA++;\n else if (lrB === \"Permissive\" && lrA !== \"Permissive\") scoreB++;\n\n if (scoreA > scoreB) {\n lines.push(`✅ Prefer ${dataA.name} — leads on ${scoreA} of 6 criteria`);\n } else if (scoreB > scoreA) {\n lines.push(`✅ Prefer ${dataB.name} — leads on ${scoreB} of 6 criteria`);\n } else {\n lines.push(`🤝 Both packages are roughly equivalent (${scoreA}/${scoreB} criteria)`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","export const COPYLEFT_LICENSES = new Set([\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\",\n \"EUPL-1.1\", \"EUPL-1.2\", \"MPL-2.0\", \"OSL-3.0\", \"CDDL-1.0\", \"EPL-1.0\", \"EPL-2.0\",\n]);\n\nexport const NETWORK_COPYLEFT = new Set([\n \"AGPL-3.0\", \"AGPL-3.0-only\", \"AGPL-3.0-or-later\",\n \"EUPL-1.1\", \"EUPL-1.2\",\n]);\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getVersion } from \"../api/depsdev.js\";\nimport { COPYLEFT_LICENSES, NETWORK_COPYLEFT } from \"../constants/licenses.js\";\nimport { parseLockfile } from \"../parsers/index.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\n// Licenses allowed under each policy\nconst POLICY_ALLOWLISTS: Record<\"permissive\" | \"copyleft\", Set<string>> = {\n permissive: new Set([\n \"MIT\", \"ISC\", \"BSD-2-Clause\", \"BSD-3-Clause\", \"Apache-2.0\", \"0BSD\",\n \"Unlicense\", \"CC0-1.0\", \"BlueOak-1.0.0\", \"Python-2.0\",\n ]),\n copyleft: new Set([\n \"MIT\", \"ISC\", \"BSD-2-Clause\", \"BSD-3-Clause\", \"Apache-2.0\", \"0BSD\",\n \"Unlicense\", \"CC0-1.0\", \"BlueOak-1.0.0\", \"Python-2.0\",\n \"LGPL-2.0\", \"LGPL-2.1\", \"LGPL-3.0\", \"MPL-2.0\", \"EPL-1.0\", \"EPL-2.0\",\n \"GPL-2.0\", \"GPL-2.0-only\", \"GPL-2.0-or-later\",\n \"GPL-3.0\", \"GPL-3.0-only\", \"GPL-3.0-or-later\",\n \"CDDL-1.0\", \"OSL-3.0\",\n ]),\n};\n\nfunction classifyLicense(license: string): \"permissive\" | \"weak-copyleft\" | \"copyleft\" | \"network-copyleft\" | \"unknown\" {\n if (NETWORK_COPYLEFT.has(license)) return \"network-copyleft\";\n if (COPYLEFT_LICENSES.has(license)) {\n if (license.startsWith(\"LGPL\") || license === \"MPL-2.0\" || license === \"EPL-1.0\" || license === \"EPL-2.0\" || license === \"CDDL-1.0\") {\n return \"weak-copyleft\";\n }\n return \"copyleft\";\n }\n if (POLICY_ALLOWLISTS.permissive.has(license)) return \"permissive\";\n return \"unknown\";\n}\n\nconst MAX_FETCH = 50;\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_license_check\",\n {\n description:\n \"Scan a lockfile for license compliance. Resolves licenses for every dependency and flags packages that violate the chosen policy (permissive, copyleft, or none).\",\n inputSchema: {\n lockfile_content: z.string().describe(\"Full text content of the lockfile\"),\n lockfile_name: z\n .string()\n .describe(\"Filename: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum\"),\n policy: z\n .enum([\"permissive\", \"copyleft\", \"none\"])\n .default(\"permissive\")\n .describe(\n \"License policy to enforce: 'permissive' (MIT/Apache/BSD only), 'copyleft' (allows GPL but not AGPL), 'none' (report only, no violations)\",\n ),\n },\n },\n async ({ lockfile_content, lockfile_name, policy }) => {\n const deps = parseLockfile(lockfile_name, lockfile_content);\n\n if (deps === null) {\n return {\n content: [\n {\n type: \"text\",\n text: `Unsupported lockfile format: ${lockfile_name}\\n\\nSupported: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Cargo.lock, go.sum`,\n },\n ],\n };\n }\n\n if (deps.length === 0) {\n return {\n content: [{ type: \"text\", text: `No dependencies found in ${lockfile_name}.` }],\n };\n }\n\n // Deduplicate\n const seen = new Set<string>();\n const unique = deps.filter((d) => {\n const key = `${d.name}@${d.version}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n const toFetch = unique.slice(0, MAX_FETCH);\n const truncated = unique.length > MAX_FETCH;\n\n // Fetch licenses in parallel (ignore failures)\n const licenseResults = await Promise.allSettled(\n toFetch.map((d) => getVersion(d.ecosystem as Ecosystem, d.name, d.version)),\n );\n\n interface LicenseResult {\n name: string;\n version: string;\n licenses: string[];\n classification: string;\n flagged: boolean;\n reason: string;\n }\n\n const allowlist = policy !== \"none\" ? POLICY_ALLOWLISTS[policy] : null;\n const results: LicenseResult[] = [];\n const licenseCount: Record<string, number> = {};\n\n for (let i = 0; i < toFetch.length; i++) {\n const dep = toFetch[i];\n if (!dep) continue;\n const result = licenseResults[i];\n const licenses =\n result?.status === \"fulfilled\" ? (result.value.licenses ?? []) : [];\n\n // Count each license\n for (const l of licenses) {\n licenseCount[l] = (licenseCount[l] ?? 0) + 1;\n }\n\n // Determine if flagged\n let flagged = false;\n let reason = \"\";\n\n if (licenses.length === 0) {\n flagged = policy !== \"none\";\n reason = \"License unknown\";\n } else if (allowlist) {\n const violating = licenses.filter((l) => !allowlist.has(l));\n if (violating.length > 0) {\n flagged = true;\n reason = `License not allowed under ${policy} policy: ${violating.join(\", \")}`;\n }\n }\n\n const classification = licenses.length === 0\n ? \"unknown\"\n : licenses.map(classifyLicense).join(\", \");\n\n if (flagged || licenses.some((l) => classifyLicense(l) !== \"permissive\")) {\n results.push({ name: dep.name, version: dep.version, licenses, classification, flagged, reason });\n }\n }\n\n const flagged = results.filter((r) => r.flagged);\n const infoOnly = results.filter((r) => !r.flagged);\n\n const lines: string[] = [\n \"🔏 Hound License Check\",\n \"═\".repeat(50),\n `Lockfile: ${lockfile_name}`,\n `Policy: ${policy}`,\n `Scanned: ${toFetch.length} packages${truncated ? ` (first ${MAX_FETCH} of ${unique.length})` : \"\"}`,\n \"\",\n ];\n\n if (flagged.length === 0) {\n lines.push(`✅ No license violations found`);\n if (policy !== \"none\") {\n lines.push(` All scanned packages comply with the ${policy} policy.`);\n }\n } else {\n lines.push(`⚠️ ${flagged.length} license violation${flagged.length === 1 ? \"\" : \"s\"} found`);\n lines.push(\"─\".repeat(50));\n for (const r of flagged) {\n const lic = r.licenses.length > 0 ? r.licenses.join(\", \") : \"unknown\";\n lines.push(` ${r.name}@${r.version}`);\n lines.push(` License: ${lic}`);\n lines.push(` ${r.reason}`);\n lines.push(\"\");\n }\n }\n\n if (infoOnly.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"Non-permissive licenses (not violations):\");\n for (const r of infoOnly) {\n const lic = r.licenses.join(\", \");\n lines.push(` ${r.name}@${r.version} ${lic}`);\n }\n lines.push(\"\");\n }\n\n // Top licenses summary\n const topLicenses = Object.entries(licenseCount)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 8);\n\n if (topLicenses.length > 0) {\n lines.push(\"─\".repeat(50));\n lines.push(\"License distribution:\");\n for (const [lic, count] of topLicenses) {\n lines.push(` ${String(count).padStart(4)}× ${lic}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"Source: deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getPackage, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport { COPYLEFT_LICENSES } from \"../constants/licenses.js\";\nimport type { Ecosystem } from \"../types/index.js\";\nimport { getDefaultVersion } from \"../utils/getDefaultVersion.js\";\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_preinstall\",\n {\n description:\n \"Safety check before installing a package. Checks known vulnerabilities, typosquatting risk, abandonment, and license concerns. Returns a go/no-go verdict.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().optional().describe(\"Package version (defaults to latest)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n // Resolve version if not provided\n let resolvedVersion = version ?? \"\";\n if (!resolvedVersion) {\n try {\n const pkg = await getPackage(eco, name);\n const defaultV = getDefaultVersion(pkg.versions);\n resolvedVersion = defaultV?.versionKey.version ?? \"\";\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `❌ Could not find package ${name} in ${ecosystem}. Check the package name.`,\n },\n ],\n };\n }\n }\n\n if (!resolvedVersion) {\n return {\n content: [\n { type: \"text\", text: `❌ Could not resolve a version for ${name} in ${ecosystem}.` },\n ],\n };\n }\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, resolvedVersion),\n queryVulns(eco, name, resolvedVersion),\n ]);\n\n if (versionResult.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `❌ Could not find ${name}@${resolvedVersion} in ${ecosystem}.`,\n },\n ],\n };\n }\n\n const pkg = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n // --- Checks ---\n const issues: { level: \"block\" | \"warn\" | \"info\"; message: string }[] = [];\n\n // 1. Vulnerabilities\n const criticalVulns = vulns.filter((v) => {\n const sev = extractSeverity(v);\n return sev === \"CRITICAL\" || sev === \"HIGH\";\n });\n if (criticalVulns.length > 0) {\n issues.push({\n level: \"block\",\n message: `${criticalVulns.length} CRITICAL/HIGH vulnerabilit${criticalVulns.length === 1 ? \"y\" : \"ies\"} known for this version`,\n });\n } else if (vulns.length > 0) {\n issues.push({\n level: \"warn\",\n message: `${vulns.length} moderate/low vulnerabilit${vulns.length === 1 ? \"y\" : \"ies\"} known for this version`,\n });\n }\n\n // 2. Typosquatting heuristics\n const typoReasons: string[] = [];\n if (/[0O1lI]/.test(name)) typoReasons.push(\"contains look-alike characters (0/O, 1/l/I)\");\n if (name.length <= 2) typoReasons.push(\"very short name\");\n if (/(.)\\1{2,}/.test(name)) typoReasons.push(\"repeated characters\");\n if (/[^a-z0-9@/._-]/.test(name)) typoReasons.push(\"unusual characters in name\");\n if (typoReasons.length >= 2) {\n issues.push({\n level: \"warn\",\n message: `Possible typosquatting risk: ${typoReasons.join(\"; \")}`,\n });\n }\n\n // 3. Abandonment — no update in >2 years + no scorecard\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n if (daysSince > 730) {\n issues.push({\n level: \"warn\",\n message: `Package version is ${Math.floor(daysSince / 365)} year(s) old — may be abandoned`,\n });\n }\n\n // 4. Low OpenSSF scorecard\n if (projectData?.scorecard != null && projectData.scorecard.overallScore < 3) {\n issues.push({\n level: \"warn\",\n message: `Low OpenSSF Scorecard score: ${projectData.scorecard.overallScore.toFixed(1)}/10`,\n });\n } else if (projectData === null) {\n issues.push({\n level: \"info\",\n message: \"No OpenSSF Scorecard data available\",\n });\n }\n\n // 5. License\n const licenses = pkg.licenses ?? [];\n if (licenses.length === 0) {\n issues.push({ level: \"warn\", message: \"License unknown\" });\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n issues.push({\n level: \"warn\",\n message: `Copyleft license detected: ${licenses.join(\", \")}`,\n });\n }\n\n // --- Verdict ---\n const blockers = issues.filter((i) => i.level === \"block\");\n const warnings = issues.filter((i) => i.level === \"warn\");\n const infos = issues.filter((i) => i.level === \"info\");\n\n const verdict = blockers.length > 0 ? \"NO-GO\" : warnings.length > 0 ? \"CAUTION\" : \"GO\";\n const verdictEmoji = verdict === \"GO\" ? \"✅\" : verdict === \"CAUTION\" ? \"⚠️\" : \"🚫\";\n\n const lines: string[] = [\n `${verdictEmoji} Pre-install check: ${name}@${resolvedVersion} (${ecosystem})`,\n \"═\".repeat(60),\n `Verdict: ${verdict}`,\n \"\",\n ];\n\n if (blockers.length > 0) {\n lines.push(\"🚫 Blockers\");\n lines.push(\"─\".repeat(30));\n for (const issue of blockers) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (warnings.length > 0) {\n lines.push(\"⚠️ Warnings\");\n lines.push(\"─\".repeat(30));\n for (const issue of warnings) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (infos.length > 0) {\n lines.push(\"ℹ️ Info\");\n lines.push(\"─\".repeat(30));\n for (const issue of infos) {\n lines.push(` • ${issue.message}`);\n }\n lines.push(\"\");\n }\n\n if (blockers.length === 0 && warnings.length === 0) {\n lines.push(\" No issues found — safe to install.\");\n lines.push(\"\");\n }\n\n if (vulns.length > 0) {\n lines.push(`💡 Run hound_vulns for full vulnerability details.`);\n }\n if (blockers.length > 0) {\n lines.push(`💡 Run hound_upgrade to find a safe version.`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractProjectId, getProject, getVersion } from \"../api/depsdev.js\";\nimport { extractSeverity, queryVulns } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport { COPYLEFT_LICENSES } from \"../constants/licenses.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nfunction letterGrade(score: number): string {\n if (score >= 90) return \"A\";\n if (score >= 75) return \"B\";\n if (score >= 60) return \"C\";\n if (score >= 40) return \"D\";\n return \"F\";\n}\n\nfunction gradeEmoji(grade: string): string {\n switch (grade) {\n case \"A\": return \"🟢\";\n case \"B\": return \"🟡\";\n case \"C\": return \"🟠\";\n case \"D\": return \"🔴\";\n default: return \"💀\";\n }\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_score\",\n {\n description:\n \"Compute a 0-100 Hound Score for a package version combining vulnerability severity, OpenSSF Scorecard, release recency, and license risk. Returns a letter grade (A-F) with a breakdown.\",\n inputSchema: {\n name: z.string().describe(\"Package name\"),\n version: z.string().describe(\"Package version\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n const [versionResult, vulnsResult] = await Promise.allSettled([\n getVersion(eco, name, version),\n queryVulns(eco, name, version),\n ]);\n\n if (versionResult.status === \"rejected\") {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find ${name}@${version} in ${ecosystem}. Check the package name and version.`,\n },\n ],\n };\n }\n\n const pkg = versionResult.value;\n const vulns = vulnsResult.status === \"fulfilled\" ? vulnsResult.value : [];\n\n const projectId = extractProjectId(pkg);\n const projectData = projectId !== null ? await getProject(projectId).catch(() => null) : null;\n\n // --- Scoring components ---\n\n // 1. Vulnerability score (0-40 points)\n let vulnScore = 40;\n for (const v of vulns) {\n const sev = extractSeverity(v);\n switch (sev) {\n case \"CRITICAL\": vulnScore -= 20; break;\n case \"HIGH\": vulnScore -= 10; break;\n case \"MODERATE\": vulnScore -= 5; break;\n case \"LOW\": vulnScore -= 2; break;\n }\n }\n vulnScore = Math.max(0, vulnScore);\n\n // 2. OpenSSF Scorecard (0-25 points)\n let scorecardScore = 0;\n if (projectData?.scorecard != null) {\n scorecardScore = Math.round((projectData.scorecard.overallScore / 10) * 25);\n } else if (projectData !== null) {\n scorecardScore = 10; // project exists but no scorecard\n }\n\n // 3. Recency score (0-20 points) — penalize stale packages\n let recencyScore = 20;\n const daysSince = Math.floor(\n (Date.now() - new Date(pkg.publishedAt).getTime()) / (1000 * 60 * 60 * 24),\n );\n if (daysSince > 730) recencyScore = 5; // >2 years\n else if (daysSince > 365) recencyScore = 10; // >1 year\n else if (daysSince > 180) recencyScore = 15; // >6 months\n\n // 4. License score (0-15 points)\n let licenseScore = 15;\n const licenses = pkg.licenses ?? [];\n if (licenses.length === 0) {\n licenseScore = 5; // unknown license\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n licenseScore = 8; // copyleft\n }\n\n const total = vulnScore + scorecardScore + recencyScore + licenseScore;\n const grade = letterGrade(total);\n const emoji = gradeEmoji(grade);\n\n const lines: string[] = [\n `${emoji} Hound Score: ${total}/100 — Grade ${grade}`,\n ` ${name}@${version} (${ecosystem})`,\n \"═\".repeat(50),\n \"\",\n \"Score Breakdown\",\n \"─\".repeat(30),\n ` Security (vulns) ${vulnScore.toString().padStart(3)}/40`,\n ` OpenSSF Scorecard ${scorecardScore.toString().padStart(3)}/25`,\n ` Release recency ${recencyScore.toString().padStart(3)}/20`,\n ` License ${licenseScore.toString().padStart(3)}/15`,\n ` ${\"─\".repeat(6)}`,\n ` Total ${total.toString().padStart(3)}/100`,\n \"\",\n ];\n\n // Details\n if (vulns.length > 0) {\n const counts: Record<string, number> = {};\n for (const v of vulns) {\n const sev = extractSeverity(v);\n counts[sev] = (counts[sev] ?? 0) + 1;\n }\n const summary = Object.entries(counts).map(([s, n]) => `${n} ${s.toLowerCase()}`).join(\", \");\n lines.push(`⚠️ ${vulns.length} known vuln(s): ${summary}`);\n } else {\n lines.push(\"✅ No known vulnerabilities\");\n }\n\n if (projectData?.scorecard != null) {\n lines.push(`🏆 OpenSSF Scorecard: ${projectData.scorecard.overallScore.toFixed(1)}/10`);\n } else if (projectData === null) {\n lines.push(\"ℹ️ No OpenSSF Scorecard data available\");\n }\n\n lines.push(`📅 Published ${daysSince} days ago`);\n\n if (licenses.length === 0) {\n lines.push(\"⚠️ License unknown\");\n } else if (licenses.some((l) => COPYLEFT_LICENSES.has(l))) {\n lines.push(`⚠️ Copyleft license: ${licenses.join(\", \")}`);\n } else {\n lines.push(`✅ License: ${licenses.join(\", \")}`);\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { getPackage } from \"../api/depsdev.js\";\nimport { queryVulnsBatch } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nfunction parseVersion(v: string): number[] {\n return v.split(\".\").map((p) => parseInt(p.replace(/[^0-9]/g, \"\"), 10) || 0);\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = parseVersion(a);\n const pb = parseVersion(b);\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_upgrade\",\n {\n description:\n \"Find the minimum version upgrade that resolves all known vulnerabilities for a package. Checks every published version and returns the nearest safe one.\",\n inputSchema: {\n name: z.string().describe(\"Package name (e.g. express, lodash)\"),\n version: z.string().describe(\"Current vulnerable version (e.g. 4.17.20)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n const eco = ecosystem as Ecosystem;\n\n let pkg: Awaited<ReturnType<typeof getPackage>>;\n try {\n pkg = await getPackage(eco, name);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Could not find package ${name} in ${ecosystem}. Check the package name.`,\n },\n ],\n };\n }\n\n // Filter to versions newer than current, sort ascending\n const candidates = pkg.versions\n .map((v) => v.versionKey.version)\n .filter((v) => compareVersions(v, version) > 0)\n .sort(compareVersions);\n\n if (candidates.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `⚠️ No newer versions of ${name} found in ${ecosystem}.\\nCurrent version: ${version}\\n\\nThis may be the latest version already.`,\n },\n ],\n };\n }\n\n // Batch query all candidates (up to 50 to avoid huge requests)\n const toCheck = candidates.slice(0, 50);\n const vulnResults = await queryVulnsBatch(\n toCheck.map((v) => ({ ecosystem: eco, name, version: v })),\n );\n\n const safeVersions = toCheck.filter((_, i) => (vulnResults[i]?.length ?? 0) === 0);\n const latestVersion = candidates.at(-1) ?? version;\n const latestVulns = vulnResults[toCheck.indexOf(latestVersion)] ?? [];\n\n const lines: string[] = [\n `🔍 Safe upgrade finder: ${name} (${ecosystem})`,\n \"═\".repeat(50),\n `Current version: ${version}`,\n `Candidates checked: ${toCheck.length} of ${candidates.length} newer versions`,\n \"\",\n ];\n\n if (safeVersions.length === 0) {\n lines.push(`❌ No safe upgrade found — all ${toCheck.length} newer versions have known vulnerabilities.`);\n lines.push(\"\");\n lines.push(\"Consider:\");\n lines.push(\" • Checking if a patch is in progress via hound_advisories\");\n lines.push(\" • Evaluating an alternative package via hound_compare\");\n } else {\n const minimum = safeVersions[0] ?? \"\";\n const latest = safeVersions.at(-1) ?? \"\";\n\n lines.push(`✅ Safe upgrade available`);\n lines.push(\"\");\n lines.push(` Minimum safe version: ${minimum}`);\n if (minimum !== latest) {\n lines.push(` Latest safe version: ${latest}`);\n }\n lines.push(\"\");\n\n if (latestVulns.length > 0 && safeVersions.at(-1) !== latestVersion) {\n lines.push(`⚠️ Latest version (${latestVersion}) still has ${latestVulns.length} known vuln(s).`);\n lines.push(` Recommended: upgrade to ${latest}`);\n } else {\n lines.push(`💡 Recommended: upgrade to ${latest}`);\n }\n\n // Show how many versions were skipped as unsafe\n const unsafeCount = toCheck.filter((_, i) => (vulnResults[i]?.length ?? 0) > 0).length;\n if (unsafeCount > 0) {\n lines.push(` (${unsafeCount} intermediate version(s) skipped — still vulnerable)`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"Source: OSV.dev + deps.dev\");\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod/v4\";\nimport { extractFixVersions, extractSeverity, queryVulns } from \"../api/osv.js\";\nimport { ECOSYSTEM_VALUES } from \"../constants/ecosystems.js\";\nimport type { Ecosystem } from \"../types/index.js\";\n\nconst SEVERITY_ICON: Record<string, string> = {\n CRITICAL: \"🔴\",\n HIGH: \"🟠\",\n MODERATE: \"🟡\",\n LOW: \"🔵\",\n UNKNOWN: \"⚪\",\n};\n\nexport function register(server: McpServer) {\n return server.registerTool(\n \"hound_vulns\",\n {\n description:\n \"List all known vulnerabilities for a specific package version, grouped by severity with fix versions and advisory links.\",\n inputSchema: {\n name: z.string().describe(\"Package name (e.g. express, lodash)\"),\n version: z.string().describe(\"Package version (e.g. 4.18.2)\"),\n ecosystem: z\n .enum(ECOSYSTEM_VALUES)\n .default(\"npm\")\n .describe(\"Package ecosystem (default: npm)\"),\n },\n },\n async ({ name, version, ecosystem }) => {\n let vulns: Awaited<ReturnType<typeof queryVulns>>;\n try {\n vulns = await queryVulns(ecosystem as Ecosystem, name, version);\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to query vulnerabilities for ${name}@${version}. The OSV API may be temporarily unavailable.`,\n },\n ],\n };\n }\n\n if (vulns.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `✅ No known vulnerabilities found for ${name}@${version} (${ecosystem}).\\n\\nThis checks the OSV database which covers GitHub Advisory Database, NVD, and more.`,\n },\n ],\n };\n }\n\n const bySeverity: Record<string, typeof vulns> = {\n CRITICAL: [],\n HIGH: [],\n MODERATE: [],\n LOW: [],\n UNKNOWN: [],\n };\n\n for (const vuln of vulns) {\n const sev = extractSeverity(vuln);\n bySeverity[sev]?.push(vuln);\n }\n\n const lines: string[] = [\n `🔍 Vulnerabilities in ${name}@${version} (${ecosystem})`,\n \"─\".repeat(50),\n `Found ${vulns.length} vulnerability${vulns.length === 1 ? \"\" : \"ies\"}`,\n \"\",\n ];\n\n for (const severity of [\"CRITICAL\", \"HIGH\", \"MODERATE\", \"LOW\", \"UNKNOWN\"]) {\n const group = bySeverity[severity] ?? [];\n if (group.length === 0) continue;\n\n const icon = SEVERITY_ICON[severity] ?? \"⚪\";\n lines.push(`${icon} ${severity} (${group.length})`);\n lines.push(\"─\".repeat(30));\n\n for (const vuln of group) {\n lines.push(` ${vuln.id}`);\n lines.push(` ${vuln.summary}`);\n\n const fixes = extractFixVersions(vuln, ecosystem as Ecosystem);\n if (fixes.length > 0) {\n lines.push(` Fix: upgrade to ${fixes.join(\" or \")}`);\n } else {\n lines.push(` Fix: no patched version available`);\n }\n\n if (vuln.aliases && vuln.aliases.length > 0) {\n lines.push(` Also known as: ${vuln.aliases.join(\", \")}`);\n }\n\n lines.push(` Published: ${vuln.published.slice(0, 10)}`);\n lines.push(\"\");\n }\n }\n\n lines.push(`Source: https://osv.dev`);\n\n return {\n content: [{ type: \"text\", text: lines.join(\"\\n\") }],\n };\n },\n );\n}\n"],"mappings":";;;AAAA,SAAS,4BAA4B;;;ACArC,SAAS,iBAAiB;;;ACC1B,SAAS,SAAS;AAEX,SAAS,gCAAgC,QAAyB;AACvE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,YAAY;AAAA,QACV,SAAS,EAAE,OAAO,EAAE,SAAS,0DAA0D;AAAA,QACvF,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,8DAA8D;AAAA,QAC1E,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,MAC5F;AAAA,IACF;AAAA,IACA,CAAC,EAAE,SAAS,KAAK,SAAS,UAAU,MAAM;AACxC,YAAM,MAAM,aAAa;AACzB,YAAM,cAAc,UAAU,WAAW,OAAO,SAAS;AACzD,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,cACP,MAAM;AAAA,cACN,MAAM,0BAA0B,WAAW,KAAK,GAAG,OAAO,GAAG;AAAA;AAAA;AAAA,gCAG3C,GAAG,KAAK,UAAU,IAAI,OAAO,KAAK,EAAE,gBAAgB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAO3E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC1CA,SAAS,KAAAA,UAAS;AAEX,SAAS,8BAA8B,QAAyB;AACrE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,YAAY;AAAA,QACV,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,MAC5F;AAAA,IACF;AAAA,IACA,CAAC,EAAE,QAAQ,MAAM;AACf,YAAM,cAAc,UAAU,aAAa,OAAO,MAAM;AACxD,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,cACP,MAAM;AAAA,cACN,MAAM,oCAAoC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAevD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACzCA,SAAS,KAAAC,UAAS;AAEX,SAAS,4BAA4B,QAAyB;AACnE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,YAAY;AAAA,QACV,WAAWA,GACR,OAAO,EACP,SAAS,EACT,SAAS,sEAAsE;AAAA,MACpF;AAAA,IACF;AAAA,IACA,CAAC,EAAE,UAAU,MAAM;AACjB,YAAM,UAAU,YAAY,qBAAqB,SAAS,MAAM;AAChE,aAAO;AAAA,QACL,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,cACP,MAAM;AAAA,cACN,MAAM,4EAA4E,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAc3F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACvCO,SAAS,gBAAgB,QAAyB;AACvD,8BAA4B,MAAM;AAClC,kCAAgC,MAAM;AACtC,gCAA8B,MAAM;AACtC;;;ACRA,SAAS,KAAAC,UAAS;;;ACYlB,IAAM,WAAW;AAEjB,IAAM,gBAA2C;AAAA,EAC/C,KAAK;AAAA,EACL,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AACZ;AA8FA,eAAe,IAAO,MAA0B;AAC9C,QAAM,MAAM,GAAG,QAAQ,GAAG,IAAI;AAC9B,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,cAAc,aAAa,OAAe,GAAG;AAAA,EAC1D,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAM,IAAI,aAAa,IAAI,QAAQ,KAAK,IAAI;AAAA,EAC9C;AAEA,SAAO,IAAI,KAAK;AAClB;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YACkB,QACA,KACA,MAChB;AACA,UAAM,sBAAsB,MAAM,QAAQ,GAAG,EAAE;AAJ/B;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAMA,eAAsB,WACpB,WACA,MACA,SACyB;AACzB,QAAM,MAAM,cAAc,SAAS;AACnC,SAAO;AAAA,IACL,YAAY,GAAG,aAAa,mBAAmB,IAAI,CAAC,aAAa,mBAAmB,OAAO,CAAC;AAAA,EAC9F;AACF;AAMA,eAAsB,WAAW,WAAsB,MAAuC;AAC5F,QAAM,MAAM,cAAc,SAAS;AACnC,SAAO,IAAoB,YAAY,GAAG,aAAa,mBAAmB,IAAI,CAAC,EAAE;AACnF;AAOA,eAAsB,gBACpB,WACA,MACA,SAC8B;AAC9B,QAAM,MAAM,cAAc,SAAS;AACnC,SAAO;AAAA,IACL,YAAY,GAAG,aAAa,mBAAmB,IAAI,CAAC,aAAa,mBAAmB,OAAO,CAAC;AAAA,EAC9F;AACF;AAMA,eAAsB,WAAW,WAA4C;AAC3E,QAAM,UAAU,UAAU,WAAW,KAAK,KAAK;AAC/C,SAAO,IAAoB,aAAa,OAAO,EAAE;AACnD;AAKA,eAAsB,YAAY,YAA8C;AAC9E,SAAO,IAAqB,eAAe,mBAAmB,UAAU,CAAC,EAAE;AAC7E;AAMO,SAAS,iBAAiB,SAAwC;AACvE,QAAM,UAAU,QAAQ,mBAAmB,CAAC;AAC5C,QAAM,aAAa,QAAQ;AAAA,IACzB,CAAC,MAAM,EAAE,iBAAiB,iBAAiB,EAAE,iBAAiB;AAAA,EAChE;AACA,SAAO,YAAY,WAAW,MAAM;AACtC;;;ACpMA,IAAMC,YAAW;AAEjB,IAAMC,iBAA2C;AAAA,EAC/C,KAAK;AAAA,EACL,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AACZ;AAyDA,eAAe,KAAgB,MAAc,MAAmC;AAC9E,QAAM,MAAM,GAAGD,SAAQ,GAAG,IAAI;AAC9B,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,cAAc,aAAa,OAAe;AAAA,IAC5C;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAM,IAAI,SAAS,IAAI,QAAQ,KAAK,IAAI;AAAA,EAC1C;AAEA,SAAO,IAAI,KAAK;AAClB;AAEO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACkB,QACA,KACA,MAChB;AACA,UAAM,iBAAiB,MAAM,QAAQ,GAAG,EAAE;AAJ1B;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAMA,eAAsB,WACpB,WACA,MACA,SACoB;AACpB,QAAM,WAAW,MAAM,KAAuB,UAAU;AAAA,IACtD;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA,WAAWC,eAAc,SAAS;AAAA,IACpC;AAAA,EACF,CAAC;AACD,SAAO,SAAS,SAAS,CAAC;AAC5B;AAOA,eAAsB,gBACpB,UACsB;AACtB,MAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AAEnC,QAAM,WAAW,MAAM,KAAuB,eAAe;AAAA,IAC3D,SAAS,SAAS,IAAI,CAAC,SAAS;AAAA,MAC9B,SAAS,IAAI;AAAA,MACb,SAAS;AAAA,QACP,MAAM,IAAI;AAAA,QACV,WAAWA,eAAc,IAAI,SAAS;AAAA,MACxC;AAAA,IACF,EAAE;AAAA,EACJ,CAAC;AAED,SAAO,SAAS,QAAQ,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC,CAAC;AAC5D;AAKA,eAAsB,QAAQ,QAAkC;AAC9D,QAAM,MAAM,GAAGD,SAAQ,UAAU,mBAAmB,MAAM,CAAC;AAC3D,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,cAAc,aAAa,OAAe,GAAG;AAAA,EAC1D,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAM,IAAI,SAAS,IAAI,QAAQ,KAAK,IAAI;AAAA,EAC1C;AAEA,SAAO,IAAI,KAAK;AAClB;AAMO,SAAS,gBAAgB,MAAyB;AAEvD,QAAM,aAAa,KAAK,mBAAmB,UAAU,YAAY;AACjE,MAAI,eAAe,WAAY,QAAO;AACtC,MAAI,eAAe,OAAQ,QAAO;AAClC,MAAI,eAAe,WAAY,QAAO;AACtC,MAAI,eAAe,MAAO,QAAO;AAGjC,QAAM,YAAY,iBAAiB,IAAI;AACvC,MAAI,cAAc,KAAM,QAAO;AAC/B,MAAI,aAAa,EAAK,QAAO;AAC7B,MAAI,aAAa,EAAK,QAAO;AAC7B,MAAI,aAAa,EAAK,QAAO;AAC7B,SAAO;AACT;AAOO,SAAS,iBAAiB,MAA8B;AAC7D,QAAM,UAAU,KAAK,YAAY,CAAC;AAClC,QAAM,YAAY,CAAC,WAAW,WAAW,SAAS;AAElD,aAAW,QAAQ,WAAW;AAC5B,UAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACjD,QAAI,OAAO;AACT,aAAO,eAAe,MAAM,KAAK;AAAA,IACnC;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,mBAAmB,MAAe,WAAgC;AAChF,QAAM,eAAeC,eAAc,SAAS;AAC5C,QAAM,QAAQ,oBAAI,IAAY;AAE9B,aAAW,YAAY,KAAK,UAAU;AACpC,QAAI,SAAS,QAAQ,UAAU,YAAY,MAAM,aAAa,YAAY,GAAG;AAC3E;AAAA,IACF;AACA,eAAW,SAAS,SAAS,QAAQ;AACnC,iBAAW,SAAS,MAAM,QAAQ;AAChC,YAAI,WAAW,SAAS,MAAM,OAAO;AACnC,gBAAM,IAAI,MAAM,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,KAAK;AAClB;AAEA,SAAS,eAAe,QAA+B;AAKrD,OAAK;AACL,SAAO;AACT;;;AFzOO,SAAS,SAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,IAAIC,GACD,OAAO,EACP,SAAS,4EAAuE;AAAA,MACrF;AAAA,IACF;AAAA,IACA,OAAO,EAAE,GAAG,MAAM;AAEhB,YAAM,CAAC,WAAW,aAAa,IAAI,MAAM,QAAQ,WAAW,CAAC,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC;AAE1F,YAAM,QAAkB,CAAC;AAEzB,UAAI,UAAU,WAAW,aAAa;AACpC,cAAM,OAAO,UAAU;AAEvB,cAAM,KAAK,uBAAgB,KAAK,EAAE,EAAE;AACpC,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,sBAAe,KAAK,OAAO,EAAE;AACxC,cAAM,KAAK,wBAAiB,KAAK,UAAU,MAAM,GAAG,EAAE,CAAC,EAAE;AACzD,cAAM,KAAK,4BAAqB,KAAK,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE;AAE5D,YAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC3C,gBAAM,KAAK,4BAAqB,KAAK,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,QAC3D;AAEA,cAAM,aAAa,KAAK,mBAAmB;AAC3C,YAAI,YAAY;AACd,gBAAM,KAAK,2BAAiB,UAAU,EAAE;AAAA,QAC1C;AAEA,YAAI,KAAK,mBAAmB,WAAW,KAAK,kBAAkB,QAAQ,SAAS,GAAG;AAChF,gBAAM,KAAK,yBAAa,KAAK,kBAAkB,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,QACrE;AAEA,YAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,6BAAsB;AACjC,gBAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AAEzB,qBAAW,YAAY,KAAK,UAAU;AACpC,kBAAM,KAAK,KAAK,SAAS,QAAQ,SAAS,KAAK,SAAS,QAAQ,IAAI,EAAE;AAEtE,uBAAW,SAAS,SAAS,QAAQ;AACnC,kBAAI,MAAM,SAAS,UAAU;AAC3B,sBAAM,aAAa,MAAM,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAC7D,sBAAM,QAAQ,MAAM,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AACnD,sBAAM,WACJ,cAAc,gBAAgB,aAAa,WAAW,aAAa;AACrE,oBAAI,SAAS,WAAW,OAAO;AAC7B,wBAAM,KAAK,kBAAkB,QAAQ,cAAc,MAAM,KAAK,EAAE;AAAA,gBAClE,OAAO;AACL,wBAAM,KAAK,kBAAkB,QAAQ,qBAAqB;AAAA,gBAC5D;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,KAAK,SAAS;AAChB,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,mBAAY;AACvB,gBAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AAEzB,gBAAM,UACJ,KAAK,QAAQ,SAAS,MAAM,GAAG,KAAK,QAAQ,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK;AACxE,gBAAM,KAAK,OAAO;AAAA,QACpB;AAEA,YAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;AACjD,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,sBAAe;AAC1B,gBAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,qBAAW,OAAO,KAAK,WAAW,MAAM,GAAG,CAAC,GAAG;AAC7C,kBAAM,KAAK,KAAK,IAAI,GAAG,EAAE;AAAA,UAC3B;AACA,cAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,kBAAM,KAAK,aAAa,KAAK,WAAW,SAAS,CAAC,OAAO;AAAA,UAC3D;AAAA,QACF;AAEA,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,yCAAyC,EAAE,EAAE;AAAA,MAC1D,WAAW,cAAc,WAAW,aAAa;AAE/C,cAAM,WAAW,cAAc;AAE/B,cAAM,KAAK,uBAAgB,SAAS,YAAY,EAAE,EAAE;AACpD,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,oBAAa,SAAS,KAAK,EAAE;AAExC,YAAI,SAAS,QAAQ,SAAS,GAAG;AAC/B,gBAAM,KAAK,4BAAqB,SAAS,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,QAC/D;AAEA,cAAM,KAAK,gCAAsB,SAAS,UAAU,EAAE;AACtD,cAAM,KAAK,0BAAmB,SAAS,WAAW,EAAE;AACpD,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,WAAW,SAAS,GAAG,EAAE;AAAA,MACtC,OAAO;AACL,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,4BAA4B,EAAE;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AG9HA,SAAS,KAAAC,UAAS;;;ACDX,IAAM,mBAAmB,CAAC,OAAO,QAAQ,MAAM,SAAS,SAAS,SAAS,UAAU;;;ADOpF,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,GAAE,OAAO,EAAE,SAAS,cAAc;AAAA,QACxC,SAASA,GAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,QAC9C,WAAWA,GACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AACtC,YAAM,MAAM;AAEZ,YAAM,CAAC,aAAa,KAAK,IAAI,MAAM,QAAQ,WAAW;AAAA,QACpD,WAAW,KAAK,MAAM,OAAO;AAAA,QAC7B,WAAW,KAAK,MAAM,OAAO;AAAA,MAC/B,CAAC;AAED,UAAI,YAAY,WAAW,YAAY;AACrC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,kBAAkB,IAAI,IAAI,OAAO,OAAO,SAAS;AAAA,YACzD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,MAAM,YAAY;AACxB,YAAM,WAAW,MAAM,WAAW,cAAc,MAAM,QAAQ,CAAC;AAG/D,YAAM,YAAY,iBAAiB,GAAG;AACtC,YAAM,cAAc,cAAc,OAAO,MAAM,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI,IAAI;AAEzF,YAAM,QAAkB,CAAC,aAAM,IAAI,IAAI,OAAO,KAAK,SAAS,KAAK,SAAI,OAAO,EAAE,GAAG,EAAE;AAGnF,YAAM,YAAY,IAAI,YAAY,MAAM,GAAG,EAAE;AAC7C,YAAM,YAAY,KAAK;AAAA,SACpB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,WAAW,EAAE,QAAQ,MAAM,MAAO,KAAK,KAAK;AAAA,MACzE;AACA,YAAM,KAAK,wBAAiB,SAAS,KAAK,SAAS,YAAY;AAG/D,YAAM,WACJ,IAAI,YAAY,IAAI,SAAS,SAAS,IAAI,IAAI,SAAS,KAAK,IAAI,IAAI;AACtE,YAAM,KAAK,sBAAe,QAAQ,EAAE;AAGpC,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,KAAK,8CAAkC;AAAA,MAC/C,OAAO;AACL,cAAM,SAAiC,CAAC;AACxC,mBAAW,KAAK,UAAU;AACxB,gBAAM,MAAM,gBAAgB,CAAC;AAC7B,iBAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AAAA,QACrC;AACA,cAAM,UAAU,OAAO,QAAQ,MAAM,EAClC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,EACzC,KAAK,IAAI;AACZ,cAAM,KAAK,kCAAwB,SAAS,MAAM,KAAK,OAAO,GAAG;AAAA,MACnE;AAGA,YAAM,gBAAgB,IAAI,cAAc,UAAU;AAClD,UAAI,gBAAgB,GAAG;AACrB,cAAM,MAAM,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,IAAI;AACxD,cAAM,KAAK,yBAAkB,GAAG,EAAE;AAAA,MACpC;AAGA,UAAI,gBAAgB,MAAM;AACxB,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,0BAAmB;AAC9B,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,iBAAY,YAAY,WAAW,eAAe,CAAC,EAAE;AAChE,cAAM,KAAK,oBAAa,YAAY,WAAW,eAAe,CAAC,EAAE;AACjE,cAAM,KAAK,0BAAmB,YAAY,gBAAgB,eAAe,CAAC,EAAE;AAE5E,YAAI,YAAY,cAAc,MAAM;AAClC,gBAAM,QAAQ,YAAY,UAAU,aAAa,QAAQ,CAAC;AAC1D,gBAAM,QAAQ,eAAe,YAAY,UAAU,YAAY;AAC/D,gBAAM,KAAK,gCAAyB,KAAK,QAAQ,KAAK,GAAG;AAEzD,gBAAM,OAAO,CAAC,GAAG,YAAY,UAAU,MAAM,EAC1C,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,CAAC;AACb,cAAI,KAAK,SAAS,GAAG;AACnB,kBAAM;AAAA,cACJ,qBAAqB,KAAK,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,YAC9E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,WAAW,IAAI,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,UAAU;AAC9D,YAAM,aAAa,IAAI,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,aAAa;AACnE,UAAI,YAAY,YAAY;AAC1B,cAAM,KAAK,EAAE;AACb,YAAI,SAAU,OAAM,KAAK,uBAAgB,SAAS,GAAG,EAAE;AACvD,YAAI,WAAY,OAAM,KAAK,qBAAc,WAAW,GAAG,EAAE;AAAA,MAC3D;AAEA,YAAM,KAAK,EAAE;AACb,YAAM;AAAA,QACJ,wCAAiC,SAAS,aAAa,mBAAmB,IAAI,CAAC,aAAa,mBAAmB,OAAO,CAAC;AAAA,MACzH;AAEA,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,OAAuB;AAC7C,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO;AACT;;;AEvIA,SAAS,KAAAC,UAAS;;;ACWX,SAAS,kBAA0C,UAA8B;AACtF,SAAO,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,SAAS,GAAG,EAAE;AAC5D;;;ADFA,IAAM,mBAA6C;AAAA,EACjD,KAAK;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,IAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO,CAAC,SAAS,SAAS,WAAW,QAAQ,UAAU,OAAO,QAAQ,OAAO;AAAA,EAC7E,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,UAAU,CAAC,SAAS,UAAU,cAAc,gBAAgB,SAAS;AACvE;AAEO,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,WAAWC,GACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,QAC9C,UAAUA,GACP,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT;AAAA,UACC;AAAA,QACF;AAAA,MACJ;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,SAAS,MAAM;AACjC,YAAM,MAAM;AACZ,YAAM,QAAQ,YAAY,iBAAiB,SAAS,KAAK,CAAC;AAE1D,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,uDAAuD,SAAS;AAAA,YACxE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,iBAAiB,MAAM,QAAQ;AAAA,QACnC,MAAM,IAAI,OAAO,SAAS;AACxB,gBAAM,MAAM,MAAM,WAAW,KAAK,IAAI;AACtC,gBAAM,iBAAiB,kBAAkB,IAAI,QAAQ;AACrD,iBAAO;AAAA,YACL;AAAA,YACA,SAAS,gBAAgB,WAAW,WAAW;AAAA,UACjD;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,WAAW,eACd,IAAI,CAAC,GAAG,OAAO;AAAA,QACd,MAAM,MAAM,CAAC,KAAK;AAAA,QAClB,SAAS,EAAE,WAAW,cAAc,EAAE,MAAM,UAAU;AAAA,MACxD,EAAE,EACD,OAAO,CAAC,MAA8C,EAAE,YAAY,IAAI;AAE3E,YAAM,SAAS,eAAe,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU,EAAE;AAErE,YAAM,cAAc,MAAM;AAAA,QACxB,SAAS,IAAI,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,EAAE;AAAA,MAC5E;AAEA,YAAM,QAAkB;AAAA,QACtB,iCAA0B,SAAS;AAAA,QACnC,SAAI,OAAO,EAAE;AAAA,QACb,WAAW,SAAS,MAAM;AAAA,QAC1B;AAAA,MACF;AAGA,YAAM,YAAY,SACf,IAAI,CAAC,KAAK,OAAO,EAAE,GAAG,KAAK,OAAO,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,EACzD,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,SAAS,EAAE,MAAM,MAAM;AAEjD,YAAM,kBAAkB,UAAU,OAAO,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC,EAAE;AAEpE,UAAI,oBAAoB,GAAG;AACzB,cAAM,KAAK,cAAS,SAAS,MAAM,sDAAiD;AACpF,cAAM,KAAK,EAAE;AAAA,MACf,OAAO;AACL,cAAM,KAAK,iBAAO,eAAe,OAAO,SAAS,MAAM,iCAAiC;AACxF,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,iBAAW,OAAO,WAAW;AAC3B,YAAI,IAAI,MAAM,WAAW,GAAG;AAC1B,gBAAM,KAAK,YAAO,IAAI,IAAI,IAAI,IAAI,OAAO,EAAE;AAAA,QAC7C,OAAO;AACL,gBAAM,KAAK,mBAAS,IAAI,IAAI,IAAI,IAAI,OAAO,WAAM,IAAI,MAAM,MAAM,UAAU;AAE3E,qBAAW,KAAK,IAAI,MAAM,MAAM,GAAG,CAAC,GAAG;AACrC,kBAAM,KAAK,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;AAAA,UAC1C;AACA,cAAI,IAAI,MAAM,SAAS,GAAG;AACxB,kBAAM,KAAK,iBAAiB,IAAI,MAAM,SAAS,CAAC,OAAO;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS,GAAG;AACd,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,iBAAO,MAAM,wCAAwC,SAAS,GAAG;AAAA,MAC9E;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,4BAA4B;AAEvC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AEzKA,SAAS,KAAAC,UAAS;AAKX,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,GAAE,OAAO,EAAE,SAAS,cAAc;AAAA,QACxC,SAASA,GAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,QAC9C,WAAWA,GACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,QAC9C,UAAUA,GACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,CAAC,EACT,SAAS,gDAAgD;AAAA,MAC9D;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,WAAW,SAAS,MAAM;AAChD,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,gBAAgB,WAAwB,MAAM,OAAO;AAAA,MACpE,QAAQ;AACN,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,uCAAuC,IAAI,IAAI,OAAO;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK;AACnB,YAAM,QAAQ,KAAK;AAEnB,YAAM,cAAc,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ,EAAE;AACjE,YAAM,gBAAgB,MAAM,OAAO,CAAC,MAAM,EAAE,aAAa,UAAU,EAAE;AACrE,YAAM,aAAa,cAAc;AAGjC,YAAM,WAAW,oBAAI,IAAsB;AAC3C,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,SAAS,IAAI,KAAK,QAAQ,EAAG,UAAS,IAAI,KAAK,UAAU,CAAC,CAAC;AAChE,iBAAS,IAAI,KAAK,QAAQ,GAAG,KAAK,KAAK,MAAM;AAAA,MAC/C;AAEA,YAAM,QAAkB;AAAA,QACtB,iCAA0B,IAAI,IAAI,OAAO,KAAK,SAAS;AAAA,QACvD,SAAI,OAAO,EAAE;AAAA,QACb,GAAG,UAAU,wBAAwB,WAAW,YAAY,aAAa;AAAA,QACzE;AAAA,MACF;AAGA,YAAM,WAAW,MAAM,CAAC;AACxB,UAAI,UAAU;AACZ,mBAAW,OAAO,OAAO,UAAU,GAAG,GAAG,UAAU,oBAAI,IAAI,CAAC;AAAA,MAC9D;AAEA,UAAI,WAAW,MAAM,gBAAgB,GAAG;AACtC,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,qCAA2B,QAAQ,+BAA+B;AAAA,MAC/E;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,kBAAkB;AAE7B,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,WACP,OACA,OACA,UACA,WACA,OACA,UACA,SACM;AACN,MAAI,QAAQ,IAAI,SAAS,EAAG;AAC5B,UAAQ,IAAI,SAAS;AAErB,QAAM,OAAO,MAAM,SAAS;AAC5B,MAAI,CAAC,KAAM;AAEX,QAAM,SAAS,KAAK,OAAO,KAAK;AAChC,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,SAAS,KAAK;AAC7B,QAAM,cAAc,KAAK,OAAO,SAAS,IAAI,kBAAQ;AACrD,QAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,OAAO,GAAG,WAAW,EAAE;AAE/F,MAAI,SAAS,UAAU;AACrB,UAAM,aAAa,SAAS,IAAI,SAAS,GAAG,UAAU;AACtD,QAAI,aAAa,GAAG;AAClB,YAAM,KAAK,GAAG,MAAM,6BAAc,UAAU,QAAQ;AAAA,IACtD;AACA;AAAA,EACF;AAEA,aAAW,YAAY,SAAS,IAAI,SAAS,KAAK,CAAC,GAAG;AACpD,eAAW,OAAO,OAAO,UAAU,UAAU,QAAQ,GAAG,UAAU,OAAO;AAAA,EAC3E;AACF;;;ACpHA,SAAS,KAAAC,UAAS;AAclB,SAAS,cAAc,MAAwB;AAC7C,QAAM,WAAW,oBAAI,IAAY;AAGjC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,aAAS,IAAI,KAAK,MAAM,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,EACnD;AAGA,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACxC,UAAM,IAAI,KAAK,OAAO,CAAC;AACvB,UAAM,IAAI,KAAK,OAAO,IAAI,CAAC;AAC3B,aAAS,IAAI,KAAK,MAAM,GAAG,CAAC,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,EAC3D;AAGA,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,aAAS,IAAI,KAAK,WAAW,KAAK,GAAG,CAAC;AACtC,aAAS,IAAI,KAAK,WAAW,KAAK,EAAE,CAAC;AAAA,EACvC;AACA,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,aAAS,IAAI,KAAK,WAAW,KAAK,GAAG,CAAC;AACtC,aAAS,IAAI,KAAK,WAAW,KAAK,EAAE,CAAC;AAAA,EACvC;AAGA,WAAS,IAAI,QAAQ,IAAI,EAAE;AAC3B,WAAS,IAAI,GAAG,IAAI,KAAK;AACzB,WAAS,IAAI,GAAG,IAAI,IAAI;AACxB,WAAS,IAAI,GAAG,IAAI,OAAO;AAG3B,WAAS,OAAO,IAAI;AAEpB,SAAO,CAAC,GAAG,QAAQ;AACrB;AAEO,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,GAAE,OAAO,EAAE,SAAS,uBAAuB;AAAA,QACjD,WAAWA,GACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,UAAU,MAAM;AAC7B,YAAM,MAAM;AACZ,YAAM,WAAW,cAAc,IAAI;AAGnC,YAAM,UAAU,MAAM,QAAQ;AAAA,QAC5B,SAAS,IAAI,OAAO,YAAY;AAC9B,gBAAM,MAAM,MAAM,WAAW,KAAK,OAAO;AACzC,iBAAO,EAAE,MAAM,SAAS,cAAc,IAAI,SAAS,OAAO;AAAA,QAC5D,CAAC;AAAA,MACH;AAEA,YAAM,WAAW,QACd,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EACtC,IAAI,CAAC,MAAO,EAAqE,KAAK,EACtF,KAAK,CAAC,GAAG,MAAM,EAAE,eAAe,EAAE,YAAY;AAGjD,YAAM,eAAe,MAAM,WAAW,KAAK,IAAI,EAC5C,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,EAC7B,MAAM,MAAM,IAAI;AAEnB,YAAM,QAAkB,CAAC,8BAAuB,IAAI,KAAK,SAAS,KAAK,SAAI,OAAO,EAAE,GAAG,EAAE;AAEzF,UAAI,iBAAiB,MAAM;AACzB,cAAM,KAAK,kBAAQ,IAAI,uBAAuB,SAAS,GAAG;AAC1D,cAAM,KAAK,yEAAoE;AAAA,MACjF,OAAO;AACL,cAAM,KAAK,WAAM,IAAI,aAAa,YAAY,sBAAsB;AAAA,MACtE;AAEA,YAAM,KAAK,EAAE;AAEb,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,KAAK,yCAAoC,SAAS,GAAG;AAC3D,cAAM,KAAK,eAAe,SAAS,MAAM,4BAA4B;AAAA,MACvE,OAAO;AACL,cAAM,KAAK,uBAAa,SAAS,MAAM,qCAAqC,SAAS,GAAG;AACxF,cAAM,KAAK,EAAE;AACb,mBAAW,OAAO,UAAU;AAC1B,gBAAM,KAAK,eAAQ,IAAI,IAAI,KAAK,IAAI,YAAY,YAAY;AAAA,QAC9D;AACA,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,4BAA4B,IAAI,yCAAyC;AACpF,cAAM,KAAK,6BAA6B,IAAI,oCAAoC;AAAA,MAClF;AAEA,YAAM,KAAK,EAAE;AACb,YAAM;AAAA,QACJ,yBAAe,SAAS,MAAM;AAAA,MAChC;AAEA,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AC1HA,SAAS,KAAAC,UAAS;;;ACSX,SAAS,cAAc,UAAkB,SAAqC;AACnF,QAAM,OAAO,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAE1C,MAAI,SAAS,oBAAqB,QAAO,iBAAiB,OAAO;AACjE,MAAI,SAAS,YAAa,QAAO,cAAc,OAAO;AACtD,MAAI,SAAS,iBAAkB,QAAO,cAAc,OAAO;AAC3D,MAAI,SAAS,mBAAoB,QAAO,kBAAkB,OAAO;AACjE,MAAI,SAAS,aAAc,QAAO,eAAe,OAAO;AACxD,MAAI,SAAS,SAAU,QAAO,WAAW,OAAO;AAEhD,SAAO;AACT;AAKA,SAAS,iBAAiB,SAA8B;AACtD,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,OAAoB,CAAC;AAG3B,QAAM,WAAW,KAAK;AACtB,MAAI,UAAU;AACZ,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACjD,UAAI,CAAC,OAAO,QAAQ,GAAI;AACxB,UAAI,CAAC,IAAI,QAAS;AAElB,YAAM,OAAO,IAAI,QAAQ,qBAAqB,EAAE;AAChD,UAAI,KAAM,MAAK,KAAK,EAAE,MAAM,SAAS,IAAI,SAAS,WAAW,MAAM,CAAC;AAAA,IACtE;AACA,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,KAAK;AAG1B,MAAI,cAAc;AAChB,iBAAa,cAAc,IAAI;AAAA,EACjC;AAEA,SAAO;AACT;AAEA,SAAS,aACP,MACA,KACM;AACN,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC9C,QAAI,IAAI,QAAS,KAAI,KAAK,EAAE,MAAM,SAAS,IAAI,SAAS,WAAW,MAAM,CAAC;AAC1E,QAAI,IAAI,cAAc;AACpB;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,cAAc,SAA8B;AACnD,QAAM,OAAoB,CAAC;AAC3B,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,MAAI,cAA6B;AAEjC,aAAW,QAAQ,OAAO;AAExB,QAAI,CAAC,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAE9F,YAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,QAAQ,MAAM,EAAE,KAAK;AAE9D,UAAI,MAAM,WAAW,GAAG,GAAG;AACzB,cAAM,QAAQ,MAAM,QAAQ,KAAK,CAAC;AAClC,sBAAc,QAAQ,IAAI,MAAM,MAAM,GAAG,KAAK,IAAI;AAAA,MACpD,OAAO;AACL,cAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,sBAAc,QAAQ,IAAI,MAAM,MAAM,GAAG,KAAK,IAAI;AAAA,MACpD;AAAA,IACF,WAAW,aAAa;AACtB,YAAM,QAAQ,uBAAuB,KAAK,IAAI;AAC9C,UAAI,QAAQ,CAAC,GAAG;AACd,aAAK,KAAK,EAAE,MAAM,aAAa,SAAS,MAAM,CAAC,GAAG,WAAW,MAAM,CAAC;AACpE,sBAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,cAAc,SAA8B;AACnD,QAAM,OAAoB,CAAC;AAC3B,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAKhC,aAAW,QAAQ,OAAO;AAExB,UAAM,UAAU,6CAA6C,KAAK,IAAI;AACtE,QAAI,UAAU,CAAC,KAAK,QAAQ,CAAC,GAAG;AAC9B,WAAK,KAAK,EAAE,MAAM,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC,GAAG,WAAW,MAAM,CAAC;AACrE;AAAA,IACF;AAEA,UAAM,UAAU,2CAA2C,KAAK,IAAI;AACpE,QAAI,UAAU,CAAC,KAAK,QAAQ,CAAC,GAAG;AAC9B,WAAK,KAAK,EAAE,MAAM,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC,GAAG,WAAW,MAAM,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,kBAAkB,SAA8B;AACvD,QAAM,OAAoB,CAAC;AAE3B,aAAW,OAAO,QAAQ,MAAM,IAAI,GAAG;AACrC,UAAM,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAAK;AAC1C,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AAGnC,UAAM,UAAU,mCAAmC,KAAK,IAAI;AAC5D,QAAI,UAAU,CAAC,KAAK,QAAQ,CAAC,GAAG;AAC9B,WAAK,KAAK,EAAE,MAAM,QAAQ,CAAC,EAAE,YAAY,GAAG,SAAS,QAAQ,CAAC,GAAG,WAAW,OAAO,CAAC;AAAA,IACtF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,eAAe,SAA8B;AACpD,QAAM,OAAoB,CAAC;AAC3B,MAAI,OAAsB;AAC1B,MAAI,UAAyB;AAC7B,MAAI,YAAY;AAEhB,aAAW,OAAO,QAAQ,MAAM,IAAI,GAAG;AACrC,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,SAAS,eAAe;AAC1B,UAAI,QAAQ,QAAS,MAAK,KAAK,EAAE,MAAM,SAAS,WAAW,QAAQ,CAAC;AACpE,aAAO;AACP,gBAAU;AACV,kBAAY;AAAA,IACd,WAAW,WAAW;AACpB,YAAM,YAAY,wBAAwB,KAAK,IAAI;AACnD,UAAI,YAAY,CAAC,EAAG,QAAO,UAAU,CAAC;AACtC,YAAM,WAAW,2BAA2B,KAAK,IAAI;AACrD,UAAI,WAAW,CAAC,EAAG,WAAU,SAAS,CAAC;AAAA,IACzC;AAAA,EACF;AACA,MAAI,QAAQ,QAAS,MAAK,KAAK,EAAE,MAAM,SAAS,WAAW,QAAQ,CAAC;AAEpE,SAAO;AACT;AAKA,SAAS,WAAW,SAA8B;AAChD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,OAAoB,CAAC;AAE3B,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AAGtC,UAAM,QAAQ,sBAAsB,KAAK,IAAI;AAC7C,QAAI,QAAQ,CAAC,KAAK,MAAM,CAAC,GAAG;AAC1B,YAAM,MAAM,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AACnC,UAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,aAAK,IAAI,GAAG;AACZ,aAAK,KAAK,EAAE,MAAM,MAAM,CAAC,GAAG,SAAS,MAAM,CAAC,GAAG,WAAW,KAAK,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ADtMA,IAAM,YAAY;AAElB,IAAM,iBAAiB,CAAC,YAAY,QAAQ,YAAY,OAAO,SAAS;AAExE,IAAM,gBAAwC;AAAA,EAC5C,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,KAAK;AAAA,EACL,SAAS;AACX;AAEO,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,kBAAkBC,GAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,QACzE,eAAeA,GACZ,OAAO,EACP;AAAA,UACC;AAAA,QACF;AAAA,MACJ;AAAA,IACF;AAAA,IACA,OAAO,EAAE,kBAAkB,cAAc,MAAM;AAC7C,YAAM,OAAO,cAAc,eAAe,gBAAgB;AAE1D,UAAI,SAAS,MAAM;AACjB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,gCAAgC,aAAa;AAAA;AAAA;AAAA,YACrD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,GAAG;AACrB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,4BAA4B,aAAa;AAAA,YACjD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,OAAO,oBAAI,IAAY;AAC7B,YAAM,SAAS,KAAK,OAAO,CAAC,MAAM;AAChC,cAAM,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO;AAClC,YAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,aAAK,IAAI,GAAG;AACZ,eAAO;AAAA,MACT,CAAC;AAED,YAAM,UAAU,OAAO,MAAM,GAAG,SAAS;AACzC,YAAM,YAAY,OAAO,SAAS;AAGlC,YAAM,cAAc,MAAM;AAAA,QACxB,QAAQ,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,WAAwB,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,EAAE;AAAA,MAChG;AAWA,YAAM,WAAsB,CAAC;AAC7B,YAAM,aAA8C,CAAC;AAErD,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,cAAM,MAAM,QAAQ,CAAC;AACrB,cAAM,QAAQ,YAAY,CAAC,KAAK,CAAC;AACjC,YAAI,CAAC,IAAK;AACV,mBAAW,KAAK,OAAO;AACrB,gBAAM,MAAM,gBAAgB,CAAC;AAC7B,qBAAW,GAAG,KAAK,WAAW,GAAG,KAAK,KAAK;AAC3C,mBAAS,KAAK;AAAA,YACZ,MAAM,IAAI;AAAA,YACV,SAAS,IAAI;AAAA,YACb,UAAU;AAAA,YACV,IAAI,EAAE;AAAA,YACN,SAAS,EAAE;AAAA,UACb,CAAC;AAAA,QACH;AAAA,MACF;AAEA,YAAM,aAAa,SAAS;AAC5B,YAAM,eAAe,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;AAG5E,YAAM,QAAkB;AAAA,QACtB;AAAA,QACA,SAAI,OAAO,EAAE;AAAA,QACb,aAAa,aAAa;AAAA,QAC1B,aAAa,QAAQ,MAAM,gBAAgB,YAAY,eAAe,SAAS,OAAO,OAAO,MAAM,MAAM,EAAE;AAAA,QAC3G;AAAA,MACF;AAGA,UAAI,eAAe,GAAG;AACpB,cAAM,KAAK,wCAAmC;AAAA,MAChD,OAAO;AACL,cAAM,KAAK,SAAS,UAAU,gBAAgB,eAAe,IAAI,MAAM,KAAK,WAAW,YAAY,WAAW,iBAAiB,IAAI,KAAK,GAAG,GAAG;AAC9I,mBAAW,OAAO,gBAAgB;AAChC,gBAAM,QAAQ,WAAW,GAAG,KAAK;AACjC,cAAI,QAAQ,GAAG;AACb,kBAAM,OAAO,cAAc,GAAG,KAAK;AACnC,kBAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,YAAY,CAAC,EAAE;AAAA,UACtD;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK,EAAE;AAGb,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,qBAAqB;AAChC,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AAEzB,mBAAW,OAAO,gBAAgB;AAChC,gBAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG;AACvD,cAAI,MAAM,WAAW,EAAG;AAExB,gBAAM,OAAO,cAAc,GAAG,KAAK;AACnC,gBAAM,KAAK;AAAA,EAAK,IAAI,IAAI,GAAG,KAAK,MAAM,MAAM,GAAG;AAG/C,gBAAM,QAAmC,CAAC;AAC1C,qBAAW,KAAK,OAAO;AACrB,kBAAM,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO;AAClC,aAAC,MAAM,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC;AAAA,UAC5B;AAEA,qBAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,KAAK,GAAG;AACtD,kBAAM,KAAK,KAAK,GAAG,EAAE;AACrB,uBAAW,KAAK,aAAa;AAC3B,oBAAM,KAAK,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;AAAA,YACxC;AAAA,UACF;AAAA,QACF;AAEA,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,wEAAiE;AAC5E,cAAM,KAAK,0EAAmE;AAAA,MAChF;AAEA,UAAI,WAAW;AACb,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,gCAAsB,SAAS,OAAO,OAAO,MAAM,6BAA6B;AAAA,MAC7F;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,iBAAiB;AAE5B,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AElLA,SAAS,KAAAC,WAAS;;;ACDX,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EACvC;AAAA,EAAW;AAAA,EAAgB;AAAA,EAC3B;AAAA,EAAW;AAAA,EAAgB;AAAA,EAC3B;AAAA,EAAY;AAAA,EAAiB;AAAA,EAC7B;AAAA,EAAY;AAAA,EAAY;AAAA,EACxB;AAAA,EAAY;AAAA,EAAY;AAAA,EAAW;AAAA,EAAW;AAAA,EAAY;AAAA,EAAW;AACvE,CAAC;AAEM,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EACtC;AAAA,EAAY;AAAA,EAAiB;AAAA,EAC7B;AAAA,EAAY;AACd,CAAC;;;ADUD,eAAe,kBAAkB,KAAgB,MAA2C;AAE1F,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,WAAW,KAAK,IAAI;AACtC,UAAM,WAAW,kBAAkB,IAAI,QAAQ;AAC/C,QAAI,CAAC,SAAU,QAAO;AACtB,qBAAiB,SAAS,WAAW;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,eAAe,WAAW,IAAI,MAAM,QAAQ,WAAW;AAAA,IAC5D,WAAW,KAAK,MAAM,cAAc;AAAA,IACpC,WAAW,KAAK,MAAM,cAAc;AAAA,EACtC,CAAC;AAED,MAAI,cAAc,WAAW,WAAY,QAAO;AAEhD,QAAM,UAAU,cAAc;AAC9B,QAAM,QAAQ,YAAY,WAAW,cAAc,YAAY,QAAQ,CAAC;AAExE,QAAM,aAAqC,CAAC;AAC5C,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,gBAAgB,CAAC;AAC7B,eAAW,GAAG,KAAK,WAAW,GAAG,KAAK,KAAK;AAAA,EAC7C;AAEA,QAAM,YAAY,iBAAiB,OAAO;AAC1C,QAAM,cAAc,cAAc,OAAO,MAAM,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI,IAAI;AAEzF,QAAM,YAAY,KAAK;AAAA,KACpB,KAAK,IAAI,IAAI,IAAI,KAAK,QAAQ,WAAW,EAAE,QAAQ,MAAM,MAAO,KAAK,KAAK;AAAA,EAC7E;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,YAAY,MAAM;AAAA,IAClB,gBAAgB,aAAa,WAAW,gBAAgB;AAAA,IACxD,OAAO,aAAa,cAAc;AAAA,IAClC,eAAe,gBAAgB;AAAA,IAC/B;AAAA,IACA,UAAU,QAAQ,YAAY,CAAC;AAAA,EACjC;AACF;AAEA,SAAS,YAAY,UAA4B;AAC/C,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,MAAI,SAAS,KAAK,CAAC,MAAM,kBAAkB,IAAI,CAAC,CAAC,EAAG,QAAO;AAC3D,SAAO;AACT;AAEA,SAAS,IAAI,GAAW,GAAmB;AACzC,SAAO,EAAE,UAAU,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,EAAE,MAAM;AACxD;AAEA,SAAS,OAAO,GAAW,GAAW,iBAAiB,MAAwB;AAC7E,MAAI,MAAM,EAAG,QAAO,CAAC,IAAI,EAAE;AAC3B,QAAM,QAAQ,iBAAiB,IAAI,IAAI,IAAI;AAC3C,SAAO,QAAQ,CAAC,UAAK,EAAE,IAAI,CAAC,IAAI,QAAG;AACrC;AAEO,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,WAAWC,IAAE,OAAO,EAAE,SAAS,oBAAoB;AAAA,QACnD,WAAWA,IAAE,OAAO,EAAE,SAAS,qBAAqB;AAAA,QACpD,WAAWA,IACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,WAAW,WAAW,UAAU,MAAM;AAC7C,YAAM,MAAM;AAEZ,YAAM,CAAC,OAAO,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,QACvC,kBAAkB,KAAK,SAAS;AAAA,QAChC,kBAAkB,KAAK,SAAS;AAAA,MAClC,CAAC;AAED,UAAI,CAAC,SAAS,CAAC,OAAO;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,yBAAyB,SAAS,OAAO,SAAS,OAAO,SAAS;AAAA,YAC1E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,kBAAkB,SAAS,OAAO,SAAS,IAAI;AAAA,UACvE;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,kBAAkB,SAAS,OAAO,SAAS,IAAI;AAAA,UACvE;AAAA,QACF;AAAA,MACF;AAEA,YAAM,MAAM;AACZ,YAAM,SAAS,CAAC,UACd,GAAG,IAAI,OAAO,EAAE,CAAC,GAAG,IAAI,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,MAAM,MAAM,GAAG,CAAC;AAEjE,YAAM,MAAM,CAAC,OAAe,MAAc,MAAc,KAAK,IAAI,KAAK,OACpE,KAAK,IAAI,OAAO,EAAE,CAAC,GAAG,IAAI,KAAK,GAAG,IAAI,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,IAAI,EAAE,KAAK,IAAI;AAE3F,YAAM,QAAkB;AAAA,QACtB,qCAA2B,SAAS;AAAA,QACpC,SAAI,OAAO,EAAE;AAAA,QACb,OAAO,EAAE;AAAA,QACT,OAAO,QAAQ;AAAA,QACf,SAAI,OAAO,EAAE;AAAA,MACf;AAGA,YAAM,KAAK,IAAI,kBAAkB,MAAM,SAAS,MAAM,OAAO,CAAC;AAG9D,YAAM,QAAQ,MAAM,eAAe,IAAI,SAAS,GAAG,MAAM,UAAU;AACnE,YAAM,QAAQ,MAAM,eAAe,IAAI,SAAS,GAAG,MAAM,UAAU;AACnE,YAAM,CAAC,KAAK,GAAG,IAAI,OAAO,MAAM,YAAY,MAAM,YAAY,KAAK;AACnE,YAAM,KAAK,IAAI,mBAAmB,OAAO,OAAO,KAAK,GAAG,CAAC;AAGzD,UAAI,MAAM,aAAa,KAAK,MAAM,aAAa,GAAG;AAChD,cAAM,SAAS,MAAM,WAAW,YAAY,MAAM,MAAM,WAAW,QAAQ;AAC3E,cAAM,SAAS,MAAM,WAAW,YAAY,MAAM,MAAM,WAAW,QAAQ;AAC3E,cAAM,KAAK,IAAI,mBAAmB,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC;AAAA,MACjE;AAGA,YAAM,MAAM,MAAM,mBAAmB,OAAO,MAAM,eAAe,QAAQ,CAAC,IAAI;AAC9E,YAAM,MAAM,MAAM,mBAAmB,OAAO,MAAM,eAAe,QAAQ,CAAC,IAAI;AAC9E,YAAM,CAAC,KAAK,GAAG,IACb,MAAM,mBAAmB,QAAQ,MAAM,mBAAmB,OACtD,OAAO,MAAM,gBAAgB,MAAM,cAAc,IACjD,CAAC,IAAI,EAAE;AACb,YAAM,KAAK,IAAI,qBAAqB,KAAK,KAAK,KAAK,GAAG,CAAC;AAGvD,YAAM,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,eAAe,IAAI;AAClE,YAAM,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,eAAe,IAAI;AAClE,YAAM,CAAC,MAAM,IAAI,IACf,MAAM,UAAU,QAAQ,MAAM,UAAU,OACpC,OAAO,MAAM,OAAO,MAAM,KAAK,IAC/B,CAAC,IAAI,EAAE;AACb,YAAM,KAAK,IAAI,gBAAgB,KAAK,KAAK,MAAM,IAAI,CAAC;AAGpD,YAAM,OAAO,GAAG,MAAM,SAAS;AAC/B,YAAM,OAAO,GAAG,MAAM,SAAS;AAC/B,YAAM,CAAC,KAAK,GAAG,IAAI,OAAO,MAAM,WAAW,MAAM,WAAW,KAAK;AACjE,YAAM,KAAK,IAAI,gBAAgB,MAAM,MAAM,KAAK,GAAG,CAAC;AAGpD,YAAM,OAAO,MAAM,SAAS,SAAS,IAAI,MAAM,SAAS,KAAK,IAAI,IAAI;AACrE,YAAM,OAAO,MAAM,SAAS,SAAS,IAAI,MAAM,SAAS,KAAK,IAAI,IAAI;AACrE,YAAM,KAAK,IAAI,WAAW,MAAM,IAAI,CAAC;AACrC,YAAM,KAAK,IAAI,gBAAgB,YAAY,MAAM,QAAQ,GAAG,YAAY,MAAM,QAAQ,CAAC,CAAC;AAGxF,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,YAAM,KAAK,gBAAgB;AAC3B,YAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AAEzB,UAAI,SAAS;AACb,UAAI,SAAS;AAGb,UAAI,MAAM,aAAa,MAAM,WAAY,WAAU;AAAA,eAC1C,MAAM,aAAa,MAAM,WAAY,WAAU;AAGxD,UAAI,MAAM,mBAAmB,QAAQ,MAAM,mBAAmB,MAAM;AAClE,YAAI,MAAM,iBAAiB,MAAM,eAAgB;AAAA,iBACxC,MAAM,iBAAiB,MAAM,eAAgB;AAAA,MACxD;AAGA,UAAI,MAAM,UAAU,QAAQ,MAAM,UAAU,MAAM;AAChD,YAAI,MAAM,QAAQ,MAAM,MAAO;AAAA,iBACtB,MAAM,QAAQ,MAAM,MAAO;AAAA,MACtC;AAGA,UAAI,MAAM,YAAY,MAAM,UAAW;AAAA,eAC9B,MAAM,YAAY,MAAM,UAAW;AAG5C,YAAM,MAAM,YAAY,MAAM,QAAQ;AACtC,YAAM,MAAM,YAAY,MAAM,QAAQ;AACtC,UAAI,QAAQ,gBAAgB,QAAQ,aAAc;AAAA,eACzC,QAAQ,gBAAgB,QAAQ,aAAc;AAEvD,UAAI,SAAS,QAAQ;AACnB,cAAM,KAAK,iBAAY,MAAM,IAAI,oBAAe,MAAM,gBAAgB;AAAA,MACxE,WAAW,SAAS,QAAQ;AAC1B,cAAM,KAAK,iBAAY,MAAM,IAAI,oBAAe,MAAM,gBAAgB;AAAA,MACxE,OAAO;AACL,cAAM,KAAK,mDAA4C,MAAM,IAAI,MAAM,YAAY;AAAA,MACrF;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,4BAA4B;AAEvC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AEpPA,SAAS,KAAAC,WAAS;AAOlB,IAAM,oBAAoE;AAAA,EACxE,YAAY,oBAAI,IAAI;AAAA,IAClB;AAAA,IAAO;AAAA,IAAO;AAAA,IAAgB;AAAA,IAAgB;AAAA,IAAc;AAAA,IAC5D;AAAA,IAAa;AAAA,IAAW;AAAA,IAAiB;AAAA,EAC3C,CAAC;AAAA,EACD,UAAU,oBAAI,IAAI;AAAA,IAChB;AAAA,IAAO;AAAA,IAAO;AAAA,IAAgB;AAAA,IAAgB;AAAA,IAAc;AAAA,IAC5D;AAAA,IAAa;AAAA,IAAW;AAAA,IAAiB;AAAA,IACzC;AAAA,IAAY;AAAA,IAAY;AAAA,IAAY;AAAA,IAAW;AAAA,IAAW;AAAA,IAC1D;AAAA,IAAW;AAAA,IAAgB;AAAA,IAC3B;AAAA,IAAW;AAAA,IAAgB;AAAA,IAC3B;AAAA,IAAY;AAAA,EACd,CAAC;AACH;AAEA,SAAS,gBAAgB,SAA+F;AACtH,MAAI,iBAAiB,IAAI,OAAO,EAAG,QAAO;AAC1C,MAAI,kBAAkB,IAAI,OAAO,GAAG;AAClC,QAAI,QAAQ,WAAW,MAAM,KAAK,YAAY,aAAa,YAAY,aAAa,YAAY,aAAa,YAAY,YAAY;AACnI,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,MAAI,kBAAkB,WAAW,IAAI,OAAO,EAAG,QAAO;AACtD,SAAO;AACT;AAEA,IAAM,YAAY;AAEX,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,kBAAkBC,IAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,QACzE,eAAeA,IACZ,OAAO,EACP,SAAS,8FAA8F;AAAA,QAC1G,QAAQA,IACL,KAAK,CAAC,cAAc,YAAY,MAAM,CAAC,EACvC,QAAQ,YAAY,EACpB;AAAA,UACC;AAAA,QACF;AAAA,MACJ;AAAA,IACF;AAAA,IACA,OAAO,EAAE,kBAAkB,eAAe,OAAO,MAAM;AACrD,YAAM,OAAO,cAAc,eAAe,gBAAgB;AAE1D,UAAI,SAAS,MAAM;AACjB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,gCAAgC,aAAa;AAAA;AAAA;AAAA,YACrD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,GAAG;AACrB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,4BAA4B,aAAa,IAAI,CAAC;AAAA,QAChF;AAAA,MACF;AAGA,YAAM,OAAO,oBAAI,IAAY;AAC7B,YAAM,SAAS,KAAK,OAAO,CAAC,MAAM;AAChC,cAAM,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO;AAClC,YAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,aAAK,IAAI,GAAG;AACZ,eAAO;AAAA,MACT,CAAC;AAED,YAAM,UAAU,OAAO,MAAM,GAAG,SAAS;AACzC,YAAM,YAAY,OAAO,SAAS;AAGlC,YAAM,iBAAiB,MAAM,QAAQ;AAAA,QACnC,QAAQ,IAAI,CAAC,MAAM,WAAW,EAAE,WAAwB,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,MAC5E;AAWA,YAAM,YAAY,WAAW,SAAS,kBAAkB,MAAM,IAAI;AAClE,YAAM,UAA2B,CAAC;AAClC,YAAM,eAAuC,CAAC;AAE9C,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,cAAM,MAAM,QAAQ,CAAC;AACrB,YAAI,CAAC,IAAK;AACV,cAAM,SAAS,eAAe,CAAC;AAC/B,cAAM,WACJ,QAAQ,WAAW,cAAe,OAAO,MAAM,YAAY,CAAC,IAAK,CAAC;AAGpE,mBAAW,KAAK,UAAU;AACxB,uBAAa,CAAC,KAAK,aAAa,CAAC,KAAK,KAAK;AAAA,QAC7C;AAGA,YAAIC,WAAU;AACd,YAAI,SAAS;AAEb,YAAI,SAAS,WAAW,GAAG;AACzB,UAAAA,WAAU,WAAW;AACrB,mBAAS;AAAA,QACX,WAAW,WAAW;AACpB,gBAAM,YAAY,SAAS,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;AAC1D,cAAI,UAAU,SAAS,GAAG;AACxB,YAAAA,WAAU;AACV,qBAAS,6BAA6B,MAAM,YAAY,UAAU,KAAK,IAAI,CAAC;AAAA,UAC9E;AAAA,QACF;AAEA,cAAM,iBAAiB,SAAS,WAAW,IACvC,YACA,SAAS,IAAI,eAAe,EAAE,KAAK,IAAI;AAE3C,YAAIA,YAAW,SAAS,KAAK,CAAC,MAAM,gBAAgB,CAAC,MAAM,YAAY,GAAG;AACxE,kBAAQ,KAAK,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,SAAS,UAAU,gBAAgB,SAAAA,UAAS,OAAO,CAAC;AAAA,QAClG;AAAA,MACF;AAEA,YAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO;AAC/C,YAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO;AAEjD,YAAM,QAAkB;AAAA,QACtB;AAAA,QACA,SAAI,OAAO,EAAE;AAAA,QACb,cAAc,aAAa;AAAA,QAC3B,cAAc,MAAM;AAAA,QACpB,cAAc,QAAQ,MAAM,YAAY,YAAY,WAAW,SAAS,OAAO,OAAO,MAAM,MAAM,EAAE;AAAA,QACpG;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,KAAK,oCAA+B;AAC1C,YAAI,WAAW,QAAQ;AACrB,gBAAM,KAAK,2CAA2C,MAAM,UAAU;AAAA,QACxE;AAAA,MACF,OAAO;AACL,cAAM,KAAK,iBAAO,QAAQ,MAAM,qBAAqB,QAAQ,WAAW,IAAI,KAAK,GAAG,QAAQ;AAC5F,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,mBAAW,KAAK,SAAS;AACvB,gBAAM,MAAM,EAAE,SAAS,SAAS,IAAI,EAAE,SAAS,KAAK,IAAI,IAAI;AAC5D,gBAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE;AACrC,gBAAM,KAAK,gBAAgB,GAAG,EAAE;AAChC,gBAAM,KAAK,OAAO,EAAE,MAAM,EAAE;AAC5B,gBAAM,KAAK,EAAE;AAAA,QACf;AAAA,MACF;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,2CAA2C;AACtD,mBAAW,KAAK,UAAU;AACxB,gBAAM,MAAM,EAAE,SAAS,KAAK,IAAI;AAChC,gBAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO,KAAK,GAAG,EAAE;AAAA,QAC/C;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAGA,YAAM,cAAc,OAAO,QAAQ,YAAY,EAC5C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,CAAC;AAEb,UAAI,YAAY,SAAS,GAAG;AAC1B,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,cAAM,KAAK,uBAAuB;AAClC,mBAAW,CAAC,KAAK,KAAK,KAAK,aAAa;AACtC,gBAAM,KAAK,KAAK,OAAO,KAAK,EAAE,SAAS,CAAC,CAAC,SAAM,GAAG,EAAE;AAAA,QACtD;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,YAAM,KAAK,kBAAkB;AAE7B,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;ACzMA,SAAS,KAAAC,WAAS;AAQX,SAASC,UAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,IAAE,OAAO,EAAE,SAAS,cAAc;AAAA,QACxC,SAASA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sCAAsC;AAAA,QAC9E,WAAWA,IACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AACtC,YAAM,MAAM;AAGZ,UAAI,kBAAkB,WAAW;AACjC,UAAI,CAAC,iBAAiB;AACpB,YAAI;AACF,gBAAMC,OAAM,MAAM,WAAW,KAAK,IAAI;AACtC,gBAAM,WAAW,kBAAkBA,KAAI,QAAQ;AAC/C,4BAAkB,UAAU,WAAW,WAAW;AAAA,QACpD,QAAQ;AACN,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,iCAA4B,IAAI,OAAO,SAAS;AAAA,cACxD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,0CAAqC,IAAI,OAAO,SAAS,IAAI;AAAA,UACrF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,CAAC,eAAe,WAAW,IAAI,MAAM,QAAQ,WAAW;AAAA,QAC5D,WAAW,KAAK,MAAM,eAAe;AAAA,QACrC,WAAW,KAAK,MAAM,eAAe;AAAA,MACvC,CAAC;AAED,UAAI,cAAc,WAAW,YAAY;AACvC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,yBAAoB,IAAI,IAAI,eAAe,OAAO,SAAS;AAAA,YACnE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,MAAM,cAAc;AAC1B,YAAM,QAAQ,YAAY,WAAW,cAAc,YAAY,QAAQ,CAAC;AAExE,YAAM,YAAY,iBAAiB,GAAG;AACtC,YAAM,cAAc,cAAc,OAAO,MAAM,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI,IAAI;AAGzF,YAAM,SAAkE,CAAC;AAGzE,YAAM,gBAAgB,MAAM,OAAO,CAAC,MAAM;AACxC,cAAM,MAAM,gBAAgB,CAAC;AAC7B,eAAO,QAAQ,cAAc,QAAQ;AAAA,MACvC,CAAC;AACD,UAAI,cAAc,SAAS,GAAG;AAC5B,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,GAAG,cAAc,MAAM,8BAA8B,cAAc,WAAW,IAAI,MAAM,KAAK;AAAA,QACxG,CAAC;AAAA,MACH,WAAW,MAAM,SAAS,GAAG;AAC3B,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,GAAG,MAAM,MAAM,6BAA6B,MAAM,WAAW,IAAI,MAAM,KAAK;AAAA,QACvF,CAAC;AAAA,MACH;AAGA,YAAM,cAAwB,CAAC;AAC/B,UAAI,UAAU,KAAK,IAAI,EAAG,aAAY,KAAK,6CAA6C;AACxF,UAAI,KAAK,UAAU,EAAG,aAAY,KAAK,iBAAiB;AACxD,UAAI,YAAY,KAAK,IAAI,EAAG,aAAY,KAAK,qBAAqB;AAClE,UAAI,iBAAiB,KAAK,IAAI,EAAG,aAAY,KAAK,4BAA4B;AAC9E,UAAI,YAAY,UAAU,GAAG;AAC3B,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,gCAAgC,YAAY,KAAK,IAAI,CAAC;AAAA,QACjE,CAAC;AAAA,MACH;AAGA,YAAM,YAAY,KAAK;AAAA,SACpB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,WAAW,EAAE,QAAQ,MAAM,MAAO,KAAK,KAAK;AAAA,MACzE;AACA,UAAI,YAAY,KAAK;AACnB,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,sBAAsB,KAAK,MAAM,YAAY,GAAG,CAAC;AAAA,QAC5D,CAAC;AAAA,MACH;AAGA,UAAI,aAAa,aAAa,QAAQ,YAAY,UAAU,eAAe,GAAG;AAC5E,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,gCAAgC,YAAY,UAAU,aAAa,QAAQ,CAAC,CAAC;AAAA,QACxF,CAAC;AAAA,MACH,WAAW,gBAAgB,MAAM;AAC/B,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAGA,YAAM,WAAW,IAAI,YAAY,CAAC;AAClC,UAAI,SAAS,WAAW,GAAG;AACzB,eAAO,KAAK,EAAE,OAAO,QAAQ,SAAS,kBAAkB,CAAC;AAAA,MAC3D,WAAW,SAAS,KAAK,CAAC,MAAM,kBAAkB,IAAI,CAAC,CAAC,GAAG;AACzD,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,SAAS,8BAA8B,SAAS,KAAK,IAAI,CAAC;AAAA,QAC5D,CAAC;AAAA,MACH;AAGA,YAAM,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,OAAO;AACzD,YAAM,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM;AACxD,YAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM;AAErD,YAAM,UAAU,SAAS,SAAS,IAAI,UAAU,SAAS,SAAS,IAAI,YAAY;AAClF,YAAM,eAAe,YAAY,OAAO,WAAM,YAAY,YAAY,iBAAO;AAE7E,YAAM,QAAkB;AAAA,QACtB,GAAG,YAAY,uBAAuB,IAAI,IAAI,eAAe,KAAK,SAAS;AAAA,QAC3E,SAAI,OAAO,EAAE;AAAA,QACb,YAAY,OAAO;AAAA,QACnB;AAAA,MACF;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,oBAAa;AACxB,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,mBAAW,SAAS,UAAU;AAC5B,gBAAM,KAAK,YAAO,MAAM,OAAO,EAAE;AAAA,QACnC;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,wBAAc;AACzB,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,mBAAW,SAAS,UAAU;AAC5B,gBAAM,KAAK,YAAO,MAAM,OAAO,EAAE;AAAA,QACnC;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,KAAK,oBAAU;AACrB,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AACzB,mBAAW,SAAS,OAAO;AACzB,gBAAM,KAAK,YAAO,MAAM,OAAO,EAAE;AAAA,QACnC;AACA,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,UAAI,SAAS,WAAW,KAAK,SAAS,WAAW,GAAG;AAClD,cAAM,KAAK,2CAAsC;AACjD,cAAM,KAAK,EAAE;AAAA,MACf;AAEA,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,KAAK,2DAAoD;AAAA,MACjE;AACA,UAAI,SAAS,SAAS,GAAG;AACvB,cAAM,KAAK,qDAA8C;AAAA,MAC3D;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,4BAA4B;AAEvC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AC7MA,SAAS,KAAAC,WAAS;AAOlB,SAAS,YAAY,OAAuB;AAC1C,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;AAEA,SAAS,WAAW,OAAuB;AACzC,UAAQ,OAAO;AAAA,IACb,KAAK;AAAK,aAAO;AAAA,IACjB,KAAK;AAAK,aAAO;AAAA,IACjB,KAAK;AAAK,aAAO;AAAA,IACjB,KAAK;AAAK,aAAO;AAAA,IACjB;AAAU,aAAO;AAAA,EACnB;AACF;AAEO,SAASC,WAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,IAAE,OAAO,EAAE,SAAS,cAAc;AAAA,QACxC,SAASA,IAAE,OAAO,EAAE,SAAS,iBAAiB;AAAA,QAC9C,WAAWA,IACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AACtC,YAAM,MAAM;AAEZ,YAAM,CAAC,eAAe,WAAW,IAAI,MAAM,QAAQ,WAAW;AAAA,QAC5D,WAAW,KAAK,MAAM,OAAO;AAAA,QAC7B,WAAW,KAAK,MAAM,OAAO;AAAA,MAC/B,CAAC;AAED,UAAI,cAAc,WAAW,YAAY;AACvC,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,kBAAkB,IAAI,IAAI,OAAO,OAAO,SAAS;AAAA,YACzD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,MAAM,cAAc;AAC1B,YAAM,QAAQ,YAAY,WAAW,cAAc,YAAY,QAAQ,CAAC;AAExE,YAAM,YAAY,iBAAiB,GAAG;AACtC,YAAM,cAAc,cAAc,OAAO,MAAM,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI,IAAI;AAKzF,UAAI,YAAY;AAChB,iBAAW,KAAK,OAAO;AACrB,cAAM,MAAM,gBAAgB,CAAC;AAC7B,gBAAQ,KAAK;AAAA,UACX,KAAK;AAAY,yBAAa;AAAI;AAAA,UAClC,KAAK;AAAY,yBAAa;AAAI;AAAA,UAClC,KAAK;AAAY,yBAAa;AAAI;AAAA,UAClC,KAAK;AAAY,yBAAa;AAAI;AAAA,QACpC;AAAA,MACF;AACA,kBAAY,KAAK,IAAI,GAAG,SAAS;AAGjC,UAAI,iBAAiB;AACrB,UAAI,aAAa,aAAa,MAAM;AAClC,yBAAiB,KAAK,MAAO,YAAY,UAAU,eAAe,KAAM,EAAE;AAAA,MAC5E,WAAW,gBAAgB,MAAM;AAC/B,yBAAiB;AAAA,MACnB;AAGA,UAAI,eAAe;AACnB,YAAM,YAAY,KAAK;AAAA,SACpB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,WAAW,EAAE,QAAQ,MAAM,MAAO,KAAK,KAAK;AAAA,MACzE;AACA,UAAI,YAAY,IAAK,gBAAe;AAAA,eAC3B,YAAY,IAAK,gBAAe;AAAA,eAChC,YAAY,IAAK,gBAAe;AAGzC,UAAI,eAAe;AACnB,YAAM,WAAW,IAAI,YAAY,CAAC;AAClC,UAAI,SAAS,WAAW,GAAG;AACzB,uBAAe;AAAA,MACjB,WAAW,SAAS,KAAK,CAAC,MAAM,kBAAkB,IAAI,CAAC,CAAC,GAAG;AACzD,uBAAe;AAAA,MACjB;AAEA,YAAM,QAAQ,YAAY,iBAAiB,eAAe;AAC1D,YAAM,QAAQ,YAAY,KAAK;AAC/B,YAAM,QAAQ,WAAW,KAAK;AAE9B,YAAM,QAAkB;AAAA,QACtB,GAAG,KAAK,iBAAiB,KAAK,qBAAgB,KAAK;AAAA,QACnD,MAAM,IAAI,IAAI,OAAO,KAAK,SAAS;AAAA,QACnC,SAAI,OAAO,EAAE;AAAA,QACb;AAAA,QACA;AAAA,QACA,SAAI,OAAO,EAAE;AAAA,QACb,yBAAyB,UAAU,SAAS,EAAE,SAAS,CAAC,CAAC;AAAA,QACzD,yBAAyB,eAAe,SAAS,EAAE,SAAS,CAAC,CAAC;AAAA,QAC9D,yBAAyB,aAAa,SAAS,EAAE,SAAS,CAAC,CAAC;AAAA,QAC5D,yBAAyB,aAAa,SAAS,EAAE,SAAS,CAAC,CAAC;AAAA,QAC5D,yBAAyB,SAAI,OAAO,CAAC,CAAC;AAAA,QACtC,yBAAyB,MAAM,SAAS,EAAE,SAAS,CAAC,CAAC;AAAA,QACrD;AAAA,MACF;AAGA,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,SAAiC,CAAC;AACxC,mBAAW,KAAK,OAAO;AACrB,gBAAM,MAAM,gBAAgB,CAAC;AAC7B,iBAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AAAA,QACrC;AACA,cAAM,UAAU,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,EAAE,KAAK,IAAI;AAC3F,cAAM,KAAK,iBAAO,MAAM,MAAM,mBAAmB,OAAO,EAAE;AAAA,MAC5D,OAAO;AACL,cAAM,KAAK,iCAA4B;AAAA,MACzC;AAEA,UAAI,aAAa,aAAa,MAAM;AAClC,cAAM,KAAK,gCAAyB,YAAY,UAAU,aAAa,QAAQ,CAAC,CAAC,KAAK;AAAA,MACxF,WAAW,gBAAgB,MAAM;AAC/B,cAAM,KAAK,mDAAyC;AAAA,MACtD;AAEA,YAAM,KAAK,uBAAgB,SAAS,WAAW;AAE/C,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,KAAK,+BAAqB;AAAA,MAClC,WAAW,SAAS,KAAK,CAAC,MAAM,kBAAkB,IAAI,CAAC,CAAC,GAAG;AACzD,cAAM,KAAK,mCAAyB,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,MAC3D,OAAO;AACL,cAAM,KAAK,mBAAc,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,MAChD;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,4BAA4B;AAEvC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;ACnKA,SAAS,KAAAC,WAAS;AAMlB,SAAS,aAAa,GAAqB;AACzC,SAAO,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,SAAS,EAAE,QAAQ,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC;AAC5E;AAEA,SAAS,gBAAgB,GAAW,GAAmB;AACrD,QAAM,KAAK,aAAa,CAAC;AACzB,QAAM,KAAK,aAAa,CAAC;AACzB,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK;AACvD,UAAM,QAAQ,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,KAAK;AACtC,QAAI,SAAS,EAAG,QAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEO,SAASC,WAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,IAAE,OAAO,EAAE,SAAS,qCAAqC;AAAA,QAC/D,SAASA,IAAE,OAAO,EAAE,SAAS,2CAA2C;AAAA,QACxE,WAAWA,IACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AACtC,YAAM,MAAM;AAEZ,UAAI;AACJ,UAAI;AACF,cAAM,MAAM,WAAW,KAAK,IAAI;AAAA,MAClC,QAAQ;AACN,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,0BAA0B,IAAI,OAAO,SAAS;AAAA,YACtD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,aAAa,IAAI,SACpB,IAAI,CAAC,MAAM,EAAE,WAAW,OAAO,EAC/B,OAAO,CAAC,MAAM,gBAAgB,GAAG,OAAO,IAAI,CAAC,EAC7C,KAAK,eAAe;AAEvB,UAAI,WAAW,WAAW,GAAG;AAC3B,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,sCAA4B,IAAI,aAAa,SAAS;AAAA,mBAAuB,OAAO;AAAA;AAAA;AAAA,YAC5F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,WAAW,MAAM,GAAG,EAAE;AACtC,YAAM,cAAc,MAAM;AAAA,QACxB,QAAQ,IAAI,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,SAAS,EAAE,EAAE;AAAA,MAC3D;AAEA,YAAM,eAAe,QAAQ,OAAO,CAAC,GAAG,OAAO,YAAY,CAAC,GAAG,UAAU,OAAO,CAAC;AACjF,YAAM,gBAAgB,WAAW,GAAG,EAAE,KAAK;AAC3C,YAAM,cAAc,YAAY,QAAQ,QAAQ,aAAa,CAAC,KAAK,CAAC;AAEpE,YAAM,QAAkB;AAAA,QACtB,kCAA2B,IAAI,KAAK,SAAS;AAAA,QAC7C,SAAI,OAAO,EAAE;AAAA,QACb,oBAAoB,OAAO;AAAA,QAC3B,uBAAuB,QAAQ,MAAM,OAAO,WAAW,MAAM;AAAA,QAC7D;AAAA,MACF;AAEA,UAAI,aAAa,WAAW,GAAG;AAC7B,cAAM,KAAK,2CAAiC,QAAQ,MAAM,6CAA6C;AACvG,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,WAAW;AACtB,cAAM,KAAK,kEAA6D;AACxE,cAAM,KAAK,8DAAyD;AAAA,MACtE,OAAO;AACL,cAAM,UAAU,aAAa,CAAC,KAAK;AACnC,cAAM,SAAS,aAAa,GAAG,EAAE,KAAK;AAEtC,cAAM,KAAK,+BAA0B;AACrC,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,2BAA2B,OAAO,EAAE;AAC/C,YAAI,YAAY,QAAQ;AACtB,gBAAM,KAAK,2BAA2B,MAAM,EAAE;AAAA,QAChD;AACA,cAAM,KAAK,EAAE;AAEb,YAAI,YAAY,SAAS,KAAK,aAAa,GAAG,EAAE,MAAM,eAAe;AACnE,gBAAM,KAAK,iCAAuB,aAAa,eAAe,YAAY,MAAM,iBAAiB;AACjG,gBAAM,KAAK,8BAA8B,MAAM,EAAE;AAAA,QACnD,OAAO;AACL,gBAAM,KAAK,qCAA8B,MAAM,EAAE;AAAA,QACnD;AAGA,cAAM,cAAc,QAAQ,OAAO,CAAC,GAAG,OAAO,YAAY,CAAC,GAAG,UAAU,KAAK,CAAC,EAAE;AAChF,YAAI,cAAc,GAAG;AACnB,gBAAM,KAAK,OAAO,WAAW,2DAAsD;AAAA,QACrF;AAAA,MACF;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,4BAA4B;AAEvC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AC/HA,SAAS,KAAAC,WAAS;AAKlB,IAAMC,iBAAwC;AAAA,EAC5C,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,KAAK;AAAA,EACL,SAAS;AACX;AAEO,SAASC,WAAS,QAAmB;AAC1C,SAAO,OAAO;AAAA,IACZ;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,aAAa;AAAA,QACX,MAAMC,IAAE,OAAO,EAAE,SAAS,qCAAqC;AAAA,QAC/D,SAASA,IAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,QAC5D,WAAWA,IACR,KAAK,gBAAgB,EACrB,QAAQ,KAAK,EACb,SAAS,kCAAkC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,OAAO,EAAE,MAAM,SAAS,UAAU,MAAM;AACtC,UAAI;AACJ,UAAI;AACF,gBAAQ,MAAM,WAAW,WAAwB,MAAM,OAAO;AAAA,MAChE,QAAQ;AACN,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,uCAAuC,IAAI,IAAI,OAAO;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,6CAAwC,IAAI,IAAI,OAAO,KAAK,SAAS;AAAA;AAAA;AAAA,YAC7E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,aAA2C;AAAA,QAC/C,UAAU,CAAC;AAAA,QACX,MAAM,CAAC;AAAA,QACP,UAAU,CAAC;AAAA,QACX,KAAK,CAAC;AAAA,QACN,SAAS,CAAC;AAAA,MACZ;AAEA,iBAAW,QAAQ,OAAO;AACxB,cAAM,MAAM,gBAAgB,IAAI;AAChC,mBAAW,GAAG,GAAG,KAAK,IAAI;AAAA,MAC5B;AAEA,YAAM,QAAkB;AAAA,QACtB,gCAAyB,IAAI,IAAI,OAAO,KAAK,SAAS;AAAA,QACtD,SAAI,OAAO,EAAE;AAAA,QACb,SAAS,MAAM,MAAM,iBAAiB,MAAM,WAAW,IAAI,KAAK,KAAK;AAAA,QACrE;AAAA,MACF;AAEA,iBAAW,YAAY,CAAC,YAAY,QAAQ,YAAY,OAAO,SAAS,GAAG;AACzE,cAAM,QAAQ,WAAW,QAAQ,KAAK,CAAC;AACvC,YAAI,MAAM,WAAW,EAAG;AAExB,cAAM,OAAOF,eAAc,QAAQ,KAAK;AACxC,cAAM,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,MAAM,GAAG;AAClD,cAAM,KAAK,SAAI,OAAO,EAAE,CAAC;AAEzB,mBAAW,QAAQ,OAAO;AACxB,gBAAM,KAAK,KAAK,KAAK,EAAE,EAAE;AACzB,gBAAM,KAAK,KAAK,KAAK,OAAO,EAAE;AAE9B,gBAAM,QAAQ,mBAAmB,MAAM,SAAsB;AAC7D,cAAI,MAAM,SAAS,GAAG;AACpB,kBAAM,KAAK,qBAAqB,MAAM,KAAK,MAAM,CAAC,EAAE;AAAA,UACtD,OAAO;AACL,kBAAM,KAAK,qCAAqC;AAAA,UAClD;AAEA,cAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC3C,kBAAM,KAAK,oBAAoB,KAAK,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,UAC1D;AAEA,gBAAM,KAAK,gBAAgB,KAAK,UAAU,MAAM,GAAG,EAAE,CAAC,EAAE;AACxD,gBAAM,KAAK,EAAE;AAAA,QACf;AAAA,MACF;AAEA,YAAM,KAAK,yBAAyB;AAEpC,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AtB/FA,IAAM,cAAc;AACpB,IAAM,iBAAiB;AAEhB,SAAS,eAA0B;AACxC,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAED,EAAAG,WAAc,MAAM;AACpB,EAAAA,UAAgB,MAAM;AACtB,EAAAA,UAAa,MAAM;AACnB,EAAAA,UAAkB,MAAM;AACxB,WAAmB,MAAM;AACzB,EAAAA,UAAgB,MAAM;AACtB,EAAAA,UAAc,MAAM;AACpB,EAAAA,UAAgB,MAAM;AACtB,EAAAA,UAAqB,MAAM;AAC3B,EAAAA,UAAmB,MAAM;AACzB,EAAAA,WAAc,MAAM;AACpB,EAAAA,WAAgB,MAAM;AACtB,kBAAgB,MAAM;AAEtB,SAAO;AACT;;;ADpCA,eAAe,OAAsB;AACnC,QAAM,SAAS,aAAa;AAC5B,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,QAAiB;AAC7B,UAAQ,MAAM,gBAAgB,GAAG;AACjC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["z","z","z","BASE_URL","ECOSYSTEM_MAP","z","z","register","z","z","register","z","z","register","z","z","register","z","z","register","z","z","register","z","z","register","z","flagged","z","register","z","pkg","z","register","z","z","register","z","z","SEVERITY_ICON","register","z","register"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hound-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"mcpName": "io.github.tiluckdave/hound",
|
|
5
5
|
"description": "The dependency bloodhound for AI coding agents. Sniffs out vulnerabilities, license risks, and health issues in your dependencies — free, no API keys.",
|
|
6
6
|
"keywords": [
|