@jbctechsolutions/mcp-office365 2.5.1 → 3.0.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.
Files changed (222) hide show
  1. package/README.md +32 -0
  2. package/dist/approval/token-manager.d.ts +28 -16
  3. package/dist/approval/token-manager.d.ts.map +1 -1
  4. package/dist/approval/token-manager.js +125 -37
  5. package/dist/approval/token-manager.js.map +1 -1
  6. package/dist/cli.d.ts +17 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +85 -2
  9. package/dist/cli.js.map +1 -1
  10. package/dist/graph/auth/config.d.ts +1 -1
  11. package/dist/graph/auth/config.d.ts.map +1 -1
  12. package/dist/graph/auth/config.js +5 -1
  13. package/dist/graph/auth/config.js.map +1 -1
  14. package/dist/graph/auth/device-code-flow.d.ts +3 -1
  15. package/dist/graph/auth/device-code-flow.d.ts.map +1 -1
  16. package/dist/graph/auth/device-code-flow.js +42 -14
  17. package/dist/graph/auth/device-code-flow.js.map +1 -1
  18. package/dist/graph/auth/token-cache.js +2 -2
  19. package/dist/graph/auth/token-cache.js.map +1 -1
  20. package/dist/graph/client/graph-client.d.ts +36 -8
  21. package/dist/graph/client/graph-client.d.ts.map +1 -1
  22. package/dist/graph/client/graph-client.js +128 -36
  23. package/dist/graph/client/graph-client.js.map +1 -1
  24. package/dist/graph/repository.d.ts +9 -6
  25. package/dist/graph/repository.d.ts.map +1 -1
  26. package/dist/graph/repository.js +63 -66
  27. package/dist/graph/repository.js.map +1 -1
  28. package/dist/ids/mint.d.ts +31 -0
  29. package/dist/ids/mint.d.ts.map +1 -0
  30. package/dist/ids/mint.js +36 -0
  31. package/dist/ids/mint.js.map +1 -0
  32. package/dist/ids/resolver.d.ts +30 -0
  33. package/dist/ids/resolver.d.ts.map +1 -0
  34. package/dist/ids/resolver.js +37 -0
  35. package/dist/ids/resolver.js.map +1 -0
  36. package/dist/ids/token.d.ts +56 -0
  37. package/dist/ids/token.d.ts.map +1 -0
  38. package/dist/ids/token.js +186 -0
  39. package/dist/ids/token.js.map +1 -0
  40. package/dist/index.d.ts +7 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +226 -5859
  43. package/dist/index.js.map +1 -1
  44. package/dist/registry/all-tools.d.ts +14 -0
  45. package/dist/registry/all-tools.d.ts.map +1 -0
  46. package/dist/registry/all-tools.js +64 -0
  47. package/dist/registry/all-tools.js.map +1 -0
  48. package/dist/registry/context.d.ts +25 -0
  49. package/dist/registry/context.d.ts.map +1 -0
  50. package/dist/registry/context.js +31 -0
  51. package/dist/registry/context.js.map +1 -0
  52. package/dist/registry/define-tool.d.ts +15 -0
  53. package/dist/registry/define-tool.d.ts.map +1 -0
  54. package/dist/registry/define-tool.js +8 -0
  55. package/dist/registry/define-tool.js.map +1 -0
  56. package/dist/registry/index.d.ts +13 -0
  57. package/dist/registry/index.d.ts.map +1 -0
  58. package/dist/registry/index.js +8 -0
  59. package/dist/registry/index.js.map +1 -0
  60. package/dist/registry/registry.d.ts +62 -0
  61. package/dist/registry/registry.d.ts.map +1 -0
  62. package/dist/registry/registry.js +134 -0
  63. package/dist/registry/registry.js.map +1 -0
  64. package/dist/registry/types.d.ts +98 -0
  65. package/dist/registry/types.d.ts.map +1 -0
  66. package/dist/registry/types.js +6 -0
  67. package/dist/registry/types.js.map +1 -0
  68. package/dist/search/compiler.d.ts +49 -0
  69. package/dist/search/compiler.d.ts.map +1 -0
  70. package/dist/search/compiler.js +168 -0
  71. package/dist/search/compiler.js.map +1 -0
  72. package/dist/signature.js +2 -2
  73. package/dist/signature.js.map +1 -1
  74. package/dist/state/migrate.d.ts +23 -0
  75. package/dist/state/migrate.d.ts.map +1 -0
  76. package/dist/state/migrate.js +81 -0
  77. package/dist/state/migrate.js.map +1 -0
  78. package/dist/state/schema.d.ts +27 -0
  79. package/dist/state/schema.d.ts.map +1 -0
  80. package/dist/state/schema.js +54 -0
  81. package/dist/state/schema.js.map +1 -0
  82. package/dist/state/store.d.ts +152 -0
  83. package/dist/state/store.d.ts.map +1 -0
  84. package/dist/state/store.js +317 -0
  85. package/dist/state/store.js.map +1 -0
  86. package/dist/tools/accounts.d.ts +37 -0
  87. package/dist/tools/accounts.d.ts.map +1 -0
  88. package/dist/tools/accounts.js +68 -0
  89. package/dist/tools/accounts.js.map +1 -0
  90. package/dist/tools/calendar-apple.d.ts +39 -0
  91. package/dist/tools/calendar-apple.d.ts.map +1 -0
  92. package/dist/tools/calendar-apple.js +159 -0
  93. package/dist/tools/calendar-apple.js.map +1 -0
  94. package/dist/tools/calendar-graph.d.ts +41 -0
  95. package/dist/tools/calendar-graph.d.ts.map +1 -0
  96. package/dist/tools/calendar-graph.js +298 -0
  97. package/dist/tools/calendar-graph.js.map +1 -0
  98. package/dist/tools/calendar-permissions.d.ts +10 -0
  99. package/dist/tools/calendar-permissions.d.ts.map +1 -1
  100. package/dist/tools/calendar-permissions.js +53 -0
  101. package/dist/tools/calendar-permissions.js.map +1 -1
  102. package/dist/tools/calendar.d.ts +151 -0
  103. package/dist/tools/calendar.d.ts.map +1 -1
  104. package/dist/tools/calendar.js +274 -0
  105. package/dist/tools/calendar.js.map +1 -1
  106. package/dist/tools/categories.d.ts +10 -0
  107. package/dist/tools/categories.d.ts.map +1 -1
  108. package/dist/tools/categories.js +54 -0
  109. package/dist/tools/categories.js.map +1 -1
  110. package/dist/tools/checklist-items.d.ts +10 -0
  111. package/dist/tools/checklist-items.d.ts.map +1 -1
  112. package/dist/tools/checklist-items.js +63 -0
  113. package/dist/tools/checklist-items.js.map +1 -1
  114. package/dist/tools/contact-folders.d.ts +50 -0
  115. package/dist/tools/contact-folders.d.ts.map +1 -0
  116. package/dist/tools/contact-folders.js +133 -0
  117. package/dist/tools/contact-folders.js.map +1 -0
  118. package/dist/tools/contacts-graph.d.ts +45 -0
  119. package/dist/tools/contacts-graph.d.ts.map +1 -0
  120. package/dist/tools/contacts-graph.js +172 -0
  121. package/dist/tools/contacts-graph.js.map +1 -0
  122. package/dist/tools/contacts.d.ts +66 -0
  123. package/dist/tools/contacts.d.ts.map +1 -1
  124. package/dist/tools/contacts.js +165 -0
  125. package/dist/tools/contacts.js.map +1 -1
  126. package/dist/tools/excel.d.ts +10 -0
  127. package/dist/tools/excel.d.ts.map +1 -1
  128. package/dist/tools/excel.js +73 -0
  129. package/dist/tools/excel.js.map +1 -1
  130. package/dist/tools/focused-overrides.d.ts +10 -0
  131. package/dist/tools/focused-overrides.d.ts.map +1 -1
  132. package/dist/tools/focused-overrides.js +54 -0
  133. package/dist/tools/focused-overrides.js.map +1 -1
  134. package/dist/tools/linked-resources.d.ts +10 -0
  135. package/dist/tools/linked-resources.d.ts.map +1 -1
  136. package/dist/tools/linked-resources.js +53 -0
  137. package/dist/tools/linked-resources.js.map +1 -1
  138. package/dist/tools/mail-apple.d.ts +40 -0
  139. package/dist/tools/mail-apple.d.ts.map +1 -0
  140. package/dist/tools/mail-apple.js +146 -0
  141. package/dist/tools/mail-apple.js.map +1 -0
  142. package/dist/tools/mail-graph.d.ts +38 -0
  143. package/dist/tools/mail-graph.d.ts.map +1 -0
  144. package/dist/tools/mail-graph.js +178 -0
  145. package/dist/tools/mail-graph.js.map +1 -0
  146. package/dist/tools/mail-rules.d.ts +12 -0
  147. package/dist/tools/mail-rules.d.ts.map +1 -1
  148. package/dist/tools/mail-rules.js +56 -0
  149. package/dist/tools/mail-rules.js.map +1 -1
  150. package/dist/tools/mail-send.d.ts +12 -0
  151. package/dist/tools/mail-send.d.ts.map +1 -1
  152. package/dist/tools/mail-send.js +219 -5
  153. package/dist/tools/mail-send.js.map +1 -1
  154. package/dist/tools/mail.d.ts +82 -2
  155. package/dist/tools/mail.d.ts.map +1 -1
  156. package/dist/tools/mail.js +239 -2
  157. package/dist/tools/mail.js.map +1 -1
  158. package/dist/tools/mailbox-organization.d.ts +20 -0
  159. package/dist/tools/mailbox-organization.d.ts.map +1 -1
  160. package/dist/tools/mailbox-organization.js +275 -0
  161. package/dist/tools/mailbox-organization.js.map +1 -1
  162. package/dist/tools/mailbox-settings.d.ts +59 -0
  163. package/dist/tools/mailbox-settings.d.ts.map +1 -0
  164. package/dist/tools/mailbox-settings.js +136 -0
  165. package/dist/tools/mailbox-settings.js.map +1 -0
  166. package/dist/tools/meetings.d.ts +10 -0
  167. package/dist/tools/meetings.d.ts.map +1 -1
  168. package/dist/tools/meetings.js +74 -0
  169. package/dist/tools/meetings.js.map +1 -1
  170. package/dist/tools/notes.d.ts +12 -0
  171. package/dist/tools/notes.d.ts.map +1 -1
  172. package/dist/tools/notes.js +66 -0
  173. package/dist/tools/notes.js.map +1 -1
  174. package/dist/tools/onedrive.d.ts +10 -0
  175. package/dist/tools/onedrive.d.ts.map +1 -1
  176. package/dist/tools/onedrive.js +124 -0
  177. package/dist/tools/onedrive.js.map +1 -1
  178. package/dist/tools/people.d.ts +10 -0
  179. package/dist/tools/people.d.ts.map +1 -1
  180. package/dist/tools/people.js +94 -0
  181. package/dist/tools/people.js.map +1 -1
  182. package/dist/tools/planner-visualization.d.ts +10 -0
  183. package/dist/tools/planner-visualization.d.ts.map +1 -1
  184. package/dist/tools/planner-visualization.js +53 -0
  185. package/dist/tools/planner-visualization.js.map +1 -1
  186. package/dist/tools/planner.d.ts +10 -0
  187. package/dist/tools/planner.d.ts.map +1 -1
  188. package/dist/tools/planner.js +183 -0
  189. package/dist/tools/planner.js.map +1 -1
  190. package/dist/tools/scheduling.d.ts +12 -0
  191. package/dist/tools/scheduling.d.ts.map +1 -1
  192. package/dist/tools/scheduling.js +38 -0
  193. package/dist/tools/scheduling.js.map +1 -1
  194. package/dist/tools/sharepoint.d.ts +10 -0
  195. package/dist/tools/sharepoint.d.ts.map +1 -1
  196. package/dist/tools/sharepoint.js +74 -0
  197. package/dist/tools/sharepoint.js.map +1 -1
  198. package/dist/tools/task-attachments.d.ts +10 -0
  199. package/dist/tools/task-attachments.d.ts.map +1 -1
  200. package/dist/tools/task-attachments.js +53 -0
  201. package/dist/tools/task-attachments.js.map +1 -1
  202. package/dist/tools/task-lists.d.ts +56 -0
  203. package/dist/tools/task-lists.d.ts.map +1 -0
  204. package/dist/tools/task-lists.js +151 -0
  205. package/dist/tools/task-lists.js.map +1 -0
  206. package/dist/tools/tasks-graph.d.ts +49 -0
  207. package/dist/tools/tasks-graph.d.ts.map +1 -0
  208. package/dist/tools/tasks-graph.js +191 -0
  209. package/dist/tools/tasks-graph.js.map +1 -0
  210. package/dist/tools/tasks.d.ts +127 -0
  211. package/dist/tools/tasks.d.ts.map +1 -1
  212. package/dist/tools/tasks.js +155 -0
  213. package/dist/tools/tasks.js.map +1 -1
  214. package/dist/tools/teams.d.ts +11 -0
  215. package/dist/tools/teams.d.ts.map +1 -1
  216. package/dist/tools/teams.js +254 -0
  217. package/dist/tools/teams.js.map +1 -1
  218. package/dist/utils/errors.d.ts +96 -5
  219. package/dist/utils/errors.d.ts.map +1 -1
  220. package/dist/utils/errors.js +227 -8
  221. package/dist/utils/errors.js.map +1 -1
  222. package/package.json +1 -1
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Durable state store (U4) — a better-sqlite3-backed store at
7
+ * `~/.mcp-office365/state.db` holding durable-ID aliases and two-phase approval
8
+ * tokens. Provides the concurrency (WAL + busy_timeout + atomic consume, D7),
9
+ * at-rest (0700/0600 permissions, D18), account-stamping (D7), and
10
+ * degradation (in-memory fallback, D15) semantics the rest of v3 builds on.
11
+ *
12
+ * This unit is the storage layer only; wiring into the ID resolver (U5) and the
13
+ * approval manager (U9) lands in those units.
14
+ */
15
+ import Database from 'better-sqlite3';
16
+ import { chmodSync, existsSync, mkdirSync } from 'node:fs';
17
+ import { homedir } from 'node:os';
18
+ import { join } from 'node:path';
19
+ import { runMigrations, migrateLegacyTokens } from './migrate.js';
20
+ import { APPROVAL_RETENTION_MS } from './schema.js';
21
+ const DEFAULT_DIR = join(homedir(), '.mcp-office365');
22
+ const LEGACY_DIR = join(homedir(), '.outlook-mcp');
23
+ const DB_FILENAME = 'state.db';
24
+ export class StateStore {
25
+ /** True when running from an in-memory fallback (durability degraded). */
26
+ degraded;
27
+ /** The db path, or ':memory:' when degraded. */
28
+ path;
29
+ /** Effective `journal_mode` pragma (e.g. 'wal'). */
30
+ journalMode;
31
+ /** Effective `busy_timeout` pragma in ms. */
32
+ busyTimeout;
33
+ db;
34
+ now;
35
+ constructor(db, path, degraded, now) {
36
+ this.db = db;
37
+ this.path = path;
38
+ this.degraded = degraded;
39
+ this.now = now;
40
+ this.journalMode = String(db.pragma('journal_mode', { simple: true }));
41
+ this.busyTimeout = Number(db.pragma('busy_timeout', { simple: true }));
42
+ }
43
+ /**
44
+ * Opens (creating if needed) the durable store. On any failure to use the
45
+ * on-disk db (corrupt/locked file, unwritable dir) it degrades to an in-memory
46
+ * store, emits a stderr warning, and reports `degraded = true` — the server
47
+ * stays usable, only durability is lost for the run.
48
+ */
49
+ static open(options = {}) {
50
+ const dir = options.dir ?? DEFAULT_DIR;
51
+ const legacyDir = options.legacyDir ?? LEGACY_DIR;
52
+ const now = options.now ?? (() => Date.now());
53
+ const warn = options.warn ?? ((msg) => void process.stderr.write(`${msg}\n`));
54
+ let fileDb;
55
+ try {
56
+ // Directory: create 0700, or repair perms if it already exists (D18).
57
+ if (!existsSync(dir)) {
58
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
59
+ }
60
+ else {
61
+ safeChmod(dir, 0o700, warn);
62
+ }
63
+ const dbPath = join(dir, DB_FILENAME);
64
+ fileDb = new Database(dbPath);
65
+ configurePragmas(fileDb);
66
+ runMigrations(fileDb); // executes DDL — surfaces a corrupt/newer file here
67
+ // The file (and its -wal/-shm sidecars) may have just been created;
68
+ // enforce 0600 across all three (and repair a loose one).
69
+ safeChmod(dbPath, 0o600, warn);
70
+ safeChmod(`${dbPath}-wal`, 0o600, warn);
71
+ safeChmod(`${dbPath}-shm`, 0o600, warn);
72
+ const store = new StateStore(fileDb, dbPath, false, now);
73
+ // The legacy token copy and boot purge are conveniences — a failure in
74
+ // either must NOT discard an otherwise-healthy on-disk store, so they run
75
+ // outside the degrade-governing path (warn-and-continue).
76
+ try {
77
+ migrateLegacyTokens(fileDb, dir, legacyDir);
78
+ }
79
+ catch (e) {
80
+ warn(`[mcp-office365] legacy token migration skipped (${e instanceof Error ? e.message : String(e)}).`);
81
+ }
82
+ try {
83
+ store.purgeExpired(now());
84
+ }
85
+ catch (e) {
86
+ warn(`[mcp-office365] boot purge skipped (${e instanceof Error ? e.message : String(e)}).`);
87
+ }
88
+ return store;
89
+ }
90
+ catch (error) {
91
+ // Release the on-disk handle (and its WAL lock) before degrading, so a
92
+ // failed open does not leak a file descriptor / lock for the process.
93
+ if (fileDb !== undefined) {
94
+ try {
95
+ fileDb.close();
96
+ }
97
+ catch {
98
+ /* best-effort */
99
+ }
100
+ }
101
+ const reason = error instanceof Error ? error.message : String(error);
102
+ warn(`[mcp-office365] state store unavailable (${reason}); running in-memory (durability degraded).`);
103
+ const mem = new Database(':memory:');
104
+ configurePragmas(mem);
105
+ runMigrations(mem);
106
+ return new StateStore(mem, ':memory:', true, now);
107
+ }
108
+ }
109
+ // ---- Aliases (D3) --------------------------------------------------------
110
+ /** Inserts or replaces a durable-ID alias. */
111
+ putAlias(input) {
112
+ this.db
113
+ .prepare(`INSERT INTO aliases (token, graph_id, entity_type, account_id, mutable, created_at)
114
+ VALUES (@token, @graphId, @entityType, @accountId, @mutable, @createdAt)
115
+ ON CONFLICT(token) DO UPDATE SET
116
+ graph_id = excluded.graph_id,
117
+ entity_type = excluded.entity_type,
118
+ account_id = excluded.account_id,
119
+ mutable = excluded.mutable`)
120
+ .run({
121
+ token: input.token,
122
+ graphId: input.graphId,
123
+ entityType: input.entityType,
124
+ accountId: input.accountId,
125
+ mutable: input.mutable === true ? 1 : 0,
126
+ createdAt: input.createdAt ?? this.now(),
127
+ });
128
+ }
129
+ /**
130
+ * Resolves an alias token, scoped to `accountId` (D7 account stamping). The
131
+ * account is a mandatory, fail-closed argument: a row minted under a different
132
+ * account is invisible, so no caller can accidentally resolve a foreign
133
+ * account's durable ID into a live Graph ID by omitting the scope.
134
+ */
135
+ getAlias(token, accountId) {
136
+ const raw = this.db
137
+ .prepare('SELECT * FROM aliases WHERE token = ? AND account_id = ?')
138
+ .get(token, accountId);
139
+ if (raw === undefined) {
140
+ return null;
141
+ }
142
+ return {
143
+ token: raw.token,
144
+ graphId: raw.graph_id,
145
+ entityType: raw.entity_type,
146
+ accountId: raw.account_id,
147
+ mutable: raw.mutable !== 0,
148
+ createdAt: raw.created_at,
149
+ };
150
+ }
151
+ /**
152
+ * Atomically registers an alias with D1a collision enforcement, in a single
153
+ * IMMEDIATE transaction so the check-and-write is not a read-then-write race:
154
+ * two concurrent immutable registrations of the same token cannot both pass
155
+ * the check and then clobber each other. Returns `'collision'` when a
156
+ * *different* Graph ID already occupies the token for an immutable entity
157
+ * (neither the stored nor the new row is mutable); otherwise upserts and
158
+ * returns `'ok'`.
159
+ */
160
+ registerAlias(input) {
161
+ const run = this.db.transaction(() => {
162
+ const existing = this.getAliasUnscoped(input.token);
163
+ if (existing !== null &&
164
+ existing.graphId !== input.graphId &&
165
+ !existing.mutable &&
166
+ input.mutable !== true) {
167
+ return 'collision';
168
+ }
169
+ this.putAlias(input);
170
+ return 'ok';
171
+ });
172
+ return run.immediate();
173
+ }
174
+ /**
175
+ * Returns an alias row regardless of account, or null. Reserved for two
176
+ * internal uses that must see across accounts: foreign-account disambiguation
177
+ * during resolution, and collision detection at mint time (D1a). It is NOT a
178
+ * resolution path — {@link getAlias} (account-scoped) is the only one of those.
179
+ */
180
+ getAliasUnscoped(token) {
181
+ const raw = this.db.prepare('SELECT * FROM aliases WHERE token = ?').get(token);
182
+ if (raw === undefined) {
183
+ return null;
184
+ }
185
+ return {
186
+ token: raw.token,
187
+ graphId: raw.graph_id,
188
+ entityType: raw.entity_type,
189
+ accountId: raw.account_id,
190
+ mutable: raw.mutable !== 0,
191
+ createdAt: raw.created_at,
192
+ };
193
+ }
194
+ /**
195
+ * Returns the account a token was minted under (any account), or null when the
196
+ * token is unknown. Distinguishes "foreign account" from "unknown" during
197
+ * resolution so a foreign token yields a typed ID_FOREIGN_ACCOUNT.
198
+ */
199
+ getAliasAccount(token) {
200
+ return this.getAliasUnscoped(token)?.accountId ?? null;
201
+ }
202
+ // ---- Approval tokens (D7/D8) --------------------------------------------
203
+ /**
204
+ * Reads an approval token scoped to `accountId` (or null). A read view for
205
+ * validation/preview; redemption still goes through {@link consumeApprovalToken}
206
+ * so the atomic guard is never bypassed.
207
+ */
208
+ getApprovalToken(token, accountId) {
209
+ const raw = this.db
210
+ .prepare('SELECT token, action, target_json, content_hash, expires_at, redeemed_at, receipt_json, created_at FROM approval_tokens WHERE token = ? AND account_id = ?')
211
+ .get(token, accountId);
212
+ if (raw === undefined) {
213
+ return null;
214
+ }
215
+ return {
216
+ token: raw.token,
217
+ action: raw.action,
218
+ targetJson: raw.target_json,
219
+ contentHash: raw.content_hash,
220
+ expiresAt: raw.expires_at,
221
+ redeemedAt: raw.redeemed_at,
222
+ receiptJson: raw.receipt_json,
223
+ createdAt: raw.created_at,
224
+ };
225
+ }
226
+ /** Stages a two-phase approval token. */
227
+ putApprovalToken(input) {
228
+ this.db
229
+ .prepare(`INSERT INTO approval_tokens
230
+ (token, operation_key, action, target_json, content_hash, account_id, expires_at, created_at)
231
+ VALUES (@token, @operationKey, @action, @targetJson, @contentHash, @accountId, @expiresAt, @createdAt)`)
232
+ .run({
233
+ token: input.token,
234
+ operationKey: input.operationKey ?? null,
235
+ action: input.action,
236
+ targetJson: input.targetJson,
237
+ contentHash: input.contentHash ?? null,
238
+ accountId: input.accountId,
239
+ expiresAt: input.expiresAt,
240
+ createdAt: input.createdAt ?? this.now(),
241
+ });
242
+ }
243
+ /**
244
+ * Atomically consumes an approval token (D8). The guarded `UPDATE … WHERE
245
+ * redeemed_at IS NULL AND expires_at > now RETURNING` means only one caller —
246
+ * across processes sharing the db — can win the redemption; the loser sees
247
+ * `already_redeemed` and can return the stored receipt. Expiry is enforced
248
+ * here at the trust boundary (not left to callers): an expired token that
249
+ * still authorizes a send/delete would defeat the whole point of a time-boxed
250
+ * two-phase approval. Foreign-account tokens are refused.
251
+ */
252
+ consumeApprovalToken(args) {
253
+ const now = args.now ?? this.now();
254
+ const updated = this.db
255
+ .prepare(`UPDATE approval_tokens
256
+ SET redeemed_at = ?, receipt_json = ?
257
+ WHERE token = ? AND account_id = ? AND redeemed_at IS NULL AND expires_at > ?
258
+ RETURNING receipt_json`)
259
+ .get(now, args.receiptJson ?? null, args.token, args.accountId, now);
260
+ if (updated !== undefined) {
261
+ return { status: 'consumed', receiptJson: updated.receipt_json };
262
+ }
263
+ // Classify why the guarded update matched nothing.
264
+ const row = this.db
265
+ .prepare('SELECT account_id, redeemed_at, receipt_json, expires_at FROM approval_tokens WHERE token = ?')
266
+ .get(args.token);
267
+ if (row === undefined) {
268
+ return { status: 'not_found' };
269
+ }
270
+ if (row.account_id !== args.accountId) {
271
+ return { status: 'foreign_account' };
272
+ }
273
+ // Redemption takes precedence over expiry so an idempotent re-consume of an
274
+ // already-redeemed token still returns its receipt.
275
+ if (row.redeemed_at !== null) {
276
+ return { status: 'already_redeemed', receiptJson: row.receipt_json };
277
+ }
278
+ return { status: 'expired' };
279
+ }
280
+ // ---- Maintenance ---------------------------------------------------------
281
+ /**
282
+ * Deletes approval tokens whose expiry is older than the retention window
283
+ * (D8, 90 days). Recently-expired receipts linger so idempotent redemption
284
+ * still returns them. Returns the number of rows purged.
285
+ */
286
+ purgeExpired(now) {
287
+ const cutoff = now - APPROVAL_RETENTION_MS;
288
+ const result = this.db.prepare('DELETE FROM approval_tokens WHERE expires_at < ?').run(cutoff);
289
+ return result.changes;
290
+ }
291
+ close() {
292
+ this.db.close();
293
+ }
294
+ }
295
+ function configurePragmas(db) {
296
+ db.pragma('journal_mode = WAL');
297
+ db.pragma('busy_timeout = 5000');
298
+ }
299
+ /**
300
+ * chmod that never throws. Windows/filesystems without POSIX modes fail benignly
301
+ * and are ignored; a genuine failure on a POSIX host (e.g. EPERM) means the file
302
+ * may sit with looser-than-intended permissions, so we surface it via `warn`
303
+ * rather than swallow silently — the at-rest exposure should be observable.
304
+ * A missing sidecar (-wal/-shm not yet created) is not a failure worth noting.
305
+ */
306
+ function safeChmod(target, mode, warn) {
307
+ try {
308
+ chmodSync(target, mode);
309
+ }
310
+ catch (error) {
311
+ const code = error.code;
312
+ if (process.platform !== 'win32' && code !== 'ENOENT' && warn != null) {
313
+ warn(`[mcp-office365] could not set permissions on ${target} (${code ?? 'error'}); it may be readable by other local users.`);
314
+ }
315
+ }
316
+ }
317
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/state/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Account tools (v3 registry-driven architecture, U2 — dual backend).
7
+ *
8
+ * `list_accounts` is served by the AppleScript account repository in both
9
+ * backends. AccountsTools wraps that repository and is registered on both the
10
+ * Graph and AppleScript toolset bags, so a single registry handler resolves the
11
+ * active backend's instance.
12
+ */
13
+ import { z } from 'zod';
14
+ import type { IAccountRepository } from '../applescript/index.js';
15
+ import type { ToolDefinition, ToolResult } from '../registry/types.js';
16
+ declare module '../registry/types.js' {
17
+ interface GraphToolsets {
18
+ accounts: AccountsTools;
19
+ }
20
+ interface AppleScriptToolsets {
21
+ accounts: AccountsTools;
22
+ }
23
+ }
24
+ export declare const ListAccountsInput: z.ZodObject<{}, z.core.$strict>;
25
+ /**
26
+ * Account tools backed by the AppleScript account repository.
27
+ */
28
+ export declare class AccountsTools {
29
+ private readonly accountRepository;
30
+ constructor(accountRepository: IAccountRepository);
31
+ listAccounts(): ToolResult;
32
+ }
33
+ /**
34
+ * Registry tool definitions for the accounts domain.
35
+ */
36
+ export declare function accountsToolDefinitions(): ToolDefinition[];
37
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/tools/accounts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvE,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,aAAa;QACrB,QAAQ,EAAE,aAAa,CAAC;KACzB;IACD,UAAU,mBAAmB;QAC3B,QAAQ,EAAE,aAAa,CAAC;KACzB;CACF;AAMD,eAAO,MAAM,iBAAiB,iCAAqB,CAAC;AAUpD;;GAEG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,iBAAiB;gBAAjB,iBAAiB,EAAE,kBAAkB;IAElE,YAAY,IAAI,UAAU;CAW3B;AAMD;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,cAAc,EAAE,CAiB1D"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * Account tools (v3 registry-driven architecture, U2 — dual backend).
7
+ *
8
+ * `list_accounts` is served by the AppleScript account repository in both
9
+ * backends. AccountsTools wraps that repository and is registered on both the
10
+ * Graph and AppleScript toolset bags, so a single registry handler resolves the
11
+ * active backend's instance.
12
+ */
13
+ import { z } from 'zod';
14
+ import { defineTool } from '../registry/define-tool.js';
15
+ import { requireGraphToolset, requireAppleScriptToolset } from '../registry/context.js';
16
+ // =============================================================================
17
+ // Input Schemas
18
+ // =============================================================================
19
+ export const ListAccountsInput = z.strictObject({});
20
+ // =============================================================================
21
+ // Accounts Tools
22
+ // =============================================================================
23
+ function jsonResult(data) {
24
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
25
+ }
26
+ /**
27
+ * Account tools backed by the AppleScript account repository.
28
+ */
29
+ export class AccountsTools {
30
+ accountRepository;
31
+ constructor(accountRepository) {
32
+ this.accountRepository = accountRepository;
33
+ }
34
+ listAccounts() {
35
+ const accounts = this.accountRepository.listAccounts();
36
+ return jsonResult({
37
+ accounts: accounts.map((acc) => ({
38
+ id: acc.id,
39
+ name: acc.name,
40
+ email: acc.email,
41
+ type: acc.type,
42
+ })),
43
+ });
44
+ }
45
+ }
46
+ // =============================================================================
47
+ // Registry Definitions (v3 registry-driven architecture, U2 — dual backend)
48
+ // =============================================================================
49
+ /**
50
+ * Registry tool definitions for the accounts domain.
51
+ */
52
+ export function accountsToolDefinitions() {
53
+ return [
54
+ defineTool({
55
+ name: 'list_accounts',
56
+ description: 'List all Exchange accounts configured in Outlook with their details',
57
+ input: ListAccountsInput,
58
+ annotations: { readOnlyHint: true },
59
+ destructive: false,
60
+ presets: [],
61
+ backends: ['graph', 'applescript'],
62
+ handler: (ctx) => (ctx.backend === 'graph'
63
+ ? requireGraphToolset(ctx, 'accounts')
64
+ : requireAppleScriptToolset(ctx, 'accounts')).listAccounts(),
65
+ }),
66
+ ];
67
+ }
68
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/tools/accounts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAYxF,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAEpD,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,SAAS,UAAU,CAAC,IAAa;IAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,iBAAqC;QAArC,sBAAiB,GAAjB,iBAAiB,CAAoB;IAAG,CAAC;IAEtE,YAAY;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,CAAC;QACvD,OAAO,UAAU,CAAC;YAChB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC/B,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC;CACF;AAED,gFAAgF;AAChF,4EAA4E;AAC5E,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,UAAU,CAAC;YACT,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,qEAAqE;YAClF,KAAK,EAAE,iBAAiB;YACxB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;YACnC,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC;YAClC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CACf,CAAC,GAAG,CAAC,OAAO,KAAK,OAAO;gBACtB,CAAC,CAAC,mBAAmB,CAAC,GAAG,EAAE,UAAU,CAAC;gBACtC,CAAC,CAAC,yBAAyB,CAAC,GAAG,EAAE,UAAU,CAAC,CAC7C,CAAC,YAAY,EAAE;SACnB,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ /**
6
+ * AppleScript-backend calendar tools (v3 registry-driven architecture, U2 —
7
+ * dual backend). Holds the calendar logic that previously lived inline in the
8
+ * `handleAppleScriptToolCall` switch, so the registry handlers stay thin and
9
+ * branch on `ctx.backend`.
10
+ *
11
+ * The advertised (canonical) schemas are Graph-shaped (Graph is the default
12
+ * backend). This backend receives the superset params and maps only the fields
13
+ * it supports to the AppleScript writer/manager, exactly as the pre-registry
14
+ * dispatch did.
15
+ */
16
+ import type { CalendarTools } from './calendar.js';
17
+ import type { ListEventsParams, GetEventParams, SearchEventsParams, CreateEventGraphParams, UpdateEventParams, DeleteEventParams, RespondToEventParams } from './calendar.js';
18
+ import type { ICalendarWriter, ICalendarManager } from '../applescript/index.js';
19
+ import type { ToolResult } from '../registry/types.js';
20
+ /**
21
+ * AppleScript calendar tools. Each method mirrors the extracted inline
22
+ * AppleScript case body and returns an MCP `ToolResult`, including the
23
+ * write-capability null checks.
24
+ */
25
+ export declare class AppleCalendarTools {
26
+ private readonly calendarTools;
27
+ private readonly calendarWriter;
28
+ private readonly calendarManager;
29
+ constructor(calendarTools: CalendarTools, calendarWriter: ICalendarWriter | null, calendarManager: ICalendarManager | null);
30
+ listCalendars(): ToolResult;
31
+ listEvents(params: ListEventsParams): ToolResult;
32
+ getEvent(params: GetEventParams): ToolResult;
33
+ searchEvents(params: SearchEventsParams): ToolResult;
34
+ createEvent(params: CreateEventGraphParams): ToolResult;
35
+ respondToEvent(params: RespondToEventParams): ToolResult;
36
+ deleteEvent(params: DeleteEventParams): ToolResult;
37
+ updateEvent(params: UpdateEventParams): ToolResult;
38
+ }
39
+ //# sourceMappingURL=calendar-apple.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-apple.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-apple.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAEV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAGjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAMvD;;;;GAIG;AACH,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBAFf,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,eAAe,GAAG,IAAI,EACtC,eAAe,EAAE,gBAAgB,GAAG,IAAI;IAG3D,aAAa,IAAI,UAAU;IAI3B,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU;IAIhD,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU;IAQ5C,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,UAAU;IAIpD,WAAW,CAAC,MAAM,EAAE,sBAAsB,GAAG,UAAU;IA+CvD,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,UAAU;IA6BxD,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,UAAU;IAoBlD,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,UAAU;CAsCnD"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Copyright (c) 2026 JBC Tech Solutions, LLC
3
+ * Licensed under the MIT License. See LICENSE file in the project root.
4
+ */
5
+ function jsonResult(data) {
6
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
7
+ }
8
+ /**
9
+ * AppleScript calendar tools. Each method mirrors the extracted inline
10
+ * AppleScript case body and returns an MCP `ToolResult`, including the
11
+ * write-capability null checks.
12
+ */
13
+ export class AppleCalendarTools {
14
+ calendarTools;
15
+ calendarWriter;
16
+ calendarManager;
17
+ constructor(calendarTools, calendarWriter, calendarManager) {
18
+ this.calendarTools = calendarTools;
19
+ this.calendarWriter = calendarWriter;
20
+ this.calendarManager = calendarManager;
21
+ }
22
+ listCalendars() {
23
+ return jsonResult(this.calendarTools.listCalendars({}));
24
+ }
25
+ listEvents(params) {
26
+ return jsonResult(this.calendarTools.listEvents(params));
27
+ }
28
+ getEvent(params) {
29
+ const result = this.calendarTools.getEvent(params);
30
+ if (result == null) {
31
+ return { content: [{ type: 'text', text: 'Event not found' }], isError: true };
32
+ }
33
+ return jsonResult(result);
34
+ }
35
+ searchEvents(params) {
36
+ return jsonResult(this.calendarTools.searchEvents(params));
37
+ }
38
+ createEvent(params) {
39
+ if (this.calendarWriter == null) {
40
+ return {
41
+ content: [{ type: 'text', text: 'Event creation is not available' }],
42
+ isError: true,
43
+ };
44
+ }
45
+ const writerParams = {
46
+ title: params.title,
47
+ startDate: params.start_date,
48
+ endDate: params.end_date,
49
+ };
50
+ if (params.calendar_id != null)
51
+ writerParams.calendarId = params.calendar_id;
52
+ if (params.location != null)
53
+ writerParams.location = params.location;
54
+ if (params.description != null)
55
+ writerParams.description = params.description;
56
+ if (params.is_all_day != null)
57
+ writerParams.isAllDay = params.is_all_day;
58
+ if (params.recurrence != null) {
59
+ const rec = params.recurrence;
60
+ const recConfig = {
61
+ frequency: rec.pattern.type,
62
+ interval: rec.pattern.interval,
63
+ };
64
+ const mut = recConfig;
65
+ if (rec.pattern.daysOfWeek != null)
66
+ mut.daysOfWeek = rec.pattern.daysOfWeek;
67
+ if (rec.range.type === 'endDate' && rec.range.endDate != null)
68
+ mut.endDate = rec.range.endDate;
69
+ if (rec.range.type === 'numbered' && rec.range.numberOfOccurrences != null)
70
+ mut.endAfterCount = rec.range.numberOfOccurrences;
71
+ writerParams.recurrence = recConfig;
72
+ }
73
+ const created = this.calendarWriter.createEvent(writerParams);
74
+ const result = {
75
+ id: created.id,
76
+ title: params.title,
77
+ start_date: params.start_date,
78
+ end_date: params.end_date,
79
+ calendar_id: created.calendarId,
80
+ location: params.location ?? null,
81
+ description: params.description ?? null,
82
+ is_all_day: params.is_all_day,
83
+ is_recurring: params.recurrence != null,
84
+ };
85
+ return jsonResult(result);
86
+ }
87
+ respondToEvent(params) {
88
+ if (this.calendarManager == null) {
89
+ return {
90
+ content: [{ type: 'text', text: 'Event response is not available' }],
91
+ isError: true,
92
+ };
93
+ }
94
+ const result = this.calendarManager.respondToEvent(params.event_id, params.response, params.send_response, params.comment);
95
+ const responseText = params.response === 'accept'
96
+ ? 'accepted'
97
+ : params.response === 'decline'
98
+ ? 'declined'
99
+ : 'tentatively accepted';
100
+ return {
101
+ content: [{
102
+ type: 'text',
103
+ text: `Successfully ${responseText} event ${result.eventId}`,
104
+ }],
105
+ };
106
+ }
107
+ deleteEvent(params) {
108
+ if (this.calendarManager == null) {
109
+ return {
110
+ content: [{ type: 'text', text: 'Event deletion is not available' }],
111
+ isError: true,
112
+ };
113
+ }
114
+ const applyTo = params.apply_to ?? 'this_instance';
115
+ this.calendarManager.deleteEvent(params.event_id, applyTo);
116
+ const deleteText = applyTo === 'all_in_series' ? ' (entire series)' : '';
117
+ return {
118
+ content: [{
119
+ type: 'text',
120
+ text: `Successfully deleted event ${params.event_id}${deleteText}`,
121
+ }],
122
+ };
123
+ }
124
+ updateEvent(params) {
125
+ if (this.calendarManager == null) {
126
+ return {
127
+ content: [{ type: 'text', text: 'Event update is not available' }],
128
+ isError: true,
129
+ };
130
+ }
131
+ // Validate date ordering if both dates are provided
132
+ if (params.start != null && params.end != null) {
133
+ if (new Date(params.start).getTime() >= new Date(params.end).getTime()) {
134
+ return {
135
+ content: [{ type: 'text', text: 'start_date must be before end_date' }],
136
+ isError: true,
137
+ };
138
+ }
139
+ }
140
+ const updates = {
141
+ ...(params.subject != null && { title: params.subject }),
142
+ ...(params.start != null && { startDate: params.start }),
143
+ ...(params.end != null && { endDate: params.end }),
144
+ ...(params.location != null && { location: params.location }),
145
+ ...(params.body != null && { description: params.body }),
146
+ ...(params.is_all_day != null && { isAllDay: params.is_all_day }),
147
+ };
148
+ const applyTo = params.apply_to ?? 'this_instance';
149
+ const result = this.calendarManager.updateEvent(params.event_id, updates, applyTo);
150
+ const seriesSuffix = applyTo === 'all_in_series' ? ' (entire series)' : '';
151
+ return {
152
+ content: [{
153
+ type: 'text',
154
+ text: `Successfully updated event ${result.id}${seriesSuffix}. Updated fields: ${result.updatedFields.join(', ')}`,
155
+ }],
156
+ };
157
+ }
158
+ }
159
+ //# sourceMappingURL=calendar-apple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-apple.js","sourceRoot":"","sources":["../../src/tools/calendar-apple.ts"],"names":[],"mappings":"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"}