myceliumail 1.0.2 → 1.0.3

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 (79) hide show
  1. package/.context7 +87 -0
  2. package/.eslintrc.json +29 -0
  3. package/COMPLETE.md +51 -0
  4. package/MYCELIUMAIL_STARTER_KIT.md +603 -0
  5. package/NEXT_STEPS.md +96 -0
  6. package/desktop/README.md +102 -0
  7. package/desktop/assets/icon.icns +0 -0
  8. package/desktop/assets/icon.iconset/icon_128x128.png +0 -0
  9. package/desktop/assets/icon.iconset/icon_128x128@2x.png +0 -0
  10. package/desktop/assets/icon.iconset/icon_16x16.png +0 -0
  11. package/desktop/assets/icon.iconset/icon_16x16@2x.png +0 -0
  12. package/desktop/assets/icon.iconset/icon_256x256.png +0 -0
  13. package/desktop/assets/icon.iconset/icon_256x256@2x.png +0 -0
  14. package/desktop/assets/icon.iconset/icon_32x32.png +0 -0
  15. package/desktop/assets/icon.iconset/icon_32x32@2x.png +0 -0
  16. package/desktop/assets/icon.iconset/icon_512x512.png +0 -0
  17. package/desktop/assets/icon.iconset/icon_512x512@2x.png +0 -0
  18. package/desktop/assets/icon.png +0 -0
  19. package/desktop/assets/tray-icon.png +0 -0
  20. package/desktop/main.js +257 -0
  21. package/desktop/package-lock.json +4198 -0
  22. package/desktop/package.json +48 -0
  23. package/desktop/preload.js +11 -0
  24. package/dist/bin/myceliumail.js +2 -0
  25. package/dist/bin/myceliumail.js.map +1 -1
  26. package/dist/commands/key-announce.d.ts +6 -0
  27. package/dist/commands/key-announce.d.ts.map +1 -0
  28. package/dist/commands/key-announce.js +63 -0
  29. package/dist/commands/key-announce.js.map +1 -0
  30. package/docs/20251215_Treebird-Ecosystem_Knowledge-Base_v2.md +292 -0
  31. package/docs/20251215_Treebird-Ecosystem_Project-Instructions_v2.md +176 -0
  32. package/docs/AGENT_DELEGATION_WORKFLOW.md +453 -0
  33. package/docs/AGENT_STARTER_KIT.md +145 -0
  34. package/docs/ANNOUNCEMENT_DRAFTS.md +55 -0
  35. package/docs/DASHBOARD_AGENT_HANDOFF.md +429 -0
  36. package/docs/DASHBOARD_AGENT_PROMPT.md +32 -0
  37. package/docs/DASHBOARD_BUILD_ROADMAP.md +61 -0
  38. package/docs/DEPLOYMENT.md +59 -0
  39. package/docs/LESSONS_LEARNED.md +127 -0
  40. package/docs/MCP_PUBLISHING_ROADMAP.md +113 -0
  41. package/docs/MCP_STARTER_KIT.md +117 -0
  42. package/docs/SSAN_MESSAGES_SUMMARY.md +92 -0
  43. package/docs/STORAGE_ARCHITECTURE.md +114 -0
  44. package/mcp-server/README.md +143 -0
  45. package/mcp-server/assets/icon.png +0 -0
  46. package/mcp-server/myceliumail-mcp-1.0.0.tgz +0 -0
  47. package/mcp-server/package-lock.json +1142 -0
  48. package/mcp-server/package.json +49 -0
  49. package/mcp-server/src/lib/config.ts +55 -0
  50. package/mcp-server/src/lib/crypto.ts +150 -0
  51. package/mcp-server/src/lib/storage.ts +267 -0
  52. package/mcp-server/src/server.ts +387 -0
  53. package/mcp-server/tsconfig.json +26 -0
  54. package/package.json +3 -3
  55. package/src/bin/myceliumail.ts +54 -0
  56. package/src/commands/broadcast.ts +70 -0
  57. package/src/commands/dashboard.ts +19 -0
  58. package/src/commands/inbox.ts +75 -0
  59. package/src/commands/key-announce.ts +70 -0
  60. package/src/commands/key-import.ts +35 -0
  61. package/src/commands/keygen.ts +44 -0
  62. package/src/commands/keys.ts +55 -0
  63. package/src/commands/read.ts +97 -0
  64. package/src/commands/send.ts +89 -0
  65. package/src/commands/watch.ts +101 -0
  66. package/src/dashboard/public/app.js +523 -0
  67. package/src/dashboard/public/index.html +75 -0
  68. package/src/dashboard/public/styles.css +68 -0
  69. package/src/dashboard/routes.ts +128 -0
  70. package/src/dashboard/server.ts +33 -0
  71. package/src/lib/config.ts +104 -0
  72. package/src/lib/crypto.ts +210 -0
  73. package/src/lib/realtime.ts +109 -0
  74. package/src/storage/local.ts +209 -0
  75. package/src/storage/supabase.ts +336 -0
  76. package/src/types/index.ts +53 -0
  77. package/supabase/migrations/000_myceliumail_setup.sql +93 -0
  78. package/supabase/migrations/001_enable_realtime.sql +10 -0
  79. package/tsconfig.json +28 -0
