@mgcrea/mcp-apple-maps 1.24.0 → 1.25.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 CHANGED
@@ -36,14 +36,26 @@ client that has not opted in is never told they exist.
36
36
  | `apple_maps_add_favorite` | save a place as a favourite, seeding it through `maps://` |
37
37
  | `apple_maps_remove_favorite` | drop a favourite row |
38
38
 
39
+ Three more press controls on a place card through Accessibility rather than writing SQL, and are
40
+ registered only when Cupertino.app hosts this server: the grant belongs to the app, so a package
41
+ run from npm has no way to reach them and is never told they exist.
42
+
43
+ | Tool | What |
44
+ | ------------------------------- | ---------------------------------------------------------- |
45
+ | `apple_maps_save_place` | add a place to the Places library (not the same as Pinned) |
46
+ | `apple_maps_remove_saved_place` | remove a place from the Places library |
47
+ | `apple_maps_add_place_to_guide` | file a place in an existing Guide; Maps cannot confirm it |
48
+
49
+ Each opens Maps, brings its window forward and leaves the place in your Recents.
50
+
39
51
  ## What it does not do
40
52
 
41
53
  It reads what is **saved on this Mac**. It does not search Apple's map of the world, geocode an
42
54
  address, give directions or compute a travel time. Those are network calls to Apple's services,
43
55
  not data on your disk.
44
56
 
45
- It writes only **favourites**, and only with `APPLE_MAPS_ALLOW_WRITES` set. Everything else here is
46
- read-only. The store is mirrored to iCloud by `NSPersistentCloudKitContainer`, so a write is an edit
57
+ It writes only with `APPLE_MAPS_ALLOW_WRITES` set: favourites through the store, and the Places
58
+ library and Guide membership through Maps' own interface. Everything else here is read-only. The store is mirrored to iCloud by `NSPersistentCloudKitContainer`, so a write is an edit
47
59
  to one replica of a synchronising object graph underneath a running app — a malformed row reaches
48
60
  every device on the account. That is why a place record is never fabricated: adding a favourite opens
49
61
  `maps://` so that Maps itself mints the record, and only then is it copied. **The place is left in
@@ -61,15 +73,20 @@ If a listing comes back empty, that means you have saved nothing of that kind. R
61
73
 
62
74
  ## Configuration
63
75
 
64
- | Variable | Default | What |
65
- | --------------------------- | ---------- | ------------------------------------------------------ |
66
- | `APPLE_MAPS_STORE` | discovered | explicit store path, for tests and forensic copies |
67
- | `APPLE_MAPS_INDEX_MODE` | `auto` | `auto` / `ro` / `immutable` / `off` |
68
- | `APPLE_MAPS_MAX_RESULTS` | 50 | default result ceiling |
69
- | `APPLE_MAPS_EXPOSE_PROMPTS` | on | register the prompt and `cupertino://maps/*` resources |
70
- | `APPLE_MAPS_DEBUG` | off | verbose logging on stderr |
76
+ | Variable | Default | What |
77
+ | ---------------------------- | ---------- | --------------------------------------------------------- |
78
+ | `APPLE_MAPS_STORE` | discovered | explicit store path, for tests and forensic copies |
79
+ | `APPLE_MAPS_INDEX_MODE` | `auto` | `auto` / `ro` / `immutable` / `off` |
80
+ | `APPLE_MAPS_MAX_RESULTS` | 50 | default result ceiling |
81
+ | `APPLE_MAPS_SEED_TIMEOUT_MS` | 30000 | how long `add_favorite` waits for Maps to resolve a place |
82
+ | `APPLE_MAPS_EXPOSE_PROMPTS` | on | register the prompt and `cupertino://maps/*` resources |
83
+ | `APPLE_MAPS_DEBUG` | off | verbose logging on stderr |
71
84
 
