@dizzlkheinz/ynab-mcpb 0.18.4 → 0.19.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 (343) hide show
  1. package/CLAUDE.md +87 -8
  2. package/bin/ynab-mcp-server.cjs +2 -2
  3. package/bin/ynab-mcp-server.js +3 -3
  4. package/biome.json +39 -0
  5. package/dist/bundle/index.cjs +67 -67
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +27 -27
  8. package/dist/server/YNABMCPServer.d.ts +3 -4
  9. package/dist/server/YNABMCPServer.js +111 -116
  10. package/dist/server/budgetResolver.d.ts +6 -5
  11. package/dist/server/budgetResolver.js +46 -36
  12. package/dist/server/cacheKeys.js +6 -6
  13. package/dist/server/cacheManager.js +14 -11
  14. package/dist/server/completions.d.ts +2 -2
  15. package/dist/server/completions.js +20 -15
  16. package/dist/server/config.d.ts +10 -5
  17. package/dist/server/config.js +24 -7
  18. package/dist/server/deltaCache.d.ts +2 -2
  19. package/dist/server/deltaCache.js +22 -16
  20. package/dist/server/deltaCache.merge.d.ts +2 -2
  21. package/dist/server/diagnostics.d.ts +4 -4
  22. package/dist/server/diagnostics.js +38 -32
  23. package/dist/server/errorHandler.d.ts +5 -12
  24. package/dist/server/errorHandler.js +219 -217
  25. package/dist/server/prompts.d.ts +2 -2
  26. package/dist/server/prompts.js +45 -45
  27. package/dist/server/rateLimiter.js +4 -4
  28. package/dist/server/requestLogger.d.ts +1 -1
  29. package/dist/server/requestLogger.js +40 -35
  30. package/dist/server/resources.d.ts +3 -3
  31. package/dist/server/resources.js +55 -52
  32. package/dist/server/responseFormatter.js +6 -6
  33. package/dist/server/securityMiddleware.d.ts +2 -2
  34. package/dist/server/securityMiddleware.js +22 -20
  35. package/dist/server/serverKnowledgeStore.js +1 -1
  36. package/dist/server/toolRegistry.d.ts +3 -3
  37. package/dist/server/toolRegistry.js +47 -40
  38. package/dist/tools/__tests__/deltaTestUtils.d.ts +3 -3
  39. package/dist/tools/__tests__/deltaTestUtils.js +2 -2
  40. package/dist/tools/accountTools.d.ts +9 -8
  41. package/dist/tools/accountTools.js +47 -47
  42. package/dist/tools/adapters.d.ts +13 -8
  43. package/dist/tools/adapters.js +21 -11
  44. package/dist/tools/budgetTools.d.ts +8 -7
  45. package/dist/tools/budgetTools.js +22 -22
  46. package/dist/tools/categoryTools.d.ts +9 -8
  47. package/dist/tools/categoryTools.js +68 -59
  48. package/dist/tools/compareTransactions/formatter.d.ts +3 -3
  49. package/dist/tools/compareTransactions/formatter.js +9 -9
  50. package/dist/tools/compareTransactions/index.d.ts +6 -6
  51. package/dist/tools/compareTransactions/index.js +58 -43
  52. package/dist/tools/compareTransactions/matcher.d.ts +1 -1
  53. package/dist/tools/compareTransactions/matcher.js +28 -15
  54. package/dist/tools/compareTransactions/parser.d.ts +2 -2
  55. package/dist/tools/compareTransactions/parser.js +144 -138
  56. package/dist/tools/compareTransactions/types.d.ts +4 -4
  57. package/dist/tools/compareTransactions.d.ts +1 -1
  58. package/dist/tools/compareTransactions.js +1 -1
  59. package/dist/tools/deltaFetcher.d.ts +2 -2
  60. package/dist/tools/deltaFetcher.js +16 -15
  61. package/dist/tools/deltaSupport.d.ts +4 -4
  62. package/dist/tools/deltaSupport.js +35 -41
  63. package/dist/tools/exportTransactions.d.ts +5 -4
  64. package/dist/tools/exportTransactions.js +61 -59
  65. package/dist/tools/monthTools.d.ts +7 -6
  66. package/dist/tools/monthTools.js +31 -29
  67. package/dist/tools/payeeTools.d.ts +7 -6
  68. package/dist/tools/payeeTools.js +28 -28
  69. package/dist/tools/reconcileAdapter.d.ts +2 -2
  70. package/dist/tools/reconcileAdapter.js +19 -12
  71. package/dist/tools/reconciliation/analyzer.d.ts +4 -4
  72. package/dist/tools/reconciliation/analyzer.js +73 -59
  73. package/dist/tools/reconciliation/csvParser.d.ts +3 -3
  74. package/dist/tools/reconciliation/csvParser.js +128 -104
  75. package/dist/tools/reconciliation/executor.d.ts +4 -4
  76. package/dist/tools/reconciliation/executor.js +148 -109
  77. package/dist/tools/reconciliation/index.d.ts +10 -10
  78. package/dist/tools/reconciliation/index.js +96 -83
  79. package/dist/tools/reconciliation/matcher.d.ts +3 -3
  80. package/dist/tools/reconciliation/matcher.js +17 -16
  81. package/dist/tools/reconciliation/payeeNormalizer.js +19 -8
  82. package/dist/tools/reconciliation/recommendationEngine.d.ts +1 -1
  83. package/dist/tools/reconciliation/recommendationEngine.js +40 -40
  84. package/dist/tools/reconciliation/reportFormatter.d.ts +2 -2
  85. package/dist/tools/reconciliation/reportFormatter.js +59 -58
  86. package/dist/tools/reconciliation/signDetector.d.ts +1 -1
  87. package/dist/tools/reconciliation/types.d.ts +16 -16
  88. package/dist/tools/reconciliation/ynabAdapter.d.ts +2 -2
  89. package/dist/tools/schemas/common.d.ts +1 -1
  90. package/dist/tools/schemas/common.js +1 -1
  91. package/dist/tools/schemas/outputs/accountOutputs.d.ts +1 -1
  92. package/dist/tools/schemas/outputs/accountOutputs.js +24 -18
  93. package/dist/tools/schemas/outputs/budgetOutputs.d.ts +1 -1
  94. package/dist/tools/schemas/outputs/budgetOutputs.js +14 -11
  95. package/dist/tools/schemas/outputs/categoryOutputs.d.ts +1 -1
  96. package/dist/tools/schemas/outputs/categoryOutputs.js +49 -29
  97. package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
  98. package/dist/tools/schemas/outputs/comparisonOutputs.js +12 -12
  99. package/dist/tools/schemas/outputs/index.d.ts +14 -14
  100. package/dist/tools/schemas/outputs/index.js +14 -14
  101. package/dist/tools/schemas/outputs/monthOutputs.d.ts +1 -1
  102. package/dist/tools/schemas/outputs/monthOutputs.js +56 -41
  103. package/dist/tools/schemas/outputs/payeeOutputs.d.ts +1 -1
  104. package/dist/tools/schemas/outputs/payeeOutputs.js +10 -10
  105. package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +2 -2
  106. package/dist/tools/schemas/outputs/reconciliationOutputs.js +45 -45
  107. package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +1 -1
  108. package/dist/tools/schemas/outputs/transactionMutationOutputs.js +28 -22
  109. package/dist/tools/schemas/outputs/transactionOutputs.d.ts +1 -1
  110. package/dist/tools/schemas/outputs/transactionOutputs.js +43 -35
  111. package/dist/tools/schemas/outputs/utilityOutputs.d.ts +1 -1
  112. package/dist/tools/schemas/outputs/utilityOutputs.js +5 -3
  113. package/dist/tools/schemas/shared/commonOutputs.d.ts +1 -1
  114. package/dist/tools/schemas/shared/commonOutputs.js +15 -9
  115. package/dist/tools/transactionReadTools.d.ts +11 -0
  116. package/dist/tools/transactionReadTools.js +202 -0
  117. package/dist/tools/transactionSchemas.d.ts +7 -7
  118. package/dist/tools/transactionSchemas.js +77 -57
  119. package/dist/tools/transactionTools.d.ts +6 -24
  120. package/dist/tools/transactionTools.js +7 -1499
  121. package/dist/tools/transactionUtils.d.ts +6 -6
  122. package/dist/tools/transactionUtils.js +78 -63
  123. package/dist/tools/transactionWriteTools.d.ts +20 -0
  124. package/dist/tools/transactionWriteTools.js +1342 -0
  125. package/dist/tools/utilityTools.d.ts +5 -4
  126. package/dist/tools/utilityTools.js +11 -11
  127. package/dist/types/index.d.ts +7 -7
  128. package/dist/types/index.js +6 -6
  129. package/dist/types/reconciliation.d.ts +1 -1
  130. package/dist/types/toolRegistration.d.ts +14 -12
  131. package/dist/utils/amountUtils.js +1 -1
  132. package/dist/utils/dateUtils.js +4 -4
  133. package/dist/utils/errors.d.ts +3 -3
  134. package/dist/utils/errors.js +4 -4
  135. package/dist/utils/money.d.ts +2 -2
  136. package/dist/utils/money.js +8 -8
  137. package/dist/utils/validationError.d.ts +1 -1
  138. package/dist/utils/validationError.js +1 -1
  139. package/docs/assets/examples/reconciliation-with-recommendations.json +66 -66
  140. package/docs/assets/schemas/reconciliation-v2.json +360 -336
  141. package/esbuild.config.mjs +53 -50
  142. package/meta.json +12548 -12548
  143. package/package.json +98 -111
  144. package/scripts/analyze-bundle.mjs +33 -30
  145. package/scripts/create-pr-description.js +169 -120
  146. package/scripts/run-all-tests.js +178 -169
  147. package/scripts/run-domain-integration-tests.js +28 -18
  148. package/scripts/run-generate-mcpb.js +19 -17
  149. package/scripts/run-throttled-integration-tests.js +92 -83
  150. package/scripts/test-delta-params.mjs +149 -120
  151. package/scripts/test-recommendations.ts +36 -32
  152. package/scripts/tmpTransaction.ts +80 -43
  153. package/scripts/validate-env.js +98 -91
  154. package/scripts/verify-build.js +78 -76
  155. package/src/__tests__/comprehensive.integration.test.ts +1281 -1154
  156. package/src/__tests__/performance.test.ts +723 -671
  157. package/src/__tests__/setup.ts +442 -395
  158. package/src/__tests__/smoke.e2e.test.ts +41 -39
  159. package/src/__tests__/testRunner.ts +314 -295
  160. package/src/__tests__/testUtils.ts +456 -364
  161. package/src/__tests__/tools/reconciliation/csvParser.integration.test.ts +109 -107
  162. package/src/__tests__/tools/reconciliation/real-world.integration.test.ts +41 -41
  163. package/src/index.ts +68 -59
  164. package/src/server/CLAUDE.md +480 -0
  165. package/src/server/YNABMCPServer.ts +821 -794
  166. package/src/server/__tests__/YNABMCPServer.integration.test.ts +929 -893
  167. package/src/server/__tests__/YNABMCPServer.test.ts +903 -899
  168. package/src/server/__tests__/budgetResolver.test.ts +466 -423
  169. package/src/server/__tests__/cacheManager.test.ts +891 -874
  170. package/src/server/__tests__/completions.integration.test.ts +115 -106
  171. package/src/server/__tests__/completions.test.ts +334 -313
  172. package/src/server/__tests__/config.test.ts +98 -86
  173. package/src/server/__tests__/deltaCache.merge.test.ts +774 -703
  174. package/src/server/__tests__/deltaCache.swr.test.ts +198 -153
  175. package/src/server/__tests__/deltaCache.test.ts +946 -759
  176. package/src/server/__tests__/diagnostics.test.ts +825 -792
  177. package/src/server/__tests__/errorHandler.integration.test.ts +512 -462
  178. package/src/server/__tests__/errorHandler.test.ts +402 -397
  179. package/src/server/__tests__/prompts.test.ts +424 -347
  180. package/src/server/__tests__/rateLimiter.test.ts +313 -309
  181. package/src/server/__tests__/requestLogger.test.ts +443 -403
  182. package/src/server/__tests__/resources.template.test.ts +196 -185
  183. package/src/server/__tests__/resources.test.ts +294 -288
  184. package/src/server/__tests__/security.integration.test.ts +487 -421
  185. package/src/server/__tests__/securityMiddleware.test.ts +519 -444
  186. package/src/server/__tests__/server-startup.integration.test.ts +509 -490
  187. package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -173
  188. package/src/server/__tests__/toolRegistration.test.ts +239 -210
  189. package/src/server/__tests__/toolRegistry.test.ts +907 -845
  190. package/src/server/budgetResolver.ts +221 -181
  191. package/src/server/cacheKeys.ts +6 -6
  192. package/src/server/cacheManager.ts +498 -484
  193. package/src/server/completions.ts +267 -243
  194. package/src/server/config.ts +35 -14
  195. package/src/server/deltaCache.merge.ts +146 -128
  196. package/src/server/deltaCache.ts +352 -309
  197. package/src/server/diagnostics.ts +257 -242
  198. package/src/server/errorHandler.ts +747 -744
  199. package/src/server/prompts.ts +181 -176
  200. package/src/server/rateLimiter.ts +131 -129
  201. package/src/server/requestLogger.ts +350 -322
  202. package/src/server/resources.ts +442 -374
  203. package/src/server/responseFormatter.ts +41 -37
  204. package/src/server/securityMiddleware.ts +223 -205
  205. package/src/server/serverKnowledgeStore.ts +67 -67
  206. package/src/server/toolRegistry.ts +508 -474
  207. package/src/tools/CLAUDE.md +604 -0
  208. package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -111
  209. package/src/tools/__tests__/accountTools.integration.test.ts +129 -111
  210. package/src/tools/__tests__/accountTools.test.ts +685 -638
  211. package/src/tools/__tests__/adapters.test.ts +142 -108
  212. package/src/tools/__tests__/budgetTools.delta.integration.test.ts +73 -73
  213. package/src/tools/__tests__/budgetTools.integration.test.ts +132 -124
  214. package/src/tools/__tests__/budgetTools.test.ts +442 -413
  215. package/src/tools/__tests__/categoryTools.delta.integration.test.ts +76 -68
  216. package/src/tools/__tests__/categoryTools.integration.test.ts +314 -288
  217. package/src/tools/__tests__/categoryTools.test.ts +656 -625
  218. package/src/tools/__tests__/compareTransactions/formatter.test.ts +535 -462
  219. package/src/tools/__tests__/compareTransactions/index.test.ts +378 -358
  220. package/src/tools/__tests__/compareTransactions/matcher.test.ts +497 -398
  221. package/src/tools/__tests__/compareTransactions/parser.test.ts +765 -747
  222. package/src/tools/__tests__/compareTransactions.test.ts +352 -332
  223. package/src/tools/__tests__/compareTransactions.window.test.ts +150 -146
  224. package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +69 -65
  225. package/src/tools/__tests__/deltaFetcher.test.ts +325 -265
  226. package/src/tools/__tests__/deltaSupport.test.ts +211 -184
  227. package/src/tools/__tests__/deltaTestUtils.ts +37 -33
  228. package/src/tools/__tests__/exportTransactions.test.ts +205 -200
  229. package/src/tools/__tests__/monthTools.delta.integration.test.ts +68 -68
  230. package/src/tools/__tests__/monthTools.integration.test.ts +178 -166
  231. package/src/tools/__tests__/monthTools.test.ts +561 -512
  232. package/src/tools/__tests__/payeeTools.delta.integration.test.ts +68 -68
  233. package/src/tools/__tests__/payeeTools.integration.test.ts +158 -142
  234. package/src/tools/__tests__/payeeTools.test.ts +486 -434
  235. package/src/tools/__tests__/transactionSchemas.test.ts +1202 -1186
  236. package/src/tools/__tests__/transactionTools.integration.test.ts +875 -825
  237. package/src/tools/__tests__/transactionTools.test.ts +4923 -4366
  238. package/src/tools/__tests__/transactionUtils.test.ts +1004 -977
  239. package/src/tools/__tests__/utilityTools.integration.test.ts +32 -32
  240. package/src/tools/__tests__/utilityTools.test.ts +68 -58
  241. package/src/tools/accountTools.ts +293 -271
  242. package/src/tools/adapters.ts +120 -63
  243. package/src/tools/budgetTools.ts +121 -116
  244. package/src/tools/categoryTools.ts +379 -339
  245. package/src/tools/compareTransactions/formatter.ts +131 -119
  246. package/src/tools/compareTransactions/index.ts +249 -214
  247. package/src/tools/compareTransactions/matcher.ts +259 -209
  248. package/src/tools/compareTransactions/parser.ts +517 -487
  249. package/src/tools/compareTransactions/types.ts +38 -38
  250. package/src/tools/compareTransactions.ts +1 -1
  251. package/src/tools/deltaFetcher.ts +281 -260
  252. package/src/tools/deltaSupport.ts +264 -259
  253. package/src/tools/exportTransactions.ts +230 -218
  254. package/src/tools/monthTools.ts +180 -165
  255. package/src/tools/payeeTools.ts +152 -140
  256. package/src/tools/reconcileAdapter.ts +297 -252
  257. package/src/tools/reconciliation/CLAUDE.md +506 -0
  258. package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +133 -124
  259. package/src/tools/reconciliation/__tests__/adapter.test.ts +249 -230
  260. package/src/tools/reconciliation/__tests__/analyzer.test.ts +408 -400
  261. package/src/tools/reconciliation/__tests__/csvParser.test.ts +71 -69
  262. package/src/tools/reconciliation/__tests__/executor.integration.test.ts +348 -323
  263. package/src/tools/reconciliation/__tests__/executor.progress.test.ts +503 -457
  264. package/src/tools/reconciliation/__tests__/executor.test.ts +898 -831
  265. package/src/tools/reconciliation/__tests__/matcher.test.ts +667 -663
  266. package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +296 -276
  267. package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +692 -624
  268. package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1008 -989
  269. package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +187 -146
  270. package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +583 -533
  271. package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +75 -74
  272. package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +70 -62
  273. package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +102 -88
  274. package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +56 -55
  275. package/src/tools/reconciliation/__tests__/signDetector.test.ts +209 -206
  276. package/src/tools/reconciliation/__tests__/ynabAdapter.test.ts +66 -60
  277. package/src/tools/reconciliation/analyzer.ts +564 -504
  278. package/src/tools/reconciliation/csvParser.ts +656 -609
  279. package/src/tools/reconciliation/executor.ts +1290 -1128
  280. package/src/tools/reconciliation/index.ts +580 -528
  281. package/src/tools/reconciliation/matcher.ts +256 -240
  282. package/src/tools/reconciliation/payeeNormalizer.ts +92 -78
  283. package/src/tools/reconciliation/recommendationEngine.ts +357 -345
  284. package/src/tools/reconciliation/reportFormatter.ts +343 -307
  285. package/src/tools/reconciliation/signDetector.ts +89 -83
  286. package/src/tools/reconciliation/types.ts +164 -159
  287. package/src/tools/reconciliation/ynabAdapter.ts +17 -15
  288. package/src/tools/schemas/CLAUDE.md +546 -0
  289. package/src/tools/schemas/common.ts +1 -1
  290. package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +410 -409
  291. package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +305 -299
  292. package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +431 -430
  293. package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +510 -495
  294. package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +179 -153
  295. package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +293 -254
  296. package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +457 -457
  297. package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +362 -356
  298. package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +402 -399
  299. package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +225 -211
  300. package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +457 -454
  301. package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +316 -315
  302. package/src/tools/schemas/outputs/accountOutputs.ts +40 -34
  303. package/src/tools/schemas/outputs/budgetOutputs.ts +24 -19
  304. package/src/tools/schemas/outputs/categoryOutputs.ts +76 -56
  305. package/src/tools/schemas/outputs/comparisonOutputs.ts +192 -169
  306. package/src/tools/schemas/outputs/index.ts +163 -163
  307. package/src/tools/schemas/outputs/monthOutputs.ts +95 -80
  308. package/src/tools/schemas/outputs/payeeOutputs.ts +18 -18
  309. package/src/tools/schemas/outputs/reconciliationOutputs.ts +386 -373
  310. package/src/tools/schemas/outputs/transactionMutationOutputs.ts +259 -231
  311. package/src/tools/schemas/outputs/transactionOutputs.ts +81 -71
  312. package/src/tools/schemas/outputs/utilityOutputs.ts +90 -84
  313. package/src/tools/schemas/shared/commonOutputs.ts +27 -19
  314. package/src/tools/toolCategories.ts +114 -114
  315. package/src/tools/transactionReadTools.ts +327 -0
  316. package/src/tools/transactionSchemas.ts +322 -291
  317. package/src/tools/transactionTools.ts +84 -2246
  318. package/src/tools/transactionUtils.ts +507 -422
  319. package/src/tools/transactionWriteTools.ts +2110 -0
  320. package/src/tools/utilityTools.ts +46 -41
  321. package/src/types/CLAUDE.md +477 -0
  322. package/src/types/__tests__/index.test.ts +51 -51
  323. package/src/types/index.ts +43 -39
  324. package/src/types/integration-tests.d.ts +26 -26
  325. package/src/types/reconciliation.ts +29 -29
  326. package/src/types/toolAnnotations.ts +30 -30
  327. package/src/types/toolRegistration.ts +43 -32
  328. package/src/utils/CLAUDE.md +508 -0
  329. package/src/utils/__tests__/dateUtils.test.ts +174 -168
  330. package/src/utils/__tests__/money.test.ts +193 -187
  331. package/src/utils/amountUtils.ts +5 -5
  332. package/src/utils/baseError.ts +5 -5
  333. package/src/utils/dateUtils.ts +29 -26
  334. package/src/utils/errors.ts +14 -14
  335. package/src/utils/money.ts +66 -52
  336. package/src/utils/validationError.ts +1 -1
  337. package/tsconfig.json +29 -29
  338. package/tsconfig.prod.json +16 -16
  339. package/vitest-reporters/split-json-reporter.ts +247 -204
  340. package/vitest.config.ts +99 -95
  341. package/.prettierignore +0 -10
  342. package/.prettierrc.json +0 -10
  343. package/eslint.config.js +0 -49
