neozip-mcp 0.1.0-beta

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.
Files changed (113) hide show
  1. package/.cursor/mcp.json.global.example +10 -0
  2. package/CHANGELOG.md +16 -0
  3. package/DOCUMENTATION.md +40 -0
  4. package/LICENSE +16 -0
  5. package/README.md +223 -0
  6. package/SECURITY.md +37 -0
  7. package/dist/account/account-state.js +86 -0
  8. package/dist/account/format-account-status.js +37 -0
  9. package/dist/account/identity-provision.js +75 -0
  10. package/dist/account/identity-wrap.js +69 -0
  11. package/dist/account/profile-crypto.js +47 -0
  12. package/dist/account/profile-store.js +108 -0
  13. package/dist/account/require-account.js +29 -0
  14. package/dist/account/token-service-identity.js +395 -0
  15. package/dist/account/types.js +2 -0
  16. package/dist/account/wallet-evm.js +39 -0
  17. package/dist/archive/blockchain-status.js +303 -0
  18. package/dist/archive/crypto-self.js +114 -0
  19. package/dist/archive/detect-text.js +56 -0
  20. package/dist/archive/embed-metadata.js +283 -0
  21. package/dist/archive/encryption.js +166 -0
  22. package/dist/archive/extract-entry-buffer.js +18 -0
  23. package/dist/archive/find-entry.js +21 -0
  24. package/dist/archive/grep-content.js +141 -0
  25. package/dist/archive/identity-key.js +176 -0
  26. package/dist/archive/manifest.js +55 -0
  27. package/dist/archive/merkle.js +31 -0
  28. package/dist/archive/metadata-paths.js +14 -0
  29. package/dist/archive/mint-archive.js +61 -0
  30. package/dist/archive/open-archive.js +23 -0
  31. package/dist/archive/read-entry-buffer.js +11 -0
  32. package/dist/archive/read-entry-content.js +51 -0
  33. package/dist/archive/recipient-access.js +26 -0
  34. package/dist/archive/recipient-decrypt.js +21 -0
  35. package/dist/archive/recipient-lookup.js +55 -0
  36. package/dist/archive/timestamp-network.js +54 -0
  37. package/dist/config/capabilities.js +37 -0
  38. package/dist/config/index.js +74 -0
  39. package/dist/connect-cli.js +312 -0
  40. package/dist/connection/coordinator.js +74 -0
  41. package/dist/connection/credentials.js +29 -0
  42. package/dist/connection/crypto.js +56 -0
  43. package/dist/connection/dump.js +79 -0
  44. package/dist/connection/incomplete-setup.js +81 -0
  45. package/dist/connection/interactive.js +814 -0
  46. package/dist/connection/legacy-profile-reader.js +47 -0
  47. package/dist/connection/magic-link.js +138 -0
  48. package/dist/connection/migrate.js +76 -0
  49. package/dist/connection/onboarding.js +524 -0
  50. package/dist/connection/origin.js +63 -0
  51. package/dist/connection/phase.js +93 -0
  52. package/dist/connection/phone.js +20 -0
  53. package/dist/connection/promote-active.js +53 -0
  54. package/dist/connection/reset.js +20 -0
  55. package/dist/connection/setup-guidance.js +154 -0
  56. package/dist/connection/status-report.js +40 -0
  57. package/dist/connection/store.js +352 -0
  58. package/dist/connection/token-auth.js +42 -0
  59. package/dist/connection/types.js +2 -0
  60. package/dist/connection/wallet-setup.js +70 -0
  61. package/dist/constants/wallet-identity.js +11 -0
  62. package/dist/index.js +47 -0
  63. package/dist/load-env.js +16 -0
  64. package/dist/neozipkit-node.js +11 -0
  65. package/dist/register/resources.js +14 -0
  66. package/dist/register/tools.js +77 -0
  67. package/dist/resources/zip-resource.js +40 -0
  68. package/dist/resources/zip-uri.js +23 -0
  69. package/dist/security/auth.js +28 -0
  70. package/dist/security/capabilities.js +85 -0
  71. package/dist/security/rate-limiter.js +43 -0
  72. package/dist/security/resource-limiter.js +44 -0
  73. package/dist/security/sandbox.js +61 -0
  74. package/dist/server.js +32 -0
  75. package/dist/startup-account-gate.js +101 -0
  76. package/dist/startup-summary.js +40 -0
  77. package/dist/token-service/require-configured.js +23 -0
  78. package/dist/tools/account.js +504 -0
  79. package/dist/tools/compress.js +237 -0
  80. package/dist/tools/connect-status.js +143 -0
  81. package/dist/tools/extract.js +62 -0
  82. package/dist/tools/grep-entries.js +42 -0
  83. package/dist/tools/identity-status.js +157 -0
  84. package/dist/tools/info.js +147 -0
  85. package/dist/tools/list.js +118 -0
  86. package/dist/tools/lookup-recipient.js +37 -0
  87. package/dist/tools/mint.js +41 -0
  88. package/dist/tools/read-entry.js +35 -0
  89. package/dist/tools/search-entries.js +71 -0
  90. package/dist/tools/stamp.js +60 -0
  91. package/dist/tools/test.js +90 -0
  92. package/dist/tools/token-service-account.js +143 -0
  93. package/dist/tools/upgrade.js +60 -0
  94. package/dist/tools/verify.js +75 -0
  95. package/dist/tools/wallet-config-status.js +119 -0
  96. package/dist/tools/wallet-info.js +64 -0
  97. package/dist/translators/index.js +106 -0
  98. package/dist/types/index.js +7 -0
  99. package/dist/util/mask.js +30 -0
  100. package/dist/util/token-service-fetch.js +23 -0
  101. package/dist/vendor/neozipkit-pro.js +3 -0
  102. package/docs/NEOZIP_CONNECTION_STORE.md +238 -0
  103. package/docs/NEOZIP_CONNECT_CLI.md +185 -0
  104. package/docs/OPERATIONS.md +992 -0
  105. package/docs/examples/CLAUDE.md.example +22 -0
  106. package/docs/examples/claude/skills/neozip-mcp/SKILL.md +54 -0
  107. package/docs/examples/claude/skills/neozip-notarization/SKILL.md +75 -0
  108. package/docs/examples/mcp.json.claude.example +11 -0
  109. package/docs/examples/neozip-mcp-cursor-rule.mdc +31 -0
  110. package/docs/installation-guides/INSTALL_CLAUDE_CODE.md +286 -0
  111. package/docs/installation-guides/INSTALL_CLAUDE_WORKSPACE.md +301 -0
  112. package/docs/installation-guides/README.md +76 -0
  113. package/package.json +99 -0
