@mgcrea/mcp-apple-maps 1.24.1 → 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 +27 -10
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{server-Cos6wXAu.js → server-CO_d1_6b.js} +39 -32
- package/dist/server-CO_d1_6b.js.map +1 -0
- package/package.json +3 -3
- package/dist/server-Cos6wXAu.js.map +0 -1
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
|
|
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
|
|
65
|
-
|
|
|
66
|
-
| `APPLE_MAPS_STORE`
|
|
67
|
-
| `APPLE_MAPS_INDEX_MODE`
|
|
68
|
-
| `APPLE_MAPS_MAX_RESULTS`
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
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`
|
|
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-
|
|
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: `
|
|
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 //
|
|
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;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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":";;;;;cAkBa,YAAY
|
|
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-
|
|
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: "
|
|
19
|
-
gitCommitDate: "2026-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
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:
|
|
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: {
|
|
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-
|
|
2566
|
+
//# sourceMappingURL=server-CO_d1_6b.js.map
|