@@ -44,7 +44,7 @@
44
44
  * }
45
45
  */
46
46
 
47
- import { z } from 'zod';
47
+ import { z } from "zod";
48
48
 
49
49
  // ============================================================================
50
50
  // DATE VALIDATION HELPERS
@@ -71,26 +71,26 @@ import { z } from 'zod';
71
71
  * isValidISODate("2024-02-31") // false (February doesn't have 31 days)
72
72
  */
73
73
  function isValidISODate(dateStr: string): boolean {
74
- // First check format
75
- if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
76
- return false;
77
- }
78
-
79
- // Parse and validate
80
- const parsed = Date.parse(dateStr);
81
- if (isNaN(parsed)) {
82
- return false;
83
- }
84
-
85
- // Verify that the parsed date components match the original string
86
- // This catches cases like "2024-02-31" which Date.parse might coerce to "2024-03-03"
87
- const date = new Date(parsed);
88
- const year = date.getUTCFullYear();
89
- const month = String(date.getUTCMonth() + 1).padStart(2, '0');
90
- const day = String(date.getUTCDate()).padStart(2, '0');
91
- const reconstructed = `${year}-${month}-${day}`;
92
-
93
- return reconstructed === dateStr;
74
+ // First check format
75
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
76
+ return false;
77
+ }
78
+
79
+ // Parse and validate
80
+ const parsed = Date.parse(dateStr);
81
+ if (Number.isNaN(parsed)) {
82
+ return false;
83
+ }
84
+
85
+ // Verify that the parsed date components match the original string
86
+ // This catches cases like "2024-02-31" which Date.parse might coerce to "2024-03-03"
87
+ const date = new Date(parsed);
88
+ const year = date.getUTCFullYear();
89
+ const month = String(date.getUTCMonth() + 1).padStart(2, "0");
90
+ const day = String(date.getUTCDate()).padStart(2, "0");
91
+ const reconstructed = `${year}-${month}-${day}`;
92
+
93
+ return reconstructed === dateStr;
94
94
  }