@@ -0,0 +1,47 @@
1
+ import * as fs from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { decryptJson } from "../account/profile-crypto.js";
5
+ export const LEGACY_MCP_PROFILE_DIR = process.env.NEOZIP_MCP_PROFILE_DIR?.trim() ||
6
+ path.join(os.homedir(), ".neozip", "mcp");
7
+ const PROFILES_PATH = () => path.join(LEGACY_MCP_PROFILE_DIR, "profiles.json");
8
+ const ACTIVE_PATH = () => path.join(LEGACY_MCP_PROFILE_DIR, "active.json");
9
+ const SECRETS_DIR = () => path.join(LEGACY_MCP_PROFILE_DIR, "secrets");
10
+ function readProfilesFile() {
11
+ if (!fs.existsSync(PROFILES_PATH())) {
12
+ return { version: 1, profiles: [] };
13
+ }
14
+ return JSON.parse(fs.readFileSync(PROFILES_PATH(), "utf8"));
15
+ }
16
+ export function listLegacyProfiles() {
17
+ return readProfilesFile().profiles;
18
+ }
19
+ export function getLegacyActiveProfileId() {
20
+ if (!fs.existsSync(ACTIVE_PATH()))
21
+ return null;
22
+ const active = JSON.parse(fs.readFileSync(ACTIVE_PATH(), "utf8"));
23
+ return active.profileId;
24
+ }
25
+ export function readLegacySecrets(profileId) {
26
+ const sp = path.join(SECRETS_DIR(), `${profileId}.json.enc`);
27
+ if (!fs.existsSync(sp))
28
+ return null;
29
+ try {
30
+ return decryptJson(fs.readFileSync(sp, "utf8"));
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ export function hasLegacyMcpProfiles() {
37
+ if (!fs.existsSync(PROFILES_PATH()))
38
+ return false;
39
+ try {
40
+ const data = readProfilesFile();
41
+ return data.profiles.length > 0;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ //# sourceMappingURL=legacy-profile-reader.js.map
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Parse user-pasted email verification input (aligned with neozip-desktop magicLinkToken.ts).
3
+ */
4
+ const DIGIT_CODE_REGEX = /^\d{4,10}$/;
5
+ function safeDecodeURIComponent(s) {
6
+ try {
7
+ if (/%[0-9A-Fa-f]{2}/.test(s))
8
+ return decodeURIComponent(s);
9
+ }
10
+ catch {
11
+ /* keep */
12
+ }
13
+ return s;
14
+ }
15
+ function extractEmailCodeFromHttpUrl(s) {
16
+ try {
17
+ const u = new URL(s);
18
+ const email = u.searchParams.get("email");
19
+ const code = u.searchParams.get("code");
20
+ if (email || code) {
21
+ return {
22
+ email: email ? safeDecodeURIComponent(email).trim().toLowerCase() : undefined,
23
+ code: code ? safeDecodeURIComponent(code).replace(/\D/g, "") : undefined,
24
+ };
25
+ }
26
+ if (u.hash && u.hash.length > 2) {
27
+ const h = u.hash.startsWith("#") ? u.hash.slice(1) : u.hash;
28
+ const hp = new URLSearchParams(h);
29
+ const he = hp.get("email");
30
+ const hc = hp.get("code");
31
+ if (he || hc) {
32
+ return {
33
+ email: he ? safeDecodeURIComponent(he).trim().toLowerCase() : undefined,
34
+ code: hc ? safeDecodeURIComponent(hc).replace(/\D/g, "") : undefined,
35
+ };
36
+ }
37
+ }
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ return null;
43
+ }
44
+ function extractFromHttpUrl(s) {
45
+ try {
46
+ const u = new URL(s);
47
+ const fromQuery = u.searchParams.get("token") ??
48
+ u.searchParams.get("t") ??
49
+ u.searchParams.get("code") ??
50
+ u.searchParams.get("verifyToken") ??
51
+ u.searchParams.get("verification") ??
52
+ u.searchParams.get("key");
53
+ if (fromQuery)
54
+ return safeDecodeURIComponent(fromQuery);
55
+ const pathParts = u.pathname.split("/").filter(Boolean);
56
+ const lastSeg = pathParts[pathParts.length - 1];
57
+ if (lastSeg &&
58
+ lastSeg.split(".").length === 3 &&
59
+ lastSeg.split(".").every((x) => x.length > 0)) {
60
+ return lastSeg;
61
+ }
62
+ if (u.hash && u.hash.length > 2) {
63
+ const h = u.hash.startsWith("#") ? u.hash.slice(1) : u.hash;
64
+ const hp = new URLSearchParams(h);
65
+ const fromHash = hp.get("token") ?? hp.get("t") ?? hp.get("code") ?? hp.get("access_token");
66
+ if (fromHash)
67
+ return safeDecodeURIComponent(fromHash);
68
+ }
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ return null;
74
+ }
75
+ /** Extract opaque token for POST /auth/exchange-token. */
76
+ export function normalizeMagicLinkTokenInput(raw) {
77
+ let s = String(raw ?? "")
78
+ .trim()
79
+ .replace(/[\u00a0\u200b\uFEFF]/g, "")
80
+ .replace(/^["']|["']$/g, "");
81
+ if (!s)
82
+ return "";
83
+ if (/^https?:\/\//i.test(s)) {
84
+ s = s.replace(/[\n\r\t]+/g, "");
85
+ }
86
+ else {
87
+ s = s.replace(/\s/g, "");
88
+ }
89
+ if (/^https?:\/\//i.test(s)) {
90
+ const extracted = extractFromHttpUrl(s);
91
+ if (extracted)
92
+ return extracted;
93
+ }
94
+ const fromToken = s.match(/(?:^|[?&#])token=([^&\s#]+)/i);
95
+ if (fromToken?.[1]) {
96
+ return safeDecodeURIComponent(fromToken[1]);
97
+ }
98
+ const fromCode = s.match(/(?:^|[?&#])code=([^&\s#]+)/i);
99
+ if (fromCode?.[1] && !/^https?:\/\//i.test(s)) {
100
+ return safeDecodeURIComponent(fromCode[1]);
101
+ }
102
+ return safeDecodeURIComponent(s);
103
+ }
104
+ /** Extract { email, code } for POST /auth/verify-email-code. */
105
+ export function extractEmailCodePair(raw) {
106
+ let s = String(raw ?? "")
107
+ .trim()
108
+ .replace(/[\u00a0\u200b\uFEFF]/g, "")
109
+ .replace(/^["']|["']$/g, "");
110
+ if (!s)
111
+ return {};
112
+ const isUrl = /^https?:\/\//i.test(s);
113
+ if (isUrl) {
114
+ s = s.replace(/[\n\r\t]+/g, "");
115
+ const fromUrl = extractEmailCodeFromHttpUrl(s);
116
+ if (fromUrl)
117
+ return fromUrl;
118
+ return {};
119
+ }
120
+ const emailMatch = s.match(/(?:^|[?&#])email=([^&\s#]+)/i);
121
+ const codeMatch = s.match(/(?:^|[?&#])code=([^&\s#]+)/i);
122
+ if (emailMatch || codeMatch) {
123
+ return {
124
+ email: emailMatch
125
+ ? safeDecodeURIComponent(emailMatch[1]).trim().toLowerCase()
126
+ : undefined,
127
+ code: codeMatch
128
+ ? safeDecodeURIComponent(codeMatch[1]).replace(/\D/g, "")
129
+ : undefined,
130
+ };
131
+ }
132
+ const digitsOnly = s.replace(/[\s-]/g, "");
133
+ if (DIGIT_CODE_REGEX.test(digitsOnly)) {
134
+ return { code: digitsOnly };
135
+ }
136
+ return {};
137
+ }
138
+ //# sourceMappingURL=magic-link.js.map
@@ -0,0 +1,76 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { encryptSecrets } from "./crypto.js";
4
+ import { getLegacyActiveProfileId, hasLegacyMcpProfiles, listLegacyProfiles, readLegacySecrets, } from "./legacy-profile-reader.js";
5
+ import { createConnection, getActiveConnectionId, getConnectionDir, listConnectionIds, selectConnection, updateConnection, } from "./store.js";
6
+ export { hasLegacyMcpProfiles };
7
+ export function migrateFromMcpProfileStore() {
8
+ if (listConnectionIds().length > 0) {
9
+ return {
10
+ migrated: 0,
11
+ skipped: listLegacyProfiles().length,
12
+ connectionDir: getConnectionDir(),
13
+ activeConnectionId: getActiveConnectionId(),
14
+ };
15
+ }
16
+ const profiles = listLegacyProfiles();
17
+ if (profiles.length === 0) {
18
+ return {
19
+ migrated: 0,
20
+ skipped: 0,
21
+ connectionDir: getConnectionDir(),
22
+ activeConnectionId: null,
23
+ };
24
+ }
25
+ const activeLegacyId = getLegacyActiveProfileId();
26
+ let activeConnectionId = null;
27
+ let migrated = 0;
28
+ for (const profile of profiles) {
29
+ const secrets = readLegacySecrets(profile.id);
30
+ const conn = createConnection({
31
+ label: profile.label,
32
+ tokenServiceUrl: profile.tokenServiceUrl,
33
+ });
34
+ const legacyExtras = profile;
35
+ updateConnection(conn.id, {
36
+ email: profile.email,
37
+ emailVerified: profile.emailVerified,
38
+ emailVerifiedAt: legacyExtras.emailVerifiedAt ??
39
+ (profile.emailVerified ? profile.updatedAt : null),
40
+ evmAddress: profile.evmAddress,
41
+ walletId: profile.walletId,
42
+ linkId: profile.linkId,
43
+ identityKeyId: profile.identityKeyId,
44
+ x25519PublicKeySpkiB64: legacyExtras.x25519PublicKeySpkiB64 ?? null,
45
+ x25519Fingerprint: profile.x25519Fingerprint,
46
+ onboardingCompleteAt: profile.identityKeyId != null ? profile.updatedAt : null,
47
+ });
48
+ if (secrets) {
49
+ const sp = path.join(getConnectionDir(), "connections", conn.id, "secrets.enc");
50
+ fs.writeFileSync(sp, encryptSecrets({
51
+ accessToken: secrets.accessToken,
52
+ accessTokenObtainedAt: secrets.accessTokenObtainedAt,
53
+ accessTokenExpiresAt: null,
54
+ evmPrivateKeyHex: secrets.evmPrivateKey?.replace(/^0x/i, "") ?? null,
55
+ }), { mode: 0o600 });
56
+ }
57
+ if (profile.id === activeLegacyId) {
58
+ selectConnection(conn.id);
59
+ activeConnectionId = conn.id;
60
+ }
61
+ else if (!activeConnectionId) {
62
+ activeConnectionId = conn.id;
63
+ }
64
+ migrated++;
65
+ }
66
+ if (activeLegacyId && activeConnectionId) {
67
+ selectConnection(activeConnectionId);
68
+ }
69
+ return {
70
+ migrated,
71
+ skipped: 0,
72
+ connectionDir: getConnectionDir(),
73
+ activeConnectionId: getActiveConnectionId(),
74
+ };
75
+ }
76
+ //# sourceMappingURL=migrate.js.map