@nodatachat/mcp 0.8.0 → 0.9.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/dist/index.js +71 -4
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -31,12 +31,16 @@
|
|
|
31
31
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
32
32
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
33
33
|
import { z } from "zod";
|
|
34
|
+
// Our deepest content scanner, shipped as its own zero-dep, Node-native npm
|
|
35
|
+
// package. nodata_scan_folder wires to it directly (not a reimplementation) so
|
|
36
|
+
// the "SEE what's sensitive" step runs INSIDE this one command, entirely local.
|
|
37
|
+
import { runFolderScan, silentLogger, formatFolderScan } from "@nodatachat/folder-scan";
|
|
34
38
|
import { homedir, hostname } from "node:os";
|
|
35
|
-
import { join } from "node:path";
|
|
39
|
+
import { join, resolve, basename } from "node:path";
|
|
36
40
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
|
|
37
41
|
import { spawn } from "node:child_process";
|
|
38
42
|
import { generateKeyPairSync, createPrivateKey, sign, randomBytes } from "node:crypto";
|
|
39
|
-
const VERSION = "0.
|
|
43
|
+
const VERSION = "0.9.0";
|
|
40
44
|
// ---------------------------------------------------------------------------
|
|
41
45
|
// Local credential store — "register once, autoload forever"
|
|
42
46
|
// ---------------------------------------------------------------------------
|
|
@@ -614,8 +618,8 @@ const SETUP_STEPS = "TURN THE DATA TOOLS ON — 3 steps, about a minute, once:\n
|
|
|
614
618
|
// Admin mode: connected. Frame the whole product as the developer's real journey
|
|
615
619
|
// — SEE -> CHOOSE -> PROVE — each step a plain-language ask mapped to a tool.
|
|
616
620
|
const START_OUTCOMES_ADMIN = "NOW — TURN YOUR DATA INTO AN AGENT THAT CAN'T LEAK, in 3 asks (just say them in plain words):\n\n" +
|
|
617
|
-
" 1. SEE what's sensitive
|
|
618
|
-
"
|
|
621
|
+
" 1. SEE what's sensitive run nodata_scan_folder — scans a local folder right here, nothing\n" +
|
|
622
|
+
" uploads (or open https://www.nodatacapsule.com/ai-folder in a browser).\n\n" +
|
|
619
623
|
" 2. CHOOSE what to release say \"let <agent> read name + plan on <table>, hide the rest\"\n" +
|
|
620
624
|
" -> I run nodata_register_table + nodata_grant; the agent gets a token.\n\n" +
|
|
621
625
|
" 3. PROVE & control the agent now reads ONLY those columns — the rest never decrypt.\n" +
|
|
@@ -805,6 +809,65 @@ function registerConnectTool(server, baseUrl) {
|
|
|
805
809
|
});
|
|
806
810
|
}
|
|
807
811
|
// ---------------------------------------------------------------------------
|
|
812
|
+
// nodata_scan_folder — SEE what's sensitive, locally, before you govern it
|
|
813
|
+
// ---------------------------------------------------------------------------
|
|
814
|
+
// The journey's first step ("SEE") brought inside the one command. It runs our
|
|
815
|
+
// deep content scanner (the published @nodatachat/folder-scan — the same detection
|
|
816
|
+
// engine the NoData agent uses: 24 secret patterns + checksum-validated PII, and
|
|
817
|
+
// PDF/Office text extraction) ENTIRELY on this machine — nothing uploads — over a
|
|
818
|
+
// folder the developer names, then points at register_table + grant for what it
|
|
819
|
+
// surfaces. Local compute needs no credential, so this is offered even in setup
|
|
820
|
+
// mode: scan before you even sign up.
|
|
821
|
+
function formatScanReport(r) {
|
|
822
|
+
// The neutral report comes from the scanner package (shared with its CLI);
|
|
823
|
+
// the MCP only adds the governance bridge — turn what the scan surfaced into
|
|
824
|
+
// the next step of the same journey.
|
|
825
|
+
const base = formatFolderScan(r);
|
|
826
|
+
if (r.error)
|
|
827
|
+
return base;
|
|
828
|
+
return (base +
|
|
829
|
+
"\n\nGOVERN what it surfaced — same journey, inside this command:\n" +
|
|
830
|
+
" · CHOOSE what an agent may read: nodata_register_table then nodata_grant (denied columns never decrypt)\n" +
|
|
831
|
+
" · PROVE every access afterwards: nodata_evidence\n" +
|
|
832
|
+
"\nWant a standalone deep scan any time? npx @nodatachat/folder-scan (this same engine).");
|
|
833
|
+
}
|
|
834
|
+
function registerScanFolderTool(server) {
|
|
835
|
+
server.registerTool("nodata_scan_folder", {
|
|
836
|
+
description: "SEE what's sensitive before you govern it. Scans a LOCAL folder for hardcoded secrets and unencrypted PII (checksum-validated — Israeli ID / Luhn credit-card / IBAN) with NoData's deep content scanner, reading PDFs and Office files too, ENTIRELY on this machine — nothing uploads, no credential needed. Returns the findings by file and severity plus the first fix, then points at nodata_register_table + nodata_grant to govern what it found. If the user asks to scan / audit / check a folder or repo for sensitive data, secrets, or exposure, call this.",
|
|
837
|
+
inputSchema: {
|
|
838
|
+
path: z
|
|
839
|
+
.string()
|
|
840
|
+
.optional()
|
|
841
|
+
.describe("Folder to scan (absolute or relative). Default: the directory the server runs in."),
|
|
842
|
+
},
|
|
843
|
+
}, async ({ path: scanPath }) => {
|
|
844
|
+
const dir = (scanPath ?? ".").trim() || ".";
|
|
845
|
+
const absDir = resolve(dir);
|
|
846
|
+
if (!existsSync(absDir)) {
|
|
847
|
+
return {
|
|
848
|
+
content: [{ type: "text", text: `No folder found at: ${absDir}\nPass an existing path, e.g. nodata_scan_folder path: "."` }],
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
try {
|
|
852
|
+
// Deep scanner: async, takes an injected logger. silentLogger keeps the
|
|
853
|
+
// MCP's stdout (JSON-RPC) clean; the scan never writes to stdout itself.
|
|
854
|
+
const report = await runFolderScan({
|
|
855
|
+
target_id: "mcp",
|
|
856
|
+
target_label: basename(absDir),
|
|
857
|
+
target_path: absDir,
|
|
858
|
+
log: silentLogger,
|
|
859
|
+
});
|
|
860
|
+
return { content: [{ type: "text", text: formatScanReport(report) }] };
|
|
861
|
+
}
|
|
862
|
+
catch (e) {
|
|
863
|
+
return {
|
|
864
|
+
content: [{ type: "text", text: `Scan failed: ${e instanceof Error ? e.message : String(e)}` }],
|
|
865
|
+
isError: true,
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
// ---------------------------------------------------------------------------
|
|
808
871
|
// Server setup
|
|
809
872
|
// ---------------------------------------------------------------------------
|
|
810
873
|
async function main() {
|
|
@@ -823,6 +886,10 @@ async function main() {
|
|
|
823
886
|
if (grantToken)
|
|
824
887
|
registerAgentTool(server, baseUrl, grantToken);
|
|
825
888
|
registerGetStarted(server, mode);
|
|
889
|
+
// The local exposure scan needs no credential — offer it wherever the owner is
|
|
890
|
+
// driving (setup, before signup, or admin), just not to a scoped agent.
|
|
891
|
+
if (mode !== "agent")
|
|
892
|
+
registerScanFolderTool(server);
|
|
826
893
|
if (mode === "setup") {
|
|
827
894
|
registerConnectTool(server, baseUrl);
|
|
828
895
|
console.error("nodata-mcp: no credential given — running in setup mode (data tools disabled).\n" +
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodatachat/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "NoData MCP Server — govern data AND code for AI agents: decide (may I?) + retrieve (authorized context) + read + secret-blind invoke + blind code advise/patch (fix code without exposure), plus admin governance/encrypt/decrypt/deliver",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "NoData MCP Server — scan a folder for exposure (locally, nothing uploads) + govern data AND code for AI agents: decide (may I?) + retrieve (authorized context) + read + secret-blind invoke + blind code advise/patch (fix code without exposure), plus admin governance/encrypt/decrypt/deliver",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nodata-mcp": "dist/index.js"
|
|
7
7
|
},
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
16
|
+
"@nodatachat/folder-scan": "^1.0.0",
|
|
16
17
|
"zod": "^4.0.0"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|