95
95
  /**
96
96
  * Reusable Zod schema for validating ISO date strings (YYYY-MM-DD).
@@ -102,11 +102,12 @@ function isValidISODate(dateStr: string): boolean {
102
102
  * schema.parse({ date: "2024-02-31" }); // Error: Invalid calendar date
103
103
  */
104
104
  export const ISODateStringSchema = z
105
- .string()
106
- .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format')
107
- .refine(isValidISODate, {
108
- message: 'Invalid calendar date (e.g., month must be 01-12, day must be valid for the month)',
109
- });
105
+ .string()
106
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format")
107
+ .refine(isValidISODate, {
108
+ message:
109
+ "Invalid calendar date (e.g., month must be 01-12, day must be valid for the month)",
110
+ });
110
111
 
111
112
  // ============================================================================
112
113
  // NESTED SCHEMAS FOR COMPOSITION
@@ -123,15 +124,18 @@ export const ISODateStringSchema = z
123
124
  * @see src/tools/compareTransactions/formatter.ts:92-102 - formatUnmatchedBank function
124
125
  */
125
126
  export const MissingInYNABItemSchema = z.object({
126
- date: ISODateStringSchema,
127
- amount: z
128
- .string()
129
- .regex(/^-?\d+\.\d{2}$/, 'Amount must be a decimal string with exactly 2 decimal places'),
130
- description: z.string(),
131
- row_number: z.number(),
132
- suggested_payee_id: z.string().optional(),
133
- suggested_payee_name: z.string().optional(),
134
- suggestion_reason: z.string().optional(),
127
+ date: ISODateStringSchema,
128
+ amount: z
129
+ .string()
130
+ .regex(
131
+ /^-?\d+\.\d{2}$/,
132
+ "Amount must be a decimal string with exactly 2 decimal places",
133
+ ),
134
+ description: z.string(),
135
+ row_number: z.number(),
136
+ suggested_payee_id: z.string().optional(),
137
+ suggested_payee_name: z.string().optional(),
138
+ suggestion_reason: z.string().optional(),
135
139
  });
