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.
@@ -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.2"
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.2",
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.2",
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. One that cannot (claude.ai) gets a two-step flow: the first call does nothing
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
 
@@ -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.13.1 | MIT | https://github.com/chrischall/mcp-utils |
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.13.1
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 confirmation = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
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 hint = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
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 }, { supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS] });
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.2";
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.2'; // x-release-please-version
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.2",
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.13.1",
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.2",
9
+ "version": "0.3.3",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "apple-icloud-mcp",
14
- "version": "0.3.2",
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).",