72
- `APPLE_MAPS_ALLOW_WRITES` is accepted and ignored: there is no mutating tool for it to gate.
85
+ `APPLE_MAPS_ALLOW_WRITES` (off) registers the tools under [What it writes](#what-it-writes).
73
86
 
74
87
  See [docs/maps.md](../../docs/maps.md) for the phase-0 measurements, including the three separate
75
88
  occasions on which this store was declared not to exist.
89
+
90
+ ## Licence
91
+
92
+ [MIT](LICENSE).
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { C as MAPS_SURFACE, N as BUILD_INFO, a as loadConfig, r as createServer } from "./server-CVGfFevI.js";
2
+ import { C as MAPS_SURFACE, N as BUILD_INFO, a as loadConfig, r as createServer } from "./server-CO_d1_6b.js";
3
3
  import { runStdioServer } from "@mgcrea/mcp-apple-core";
4
4
  //#region src/cli.ts
5
5
  const LOG_PREFIX = "apple-maps-mcp";
@@ -18,7 +18,7 @@ runStdioServer({
18
18
  const rows = (k) => caps?.entities?.[k]?.rows ?? 0;
19
19
  return {
20
20
  server,
21
- banner: `read-only, store=${status.store.opened ? status.store.mode ?? "open" : "UNREADABLE"}, favorites=${rows("favorites")}, collections=${rows("collections")}, recents=${rows("history")}, index=${config.indexMode}`
21
+ banner: `writes=${config.allowWrites ? "ENABLED" : "disabled"}, store=${status.store.opened ? status.store.mode ?? "open" : "UNREADABLE"}, favorites=${rows("favorites")}, collections=${rows("collections")}, recents=${rows("history")}, index=${config.indexMode}`
22
22
  };
23
23
  }
24
24
  }).catch((err) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { runStdioServer } from \"@mgcrea/mcp-apple-core\";\n\nimport { BUILD_INFO } from \"./build-info.js\";\nimport { MAPS_SURFACE } from \"./client/errors.js\";\nimport { loadConfig } from \"./config.js\";\nimport { createServer } from \"./server.js\";\n\nconst LOG_PREFIX = \"apple-maps-mcp\";\n\nrunStdioServer({\n build: BUILD_INFO,\n surface: MAPS_SURFACE,\n logPrefix: LOG_PREFIX,\n start: async (logger) => {\n const config = loadConfig();\n const { server, client } = createServer({ config, logger });\n const status = client.status();\n const caps = status.capabilities as { entities?: Record<string, { rows?: number }> } | null;\n const rows = (k: string): number => caps?.entities?.[k]?.rows ?? 0;\n return {\n server,\n // No writes= line: this surface has no mutating tool, and printing a flag\n // that gates nothing would imply one exists. The counts are named because\n // \"store=open\" alone cannot distinguish a working server from one pointed\n // at an empty replica — which is exactly what the device-local cache is.\n banner:\n `read-only, ` +\n `store=${status.store.opened ? (status.store.mode ?? \"open\") : \"UNREADABLE\"}, ` +\n `favorites=${rows(\"favorites\")}, ` +\n `collections=${rows(\"collections\")}, ` +\n `recents=${rows(\"history\")}, ` +\n `index=${config.indexMode}`,\n };\n },\n}).catch((err: unknown) => {\n console.error(`[${LOG_PREFIX}] fatal:`, err);\n process.exit(1);\n});\n"],"mappings":";;;;AAQA,MAAM,aAAa;AAEnB,eAAe;CACb,OAAO;CACP,SAAS;CACT,WAAW;CACX,OAAO,OAAO,WAAW;EACvB,MAAM,SAAS,WAAW;EAC1B,MAAM,EAAE,QAAQ,WAAW,aAAa;GAAE;GAAQ;EAAO,CAAC;EAC1D,MAAM,SAAS,OAAO,OAAO;EAC7B,MAAM,OAAO,OAAO;EACpB,MAAM,QAAQ,MAAsB,MAAM,WAAW,EAAE,EAAE,QAAQ;EACjE,OAAO;GACL;GAKA,QACE,oBACS,OAAO,MAAM,SAAU,OAAO,MAAM,QAAQ,SAAU,aAAa,cAC/D,KAAK,WAAW,EAAE,gBAChB,KAAK,aAAa,EAAE,YACxB,KAAK,SAAS,EAAE,UAClB,OAAO;EACpB;CACF;AACF,CAAC,CAAC,CAAC,OAAO,QAAiB;CACzB,QAAQ,MAAM,IAAI,WAAW,WAAW,GAAG;CAC3C,QAAQ,KAAK,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { runStdioServer } from \"@mgcrea/mcp-apple-core\";\n\nimport { BUILD_INFO } from \"./build-info.js\";\nimport { MAPS_SURFACE } from \"./client/errors.js\";\nimport { loadConfig } from \"./config.js\";\nimport { createServer } from \"./server.js\";\n\nconst LOG_PREFIX = \"apple-maps-mcp\";\n\nrunStdioServer({\n build: BUILD_INFO,\n surface: MAPS_SURFACE,\n logPrefix: LOG_PREFIX,\n start: async (logger) => {\n const config = loadConfig();\n const { server, client } = createServer({ config, logger });\n const status = client.status();\n const caps = status.capabilities as { entities?: Record<string, { rows?: number }> } | null;\n const rows = (k: string): number => caps?.entities?.[k]?.rows ?? 0;\n return {\n server,\n // The counts are named because \"store=open\" alone cannot distinguish a\n // working server from one pointed at an empty replica — which is exactly\n // what the device-local cache is.\n banner:\n `writes=${config.allowWrites ? \"ENABLED\" : \"disabled\"}, ` +\n `store=${status.store.opened ? (status.store.mode ?? \"open\") : \"UNREADABLE\"}, ` +\n `favorites=${rows(\"favorites\")}, ` +\n `collections=${rows(\"collections\")}, ` +\n `recents=${rows(\"history\")}, ` +\n `index=${config.indexMode}`,\n };\n },\n}).catch((err: unknown) => {\n console.error(`[${LOG_PREFIX}] fatal:`, err);\n process.exit(1);\n});\n"],"mappings":";;;;AAQA,MAAM,aAAa;AAEnB,eAAe;CACb,OAAO;CACP,SAAS;CACT,WAAW;CACX,OAAO,OAAO,WAAW;EACvB,MAAM,SAAS,WAAW;EAC1B,MAAM,EAAE,QAAQ,WAAW,aAAa;GAAE;GAAQ;EAAO,CAAC;EAC1D,MAAM,SAAS,OAAO,OAAO;EAC7B,MAAM,OAAO,OAAO;EACpB,MAAM,QAAQ,MAAsB,MAAM,WAAW,EAAE,EAAE,QAAQ;EACjE,OAAO;GACL;GAIA,QACE,UAAU,OAAO,cAAc,YAAY,WAAW,UAC7C,OAAO,MAAM,SAAU,OAAO,MAAM,QAAQ,SAAU,aAAa,cAC/D,KAAK,WAAW,EAAE,gBAChB,KAAK,aAAa,EAAE,YACxB,KAAK,SAAS,EAAE,UAClB,OAAO;EACpB;CACF;AACF,CAAC,CAAC,CAAC,OAAO,QAAiB;CACzB,QAAQ,MAAM,IAAI,WAAW,WAAW,GAAG;CAC3C,QAAQ,KAAK,CAAC;AAChB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AppleAutomationError, AppleAutomationError as AppleMapsError, BuildInfo, CORE_DATA_EPOCH_OFFSET, FileFacts, IndexUnavailableError, InterferenceWatch, Logger, ReadOnlyMode, SchemaDriftError, StoreFacts, SurfaceContext } from "@mgcrea/mcp-apple-core";