136
140
 
137
141
  export type MissingInYNABItem = z.infer<typeof MissingInYNABItemSchema>;
@@ -147,14 +151,17 @@ export type MissingInYNABItem = z.infer<typeof MissingInYNABItemSchema>;
147
151
  * @see src/tools/compareTransactions/formatter.ts:108-116 - formatUnmatchedYNAB function
148
152
  */
149
153
  export const MissingInBankItemSchema = z.object({
150
- id: z.string(),
151
- date: ISODateStringSchema,
152
- amount: z
153
- .string()
154
- .regex(/^-?\d+\.\d{2}$/, 'Amount must be a decimal string with exactly 2 decimal places'),
155
- payee_name: z.string().nullable(),
156
- memo: z.string().nullable(),
157
- cleared: z.string(),
154
+ id: z.string(),
155
+ date: ISODateStringSchema,
156
+ amount: z
157
+ .string()
158
+ .regex(
159
+ /^-?\d+\.\d{2}$/,
160
+ "Amount must be a decimal string with exactly 2 decimal places",
161
+ ),
162
+ payee_name: z.string().nullable(),
163
+ memo: z.string().nullable(),
164
+ cleared: z.string(),
158
165
  });
159
166
 
160
167
  export type MissingInBankItem = z.infer<typeof MissingInBankItemSchema>;
