apple-mail-mcp 2.1.0 → 2.1.1

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 CHANGED
@@ -348,6 +348,29 @@ config. Gmail label semantics: common names (`All Mail`, `Sent`, `Trash`,
348
348
  > (e.g. `iCloud`), and use an **app-specific password** (from appleid.apple.com)
349
349
  > stored in the Keychain.
350
350
 
351
+ ##### Configuration file (when the host strips `env`)
352
+
353
+ Some host apps (e.g. Claude Desktop) launch the MCP server with a scrubbed
354
+ environment and ignore the `env` block in their server config, so there's no way
355
+ to pass `APPLE_MAIL_MCP_*` settings through it. In that case, put them in a JSON
356
+ file the host doesn't manage — `APPLE_MAIL_MCP_CONFIG_FILE`, or by default
357
+ `~/Library/Application Support/apple-mail-mcp/config.json`:
358
+
359
+ ```json
360
+ {
361
+ "APPLE_MAIL_MCP_IMAP_USER": "you@gmail.com",
362
+ "APPLE_MAIL_MCP_IMAP_HOST": "imap.gmail.com",
363
+ "APPLE_MAIL_MCP_IMAP_KEYCHAIN_SERVICE": "imap.gmail.com",
364
+ "APPLE_MAIL_MCP_IMAP_KEYCHAIN_ACCOUNT": "you@gmail.com",
365
+ "APPLE_MAIL_MCP_IMAP_IDLE": "1"
366
+ }
367
+ ```
368
+
369
+ The server reads it at startup and merges values into the environment **without
370
+ overriding** anything already set there (so an explicit `env` still wins). Store
371
+ only non-secret config here — **passwords belong in the Keychain**, never in this
372
+ file.
373
+
351
374
  ##### Push notifications (IMAP IDLE) — opt-in
352
375
 
353
376
  When `APPLE_MAIL_MCP_IMAP_IDLE=1`, the server opens a dedicated, long-lived
package/build/index.js CHANGED
@@ -34,6 +34,10 @@ import { runDoctor, formatDoctorReport } from "./tools/doctor.js";
34
34
  import { registerResourcesAndPrompts } from "./tools/resourcesAndPrompts.js";
35
35
  import { normalizeSubject, subjectFromGetMessage } from "./tools/thread.js";
36
36
  import { ImapIdleWatcher } from "./services/imapIdle.js";
37
+ import { loadFileConfig } from "./services/fileConfig.js";
38
+ // Load file-based config FIRST (2.1.1) — before anything reads APPLE_MAIL_MCP_*.
39
+ // Lets users configure the server when the host app strips the MCP env block.
40
+ loadFileConfig();
37
41
  // =============================================================================
38
42
  // Shared Validation Schemas
39
43
  // =============================================================================
@@ -0,0 +1,7 @@
1
+ export declare function fileConfigPath(env?: NodeJS.ProcessEnv): string;
2
+ /**
3
+ * Merge a JSON config file's string values into `env` for keys not already set.
4
+ * Returns the list of keys actually applied. Tolerates a missing/corrupt file.
5
+ */
6
+ export declare function loadFileConfig(env?: NodeJS.ProcessEnv, path?: string): string[];
7
+ //# sourceMappingURL=fileConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileConfig.d.ts","sourceRoot":"","sources":["../../src/services/fileConfig.ts"],"names":[],"mappings":"AAqBA,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAI3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,MAA4B,GACjC,MAAM,EAAE,CAiBV"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * File-based configuration loader (2.1.1).
3
+ *
4
+ * Some host apps (e.g. Claude Desktop) spawn the MCP server with a scrubbed
5
+ * environment and ignore/strip the `env` block in their server config, so
6
+ * there's no way to pass `APPLE_MAIL_MCP_*` settings in. This loads them from a
7
+ * JSON file the host doesn't manage, merging into `process.env` WITHOUT
8
+ * overriding anything already set (so an explicit env still wins).
9
+ *
10
+ * The file holds only non-secret config — account/host/Keychain-service names
11
+ * and flags. Passwords are NEVER stored here; they stay in the macOS Keychain.
12
+ *
13
+ * Path: `APPLE_MAIL_MCP_CONFIG_FILE`, else
14
+ * `~/Library/Application Support/apple-mail-mcp/config.json`.
15
+ *
16
+ * @module services/fileConfig
17
+ */
18
+ import { existsSync, readFileSync } from "fs";
19
+ import { join } from "path";
20
+ import { homedir } from "os";
21
+ export function fileConfigPath(env = process.env) {
22
+ const override = env.APPLE_MAIL_MCP_CONFIG_FILE;
23
+ if (override && override.trim())
24
+ return override.trim();
25
+ return join(homedir(), "Library", "Application Support", "apple-mail-mcp", "config.json");
26
+ }
27
+ /**
28
+ * Merge a JSON config file's string values into `env` for keys not already set.
29
+ * Returns the list of keys actually applied. Tolerates a missing/corrupt file.
30
+ */
31
+ export function loadFileConfig(env = process.env, path = fileConfigPath(env)) {
32
+ const applied = [];
33
+ try {
34
+ if (!existsSync(path))
35
+ return applied;
36
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
37
+ if (!parsed || typeof parsed !== "object")
38
+ return applied;
39
+ for (const [k, v] of Object.entries(parsed)) {
40
+ if (typeof v !== "string")
41
+ continue;
42
+ if (env[k] === undefined || env[k] === "") {
43
+ env[k] = v;
44
+ applied.push(k);
45
+ }
46
+ }
47
+ }
48
+ catch (e) {
49
+ console.error(`Failed to load apple-mail-mcp config file ${path}: ${String(e)}`);
50
+ }
51
+ return applied;
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude",
5
5
  "type": "module",
6
6
  "main": "build/index.js",