1
+ import { AppleAutomationError, AppleAutomationError as AppleMapsError, BuildInfo, CORE_DATA_EPOCH_OFFSET, Epoch, FileFacts, IndexUnavailableError, InterferenceWatch, Logger, ReadOnlyMode, SchemaDriftError, StoreFacts, SurfaceContext } from "@mgcrea/mcp-apple-core";
2
2
  import { DatabaseSync } from "node:sqlite";
3
3
  import { z } from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -6,20 +6,6 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
6
  declare const BUILD_INFO: BuildInfo;
7
7
  //#endregion
8
8
  //#region src/client/dates.d.ts
9
- /**
10
- * How this store's timestamps map onto real time.
11
- *
12
- * `confident` is the field that matters. `detectEpoch` always returns an offset
13
- * — it falls back to unix when nothing fits — so the offset alone cannot
14
- * distinguish "measured as unix" from "gave up and assumed unix". Rendering the
15
- * second as though it were the first is the failure this module exists to
16
- * prevent, so the two are kept apart.
17
- */
18
- type Epoch = {
19
- offset: number;
20
- reason: string;
21
- confident: boolean;
22
- };
23
9
  declare const resolveEpoch: (maxTimestamp: number | null, now?: number) => Epoch;
24
10
  /** The expectation docs/maps.md carries, used only where no store is open. */