@@ -170,22 +177,28 @@ export type MissingInBankItem = z.infer<typeof MissingInBankItemSchema>;
170
177
  * @see src/tools/compareTransactions/formatter.ts:72-86 - formatMatches function
171
178
  */
172
179
  export const MatchItemSchema = z.object({
173
- bank_date: ISODateStringSchema,
174
- bank_amount: z
175
- .string()
176
- .regex(/^-?\d+\.\d{2}$/, 'Amount must be a decimal string with exactly 2 decimal places'),
177
- bank_description: z.string(),
178
- ynab_date: ISODateStringSchema,
179
- ynab_amount: z
180
- .string()
181
- .regex(/^-?\d+\.\d{2}$/, 'Amount must be a decimal string with exactly 2 decimal places'),
182
- ynab_payee: z.string().nullable(),
183
- ynab_transaction: z.object({
184
- id: z.string(),
185
- cleared: z.string(),
186
- }),
187
- match_score: z.number(),
188
- match_reasons: z.array(z.string()),
180
+ bank_date: ISODateStringSchema,
181
+ bank_amount: z
182
+ .string()
183
+ .regex(
184
+ /^-?\d+\.\d{2}$/,
185
+ "Amount must be a decimal string with exactly 2 decimal places",
186
+ ),
187
+ bank_description: z.string(),
188
+ ynab_date: ISODateStringSchema,
189
+ ynab_amount: z
190
+ .string()
191
+ .regex(
192
+ /^-?\d+\.\d{2}$/,
193
+ "Amount must be a decimal string with exactly 2 decimal places",
194
+ ),
195
+ ynab_payee: z.string().nullable(),
196
+ ynab_transaction: z.object({
197
+ id: z.string(),
198
+ cleared: z.string(),
199
+ }),
200
+ match_score: z.number(),
201
+ match_reasons: z.array(z.string()),
189
202
  });