@@ -0,0 +1,429 @@
1
+ # 🍄 Myceliumail Web Dashboard - Agent Handoff Brief
2
+
3
+ > **For a fresh Gemini agent to build the web dashboard**
4
+
5
+ ---
6
+
7
+ ## Your Mission
8
+
9
+ Build a **local web dashboard** (http://localhost:3737) to view Myceliumail messages with:
10
+ - Unified inbox (local JSON + Supabase)
11
+ - Auto-decrypt encrypted messages
12
+ - Mark as read/archive
13
+ - Beautiful, clean UI
14
+
15
+ **Estimated time:** 4-6 hours
16
+ **Complexity:** Medium-Low
17
+
18
+ ---
19
+
20
+ ## What's Already Built (You Can Use)
21
+
22
+ ### Existing Modules in `src/`
23
+
24
+ | Module | Path | What It Does |
25
+ |--------|------|--------------|
26
+ | **Storage** | `storage/local.ts` | Read/write local JSON messages |
27
+ | **Storage** | `storage/supabase.ts` | Read/write Supabase messages |
28
+ | **Crypto** | `lib/crypto.ts` | Encrypt/decrypt with NaCl |
29
+ | **Config** | `lib/config.ts` | Load agent ID, credentials |
30
+ | **Types** | `types/index.ts` | TypeScript interfaces |
31
+
32
+ **Key functions you'll use:**
33
+ ```typescript
34
+ // From storage/local.ts or storage/supabase.ts
35
+ import { getInbox, getMessage, markAsRead, archiveMessage } from '../storage/supabase.js';
36
+
37
+ // From crypto.ts
38
+ import { loadKeyPair, decryptMessage } from '../lib/crypto.js';
39
+
40
+ // From config.ts
41
+ import { loadConfig } from '../lib/config.js';
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Project Structure (Create These)
47
+
48
+ ```
49
+ src/dashboard/
50
+ ├── server.ts # Fastify HTTP server
51
+ ├── routes.ts # API endpoints
52
+ └── public/
53
+ ├── index.html # Dashboard UI
54
+ ├── app.js # Frontend logic
55
+ └── styles.css # Styling
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Roadmap: Step-by-Step
61
+
62
+ ### Step 1: Install Dependencies (15 min)
63
+
64
+ ```bash
65
+ cd myceliumail # or your project directory
66
+ npm install fastify @fastify/static @fastify/cors
67
+ ```
68
+
69
+ ### Step 2: Create Basic Server (30 min)
70
+
71
+ **File:** `src/dashboard/server.ts`
72
+
73
+ ```typescript
74
+ import Fastify from 'fastify';
75
+ import fastifyStatic from '@fastify/static';
76
+ import { join, dirname } from 'path';
77
+ import { fileURLToPath } from 'url';
78
+
79
+ const __dirname = dirname(fileURLToPath(import.meta.url));
80
+
81
+ export async function startDashboard(port = 3737) {
82
+ const fastify = Fastify({ logger: true });
83
+
84
+ // Serve static files
85
+ await fastify.register(fastifyStatic, {
86
+ root: join(__dirname, 'public'),
87
+ prefix: '/'
88
+ });
89
+
90
+ // Start server
91
+ await fastify.listen({ port, host: '127.0.0.1' });
92
+ console.log(`🍄 Dashboard running on http://localhost:${port}`);
93
+
94
+ return fastify;
95
+ }
96
+ ```
97
+
98
+ **Test:** Run `node -r esbuild-register src/dashboard/server.ts` → should start server
99
+
100
+ ### Step 3: Create API Routes (1-2 hours)
101
+
102
+ **File:** `src/dashboard/routes.ts`
103
+
104
+ ```typescript
105
+ import type { FastifyInstance } from 'fastify';
106
+ import { loadConfig } from '../lib/config.js';
107
+ import * as storage from '../storage/supabase.js';
108
+ import { loadKeyPair, decryptMessage } from '../lib/crypto.js';
109
+
110
+ export async function registerRoutes(fastify: FastifyInstance) {
111
+ const config = loadConfig();
112
+ const agentId = config.agentId;
113
+
114
+ // GET /api/inbox
115
+ fastify.get('/api/inbox', async (request, reply) => {
116
+ const messages = await storage.getInbox(agentId, { limit: 100 });
117
+
118
+ // Decrypt encrypted messages
119
+ const keyPair = loadKeyPair(agentId);
120
+ const decrypted = messages.map(msg => {
121
+ if (msg.encrypted && keyPair && msg.ciphertext) {
122
+ try {
123
+ const decryptedText = decryptMessage({
124
+ ciphertext: msg.ciphertext,
125
+ nonce: msg.nonce!,
126
+ senderPublicKey: msg.senderPublicKey!
127
+ }, keyPair);
128
+
129
+ if (decryptedText) {
130
+ const parsed = JSON.parse(decryptedText);
131
+ return { ...msg, subject: parsed.subject, body: parsed.body, decrypted: true };
132
+ }
133
+ } catch {}
134
+ }
135
+ return msg;
136
+ });
137
+
138
+ return { messages: decrypted, total: decrypted.length };
139
+ });
140
+
141
+ // GET /api/message/:id
142
+ fastify.get('/api/message/:id', async (request, reply) => {
143
+ const { id } = request.params as { id: string };
144
+ const message = await storage.getMessage(id);
145
+
146
+ if (!message) {
147
+ return reply.code(404).send({ error: 'Message not found' });
148
+ }
149
+
150
+ // Decrypt if needed
151
+ const keyPair = loadKeyPair(agentId);
152
+ if (message.encrypted && keyPair && message.ciphertext) {
153
+ try {
154
+ const decryptedText = decryptMessage({
155
+ ciphertext: message.ciphertext,
156
+ nonce: message.nonce!,
157
+ senderPublicKey: message.senderPublicKey!
158
+ }, keyPair);
159
+
160
+ if (decryptedText) {
161
+ const parsed = JSON.parse(decryptedText);
162
+ return { ...message, subject: parsed.subject, body: parsed.body, decrypted: true };
163
+ }
164
+ } catch {}
165
+ }
166
+
167
+ return message;
168
+ });
169
+
170
+ // POST /api/message/:id/read
171
+ fastify.post('/api/message/:id/read', async (request, reply) => {
172
+ const { id } = request.params as { id: string };
173
+ await storage.markAsRead(id);
174
+ return { success: true };
175
+ });
176
+
177
+ // POST /api/message/:id/archive
178
+ fastify.post('/api/message/:id/archive', async (request, reply) => {
179
+ const { id } = request.params as { id: string };
180
+ await storage.archiveMessage(id);
181
+ return { success: true };
182
+ });
183
+
184
+ // GET /api/stats
185
+ fastify.get('/api/stats', async (request, reply) => {
186
+ const messages = await storage.getInbox(agentId);
187
+ const unread = messages.filter(m => !m.read).length;
188
+ return {
189
+ total: messages.length,
190
+ unread,
191
+ encrypted: messages.filter(m => m.encrypted).length
192
+ };
193
+ });
194
+ }
195
+ ```
196
+
197
+ **Update server.ts to use routes:**
198
+ ```typescript
199
+ import { registerRoutes } from './routes.js';
200
+
201
+ // After creating fastify instance:
202
+ await registerRoutes(fastify);
203
+ ```
204
+
205
+ ### Step 4: Create Frontend UI (2-3 hours)
206
+
207
+ **File:** `src/dashboard/public/index.html`
208
+
209
+ ```html
210
+ <!DOCTYPE html>
211
+ <html lang="en">
212
+ <head>
213
+ <meta charset="UTF-8">
214
+ <title>🍄 Myceliumail Dashboard</title>
215
+ <script src="https://cdn.tailwindcss.com"></script>
216
+ <link rel="stylesheet" href="/styles.css">
217
+ </head>
218
+ <body class="bg-gray-900 text-gray-100">
219
+ <div class="container mx-auto p-6">
220
+ <!-- Header -->
221
+ <header class="flex justify-between items-center mb-8">
222
+ <h1 class="text-3xl font-bold">🍄 Myceliumail Dashboard</h1>
223
+ <div id="stats" class="text-sm text-gray-400"></div>
224
+ </header>
225
+
226
+ <!-- Inbox List -->
227
+ <div class="grid grid-cols-3 gap-6">
228
+ <div class="col-span-1 bg-gray-800 rounded-lg p-4">
229
+ <h2 class="text-xl font-semibold mb-4">Inbox</h2>
230
+ <div id="inbox-list" class="space-y-2"></div>
231
+ </div>
232
+
233
+ <!-- Message Detail -->
234
+ <div class="col-span-2 bg-gray-800 rounded-lg p-6">
235
+ <div id="message-detail">
236
+ <p class="text-gray-500">Select a message to view</p>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+
242
+ <script src="/app.js"></script>
243
+ </body>
244
+ </html>
245
+ ```
246
+
247
+ **File:** `src/dashboard/public/app.js`
248
+
249
+ ```javascript
250
+ // Load inbox on page load
251
+ async function loadInbox() {
252
+ const res = await fetch('/api/inbox');
253
+ const data = await res.json();
254
+
255
+ const list = document.getElementById('inbox-list');
256
+ list.innerHTML = data.messages.map(msg => `
257
+ <div class="message-item p-3 rounded cursor-pointer hover:bg-gray-700 ${msg.read ? '' : 'font-bold'}"
258
+ onclick="viewMessage('${msg.id}')">
259
+ <div class="flex items-center gap-2">
260
+ ${msg.encrypted ? '🔐' : '📨'}
261
+ ${!msg.read ? '●' : ''}
262
+ <span class="text-sm">${msg.sender}</span>
263
+ </div>
264
+ <div class="text-sm text-gray-400 truncate">${msg.subject || '(no subject)'}</div>
265
+ </div>
266
+ `).join('');
267
+
268
+ updateStats(data);
269
+ }
270
+
271
+ async function viewMessage(id) {
272
+ const res = await fetch(`/api/message/${id}`);
273
+ const msg = await res.json();
274
+
275
+ const detail = document.getElementById('message-detail');
276
+ detail.innerHTML = `
277
+ <div class="mb-4">
278
+ <div class="text-sm text-gray-400">From: ${msg.sender}</div>
279
+ <h2 class="text-2xl font-bold">${msg.subject}</h2>
280
+ <div class="text-sm text-gray-400">${new Date(msg.createdAt).toLocaleString()}</div>
281
+ ${msg.encrypted ? '<div class="text-sm text-green-400">🔐 Encrypted (decrypted ✅)</div>' : ''}
282
+ </div>
283
+ <div class="prose prose-invert max-w-none">
284
+ <p class="whitespace-pre-wrap">${msg.body}</p>
285
+ </div>
286
+ <div class="mt-6 flex gap-4">
287
+ <button onclick="archiveMessage('${msg.id}')"
288
+ class="px-4 py-2 bg-gray-700 rounded hover:bg-gray-600">
289
+ Archive
290
+ </button>
291
+ </div>
292
+ `;
293
+
294
+ // Mark as read
295
+ await fetch(`/api/message/${id}/read`, { method: 'POST' });
296
+ loadInbox(); // Refresh
297
+ }
298
+
299
+ async function archiveMessage(id) {
300
+ await fetch(`/api/message/${id}/archive`, { method: 'POST' });
301
+ loadInbox();
302
+ document.getElementById('message-detail').innerHTML = '<p class="text-gray-500">Select a message to view</p>';
303
+ }
304
+
305
+ function updateStats(data) {
306
+ document.getElementById('stats').innerHTML = `
307
+ Total: ${data.total} | Unread: ${data.messages.filter(m => !m.read).length}
308
+ `;
309
+ }
310
+
311
+ // Load on page load
312
+ loadInbox();
313
+
314
+ // Auto-refresh every 10 seconds
315
+ setInterval(loadInbox, 10000);
316
+ ```
317
+
318
+ **File:** `src/dashboard/public/styles.css`
319
+
320
+ ```css
321
+ body {
322
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
323
+ }
324
+
325
+ .message-item {
326
+ transition: all 0.2s;
327
+ }
328
+
329
+ .message-item:hover {
330
+ transform: translateX(4px);
331
+ }
332
+ ```
333
+
334
+ ### Step 5: Add CLI Command (30 min)
335
+
336
+ **File:** `src/commands/dashboard.ts`
337
+
338
+ ```typescript
339
+ import { Command } from 'commander';
340
+ import { startDashboard } from '../dashboard/server.js';
341
+
342
+ export function createDashboardCommand(): Command {
343
+ return new Command('dashboard')
344
+ .description('Start web dashboard on localhost:3737')
345
+ .option('-p, --port <port>', 'Port to run on', '3737')
346
+ .action(async (options) => {
347
+ const port = parseInt(options.port, 10);
348
+ await startDashboard(port);
349
+ console.log(`\n🍄 Dashboard running: http://localhost:${port}\n`);
350
+ console.log('Press Ctrl+C to stop\n');
351
+ });
352
+ }
353
+ ```
354
+
355
+ **Add to** `src/bin/myceliumail.ts`:
356
+ ```typescript
357
+ import { createDashboardCommand } from '../commands/dashboard.js';
358
+
359
+ // Register with other commands
360
+ program.addCommand(createDashboardCommand());
361
+ ```
362
+
363
+ ### Step 6: Build & Test (30 min)
364
+
365
+ ```bash
366
+ # Build
367
+ npm run build
368
+
369
+ # Test
370
+ mycmail dashboard
371
+
372
+ # Open browser
373
+ open http://localhost:3737
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Acceptance Criteria
379
+
380
+ ✅ Dashboard loads on http://localhost:3737
381
+ ✅ Shows all messages from inbox
382
+ ✅ Encrypted messages are decrypted automatically
383
+ ✅ Clicking message shows full content
384
+ ✅ Mark as read works
385
+ ✅ Archive works
386
+ ✅ Stats show correct counts
387
+ ✅ Auto-refresh every 10 seconds
388
+ ✅ Dark mode, clean UI
389
+
390
+ ---
391
+
392
+ ## Testing Scenarios
393
+
394
+ 1. **Empty inbox** → Shows "No messages"
395
+ 2. **Encrypted message** → Decrypts and displays ✅
396
+ 3. **Unread message** → Shows bold, has ● indicator
397
+ 4. **Archive** → Message disappears from list
398
+ 5. **Multiple agents** → All messages visible
399
+
400
+ ---
401
+
402
+ ## Troubleshooting
403
+
404
+ **Port already in use:**
405
+ ```bash
406
+ mycmail dashboard --port 3738
407
+ ```
408
+
409
+ **Build errors:**
410
+ ```bash
411
+ npm install @types/node fastify @fastify/static
412
+ ```
413
+
414
+ **Messages not showing:**
415
+ - Check storage: `cat ~/.myceliumail/data/messages.json`
416
+ - Check config: `echo $MYCELIUMAIL_AGENT_ID`
417
+ - Check logs in terminal
418
+
419
+ ---
420
+
421
+ ## Resources
422
+
423
+ - **Fastify docs:** https://fastify.dev/
424
+ - **Tailwind CSS:** https://tailwindcss.com/docs
425
+ - **Existing code:** `src/`
426
+
427
+ ---
428
+
429
+ **Ready to build! Start with Step 1.** 🍄
@@ -0,0 +1,32 @@
1
+ # Quick Start Prompt for Fresh Agent
2
+
3
+ **Copy-paste this to a new Gemini agent:**
4
+
5
+ ---
6
+
7
+ Hi! I need you to build a web dashboard for Myceliumail.
8
+
9
+ **Context:**
10
+ - Project: `./` (clone from GitHub)
11
+ - Read this first: `docs/DASHBOARD_AGENT_HANDOFF.md`
12
+ - Follow roadmap: `docs/DASHBOARD_BUILD_ROADMAP.md`
13
+
14
+ **Your mission:**
15
+ Build a local web dashboard (http://localhost:3737) to view Myceliumail messages.
16
+
17
+ **Key requirements:**
18
+ 1. Use existing modules in `src/storage/`, `src/lib/crypto.ts`, `src/lib/config.ts`
19
+ 2. Build with Fastify + Tailwind CSS
20
+ 3. Auto-decrypt encrypted messages
21
+ 4. Dark mode UI, clean design
22
+ 5. Add `mycmail dashboard` CLI command
23
+
24
+ **Time estimate:** 4-6 hours
25
+
26
+ **Acceptance criteria:** User can run `mycmail dashboard`, open browser, see all messages (encrypted ones decrypted), archive/mark as read.
27
+
28
+ Start with Phase 1 in the roadmap!
29
+
30
+ ---
31
+
32
+ **That's it! Hand this to a new agent and they're ready to build.**
@@ -0,0 +1,61 @@
1
+ # Dashboard Build Roadmap
2
+
3
+ > Quick reference for agent building the web dashboard
4
+
5
+ ## Phase 1: Setup (15 min)
6
+ - [ ] Install: `npm install fastify @fastify/static @fastify/cors`
7
+ - [ ] Create: `src/dashboard/` directory
8
+ - [ ] Create: `src/dashboard/public/` directory
9
+
10
+ ## Phase 2: Backend (2 hours)
11
+ - [ ] Create `src/dashboard/server.ts` (Fastify server)
12
+ - [ ] Create `src/dashboard/routes.ts` (5 API endpoints)
13
+ - [ ] Test: `GET /api/inbox` returns messages
14
+ - [ ] Test: `GET /api/message/:id` decrypts encrypted messages
15
+ - [ ] Test: `POST /api/message/:id/read` marks as read
16
+
17
+ ## Phase 3: Frontend (2-3 hours)
18
+ - [ ] Create `src/dashboard/public/index.html` (layout + Tailwind)
19
+ - [ ] Create `src/dashboard/public/app.js` (fetch API, render messages)
20
+ - [ ] Create `src/dashboard/public/styles.css` (custom styles)
21
+ - [ ] Test: Messages load in browser
22
+ - [ ] Test: Click message → shows detail
23
+ - [ ] Test: Archive button works
24
+
25
+ ## Phase 4: CLI Integration (30 min)
26
+ - [ ] Create `src/commands/dashboard.ts`
27
+ - [ ] Register in `src/bin/myceliumail.ts`
28
+ - [ ] Build: `npm run build`
29
+ - [ ] Test: `mycmail dashboard` starts server
30
+
31
+ ## Phase 5: Polish (1 hour)
32
+ - [ ] Add auto-refresh (10 sec interval)
33
+ - [ ] Add unread indicators (bold + ●)
34
+ - [ ] Add stats header (total, unread)
35
+ - [ ] Add keyboard shortcuts (optional)
36
+ - [ ] Dark mode polish
37
+
38
+ ## Acceptance Tests
39
+ - [ ] Can view all local messages
40
+ - [ ] Can view Supabase messages (if configured)
41
+ - [ ] Encrypted messages decrypt automatically
42
+ - [ ] Mark as read updates UI
43
+ - [ ] Archive removes from inbox
44
+ - [ ] UI is responsive and clean
45
+
46
+ ## Time Budget
47
+ - Setup: 15 min
48
+ - Backend: 2 hours
49
+ - Frontend: 2-3 hours
50
+ - CLI: 30 min
51
+ - Polish: 1 hour
52
+ **Total: 4-6 hours**
53
+
54
+ ## Key Files to Reference
55
+ - Storage API: `src/storage/supabase.ts`
56
+ - Crypto: `src/lib/crypto.ts`
57
+ - Config: `src/lib/config.ts`
58
+ - Types: `src/types/index.ts`
59
+
60
+ ## Success =
61
+ User runs `mycmail dashboard`, opens browser, sees beautiful inbox with all messages (encrypted ones decrypted), can archive/read, feels 🍄 magical!
@@ -0,0 +1,59 @@
1
+ # Myceliumail Deployment Checklist
2
+
3
+ ## Pre-Deployment
4
+
5
+ ### 1. Environment Setup
6
+ - [ ] Set `MYCELIUMAIL_STORAGE=supabase` in `.env`
7
+ - [ ] Set production Supabase credentials:
8
+ ```bash
9
+ SUPABASE_URL=https://your-project.supabase.co
10
+ SUPABASE_ANON_KEY=your-production-key
11
+ ```
12
+ - [ ] Verify agent ID: `MYCELIUMAIL_AGENT_ID=your-agent`
13
+
14
+ ### 2. Database
15
+ - [ ] Run migrations on production Supabase
16
+ - [ ] Verify `agent_messages` table exists with correct schema
17
+ - [ ] Check RLS policies are enabled
18
+
19
+ ### 3. Build & Test
20
+ - [ ] Run `npm run build` - no errors
21
+ - [ ] Test send: `mycmail send test-agent "Test" -m "Hello"`
22
+ - [ ] Test inbox: `mycmail inbox`
23
+ - [ ] Test dashboard: `mycmail dashboard`
24
+
25
+ ### 4. Security
26
+ - [ ] Ensure `.env` is in `.gitignore`
27
+ - [ ] No secrets committed to git
28
+ - [ ] Review public keys in `docs/AGENT_STARTER_KIT.md`
29
+
30
+ ---
31
+
32
+ ## Post-Deployment
33
+
34
+ ### 1. Verify
35
+ - [ ] Send test message to known agent
36
+ - [ ] Check message appears in Supabase dashboard
37
+ - [ ] Verify encryption works: `mycmail send agent "Test" -m "Secret" --encrypt`
38
+
39
+ ### 2. Update Agents
40
+ - [ ] Notify agents of production URL
41
+ - [ ] Share updated MCP config with Supabase credentials
42
+ - [ ] Confirm agents can send/receive
43
+
44
+ ### 3. Monitor
45
+ - [ ] Check Supabase logs for errors
46
+ - [ ] Monitor message table growth
47
+ - [ ] Review API usage/limits
48
+
49
+ ---
50
+
51
+ ## Rollback
52
+ If issues occur:
53
+ ```bash
54
+ # Switch back to local storage
55
+ MYCELIUMAIL_STORAGE=local mycmail inbox
56
+
57
+ # Or switch to staging
58
+ SUPABASE_URL=https://staging-project.supabase.co
59
+ ```
@@ -0,0 +1,127 @@
1
+ # Lessons Learned: MCP Supabase Connection Debugging
2
+
3
+ ## Date
4
+ December 17-18, 2025
5
+
6
+ ## Issue Summary
7
+ Watson (Claude Desktop MCP user) could not see Supabase messages. The MCP server only showed locally cached messages instead of fetching from the cloud.
8
+
9
+ ---
10
+
11
+ ## Root Causes Identified
12
+
13
+ ### 1. Schema Mismatch (Code Bug)
14
+ **Problem:** The MCP server's `storage.ts` was using incorrect column names when querying Supabase:
15
+ - Used `recipient` instead of `to_agent`
16
+ - Used `sender` instead of `from_agent`
17
+ - Used `body` instead of `message`
18
+
19
+ **Symptom:** Supabase queries returned empty results because the columns didn't exist.
20
+
21
+ **Fix:** Updated all Supabase queries in `storage.ts` to use the correct column names matching the actual `agent_messages` table schema.
22
+
23
+ **Lesson:** Always verify that code column names match the actual database schema. Consider using generated types from Supabase to catch these mismatches at compile time.
24
+
25
+ ---
26
+
27
+ ### 2. Silent Error Swallowing (Bad Pattern)
28
+ **Problem:** All Supabase operations had empty `catch` blocks:
29
+ ```typescript
30
+ } catch {
31
+ // Fall through to local
32
+ }
33
+ ```
34
+
35
+ **Symptom:** Errors were completely hidden. When Supabase failed, the code silently fell back to local storage without any indication of why.
36
+
37
+ **Fix:** Added proper error logging to all catch blocks:
38
+ ```typescript
39
+ } catch (err) {
40
+ console.error('getInbox failed, falling back to local:', err);
41
+ // Fall through to local
42
+ }
43
+ ```
44
+
45
+ **Lesson:** Never use empty catch blocks. Always log errors, even when recovering gracefully. Silent failures are debugging nightmares.
46
+
47
+ ---
48
+
49
+ ### 3. NPX Caching (Deployment Issue)
50
+ **Problem:** `npx myceliumail-mcp` was aggressively caching old versions of the package, even after publishing fixes to npm.
51
+
52
+ **Symptom:** Even after publishing v1.0.6 with fixes, Claude Desktop kept running the broken old version.
53
+
54
+ **Attempted Solutions:**
55
+ - `npx -y myceliumail-mcp@1.0.6` - Did not reliably bust cache
56
+ - `npm cache clean --force` - Not effective for npx cache
57
+
58
+ **Final Fix:** Configured Claude Desktop to run the local build directly:
59
+ ```json
60
+ {
61
+ "command": "node",
62
+ "args": ["/path/to/dist/server.js"]
63
+ }
64
+ ```
65
+
66
+ **Lesson:** For development and debugging, always use local builds with direct paths. Don't trust `npx` caching behavior during active development. For production users, consider adding version-specific instructions: `npx myceliumail-mcp@latest`.
67
+
68
+ ---
69
+
70
+ ### 4. Missing Global Config Support (Feature Gap)
71
+ **Problem:** The MCP server only read Supabase credentials from environment variables, but Claude Desktop's MCP config doesn't support complex env var setup easily.
72
+
73
+ **Fix:** Added fallback to read from `~/.myceliumail/config.json`, same as the CLI tool.
74
+
75
+ **Lesson:** MCP servers should support multiple config sources (env vars, config files) for flexibility across different deployment contexts.
76
+
77
+ ---
78
+
79
+ ## Debugging Techniques Used
80
+
81
+ ### 1. File-Based Debug Logging
82
+ When console output was being swallowed by the MCP runtime, we added file-based logging:
83
+ ```typescript
84
+ const LOG_FILE = join(homedir(), '.myceliumail', 'debug.log');
85
+ appendFileSync(LOG_FILE, `[${timestamp}] ${msg}\n`);
86
+ ```
87
+
88
+ This proved essential for diagnosing issues in environments where stderr isn't visible.
89
+
90
+ ### 2. Reproduction Script
91
+ Created `debug-mcp-connection.js` to test the Supabase connection outside of the MCP context:
92
+ ```javascript
93
+ const { hasSupabase } = require('./dist/lib/config.js');
94
+ const { getInbox } = require('./dist/lib/storage.js');
95
+ // Test directly
96
+ ```
97
+
98
+ This isolated whether the issue was in the code or the MCP runtime environment.
99
+
100
+ ### 3. Direct Supabase Verification
101
+ Used the Supabase MCP tool to verify data existed:
102
+ ```sql
103
+ SELECT * FROM agent_messages WHERE to_agent = 'watson';
104
+ ```
105
+
106
+ This confirmed the data was in the cloud and the issue was in fetching, not storage.
107
+
108
+ ---
109
+
110
+ ## Prevention Guidelines
111
+
112
+ 1. **Schema Validation:** Use TypeScript generated types from Supabase CLI to catch column name mismatches at compile time.
113
+
114
+ 2. **Error Visibility:** Always log errors, never swallow them silently. Use a consistent error logging pattern.
115
+
116
+ 3. **Multiple Config Sources:** Support env vars AND config files for flexibility.
117
+
118
+ 4. **Local Development:** Always test with local builds during debugging. Don't rely on npm/npx for rapid iteration.
119
+
120
+ 5. **Integration Tests:** Add tests that actually hit Supabase (in a test project) to catch schema drift.
121
+
122
+ ---
123
+
124
+ ## Related Files Modified
125
+ - `mcp-server/src/lib/config.ts` - Added config file support
126
+ - `mcp-server/src/lib/storage.ts` - Fixed column names, added error logging
127
+ - `mcp-server/package.json` - Version bumps