25
11
  declare const APPLE_SECONDS: Epoch;
@@ -120,7 +106,6 @@ declare const ConfigSchema: z.ZodObject<{
120
106
  allowWrites: z.ZodDefault<z.ZodBoolean>;
121
107
  exposePrompts: z.ZodDefault<z.ZodBoolean>;
122
108
  lazyTools: z.ZodDefault<z.ZodBoolean>;
123
- debug: z.ZodDefault<z.ZodBoolean>;
124
109
  osascriptPath: z.ZodDefault<z.ZodString>;
125
110
  osascriptTimeoutMs: z.ZodDefault<z.ZodNumber>;
126
111
  maxResults: z.ZodDefault<z.ZodNumber>;
@@ -131,6 +116,7 @@ declare const ConfigSchema: z.ZodObject<{
131
116
  off: "off";
132
117
  ro: "ro";
133
118
  }>>;
119
+ seedTimeoutMs: z.ZodDefault<z.ZodNumber>;
134
120
  }, z.core.$strict>;
135
121
  type Config = z.infer<typeof ConfigSchema>;
136
122
  declare const loadConfig: (env?: NodeJS.ProcessEnv) => Config;
@@ -488,7 +474,7 @@ declare const decodeCollectionRef: (raw: string) => EntityKey;
488
474
  //#endregion
489
475
  //#region src/client/write.d.ts
490
476
  /** Injected so tests never launch an application. */
