@scoutwyze/fips-mcp 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ScoutWyze
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,42 @@
1
- # Temporary Holding Version
1
+ # ScoutWyze FIPS MCP server
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Is this product version FIPS 140-3 validated, in NIST's queue, or expiring? An MCP server for the
4
+ [ScoutWyze FIPS](https://scoutwyze-fips.fly.dev) status API. Answers come from NIST CMVP lists (active
5
+ certificates, Modules In Process, Implementation Under Test), with links to the NIST pages used.
6
+
7
+ Covers Windows 11 / Server, macOS / iOS, FortiOS, PAN-OS, Panorama, Cisco FTD, RHEL, Ubuntu, Samsung
8
+ Android, Aruba, SonicWall, F5, Juniper, VMware ESXi and Okta. Unmapped products are logged as requests.
9
+
10
+ ## Install
11
+
12
+ ```json
13
+ {
14
+ "mcpServers": {
15
+ "scoutwyze-fips": {
16
+ "command": "npx",
17
+ "args": ["-y", "@scoutwyze/fips-mcp"]
18
+ }
19
+ }
20
+ }
21
+ ```
22
+
23
+ Optional env: `SCOUTWYZE_API_KEY` (prepaid key), `SCOUTWYZE_FIPS_BASE_URL` (local development only).
24
+
25
+ ## Tools
26
+
27
+ | Tool | What it does | Cost |
28
+ |---|---|---|
29
+ | `fips_list_products` | Covered products and versions | Free |
30
+ | `fips_lookup` | Status of one product version, with certificates, sunset dates, post-quantum algorithms and receipts | A few free per day, then credits or x402 |
31
+ | `fips_expiring` | Covered versions whose certificates sunset within N days | Free |
32
+ | `fips_batch` | Up to 500 versions in one call | Prepaid credits |
33
+
34
+ Statuses: `ACTIVE`, `EXPIRING` (sunset within 180 days), `HISTORICAL`, `IN_QUEUE`, `NOT_VALIDATED`,
35
+ `UNVERIFIED`. If NIST data is stale, the answer is `UNVERIFIED`, never `ACTIVE`.
36
+
37
+ ## Payments
38
+
39
+ This server never holds a private key or pays anything. A 402 response is returned as tool content;
40
+ a wallet-capable calling agent can pay the x402 challenge (USDC on Base) and retry with `X-PAYMENT`.
41
+
42
+ Not legal or compliance advice. Confirm with your assessor.
package/dist/client.js ADDED
@@ -0,0 +1,29 @@
1
+ // Thin, stateless HTTP client for the ScoutWyze FIPS API. No business logic, no caching,
2
+ // no fallback data: every call either relays the real upstream response or fails closed.
3
+ // This module is the only place that reads SCOUTWYZE_API_KEY; it is never returned or echoed.
4
+ const BASE_URL = process.env.SCOUTWYZE_FIPS_BASE_URL || "https://scoutwyze-fips.fly.dev";
5
+ const API_KEY = process.env.SCOUTWYZE_API_KEY;
6
+ /**
7
+ * Never throws on a non-2xx response: a 402 (free allowance used up, insufficient credits,
8
+ * or an x402 payment challenge) is passed straight through as content. Only throws on a
9
+ * network failure, which callers must report as unreachable rather than invent a result.
10
+ */
11
+ export async function callFips(path, init) {
12
+ const headers = { "content-type": "application/json" };
13
+ if (API_KEY)
14
+ headers["authorization"] = `Bearer ${API_KEY}`;
15
+ const res = await fetch(`${BASE_URL}${path}`, {
16
+ method: init.method,
17
+ headers,
18
+ body: init.body !== undefined ? JSON.stringify(init.body) : undefined,
19
+ });
20
+ let body;
21
+ try {
22
+ body = await res.json();
23
+ }
24
+ catch {
25
+ body = { error: "invalid_upstream_response", message: `Upstream returned HTTP ${res.status} with a non-JSON body.` };
26
+ }
27
+ return { status: res.status, body };
28
+ }
29
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,yFAAyF;AACzF,8FAA8F;AAE9F,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,gCAAgC,CAAC;AACzF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AAO9C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,IAAgD;IAC3F,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;IAC/E,IAAI,OAAO;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,OAAO,EAAE,CAAC;IAE5D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE;QAC5C,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACtE,CAAC,CAAC;IAEH,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,EAAE,KAAK,EAAE,2BAA2B,EAAE,OAAO,EAAE,0BAA0B,GAAG,CAAC,MAAM,wBAAwB,EAAE,CAAC;IACvH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ // ScoutWyze FIPS MCP server: a stateless pass-through to the FIPS status API for MCP hosts
3
+ // (Claude Desktop, Cursor, agent frameworks). Same boundary as the compute MCP server: it never
4
+ // holds a private key and never pays an x402 challenge itself. A 402 is returned as content for
5
+ // a wallet-capable calling agent to settle and retry. Auth is an optional SCOUTWYZE_API_KEY.
6
+ import { createRequire } from "node:module";
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { z } from "zod";
10
+ import { callFips } from "./client.js";
11
+ const pkg = createRequire(import.meta.url)("../package.json");
12
+ const server = new McpServer({ name: "scoutwyze-fips", version: pkg.version, title: "ScoutWyze FIPS" });
13
+ /** 402 (payment needed) and 404 (product not mapped yet, with the list of known products)
14
+ * are normal answers an agent should read, not errors. The body is always the unmodified
15
+ * upstream JSON. */
16
+ function toolResult(status, body) {
17
+ const isError = status >= 400 && status !== 402 && status !== 404;
18
+ return { isError, content: [{ type: "text", text: JSON.stringify(body, null, 2) }] };
19
+ }
20
+ /** Fixed message on network failure; never a cached or invented answer. */
21
+ function unreachableResult() {
22
+ return { isError: true, content: [{ type: "text", text: "ScoutWyze FIPS is unreachable right now. Try again shortly." }] };
23
+ }
24
+ async function relay(path, init) {
25
+ try {
26
+ const { status, body } = await callFips(path, init);
27
+ return toolResult(status, body);
28
+ }
29
+ catch {
30
+ return unreachableResult();
31
+ }
32
+ }
33
+ server.registerTool("fips_list_products", {
34
+ title: "ScoutWyze FIPS: list covered products",
35
+ description: "Free. Lists the products and versions ScoutWyze FIPS covers (vendor, product, aliases, versions). Call this first to pick exact product and version names for fips_lookup.",
36
+ inputSchema: {},
37
+ }, async () => relay("/v1/fips/products", { method: "GET" }));
38
+ server.registerTool("fips_lookup", {
39
+ title: "ScoutWyze FIPS: is this version FIPS 140-3 validated?",
40
+ description: "Returns the FIPS 140-3 status of one product version from NIST CMVP data: ACTIVE, EXPIRING (sunset within 180 days), HISTORICAL, IN_QUEUE (NIST in-process or lab Implementation Under Test list), NOT_VALIDATED or UNVERIFIED, with certificate numbers, sunset dates, post-quantum algorithms and links to the NIST pages used (receipts). The answer is fail-closed: if NIST data is stale it says UNVERIFIED rather than ACTIVE. A few free lookups per day; after that, either set SCOUTWYZE_API_KEY (prepaid credits) or the tool returns an HTTP 402 with an x402 USDC-on-Base challenge that a wallet-capable agent must pay and retry with X-PAYMENT. This server cannot pay it. Unmapped products return 404 with the known list and are always free. Not legal or compliance advice.",
41
+ inputSchema: {
42
+ product: z.string().min(1).max(100).describe('Product name or alias, e.g. "FortiOS", "Windows 11", "RHEL"'),
43
+ version: z.string().max(60).optional().describe('Version, e.g. "7.6", "24H2", "9"'),
44
+ },
45
+ }, async ({ product, version }) => {
46
+ const q = new URLSearchParams({ product });
47
+ if (version)
48
+ q.set("version", version);
49
+ return relay(`/v1/fips/lookup?${q}`, { method: "GET" });
50
+ });
51
+ server.registerTool("fips_expiring", {
52
+ title: "ScoutWyze FIPS: certificates sunsetting soon",
53
+ description: "Free. Lists covered product versions whose FIPS certificates sunset within the given number of days (default 180).",
54
+ inputSchema: { within: z.number().int().min(1).max(3650).optional().describe("Days ahead, default 180") },
55
+ }, async ({ within }) => relay(`/v1/fips/expiring${within ? `?within=${within}` : ""}`, { method: "GET" }));
56
+ server.registerTool("fips_batch", {
57
+ title: "ScoutWyze FIPS: check an inventory",
58
+ description: "Checks up to 500 product versions in one call and returns per-item status plus counts. Requires a prepaid SCOUTWYZE_API_KEY (billed per item; no free tier, no x402). Without a key or credits it returns HTTP 402 with signup and credit-pack details.",
59
+ inputSchema: {
60
+ items: z
61
+ .array(z.object({ product: z.string().min(1).max(100), version: z.string().max(60) }))
62
+ .min(1)
63
+ .max(500)
64
+ .describe('e.g. [{"product":"Windows 11","version":"24H2"}]'),
65
+ },
66
+ }, async ({ items }) => relay("/v1/fips/batch", { method: "POST", body: { items } }));
67
+ await server.connect(new StdioServerTransport());
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,63 @@
1
1
  {
2
2
  "name": "@scoutwyze/fips-mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "mcpName": "io.github.scoutwyze-max/fips-mcp",
6
+ "type": "module",
7
+ "description": "MCP server for ScoutWyze FIPS: is this product version FIPS 140-3 validated, in NIST's queue, or expiring? Answers from NIST CMVP lists with receipts. Stateless pass-through: holds no private keys, never signs or settles a payment itself.",
8
+ "keywords": [
9
+ "mcp",
10
+ "model-context-protocol",
11
+ "fips",
12
+ "fips-140-3",
13
+ "nist",
14
+ "cmvp",
15
+ "cmmc",
16
+ "compliance",
17
+ "x402",
18
+ "scoutwyze"
19
+ ],
20
+ "homepage": "https://scoutwyze-fips.fly.dev",
21
+ "bugs": {
22
+ "url": "https://github.com/scoutwyze-max/fips-mcp/issues"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/scoutwyze-max/fips-mcp.git"
27
+ },
28
+ "license": "MIT",
29
+ "main": "dist/index.js",
30
+ "bin": {
31
+ "scoutwyze-fips-mcp": "dist/index.js"
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc -p tsconfig.json",
41
+ "postbuild": "chmod +x dist/index.js",
42
+ "start": "node dist/index.js",
43
+ "dev": "tsx src/index.ts",
44
+ "prepublishOnly": "npm run build",
45
+ "build:mcpb": "./scripts/build-mcpb.sh"
46
+ },
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "1.30.1",
49
+ "zod": "3.25.76"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "20.19.43",
53
+ "tsx": "4.23.15",
54
+ "typescript": "5.9.3",
55
+ "@anthropic-ai/mcpb": "2.1.2"
56
+ },
57
+ "overrides": {
58
+ "zod": "3.25.76"
59
+ },
60
+ "engines": {
61
+ "node": ">=18"
62
+ }
63
+ }