@dizzlkheinz/ynab-mcpb 0.18.3 → 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 (346) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/CLAUDE.md +87 -8
  3. package/bin/ynab-mcp-server.cjs +2 -2
  4. package/bin/ynab-mcp-server.js +3 -3
  5. package/biome.json +39 -0
  6. package/dist/bundle/index.cjs +67 -67
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +27 -27
  9. package/dist/server/YNABMCPServer.d.ts +3 -4
  10. package/dist/server/YNABMCPServer.js +111 -116
  11. package/dist/server/budgetResolver.d.ts +6 -5
  12. package/dist/server/budgetResolver.js +46 -36
  13. package/dist/server/cacheKeys.js +6 -6
  14. package/dist/server/cacheManager.js +14 -11
  15. package/dist/server/completions.d.ts +2 -2
  16. package/dist/server/completions.js +20 -15
  17. package/dist/server/config.d.ts +10 -5
  18. package/dist/server/config.js +24 -7
  19. package/dist/server/deltaCache.d.ts +2 -2
  20. package/dist/server/deltaCache.js +22 -16
  21. package/dist/server/deltaCache.merge.d.ts +2 -2
  22. package/dist/server/diagnostics.d.ts +4 -4
  23. package/dist/server/diagnostics.js +38 -32
  24. package/dist/server/errorHandler.d.ts +5 -12
  25. package/dist/server/errorHandler.js +219 -217
  26. package/dist/server/prompts.d.ts +2 -2
  27. package/dist/server/prompts.js +45 -45
  28. package/dist/server/rateLimiter.js +4 -4
  29. package/dist/server/requestLogger.d.ts +1 -1
  30. package/dist/server/requestLogger.js +40 -35
  31. package/dist/server/resources.d.ts +3 -3
  32. package/dist/server/resources.js +55 -52
  33. package/dist/server/responseFormatter.js +6 -6
  34. package/dist/server/securityMiddleware.d.ts +2 -2
  35. package/dist/server/securityMiddleware.js +22 -20
  36. package/dist/server/serverKnowledgeStore.js +1 -1
  37. package/dist/server/toolRegistry.d.ts +3 -3
  38. package/dist/server/toolRegistry.js +47 -40
  39. package/dist/tools/__tests__/deltaTestUtils.d.ts +3 -3
  40. package/dist/tools/__tests__/deltaTestUtils.js +2 -2
  41. package/dist/tools/accountTools.d.ts +9 -8
  42. package/dist/tools/accountTools.js +47 -47
  43. package/dist/tools/adapters.d.ts +13 -8
  44. package/dist/tools/adapters.js +21 -11
  45. package/dist/tools/budgetTools.d.ts +8 -7
  46. package/dist/tools/budgetTools.js +22 -22
  47. package/dist/tools/categoryTools.d.ts +9 -8
  48. package/dist/tools/categoryTools.js +68 -59
  49. package/dist/tools/compareTransactions/formatter.d.ts +3 -3
  50. package/dist/tools/compareTransactions/formatter.js +9 -9
  51. package/dist/tools/compareTransactions/index.d.ts +6 -6
  52. package/dist/tools/compareTransactions/index.js +58 -43
  53. package/dist/tools/compareTransactions/matcher.d.ts +1 -1
  54. package/dist/tools/compareTransactions/matcher.js +28 -15
  55. package/dist/tools/compareTransactions/parser.d.ts +2 -2
  56. package/dist/tools/compareTransactions/parser.js +144 -138
  57. package/dist/tools/compareTransactions/types.d.ts +4 -4
  58. package/dist/tools/compareTransactions.d.ts +1 -1
  59. package/dist/tools/compareTransactions.js +1 -1
  60. package/dist/tools/deltaFetcher.d.ts +2 -2
  61. package/dist/tools/deltaFetcher.js +16 -15
  62. package/dist/tools/deltaSupport.d.ts +4 -4
  63. package/dist/tools/deltaSupport.js +35 -41
  64. package/dist/tools/exportTransactions.d.ts +5 -4
  65. package/dist/tools/exportTransactions.js +61 -59
  66. package/dist/tools/monthTools.d.ts +7 -6
  67. package/dist/tools/monthTools.js +31 -29
  68. package/dist/tools/payeeTools.d.ts +7 -6
  69. package/dist/tools/payeeTools.js +28 -28
  70. package/dist/tools/reconcileAdapter.d.ts +2 -2
  71. package/dist/tools/reconcileAdapter.js +21 -11
  72. package/dist/tools/reconciliation/analyzer.d.ts +4 -4
  73. package/dist/tools/reconciliation/analyzer.js +136 -57
  74. package/dist/tools/reconciliation/csvParser.d.ts +3 -3
  75. package/dist/tools/reconciliation/csvParser.js +128 -104
  76. package/dist/tools/reconciliation/executor.d.ts +4 -4
  77. package/dist/tools/reconciliation/executor.js +148 -109
  78. package/dist/tools/reconciliation/index.d.ts +10 -10
  79. package/dist/tools/reconciliation/index.js +96 -83
  80. package/dist/tools/reconciliation/matcher.d.ts +3 -3
  81. package/dist/tools/reconciliation/matcher.js +17 -16
  82. package/dist/tools/reconciliation/payeeNormalizer.js +19 -8
  83. package/dist/tools/reconciliation/recommendationEngine.d.ts +1 -1
  84. package/dist/tools/reconciliation/recommendationEngine.js +40 -40
  85. package/dist/tools/reconciliation/reportFormatter.d.ts +2 -2
  86. package/dist/tools/reconciliation/reportFormatter.js +79 -54
  87. package/dist/tools/reconciliation/signDetector.d.ts +1 -1
  88. package/dist/tools/reconciliation/types.d.ts +19 -16
  89. package/dist/tools/reconciliation/ynabAdapter.d.ts +2 -2
  90. package/dist/tools/schemas/common.d.ts +1 -1
  91. package/dist/tools/schemas/common.js +1 -1
  92. package/dist/tools/schemas/outputs/accountOutputs.d.ts +1 -1
  93. package/dist/tools/schemas/outputs/accountOutputs.js +24 -18
  94. package/dist/tools/schemas/outputs/budgetOutputs.d.ts +1 -1
  95. package/dist/tools/schemas/outputs/budgetOutputs.js +14 -11
  96. package/dist/tools/schemas/outputs/categoryOutputs.d.ts +1 -1
  97. package/dist/tools/schemas/outputs/categoryOutputs.js +49 -29
  98. package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
  99. package/dist/tools/schemas/outputs/comparisonOutputs.js +12 -12
  100. package/dist/tools/schemas/outputs/index.d.ts +14 -14
  101. package/dist/tools/schemas/outputs/index.js +14 -14
  102. package/dist/tools/schemas/outputs/monthOutputs.d.ts +1 -1
  103. package/dist/tools/schemas/outputs/monthOutputs.js +56 -41
  104. package/dist/tools/schemas/outputs/payeeOutputs.d.ts +1 -1
  105. package/dist/tools/schemas/outputs/payeeOutputs.js +10 -10
  106. package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +2 -2
  107. package/dist/tools/schemas/outputs/reconciliationOutputs.js +45 -45
  108. package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +1 -1
  109. package/dist/tools/schemas/outputs/transactionMutationOutputs.js +28 -22
  110. package/dist/tools/schemas/outputs/transactionOutputs.d.ts +1 -1
  111. package/dist/tools/schemas/outputs/transactionOutputs.js +43 -35
  112. package/dist/tools/schemas/outputs/utilityOutputs.d.ts +1 -1
  113. package/dist/tools/schemas/outputs/utilityOutputs.js +5 -3
  114. package/dist/tools/schemas/shared/commonOutputs.d.ts +1 -1
  115. package/dist/tools/schemas/shared/commonOutputs.js +15 -9
  116. package/dist/tools/transactionReadTools.d.ts +11 -0
  117. package/dist/tools/transactionReadTools.js +202 -0
  118. package/dist/tools/transactionSchemas.d.ts +309 -0
  119. package/dist/tools/transactionSchemas.js +235 -0
  120. package/dist/tools/transactionTools.d.ts +6 -302
  121. package/dist/tools/transactionTools.js +7 -2054
  122. package/dist/tools/transactionUtils.d.ts +31 -0
  123. package/dist/tools/transactionUtils.js +364 -0
  124. package/dist/tools/transactionWriteTools.d.ts +20 -0
  125. package/dist/tools/transactionWriteTools.js +1342 -0
  126. package/dist/tools/utilityTools.d.ts +5 -4
  127. package/dist/tools/utilityTools.js +11 -11
  128. package/dist/types/index.d.ts +7 -7
  129. package/dist/types/index.js +6 -6
  130. package/dist/types/reconciliation.d.ts +1 -1
  131. package/dist/types/toolRegistration.d.ts +14 -12
  132. package/dist/utils/amountUtils.js +1 -1
  133. package/dist/utils/dateUtils.js +4 -4
  134. package/dist/utils/errors.d.ts +3 -3
  135. package/dist/utils/errors.js +4 -4
  136. package/dist/utils/money.d.ts +2 -2
  137. package/dist/utils/money.js +8 -8
  138. package/dist/utils/validationError.d.ts +1 -1
  139. package/dist/utils/validationError.js +1 -1
  140. package/docs/assets/examples/reconciliation-with-recommendations.json +66 -66
  141. package/docs/assets/schemas/reconciliation-v2.json +360 -336
  142. package/docs/plans/2025-12-25-transaction-tools-refactor-design.md +211 -0
  143. package/docs/plans/2025-12-25-transaction-tools-refactor.md +905 -0
  144. package/esbuild.config.mjs +53 -50
  145. package/meta.json +12548 -12548
  146. package/package.json +98 -109
  147. package/scripts/analyze-bundle.mjs +33 -30
  148. package/scripts/create-pr-description.js +169 -120
  149. package/scripts/run-all-tests.js +205 -0
  150. package/scripts/run-domain-integration-tests.js +28 -18
  151. package/scripts/run-generate-mcpb.js +19 -17
  152. package/scripts/run-throttled-integration-tests.js +92 -83
  153. package/scripts/test-delta-params.mjs +149 -120
  154. package/scripts/test-recommendations.ts +36 -32
  155. package/scripts/tmpTransaction.ts +80 -43
  156. package/scripts/validate-env.js +98 -91
  157. package/scripts/verify-build.js +78 -76
  158. package/src/__tests__/comprehensive.integration.test.ts +1281 -1154
  159. package/src/__tests__/performance.test.ts +723 -671
  160. package/src/__tests__/setup.ts +442 -395
  161. package/src/__tests__/smoke.e2e.test.ts +41 -39
  162. package/src/__tests__/testRunner.ts +314 -295
  163. package/src/__tests__/testUtils.ts +456 -364
  164. package/src/__tests__/tools/reconciliation/csvParser.integration.test.ts +109 -107
  165. package/src/__tests__/tools/reconciliation/real-world.integration.test.ts +41 -41
  166. package/src/index.ts +68 -59
  167. package/src/server/CLAUDE.md +480 -0
  168. package/src/server/YNABMCPServer.ts +821 -794
  169. package/src/server/__tests__/YNABMCPServer.integration.test.ts +929 -893
  170. package/src/server/__tests__/YNABMCPServer.test.ts +903 -899
  171. package/src/server/__tests__/budgetResolver.test.ts +466 -423
  172. package/src/server/__tests__/cacheManager.test.ts +891 -874
  173. package/src/server/__tests__/completions.integration.test.ts +115 -106
  174. package/src/server/__tests__/completions.test.ts +334 -313
  175. package/src/server/__tests__/config.test.ts +98 -86
  176. package/src/server/__tests__/deltaCache.merge.test.ts +774 -703
  177. package/src/server/__tests__/deltaCache.swr.test.ts +198 -153
  178. package/src/server/__tests__/deltaCache.test.ts +946 -759
  179. package/src/server/__tests__/diagnostics.test.ts +825 -792
  180. package/src/server/__tests__/errorHandler.integration.test.ts +512 -462
  181. package/src/server/__tests__/errorHandler.test.ts +402 -397
  182. package/src/server/__tests__/prompts.test.ts +424 -347
  183. package/src/server/__tests__/rateLimiter.test.ts +313 -309
  184. package/src/server/__tests__/requestLogger.test.ts +443 -403
  185. package/src/server/__tests__/resources.template.test.ts +196 -185
  186. package/src/server/__tests__/resources.test.ts +294 -288
  187. package/src/server/__tests__/security.integration.test.ts +487 -421
  188. package/src/server/__tests__/securityMiddleware.test.ts +519 -444
  189. package/src/server/__tests__/server-startup.integration.test.ts +509 -490
  190. package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -173
  191. package/src/server/__tests__/toolRegistration.test.ts +239 -210
  192. package/src/server/__tests__/toolRegistry.test.ts +907 -845
  193. package/src/server/budgetResolver.ts +221 -181
  194. package/src/server/cacheKeys.ts +6 -6
  195. package/src/server/cacheManager.ts +498 -484
  196. package/src/server/completions.ts +267 -243
  197. package/src/server/config.ts +35 -14
  198. package/src/server/deltaCache.merge.ts +146 -128
  199. package/src/server/deltaCache.ts +352 -309
  200. package/src/server/diagnostics.ts +257 -242
  201. package/src/server/errorHandler.ts +747 -744
  202. package/src/server/prompts.ts +181 -176
  203. package/src/server/rateLimiter.ts +131 -129
  204. package/src/server/requestLogger.ts +350 -322
  205. package/src/server/resources.ts +442 -374
  206. package/src/server/responseFormatter.ts +41 -37
  207. package/src/server/securityMiddleware.ts +223 -205
  208. package/src/server/serverKnowledgeStore.ts +67 -67
  209. package/src/server/toolRegistry.ts +508 -474
  210. package/src/tools/CLAUDE.md +604 -0
  211. package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -111
  212. package/src/tools/__tests__/accountTools.integration.test.ts +129 -111
  213. package/src/tools/__tests__/accountTools.test.ts +685 -638
  214. package/src/tools/__tests__/adapters.test.ts +142 -108
  215. package/src/tools/__tests__/budgetTools.delta.integration.test.ts +73 -73
  216. package/src/tools/__tests__/budgetTools.integration.test.ts +132 -124
  217. package/src/tools/__tests__/budgetTools.test.ts +442 -413
  218. package/src/tools/__tests__/categoryTools.delta.integration.test.ts +76 -68
  219. package/src/tools/__tests__/categoryTools.integration.test.ts +314 -288
  220. package/src/tools/__tests__/categoryTools.test.ts +656 -625
  221. package/src/tools/__tests__/compareTransactions/formatter.test.ts +535 -462
  222. package/src/tools/__tests__/compareTransactions/index.test.ts +378 -358
  223. package/src/tools/__tests__/compareTransactions/matcher.test.ts +497 -398
  224. package/src/tools/__tests__/compareTransactions/parser.test.ts +765 -747
  225. package/src/tools/__tests__/compareTransactions.test.ts +352 -332
  226. package/src/tools/__tests__/compareTransactions.window.test.ts +150 -146
  227. package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +69 -65
  228. package/src/tools/__tests__/deltaFetcher.test.ts +325 -265
  229. package/src/tools/__tests__/deltaSupport.test.ts +211 -184
  230. package/src/tools/__tests__/deltaTestUtils.ts +37 -33
  231. package/src/tools/__tests__/exportTransactions.test.ts +205 -200
  232. package/src/tools/__tests__/monthTools.delta.integration.test.ts +68 -68
  233. package/src/tools/__tests__/monthTools.integration.test.ts +178 -166
  234. package/src/tools/__tests__/monthTools.test.ts +561 -512
  235. package/src/tools/__tests__/payeeTools.delta.integration.test.ts +68 -68
  236. package/src/tools/__tests__/payeeTools.integration.test.ts +158 -142
  237. package/src/tools/__tests__/payeeTools.test.ts +486 -434
  238. package/src/tools/__tests__/transactionSchemas.test.ts +1204 -0
  239. package/src/tools/__tests__/transactionTools.integration.test.ts +875 -825
  240. package/src/tools/__tests__/transactionTools.test.ts +4923 -4366
  241. package/src/tools/__tests__/transactionUtils.test.ts +1016 -0
  242. package/src/tools/__tests__/utilityTools.integration.test.ts +32 -32
  243. package/src/tools/__tests__/utilityTools.test.ts +68 -58
  244. package/src/tools/accountTools.ts +293 -271
  245. package/src/tools/adapters.ts +120 -63
  246. package/src/tools/budgetTools.ts +121 -116
  247. package/src/tools/categoryTools.ts +379 -339
  248. package/src/tools/compareTransactions/formatter.ts +131 -119
  249. package/src/tools/compareTransactions/index.ts +249 -214
  250. package/src/tools/compareTransactions/matcher.ts +259 -209
  251. package/src/tools/compareTransactions/parser.ts +517 -487
  252. package/src/tools/compareTransactions/types.ts +38 -38
  253. package/src/tools/compareTransactions.ts +1 -1
  254. package/src/tools/deltaFetcher.ts +281 -260
  255. package/src/tools/deltaSupport.ts +264 -259
  256. package/src/tools/exportTransactions.ts +230 -218
  257. package/src/tools/monthTools.ts +180 -165
  258. package/src/tools/payeeTools.ts +152 -140
  259. package/src/tools/reconcileAdapter.ts +297 -246
  260. package/src/tools/reconciliation/CLAUDE.md +506 -0
  261. package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +135 -112
  262. package/src/tools/reconciliation/__tests__/adapter.test.ts +249 -227
  263. package/src/tools/reconciliation/__tests__/analyzer.test.ts +408 -335
  264. package/src/tools/reconciliation/__tests__/csvParser.test.ts +71 -69
  265. package/src/tools/reconciliation/__tests__/executor.integration.test.ts +348 -323
  266. package/src/tools/reconciliation/__tests__/executor.progress.test.ts +503 -457
  267. package/src/tools/reconciliation/__tests__/executor.test.ts +898 -831
  268. package/src/tools/reconciliation/__tests__/matcher.test.ts +667 -663
  269. package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +296 -276
  270. package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +692 -624
  271. package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1008 -986
  272. package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +187 -146
  273. package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +583 -530
  274. package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +75 -71
  275. package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +70 -58
  276. package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +102 -88
  277. package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +58 -43
  278. package/src/tools/reconciliation/__tests__/signDetector.test.ts +209 -206
  279. package/src/tools/reconciliation/__tests__/ynabAdapter.test.ts +66 -60
  280. package/src/tools/reconciliation/analyzer.ts +582 -406
  281. package/src/tools/reconciliation/csvParser.ts +656 -609
  282. package/src/tools/reconciliation/executor.ts +1290 -1128
  283. package/src/tools/reconciliation/index.ts +580 -528
  284. package/src/tools/reconciliation/matcher.ts +256 -240
  285. package/src/tools/reconciliation/payeeNormalizer.ts +92 -78
  286. package/src/tools/reconciliation/recommendationEngine.ts +357 -345
  287. package/src/tools/reconciliation/reportFormatter.ts +349 -276
  288. package/src/tools/reconciliation/signDetector.ts +89 -83
  289. package/src/tools/reconciliation/types.ts +164 -153
  290. package/src/tools/reconciliation/ynabAdapter.ts +17 -15
  291. package/src/tools/schemas/CLAUDE.md +546 -0
  292. package/src/tools/schemas/common.ts +1 -1
  293. package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +410 -409
  294. package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +305 -299
  295. package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +431 -430
  296. package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +510 -495
  297. package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +179 -153
  298. package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +293 -254
  299. package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +457 -457
  300. package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +362 -356
  301. package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +402 -399
  302. package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +225 -211
  303. package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +457 -454
  304. package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +316 -315
  305. package/src/tools/schemas/outputs/accountOutputs.ts +40 -34
  306. package/src/tools/schemas/outputs/budgetOutputs.ts +24 -19
  307. package/src/tools/schemas/outputs/categoryOutputs.ts +76 -56
  308. package/src/tools/schemas/outputs/comparisonOutputs.ts +192 -169
  309. package/src/tools/schemas/outputs/index.ts +163 -163
  310. package/src/tools/schemas/outputs/monthOutputs.ts +95 -80
  311. package/src/tools/schemas/outputs/payeeOutputs.ts +18 -18
  312. package/src/tools/schemas/outputs/reconciliationOutputs.ts +386 -373
  313. package/src/tools/schemas/outputs/transactionMutationOutputs.ts +259 -231
  314. package/src/tools/schemas/outputs/transactionOutputs.ts +81 -71
  315. package/src/tools/schemas/outputs/utilityOutputs.ts +90 -84
  316. package/src/tools/schemas/shared/commonOutputs.ts +27 -19
  317. package/src/tools/toolCategories.ts +114 -114
  318. package/src/tools/transactionReadTools.ts +327 -0
  319. package/src/tools/transactionSchemas.ts +484 -0
  320. package/src/tools/transactionTools.ts +107 -2990
  321. package/src/tools/transactionUtils.ts +621 -0
  322. package/src/tools/transactionWriteTools.ts +2110 -0
  323. package/src/tools/utilityTools.ts +46 -41
  324. package/src/types/CLAUDE.md +477 -0
  325. package/src/types/__tests__/index.test.ts +51 -51
  326. package/src/types/index.ts +43 -39
  327. package/src/types/integration-tests.d.ts +26 -26
  328. package/src/types/reconciliation.ts +29 -29
  329. package/src/types/toolAnnotations.ts +30 -30
  330. package/src/types/toolRegistration.ts +43 -32
  331. package/src/utils/CLAUDE.md +508 -0
  332. package/src/utils/__tests__/dateUtils.test.ts +174 -168
  333. package/src/utils/__tests__/money.test.ts +193 -187
  334. package/src/utils/amountUtils.ts +5 -5
  335. package/src/utils/baseError.ts +5 -5
  336. package/src/utils/dateUtils.ts +29 -26
  337. package/src/utils/errors.ts +14 -14
  338. package/src/utils/money.ts +66 -52
  339. package/src/utils/validationError.ts +1 -1
  340. package/tsconfig.json +29 -29
  341. package/tsconfig.prod.json +16 -16
  342. package/vitest-reporters/split-json-reporter.ts +247 -204
  343. package/vitest.config.ts +99 -95
  344. package/.prettierignore +0 -10
  345. package/.prettierrc.json +0 -10
  346. 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
+ >;