190
203
 
191
204
  export type MatchItem = z.infer<typeof MatchItemSchema>;
@@ -208,15 +221,17 @@ export type MatchItem = z.infer<typeof MatchItemSchema>;
208
221
  * @internal
209
222
  */
210
223
  export const BankTransactionComparisonSchema = z.object({
211
- date: ISODateStringSchema,
212
- amount: z.number(),
213
- description: z.string(),
214
- raw_amount: z.string(),
215
- raw_date: z.string(),
216
- row_number: z.number(),
224
+ date: ISODateStringSchema,
225
+ amount: z.number(),
226
+ description: z.string(),
227
+ raw_amount: z.string(),
228
+ raw_date: z.string(),
229
+ row_number: z.number(),
217
230
  });
218
231
 
219
- export type BankTransactionComparison = z.infer<typeof BankTransactionComparisonSchema>;
232
+ export type BankTransactionComparison = z.infer<
233
+ typeof BankTransactionComparisonSchema
234
+ >;
220
235
 
221
236
  /**
222
237
  * YNAB transaction (internal type, used during matching).
@@ -232,17 +247,19 @@ export type BankTransactionComparison = z.infer<typeof BankTransactionComparison
232
247
  * @internal
233
248
  */
234
249
  export const YNABTransactionComparisonSchema = z.object({
235
- id: z.string(),
236
- date: ISODateStringSchema,
237
- amount: z.number(),
238
- payee_name: z.string().nullable(),
239
- memo: z.string().nullable(),
240
- cleared: z.string(),
241
- account_name: z.string().optional(),
242
- category_name: z.string().optional(),
250
+ id: z.string(),
251
+ date: ISODateStringSchema,
252
+ amount: z.number(),
253
+ payee_name: z.string().nullable(),
254
+ memo: z.string().nullable(),
255
+ cleared: z.string(),
256
+ account_name: z.string().optional(),
257
+ category_name: z.string().optional(),
243
258
  });
244
259
 
245
- export type YNABTransactionComparison = z.infer<typeof YNABTransactionComparisonSchema>;
260
+ export type YNABTransactionComparison = z.infer<
261
+ typeof YNABTransactionComparisonSchema
262
+ >;
246
263
 
247
264
  /**
248
265
  * Matched transaction pair (internal type, used during matching).
@@ -258,21 +275,23 @@ export type YNABTransactionComparison = z.infer<typeof YNABTransactionComparison
258
275
  * @internal
259
276
  */
