@quantakrypto/mcp 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -5
- package/dist/index.d.ts +1 -1
- package/dist/resources.d.ts +39 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +75 -0
- package/dist/resources.js.map +1 -0
- package/dist/rules.d.ts +18 -13
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +55 -75
- package/dist/rules.js.map +1 -1
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +43 -1
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +6 -6
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +600 -11
- package/dist/tools.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -142,6 +142,53 @@ tooling. Reads the filesystem, so it is gated like `scan_path` over HTTP.
|
|
|
142
142
|
}
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
## Copilot tools — migrate through the engine
|
|
146
|
+
|
|
147
|
+
These let an AI coding agent do a PQC migration **through the deterministic
|
|
148
|
+
engine** ("the model proposes, the engine disposes"): the agent plans, edits,
|
|
149
|
+
and re-verifies against the same detectors the CLI uses, so nothing is claimed
|
|
150
|
+
fixed that the scanner still flags.
|
|
151
|
+
|
|
152
|
+
- **`plan_migration`** — scan a path and return a prioritized, phased plan
|
|
153
|
+
(harvest-now-decrypt-later first, then signatures, then transport/certs), each
|
|
154
|
+
group with its PQC target and locations. Reads the filesystem, so it is gated
|
|
155
|
+
like `scan_path` over HTTP. `{ path }`.
|
|
156
|
+
- **`get_fix_examples`** — before/after migration code for a classical
|
|
157
|
+
`algorithm` (or a finding's `ruleId`). No filesystem access.
|
|
158
|
+
- **`verify_fix`** — run the detectors over a `code` snippet (plus `language` or
|
|
159
|
+
`filename`) and report any classical crypto that remains. The agent's
|
|
160
|
+
fix-confirmation loop. No filesystem access.
|
|
161
|
+
- **`check_dependency`** — look a package `name` (+ `ecosystem`, default npm) up
|
|
162
|
+
in the vulnerable-dependency database. No filesystem access.
|
|
163
|
+
- **`score_delta`** — readiness-score / HNDL change between two finding sets
|
|
164
|
+
(`before`, `after` from `scan_path --format json`). No filesystem access.
|
|
165
|
+
- **`triage_findings`** — deterministic, offline, key-free. Emits a triage
|
|
166
|
+
REQUEST bundle (rubric + verdict schema + per-finding metadata + fingerprints)
|
|
167
|
+
for the host agent to reason over. It never calls a model. No filesystem access.
|
|
168
|
+
- **`apply_triage`** — deterministically attach the host agent's verdicts to
|
|
169
|
+
their findings (matched by fingerprint) and re-sort by exposure. Never
|
|
170
|
+
suppresses; malformed verdicts are ignored. No filesystem access.
|
|
171
|
+
- **`remediate_findings`** — deterministic, offline, key-free. Emits a fix
|
|
172
|
+
REQUEST bundle (rubric + fix schema + per-finding metadata + fingerprints) for
|
|
173
|
+
the host agent to fix: propose the corrected file, verify with `verify_fix`,
|
|
174
|
+
keep only verified fixes. Never merges. No filesystem access.
|
|
175
|
+
|
|
176
|
+
> Triage on the MCP plane keeps the "engine disposes" guarantee: the server
|
|
177
|
+
> stays offline and never holds an API key — the host agent (which already has
|
|
178
|
+
> the code open) does the reasoning, and `apply_triage` records it
|
|
179
|
+
> deterministically. The BYOK client that calls a provider directly lives only
|
|
180
|
+
> in `qscan --triage` (for CI, where there is no host agent).
|
|
181
|
+
|
|
182
|
+
## Resources & prompts
|
|
183
|
+
|
|
184
|
+
Beyond tools, the server exposes MCP **resources** and a **prompt** (advertised in
|
|
185
|
+
the `initialize` capabilities, all offline/static):
|
|
186
|
+
|
|
187
|
+
- `resources/list` + `resources/read` — `quantakrypto://rules` (the full rule
|
|
188
|
+
catalog as JSON) and `quantakrypto://guide/migration` (a Markdown migration guide).
|
|
189
|
+
- `prompts/list` + `prompts/get` — the `migrate` prompt (optional `path` arg): a
|
|
190
|
+
ready-made "scan → triage → remediate → verify, draft PR only" workflow.
|
|
191
|
+
|
|
145
192
|
## Hosted HTTP server (safe-by-default)
|
|
146
193
|
|
|
147
194
|
The same `McpServer` can be served over HTTP (a Streamable-HTTP-style JSON-RPC
|
|
@@ -155,11 +202,13 @@ is reachable by untrusted peers:
|
|
|
155
202
|
- **Bearer-token auth.** Set `QUANTAKRYPTO_MCP_TOKEN` and every `/mcp` request must
|
|
156
203
|
send `Authorization: Bearer <token>`, else `401`. With no token set, only the
|
|
157
204
|
loopback bind is allowed.
|
|
158
|
-
- **Filesystem tools are disabled by default.** `scan_path`, `inventory_crypto
|
|
159
|
-
and `
|
|
160
|
-
only when `QUANTAKRYPTO_MCP_ALLOW_FS=1`. The knowledge
|
|
161
|
-
|
|
162
|
-
`
|
|
205
|
+
- **Filesystem tools are disabled by default.** `scan_path`, `inventory_crypto`,
|
|
206
|
+
`generate_cbom` and `plan_migration` read arbitrary server paths, so over HTTP
|
|
207
|
+
they are exposed only when `QUANTAKRYPTO_MCP_ALLOW_FS=1`. The knowledge /
|
|
208
|
+
copilot tools that take no path (`explain_finding`, `suggest_hybrid`,
|
|
209
|
+
`list_rules`, `get_fix_examples`, `verify_fix`, `check_dependency`,
|
|
210
|
+
`score_delta`, `triage_findings`, `apply_triage`, `remediate_findings`) are
|
|
211
|
+
always available. `tools/list` and `tools/call` both reflect the gating.
|
|
163
212
|
- **Filesystem tools are root-confined.** Even with `QUANTAKRYPTO_MCP_ALLOW_FS=1`,
|
|
164
213
|
every scanned path must resolve inside the `QUANTAKRYPTO_MCP_ROOT` allow-list
|
|
165
214
|
(`:`-separated; the process CWD by default). `..` traversal and out-of-root
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type { JsonRpcRequest, JsonRpcResponse, JsonRpcSuccess, JsonRpcFailure, T
|
|
|
16
16
|
/** The MCP server name advertised to clients. */
|
|
17
17
|
export declare const SERVER_NAME = "quantakrypto";
|
|
18
18
|
/** The version reported by the server (kept in sync with @quantakrypto/core). */
|
|
19
|
-
export declare const SERVER_VERSION = "0.
|
|
19
|
+
export declare const SERVER_VERSION = "0.4.0";
|
|
20
20
|
export interface CreateServerOptions {
|
|
21
21
|
/** Override the advertised server version (defaults to @quantakrypto/core VERSION). */
|
|
22
22
|
version?: string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** A resource descriptor for `resources/list`. */
|
|
2
|
+
export interface ResourceDescriptor {
|
|
3
|
+
uri: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const RESOURCES: ResourceDescriptor[];
|
|
9
|
+
/** Read a resource body by URI, or null when the URI is unknown. */
|
|
10
|
+
export declare function readResource(uri: string): {
|
|
11
|
+
uri: string;
|
|
12
|
+
mimeType: string;
|
|
13
|
+
text: string;
|
|
14
|
+
} | null;
|
|
15
|
+
/** A prompt descriptor for `prompts/list`. */
|
|
16
|
+
export interface PromptDescriptor {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
arguments?: {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
export declare const PROMPTS: PromptDescriptor[];
|
|
26
|
+
/** A prompt message (MCP `prompts/get` shape). */
|
|
27
|
+
export interface PromptMessage {
|
|
28
|
+
role: "user";
|
|
29
|
+
content: {
|
|
30
|
+
type: "text";
|
|
31
|
+
text: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Materialize a prompt by name, or null when unknown. */
|
|
35
|
+
export declare function getPrompt(name: string, args: Record<string, unknown>): {
|
|
36
|
+
description: string;
|
|
37
|
+
messages: PromptMessage[];
|
|
38
|
+
} | null;
|
|
39
|
+
//# sourceMappingURL=resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAQA,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,kBAAkB,EAczC,CAAC;AAmBF,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAYhG;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CACzE;AAED,eAAO,MAAM,OAAO,EAAE,gBAAgB,EAOrC,CAAC;AAEF,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,0DAA0D;AAC1D,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAc3D"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources + prompts. Resources expose read-only reference data (the full
|
|
3
|
+
* rule catalog + a migration guide); the prompt gives a client a one-call
|
|
4
|
+
* "migrate this path" workflow that drives the deterministic tools. All offline
|
|
5
|
+
* and static — no filesystem, no network, no key.
|
|
6
|
+
*/
|
|
7
|
+
import { defaultRegistry, REMEDIATE_RUBRIC } from "@quantakrypto/core";
|
|
8
|
+
export const RESOURCES = [
|
|
9
|
+
{
|
|
10
|
+
uri: "quantakrypto://rules",
|
|
11
|
+
name: "Quantakrypto rule catalog",
|
|
12
|
+
description: "Every detection rule quantakrypto can emit (id, title, severity, category, HNDL, remediation).",
|
|
13
|
+
mimeType: "application/json",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
uri: "quantakrypto://guide/migration",
|
|
17
|
+
name: "PQC migration guide",
|
|
18
|
+
description: "How to migrate quantum-vulnerable cryptography using the quantakrypto MCP tools.",
|
|
19
|
+
mimeType: "text/markdown",
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
const MIGRATION_GUIDE = `# Post-Quantum Migration with quantakrypto
|
|
23
|
+
|
|
24
|
+
A safe, deterministic loop ("the model proposes, the engine disposes"):
|
|
25
|
+
|
|
26
|
+
1. **Inventory** — call \`scan_path\` on the target to list quantum-vulnerable findings.
|
|
27
|
+
2. **Triage** — call \`triage_findings\` for the bundle, decide an exposure verdict per
|
|
28
|
+
finding, then \`apply_triage\` to rank them (harvest-now-decrypt-later first).
|
|
29
|
+
3. **Remediate** — call \`remediate_findings\`; for each finding propose the corrected
|
|
30
|
+
full file, then \`verify_fix\` on your result. Keep ONLY fixes that clear the finding
|
|
31
|
+
and introduce no new one. Skip any file containing secrets.
|
|
32
|
+
4. Open a **draft** PR for review. Never auto-merge.
|
|
33
|
+
|
|
34
|
+
## Remediation rubric
|
|
35
|
+
|
|
36
|
+
${REMEDIATE_RUBRIC}
|
|
37
|
+
`;
|
|
38
|
+
/** Read a resource body by URI, or null when the URI is unknown. */
|
|
39
|
+
export function readResource(uri) {
|
|
40
|
+
if (uri === "quantakrypto://rules") {
|
|
41
|
+
return {
|
|
42
|
+
uri,
|
|
43
|
+
mimeType: "application/json",
|
|
44
|
+
text: JSON.stringify(defaultRegistry.ruleCatalog(), null, 2),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (uri === "quantakrypto://guide/migration") {
|
|
48
|
+
return { uri, mimeType: "text/markdown", text: MIGRATION_GUIDE };
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
export const PROMPTS = [
|
|
53
|
+
{
|
|
54
|
+
name: "migrate",
|
|
55
|
+
description: "Plan and apply a post-quantum migration for a path using the deterministic tools.",
|
|
56
|
+
arguments: [{ name: "path", description: "Path to scan (default: .)", required: false }],
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
/** Materialize a prompt by name, or null when unknown. */
|
|
60
|
+
export function getPrompt(name, args) {
|
|
61
|
+
if (name !== "migrate")
|
|
62
|
+
return null;
|
|
63
|
+
const path = typeof args.path === "string" && args.path ? args.path : ".";
|
|
64
|
+
const text = `Migrate ${path} off quantum-vulnerable cryptography using the quantakrypto tools.\n` +
|
|
65
|
+
`1) Call scan_path on "${path}".\n` +
|
|
66
|
+
`2) Call triage_findings, decide exposure verdicts, then apply_triage to rank them.\n` +
|
|
67
|
+
`3) For each finding: call remediate_findings, propose the corrected full file, then\n` +
|
|
68
|
+
` verify_fix on your result — keep only fixes that clear the finding.\n` +
|
|
69
|
+
`Never touch files containing secrets; never auto-merge — open a draft PR for review.`;
|
|
70
|
+
return {
|
|
71
|
+
description: "Plan and apply a post-quantum migration.",
|
|
72
|
+
messages: [{ role: "user", content: { type: "text", text } }],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAUvE,MAAM,CAAC,MAAM,SAAS,GAAyB;IAC7C;QACE,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,2BAA2B;QACjC,WAAW,EACT,gGAAgG;QAClG,QAAQ,EAAE,kBAAkB;KAC7B;IACD;QACE,GAAG,EAAE,gCAAgC;QACrC,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,kFAAkF;QAC/F,QAAQ,EAAE,eAAe;KAC1B;CACF,CAAC;AAEF,MAAM,eAAe,GAAG;;;;;;;;;;;;;;EActB,gBAAgB;CACjB,CAAC;AAEF,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,GAAG,KAAK,sBAAsB,EAAE,CAAC;QACnC,OAAO;YACL,GAAG;YACH,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;SAC7D,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,KAAK,gCAAgC,EAAE,CAAC;QAC7C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AASD,MAAM,CAAC,MAAM,OAAO,GAAuB;IACzC;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EACT,mFAAmF;QACrF,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,2BAA2B,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;KACzF;CACF,CAAC;AAQF,0DAA0D;AAC1D,MAAM,UAAU,SAAS,CACvB,IAAY,EACZ,IAA6B;IAE7B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1E,MAAM,IAAI,GACR,WAAW,IAAI,sEAAsE;QACrF,yBAAyB,IAAI,MAAM;QACnC,sFAAsF;QACtF,uFAAuF;QACvF,0EAA0E;QAC1E,sFAAsF,CAAC;IACzF,OAAO;QACL,WAAW,EAAE,0CAA0C;QACvD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC"}
|
package/dist/rules.d.ts
CHANGED
|
@@ -8,15 +8,17 @@
|
|
|
8
8
|
* by prefix and therefore returned "no matching detector" for every real
|
|
9
9
|
* library finding (P0-5).
|
|
10
10
|
*
|
|
11
|
-
* This module resolves a finding's `ruleId` against core's
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
11
|
+
* This module resolves a finding's `ruleId` against core's rule catalog
|
|
12
|
+
* ({@link defaultRegistry.ruleCatalog}) — the single source of truth declared by
|
|
13
|
+
* the detectors themselves. There is no hand-curated table to keep in sync: the
|
|
14
|
+
* ruleId → { detector, algorithm } mapping is derived from the catalog at load
|
|
15
|
+
* time, so a new rule added in core is resolvable here the moment it ships. The
|
|
16
|
+
* one non-detector rule (`dep-vulnerable`, produced by the manifest scanner
|
|
17
|
+
* rather than a {@link Detector}) is supplemented explicitly. Unknown rules fall
|
|
18
|
+
* back to a prefix match against the detector id space, then to unresolved.
|
|
19
|
+
* Pure and synchronous — no I/O — so it is directly unit-testable.
|
|
18
20
|
*/
|
|
19
|
-
import type { AlgorithmFamily } from "@quantakrypto/core";
|
|
21
|
+
import type { AlgorithmFamily, RuleMeta } from "@quantakrypto/core";
|
|
20
22
|
/** A resolved rule: the detector it belongs to (if any) and its algorithm. */
|
|
21
23
|
export interface ResolvedRule {
|
|
22
24
|
/** The rule id that was looked up (echoed for convenience). */
|
|
@@ -28,6 +30,8 @@ export interface ResolvedRule {
|
|
|
28
30
|
};
|
|
29
31
|
/** The classical algorithm family the rule concerns, when known. */
|
|
30
32
|
algorithm?: AlgorithmFamily;
|
|
33
|
+
/** The catalog metadata for the rule, when it is a known core rule. */
|
|
34
|
+
meta?: RuleMeta;
|
|
31
35
|
/** How the match was made — useful for tests and diagnostics. */
|
|
32
36
|
via: "index" | "detector-id" | "prefix" | "unresolved";
|
|
33
37
|
}
|
|
@@ -35,14 +39,15 @@ export interface ResolvedRule {
|
|
|
35
39
|
* Resolve a finding's `ruleId` to its detector and algorithm.
|
|
36
40
|
*
|
|
37
41
|
* Resolution order:
|
|
38
|
-
* 1.
|
|
39
|
-
* 2.
|
|
40
|
-
* 3.
|
|
41
|
-
* 4.
|
|
42
|
+
* 1. The core rule catalog — the authoritative path for every detector rule.
|
|
43
|
+
* 2. The {@link EXTRA_RULES} supplement (non-detector rules, e.g. dependencies).
|
|
44
|
+
* 3. Exact detector id (a rule that IS a detector id, e.g. a future 1:1 rule).
|
|
45
|
+
* 4. Prefix against the detector id space (`node-crypto-*`, `pem-*`, …).
|
|
46
|
+
* 5. Unresolved — caller falls back to the algorithm remediation.
|
|
42
47
|
*
|
|
43
48
|
* Pure: depends only on its argument and the static core detector set.
|
|
44
49
|
*/
|
|
45
50
|
export declare function resolveRule(ruleId: string): ResolvedRule;
|
|
46
|
-
/** Exposed for tests: the set of canonical rule ids the
|
|
51
|
+
/** Exposed for tests: the set of canonical rule ids resolvable via the catalog. */
|
|
47
52
|
export declare const KNOWN_RULE_IDS: readonly string[];
|
|
48
53
|
//# sourceMappingURL=rules.d.ts.map
|
package/dist/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAY,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9E,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,oEAAoE;IACpE,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,uEAAuE;IACvE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,iEAAiE;IACjE,GAAG,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,YAAY,CAAC;CACxD;AAyBD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAwDxD;AAED,mFAAmF;AACnF,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EASxC,CAAC"}
|
package/dist/rules.js
CHANGED
|
@@ -8,72 +8,28 @@
|
|
|
8
8
|
* by prefix and therefore returned "no matching detector" for every real
|
|
9
9
|
* library finding (P0-5).
|
|
10
10
|
*
|
|
11
|
-
* This module resolves a finding's `ruleId` against core's
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
11
|
+
* This module resolves a finding's `ruleId` against core's rule catalog
|
|
12
|
+
* ({@link defaultRegistry.ruleCatalog}) — the single source of truth declared by
|
|
13
|
+
* the detectors themselves. There is no hand-curated table to keep in sync: the
|
|
14
|
+
* ruleId → { detector, algorithm } mapping is derived from the catalog at load
|
|
15
|
+
* time, so a new rule added in core is resolvable here the moment it ships. The
|
|
16
|
+
* one non-detector rule (`dep-vulnerable`, produced by the manifest scanner
|
|
17
|
+
* rather than a {@link Detector}) is supplemented explicitly. Unknown rules fall
|
|
18
|
+
* back to a prefix match against the detector id space, then to unresolved.
|
|
19
|
+
* Pure and synchronous — no I/O — so it is directly unit-testable.
|
|
18
20
|
*/
|
|
19
21
|
import { defaultRegistry, detectors } from "@quantakrypto/core";
|
|
20
22
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* `@quantakrypto/core` (see `packages/core/src/detectors/*` and `dependencies.ts`).
|
|
25
|
-
* The `detectorId` values reference real detector ids in {@link
|
|
26
|
-
* defaultRegistry}; the descriptions are not duplicated here — they are read
|
|
27
|
-
* live from the registry so they never drift. Algorithms that a single rule
|
|
28
|
-
* can span (e.g. `jsrsasign-*` covers RSA *and* EC) are recorded as
|
|
29
|
-
* `"unknown"`, matching core's own classification.
|
|
23
|
+
* Rules that are NOT emitted by a {@link Detector} and so are absent from the
|
|
24
|
+
* catalog, but are still canonical core ruleIds. Today that is only the
|
|
25
|
+
* dependency-manifest scanner's `dep-vulnerable` rule.
|
|
30
26
|
*/
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
"node-crypto-keygen": { detectorId: "node-crypto", algorithm: "unknown" },
|
|
34
|
-
"node-crypto-sign": { detectorId: "node-crypto", algorithm: "unknown" },
|
|
35
|
-
"node-crypto-sign-oneshot": { detectorId: "node-crypto", algorithm: "unknown" },
|
|
36
|
-
"node-crypto-dh": { detectorId: "node-crypto", algorithm: "DH" },
|
|
37
|
-
"node-crypto-dh-modp": { detectorId: "node-crypto", algorithm: "DH" },
|
|
38
|
-
"node-crypto-ecdh": { detectorId: "node-crypto", algorithm: "ECDH" },
|
|
39
|
-
"node-crypto-rsa-encrypt": { detectorId: "node-crypto", algorithm: "RSA" },
|
|
40
|
-
"node-crypto-dh-keyobject": { detectorId: "node-crypto", algorithm: "DH" },
|
|
41
|
-
// webcrypto detector
|
|
42
|
-
"webcrypto-classical": { detectorId: "webcrypto", algorithm: "unknown" },
|
|
43
|
-
// crypto-libs detector (the library findings P0-5 was about)
|
|
44
|
-
"forge-rsa-keygen": { detectorId: "crypto-libs", algorithm: "RSA" },
|
|
45
|
-
"forge-ed25519": { detectorId: "crypto-libs", algorithm: "EdDSA" },
|
|
46
|
-
"elliptic-ec": { detectorId: "crypto-libs", algorithm: "ECDSA" },
|
|
47
|
-
"secp256k1-usage": { detectorId: "crypto-libs", algorithm: "ECDSA" },
|
|
48
|
-
"jsrsasign-keygen": { detectorId: "crypto-libs", algorithm: "unknown" },
|
|
49
|
-
"jsrsasign-sign": { detectorId: "crypto-libs", algorithm: "unknown" },
|
|
50
|
-
"node-rsa": { detectorId: "crypto-libs", algorithm: "RSA" },
|
|
51
|
-
// jwt-jose detector
|
|
52
|
-
"jwt-classical-alg": { detectorId: "jwt-jose", algorithm: "unknown" },
|
|
53
|
-
"jose-ecdh-es": { detectorId: "jwt-jose", algorithm: "ECDH" },
|
|
54
|
-
// tls-config detector
|
|
55
|
-
"tls-legacy-version": { detectorId: "tls-config", algorithm: "unknown" },
|
|
56
|
-
"tls-reject-unauthorized": { detectorId: "tls-config", algorithm: "unknown" },
|
|
57
|
-
"tls-weak-cipher": { detectorId: "tls-config", algorithm: "unknown" },
|
|
58
|
-
// ssh-cert detector
|
|
59
|
-
"ssh-public-key": { detectorId: "ssh-cert", algorithm: "unknown" },
|
|
60
|
-
"cert-signature-algorithm": { detectorId: "ssh-cert", algorithm: "unknown" },
|
|
61
|
-
// pem-material detector
|
|
62
|
-
"pem-rsa-private-key": { detectorId: "pem-material", algorithm: "RSA" },
|
|
63
|
-
"pem-ec-private-key": { detectorId: "pem-material", algorithm: "ECDSA" },
|
|
64
|
-
"pem-dsa-private-key": { detectorId: "pem-material", algorithm: "DSA" },
|
|
65
|
-
"pem-openssh-private-key": { detectorId: "pem-material", algorithm: "unknown" },
|
|
66
|
-
"pem-pgp-private-key": { detectorId: "pem-material", algorithm: "unknown" },
|
|
67
|
-
"pem-pgp-message": { detectorId: "pem-material", algorithm: "unknown" },
|
|
68
|
-
"pem-pkcs8-private-key": { detectorId: "pem-material", algorithm: "unknown" },
|
|
69
|
-
"pem-certificate": { detectorId: "pem-material", algorithm: "unknown" },
|
|
70
|
-
// dependency scanner (not a Detector, handled by scan()); no registry entry.
|
|
71
|
-
"dep-vulnerable": { detectorId: "dep-vulnerable", algorithm: "unknown" },
|
|
27
|
+
const EXTRA_RULES = {
|
|
28
|
+
"dep-vulnerable": { algorithm: "unknown" },
|
|
72
29
|
};
|
|
73
|
-
/** Build
|
|
30
|
+
/** Build an id → Detector lookup over the active detector set (registry first). */
|
|
74
31
|
function detectorMap() {
|
|
75
32
|
const map = new Map();
|
|
76
|
-
// Prefer the registry; fall back to the exported `detectors` array.
|
|
77
33
|
const all = (() => {
|
|
78
34
|
try {
|
|
79
35
|
return defaultRegistry.all();
|
|
@@ -90,28 +46,41 @@ function detectorMap() {
|
|
|
90
46
|
* Resolve a finding's `ruleId` to its detector and algorithm.
|
|
91
47
|
*
|
|
92
48
|
* Resolution order:
|
|
93
|
-
* 1.
|
|
94
|
-
* 2.
|
|
95
|
-
* 3.
|
|
96
|
-
* 4.
|
|
49
|
+
* 1. The core rule catalog — the authoritative path for every detector rule.
|
|
50
|
+
* 2. The {@link EXTRA_RULES} supplement (non-detector rules, e.g. dependencies).
|
|
51
|
+
* 3. Exact detector id (a rule that IS a detector id, e.g. a future 1:1 rule).
|
|
52
|
+
* 4. Prefix against the detector id space (`node-crypto-*`, `pem-*`, …).
|
|
53
|
+
* 5. Unresolved — caller falls back to the algorithm remediation.
|
|
97
54
|
*
|
|
98
55
|
* Pure: depends only on its argument and the static core detector set.
|
|
99
56
|
*/
|
|
100
57
|
export function resolveRule(ruleId) {
|
|
101
58
|
const id = ruleId.trim();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
59
|
+
// 1. Catalog — the authoritative path for known core detector rules.
|
|
60
|
+
const entry = (() => {
|
|
61
|
+
try {
|
|
62
|
+
return defaultRegistry.forRule(id);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
if (entry) {
|
|
107
69
|
return {
|
|
108
70
|
ruleId: id,
|
|
109
|
-
detector:
|
|
110
|
-
algorithm:
|
|
71
|
+
detector: { id: entry.detector.id, description: entry.detector.description },
|
|
72
|
+
algorithm: entry.rule.algorithm ?? "unknown",
|
|
73
|
+
meta: entry.rule,
|
|
111
74
|
via: "index",
|
|
112
75
|
};
|
|
113
76
|
}
|
|
114
|
-
// 2.
|
|
77
|
+
// 2. Non-detector supplement (dependency scanner, …).
|
|
78
|
+
const extra = EXTRA_RULES[id];
|
|
79
|
+
if (extra) {
|
|
80
|
+
return { ruleId: id, algorithm: extra.algorithm, via: "index" };
|
|
81
|
+
}
|
|
82
|
+
const detectorsById = detectorMap();
|
|
83
|
+
// 3. Exact detector id.
|
|
115
84
|
const exact = detectorsById.get(id);
|
|
116
85
|
if (exact) {
|
|
117
86
|
return {
|
|
@@ -120,7 +89,7 @@ export function resolveRule(ruleId) {
|
|
|
120
89
|
via: "detector-id",
|
|
121
90
|
};
|
|
122
91
|
}
|
|
123
|
-
//
|
|
92
|
+
// 4. Longest-prefix detector id (e.g. `node-crypto-foo` → `node-crypto`).
|
|
124
93
|
let best;
|
|
125
94
|
for (const det of detectorsById.values()) {
|
|
126
95
|
if (id === det.id || id.startsWith(`${det.id}-`)) {
|
|
@@ -135,9 +104,20 @@ export function resolveRule(ruleId) {
|
|
|
135
104
|
via: "prefix",
|
|
136
105
|
};
|
|
137
106
|
}
|
|
138
|
-
//
|
|
107
|
+
// 5. Unresolved.
|
|
139
108
|
return { ruleId: id, via: "unresolved" };
|
|
140
109
|
}
|
|
141
|
-
/** Exposed for tests: the set of canonical rule ids the
|
|
142
|
-
export const KNOWN_RULE_IDS =
|
|
110
|
+
/** Exposed for tests: the set of canonical rule ids resolvable via the catalog. */
|
|
111
|
+
export const KNOWN_RULE_IDS = (() => {
|
|
112
|
+
const ids = [];
|
|
113
|
+
try {
|
|
114
|
+
for (const r of defaultRegistry.ruleCatalog())
|
|
115
|
+
ids.push(r.id);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// ignore — an empty/broken catalog just yields the supplement below.
|
|
119
|
+
}
|
|
120
|
+
ids.push(...Object.keys(EXTRA_RULES));
|
|
121
|
+
return ids;
|
|
122
|
+
})();
|
|
143
123
|
//# sourceMappingURL=rules.js.map
|
package/dist/rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -55,6 +55,10 @@ export declare class McpServer {
|
|
|
55
55
|
handle(message: unknown, context?: ToolContext): Promise<JsonRpcResponse | null>;
|
|
56
56
|
/** Route a request to the right handler. Throws {@link RpcError} on failure. */
|
|
57
57
|
private dispatch;
|
|
58
|
+
/** `resources/read`: return the body for a known resource URI. */
|
|
59
|
+
private onResourcesRead;
|
|
60
|
+
/** `prompts/get`: materialize a named prompt with optional arguments. */
|
|
61
|
+
private onPromptsGet;
|
|
58
62
|
/** Build the `initialize` result. */
|
|
59
63
|
private onInitialize;
|
|
60
64
|
/** Validate params and execute a tool for `tools/call`. */
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,OAAO,KAAK,EAEV,eAAe,EACf,WAAW,EACX,cAAc,EACd,cAAc,EAEf,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,OAAO,KAAK,EAEV,eAAe,EACf,WAAW,EACX,cAAc,EACd,cAAc,EAEf,MAAM,eAAe,CAAC;AAGvB,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,IAAI,EAAE,UAAU,CAAC;IACjB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,mEAAmE;IACnE,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,gBAAgB;IAKrC,2EAA2E;IAC3E,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAQxC,uEAAuE;IACvE,SAAS,IAAI,cAAc,EAAE;IAM7B,wDAAwD;IACxD,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;;;;;;;;OASG;IACG,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA8BtF,gFAAgF;YAClE,QAAQ;IA0BtB,kEAAkE;IAClE,OAAO,CAAC,eAAe;IAavB,yEAAyE;IACzE,OAAO,CAAC,YAAY;IAiBpB,qCAAqC;IACrC,OAAO,CAAC,YAAY;IAgBpB,2DAA2D;YAC7C,WAAW;CAuB1B"}
|
package/dist/server.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import process from "node:process";
|
|
17
17
|
import { ErrorCode, MCP_PROTOCOL_VERSION, RpcError, isJsonRpcRequestLike, isNotification, makeFailure, makeSuccess, } from "./protocol.js";
|
|
18
|
+
import { RESOURCES, PROMPTS, readResource, getPrompt } from "./resources.js";
|
|
18
19
|
/**
|
|
19
20
|
* A minimal, spec-faithful MCP server. Register tools with {@link registerTool}
|
|
20
21
|
* and drive it one message at a time with {@link handle}.
|
|
@@ -101,18 +102,59 @@ export class McpServer {
|
|
|
101
102
|
return { tools: this.listTools() };
|
|
102
103
|
case "tools/call":
|
|
103
104
|
return this.onToolsCall(req.params, context);
|
|
105
|
+
case "resources/list":
|
|
106
|
+
return { resources: RESOURCES };
|
|
107
|
+
case "resources/read":
|
|
108
|
+
return this.onResourcesRead(req.params);
|
|
109
|
+
case "prompts/list":
|
|
110
|
+
return { prompts: PROMPTS };
|
|
111
|
+
case "prompts/get":
|
|
112
|
+
return this.onPromptsGet(req.params);
|
|
104
113
|
default:
|
|
105
114
|
throw new RpcError(ErrorCode.MethodNotFound, `method not found: ${req.method}`);
|
|
106
115
|
}
|
|
107
116
|
}
|
|
117
|
+
/** `resources/read`: return the body for a known resource URI. */
|
|
118
|
+
onResourcesRead(params) {
|
|
119
|
+
if (typeof params !== "object" || params === null || Array.isArray(params)) {
|
|
120
|
+
throw new RpcError(ErrorCode.InvalidParams, "resources/read requires an object params");
|
|
121
|
+
}
|
|
122
|
+
const uri = params.uri;
|
|
123
|
+
if (typeof uri !== "string" || uri.length === 0) {
|
|
124
|
+
throw new RpcError(ErrorCode.InvalidParams, "resources/read requires a 'uri' string");
|
|
125
|
+
}
|
|
126
|
+
const contents = readResource(uri);
|
|
127
|
+
if (!contents)
|
|
128
|
+
throw new RpcError(ErrorCode.InvalidParams, `unknown resource: ${uri}`);
|
|
129
|
+
return { contents: [contents] };
|
|
130
|
+
}
|
|
131
|
+
/** `prompts/get`: materialize a named prompt with optional arguments. */
|
|
132
|
+
onPromptsGet(params) {
|
|
133
|
+
if (typeof params !== "object" || params === null || Array.isArray(params)) {
|
|
134
|
+
throw new RpcError(ErrorCode.InvalidParams, "prompts/get requires an object params");
|
|
135
|
+
}
|
|
136
|
+
const { name, arguments: args } = params;
|
|
137
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
138
|
+
throw new RpcError(ErrorCode.InvalidParams, "prompts/get requires a 'name' string");
|
|
139
|
+
}
|
|
140
|
+
const promptArgs = args && typeof args === "object" && !Array.isArray(args)
|
|
141
|
+
? args
|
|
142
|
+
: {};
|
|
143
|
+
const prompt = getPrompt(name, promptArgs);
|
|
144
|
+
if (!prompt)
|
|
145
|
+
throw new RpcError(ErrorCode.InvalidParams, `unknown prompt: ${name}`);
|
|
146
|
+
return prompt;
|
|
147
|
+
}
|
|
108
148
|
/** Build the `initialize` result. */
|
|
109
149
|
onInitialize() {
|
|
110
150
|
this.initialized = true;
|
|
111
151
|
const result = {
|
|
112
152
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
113
153
|
capabilities: {
|
|
114
|
-
//
|
|
154
|
+
// Everything we expose is static, so listChanged is false throughout.
|
|
115
155
|
tools: { listChanged: false },
|
|
156
|
+
resources: { listChanged: false },
|
|
157
|
+
prompts: { listChanged: false },
|
|
116
158
|
},
|
|
117
159
|
serverInfo: { name: this.info.name, version: this.info.version },
|
|
118
160
|
};
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EACL,SAAS,EACT,oBAAoB,EACpB,QAAQ,EACR,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EACL,SAAS,EACT,oBAAoB,EACpB,QAAQ,EACR,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,WAAW,GACZ,MAAM,eAAe,CAAC;AASvB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAe7E;;;GAGG;AACH,MAAM,OAAO,SAAS;IACH,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1C,IAAI,CAAa;IACjB,YAAY,CAAU;IACvC,mEAAmE;IAC3D,WAAW,GAAG,KAAK,CAAC;IAE5B,YAAY,OAAyB;QACnC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC3C,CAAC;IAED,2EAA2E;IAC3E,YAAY,CAAC,IAAoB;QAC/B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uEAAuE;IACvE,SAAS;QACP,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;aAC5B,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;aACjF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,wDAAwD;IACxD,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAM,CAAC,OAAgB,EAAE,OAAqB;QAClD,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,2EAA2E;YAC3E,OAAO,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,GAAG,GAAG,OAAyB,CAAC;QACtC,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACjD,2DAA2D;YAC3D,IAAI,YAAY;gBAAE,OAAO,IAAI,CAAC;YAC9B,OAAO,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,YAAY;gBAAE,OAAO,IAAI,CAAC,CAAC,oCAAoC;YACnE,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;gBAC5B,8EAA8E;gBAC9E,OAAO,WAAW,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1D,CAAC;YACD,4EAA4E;YAC5E,uEAAuE;YACvE,8DAA8D;YAC9D,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,MAAM,IAAI,CAAC,CAAC;YACvF,OAAO,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,gFAAgF;IACxE,KAAK,CAAC,QAAQ,CAAC,GAAmB,EAAE,OAAqB;QAC/D,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,YAAY;gBACf,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7B,KAAK,2BAA2B;gBAC9B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBACxB,OAAO,EAAE,CAAC,CAAC,4CAA4C;YACzD,KAAK,MAAM;gBACT,OAAO,EAAE,CAAC;YACZ,KAAK,YAAY;gBACf,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACrC,KAAK,YAAY;gBACf,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC/C,KAAK,gBAAgB;gBACnB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;YAClC,KAAK,gBAAgB;gBACnB,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1C,KAAK,cAAc;gBACjB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YAC9B,KAAK,aAAa;gBAChB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACvC;gBACE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,qBAAqB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED,kEAAkE;IAC1D,eAAe,CAAC,MAAe;QACrC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,0CAA0C,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,GAAG,GAAI,MAA4B,CAAC,GAAG,CAAC;QAC9C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,wCAAwC,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,qBAAqB,GAAG,EAAE,CAAC,CAAC;QACvF,OAAO,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IAClC,CAAC;IAED,yEAAyE;IACjE,YAAY,CAAC,MAAe;QAClC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,uCAAuC,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAiD,CAAC;QACpF,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,sCAAsC,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,UAAU,GACd,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACtD,CAAC,CAAE,IAAgC;YACnC,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,mBAAmB,IAAI,EAAE,CAAC,CAAC;QACpF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,qCAAqC;IAC7B,YAAY;QAClB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,MAAM,MAAM,GAA4B;YACtC,eAAe,EAAE,oBAAoB;YACrC,YAAY,EAAE;gBACZ,sEAAsE;gBACtE,KAAK,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;gBAC7B,SAAS,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;gBACjC,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;aAChC;YACD,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;SACjE,CAAC;QACF,IAAI,IAAI,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,2DAA2D;IACnD,KAAK,CAAC,WAAW,CAAC,MAAe,EAAE,OAAqB;QAC9D,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,sCAAsC,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAGjC,CAAC;QACF,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,qCAAqC,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC7F,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,oCAAoC,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;QACzD,4EAA4E;QAC5E,6EAA6E;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;CACF"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* quantakrypto MCP tools, backed by {@link @quantakrypto/core}.
|
|
3
3
|
*
|
|
4
|
-
* Every tool returns an MCP {@link ToolResult} ({ content, isError? }).
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Every tool returns an MCP {@link ToolResult} ({ content, isError? }). Each
|
|
5
|
+
* handler runs core calls through {@link safe} so any runtime failure (a bad
|
|
6
|
+
* path, a work-budget overflow, an unexpected error) surfaces as a readable
|
|
7
|
+
* `isError` tool result with host details stripped, rather than a protocol-level
|
|
8
|
+
* crash.
|
|
9
9
|
*/
|
|
10
10
|
import type { AlgorithmFamily, ScanOptions, ScanResult } from "@quantakrypto/core";
|
|
11
11
|
import type { JsonSchema, ToolContext, ToolDefinition, ToolResult } from "./protocol.js";
|
|
@@ -50,7 +50,7 @@ export declare const FS_TOOL_NAMES: readonly string[];
|
|
|
50
50
|
/** All quantakrypto MCP tools, in a stable order. */
|
|
51
51
|
export declare const quantakryptoTools: ToolDefinition[];
|
|
52
52
|
/** The core version these tools are built against (re-exported for diagnostics). */
|
|
53
|
-
export declare const CORE_VERSION = "0.
|
|
53
|
+
export declare const CORE_VERSION = "0.4.0";
|
|
54
54
|
/** Exposed for tests and advanced callers. */
|
|
55
55
|
export declare const __test: {
|
|
56
56
|
normalizeAlgorithm: typeof normalizeAlgorithm;
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsBH,OAAO,KAAK,EACV,eAAe,EAIf,WAAW,EACX,UAAU,EAGX,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAkBzF;;;;;;GAMG;AACH,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAS1D;AAkBD;;;;;;;;;GASG;AACH,iBAAS,gBAAgB,CACvB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,WAAW,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAexE;AAED,6EAA6E;AAC7E,iBAAS,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAmB1D;AAED,gEAAgE;AAChE,iBAAS,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAmCjD;AAwPD,+EAA+E;AAC/E,iBAAS,kBAAkB,CAAC,SAAS,EAAE,eAAe,GAAG,MAAM,EAAE,CA4BhE;AAusBD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAK1C,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,cAAc,EAiB7C,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,YAAY,UAAU,CAAC;AAEpC,8CAA8C;AAC9C,eAAO,MAAM,MAAM;;;;;;CAMlB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC"}
|