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
|
+
}
|