260
277
  export const TransactionMatchComparisonSchema = z.object({
261
- bank_transaction: BankTransactionComparisonSchema,
262
- ynab_transaction: YNABTransactionComparisonSchema,
263
- match_score: z.number().min(0).max(100),
264
- match_reasons: z.array(z.string()),
278
+ bank_transaction: BankTransactionComparisonSchema,
279
+ ynab_transaction: YNABTransactionComparisonSchema,
280
+ match_score: z.number().min(0).max(100),
281
+ match_reasons: z.array(z.string()),
265
282
  });
266
283
 
267
- export type TransactionMatchComparison = z.infer<typeof TransactionMatchComparisonSchema>;
284
+ export type TransactionMatchComparison = z.infer<
285
+ typeof TransactionMatchComparisonSchema
286
+ >;
268
287
 
269
288
  /**
270
289
  * Comparison configuration parameters.
271
290
  * Documents tolerance settings used for matching.
272
291
  */
273
292
  export const ComparisonParametersSchema = z.object({
274
- amount_tolerance: z.number().optional(),
275
- date_tolerance_days: z.number().optional(),
293
+ amount_tolerance: z.number().optional(),
294
+ date_tolerance_days: z.number().optional(),
276
295
  });
277
296
 
278
297
  export type ComparisonParameters = z.infer<typeof ComparisonParametersSchema>;
@@ -291,23 +310,23 @@ export type ComparisonParameters = z.infer<typeof ComparisonParametersSchema>;
291
310
  * DateRangeSchema.parse({ start: "2024-12-31", end: "2024-01-01" }) // Error: start date must be before or equal to end date
292
311
  */
293
312
  export const DateRangeSchema = z
294
- .object({
295
- start: ISODateStringSchema,
296
- end: ISODateStringSchema,
297
- })
298
- .refine(
299
- (data) => {
300
- // Parse both dates - we know they're valid ISO dates due to ISODateStringSchema
301
- const startDate = Date.parse(data.start);
302
- const endDate = Date.parse(data.end);
303
-
304
- // Validate logical ordering: start must be <= end
305
- return startDate <= endDate;
306
- },
307
- {
308
- message: 'Start date must be before or equal to end date',
309
- },
310
- );
313
+ .object({
314
+ start: ISODateStringSchema,
315
+ end: ISODateStringSchema,
316
+ })
317
+ .refine(
318
+ (data) => {
319
+ // Parse both dates - we know they're valid ISO dates due to ISODateStringSchema
320
+ const startDate = Date.parse(data.start);
321
+ const endDate = Date.parse(data.end);
322
+
323
+ // Validate logical ordering: start must be <= end
324
+ return startDate <= endDate;
325
+ },
326
+ {
327
+ message: "Start date must be before or equal to end date",
328
+ },
329
+ );
311
330
 
312
331
  export type DateRange = z.infer<typeof DateRangeSchema>;
313
332
 
@@ -322,16 +341,16 @@ export type DateRange = z.infer<typeof DateRangeSchema>;
322
341
  * @see src/tools/exportTransactions.ts:184-197 - Export info construction
323
342
  */
324
343
  export const ExportInfoSchema = z.object({
325
- exported_at: z.string(),
326
- total_transactions: z.number(),
327
- minimal: z.boolean(),
328
- filters: z.object({
329
- budget_id: z.string().optional(),
330
- account_id: z.string().nullable(),
331
- category_id: z.string().nullable(),
332
- since_date: z.string().nullable(),
333
- type: z.string().nullable(),
334
- }),
344
+ exported_at: z.string(),
345
+ total_transactions: z.number(),
346
+ minimal: z.boolean(),
347
+ filters: z.object({
348
+ budget_id: z.string().optional(),
349
+ account_id: z.string().nullable(),
350
+ category_id: z.string().nullable(),
351
+ since_date: z.string().nullable(),
352
+ type: z.string().nullable(),
353
+ }),
335
354
  });
336
355
 
337
356
  export type ExportInfo = z.infer<typeof ExportInfoSchema>;
@@ -352,37 +371,37 @@ export type ExportInfo = z.infer<typeof ExportInfoSchema>;
352
371
  * @see src/tools/exportTransactions.ts:204 - Amount field directly from transaction.amount (milliunits)
353
372
  */
354
373
  export const ExportedTransactionMinimalSchema = z.object({
355
- id: z.string(),
356
- date: z.string(),
357
- amount: z.number(), // Raw YNAB milliunits
358
- payee_name: z.string().nullable(),
359
- cleared: z.string(),
374
+ id: z.string(),
375
+ date: z.string(),
376
+ amount: z.number(), // Raw YNAB milliunits
377
+ payee_name: z.string().nullable(),
378
+ cleared: z.string(),
360
379
  });
361
380
 
