myceliumail-mcp 1.0.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/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # 🍄 Myceliumail MCP Server
2
+
3
+ > **Connect Myceliumail to Claude Desktop and other MCP clients**
4
+
5
+ <img src="assets/icon.png" alt="Myceliumail" width="128" />
6
+
7
+ ## Quick Start
8
+
9
+ ### 1. Build the MCP Server
10
+
11
+ ```bash
12
+ cd mcp-server
13
+ npm install
14
+ npm run build
15
+ ```
16
+
17
+ ### 2. Configure Claude Desktop
18
+
19
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "myceliumail": {
25
+ "command": "node",
26
+ "args": ["/Users/YOUR_USERNAME/Dev/myceliumail/mcp-server/dist/server.js"],
27
+ "env": {
28
+ "MYCELIUMAIL_AGENT_ID": "claude-desktop"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ **Important:** Replace `/Users/YOUR_USERNAME/Dev/myceliumail` with your actual path.
36
+
37
+ ### 3. Restart Claude Desktop
38
+
39
+ Quit and reopen Claude Desktop. You should see "myceliumail" in the MCP tools.
40
+
41
+ ---
42
+
43
+ ## Available Tools
44
+
45
+ | Tool | Description |
46
+ |------|-------------|
47
+ | `check_inbox` | View incoming messages |
48
+ | `read_message` | Read a specific message |
49
+ | `send_message` | Send a message to another agent |
50
+ | `reply_message` | Reply to a message |
51
+ | `generate_keys` | Create encryption keypair |
52
+ | `list_keys` | Show known keys |
53
+ | `import_key` | Import peer's public key |
54
+ | `archive_message` | Archive a message |
55
+
56
+ ---
57
+
58
+ ## Usage Examples
59
+
60
+ ### Check inbox
61
+ ```
62
+ "What messages do I have in my myceliumail inbox?"
63
+ ```
64
+
65
+ ### Send a message
66
+ ```
67
+ "Send a myceliumail message to spidersan-agent with subject 'Need help' and body 'Can you review my PR?'"
68
+ ```
69
+
70
+ ### Encrypted messaging
71
+ ```
72
+ "First generate my encryption keys, then import spidersan-agent's key: PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8="
73
+ "Now send an encrypted message to spidersan-agent about the secret project"
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Environment Variables
79
+
80
+ | Variable | Description | Required |
81
+ |----------|-------------|----------|
82
+ | `MYCELIUMAIL_AGENT_ID` | Your agent identity | Yes |
83
+ | `SUPABASE_URL` | Supabase project URL | No (uses local storage) |
84
+ | `SUPABASE_ANON_KEY` | Supabase anon key | No (uses local storage) |
85
+
86
+ ---
87
+
88
+ ## With Supabase (Cloud Sync)
89
+
90
+ To enable cross-agent messaging via cloud:
91
+
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "myceliumail": {
96
+ "command": "node",
97
+ "args": ["/path/to/mcp-server/dist/server.js"],
98
+ "env": {
99
+ "MYCELIUMAIL_AGENT_ID": "claude-desktop",
100
+ "SUPABASE_URL": "https://your-project.supabase.co",
101
+ "SUPABASE_ANON_KEY": "your-anon-key"
102
+ }
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Known Agents
111
+
112
+ | Agent | Public Key |
113
+ |-------|------------|
114
+ | `mycsan` | `PKbSbbHJY3DstxsqjWjgfi9tP5jjM9fSqEd7BLciex8=` |
115
+
116
+ ---
117
+
118
+ ## Troubleshooting
119
+
120
+ **MCP server not appearing in Claude Desktop**
121
+ - Verify the path in config is correct
122
+ - Check Claude Desktop logs: `~/Library/Logs/Claude/`
123
+ - Ensure server builds: `npm run build`
124
+
125
+ **Messages not syncing between agents**
126
+ - Without Supabase: messages are local only
127
+ - With Supabase: verify credentials and run migration
128
+
129
+ **Encryption not working**
130
+ - Generate keys first: use `generate_keys` tool
131
+ - Import peer's key: use `import_key` tool
132
+
133
+ ---
134
+
135
+ ## Uninstalling
136
+
137
+ Remove the `myceliumail` entry from your Claude Desktop config:
138
+
139
+ **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
140
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
141
+
142
+ Then restart Claude Desktop.
143
+
Binary file
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Myceliumail MCP - Config Module
3
+ */
4
+ export declare function getAgentId(): string;
5
+ export declare function getSupabaseUrl(): string | undefined;
6
+ export declare function getSupabaseKey(): string | undefined;
7
+ export declare function hasSupabase(): boolean;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Myceliumail MCP - Config Module
3
+ */
4
+ export function getAgentId() {
5
+ return process.env.MYCELIUMAIL_AGENT_ID ||
6
+ process.env.MYCELIUMAIL_AGENT ||
7
+ 'anonymous';
8
+ }
9
+ export function getSupabaseUrl() {
10
+ return process.env.SUPABASE_URL;
11
+ }
12
+ export function getSupabaseKey() {
13
+ return process.env.SUPABASE_ANON_KEY;
14
+ }
15
+ export function hasSupabase() {
16
+ return !!(getSupabaseUrl() && getSupabaseKey());
17
+ }
18
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,UAAU;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB;QACnC,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAC7B,WAAW,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,cAAc;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW;IACvB,OAAO,CAAC,CAAC,CAAC,cAAc,EAAE,IAAI,cAAc,EAAE,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Myceliumail MCP - Crypto Module
3
+ *
4
+ * NaCl encryption for agent messaging.
5
+ */
6
+ export interface KeyPair {
7
+ publicKey: Uint8Array;
8
+ secretKey: Uint8Array;
9
+ }
10
+ export interface EncryptedMessage {
11
+ ciphertext: string;
12
+ nonce: string;
13
+ senderPublicKey: string;
14
+ }
15
+ export declare function generateKeyPair(): KeyPair;
16
+ export declare function saveKeyPair(agentId: string, keyPair: KeyPair): void;
17
+ export declare function loadKeyPair(agentId: string): KeyPair | null;
18
+ export declare function hasKeyPair(agentId: string): boolean;
19
+ export declare function getPublicKeyBase64(keyPair: KeyPair): string;
20
+ export declare function encryptMessage(message: string, recipientPublicKey: Uint8Array, senderKeyPair: KeyPair): EncryptedMessage;
21
+ export declare function decryptMessage(encrypted: EncryptedMessage, recipientKeyPair: KeyPair): string | null;
22
+ export declare function loadKnownKeys(): Record<string, string>;
23
+ export declare function saveKnownKey(agentId: string, publicKeyBase64: string): void;
24
+ export declare function getKnownKey(agentId: string): string | null;
25
+ export declare function listOwnKeys(): string[];
26
+ export declare function decodePublicKey(base64: string): Uint8Array;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Myceliumail MCP - Crypto Module
3
+ *
4
+ * NaCl encryption for agent messaging.
5
+ */
6
+ import nacl from 'tweetnacl';
7
+ import util from 'tweetnacl-util';
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { homedir } from 'os';
11
+ const KEYS_DIR = join(homedir(), '.myceliumail', 'keys');
12
+ function ensureKeysDir() {
13
+ if (!existsSync(KEYS_DIR)) {
14
+ mkdirSync(KEYS_DIR, { recursive: true });
15
+ }
16
+ }
17
+ export function generateKeyPair() {
18
+ return nacl.box.keyPair();
19
+ }
20
+ export function saveKeyPair(agentId, keyPair) {
21
+ ensureKeysDir();
22
+ const serialized = {
23
+ publicKey: util.encodeBase64(keyPair.publicKey),
24
+ secretKey: util.encodeBase64(keyPair.secretKey),
25
+ };
26
+ const path = join(KEYS_DIR, `${agentId}.key.json`);
27
+ writeFileSync(path, JSON.stringify(serialized, null, 2), { mode: 0o600 });
28
+ }
29
+ export function loadKeyPair(agentId) {
30
+ const path = join(KEYS_DIR, `${agentId}.key.json`);
31
+ if (!existsSync(path))
32
+ return null;
33
+ try {
34
+ const data = JSON.parse(readFileSync(path, 'utf-8'));
35
+ return {
36
+ publicKey: util.decodeBase64(data.publicKey),
37
+ secretKey: util.decodeBase64(data.secretKey),
38
+ };
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ export function hasKeyPair(agentId) {
45
+ return existsSync(join(KEYS_DIR, `${agentId}.key.json`));
46
+ }
47
+ export function getPublicKeyBase64(keyPair) {
48
+ return util.encodeBase64(keyPair.publicKey);
49
+ }
50
+ export function encryptMessage(message, recipientPublicKey, senderKeyPair) {
51
+ const messageBytes = util.decodeUTF8(message);
52
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
53
+ const ciphertext = nacl.box(messageBytes, nonce, recipientPublicKey, senderKeyPair.secretKey);
54
+ return {
55
+ ciphertext: util.encodeBase64(ciphertext),
56
+ nonce: util.encodeBase64(nonce),
57
+ senderPublicKey: util.encodeBase64(senderKeyPair.publicKey),
58
+ };
59
+ }
60
+ export function decryptMessage(encrypted, recipientKeyPair) {
61
+ try {
62
+ const ciphertext = util.decodeBase64(encrypted.ciphertext);
63
+ const nonce = util.decodeBase64(encrypted.nonce);
64
+ const senderPublicKey = util.decodeBase64(encrypted.senderPublicKey);
65
+ const decrypted = nacl.box.open(ciphertext, nonce, senderPublicKey, recipientKeyPair.secretKey);
66
+ if (!decrypted)
67
+ return null;
68
+ return util.encodeUTF8(decrypted);
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ export function loadKnownKeys() {
75
+ const path = join(KEYS_DIR, 'known_keys.json');
76
+ if (!existsSync(path))
77
+ return {};
78
+ try {
79
+ return JSON.parse(readFileSync(path, 'utf-8'));
80
+ }
81
+ catch {
82
+ return {};
83
+ }
84
+ }
85
+ export function saveKnownKey(agentId, publicKeyBase64) {
86
+ ensureKeysDir();
87
+ const keys = loadKnownKeys();
88
+ keys[agentId] = publicKeyBase64;
89
+ writeFileSync(join(KEYS_DIR, 'known_keys.json'), JSON.stringify(keys, null, 2));
90
+ }
91
+ export function getKnownKey(agentId) {
92
+ const keys = loadKnownKeys();
93
+ return keys[agentId] || null;
94
+ }
95
+ export function listOwnKeys() {
96
+ ensureKeysDir();
97
+ try {
98
+ const files = readdirSync(KEYS_DIR);
99
+ return files
100
+ .filter(f => f.endsWith('.key.json'))
101
+ .map(f => f.replace('.key.json', ''));
102
+ }
103
+ catch {
104
+ return [];
105
+ }
106
+ }
107
+ export function decodePublicKey(base64) {
108
+ return util.decodeBase64(base64);
109
+ }
110
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/lib/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Myceliumail MCP - Storage Module
3
+ *
4
+ * Local JSON storage with optional Supabase sync.
5
+ */
6
+ export interface Message {
7
+ id: string;
8
+ sender: string;
9
+ recipient: string;
10
+ subject: string;
11
+ body: string;
12
+ encrypted: boolean;
13
+ ciphertext?: string;
14
+ nonce?: string;
15
+ senderPublicKey?: string;
16
+ read: boolean;
17
+ archived: boolean;
18
+ createdAt: Date;
19
+ }
20
+ export declare function sendMessage(sender: string, recipient: string, subject: string, body: string, options?: {
21
+ encrypted?: boolean;
22
+ ciphertext?: string;
23
+ nonce?: string;
24
+ senderPublicKey?: string;
25
+ }): Promise<Message>;
26
+ export declare function getInbox(agentId: string, options?: {
27
+ unreadOnly?: boolean;
28
+ limit?: number;
29
+ }): Promise<Message[]>;
30
+ export declare function getMessage(id: string): Promise<Message | null>;
31
+ export declare function markAsRead(id: string): Promise<boolean>;
32
+ export declare function archiveMessage(id: string): Promise<boolean>;
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Myceliumail MCP - Storage Module
3
+ *
4
+ * Local JSON storage with optional Supabase sync.
5
+ */
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ import { randomUUID } from 'crypto';
10
+ import { getSupabaseUrl, getSupabaseKey, hasSupabase } from './config.js';
11
+ const DATA_DIR = join(homedir(), '.myceliumail', 'data');
12
+ const MESSAGES_FILE = join(DATA_DIR, 'messages.json');
13
+ function ensureDataDir() {
14
+ if (!existsSync(DATA_DIR)) {
15
+ mkdirSync(DATA_DIR, { recursive: true });
16
+ }
17
+ }
18
+ function loadLocalMessages() {
19
+ if (!existsSync(MESSAGES_FILE))
20
+ return [];
21
+ try {
22
+ return JSON.parse(readFileSync(MESSAGES_FILE, 'utf-8'));
23
+ }
24
+ catch {
25
+ return [];
26
+ }
27
+ }
28
+ function saveLocalMessages(messages) {
29
+ ensureDataDir();
30
+ writeFileSync(MESSAGES_FILE, JSON.stringify(messages, null, 2));
31
+ }
32
+ function toMessage(stored) {
33
+ return { ...stored, createdAt: new Date(stored.createdAt) };
34
+ }
35
+ // Supabase helpers
36
+ async function supabaseRequest(path, options = {}) {
37
+ const url = `${getSupabaseUrl()}/rest/v1${path}`;
38
+ const response = await fetch(url, {
39
+ ...options,
40
+ headers: {
41
+ 'Content-Type': 'application/json',
42
+ 'apikey': getSupabaseKey(),
43
+ 'Authorization': `Bearer ${getSupabaseKey()}`,
44
+ 'Prefer': options.method === 'POST' ? 'return=representation' : 'return=minimal',
45
+ ...options.headers,
46
+ },
47
+ });
48
+ if (!response.ok)
49
+ throw new Error(await response.text());
50
+ if (response.status === 204)
51
+ return {};
52
+ return response.json();
53
+ }
54
+ export async function sendMessage(sender, recipient, subject, body, options) {
55
+ const newMessage = {
56
+ id: randomUUID(),
57
+ sender,
58
+ recipient,
59
+ subject: options?.encrypted ? '' : subject,
60
+ body: options?.encrypted ? '' : body,
61
+ encrypted: options?.encrypted || false,
62
+ ciphertext: options?.ciphertext,
63
+ nonce: options?.nonce,
64
+ senderPublicKey: options?.senderPublicKey,
65
+ read: false,
66
+ archived: false,
67
+ createdAt: new Date().toISOString(),
68
+ };
69
+ if (hasSupabase()) {
70
+ try {
71
+ const [result] = await supabaseRequest('/agent_messages', {
72
+ method: 'POST',
73
+ body: JSON.stringify({
74
+ sender: newMessage.sender,
75
+ recipient: newMessage.recipient,
76
+ subject: newMessage.subject || null,
77
+ body: newMessage.body || null,
78
+ encrypted: newMessage.encrypted,
79
+ ciphertext: newMessage.ciphertext,
80
+ nonce: newMessage.nonce,
81
+ sender_public_key: newMessage.senderPublicKey,
82
+ }),
83
+ });
84
+ return toMessage({
85
+ ...newMessage,
86
+ id: result.id
87
+ });
88
+ }
89
+ catch {
90
+ // Fall through to local
91
+ }
92
+ }
93
+ // Local storage
94
+ const messages = loadLocalMessages();
95
+ messages.push(newMessage);
96
+ saveLocalMessages(messages);
97
+ return toMessage(newMessage);
98
+ }
99
+ export async function getInbox(agentId, options) {
100
+ if (hasSupabase()) {
101
+ try {
102
+ let query = `/agent_messages?recipient=eq.${agentId}&archived=eq.false&order=created_at.desc`;
103
+ if (options?.unreadOnly)
104
+ query += '&read=eq.false';
105
+ if (options?.limit)
106
+ query += `&limit=${options.limit}`;
107
+ const results = await supabaseRequest(query);
108
+ return results.map(r => ({
109
+ id: r.id,
110
+ sender: r.sender,
111
+ recipient: r.recipient,
112
+ subject: r.subject || '',
113
+ body: r.body || '',
114
+ encrypted: r.encrypted,
115
+ ciphertext: r.ciphertext,
116
+ nonce: r.nonce,
117
+ senderPublicKey: r.sender_public_key,
118
+ read: r.read,
119
+ archived: r.archived,
120
+ createdAt: new Date(r.created_at),
121
+ }));
122
+ }
123
+ catch {
124
+ // Fall through to local
125
+ }
126
+ }
127
+ // Local storage
128
+ const messages = loadLocalMessages();
129
+ let filtered = messages.filter(m => m.recipient === agentId && !m.archived);
130
+ if (options?.unreadOnly)
131
+ filtered = filtered.filter(m => !m.read);
132
+ filtered.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
133
+ if (options?.limit)
134
+ filtered = filtered.slice(0, options.limit);
135
+ return filtered.map(toMessage);
136
+ }
137
+ export async function getMessage(id) {
138
+ if (hasSupabase()) {
139
+ try {
140
+ const results = await supabaseRequest(`/agent_messages?id=eq.${id}`);
141
+ if (results.length > 0) {
142
+ const r = results[0];
143
+ return {
144
+ id: r.id,
145
+ sender: r.sender,
146
+ recipient: r.recipient,
147
+ subject: r.subject || '',
148
+ body: r.body || '',
149
+ encrypted: r.encrypted,
150
+ ciphertext: r.ciphertext,
151
+ nonce: r.nonce,
152
+ senderPublicKey: r.sender_public_key,
153
+ read: r.read,
154
+ archived: r.archived,
155
+ createdAt: new Date(r.created_at),
156
+ };
157
+ }
158
+ }
159
+ catch {
160
+ // Fall through
161
+ }
162
+ }
163
+ const messages = loadLocalMessages();
164
+ const found = messages.find(m => m.id === id);
165
+ return found ? toMessage(found) : null;
166
+ }
167
+ export async function markAsRead(id) {
168
+ if (hasSupabase()) {
169
+ try {
170
+ await supabaseRequest(`/agent_messages?id=eq.${id}`, {
171
+ method: 'PATCH',
172
+ body: JSON.stringify({ read: true }),
173
+ });
174
+ return true;
175
+ }
176
+ catch {
177
+ // Fall through
178
+ }
179
+ }
180
+ const messages = loadLocalMessages();
181
+ const idx = messages.findIndex(m => m.id === id);
182
+ if (idx === -1)
183
+ return false;
184
+ messages[idx].read = true;
185
+ saveLocalMessages(messages);
186
+ return true;
187
+ }
188
+ export async function archiveMessage(id) {
189
+ if (hasSupabase()) {
190
+ try {
191
+ await supabaseRequest(`/agent_messages?id=eq.${id}`, {
192
+ method: 'PATCH',
193
+ body: JSON.stringify({ archived: true }),
194
+ });
195
+ return true;
196
+ }
197
+ catch {
198
+ // Fall through
199
+ }
200
+ }
201
+ const messages = loadLocalMessages();
202
+ const idx = messages.findIndex(m => m.id === id);
203
+ if (idx === -1)
204
+ return false;
205
+ messages[idx].archived = true;
206
+ saveLocalMessages(messages);
207
+ return true;
208
+ }
209
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/lib/storage.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;AACpC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AAqBtD,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,SAAS,iBAAiB;IACtB,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,SAAS,iBAAiB,CAAC,QAAyB;IAChD,aAAa,EAAE,CAAC;IAChB,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,SAAS,CAAC,MAAqB;IACpC,OAAO,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,mBAAmB;AACnB,KAAK,UAAU,eAAe,CAAI,IAAY,EAAE,UAAuB,EAAE;IACrE,MAAM,GAAG,GAAG,GAAG,cAAc,EAAE,WAAW,IAAI,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC9B,GAAG,OAAO;QACV,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,QAAQ,EAAE,cAAc,EAAG;YAC3B,eAAe,EAAE,UAAU,cAAc,EAAE,EAAE;YAC7C,QAAQ,EAAE,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,gBAAgB;YAChF,GAAG,OAAO,CAAC,OAAO;SACrB;KACJ,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,EAAO,CAAC;IAC5C,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,MAAc,EACd,SAAiB,EACjB,OAAe,EACf,IAAY,EACZ,OAKC;IAED,MAAM,UAAU,GAAkB;QAC9B,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM;QACN,SAAS;QACT,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,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC;IAEF,IAAI,WAAW,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,eAAe,CAAkB,iBAAiB,EAAE;gBACvE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACjB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,IAAI;oBACnC,IAAI,EAAE,UAAU,CAAC,IAAI,IAAI,IAAI;oBAC7B,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,UAAU,EAAE,UAAU,CAAC,UAAU;oBACjC,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,iBAAiB,EAAE,UAAU,CAAC,eAAe;iBAChD,CAAC;aACL,CAAC,CAAC;YACH,OAAO,SAAS,CAAC;gBACb,GAAG,UAAU;gBACb,EAAE,EAAG,MAAoC,CAAC,EAAE;aAC/C,CAAC,CAAC;QACP,CAAC;QAAC,MAAM,CAAC;YACL,wBAAwB;QAC5B,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,SAAS,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC1B,OAAe,EACf,OAAkD;IAElD,IAAI,WAAW,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC;YACD,IAAI,KAAK,GAAG,gCAAgC,OAAO,0CAA0C,CAAC;YAC9F,IAAI,OAAO,EAAE,UAAU;gBAAE,KAAK,IAAI,gBAAgB,CAAC;YACnD,IAAI,OAAO,EAAE,KAAK;gBAAE,KAAK,IAAI,UAAU,OAAO,CAAC,KAAK,EAAE,CAAC;YAEvD,MAAM,OAAO,GAAG,MAAM,eAAe,CAKjC,KAAK,CAAC,CAAC;YAEX,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACrB,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;gBACxB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,eAAe,EAAE,CAAC,CAAC,iBAAiB;gBACpC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;aACpC,CAAC,CAAC,CAAC;QACR,CAAC;QAAC,MAAM,CAAC;YACL,wBAAwB;QAC5B,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,IAAI,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5E,IAAI,OAAO,EAAE,UAAU;QAAE,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3F,IAAI,OAAO,EAAE,KAAK;QAAE,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChE,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAAU;IACvC,IAAI,WAAW,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,eAAe,CAKjC,yBAAyB,EAAE,EAAE,CAAC,CAAC;YAEnC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACrB,OAAO;oBACH,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE;oBACxB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;oBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;oBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,eAAe,EAAE,CAAC,CAAC,iBAAiB;oBACpC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;oBACpB,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;iBACpC,CAAC;YACN,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,eAAe;QACnB,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,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,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,EAAU;IACvC,IAAI,WAAW,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC;YACD,MAAM,eAAe,CAAC,yBAAyB,EAAE,EAAE,EAAE;gBACjD,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;aACvC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACL,eAAe;QACnB,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAU;IAC3C,IAAI,WAAW,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC;YACD,MAAM,eAAe,CAAC,yBAAyB,EAAE,EAAE,EAAE;gBACjD,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;aAC3C,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACL,eAAe;QACnB,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC9B,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AAChB,CAAC"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Myceliumail MCP Server
4
+ *
5
+ * Exposes Myceliumail messaging as MCP tools for Claude Desktop
6
+ * and other MCP-compatible clients.
7
+ */
8
+ export {};