@nodatachat/mcp 0.7.0 → 0.8.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 +66 -64
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ import { join } from "node:path";
|
|
|
36
36
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
|
|
37
37
|
import { spawn } from "node:child_process";
|
|
38
38
|
import { generateKeyPairSync, createPrivateKey, sign, randomBytes } from "node:crypto";
|
|
39
|
-
const VERSION = "0.
|
|
39
|
+
const VERSION = "0.8.0";
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
// Local credential store — "register once, autoload forever"
|
|
42
42
|
// ---------------------------------------------------------------------------
|
|
@@ -595,58 +595,59 @@ function registerAgentTool(server, baseUrl, grantToken) {
|
|
|
595
595
|
return formatResult(resp);
|
|
596
596
|
});
|
|
597
597
|
}
|
|
598
|
-
const START_ACHIEVEMENT = "WHAT
|
|
599
|
-
" Give any agent real power over your data, without
|
|
600
|
-
" (Possession is not permission:
|
|
601
|
-
// Setup
|
|
602
|
-
//
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
"
|
|
607
|
-
"
|
|
608
|
-
"
|
|
609
|
-
"
|
|
610
|
-
"
|
|
611
|
-
"
|
|
612
|
-
"
|
|
613
|
-
"
|
|
614
|
-
|
|
598
|
+
const START_ACHIEVEMENT = "WHAT NODATA DOES — in one line:\n" +
|
|
599
|
+
" Give any agent real power over your data, without the power to leak it.\n" +
|
|
600
|
+
" (Possession is not permission: it can hold the key and still not read what you didn't allow.)\n";
|
|
601
|
+
// Setup mode: NOT connected yet. The one job here is to switch the tools on, so
|
|
602
|
+
// this is a numbered do-this-exactly list — three steps, not a catalogue. The
|
|
603
|
+
// last line answers the two questions everyone asks: "how do I activate?" (/mcp)
|
|
604
|
+
// and "what about next time?" (nothing).
|
|
605
|
+
const SETUP_STEPS = "TURN THE DATA TOOLS ON — 3 steps, about a minute, once:\n\n" +
|
|
606
|
+
" 1. GET A KEY call nodata_connect (no arguments)\n" +
|
|
607
|
+
" -> opens the signup in your browser: email + company (~30s), a 12-word\n" +
|
|
608
|
+
" recovery phrase to keep, and an ORG KEY shown ONCE. Copy that key.\n\n" +
|
|
609
|
+
" 2. SAVE IT call nodata_connect again, this time with\n" +
|
|
610
|
+
" api_key: \"<the key you copied>\"\n" +
|
|
611
|
+
" -> saved on this machine; you never paste it again.\n\n" +
|
|
612
|
+
" 3. ACTIVATE type /mcp (or restart Claude Code) so the tools load.\n\n" +
|
|
613
|
+
"COMING BACK LATER? Nothing to redo — it starts ready. If the tools look missing, just /mcp.\n";
|
|
614
|
+
// Admin mode: connected. Frame the whole product as the developer's real journey
|
|
615
|
+
// — SEE -> CHOOSE -> PROVE — each step a plain-language ask mapped to a tool.
|
|
616
|
+
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 open https://www.nodatacapsule.com/ai-folder\n" +
|
|
618
|
+
" -> pick a folder; it shows what an AI could read. Nothing uploads.\n\n" +
|
|
619
|
+
" 2. CHOOSE what to release say \"let <agent> read name + plan on <table>, hide the rest\"\n" +
|
|
620
|
+
" -> I run nodata_register_table + nodata_grant; the agent gets a token.\n\n" +
|
|
621
|
+
" 3. PROVE & control the agent now reads ONLY those columns — the rest never decrypt.\n" +
|
|
622
|
+
" \"what did it see?\" -> nodata_evidence · \"cut it off\" -> nodata_revoke\n\n" +
|
|
623
|
+
"Also: a secret even NoData can't read -> nodata_encrypt, then hand it over once -> nodata_deliver.\n";
|
|
615
624
|
// The agent-scoped reader IS the governed agent: it holds only decide/retrieve/read/use,
|
|
616
|
-
// so its
|
|
617
|
-
const START_OUTCOMES_AGENT = "WHAT YOU CAN DO — scoped to your grant
|
|
618
|
-
"
|
|
619
|
-
"
|
|
620
|
-
"
|
|
621
|
-
"
|
|
622
|
-
|
|
623
|
-
"
|
|
624
|
-
"
|
|
625
|
-
"
|
|
626
|
-
"
|
|
627
|
-
" Invoke a pre-registered capability; the Capsule injects the sealed credential server-side and\n" +
|
|
628
|
-
" returns only the result. The secret never reaches you.\n" +
|
|
629
|
-
" Start: nodata_use.\n";
|
|
630
|
-
const START_UNSTUCK = "IF IT SEEMS STUCK — there is always a next step:\n" +
|
|
631
|
-
" - Don't see the nodata_* tools yet? They load when the MCP client starts. Restart Claude Code\n" +
|
|
632
|
-
" (or run /mcp). This is expected, not an error.\n" +
|
|
633
|
-
" - No MCP at all, or it won't connect? The same governance runs without it — one curl, or the\n" +
|
|
634
|
-
" guided page at https://www.nodatacapsule.com/developers/get-started\n";
|
|
625
|
+
// so its steps name those verbs (pointing it at admin tools it lacks would dead-end it).
|
|
626
|
+
const START_OUTCOMES_AGENT = "WHAT YOU CAN DO — scoped to your grant; you reach only what it allows, the rest never decrypts:\n\n" +
|
|
627
|
+
" 1. PLAN nodata_decide \"may I reach X?\" -> allow / partial / deny + a signed proof. No data moves.\n" +
|
|
628
|
+
" 2. PULL nodata_retrieve prompt-ready context, allowed fields only, with a receipt.\n" +
|
|
629
|
+
" (nodata_read for raw governed rows.)\n" +
|
|
630
|
+
" 3. ACT nodata_use run a capability with a secret injected server-side — you never see it.\n";
|
|
631
|
+
const START_UNSTUCK = "STUCK? There's always a next step:\n" +
|
|
632
|
+
" - Don't see the nodata_* tools? They load when the client starts — type /mcp or restart.\n" +
|
|
633
|
+
" (Expected, not an error.)\n" +
|
|
634
|
+
" - No MCP at all? The same governance runs from one curl, or the guided page:\n" +
|
|
635
|
+
" https://www.nodatacapsule.com/developers/get-started\n";
|
|
635
636
|
function startHeader(mode) {
|
|
636
637
|
if (mode === "setup") {
|
|
637
|
-
return
|
|
638
|
-
"Fastest unlock — nothing to retype: call nodata_connect. It opens the free signup in your\n" +
|
|
639
|
-
"browser (email + company, ~30s, with your recovery phrase + email verify), then you call it\n" +
|
|
640
|
-
"once more with the key it shows and it's SAVED — every later start comes up ready, and the\n" +
|
|
641
|
-
"only step left is one /mcp so the client reloads the tools.\n\n");
|
|
638
|
+
return "You're connected to NoData — but there's NO key yet, so the data tools are still off.\n\n";
|
|
642
639
|
}
|
|
643
640
|
if (mode === "agent") {
|
|
644
|
-
return
|
|
645
|
-
"allows, and denied fields never decrypt for you. Plan with nodata_decide, then nodata_retrieve.\n\n");
|
|
641
|
+
return "You're connected to NoData, scoped to one grant token.\n\n";
|
|
646
642
|
}
|
|
647
|
-
return "You're connected to NoData (admin).
|
|
643
|
+
return "You're connected to NoData (admin mode). You don't memorize commands — just ask in plain words.\n\n";
|
|
648
644
|
}
|
|
649
645
|
function getStartedText(mode) {
|
|
646
|
+
// Setup leads with the 3 connect steps (the only thing that matters when off);
|
|
647
|
+
// admin/agent lead with the journey they can act on right now.
|
|
648
|
+
if (mode === "setup") {
|
|
649
|
+
return startHeader(mode) + START_ACHIEVEMENT + "\n" + SETUP_STEPS + "\n" + START_UNSTUCK;
|
|
650
|
+
}
|
|
650
651
|
const outcomes = mode === "agent" ? START_OUTCOMES_AGENT : START_OUTCOMES_ADMIN;
|
|
651
652
|
return startHeader(mode) + START_ACHIEVEMENT + "\n" + outcomes + "\n" + START_UNSTUCK;
|
|
652
653
|
}
|
|
@@ -687,11 +688,11 @@ function openInBrowser(url) {
|
|
|
687
688
|
}
|
|
688
689
|
function registerConnectTool(server, baseUrl) {
|
|
689
690
|
server.registerTool("nodata_connect", {
|
|
690
|
-
description: "Switch NoData's data tools on.
|
|
691
|
-
"browser (email + company, ~30s — also where your recovery phrase + email verification " +
|
|
692
|
-
"happen)
|
|
693
|
-
"is saved
|
|
694
|
-
"
|
|
691
|
+
description: "Switch NoData's data tools on. Step 1: call with NO arguments to open the free signup in a " +
|
|
692
|
+
"browser (email + company, ~30s — also where your 12-word recovery phrase + email verification " +
|
|
693
|
+
"happen); it shows an ORG KEY once. Step 2: call this tool again with that key as `api_key` and " +
|
|
694
|
+
"it is saved on this machine, so every later start comes up ready with nothing to retype. " +
|
|
695
|
+
"Step 3: type /mcp (or restart) so the client loads the tools.",
|
|
695
696
|
inputSchema: {
|
|
696
697
|
api_key: z
|
|
697
698
|
.string()
|
|
@@ -708,15 +709,16 @@ function registerConnectTool(server, baseUrl) {
|
|
|
708
709
|
content: [
|
|
709
710
|
{
|
|
710
711
|
type: "text",
|
|
711
|
-
text: (opened ? "
|
|
712
|
+
text: (opened ? "STEP 1 of 3 — opened the NoData signup in your browser:\n " : "STEP 1 of 3 — open the NoData signup in your browser:\n ") +
|
|
712
713
|
url +
|
|
713
714
|
"\n\n" +
|
|
714
|
-
"
|
|
715
|
-
"
|
|
716
|
-
"is the only way back into
|
|
717
|
-
"
|
|
718
|
-
|
|
719
|
-
|
|
715
|
+
"There, about a minute:\n" +
|
|
716
|
+
" - email + company (a personal email is fine for the sandbox)\n" +
|
|
717
|
+
" - a 12-WORD RECOVERY PHRASE — save it; it is the only way back into your org\n" +
|
|
718
|
+
" - your ORG KEY, shown ONCE — copy it\n\n" +
|
|
719
|
+
"STEP 2 — come back and call this tool again with the key:\n" +
|
|
720
|
+
' nodata_connect api_key: "<the key you copied>"\n' +
|
|
721
|
+
"and I'll save it so you never paste it again. (Then STEP 3: type /mcp to activate.)",
|
|
720
722
|
},
|
|
721
723
|
],
|
|
722
724
|
};
|
|
@@ -762,10 +764,10 @@ function registerConnectTool(server, baseUrl) {
|
|
|
762
764
|
content: [
|
|
763
765
|
{
|
|
764
766
|
type: "text",
|
|
765
|
-
text: `
|
|
766
|
-
"at ~/.nodata/credentials.json (readable only by you). The org key you pasted was NOT
|
|
767
|
-
"every start now proves possession by signing a fresh challenge and gets a 15-minute token.\n\n" +
|
|
768
|
-
"
|
|
767
|
+
text: `STEP 2 done — this device is enrolled as "${label}" (${handle}), and only its PRIVATE key is\n` +
|
|
768
|
+
"saved at ~/.nodata/credentials.json (readable only by you). The org key you pasted was NOT\n" +
|
|
769
|
+
"stored: every start now proves possession by signing a fresh challenge and gets a 15-minute token.\n\n" +
|
|
770
|
+
"STEP 3 — type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.",
|
|
769
771
|
},
|
|
770
772
|
],
|
|
771
773
|
};
|
|
@@ -793,10 +795,10 @@ function registerConnectTool(server, baseUrl) {
|
|
|
793
795
|
{
|
|
794
796
|
type: "text",
|
|
795
797
|
text: (attestUnavailable
|
|
796
|
-
? "
|
|
797
|
-
: `
|
|
798
|
+
? "STEP 2 done — saved your key on this machine (device attestation isn't available on this\nserver yet, so this is the key-at-rest path). "
|
|
799
|
+
: `STEP 2 done — saved your key on this machine (device enrollment didn't succeed: ${enrolled.error}). `) +
|
|
798
800
|
"Every future start loads it automatically — no re-register, no re-paste.\n\n" +
|
|
799
|
-
"
|
|
801
|
+
"STEP 3 — type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.",
|
|
800
802
|
},
|
|
801
803
|
],
|
|
802
804
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodatachat/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
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",
|
|
5
5
|
"bin": {
|
|
6
6
|
"nodata-mcp": "dist/index.js"
|