362
381
  export const ExportedTransactionFullSchema = z.object({
363
- id: z.string(),
364
- date: z.string(),
365
- amount: z.number(), // Raw YNAB milliunits
366
- memo: z.string().nullable(),
367
- cleared: z.string(),
368
- approved: z.boolean(),
369
- flag_color: z.string().nullable(),
370
- account_id: z.string(),
371
- payee_id: z.string().nullable(),
372
- category_id: z.string().nullable(),
373
- transfer_account_id: z.string().nullable(),
374
- transfer_transaction_id: z.string().nullable(),
375
- matched_transaction_id: z.string().nullable(),
376
- import_id: z.string().nullable(),
377
- deleted: z.boolean(),
378
- account_name: z.string().optional(),
379
- payee_name: z.string().nullable(),
380
- category_name: z.string().nullable(),
382
+ id: z.string(),
383
+ date: z.string(),
384
+ amount: z.number(), // Raw YNAB milliunits
385
+ memo: z.string().nullable(),
386
+ cleared: z.string(),
387
+ approved: z.boolean(),
388
+ flag_color: z.string().nullable(),
389
+ account_id: z.string(),
390
+ payee_id: z.string().nullable(),
391
+ category_id: z.string().nullable(),
392
+ transfer_account_id: z.string().nullable(),
393
+ transfer_transaction_id: z.string().nullable(),
394
+ matched_transaction_id: z.string().nullable(),
395
+ import_id: z.string().nullable(),
396
+ deleted: z.boolean(),
397
+ account_name: z.string().optional(),
398
+ payee_name: z.string().nullable(),
399
+ category_name: z.string().nullable(),
381
400
  });
382
401
 
383
402
  export const ExportedTransactionSchema = z.union([
384
- ExportedTransactionMinimalSchema,
385
- ExportedTransactionFullSchema,
403
+ ExportedTransactionMinimalSchema,
404
+ ExportedTransactionFullSchema,
386
405
  ]);
387
406
 
388
407
  export type ExportedTransaction = z.infer<typeof ExportedTransactionSchema>;
@@ -449,8 +468,8 @@ export type ExportedTransaction = z.infer<typeof ExportedTransactionSchema>;
449
468
  * }
450
469
  */
451
470
  export const ExportFileSchema = z.object({
452
- export_info: ExportInfoSchema,
453
- transactions: z.array(ExportedTransactionSchema),
471
+ export_info: ExportInfoSchema,
472
+ transactions: z.array(ExportedTransactionSchema),
454
473
  });
455
474
 
456
475
  export type ExportFile = z.infer<typeof ExportFileSchema>;
@@ -513,21 +532,23 @@ export type ExportFile = z.infer<typeof ExportFileSchema>;
513
532
  * }
514
533
  */
515
534
  export const CompareTransactionsOutputSchema = z.object({
516
- summary: z.object({
517
- bank_transactions_count: z.number(),
518
- ynab_transactions_count: z.number(),
519
- matches_found: z.number(),
520
- missing_in_ynab: z.number(),
521
- missing_in_bank: z.number(),
522
- date_range: DateRangeSchema,
523
- parameters: ComparisonParametersSchema,
524
- }),
525
- matches: z.array(MatchItemSchema),
526
- missing_in_ynab: z.array(MissingInYNABItemSchema),
527
- missing_in_bank: z.array(MissingInBankItemSchema),
535
+ summary: z.object({
536
+ bank_transactions_count: z.number(),
537
+ ynab_transactions_count: z.number(),
538
+ matches_found: z.number(),
539
+ missing_in_ynab: z.number(),
540
+ missing_in_bank: z.number(),
541
+ date_range: DateRangeSchema,
542
+ parameters: ComparisonParametersSchema,
543
+ }),
544
+ matches: z.array(MatchItemSchema),
545
+ missing_in_ynab: z.array(MissingInYNABItemSchema),
546
+ missing_in_bank: z.array(MissingInBankItemSchema),
528
547
  });
529
548
 
530
- export type CompareTransactionsOutput = z.infer<typeof CompareTransactionsOutputSchema>;
549
+ export type CompareTransactionsOutput = z.infer<
550
+ typeof CompareTransactionsOutputSchema
551
+ >;
531
552
 
532
553
  /**
533
554
  * Transaction export tool response (MCP tool result).
@@ -576,25 +597,27 @@ export type CompareTransactionsOutput = z.infer<typeof CompareTransactionsOutput
576
597
  * }
577
598
  */
578
599
  export const ExportTransactionsOutputSchema = z.object({
579
- message: z.string(),
580
- filename: z.string(),
581
- full_path: z.string(),
582
- export_directory: z.string(),
583
- export_mode: z.enum(['minimal', 'full']),
584
- minimal_fields: z.string().nullable(),
585
- filename_explanation: z.string(),
586
- preview_count: z.number(),
587
- total_count: z.number(),
588
- preview_transactions: z.array(
589
- z.object({
590
- id: z.string(),
591
- date: z.string(),
592
- amount: z.number(), // Raw YNAB milliunits
593
- memo: z.string().nullable().optional(),
594
- payee_name: z.string().nullable().optional(),
595
- category_name: z.string().nullable().optional(),
596
- }),
597
- ),
600
+ message: z.string(),
601
+ filename: z.string(),
602
+ full_path: z.string(),
603
+ export_directory: z.string(),
604
+ export_mode: z.enum(["minimal", "full"]),
605
+ minimal_fields: z.string().nullable(),
606
+ filename_explanation: z.string(),
607
+ preview_count: z.number(),
608
+ total_count: z.number(),
609
+ preview_transactions: z.array(
610
+ z.object({
611
+ id: z.string(),
612
+ date: z.string(),
613
+ amount: z.number(), // Raw YNAB milliunits
614
+ memo: z.string().nullable().optional(),
615
+ payee_name: z.string().nullable().optional(),
616
+ category_name: z.string().nullable().optional(),
617
+ }),
618
+ ),
598
619
  });
599
620
 
600
- export type ExportTransactionsOutput = z.infer<typeof ExportTransactionsOutputSchema>;
621
+ export type ExportTransactionsOutput = z.infer<
622
+ typeof ExportTransactionsOutputSchema
623
+ >;