apple-icloud-mcp 0.3.2 → 0.3.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +3 -1
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/dist/bundle.js +38 -7
- package/dist/version.js +1 -1
- package/mint.yaml +7 -0
- package/package.json +2 -2
- package/server.json +8 -2
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Unofficial Apple Music, iCloud Calendar/Contacts/Mail, Apple Maps and WeatherKit tools for Claude Code",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.3"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"displayName": "Apple iCloud",
|
|
15
15
|
"source": "./",
|
|
16
16
|
"description": "Apple Music playlists and library, iCloud Calendar, Contacts and Mail, Apple Maps, WeatherKit and iTunes search for Claude via MCP — runs anywhere, no Mac required. Unofficial; not affiliated with Apple.",
|
|
17
|
-
"version": "0.3.
|
|
17
|
+
"version": "0.3.3",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Chris Chall"
|
|
20
20
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apple-icloud",
|
|
3
3
|
"displayName": "Apple iCloud",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.3",
|
|
5
5
|
"description": "Apple Music playlists and library, iCloud Calendar, Contacts and Mail, Apple Maps, WeatherKit and iTunes search for Claude via MCP — runs anywhere, no Mac required. Unofficial; not affiliated with Apple.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Chris Chall"
|
package/README.md
CHANGED
|
@@ -363,13 +363,14 @@ An unrecognised value fails closed to `none`. `APPLE_SERVICES` (comma-separated:
|
|
|
363
363
|
Irreversible actions and anything that reaches another person ask for confirmation first: **sending mail**,
|
|
364
364
|
**deleting** an event, contact, playlist or library item, **removing or reordering** playlist tracks, and
|
|
365
365
|
**creating or changing an event with attendees** (iCloud emails them). A client that can show a prompt
|
|
366
|
-
(Claude Code) asks you directly
|
|
366
|
+
(Claude Code) asks you directly, unless `MCP_CONFIRM_ELICITATION=off`. One that cannot (claude.ai) gets a two-step flow: the first call does nothing
|
|
367
367
|
and returns a preview plus a `confirmToken`; only a repeat call with that token acts, and it is refused if the
|
|
368
368
|
target changed in between.
|
|
369
369
|
|
|
370
370
|
| Variable | Meaning |
|
|
371
371
|
|---|---|
|
|
372
372
|
| `MCP_CONFIRM_MODE` | `ask-user` (default — the model must get your OK before repeating the call), `auto` (the model may confirm after reviewing the preview), `refuse` (never). Unknown values mean `refuse`. |
|
|
373
|
+
| `MCP_CONFIRM_ELICITATION` | `on` (default) or `off`. `off` never shows a prompt, so every client gets the two-step flow under `MCP_CONFIRM_MODE`. Set it for a client that says it can prompt but never does (the gated call hangs — opencode 2.0.x). Any other value stays `on` (with a stderr warning). |
|
|
373
374
|
| `MCP_CONFIRM_TTL_SECONDS` | How long a token is valid (default 600). |
|
|
374
375
|
| `MCP_CONFIRM_SECRET` | Token signing key; random per process by default (on mcp-host, the host's per-child `MCP_HOST_CONFIRM_SECRET` beside an absolute `MCP_DATA_DIR` is used instead). Set it so a token survives a restart; spent tokens are recorded on disk (`confirm-spent.json`), so none can be replayed (unless `APPLE_STATE_CACHE=false` or the directory is unwritable — a warning says so). |
|
|
375
376
|
|
|
@@ -430,6 +431,7 @@ All optional; each service activates when its credentials are present. Values th
|
|
|
430
431
|
| Variable | Meaning |
|
|
431
432
|
|---|---|
|
|
432
433
|
| `MCP_CONFIRM_MODE` | How confirm-gated writes (send mail, deletes, removing tracks, invitations) behave on a client with no prompt, like claude.ai: "ask-user" (default: preview + confirmToken, the model must get your OK), "auto", or "refuse". Unknown values mean refuse. |
|
|
434
|
+
| `MCP_CONFIRM_ELICITATION` | "off" never shows a confirmation prompt, so every client gets the MCP_CONFIRM_MODE flow. Set it for a client that says it can prompt but never does (the gated call hangs, e.g. opencode 2.0.x). Any other value stays "on" (with a stderr warning). |
|
|
433
435
|
| `MCP_CONFIRM_TTL_SECONDS` | Lifetime of a confirmToken in seconds (default 600). |
|
|
434
436
|
| `MCP_CONFIRM_SECRET` 🔒 | Signing key for confirmTokens. Random per process by default; set it so a token issued just before a restart or redeploy still works (spent tokens are recorded on disk, so none can be replayed). |
|
|
435
437
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -22,7 +22,7 @@ MPL-2.0 is a file-level license: it covers ical.js's own files and does not exte
|
|
|
22
22
|
|
|
23
23
|
| Package | Version | License | Source |
|
|
24
24
|
|---|---|---|---|
|
|
25
|
-
| @chrischall/mcp-utils | 2.
|
|
25
|
+
| @chrischall/mcp-utils | 2.15.0 | MIT | https://github.com/chrischall/mcp-utils |
|
|
26
26
|
| @esbuild/aix-ppc64 | 0.28.2 | MIT | — |
|
|
27
27
|
| @esbuild/android-arm | 0.28.2 | MIT | — |
|
|
28
28
|
| @esbuild/android-arm64 | 0.28.2 | MIT | — |
|
|
@@ -113,7 +113,7 @@ MPL-2.0 is a file-level license: it covers ical.js's own files and does not exte
|
|
|
113
113
|
|
|
114
114
|
## License and notice texts
|
|
115
115
|
|
|
116
|
-
### @chrischall/mcp-utils@2.
|
|
116
|
+
### @chrischall/mcp-utils@2.15.0
|
|
117
117
|
|
|
118
118
|
- License: MIT
|
|
119
119
|
- Source: https://github.com/chrischall/mcp-utils
|
package/dist/bundle.js
CHANGED
|
@@ -35629,6 +35629,15 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
35629
35629
|
};
|
|
35630
35630
|
const response = inputResponse(ctx.mcpReq.inputResponses, requestKey);
|
|
35631
35631
|
const accepted = acceptedContent(ctx.mcpReq.inputResponses, requestKey, confirmationSchema);
|
|
35632
|
+
if (options.elicitation === false) {
|
|
35633
|
+
return textResult({
|
|
35634
|
+
confirmed: false,
|
|
35635
|
+
dispatched: false,
|
|
35636
|
+
action: options.action,
|
|
35637
|
+
reason: "confirmation-unsupported",
|
|
35638
|
+
note: options.unsupportedNote ? `${DISABLED_NOTE}. ${options.unsupportedNote}` : `${DISABLED_NOTE}.`
|
|
35639
|
+
});
|
|
35640
|
+
}
|
|
35632
35641
|
if (response.kind === "missing") {
|
|
35633
35642
|
if (callerAcceptsFormElicitation(ctx) === false) {
|
|
35634
35643
|
return textResult({
|
|
@@ -35659,7 +35668,7 @@ ${JSON.stringify(preview, null, 2)}`,
|
|
|
35659
35668
|
note: "Nothing was changed because the confirmation was declined, cancelled, or left unchecked."
|
|
35660
35669
|
});
|
|
35661
35670
|
}
|
|
35662
|
-
var DEFAULT_REQUEST_KEY, DEFAULT_CONFIRMATION_LABEL, UNSUPPORTED_NOTE, STATE_PREFIX;
|
|
35671
|
+
var DEFAULT_REQUEST_KEY, DEFAULT_CONFIRMATION_LABEL, UNSUPPORTED_NOTE, DISABLED_NOTE, STATE_PREFIX;
|
|
35663
35672
|
var init_confirmation = __esm({
|
|
35664
35673
|
"node_modules/@chrischall/mcp-utils/dist/server/confirmation.js"() {
|
|
35665
35674
|
init_dist();
|
|
@@ -35670,6 +35679,7 @@ var init_confirmation = __esm({
|
|
|
35670
35679
|
DEFAULT_REQUEST_KEY = "confirmation";
|
|
35671
35680
|
DEFAULT_CONFIRMATION_LABEL = "Confirm this action should proceed.";
|
|
35672
35681
|
UNSUPPORTED_NOTE = "Nothing was done because this client cannot show a confirmation prompt (it declares no MCP elicitation capability), and this action is never taken without one";
|
|
35682
|
+
DISABLED_NOTE = "Nothing was done because confirmation prompts are turned off for this server, and this action is never taken without one";
|
|
35673
35683
|
STATE_PREFIX = "mcpu.confirm.v1.";
|
|
35674
35684
|
}
|
|
35675
35685
|
});
|
|
@@ -35823,7 +35833,7 @@ async function tokenConfirmation(action, fb) {
|
|
|
35823
35833
|
}
|
|
35824
35834
|
async function requireConfirmationWithFallback(ctx, options) {
|
|
35825
35835
|
const { tokenFallback, ...confirmation } = options;
|
|
35826
|
-
if (tokenFallback && callerAcceptsFormElicitation(ctx) === false) {
|
|
35836
|
+
if (tokenFallback && (options.elicitation === false || callerAcceptsFormElicitation(ctx) === false)) {
|
|
35827
35837
|
return tokenConfirmation(options.action, tokenFallback);
|
|
35828
35838
|
}
|
|
35829
35839
|
return requireConfirmation(ctx, confirmation);
|
|
@@ -36030,6 +36040,20 @@ function readConfirmMode(env = process.env) {
|
|
|
36030
36040
|
}
|
|
36031
36041
|
return "refuse";
|
|
36032
36042
|
}
|
|
36043
|
+
function readConfirmElicitation(env = process.env) {
|
|
36044
|
+
const raw = readEnvVar("MCP_CONFIRM_ELICITATION", { env })?.trim().toLowerCase();
|
|
36045
|
+
if (!raw || raw === "on")
|
|
36046
|
+
return "on";
|
|
36047
|
+
if (raw === "off")
|
|
36048
|
+
return "off";
|
|
36049
|
+
const key = `elicitation:${raw}`;
|
|
36050
|
+
if (!warned.has(key)) {
|
|
36051
|
+
warned.add(key);
|
|
36052
|
+
process.stderr.write(`MCP_CONFIRM_ELICITATION="${raw}" is not one of on, off; treating it as on.
|
|
36053
|
+
`);
|
|
36054
|
+
}
|
|
36055
|
+
return "on";
|
|
36056
|
+
}
|
|
36033
36057
|
function readConfirmTtl(env) {
|
|
36034
36058
|
const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
|
|
36035
36059
|
if (!raw)
|
|
@@ -36085,10 +36109,13 @@ function confirmationFromEnv(options) {
|
|
|
36085
36109
|
const spent = callerSpent ?? spentTokenStoreFromEnv(env);
|
|
36086
36110
|
const mode = readConfirmMode(env);
|
|
36087
36111
|
const ttlSeconds = readConfirmTtl(env);
|
|
36112
|
+
const elicitationOff = readConfirmElicitation(env) === "off";
|
|
36088
36113
|
const bound = args === void 0 ? void 0 : boundArgs(args);
|
|
36089
|
-
const
|
|
36114
|
+
const bindingAdded = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
|
|
36115
|
+
const confirmation = elicitationOff ? { ...bindingAdded, elicitation: false } : bindingAdded;
|
|
36090
36116
|
if (mode === "refuse" || ttlSeconds === void 0) {
|
|
36091
|
-
const
|
|
36117
|
+
const reason = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
|
|
36118
|
+
const hint = elicitationOff ? `${ELICITATION_OFF_HINT} ${reason}` : reason;
|
|
36092
36119
|
return {
|
|
36093
36120
|
...confirmation,
|
|
36094
36121
|
unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
|
|
@@ -36114,7 +36141,7 @@ function confirmationFromEnv(options) {
|
|
|
36114
36141
|
}
|
|
36115
36142
|
};
|
|
36116
36143
|
}
|
|
36117
|
-
var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, fileStores, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT, BAD_TTL_HINT;
|
|
36144
|
+
var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, fileStores, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT, ELICITATION_OFF_HINT, BAD_TTL_HINT;
|
|
36118
36145
|
var init_confirm_env = __esm({
|
|
36119
36146
|
"node_modules/@chrischall/mcp-utils/dist/server/confirm-env.js"() {
|
|
36120
36147
|
init_config();
|
|
@@ -36126,6 +36153,7 @@ var init_confirm_env = __esm({
|
|
|
36126
36153
|
fileStores = /* @__PURE__ */ new Map();
|
|
36127
36154
|
CONFIRM_TOKEN_AUTO_INSTRUCTION = "Nothing has been done yet. Review this preview; if it is what was intended, call again with the same arguments plus confirmToken. (This server runs with MCP_CONFIRM_MODE=auto, so the user's approval in chat is not required.)";
|
|
36128
36155
|
REFUSE_HINT = "Set MCP_CONFIRM_MODE=ask-user on the server to allow two-step confirmation instead.";
|
|
36156
|
+
ELICITATION_OFF_HINT = "MCP_CONFIRM_ELICITATION=off on the server turns confirmation prompts off.";
|
|
36129
36157
|
BAD_TTL_HINT = "MCP_CONFIRM_TTL_SECONDS on the server is not a positive whole number of seconds; fix it to allow two-step confirmation.";
|
|
36130
36158
|
}
|
|
36131
36159
|
});
|
|
@@ -36222,7 +36250,10 @@ function surfaceToolHints(server) {
|
|
|
36222
36250
|
));
|
|
36223
36251
|
}
|
|
36224
36252
|
async function createMcpServer(opts) {
|
|
36225
|
-
const server = new McpServer({ name: opts.name, version: opts.version }, {
|
|
36253
|
+
const server = new McpServer({ name: opts.name, version: opts.version }, {
|
|
36254
|
+
supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS],
|
|
36255
|
+
...opts.maxToolInputElements !== void 0 ? { maxToolInputElements: opts.maxToolInputElements } : {}
|
|
36256
|
+
});
|
|
36226
36257
|
if (opts.surfaceHints !== false)
|
|
36227
36258
|
surfaceToolHints(server);
|
|
36228
36259
|
if (opts.banner !== void 0) {
|
|
@@ -36772,7 +36803,7 @@ var VERSION;
|
|
|
36772
36803
|
var init_version = __esm({
|
|
36773
36804
|
"src/version.ts"() {
|
|
36774
36805
|
"use strict";
|
|
36775
|
-
VERSION = "0.3.
|
|
36806
|
+
VERSION = "0.3.3";
|
|
36776
36807
|
}
|
|
36777
36808
|
});
|
|
36778
36809
|
|
package/dist/version.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// The server's self-reported version. release-please bumps this line (it is
|
|
2
2
|
// registered in release-please-config.json `extra-files`); tests/version-sync
|
|
3
3
|
// fails CI if it ever drifts from package.json.
|
|
4
|
-
export const VERSION = '0.3.
|
|
4
|
+
export const VERSION = '0.3.3'; // x-release-please-version
|
package/mint.yaml
CHANGED
|
@@ -59,6 +59,13 @@ env:
|
|
|
59
59
|
invitations) behave on a client with no prompt, like claude.ai: "ask-user"
|
|
60
60
|
(default: preview + confirmToken, the model must get your OK), "auto", or
|
|
61
61
|
"refuse". Unknown values mean refuse.
|
|
62
|
+
- name: MCP_CONFIRM_ELICITATION
|
|
63
|
+
required: false
|
|
64
|
+
help: >-
|
|
65
|
+
"off" never shows a confirmation prompt, so every client gets the
|
|
66
|
+
MCP_CONFIRM_MODE flow. Set it for a client that says it can prompt but
|
|
67
|
+
never does (the gated call hangs, e.g. opencode 2.0.x). Any other value
|
|
68
|
+
stays "on" (with a stderr warning).
|
|
62
69
|
- name: MCP_CONFIRM_SECRET
|
|
63
70
|
secret: true
|
|
64
71
|
required: false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apple-icloud-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"mcpName": "io.github.chrischall/apple-icloud-mcp",
|
|
6
6
|
"description": "Unofficial MCP server for Apple's services — Apple Music playlists and library, iCloud Calendar, Contacts and Mail, Apple Maps, WeatherKit and iTunes search — that runs anywhere, no Mac needed. Not affiliated with Apple. Developed and maintained by AI (Claude Code)",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@chrischall/mcp-utils": "^2.
|
|
57
|
+
"@chrischall/mcp-utils": "^2.15.0",
|
|
58
58
|
"@modelcontextprotocol/server": "^2.3.0",
|
|
59
59
|
"@xmldom/xmldom": "^0.9.12",
|
|
60
60
|
"dotenv": "^18.0.5",
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/chrischall/apple-icloud-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.3",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "apple-icloud-mcp",
|
|
14
|
-
"version": "0.3.
|
|
14
|
+
"version": "0.3.3",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -193,6 +193,12 @@
|
|
|
193
193
|
"isRequired": false,
|
|
194
194
|
"format": "string"
|
|
195
195
|
},
|
|
196
|
+
{
|
|
197
|
+
"name": "MCP_CONFIRM_ELICITATION",
|
|
198
|
+
"description": "\"off\" never shows a confirmation prompt, so every client gets the MCP_CONFIRM_MODE flow. Set it for a client that says it can prompt but never does (the gated call hangs, e.g. opencode 2.0.x). Any other value stays \"on\" (with a stderr warning).",
|
|
199
|
+
"isRequired": false,
|
|
200
|
+
"format": "string"
|
|
201
|
+
},
|
|
196
202
|
{
|
|
197
203
|
"name": "MCP_CONFIRM_TTL_SECONDS",
|
|
198
204
|
"description": "Lifetime of a confirmToken in seconds (default 600).",
|