0nmcp 2.2.0 → 2.3.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/cli.js +143 -0
- package/lib/badges.json +5 -5
- package/lib/catalog.json +653 -3
- package/lib/stats.json +647 -35
- package/package.json +12 -10
- package/vault/sync.js +250 -0
package/cli.js
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* npx 0nmcp Start MCP server (stdio)
|
|
9
|
+
* npx 0nmcp login Authenticate with 0nmcp.com (device auth flow)
|
|
10
|
+
* npx 0nmcp logout Revoke token and clear local auth
|
|
11
|
+
* npx 0nmcp whoami Show authenticated user info
|
|
9
12
|
* npx 0nmcp serve Start HTTP server (REST + MCP + webhooks)
|
|
10
13
|
* npx 0nmcp run <wf> Run a .0n workflow from CLI
|
|
11
14
|
* npx 0nmcp init Initialize ~/.0n directory
|
|
@@ -17,6 +20,8 @@
|
|
|
17
20
|
* npx 0nmcp migrate Migrate from ~/.0nmcp to ~/.0n
|
|
18
21
|
* npx 0nmcp engine Engine commands (import, verify, platforms, export, open)
|
|
19
22
|
* npx 0nmcp app Application commands (run, build, inspect, validate, list)
|
|
23
|
+
* npx 0nmcp vault sync Push local credentials to cloud (E2E encrypted)
|
|
24
|
+
* npx 0nmcp vault pull Pull credentials from cloud to local
|
|
20
25
|
*
|
|
21
26
|
* ═══════════════════════════════════════════════════════════════════════════
|
|
22
27
|
*/
|
|
@@ -71,6 +76,33 @@ async function main() {
|
|
|
71
76
|
return;
|
|
72
77
|
}
|
|
73
78
|
|
|
79
|
+
// ── Auth commands (no login required) ──────────────────────
|
|
80
|
+
|
|
81
|
+
if (command === 'login') {
|
|
82
|
+
console.log(BANNER);
|
|
83
|
+
const { login } = await import('./auth.js');
|
|
84
|
+
await login();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (command === 'logout') {
|
|
89
|
+
const { logout } = await import('./auth.js');
|
|
90
|
+
await logout();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (command === 'whoami') {
|
|
95
|
+
const { whoami } = await import('./auth.js');
|
|
96
|
+
await whoami();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (command === 'version' || command === '--version' || command === '-v') {
|
|
101
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
102
|
+
console.log(`0nmcp v${pkg.version}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
74
106
|
// Help
|
|
75
107
|
if (command === 'help' || command === '--help' || command === '-h') {
|
|
76
108
|
console.log(BANNER);
|
|
@@ -78,6 +110,9 @@ async function main() {
|
|
|
78
110
|
${c.bright}Usage:${c.reset}
|
|
79
111
|
|
|
80
112
|
${c.cyan}npx 0nmcp${c.reset} Start MCP server (stdio, for Claude Desktop)
|
|
113
|
+
${c.cyan}npx 0nmcp login${c.reset} Authenticate with 0nmcp.com
|
|
114
|
+
${c.cyan}npx 0nmcp logout${c.reset} Revoke token and clear local auth
|
|
115
|
+
${c.cyan}npx 0nmcp whoami${c.reset} Show authenticated user info
|
|
81
116
|
${c.cyan}npx 0nmcp serve${c.reset} Start HTTP server (REST + MCP + webhooks)
|
|
82
117
|
${c.cyan}npx 0nmcp run <wf>${c.reset} Run a .0n workflow from CLI
|
|
83
118
|
${c.cyan}npx 0nmcp init${c.reset} Initialize ~/.0n directory
|
|
@@ -157,6 +192,23 @@ ${c.bright}Links:${c.reset}
|
|
|
157
192
|
return;
|
|
158
193
|
}
|
|
159
194
|
|
|
195
|
+
// ── Auth Gate ──────────────────────────────────────────────
|
|
196
|
+
// All commands below this point require authentication.
|
|
197
|
+
const AUTH_FREE = ['help', '--help', '-h', 'login', 'logout', 'whoami', 'version', '--version', '-v'];
|
|
198
|
+
if (!AUTH_FREE.includes(command)) {
|
|
199
|
+
try {
|
|
200
|
+
const { isAuthenticated } = await import('./auth.js');
|
|
201
|
+
if (!await isAuthenticated()) {
|
|
202
|
+
console.log(`\n${c.red}${c.bright} Authentication required.${c.reset}`);
|
|
203
|
+
console.log(` Run: ${c.cyan}0nmcp login${c.reset}\n`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
// Auth module load failure — allow through for local-only ops
|
|
208
|
+
// This handles cases where the module has issues
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
160
212
|
// Init
|
|
161
213
|
if (command === 'init') {
|
|
162
214
|
console.log(BANNER);
|
|
@@ -586,6 +638,12 @@ ${c.bright}Vault Container Commands${c.reset} ${c.yellow}(Patent Pending #63/990
|
|
|
586
638
|
|
|
587
639
|
${c.cyan}vault revoke <id>${c.reset} Revoke a transfer ID
|
|
588
640
|
|
|
641
|
+
${c.bright}Vault Sync (E2E Encrypted):${c.reset}
|
|
642
|
+
|
|
643
|
+
${c.cyan}vault sync${c.reset} Push local credentials to cloud (encrypted)
|
|
644
|
+
${c.cyan}vault pull${c.reset} Pull credentials from cloud to local
|
|
645
|
+
${c.cyan}vault sync-passphrase${c.reset} Set/change your sync passphrase
|
|
646
|
+
|
|
589
647
|
${c.bright}7 Semantic Layers:${c.reset}
|
|
590
648
|
workflows, credentials, env_vars, mcp_configs,
|
|
591
649
|
site_profiles, ai_brain, audit_trail
|
|
@@ -593,6 +651,91 @@ ${c.bright}7 Semantic Layers:${c.reset}
|
|
|
593
651
|
return;
|
|
594
652
|
}
|
|
595
653
|
|
|
654
|
+
// ── Vault Sync Commands ──────────────────────────────────
|
|
655
|
+
|
|
656
|
+
if (sub === 'sync' && args[1] !== 'passphrase') {
|
|
657
|
+
const { getToken } = await import('./auth.js');
|
|
658
|
+
const { pushToCloud } = await import('./vault/sync.js');
|
|
659
|
+
|
|
660
|
+
const token = await getToken();
|
|
661
|
+
if (!token) {
|
|
662
|
+
console.log(`${c.red}Not authenticated. Run: ${c.cyan}0nmcp login${c.reset}`);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const passphrase = getFlag(args, '--passphrase') || await promptInput('Sync passphrase: ');
|
|
667
|
+
if (!passphrase) {
|
|
668
|
+
console.log(`${c.red}Passphrase required for E2E encryption.${c.reset}`);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
console.log(`\n${c.bright}Encrypting and pushing to cloud...${c.reset}`);
|
|
673
|
+
const { pushed, errors } = await pushToCloud(token, passphrase);
|
|
674
|
+
|
|
675
|
+
console.log(`\n${c.green}✓${c.reset} Pushed ${c.bright}${pushed}${c.reset} credentials (E2E encrypted)`);
|
|
676
|
+
if (errors.length > 0) {
|
|
677
|
+
console.log(`${c.red}Errors:${c.reset}`);
|
|
678
|
+
for (const err of errors) console.log(` ${c.red}●${c.reset} ${err}`);
|
|
679
|
+
}
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (sub === 'pull') {
|
|
684
|
+
const { getToken } = await import('./auth.js');
|
|
685
|
+
const { pullFromCloud } = await import('./vault/sync.js');
|
|
686
|
+
|
|
687
|
+
const token = await getToken();
|
|
688
|
+
if (!token) {
|
|
689
|
+
console.log(`${c.red}Not authenticated. Run: ${c.cyan}0nmcp login${c.reset}`);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const passphrase = getFlag(args, '--passphrase') || await promptInput('Sync passphrase: ');
|
|
694
|
+
if (!passphrase) {
|
|
695
|
+
console.log(`${c.red}Passphrase required to decrypt credentials.${c.reset}`);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
console.log(`\n${c.bright}Pulling and decrypting from cloud...${c.reset}`);
|
|
700
|
+
const { pulled, errors } = await pullFromCloud(token, passphrase);
|
|
701
|
+
|
|
702
|
+
console.log(`\n${c.green}✓${c.reset} Pulled ${c.bright}${pulled}${c.reset} credentials to ~/.0n/connections/`);
|
|
703
|
+
if (errors.length > 0) {
|
|
704
|
+
console.log(`${c.red}Errors:${c.reset}`);
|
|
705
|
+
for (const err of errors) console.log(` ${c.red}●${c.reset} ${err}`);
|
|
706
|
+
}
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (sub === 'sync-passphrase') {
|
|
711
|
+
const { markSyncSetup, hasSyncSetup } = await import('./vault/sync.js');
|
|
712
|
+
|
|
713
|
+
if (hasSyncSetup()) {
|
|
714
|
+
console.log(`${c.yellow}Sync passphrase was previously configured.${c.reset}`);
|
|
715
|
+
console.log(`${c.dim}Use your existing passphrase with ${c.cyan}vault sync${c.reset}${c.dim} and ${c.cyan}vault pull${c.reset}${c.dim}.${c.reset}`);
|
|
716
|
+
console.log(`${c.dim}To change it, use a new passphrase — but you'll need to re-sync all credentials.${c.reset}\n`);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const pass1 = await promptInput('New sync passphrase: ');
|
|
720
|
+
const pass2 = await promptInput('Confirm passphrase: ');
|
|
721
|
+
|
|
722
|
+
if (pass1 !== pass2) {
|
|
723
|
+
console.log(`${c.red}Passphrases do not match.${c.reset}`);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (pass1.length < 8) {
|
|
728
|
+
console.log(`${c.red}Passphrase must be at least 8 characters.${c.reset}`);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
markSyncSetup();
|
|
733
|
+
console.log(`\n${c.green}✓${c.reset} Sync passphrase configured.`);
|
|
734
|
+
console.log(`${c.dim}Use ${c.cyan}vault sync${c.reset}${c.dim} to push credentials to cloud.${c.reset}`);
|
|
735
|
+
console.log(`${c.dim}Use ${c.cyan}vault pull${c.reset}${c.dim} on another device to pull them down.${c.reset}\n`);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
|
|
596
739
|
if (sub === 'create') {
|
|
597
740
|
const { assembleContainer, saveContainer } = await import('./vault/container.js');
|
|
598
741
|
const { LAYER_NAMES } = await import('./vault/layers.js');
|
package/lib/badges.json
CHANGED
|
@@ -2,31 +2,31 @@
|
|
|
2
2
|
"tools": {
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"label": "tools",
|
|
5
|
-
"message": "
|
|
5
|
+
"message": "545",
|
|
6
6
|
"color": "00ff88"
|
|
7
7
|
},
|
|
8
8
|
"services": {
|
|
9
9
|
"schemaVersion": 1,
|
|
10
10
|
"label": "services",
|
|
11
|
-
"message": "
|
|
11
|
+
"message": "48",
|
|
12
12
|
"color": "00d4ff"
|
|
13
13
|
},
|
|
14
14
|
"actions": {
|
|
15
15
|
"schemaVersion": 1,
|
|
16
16
|
"label": "actions",
|
|
17
|
-
"message": "
|
|
17
|
+
"message": "104",
|
|
18
18
|
"color": "ff6b35"
|
|
19
19
|
},
|
|
20
20
|
"triggers": {
|
|
21
21
|
"schemaVersion": 1,
|
|
22
22
|
"label": "triggers",
|
|
23
|
-
"message": "
|
|
23
|
+
"message": "155",
|
|
24
24
|
"color": "9945ff"
|
|
25
25
|
},
|
|
26
26
|
"total": {
|
|
27
27
|
"schemaVersion": 1,
|
|
28
28
|
"label": "capabilities",
|
|
29
|
-
"message": "
|
|
29
|
+
"message": "1078",
|
|
30
30
|
"color": "00ff88"
|
|
31
31
|
}
|
|
32
32
|
}
|