myceliumail 1.0.5 → 1.0.7

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 (59) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CODEX_SETUP.md +47 -0
  3. package/README.md +68 -2
  4. package/dist/bin/myceliumail.js +8 -0
  5. package/dist/bin/myceliumail.js.map +1 -1
  6. package/dist/commands/activate.d.ts +10 -0
  7. package/dist/commands/activate.d.ts.map +1 -0
  8. package/dist/commands/activate.js +77 -0
  9. package/dist/commands/activate.js.map +1 -0
  10. package/dist/commands/export.d.ts +6 -0
  11. package/dist/commands/export.d.ts.map +1 -0
  12. package/dist/commands/export.js +171 -0
  13. package/dist/commands/export.js.map +1 -0
  14. package/dist/commands/key-import.d.ts.map +1 -1
  15. package/dist/commands/key-import.js +5 -0
  16. package/dist/commands/key-import.js.map +1 -1
  17. package/dist/commands/send.d.ts +1 -0
  18. package/dist/commands/send.d.ts.map +1 -1
  19. package/dist/commands/send.js +30 -6
  20. package/dist/commands/send.js.map +1 -1
  21. package/dist/commands/status.d.ts +10 -0
  22. package/dist/commands/status.d.ts.map +1 -0
  23. package/dist/commands/status.js +93 -0
  24. package/dist/commands/status.js.map +1 -0
  25. package/dist/commands/watch.d.ts +4 -0
  26. package/dist/commands/watch.d.ts.map +1 -1
  27. package/dist/commands/watch.js +69 -0
  28. package/dist/commands/watch.js.map +1 -1
  29. package/dist/lib/config.js +1 -1
  30. package/dist/lib/config.js.map +1 -1
  31. package/dist/lib/crypto.d.ts.map +1 -1
  32. package/dist/lib/crypto.js +5 -4
  33. package/dist/lib/crypto.js.map +1 -1
  34. package/dist/lib/license.d.ts +61 -0
  35. package/dist/lib/license.d.ts.map +1 -0
  36. package/dist/lib/license.js +173 -0
  37. package/dist/lib/license.js.map +1 -0
  38. package/dist/storage/local.d.ts.map +1 -1
  39. package/dist/storage/local.js +5 -2
  40. package/dist/storage/local.js.map +1 -1
  41. package/mcp-server/CHANGELOG.md +68 -0
  42. package/mcp-server/README.md +11 -0
  43. package/mcp-server/package-lock.json +2 -2
  44. package/mcp-server/package.json +5 -4
  45. package/mcp-server/src/lib/license.ts +147 -0
  46. package/mcp-server/src/lib/storage.ts +74 -27
  47. package/mcp-server/src/server.ts +4 -0
  48. package/package.json +1 -1
  49. package/src/bin/myceliumail.ts +10 -0
  50. package/src/commands/activate.ts +85 -0
  51. package/src/commands/export.ts +212 -0
  52. package/src/commands/key-import.ts +7 -0
  53. package/src/commands/send.ts +34 -6
  54. package/src/commands/status.ts +114 -0
  55. package/src/commands/watch.ts +86 -0
  56. package/src/lib/config.ts +1 -1
  57. package/src/lib/crypto.ts +5 -4
  58. package/src/lib/license.ts +215 -0
  59. package/src/storage/local.ts +5 -2
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Myceliumail License Verification
3
+ *
4
+ * Ed25519-based license verification for Pro features.
5
+ * Public key is embedded; private key is kept by treebird for signing.
6
+ */
7
+ import nacl from 'tweetnacl';
8
+ import util from 'tweetnacl-util';
9
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
10
+ import { join } from 'path';
11
+ import { homedir } from 'os';
12
+ import { loadKnownKeys } from './crypto.js';
13
+ // License storage location
14
+ const LICENSE_DIR = join(homedir(), '.myceliumail');
15
+ const LICENSE_FILE = join(LICENSE_DIR, 'license.key');
16
+ // Treebird's public key for license verification (Ed25519)
17
+ // Use the same key as Spidersan for unified licensing
18
+ const TREEBIRD_PUBLIC_KEY = 'XqIqSlybZGKkKemgLKKl8P9MepnObhcJcxxZHtgG8/o=';
19
+ // Free tier limits
20
+ export const FREE_TIER_LIMITS = {
21
+ maxImportedKeys: 5,
22
+ };
23
+ /**
24
+ * Ensure license directory exists
25
+ */
26
+ function ensureLicenseDir() {
27
+ if (!existsSync(LICENSE_DIR)) {
28
+ mkdirSync(LICENSE_DIR, { recursive: true });
29
+ }
30
+ }
31
+ /**
32
+ * Parse a license string into components
33
+ * Format: LICENSE_V1.BASE64_DATA.BASE64_SIGNATURE
34
+ */
35
+ function parseLicenseString(licenseString) {
36
+ const parts = licenseString.trim().split('.');
37
+ if (parts.length !== 3)
38
+ return null;
39
+ const [version, data, signature] = parts;
40
+ if (version !== 'LICENSE_V1')
41
+ return null;
42
+ return { version, data, signature };
43
+ }
44
+ /**
45
+ * Verify a license string using Ed25519 detached signature
46
+ */
47
+ export function verifyLicense(licenseString) {
48
+ try {
49
+ const parsed = parseLicenseString(licenseString);
50
+ if (!parsed)
51
+ return null;
52
+ const dataBytes = util.decodeBase64(parsed.data);
53
+ // Verify detached Ed25519 signature
54
+ const publicKey = util.decodeBase64(TREEBIRD_PUBLIC_KEY);
55
+ const signatureBytes = util.decodeBase64(parsed.signature);
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ const isValid = nacl.sign.detached.verify(dataBytes, signatureBytes, publicKey);
58
+ if (!isValid)
59
+ return null;
60
+ const dataString = util.encodeUTF8(dataBytes);
61
+ const data = JSON.parse(dataString);
62
+ const expiresAt = new Date(data.expiresAt);
63
+ const isExpired = expiresAt < new Date();
64
+ return {
65
+ data,
66
+ isValid: true,
67
+ isExpired,
68
+ };
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Save a license key to disk
76
+ */
77
+ export function saveLicense(licenseString) {
78
+ try {
79
+ ensureLicenseDir();
80
+ writeFileSync(LICENSE_FILE, licenseString.trim(), { mode: 0o600 });
81
+ return true;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ /**
88
+ * Load the saved license from disk
89
+ */
90
+ export function loadLicense() {
91
+ if (!existsSync(LICENSE_FILE))
92
+ return null;
93
+ try {
94
+ const licenseString = readFileSync(LICENSE_FILE, 'utf-8');
95
+ return verifyLicense(licenseString);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Check if user has a valid Pro license
103
+ */
104
+ export function isPro() {
105
+ const license = loadLicense();
106
+ if (!license)
107
+ return false;
108
+ if (!license.isValid)
109
+ return false;
110
+ if (license.isExpired)
111
+ return false;
112
+ return license.data.plan === 'pro';
113
+ }
114
+ /**
115
+ * Check if a specific Pro feature is enabled
116
+ */
117
+ export function hasFeature(feature) {
118
+ const license = loadLicense();
119
+ if (!license || !license.isValid || license.isExpired)
120
+ return false;
121
+ return license.data.features.includes(feature);
122
+ }
123
+ /**
124
+ * Get license status summary
125
+ */
126
+ export function getLicenseStatus() {
127
+ const license = loadLicense();
128
+ if (!license || !license.isValid || license.isExpired) {
129
+ return {
130
+ plan: 'free',
131
+ features: [],
132
+ };
133
+ }
134
+ const expiresAt = new Date(license.data.expiresAt);
135
+ const now = new Date();
136
+ const daysRemaining = Math.ceil((expiresAt.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
137
+ return {
138
+ plan: license.data.plan,
139
+ email: license.data.email,
140
+ expiresAt: license.data.expiresAt,
141
+ features: license.data.features,
142
+ daysRemaining,
143
+ };
144
+ }
145
+ /**
146
+ * Check imported key limit and throw if exceeded (for free tier)
147
+ */
148
+ export function checkKeyLimit() {
149
+ if (isPro())
150
+ return; // Pro has unlimited
151
+ const knownKeys = loadKnownKeys();
152
+ const keyCount = Object.keys(knownKeys).length;
153
+ if (keyCount >= FREE_TIER_LIMITS.maxImportedKeys) {
154
+ console.error(`\n🍄 Free tier limit reached: ${keyCount}/${FREE_TIER_LIMITS.maxImportedKeys} imported keys`);
155
+ console.error('');
156
+ console.error(' Options:');
157
+ console.error(' • Remove unused keys from ~/.myceliumail/keys/known_keys.json');
158
+ console.error(' • Upgrade: myceliumail.dev/pro for unlimited keys');
159
+ console.error('');
160
+ process.exit(1);
161
+ }
162
+ }
163
+ /**
164
+ * Print Pro upsell message (soft sell)
165
+ */
166
+ export function printProUpsell(feature) {
167
+ if (isPro())
168
+ return;
169
+ console.log('');
170
+ console.log(`💎 Pro tip: Upgrade for ${feature}`);
171
+ console.log(' myceliumail.dev/pro');
172
+ }
173
+ //# sourceMappingURL=license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/lib/license.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgD/D;;GAEG;AACH,wBAAsB,WAAW,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9E,GACF,OAAO,CAAC,OAAO,CAAC,CA4BlB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAuB1F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAIpE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB/E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQjE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAcjF"}
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgD/D;;GAEG;AACH,wBAAsB,WAAW,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9E,GACF,OAAO,CAAC,OAAO,CAAC,CA4BlB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAyB1F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAIpE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB/E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQjE;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAejF"}
@@ -79,9 +79,11 @@ export async function sendMessage(sender, recipient, subject, body, options) {
79
79
  */
80
80
  export async function getInbox(agentId, options) {
81
81
  const messages = loadMessages();
82
+ const normalizedAgentId = agentId.toLowerCase();
82
83
  let filtered = agentId === 'all'
83
84
  ? messages.filter(m => !m.archived)
84
- : messages.filter(m => (m.recipient === agentId || m.recipients?.includes(agentId)) && !m.archived);
85
+ : messages.filter(m => (m.recipient.toLowerCase() === normalizedAgentId ||
86
+ m.recipients?.some(r => r.toLowerCase() === normalizedAgentId)) && !m.archived);
85
87
  if (options?.unreadOnly) {
86
88
  filtered = filtered.filter(m => !m.read);
87
89
  }
@@ -150,7 +152,8 @@ export async function archiveMessage(id) {
150
152
  */
151
153
  export async function getSent(agentId, limit) {
152
154
  const messages = loadMessages();
153
- let filtered = messages.filter(m => m.sender === agentId);
155
+ const normalizedAgentId = agentId.toLowerCase();
156
+ let filtered = messages.filter(m => m.sender.toLowerCase() === normalizedAgentId);
154
157
  filtered.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
155
158
  if (limit) {
156
159
  filtered = filtered.slice(0, limit);
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AAMtD;;GAEG;AACH,SAAS,aAAa;IAClB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,YAAY;IACjB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1C,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,QAAyB;IAC3C,aAAa,EAAE,CAAC;IAChB,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,MAAqB;IACpC,OAAO;QACH,GAAG,MAAM;QACT,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;KACxC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,MAAc,EACd,SAA4B,EAC5B,OAAe,EACf,IAAY,EACZ,OAMC;IAED,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAEhC,yBAAyB;IACzB,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzE,MAAM,gBAAgB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAkB;QAC9B,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM;QACN,SAAS,EAAE,gBAAgB;QAC3B,UAAU,EAAE,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAChE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;QAC1C,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;QACpC,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK;QACtC,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC;IAEF,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEvB,OAAO,SAAS,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,OAAsB;IAClE,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAEhC,IAAI,QAAQ,GAAG,OAAO,KAAK,KAAK;QAC5B,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACnC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAClB,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAC9E,CAAC;IAEN,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,yCAAyC;IACzC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnB,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;IAEF,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;QACjB,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAAU;IACvC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAAU,EAAE,OAAgB;IACzD,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/B,mCAAmC;IACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,gBAAgB;IAChB,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;IAE5B,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAU;IAC1C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/B,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1B,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAU;IAC3C,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,KAAK,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/B,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,KAAc;IACzD,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAEhC,IAAI,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IAE1D,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACnB,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CACpE,CAAC;IAEF,IAAI,KAAK,EAAE,CAAC;QACR,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ # Changelog - Myceliumail MCP Server
2
+
3
+ All notable changes to the MCP server will be documented in this file.
4
+
5
+ ## [1.0.11] - 2025-12-21
6
+
7
+ ### Fixed
8
+ - DMG installer and desktop app fixes
9
+ - Improved error handling in MCP tools
10
+
11
+ ## [1.0.9] - 2025-12-20
12
+
13
+ ### Fixed
14
+ - Partial ID lookup for message reading (matches main CLI fix)
15
+
16
+ ## [1.0.8] - 2025-12-20
17
+
18
+ ### Added
19
+ - Sync with main myceliumail package updates
20
+
21
+ ## [1.0.7] - 2025-12-18
22
+
23
+ ### Fixed
24
+ - Supabase column names to match actual schema (`to_agent` vs `recipient`)
25
+ - Added error logging (removed silent catch blocks)
26
+ - Config file support (`~/.myceliumail/config.json`)
27
+
28
+ ## [1.0.6] - 2025-12-18
29
+
30
+ ### Fixed
31
+ - Agent ID case normalization (all lowercase)
32
+
33
+ ## [1.0.5] - 2025-12-18
34
+
35
+ ### Fixed
36
+ - Key import handling improvements
37
+
38
+ ## [1.0.4] - 2025-12-18
39
+
40
+ ### Fixed
41
+ - Encryption/decryption edge cases
42
+
43
+ ## [1.0.3] - 2025-12-17
44
+
45
+ ### Fixed
46
+ - Message sending reliability improvements
47
+
48
+ ## [1.0.2] - 2025-12-16
49
+
50
+ ### Fixed
51
+ - Initial bug fixes after launch
52
+
53
+ ## [1.0.0] - 2025-12-16
54
+
55
+ ### Added
56
+ - Initial MCP server release
57
+ - 8 messaging tools for Claude Desktop:
58
+ - `check_inbox` - List received messages
59
+ - `read_message` - Read and decrypt messages
60
+ - `send_message` - Send messages to other agents
61
+ - `reply_message` - Reply to messages
62
+ - `generate_keys` - Create encryption keypair
63
+ - `list_keys` - Show available keys
64
+ - `import_key` - Import peer public keys
65
+ - `archive_message` - Archive messages
66
+ - End-to-end encryption support (NaCl/TweetNaCl.js)
67
+ - Local and Supabase storage backends
68
+ - Automatic fallback from cloud to local storage
@@ -141,3 +141,14 @@ Remove the `myceliumail` entry from your Claude Desktop config:
141
141
 
142
142
  Then restart Claude Desktop.
143
143
 
144
+ ---
145
+
146
+ ## Support
147
+
148
+ If you find Myceliumail useful, consider supporting development:
149
+
150
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat&logo=buy-me-a-coffee)](https://buymeacoffee.com/tree.bird)
151
+
152
+ ---
153
+
154
+ **Part of the [Myceliumail](https://github.com/treebird7/myceliumail) ecosystem** 🍄
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "myceliumail-mcp",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "myceliumail-mcp",
9
- "version": "1.0.8",
9
+ "version": "1.0.11",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/sdk": "^1.0.0",
@@ -1,12 +1,9 @@
1
1
  {
2
2
  "name": "myceliumail-mcp",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "description": "MCP server for Myceliumail - End-to-End Encrypted Messaging for AI Agents",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
7
- "bin": {
8
- "myceliumail-mcp": "./dist/server.js"
9
- },
10
7
  "scripts": {
11
8
  "build": "tsc",
12
9
  "dev": "tsc --watch",
@@ -33,6 +30,10 @@
33
30
  "bugs": {
34
31
  "url": "https://github.com/treebird7/myceliumail/issues"
35
32
  },
33
+ "funding": {
34
+ "type": "buymeacoffee",
35
+ "url": "https://buymeacoffee.com/tree.bird"
36
+ },
36
37
  "readme": "README.md",
37
38
  "dependencies": {
38
39
  "@modelcontextprotocol/sdk": "^1.0.0",
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Myceliumail MCP License Verification
3
+ *
4
+ * Ed25519-based license verification for MCP Pro features.
5
+ * MCP server is a Pro feature - requires valid license to start.
6
+ */
7
+
8
+ import nacl from 'tweetnacl';
9
+ import util from 'tweetnacl-util';
10
+ import { existsSync, readFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { homedir } from 'os';
13
+
14
+ // License storage location (shared with CLI)
15
+ const LICENSE_FILE = join(homedir(), '.myceliumail', 'license.key');
16
+
17
+ // Treebird's public key for license verification (Ed25519)
18
+ const TREEBIRD_PUBLIC_KEY = 'XqIqSlybZGKkKemgLKKl8P9MepnObhcJcxxZHtgG8/o=';
19
+
20
+ export interface LicenseData {
21
+ email: string;
22
+ plan: 'free' | 'pro';
23
+ expiresAt: string;
24
+ issuedAt: string;
25
+ features: string[];
26
+ }
27
+
28
+ export interface License {
29
+ data: LicenseData;
30
+ isValid: boolean;
31
+ isExpired: boolean;
32
+ }
33
+
34
+ /**
35
+ * Parse a license string into components
36
+ */
37
+ function parseLicenseString(licenseString: string): { version: string; data: string; signature: string } | null {
38
+ const parts = licenseString.trim().split('.');
39
+ if (parts.length !== 3) return null;
40
+
41
+ const [version, data, signature] = parts;
42
+ if (version !== 'LICENSE_V1') return null;
43
+
44
+ return { version, data, signature };
45
+ }
46
+
47
+ /**
48
+ * Verify a license string using Ed25519 detached signature
49
+ */
50
+ export function verifyLicense(licenseString: string): License | null {
51
+ try {
52
+ const parsed = parseLicenseString(licenseString);
53
+ if (!parsed) return null;
54
+
55
+ const dataBytes = util.decodeBase64(parsed.data);
56
+ const publicKey = util.decodeBase64(TREEBIRD_PUBLIC_KEY);
57
+ const signatureBytes = util.decodeBase64(parsed.signature);
58
+
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ const isValid = (nacl as any).sign.detached.verify(dataBytes, signatureBytes, publicKey);
61
+ if (!isValid) return null;
62
+
63
+ const dataString = util.encodeUTF8(dataBytes);
64
+ const data = JSON.parse(dataString) as LicenseData;
65
+
66
+ const expiresAt = new Date(data.expiresAt);
67
+ const isExpired = expiresAt < new Date();
68
+
69
+ return {
70
+ data,
71
+ isValid: true,
72
+ isExpired,
73
+ };
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Load and verify license from disk
81
+ */
82
+ export function loadLicense(): License | null {
83
+ if (!existsSync(LICENSE_FILE)) return null;
84
+
85
+ try {
86
+ const licenseString = readFileSync(LICENSE_FILE, 'utf-8');
87
+ return verifyLicense(licenseString);
88
+ } catch {
89
+ return null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Check if user has a valid Pro license
95
+ */
96
+ export function isPro(): boolean {
97
+ const license = loadLicense();
98
+ if (!license) return false;
99
+ if (!license.isValid) return false;
100
+ if (license.isExpired) return false;
101
+ return license.data.plan === 'pro';
102
+ }
103
+
104
+ /**
105
+ * Check if MCP feature is enabled
106
+ */
107
+ export function hasMcpAccess(): boolean {
108
+ const license = loadLicense();
109
+ if (!license || !license.isValid || license.isExpired) return false;
110
+ return license.data.features.includes('mcp_server');
111
+ }
112
+
113
+ /**
114
+ * Verify Pro license or exit with upgrade message
115
+ */
116
+ export function requireProLicense(): void {
117
+ const license = loadLicense();
118
+
119
+ if (!license) {
120
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
121
+ console.error('🍄 Myceliumail MCP Server - Pro Feature');
122
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
123
+ console.error('');
124
+ console.error('This feature requires a Pro license.');
125
+ console.error('');
126
+ console.error('Activate with: mycmail activate <license-key>');
127
+ console.error('Get a license: myceliumail.dev/pro');
128
+ console.error('');
129
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
130
+ process.exit(1);
131
+ }
132
+
133
+ if (!license.isValid) {
134
+ console.error('❌ Invalid license. Please re-activate.');
135
+ console.error(' mycmail activate <license-key>');
136
+ process.exit(1);
137
+ }
138
+
139
+ if (license.isExpired) {
140
+ console.error('❌ License expired on', new Date(license.data.expiresAt).toLocaleDateString());
141
+ console.error(' Renew at: myceliumail.dev/pro');
142
+ process.exit(1);
143
+ }
144
+
145
+ // Valid Pro license - show confirmation
146
+ console.error(`🍄 Myceliumail MCP (Pro) - ${license.data.email}`);
147
+ }
@@ -189,29 +189,59 @@ export async function getInbox(
189
189
  export async function getMessage(id: string): Promise<Message | null> {
190
190
  if (hasSupabase()) {
191
191
  try {
192
- const results = await supabaseRequest<Array<{
193
- id: string; from_agent: string; to_agent: string;
194
- subject: string; message: string; encrypted: boolean;
195
- ciphertext: string; nonce: string; sender_public_key: string;
196
- read: boolean; created_at: string;
197
- }>>(`/agent_messages?id=eq.${id}`);
192
+ // For partial IDs, fetch recent and filter client-side
193
+ // (PostgreSQL UUID doesn't support LIKE operator)
194
+ if (id.length < 36) {
195
+ const results = await supabaseRequest<Array<{
196
+ id: string; from_agent: string; to_agent: string;
197
+ subject: string; message: string; encrypted: boolean;
198
+ ciphertext: string; nonce: string; sender_public_key: string;
199
+ read: boolean; created_at: string;
200
+ }>>(`/agent_messages?order=created_at.desc&limit=100`);
198
201
 
199
- if (results.length > 0) {
200
- const r = results[0];
201
- return {
202
- id: r.id,
203
- sender: r.from_agent,
204
- recipient: r.to_agent,
205
- subject: r.subject || '',
206
- body: r.message || '',
207
- encrypted: r.encrypted,
208
- ciphertext: r.ciphertext,
209
- nonce: r.nonce,
210
- senderPublicKey: r.sender_public_key,
211
- read: r.read,
212
- archived: false,
213
- createdAt: new Date(r.created_at),
214
- };
202
+ const r = results.find(row => row.id.startsWith(id));
203
+ if (r) {
204
+ return {
205
+ id: r.id,
206
+ sender: r.from_agent,
207
+ recipient: r.to_agent,
208
+ subject: r.subject || '',
209
+ body: r.message || '',
210
+ encrypted: r.encrypted,
211
+ ciphertext: r.ciphertext,
212
+ nonce: r.nonce,
213
+ senderPublicKey: r.sender_public_key,
214
+ read: r.read,
215
+ archived: false,
216
+ createdAt: new Date(r.created_at),
217
+ };
218
+ }
219
+ } else {
220
+ // Full UUID - exact match
221
+ const results = await supabaseRequest<Array<{
222
+ id: string; from_agent: string; to_agent: string;
223
+ subject: string; message: string; encrypted: boolean;
224
+ ciphertext: string; nonce: string; sender_public_key: string;
225
+ read: boolean; created_at: string;
226
+ }>>(`/agent_messages?id=eq.${id}`);
227
+
228
+ if (results.length > 0) {
229
+ const r = results[0];
230
+ return {
231
+ id: r.id,
232
+ sender: r.from_agent,
233
+ recipient: r.to_agent,
234
+ subject: r.subject || '',
235
+ body: r.message || '',
236
+ encrypted: r.encrypted,
237
+ ciphertext: r.ciphertext,
238
+ nonce: r.nonce,
239
+ senderPublicKey: r.sender_public_key,
240
+ read: r.read,
241
+ archived: false,
242
+ createdAt: new Date(r.created_at),
243
+ };
244
+ }
215
245
  }
216
246
  } catch (err) {
217
247
  console.error('getMessage failed, falling back to local:', err);
@@ -219,15 +249,24 @@ export async function getMessage(id: string): Promise<Message | null> {
219
249
  }
220
250
  }
221
251
 
252
+ // Local storage - also supports partial ID
222
253
  const messages = loadLocalMessages();
223
- const found = messages.find(m => m.id === id);
254
+ const found = messages.find(m => m.id === id || m.id.startsWith(id));
224
255
  return found ? toMessage(found) : null;
225
256
  }
226
257
 
227
258
  export async function markAsRead(id: string): Promise<boolean> {
259
+ // For partial IDs, resolve full UUID first
260
+ let fullId = id;
261
+ if (id.length < 36) {
262
+ const msg = await getMessage(id);
263
+ if (!msg) return false;
264
+ fullId = msg.id;
265
+ }
266
+
228
267
  if (hasSupabase()) {
229
268
  try {
230
- await supabaseRequest(`/agent_messages?id=eq.${id}`, {
269
+ await supabaseRequest(`/agent_messages?id=eq.${fullId}`, {
231
270
  method: 'PATCH',
232
271
  body: JSON.stringify({ read: true }),
233
272
  });
@@ -238,7 +277,7 @@ export async function markAsRead(id: string): Promise<boolean> {
238
277
  }
239
278
 
240
279
  const messages = loadLocalMessages();
241
- const idx = messages.findIndex(m => m.id === id);
280
+ const idx = messages.findIndex(m => m.id === fullId);
242
281
  if (idx === -1) return false;
243
282
  messages[idx].read = true;
244
283
  saveLocalMessages(messages);
@@ -246,9 +285,17 @@ export async function markAsRead(id: string): Promise<boolean> {
246
285
  }
247
286
 
248
287
  export async function archiveMessage(id: string): Promise<boolean> {
288
+ // For partial IDs, resolve full UUID first
289
+ let fullId = id;
290
+ if (id.length < 36) {
291
+ const msg = await getMessage(id);
292
+ if (!msg) return false;
293
+ fullId = msg.id;
294
+ }
295
+
249
296
  if (hasSupabase()) {
250
297
  try {
251
- await supabaseRequest(`/agent_messages?id=eq.${id}`, {
298
+ await supabaseRequest(`/agent_messages?id=eq.${fullId}`, {
252
299
  method: 'PATCH',
253
300
  body: JSON.stringify({ archived: true }),
254
301
  });
@@ -259,7 +306,7 @@ export async function archiveMessage(id: string): Promise<boolean> {
259
306
  }
260
307
 
261
308
  const messages = loadLocalMessages();
262
- const idx = messages.findIndex(m => m.id === id);
309
+ const idx = messages.findIndex(m => m.id === fullId);
263
310
  if (idx === -1) return false;
264
311
  messages[idx].archived = true;
265
312
  saveLocalMessages(messages);