491
- type OpenUrl = (url: string) => void;
477
+ type OpenUrl = (url: string) => void | Promise<void>;
492
478
  type AddFavoriteInput = {
493
479
  /** What to search for. A name; a bare coordinate does NOT open a place card. */
494
480
  query: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/client/dates.ts","../src/client/errors.ts","../src/client/locate.ts","../src/config.ts","../src/client/ax.ts","../src/client/store.ts","../src/client/ref.ts","../src/client/write.ts","../src/client/maps.ts","../src/server.ts","../src/tools/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/client/dates.ts","../src/client/errors.ts","../src/client/locate.ts","../src/config.ts","../src/client/ax.ts","../src/client/store.ts","../src/client/ref.ts","../src/client/write.ts","../src/client/maps.ts","../src/server.ts","../src/tools/index.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { A as fromStoreTime, C as MAPS_SURFACE, D as UndatableStoreError, E as SchemaDriftError, M as resolveEpoch, N as BUILD_INFO, O as APPLE_SECONDS, S as MAPS_BUNDLE_ID, T as PlaceNotFoundError, _ as defaultDirectory, a as loadConfig, b as AppleMapsError, c as introspect, d as InvalidMapsRefError, f as PLACE_REF_VERSION, g as encodePlaceRef, h as encodeCollectionRef, i as registerTools, j as renderInstant, k as CORE_DATA_EPOCH_OFFSET, l as openStore, m as decodePlaceRef, n as SERVER_VERSION, o as AppleMapsClient, p as decodeCollectionRef, r as createServer, s as MapsStore, t as SERVER_NAME, u as COLLECTION_REF_VERSION, v as defaultStorePath, w as MapsStoreUnavailableError, x as IndexUnavailableError, y as locateStore } from "./server-CVGfFevI.js";
1
+ import { A as fromStoreTime, C as MAPS_SURFACE, D as UndatableStoreError, E as SchemaDriftError, M as resolveEpoch, N as BUILD_INFO, O as APPLE_SECONDS, S as MAPS_BUNDLE_ID, T as PlaceNotFoundError, _ as defaultDirectory, a as loadConfig, b as AppleMapsError, c as introspect, d as InvalidMapsRefError, f as PLACE_REF_VERSION, g as encodePlaceRef, h as encodeCollectionRef, i as registerTools, j as renderInstant, k as CORE_DATA_EPOCH_OFFSET, l as openStore, m as decodePlaceRef, n as SERVER_VERSION, o as AppleMapsClient, p as decodeCollectionRef, r as createServer, s as MapsStore, t as SERVER_NAME, u as COLLECTION_REF_VERSION, v as defaultStorePath, w as MapsStoreUnavailableError, x as IndexUnavailableError, y as locateStore } from "./server-CO_d1_6b.js";
2
2
  export { APPLE_SECONDS, AppleMapsClient, AppleMapsError, BUILD_INFO, COLLECTION_REF_VERSION, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, InvalidMapsRefError, MAPS_BUNDLE_ID, MAPS_SURFACE, MapsStore, MapsStoreUnavailableError, PLACE_REF_VERSION, PlaceNotFoundError, SERVER_NAME, SERVER_VERSION, SchemaDriftError, UndatableStoreError, createServer, decodeCollectionRef, decodePlaceRef, defaultDirectory, defaultStorePath, encodeCollectionRef, encodePlaceRef, fromStoreTime, introspect, loadConfig, locateStore, openStore, registerTools, renderInstant, resolveEpoch };
@@ -1,10 +1,11 @@
1
- import { AppleAutomationError, AppleAutomationError as AppleMapsError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, SchemaDriftError, SchemaDriftError as SchemaDriftError$1, columnsOf, compact, describeStore, detectEpoch, escapeLike, fail, fingerprintSchema, inspectFile, interferenceNote, limitArg, ok, openAxChannel, openReadOnly, parseBool, parseConfig, parseIntOpt, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, resolveLimit, trimmed, watchInterference, withLazyTools, wrap, wrapResult } from "@mgcrea/mcp-apple-core";
1
+ import { AppleAutomationError, AppleAutomationError as AppleMapsError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, SchemaDriftError, SchemaDriftError as SchemaDriftError$1, buildBaseDiagnostics, columnsOf, compact, confirmArg, describeStore, detectEpoch, escapeLike, fail, fingerprintSchema, inspectFile, interferenceNote, limitArg, ok, openAxChannel, openReadOnly, parseBool, parseConfig, parseIntOpt, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, resolveLimit, trimmed, watchInterference, withLazyTools, wrap, wrapResult } from "@mgcrea/mcp-apple-core";
2
2
  import { readdirSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { execFileSync } from "node:child_process";
5
+ import { execFile, execFileSync } from "node:child_process";
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { DatabaseSync } from "node:sqlite";
8
+ import { promisify } from "node:util";
8
9
  import { z } from "zod";
9
10
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
11
  //#region src/build-info.ts
@@ -15,8 +16,8 @@ const pkg = readPackageIdentity(new URL("../package.json", import.meta.url), {
15
16
  const BUILD_INFO = {
16
17
  name: pkg.name,
17
18
  version: pkg.version,
18
- gitCommit: "2398a54",
19
- gitCommitDate: "2026-09-26T21:25:01+02:00"
19
+ gitCommit: "782cb1c",
20
+ gitCommitDate: "2026-10-03T15:37:05+02:00"
20
21
  };
21
22
  //#endregion
22
23
  //#region src/client/dates.ts
@@ -46,16 +47,7 @@ const BUILD_INFO = {
46
47
  * arrived at after a probe misread its own column — adopted here rather than
47
48
  * re-derived.
48
49
  */
49
- /** What `detectEpoch` says when it has matched nothing. Same shape as Safari's. */
50
- const GAVE_UP = /^(no dated rows|neither epoch)/;
51
- const resolveEpoch = (maxTimestamp, now = Date.now()) => {
52
- const { offset, reason } = detectEpoch(maxTimestamp, now);
53
- return {
54
- offset,
55
- reason,
56
- confident: !GAVE_UP.test(reason)
57
- };
58
- };
50
+ const resolveEpoch = (maxTimestamp, now = Date.now()) => detectEpoch(maxTimestamp, now);
59
51
  /** The expectation docs/maps.md carries, used only where no store is open. */
60
52
  const APPLE_SECONDS = {
61
53
  offset: CORE_DATA_EPOCH_OFFSET,
@@ -1359,11 +1351,8 @@ const progress = (message) => {
1359
1351
  var MapsWriteError = class extends AppleAutomationError {
1360
1352
  name = "MapsWriteError";
1361
1353
  };
1362
- const defaultOpenUrl = (url) => {
1363
- execFileSync("/usr/bin/open", ["-g", url], {
1364
- timeout: 1e4,
1365
- stdio: "ignore"
1366
- });
1354
+ const defaultOpenUrl = async (url) => {
1355
+ await promisify(execFile)("/usr/bin/open", ["-g", url], { timeout: 1e4 });
1367
1356
  };
1368
1357
  const uuidBytes = () => Uint8Array.from(Buffer.from(randomUUID().replaceAll("-", ""), "hex"));
1369
1358
  const uuidOf = (bytes) => {
@@ -1565,7 +1554,7 @@ var MapsWriter = class {
1565
1554
  if (!donor) {
1566
1555
  const url = `maps://?q=${encodeURIComponent(input.query)}`;
1567
1556
  progress(`asking Maps to resolve ${JSON.stringify(input.query)}…`);
1568
- this.#openUrl(url);
1557
+ await this.#openUrl(url);
1569
1558
  seeded = true;
1570
1559
  progress(`opened, waiting up to ${Math.round(this.#seedTimeoutMs / 1e3)}s for a record`);
1571
1560
  const deadline = Date.now() + this.#seedTimeoutMs;
@@ -1740,6 +1729,7 @@ var AppleMapsClient = class {
1740
1729
  if (!located.readable || !located.storePath) throw new MapsStoreUnavailableError(located.reason ?? "Maps' store could not be opened.");
1741
1730
  return new MapsWriter({
1742
1731
  storePath: located.storePath,
1732
+ seedTimeoutMs: this.#config.seedTimeoutMs,
1743
1733
  ...openUrl ? { openUrl } : {}
1744
1734
  });
1745
1735
  }
@@ -1916,18 +1906,24 @@ const ConfigSchema = BaseConfigSchema.extend({
1916
1906
  "ro",
1917
1907
  "immutable",
1918
1908
  "off"
1919
- ]).default("auto")
1909
+ ]).default("auto"),
1910
+ /**
1911
+ * How long `add_favorite` waits for Maps to resolve a place it does not know.
1912
+ * Tens of seconds is normal — Maps goes to the network — and a slow link
1913
+ * needs more; this is the one timeout in the bundle that was not a setting.
1914
+ */
1915
+ seedTimeoutMs: z.number().int().min(1e3).max(6e5).default(3e4)
1920
1916
  }).strict();
1921
1917
  const loadConfig = (env = process.env) => parseConfig(ConfigSchema, {
1922
1918
  allowWrites: parseBool(env.APPLE_MAPS_ALLOW_WRITES),
1923
1919
  exposePrompts: parseBool(env.APPLE_MAPS_EXPOSE_PROMPTS),
1924
1920
  lazyTools: parseBool(env.APPLE_MAPS_LAZY_TOOLS),
1925
- debug: parseBool(env.APPLE_MAPS_DEBUG),
1926
1921
  storePath: trimmed(env.APPLE_MAPS_STORE),
1927
1922
  indexMode: trimmed(env.APPLE_MAPS_INDEX_MODE),
1928
1923
  osascriptPath: trimmed(env.APPLE_MAPS_OSASCRIPT_PATH),
1929
1924
  osascriptTimeoutMs: parseIntOpt(env.APPLE_MAPS_OSASCRIPT_TIMEOUT_MS),
1930
- maxResults: parseIntOpt(env.APPLE_MAPS_MAX_RESULTS)
1925
+ maxResults: parseIntOpt(env.APPLE_MAPS_MAX_RESULTS),
1926
+ seedTimeoutMs: parseIntOpt(env.APPLE_MAPS_SEED_TIMEOUT_MS)
1931
1927
  });
1932
1928
  //#endregion
1933
1929
  //#region src/guide.ts
@@ -2060,12 +2056,17 @@ const queryArg = z.string().min(1).describe("Text to look for in a place's name,
2060
2056
  const buildDiagnostics = async (client) => {
2061
2057
  const status = client.status();
2062
2058
  const located = status.located;
2059
+ const base = buildBaseDiagnostics({
2060
+ build: BUILD_INFO,
2061
+ config: client.config,
2062
+ allowWrites: client.config.allowWrites
2063
+ });
2063
2064
  return {
2064
- server: {
2065
- name: BUILD_INFO.name,
2066
- version: BUILD_INFO.version
2065
+ ...base,
2066
+ settings: {
2067
+ ...base.settings,
2068
+ seedTimeoutMs: client.config.seedTimeoutMs
2067
2069
  },
2068
- settings: { exposePrompts: client.config.exposePrompts },
2069
2070
  lanes: {
2070
2071
  summary: "Maps has ONE lane. Maps.app ships no scripting dictionary — there is no .sdef in the bundle, checked directly — so there is no Apple Events fallback. Without Full Disk Access this server cannot read anything at all, and it says so rather than returning empty lists.",
2071
2072
  fileLane: {
@@ -2187,8 +2188,11 @@ const registerAxWriteTools = (server, lane) => {
2187
2188
  }) : fail(`"${args.query}" was pressed through the save sheet but its card does not report it as saved, so this MUST NOT be reported as done. Check Maps.` + await disturbed());
2188
2189
  }));
2189
2190
  server.registerTool("apple_maps_remove_saved_place", {
2190
- description: "Remove a place from Maps' Places library, through the card's overflow menu. This does NOT touch favourites — use apple_maps_remove_favorite for those. SIDE EFFECTS: opens Maps, brings its window forward, and leaves the place in the user's Recents. Syncs to the user's other Apple devices. Needs Accessibility for Cupertino.",
2191
- inputSchema: place,
2191
+ description: "Remove a place from Maps' Places library, through the card's overflow menu. This does NOT touch favourites — use apple_maps_remove_favorite for those. SIDE EFFECTS: opens Maps, brings its window forward, and leaves the place in the user's Recents. Syncs to the user's other Apple devices. Needs Accessibility for Cupertino, and an explicit confirm: the removal is not undoable from here.",
2192
+ inputSchema: {
2193
+ ...place,
2194
+ confirm: confirmArg
2195
+ },
2192
2196
  annotations: {
2193
2197
  readOnlyHint: false,
2194
2198
  destructiveHint: true,
@@ -2473,8 +2477,11 @@ const registerWriteTools = (server, client) => {
2473
2477
  }));
2474
2478
  }));
2475
2479
  server.registerTool("apple_maps_remove_favorite", {
2476
- description: "Remove a place from Maps' favourites, by a ref from apple_maps_list_favorites. This deletes the favourite on the user's other Apple devices too, through iCloud. It does not affect Guides, Recents, or anything else that references the same place. Needs Full Disk Access.",
2477
- inputSchema: { ref: placeRefArg },
2480
+ description: "Remove a place from Maps' favourites, by a ref from apple_maps_list_favorites. This deletes the favourite on the user's other Apple devices too, through iCloud. It does not affect Guides, Recents, or anything else that references the same place. Needs Full Disk Access, and an explicit confirm: the deletion is not undoable from here.",
2481
+ inputSchema: {
2482
+ ref: placeRefArg,
2483
+ confirm: confirmArg
2484
+ },
2478
2485
  annotations: {
2479
2486
  readOnlyHint: false,
2480
2487
  idempotentHint: true,
@@ -2556,4 +2563,4 @@ const createServer = (opts) => {
2556
2563
  //#endregion
2557
2564
  export { fromStoreTime as A, MAPS_SURFACE as C, UndatableStoreError as D, SchemaDriftError$1 as E, resolveEpoch as M, BUILD_INFO as N, APPLE_SECONDS as O, MAPS_BUNDLE_ID as S, PlaceNotFoundError as T, defaultDirectory as _, loadConfig as a, AppleMapsError as b, introspect as c, InvalidMapsRefError as d, PLACE_REF_VERSION as f, encodePlaceRef as g, encodeCollectionRef as h, registerTools as i, renderInstant as j, CORE_DATA_EPOCH_OFFSET as k, openStore as l, decodePlaceRef as m, SERVER_VERSION as n, AppleMapsClient as o, decodeCollectionRef as p, createServer as r, MapsStore as s, SERVER_NAME as t, COLLECTION_REF_VERSION as u, defaultStorePath as v, MapsStoreUnavailableError as w, IndexUnavailableError as x, locateStore as y };
2558
2565
 
2559
- //# sourceMappingURL=server-CVGfFevI.js.map
2566
+ //# sourceMappingURL=server-CO_d1_6b.js.map