@quantakrypto/mcp 0.4.1 → 0.4.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/HOSTING.md +11 -7
- package/LICENSE +201 -0
- package/dist/fsconfig.d.ts +10 -0
- package/dist/fsconfig.d.ts.map +1 -1
- package/dist/fsconfig.js +15 -0
- package/dist/fsconfig.js.map +1 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -1
- package/dist/resources.js.map +1 -1
- package/dist/rules.d.ts.map +1 -1
- package/dist/rules.js +3 -2
- package/dist/rules.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -1
- package/dist/server.js.map +1 -1
- package/dist/stdio.js.map +1 -1
- package/dist/tools.d.ts +3 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +126 -15
- package/dist/tools.js.map +1 -1
- package/package.json +2 -2
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;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;
|
|
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;IAcvB,yEAAyE;IACzE,OAAO,CAAC,YAAY;IAiBpB,qCAAqC;IACrC,OAAO,CAAC,YAAY;IAgBpB,2DAA2D;YAC7C,WAAW;CAuB1B"}
|
package/dist/server.js
CHANGED
|
@@ -124,8 +124,9 @@ export class McpServer {
|
|
|
124
124
|
throw new RpcError(ErrorCode.InvalidParams, "resources/read requires a 'uri' string");
|
|
125
125
|
}
|
|
126
126
|
const contents = readResource(uri);
|
|
127
|
+
// MCP spec: unknown resource → -32002 (Resource not found), uri in data.
|
|
127
128
|
if (!contents)
|
|
128
|
-
throw new RpcError(ErrorCode.
|
|
129
|
+
throw new RpcError(ErrorCode.ResourceNotFound, "Resource not found", { uri });
|
|
129
130
|
return { contents: [contents] };
|
|
130
131
|
}
|
|
131
132
|
/** `prompts/get`: materialize a named prompt with optional arguments. */
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
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,yEAAyE;QACzE,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7F,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","sourcesContent":["/**\n * Transport-agnostic MCP server core.\n *\n * {@link McpServer} owns a tool registry and a single pure entry point,\n * {@link McpServer.handle}, that turns one JSON-RPC message into one JSON-RPC\n * response (or `null` for notifications, which get no reply). It performs no\n * I/O whatsoever — the stdio and http transports feed it parsed messages and\n * serialize whatever it returns. This makes the whole protocol surface\n * unit-testable by calling `handle` directly.\n *\n * The one concession to I/O is that unexpected (non-{@link RpcError}) throws are\n * logged to stderr with full detail and replaced with a generic message in the\n * response, so server internals (paths, ENOENT targets) never reach the remote\n * caller. The wire response remains a pure function of the inputs.\n */\n\nimport process from \"node:process\";\n\nimport {\n ErrorCode,\n MCP_PROTOCOL_VERSION,\n RpcError,\n isJsonRpcRequestLike,\n isNotification,\n makeFailure,\n makeSuccess,\n} from \"./protocol.js\";\nimport type {\n JsonRpcRequest,\n JsonRpcResponse,\n ToolContext,\n ToolDefinition,\n ToolDescriptor,\n ToolResult,\n} from \"./protocol.js\";\nimport { RESOURCES, PROMPTS, readResource, getPrompt } from \"./resources.js\";\n\n/** Identifying info advertised to clients during `initialize`. */\nexport interface ServerInfo {\n name: string;\n version: string;\n}\n\nexport interface McpServerOptions {\n /** Server identity returned in the `initialize` handshake. */\n info: ServerInfo;\n /** Optional human-readable instructions surfaced to the client. */\n instructions?: string;\n}\n\n/**\n * A minimal, spec-faithful MCP server. Register tools with {@link registerTool}\n * and drive it one message at a time with {@link handle}.\n */\nexport class McpServer {\n private readonly tools = new Map<string, ToolDefinition>();\n private readonly info: ServerInfo;\n private readonly instructions?: string;\n /** Set once `initialize` has been received; informational only. */\n private initialized = false;\n\n constructor(options: McpServerOptions) {\n this.info = options.info;\n this.instructions = options.instructions;\n }\n\n /** Register a tool. Throws if a tool with the same name already exists. */\n registerTool(tool: ToolDefinition): this {\n if (this.tools.has(tool.name)) {\n throw new Error(`duplicate tool registration: ${tool.name}`);\n }\n this.tools.set(tool.name, tool);\n return this;\n }\n\n /** The public descriptors of all registered tools (sorted by name). */\n listTools(): ToolDescriptor[] {\n return [...this.tools.values()]\n .map(({ name, description, inputSchema }) => ({ name, description, inputSchema }))\n .sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /** Whether the `initialize` handshake has completed. */\n get isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Process a single JSON-RPC message.\n *\n * @param message An already-parsed JSON value (the transport handles framing\n * and `JSON.parse`). May be malformed; this method validates it.\n * @param context Optional per-call context (e.g. an `AbortSignal` for the\n * transport's request deadline) forwarded to the invoked tool handler.\n * @returns The response to send back, or `null` when no reply is due\n * (notifications, or an unparseable notification-shaped message).\n */\n async handle(message: unknown, context?: ToolContext): Promise<JsonRpcResponse | null> {\n if (!isJsonRpcRequestLike(message)) {\n // Not a valid request object. We can't know its id, so reply with null id.\n return makeFailure(null, ErrorCode.InvalidRequest, \"invalid JSON-RPC request\");\n }\n\n const req = message as JsonRpcRequest;\n const notification = isNotification(req);\n const id = notification ? null : (req.id ?? null);\n\n try {\n const result = await this.dispatch(req, context);\n // Notifications never receive a response, even on success.\n if (notification) return null;\n return makeSuccess(id, result);\n } catch (err) {\n if (notification) return null; // swallow errors from notifications\n if (err instanceof RpcError) {\n // RpcError messages are author-controlled validation strings, safe to return.\n return makeFailure(id, err.code, err.message, err.data);\n }\n // An unexpected throw may carry a server-side detail (a filesystem path, an\n // ENOENT for /etc/shadow, …). Log the detail locally; return a generic\n // message so the remote caller never learns server internals.\n const detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n process.stderr.write(`quantakrypto MCP: internal error handling request: ${detail}\\n`);\n return makeFailure(id, ErrorCode.InternalError, \"internal error\");\n }\n }\n\n /** Route a request to the right handler. Throws {@link RpcError} on failure. */\n private async dispatch(req: JsonRpcRequest, context?: ToolContext): Promise<unknown> {\n switch (req.method) {\n case \"initialize\":\n return this.onInitialize();\n case \"notifications/initialized\":\n this.initialized = true;\n return {}; // notification → result ignored by handle()\n case \"ping\":\n return {};\n case \"tools/list\":\n return { tools: this.listTools() };\n case \"tools/call\":\n return this.onToolsCall(req.params, context);\n case \"resources/list\":\n return { resources: RESOURCES };\n case \"resources/read\":\n return this.onResourcesRead(req.params);\n case \"prompts/list\":\n return { prompts: PROMPTS };\n case \"prompts/get\":\n return this.onPromptsGet(req.params);\n default:\n throw new RpcError(ErrorCode.MethodNotFound, `method not found: ${req.method}`);\n }\n }\n\n /** `resources/read`: return the body for a known resource URI. */\n private onResourcesRead(params: unknown): unknown {\n if (typeof params !== \"object\" || params === null || Array.isArray(params)) {\n throw new RpcError(ErrorCode.InvalidParams, \"resources/read requires an object params\");\n }\n const uri = (params as { uri?: unknown }).uri;\n if (typeof uri !== \"string\" || uri.length === 0) {\n throw new RpcError(ErrorCode.InvalidParams, \"resources/read requires a 'uri' string\");\n }\n const contents = readResource(uri);\n // MCP spec: unknown resource → -32002 (Resource not found), uri in data.\n if (!contents) throw new RpcError(ErrorCode.ResourceNotFound, \"Resource not found\", { uri });\n return { contents: [contents] };\n }\n\n /** `prompts/get`: materialize a named prompt with optional arguments. */\n private onPromptsGet(params: unknown): unknown {\n if (typeof params !== \"object\" || params === null || Array.isArray(params)) {\n throw new RpcError(ErrorCode.InvalidParams, \"prompts/get requires an object params\");\n }\n const { name, arguments: args } = params as { name?: unknown; arguments?: unknown };\n if (typeof name !== \"string\" || name.length === 0) {\n throw new RpcError(ErrorCode.InvalidParams, \"prompts/get requires a 'name' string\");\n }\n const promptArgs =\n args && typeof args === \"object\" && !Array.isArray(args)\n ? (args as Record<string, unknown>)\n : {};\n const prompt = getPrompt(name, promptArgs);\n if (!prompt) throw new RpcError(ErrorCode.InvalidParams, `unknown prompt: ${name}`);\n return prompt;\n }\n\n /** Build the `initialize` result. */\n private onInitialize(): unknown {\n this.initialized = true;\n const result: Record<string, unknown> = {\n protocolVersion: MCP_PROTOCOL_VERSION,\n capabilities: {\n // Everything we expose is static, so listChanged is false throughout.\n tools: { listChanged: false },\n resources: { listChanged: false },\n prompts: { listChanged: false },\n },\n serverInfo: { name: this.info.name, version: this.info.version },\n };\n if (this.instructions) result.instructions = this.instructions;\n return result;\n }\n\n /** Validate params and execute a tool for `tools/call`. */\n private async onToolsCall(params: unknown, context?: ToolContext): Promise<ToolResult> {\n if (typeof params !== \"object\" || params === null || Array.isArray(params)) {\n throw new RpcError(ErrorCode.InvalidParams, \"tools/call requires an object params\");\n }\n const { name, arguments: args } = params as {\n name?: unknown;\n arguments?: unknown;\n };\n if (typeof name !== \"string\" || name.length === 0) {\n throw new RpcError(ErrorCode.InvalidParams, \"tools/call requires a 'name' string\");\n }\n const tool = this.tools.get(name);\n if (!tool) {\n throw new RpcError(ErrorCode.InvalidParams, `unknown tool: ${name}`);\n }\n if (args !== undefined && (typeof args !== \"object\" || args === null || Array.isArray(args))) {\n throw new RpcError(ErrorCode.InvalidParams, \"tool 'arguments' must be an object\");\n }\n const toolArgs = (args ?? {}) as Record<string, unknown>;\n // Tool-level failures are reported as isError results, not protocol errors,\n // so the model can read and react to them. Only unexpected throws bubble up.\n return tool.handler(toolArgs, context);\n }\n}\n"]}
|
package/dist/stdio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGvD,uEAAuE;AACvE,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAiB,EACjB,QAA+B,OAAO,CAAC,KAAK,EAC5C,SAAgC,OAAO,CAAC,MAAM;IAE9C,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE3D,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,oCAAoC;QAEnE,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,8CAA8C;QAC9C,KAAK,MAAM;aACR,MAAM,CAAC,MAAM,CAAC;aACd,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YACjB,IAAI,QAAQ,KAAK,IAAI;gBAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QACvE,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtB,yEAAyE;YACzE,MAAM,WAAW,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,WAAW,IAAI,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAClB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,2EAA2E;AAC3E,SAAS,IAAI;IACX,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAChE,cAAc,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,KAAK,QAAQ,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,IAAI,EAAE,CAAC;AACT,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * quantakrypto-mcp — stdio transport.\n *\n * MCP's stdio transport is newline-delimited JSON: exactly one JSON-RPC 2.0\n * message per line on stdin, one per line on stdout. (This is NOT HTTP-style\n * Content-Length framing.) This module reads stdin line-by-line with\n * {@link node:readline}, hands each parsed message to {@link McpServer.handle},\n * and writes any response back as a single line on stdout. Diagnostics go to\n * stderr so they never corrupt the protocol stream.\n *\n * Run as the `quantakrypto-mcp` bin, or `node dist/stdio.js`.\n */\n\nimport { createInterface } from \"node:readline\";\nimport process from \"node:process\";\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { createQuantakryptoServer } from \"./index.js\";\nimport { ErrorCode, makeFailure } from \"./protocol.js\";\nimport type { McpServer } from \"./server.js\";\n\n/** Serialize a value as one newline-terminated JSON line to stdout. */\nfunction writeLine(value: unknown): void {\n process.stdout.write(JSON.stringify(value) + \"\\n\");\n}\n\n/**\n * Attach a line-delimited JSON-RPC loop to the given streams. Exposed (rather\n * than only run on import) so it can be reused or tested with custom streams.\n */\nexport function runStdioServer(\n server: McpServer,\n input: NodeJS.ReadableStream = process.stdin,\n output: NodeJS.WritableStream = process.stdout,\n): void {\n const rl = createInterface({ input, crlfDelay: Infinity });\n\n rl.on(\"line\", (raw: string) => {\n const line = raw.trim();\n if (line.length === 0) return; // tolerate blank lines / keepalives\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n // Parse error: we have no id, so reply with a null-id error per JSON-RPC.\n output.write(JSON.stringify(makeFailure(null, ErrorCode.ParseError, \"parse error\")) + \"\\n\");\n return;\n }\n\n // Process asynchronously; responses are written as they resolve. Ordering\n // within a single client is preserved because handlers here are fast and\n // the event loop drains line events in order.\n void server\n .handle(parsed)\n .then((response) => {\n if (response !== null) output.write(JSON.stringify(response) + \"\\n\");\n })\n .catch((err: unknown) => {\n // Defensive: handle() already catches, but never let a rejection escape.\n const messageText = err instanceof Error ? err.message : String(err);\n process.stderr.write(`quantakrypto-mcp internal error: ${messageText}\\n`);\n });\n });\n\n rl.on(\"close\", () => {\n process.exitCode = 0;\n });\n}\n\n/** Entry point when executed directly (the bin / `node dist/stdio.js`). */\nfunction main(): void {\n const server = createQuantakryptoServer();\n process.stderr.write(`quantakrypto MCP server (stdio) ready\\n`);\n runStdioServer(server);\n}\n\n/**\n * True when this module is the program's entry point. Resolves symlinks so the\n * check also holds when launched via the `quantakrypto-mcp` bin shim in node_modules/.bin.\n */\nfunction isMainModule(): boolean {\n const argv1 = process.argv[1];\n if (!argv1) return false;\n const thisPath = fileURLToPath(import.meta.url);\n try {\n return realpathSync(argv1) === realpathSync(thisPath);\n } catch {\n return argv1 === thisPath;\n }\n}\n\n// Only auto-run when invoked as a script, not when imported by tests.\nif (isMainModule()) {\n main();\n}\n\nexport { writeLine };\n"]}
|
package/dist/tools.d.ts
CHANGED
|
@@ -27,13 +27,13 @@ declare function describeError(label: string, err: unknown): string;
|
|
|
27
27
|
* directly. The `signal` from the transport's request deadline (when present) is
|
|
28
28
|
* threaded in so a timed-out request actually aborts the underlying scan.
|
|
29
29
|
*/
|
|
30
|
-
declare function buildScanOptions(requested: string, context?: ToolContext): {
|
|
30
|
+
declare function buildScanOptions(requested: string, context?: ToolContext): Promise<{
|
|
31
31
|
ok: true;
|
|
32
32
|
options: ScanOptions;
|
|
33
33
|
} | {
|
|
34
34
|
ok: false;
|
|
35
35
|
result: ToolResult;
|
|
36
|
-
}
|
|
36
|
+
}>;
|
|
37
37
|
/** Map a free-text algorithm string onto a known {@link AlgorithmFamily}. */
|
|
38
38
|
declare function normalizeAlgorithm(input: string): AlgorithmFamily;
|
|
39
39
|
/** Render a scan result as a compact human-readable summary. */
|
|
@@ -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.4.
|
|
53
|
+
export declare const CORE_VERSION = "0.4.3";
|
|
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;AAyBH,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,iBAAe,gBAAgB,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC,CAuBjF;AAED,6EAA6E;AAC7E,iBAAS,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAmB1D;AAED,gEAAgE;AAChE,iBAAS,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAmCjD;AAuQD,+EAA+E;AAC/E,iBAAS,kBAAkB,CAAC,SAAS,EAAE,eAAe,GAAG,MAAM,EAAE,CA4BhE;AAqzBD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAK1C,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,cAAc,EAkB7C,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"}
|
package/dist/tools.js
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
* crash.
|
|
9
9
|
*/
|
|
10
10
|
import process from "node:process";
|
|
11
|
-
import { VERSION, AbortError, BudgetExceededError, buildInventory, buildRemediateRequest, buildTriageRequest, compareFindings, detectors, fingerprintFinding, languageToExtension, remediationFor, scan, SEVERITY_ORDER, toCbom, verifyFix, vulnerableDependencies, } from "@quantakrypto/core";
|
|
11
|
+
import { VERSION, AbortError, BudgetExceededError, buildInventory, buildRemediateRequest, buildTriageRequest, compareFindings, detectors, fingerprintFinding, isManifestFile, languageToExtension, remediateFindings, remediationFor, remediationForTier, scan, SEVERITY_ORDER, toCbom, verifyFix, vulnerableDependencies, } from "@quantakrypto/core";
|
|
12
12
|
import { errorResult, textResult } from "./protocol.js";
|
|
13
13
|
import { resolveRule } from "./rules.js";
|
|
14
|
-
import { resolveFsConfig, resolveScanPath } from "./fsconfig.js";
|
|
14
|
+
import { realpathInsideRoots, resolveFsConfig, resolveScanPath } from "./fsconfig.js";
|
|
15
15
|
/** All classical algorithm families we can advise on, used for validation/help. */
|
|
16
16
|
const ALGORITHM_FAMILIES = [
|
|
17
17
|
"RSA",
|
|
@@ -66,12 +66,20 @@ async function safe(label, fn) {
|
|
|
66
66
|
* directly. The `signal` from the transport's request deadline (when present) is
|
|
67
67
|
* threaded in so a timed-out request actually aborts the underlying scan.
|
|
68
68
|
*/
|
|
69
|
-
function buildScanOptions(requested, context) {
|
|
69
|
+
async function buildScanOptions(requested, context) {
|
|
70
70
|
const config = resolveFsConfig(process.env);
|
|
71
71
|
const decision = resolveScanPath(config, requested);
|
|
72
72
|
if (!decision.ok) {
|
|
73
73
|
return { ok: false, result: errorResult(`scan rejected: ${decision.reason}`) };
|
|
74
74
|
}
|
|
75
|
+
// Symlink-escape hardening: re-verify containment against the real, resolved
|
|
76
|
+
// paths so a symlink inside a root can't read outside it (audit: mcp #1).
|
|
77
|
+
if (!(await realpathInsideRoots(decision.path, config))) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
result: errorResult("scan rejected: path resolves outside the configured root(s) (symlink)."),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
75
83
|
return {
|
|
76
84
|
ok: true,
|
|
77
85
|
options: {
|
|
@@ -178,7 +186,7 @@ const scanPathTool = {
|
|
|
178
186
|
return errorResult("scan_path requires a non-empty 'path' string.");
|
|
179
187
|
}
|
|
180
188
|
const format = args.format === "json" ? "json" : "summary";
|
|
181
|
-
const opts = buildScanOptions(path, context);
|
|
189
|
+
const opts = await buildScanOptions(path, context);
|
|
182
190
|
if (!opts.ok)
|
|
183
191
|
return opts.result;
|
|
184
192
|
const scanned = await safe("scan", () => scan(opts.options));
|
|
@@ -211,7 +219,7 @@ const inventoryCryptoTool = {
|
|
|
211
219
|
if (typeof path !== "string" || path.length === 0) {
|
|
212
220
|
return errorResult("inventory_crypto requires a non-empty 'path' string.");
|
|
213
221
|
}
|
|
214
|
-
const opts = buildScanOptions(path, context);
|
|
222
|
+
const opts = await buildScanOptions(path, context);
|
|
215
223
|
if (!opts.ok)
|
|
216
224
|
return opts.result;
|
|
217
225
|
const scanned = await safe("scan", () => scan(opts.options));
|
|
@@ -331,7 +339,8 @@ const explainFindingTool = {
|
|
|
331
339
|
const suggestHybridTool = {
|
|
332
340
|
name: "suggest_hybrid",
|
|
333
341
|
description: "Recommend a post-quantum / hybrid migration. Provide an 'algorithm' " +
|
|
334
|
-
"(e.g. RSA, ECDH, ECDSA) or free-text 'context' describing the usage."
|
|
342
|
+
"(e.g. RSA, ECDH, ECDSA) or free-text 'context' describing the usage. " +
|
|
343
|
+
"Set 'tier' to 'category-5' for CNSA 2.0 / national-security systems.",
|
|
335
344
|
inputSchema: {
|
|
336
345
|
type: "object",
|
|
337
346
|
properties: {
|
|
@@ -343,6 +352,12 @@ const suggestHybridTool = {
|
|
|
343
352
|
type: "string",
|
|
344
353
|
description: "Free-text description of the cryptographic usage (used when no algorithm is given).",
|
|
345
354
|
},
|
|
355
|
+
tier: {
|
|
356
|
+
type: "string",
|
|
357
|
+
enum: ["category-3", "category-5"],
|
|
358
|
+
description: "Security tier: 'category-3' (default, commercial — ML-KEM-768 / ML-DSA-65) or " +
|
|
359
|
+
"'category-5' (CNSA 2.0 / NSS, long-lived secrets — ML-KEM-1024 / ML-DSA-87).",
|
|
360
|
+
},
|
|
346
361
|
},
|
|
347
362
|
additionalProperties: false,
|
|
348
363
|
},
|
|
@@ -353,10 +368,17 @@ const suggestHybridTool = {
|
|
|
353
368
|
return errorResult("suggest_hybrid requires either 'algorithm' or 'context'.");
|
|
354
369
|
}
|
|
355
370
|
const algorithm = normalizeAlgorithm(algoInput || context);
|
|
371
|
+
const tier = args.tier === "category-5"
|
|
372
|
+
? "category-5"
|
|
373
|
+
: args.tier === "category-3"
|
|
374
|
+
? "category-3"
|
|
375
|
+
: undefined;
|
|
356
376
|
const lines = [];
|
|
357
377
|
lines.push(`Migration guidance for: ${algoInput || context}`);
|
|
358
378
|
lines.push(`Detected family: ${algorithm}`);
|
|
359
|
-
|
|
379
|
+
if (tier)
|
|
380
|
+
lines.push(`Security tier: ${tier}`);
|
|
381
|
+
const rem = await safe("remediationFor", () => tier ? remediationForTier(algorithm, tier) : remediationFor(algorithm));
|
|
360
382
|
if (rem.ok && rem.value) {
|
|
361
383
|
lines.push(`Recommended replacement: ${rem.value.recommendation}`);
|
|
362
384
|
lines.push(`Rationale: ${rem.value.detail}`);
|
|
@@ -452,7 +474,7 @@ const generateCbomTool = {
|
|
|
452
474
|
if (typeof path !== "string" || path.length === 0) {
|
|
453
475
|
return errorResult("generate_cbom requires a non-empty 'path' string.");
|
|
454
476
|
}
|
|
455
|
-
const opts = buildScanOptions(path, context);
|
|
477
|
+
const opts = await buildScanOptions(path, context);
|
|
456
478
|
if (!opts.ok)
|
|
457
479
|
return opts.result;
|
|
458
480
|
const scanned = await safe("scan", () => scan(opts.options));
|
|
@@ -533,7 +555,7 @@ const planMigrationTool = {
|
|
|
533
555
|
if (typeof path !== "string" || path.length === 0) {
|
|
534
556
|
return errorResult("plan_migration requires a non-empty 'path' string.");
|
|
535
557
|
}
|
|
536
|
-
const opts = buildScanOptions(path, context);
|
|
558
|
+
const opts = await buildScanOptions(path, context);
|
|
537
559
|
if (!opts.ok)
|
|
538
560
|
return opts.result;
|
|
539
561
|
const scanned = await safe("scan", () => scan(opts.options));
|
|
@@ -869,6 +891,18 @@ const scoreDeltaTool = {
|
|
|
869
891
|
};
|
|
870
892
|
},
|
|
871
893
|
};
|
|
894
|
+
/**
|
|
895
|
+
* True when every element looks like a scan Finding (a string `ruleId` and a
|
|
896
|
+
* `location.file`). Guards the triage/remediate tools so a malformed `findings`
|
|
897
|
+
* element surfaces as a tool `isError` result rather than throwing a protocol
|
|
898
|
+
* `-32603` internal error downstream (audit: mcp #4).
|
|
899
|
+
*/
|
|
900
|
+
function areFindings(arr) {
|
|
901
|
+
return arr.every((f) => f !== null &&
|
|
902
|
+
typeof f === "object" &&
|
|
903
|
+
typeof f.ruleId === "string" &&
|
|
904
|
+
typeof f.location?.file === "string");
|
|
905
|
+
}
|
|
872
906
|
const triageFindingsTool = {
|
|
873
907
|
name: "triage_findings",
|
|
874
908
|
description: "Produce a deterministic triage REQUEST bundle (rubric + verdict schema + " +
|
|
@@ -885,8 +919,8 @@ const triageFindingsTool = {
|
|
|
885
919
|
additionalProperties: false,
|
|
886
920
|
},
|
|
887
921
|
async handler(args) {
|
|
888
|
-
if (!Array.isArray(args.findings)) {
|
|
889
|
-
return errorResult("triage_findings requires a 'findings' array.");
|
|
922
|
+
if (!Array.isArray(args.findings) || !areFindings(args.findings)) {
|
|
923
|
+
return errorResult("triage_findings requires a 'findings' array of scan findings (each with a string ruleId and location.file).");
|
|
890
924
|
}
|
|
891
925
|
const findings = args.findings;
|
|
892
926
|
const request = buildTriageRequest(findings, "metadata");
|
|
@@ -895,7 +929,16 @@ const triageFindingsTool = {
|
|
|
895
929
|
fingerprint: fingerprintFinding(f),
|
|
896
930
|
context: request.contexts[i],
|
|
897
931
|
}));
|
|
898
|
-
|
|
932
|
+
// The verdict schema advertised to the agent MUST include `fingerprint`
|
|
933
|
+
// (the instructions require it, and apply_triage keys on it) — core's
|
|
934
|
+
// single-verdict schema doesn't, so extend it here (audit: mcp bundle).
|
|
935
|
+
const props = request.schema.properties ?? {};
|
|
936
|
+
const schema = {
|
|
937
|
+
type: "object",
|
|
938
|
+
required: ["fingerprint", "exposureScore", "priority", "rationale"],
|
|
939
|
+
properties: { fingerprint: { type: "string" }, ...props },
|
|
940
|
+
};
|
|
941
|
+
const bundle = { rubric: request.rubric, schema, items };
|
|
899
942
|
return {
|
|
900
943
|
content: [
|
|
901
944
|
{
|
|
@@ -920,7 +963,11 @@ function parseVerdict(v) {
|
|
|
920
963
|
const rationale = o.rationale;
|
|
921
964
|
if (typeof fingerprint !== "string")
|
|
922
965
|
return null;
|
|
923
|
-
|
|
966
|
+
// `Number.isFinite` rejects NaN/Infinity — NaN passes both `< 0` and `> 100`
|
|
967
|
+
// (they're false) and would poison the exposure sort comparator (audit: mcp #3).
|
|
968
|
+
if (typeof exposureScore !== "number" || !Number.isFinite(exposureScore))
|
|
969
|
+
return null;
|
|
970
|
+
if (exposureScore < 0 || exposureScore > 100)
|
|
924
971
|
return null;
|
|
925
972
|
if (priority !== "now" && priority !== "soon" && priority !== "later")
|
|
926
973
|
return null;
|
|
@@ -946,6 +993,9 @@ const applyTriageTool = {
|
|
|
946
993
|
if (!Array.isArray(args.findings) || !Array.isArray(args.verdicts)) {
|
|
947
994
|
return errorResult("apply_triage requires 'findings' and 'verdicts' arrays.");
|
|
948
995
|
}
|
|
996
|
+
if (!areFindings(args.findings)) {
|
|
997
|
+
return errorResult("apply_triage: each 'findings' element needs a string ruleId and location.file.");
|
|
998
|
+
}
|
|
949
999
|
const findings = args.findings;
|
|
950
1000
|
const byFingerprint = new Map();
|
|
951
1001
|
let skipped = 0;
|
|
@@ -1004,8 +1054,8 @@ const remediateFindingsTool = {
|
|
|
1004
1054
|
additionalProperties: false,
|
|
1005
1055
|
},
|
|
1006
1056
|
async handler(args) {
|
|
1007
|
-
if (!Array.isArray(args.findings)) {
|
|
1008
|
-
return errorResult("remediate_findings requires a 'findings' array.");
|
|
1057
|
+
if (!Array.isArray(args.findings) || !areFindings(args.findings)) {
|
|
1058
|
+
return errorResult("remediate_findings requires a 'findings' array of scan findings (each with a string ruleId and location.file).");
|
|
1009
1059
|
}
|
|
1010
1060
|
const findings = args.findings;
|
|
1011
1061
|
const request = buildRemediateRequest(findings, "metadata");
|
|
@@ -1027,6 +1077,66 @@ const remediateFindingsTool = {
|
|
|
1027
1077
|
};
|
|
1028
1078
|
},
|
|
1029
1079
|
};
|
|
1080
|
+
const applyVerifiedPatchTool = {
|
|
1081
|
+
name: "apply_verified_patch",
|
|
1082
|
+
description: "Deterministically VERIFY a proposed fix before writing it — runs the same " +
|
|
1083
|
+
"patch-policy + verify_fix + blast-radius gates as `qremediate` (offline, no " +
|
|
1084
|
+
"key, no network). Give the finding, the file's current content, and your " +
|
|
1085
|
+
"proposed FULL corrected content; returns approved:true only if the patch is " +
|
|
1086
|
+
"in-policy, clears the finding, adds no new finding, introduces no network/exec " +
|
|
1087
|
+
"sink, and is bounded in size. This does NOT write the file — you write it, " +
|
|
1088
|
+
"only when approved, and never auto-merge.",
|
|
1089
|
+
inputSchema: {
|
|
1090
|
+
type: "object",
|
|
1091
|
+
properties: {
|
|
1092
|
+
finding: {
|
|
1093
|
+
type: "object",
|
|
1094
|
+
description: "The scan finding being fixed (needs a string ruleId and location.file).",
|
|
1095
|
+
},
|
|
1096
|
+
originalContent: { type: "string", description: "The file's current full content." },
|
|
1097
|
+
newContent: { type: "string", description: "Your proposed full corrected file content." },
|
|
1098
|
+
},
|
|
1099
|
+
required: ["finding", "originalContent", "newContent"],
|
|
1100
|
+
additionalProperties: false,
|
|
1101
|
+
},
|
|
1102
|
+
async handler(args) {
|
|
1103
|
+
const finding = args.finding;
|
|
1104
|
+
if (!finding || typeof finding !== "object" || !areFindings([finding])) {
|
|
1105
|
+
return errorResult("apply_verified_patch requires a 'finding' with a string ruleId and location.file.");
|
|
1106
|
+
}
|
|
1107
|
+
if (typeof args.originalContent !== "string" || typeof args.newContent !== "string") {
|
|
1108
|
+
return errorResult("apply_verified_patch requires string 'originalContent' and 'newContent'.");
|
|
1109
|
+
}
|
|
1110
|
+
const file = finding.location.file;
|
|
1111
|
+
const originalContent = args.originalContent;
|
|
1112
|
+
const patch = {
|
|
1113
|
+
path: file,
|
|
1114
|
+
newContent: args.newContent,
|
|
1115
|
+
ruleId: finding.ruleId,
|
|
1116
|
+
source: "llm",
|
|
1117
|
+
};
|
|
1118
|
+
const res = await safe("apply_verified_patch", () => remediateFindings([finding], {
|
|
1119
|
+
readContent: () => originalContent,
|
|
1120
|
+
patchSource: () => patch,
|
|
1121
|
+
policy: {
|
|
1122
|
+
findingFiles: new Set([file]),
|
|
1123
|
+
manifestFiles: new Set(isManifestFile(file) ? [file] : []),
|
|
1124
|
+
},
|
|
1125
|
+
}));
|
|
1126
|
+
if (!res.ok)
|
|
1127
|
+
return res.result;
|
|
1128
|
+
const approved = res.value.applied.length > 0;
|
|
1129
|
+
return textResult(JSON.stringify({
|
|
1130
|
+
approved,
|
|
1131
|
+
path: file,
|
|
1132
|
+
ruleId: finding.ruleId,
|
|
1133
|
+
...(approved ? {} : { reason: res.value.rejected[0]?.reason ?? "rejected" }),
|
|
1134
|
+
note: approved
|
|
1135
|
+
? "Cleared every deterministic gate — safe to write. Open a diff/PR for review; never auto-merge."
|
|
1136
|
+
: "Rejected by the deterministic gates — do NOT write this patch.",
|
|
1137
|
+
}, null, 2));
|
|
1138
|
+
},
|
|
1139
|
+
};
|
|
1030
1140
|
/**
|
|
1031
1141
|
* Tools that read arbitrary filesystem paths. Disabled by default on the HTTP
|
|
1032
1142
|
* transport (see {@link ./http.ts}) because a hosted endpoint must not be an
|
|
@@ -1057,6 +1167,7 @@ export const quantakryptoTools = [
|
|
|
1057
1167
|
triageFindingsTool,
|
|
1058
1168
|
applyTriageTool,
|
|
1059
1169
|
remediateFindingsTool,
|
|
1170
|
+
applyVerifiedPatchTool,
|
|
1060
1171
|
];
|
|
1061
1172
|
/** The core version these tools are built against (re-exported for diagnostics). */
|
|
1062
1173
|
export const CORE_VERSION = VERSION;
|