@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
@@ -0,0 +1,604 @@
1
+ # Tools - YNAB MCP Server
2
+
3
+ This directory contains all YNAB operations exposed via MCP tools, organized by domain (budget, account, transaction, category, payee, month, utility, reconciliation).
4
+
5
+ ## Purpose & Responsibilities
6
+
7
+ The `src/tools/` directory implements:
8
+
9
+ 1. **YNAB Operations** - CRUD operations for budgets, accounts, transactions, categories, payees
10
+ 2. **Tool Registration** - Domain-specific factory functions that register tools with the ToolRegistry
11
+ 3. **Input Validation** - Zod schemas for type-safe input validation
12
+ 4. **Adapter Pattern** - Consistent handler wrapping with dependency injection
13
+ 5. **Special Operations** - Transaction comparison, export, receipt itemization, reconciliation
14
+
15
+ ## Directory Structure
16
+
17
+ ```
18
+ src/tools/
19
+ ├── budgetTools.ts # Budget listing and retrieval
20
+ ├── accountTools.ts # Account management (list, get, create)
21
+ ├── transactionTools.ts # Transaction CRUD operations (2,274 lines)
22
+ ├── transactionSchemas.ts # Transaction Zod schemas (453 lines, v0.18.4)
23
+ ├── transactionUtils.ts # Transaction utilities (536 lines, v0.18.4)
24
+ ├── categoryTools.ts # Category management (list, get, update)
25
+ ├── payeeTools.ts # Payee listing and retrieval
26
+ ├── monthTools.ts # Monthly budget data (get, list)
27
+ ├── utilityTools.ts # User info and amount conversion
28
+ ├── adapters.ts # Tool adapter implementations
29
+ ├── toolCategories.ts # Tool categorization and annotations
30
+ ├── compareTransactions.ts # CSV comparison tool entry point
31
+ ├── exportTransactions.ts # Transaction export to JSON files
32
+ ├── reconcileAdapter.ts # Legacy adapter for reconciliation tool
33
+ ├── deltaFetcher.ts # Delta request utilities
34
+ ├── deltaSupport.ts # Delta request support utilities
35
+ ├── compareTransactions/ # CSV comparison modular components
36
+ │ ├── parser.ts # CSV parsing
37
+ │ ├── matcher.ts # Transaction matching
38
+ │ └── formatter.ts # Report formatting
39
+ ├── reconciliation/ # Comprehensive reconciliation system (v2)
40
+ │ ├── csvParser.ts # CSV parsing with bank presets
41
+ │ ├── matcher.ts # Fuzzy matching engine
42
+ │ ├── analyzer.ts # Transaction analysis
43
+ │ ├── executor.ts # Bulk transaction operations
44
+ │ ├── recommendationEngine.ts # Smart reconciliation recommendations
45
+ │ ├── reportFormatter.ts # Human-readable reports
46
+ │ ├── signDetector.ts # Auto-detection of debit/credit signs
47
+ │ ├── payeeNormalizer.ts # Payee name normalization
48
+ │ └── ynabAdapter.ts # YNAB API integration layer
49
+ └── schemas/ # Zod schemas for input/output validation
50
+ ├── common.ts # Shared schemas (emptyObject, looseObject)
51
+ └── outputs/ # Output validation schemas (11 files)
52
+ ```
53
+
54
+ ## Key Patterns & Conventions
55
+
56
+ ### 1. Tool Registration Pattern
57
+
58
+ All tools use domain-specific factory functions that register with ToolRegistry:
59
+
60
+ ```typescript
61
+ // In budgetTools.ts
62
+ export function registerBudgetTools(
63
+ registry: ToolRegistry,
64
+ context: ToolContext
65
+ ): void {
66
+ registry.register({
67
+ name: 'list_budgets',
68
+ description: 'List all budgets',
69
+ inputSchema: emptyObjectSchema,
70
+ handler: adaptNoInput(handleListBudgets, context),
71
+ metadata: {
72
+ annotations: {
73
+ ...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
74
+ title: 'YNAB: List Budgets',
75
+ },
76
+ },
77
+ });
78
+ }
79
+ ```
80
+
81
+ **Why Critical**: Centralized registration enables consistent validation, security, error handling, and progress notifications.
82
+
83
+ **What Breaks**: Registering tools outside factory functions → bypasses security, no DI, inconsistent error handling.
84
+
85
+ ### 2. Adapter Pattern
86
+
87
+ Use adapter helpers from `adapters.ts` to wrap handlers with dependency injection:
88
+
89
+ ```typescript
90
+ import { adapt, adaptWrite, adaptWithDelta, adaptNoInput } from './adapters.js';
91
+
92
+ // Read-only tool with input
93
+ handler: adapt(handleGetBudget, context);
94
+
95
+ // Write tool (invalidates cache)
96
+ handler: adaptWrite(handleUpdateTransaction, context);
97
+
98
+ // Delta-aware tool
99
+ handler: adaptWithDelta(handleListTransactions, context);
100
+
101
+ // No-input tool
102
+ handler: adaptNoInput(handleGetUser, context);
103
+ ```
104
+
105
+ **Adapter Types**:
106
+
107
+ - `adapt` - Standard read-only handler with input
108
+ - `adaptWrite` - Write handler (invalidates cache, supports progress)
109
+ - `adaptWithDelta` - Delta-aware handler for efficient updates
110
+ - `adaptNoInput` - Handler with no input parameters
111
+
112
+ **Why Critical**: Adapters inject ToolContext dependencies, enable progress notifications, and ensure consistent error handling.
113
+
114
+ **What Breaks**: Not using adapters → no DI, missing errorHandler, no progress support, inconsistent behavior.
115
+
116
+ ### 3. Schema Organization
117
+
118
+ Schemas are organized by domain and strictness:
119
+
120
+ ```typescript
121
+ // Input schemas (in tool files)
122
+ const CreateTransactionSchema = z
123
+ .object({
124
+ budget_id: z.string().optional(),
125
+ account_id: z.string(),
126
+ amount: z.number(),
127
+ date: z.string(),
128
+ // ...
129
+ })
130
+ .strict(); // CRITICAL: Always use .strict()
131
+
132
+ // Shared schemas (in schemas/common.ts)
133
+ export const emptyObjectSchema = z.object({}).strict();
134
+ export const looseObjectSchema = z.object({}).passthrough();
135
+
136
+ // Output schemas (in schemas/outputs/)
137
+ export const BudgetOutputSchema = z.object({
138
+ id: z.string(),
139
+ name: z.string(),
140
+ // ...
141
+ });
142
+ ```
143
+
144
+ **Why Critical**: `.strict()` prevents unknown fields, which is a security concern. Input validation catches errors early.
145
+
146
+ **What Breaks**: Missing `.strict()` → security vulnerability (unknown fields accepted). Missing validation → runtime errors, data corruption.
147
+
148
+ ### 4. Amount Handling (CRITICAL!)
149
+
150
+ YNAB uses **milliunits** (1 dollar = 1000 milliunits). Always convert before API calls:
151
+
152
+ ```typescript
153
+ import { milliunitsToAmount, amountToMilliunits } from '../utils/money.js';
154
+
155
+ // User provides dollars, convert to milliunits for API
156
+ const transaction = {
157
+ amount: amountToMilliunits(userInputDollars), // e.g., 25.50 → 25500
158
+ // ...
159
+ };
160
+
161
+ // API returns milliunits, convert to dollars for display
162
+ const displayAmount = milliunitsToAmount(transaction.amount); // 25500 → 25.50
163
+ ```
164
+
165
+ **Why CRITICAL**: Missing conversion → amounts are 1000x wrong (e.g., $25.50 becomes $0.02550 or $25,500.00).
166
+
167
+ **What Breaks**: Direct dollar amounts to API → wrong values. Missing conversion from API → wrong display.
168
+
169
+ ### 5. Progress Notifications
170
+
171
+ Long-running tools (reconciliation, bulk operations) emit progress updates:
172
+
173
+ ```typescript
174
+ async function handleReconcileAccount(
175
+ input: ReconcileInput,
176
+ sendProgress?: ProgressCallback
177
+ ): Promise<ReconcileResult> {
178
+ await sendProgress?.({
179
+ progress: 10,
180
+ total: 100,
181
+ message: 'Parsing CSV...',
182
+ });
183
+
184
+ // ... parsing logic ...
185
+
186
+ await sendProgress?.({
187
+ progress: 50,
188
+ total: 100,
189
+ message: 'Matching transactions...',
190
+ });
191
+
192
+ // ... matching logic ...
193
+
194
+ await sendProgress?.({
195
+ progress: 100,
196
+ total: 100,
197
+ message: 'Complete',
198
+ });
199
+
200
+ return result;
201
+ }
202
+ ```
203
+
204
+ **Why Critical**: Operations >5 seconds need progress to prevent timeouts and improve UX.
205
+
206
+ **What Breaks**: Missing optional chaining (`?.`) → TypeError. Missing progress updates → poor UX, timeouts.
207
+
208
+ ### 6. Cache Invalidation
209
+
210
+ Write operations must invalidate related caches:
211
+
212
+ ```typescript
213
+ // After creating/updating/deleting a transaction
214
+ await updateTransaction(transactionId, updates);
215
+
216
+ // Invalidate related caches
217
+ context.cacheManager.delete(`transaction:${transactionId}`);
218
+ context.cacheManager.delete(`transactions:${budgetId}`);
219
+ context.cacheManager.delete(`account:${accountId}`); // Account balance changed
220
+ ```
221
+
222
+ **Why Critical**: Stale cache → users see outdated data, inconsistent state.
223
+
224
+ **What Breaks**: Missing invalidation → stale data persists until TTL expires (2-10 minutes).
225
+
226
+ ## Transaction Tools (Special Note)
227
+
228
+ In v0.18.4, transaction tools were refactored into 3 files for maintainability:
229
+
230
+ ### File Breakdown
231
+
232
+ 1. **transactionSchemas.ts** (453 lines)
233
+ - Zod schemas for all transaction operations
234
+ - Input: `CreateTransactionSchema`, `UpdateTransactionSchema`, etc.
235
+ - Shared types: `TransactionInput`, `BulkTransactionInput`
236
+
237
+ 2. **transactionUtils.ts** (536 lines)
238
+ - Transaction utilities and helpers
239
+ - Receipt itemization logic (smart collapse for 5+ items)
240
+ - Big ticket preservation (items >10% of total)
241
+ - Tax allocation across line items
242
+ - Date validation, amount validation
243
+
244
+ 3. **transactionTools.ts** (2,274 lines)
245
+ - Tool registration factory (`registerTransactionTools`)
246
+ - Handler implementations for all transaction operations
247
+ - Tools: `create_transaction`, `update_transaction`, `delete_transaction`, `create_transactions`, `create_receipt_split_transaction`, `list_transactions`, `get_transaction`, `export_transactions`, `update_transactions`
248
+
249
+ ### Why Refactored
250
+
251
+ - **Maintainability**: 3,263 lines in one file was unwieldy
252
+ - **Separation of Concerns**: Schemas, utilities, and handlers are distinct responsibilities
253
+ - **Testability**: Easier to unit test schemas and utilities separately
254
+
255
+ ## Receipt Itemization (v0.18.2+)
256
+
257
+ The `create_receipt_split_transaction` tool uses smart itemization logic:
258
+
259
+ ### Features
260
+
261
+ 1. **Smart Collapse**: Collapses 5+ small items into "Other items" memo entry
262
+ 2. **Big Ticket Preservation**: Items >10% of total are always preserved as separate splits
263
+ 3. **Tax Allocation**: Distributes tax proportionally across line items
264
+ 4. **Memo Format**: Each split gets memo like "Item Name ($12.34)" for traceability
265
+
266
+ ### Example
267
+
268
+ ```typescript
269
+ // 8-item receipt with $100 total, $10 tax
270
+ // Result: 4 big items ($15+ each) + 1 "Other items (4 items, $20.00)" + tax split
271
+ ```
272
+
273
+ **Why Important**: Keeps transaction list clean while preserving important line items.
274
+
275
+ **What Breaks**: Manual memo formatting → inconsistent, hard to parse.
276
+
277
+ ## Common Development Tasks
278
+
279
+ ### Adding a New Tool
280
+
281
+ 1. **Choose domain file** (e.g., `budgetTools.ts` for budget operations)
282
+
283
+ 2. **Create Zod schema** with strict validation:
284
+ ```typescript
285
+ const MyToolSchema = z
286
+ .object({
287
+ budget_id: z.string().optional(),
288
+ my_field: z.string(),
289
+ })
290
+ .strict(); // CRITICAL
291
+ ```
292
+
293
+ 3. **Implement handler function**:
294
+ ```typescript
295
+ async function handleMyTool(
296
+ input: z.infer<typeof MyToolSchema>,
297
+ context: ToolContext
298
+ ): Promise<MyResult> {
299
+ const budgetId = BudgetResolver.resolveBudgetId(
300
+ input.budget_id,
301
+ context.getDefaultBudgetId()
302
+ );
303
+ if (typeof budgetId !== 'string') return budgetId;
304
+
305
+ // ... implementation ...
306
+
307
+ return result;
308
+ }
309
+ ```
310
+
311
+ 4. **Register in factory function**:
312
+ ```typescript
313
+ export function registerMyDomainTools(
314
+ registry: ToolRegistry,
315
+ context: ToolContext
316
+ ): void {
317
+ registry.register({
318
+ name: 'my_tool',
319
+ description: 'My tool description',
320
+ inputSchema: MyToolSchema,
321
+ handler: adapt(handleMyTool, context),
322
+ metadata: {
323
+ annotations: {
324
+ ...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
325
+ title: 'YNAB: My Tool',
326
+ },
327
+ },
328
+ });
329
+ }
330
+ ```
331
+
332
+ 5. **Add unit tests** in `__tests__/myDomainTools.test.ts`
333
+
334
+ 6. **Add integration tests** in `__tests__/myDomainTools.integration.test.ts`
335
+
336
+ ### Modifying Existing Tool
337
+
338
+ 1. **Read the current schema** to understand inputs
339
+ 2. **Update schema** if adding/changing fields:
340
+ ```typescript
341
+ const UpdatedSchema = ExistingSchema.extend({
342
+ new_field: z.string().optional(),
343
+ });
344
+ ```
345
+ 3. **Update handler** with new logic
346
+ 4. **Update tests** to cover new behavior
347
+ 5. **Invalidate caches** if it's a write operation
348
+
349
+ ### Adding Progress Notifications
350
+
351
+ 1. **Update handler signature**:
352
+ ```typescript
353
+ async function handleMyTool(
354
+ input: MyInput,
355
+ sendProgress?: ProgressCallback
356
+ ): Promise<MyOutput>
357
+ ```
358
+
359
+ 2. **Use `adaptWrite` adapter** (supports progress):
360
+ ```typescript
361
+ handler: adaptWrite(handleMyTool, context);
362
+ ```
363
+
364
+ 3. **Emit progress updates**:
365
+ ```typescript
366
+ await sendProgress?.({
367
+ progress: currentStep,
368
+ total: totalSteps,
369
+ message: 'Processing...',
370
+ });
371
+ ```
372
+
373
+ ### Adding Output Schema
374
+
375
+ 1. **Create schema** in `schemas/outputs/`:
376
+ ```typescript
377
+ export const MyOutputSchema = z.object({
378
+ id: z.string(),
379
+ name: z.string(),
380
+ // ...
381
+ });
382
+ ```
383
+
384
+ 2. **Use in handler**:
385
+ ```typescript
386
+ const result = await fetchData();
387
+ return MyOutputSchema.parse(result); // Validates output
388
+ ```
389
+
390
+ ## Testing Approach
391
+
392
+ ### Unit Tests
393
+
394
+ - **Location**: `src/tools/__tests__/*.test.ts`
395
+ - **Mock**: YNAB API, ToolContext, all external dependencies
396
+ - **Coverage**: 80% minimum
397
+ - **Focus**: Handler logic, error handling, edge cases
398
+
399
+ ### Integration Tests
400
+
401
+ - **Location**: `src/tools/__tests__/*.integration.test.ts`
402
+ - **Mock**: YNAB API (use realistic fixtures)
403
+ - **Real**: ToolContext, cacheManager, errorHandler
404
+ - **Focus**: End-to-end tool execution, cache behavior
405
+
406
+ ### Example Unit Test
407
+
408
+ ```typescript
409
+ describe('handleCreateTransaction', () => {
410
+ it('should convert dollars to milliunits', async () => {
411
+ const context = createMockContext();
412
+ const input = {
413
+ account_id: 'acc123',
414
+ amount: 25.5, // Dollars
415
+ date: '2025-01-31',
416
+ };
417
+
418
+ await handleCreateTransaction(input, context);
419
+
420
+ expect(context.ynabAPI.createTransaction).toHaveBeenCalledWith(
421
+ expect.objectContaining({
422
+ amount: 25500, // Milliunits!
423
+ })
424
+ );
425
+ });
426
+ });
427
+ ```
428
+
429
+ ## What Will Break If Violated
430
+
431
+ ### 1. Missing Milliunits Conversion
432
+
433
+ **Problem**: Passing dollar amounts directly to YNAB API.
434
+
435
+ **Impact**: Amounts are 1000x wrong (e.g., $25.50 → $0.02550 or $25,500.00).
436
+
437
+ **Fix**: Always use `amountToMilliunits()` before API calls:
438
+
439
+ ```typescript
440
+ // BAD
441
+ await ynabAPI.createTransaction({
442
+ amount: 25.5, // Wrong!
443
+ });
444
+
445
+ // GOOD
446
+ await ynabAPI.createTransaction({
447
+ amount: amountToMilliunits(25.5), // 25500 milliunits
448
+ });
449
+ ```
450
+
451
+ ### 2. Schema Without `.strict()`
452
+
453
+ **Problem**: Input schemas missing `.strict()` modifier.
454
+
455
+ **Impact**: Security vulnerability (unknown fields accepted), potential injection attacks.
456
+
457
+ **Fix**: Always use `.strict()` on input schemas:
458
+
459
+ ```typescript
460
+ // BAD
461
+ const MySchema = z.object({
462
+ field: z.string(),
463
+ }); // Allows unknown fields!
464
+
465
+ // GOOD
466
+ const MySchema = z
467
+ .object({
468
+ field: z.string(),
469
+ })
470
+ .strict(); // Rejects unknown fields
471
+ ```
472
+
473
+ ### 3. Missing Cache Invalidation
474
+
475
+ **Problem**: Write operations without cache invalidation.
476
+
477
+ **Impact**: Users see stale data for 2-10 minutes (until TTL expires).
478
+
479
+ **Fix**: Invalidate related caches after writes:
480
+
481
+ ```typescript
482
+ await updateTransaction(id, updates);
483
+
484
+ // Invalidate all related caches
485
+ context.cacheManager.delete(`transaction:${id}`);
486
+ context.cacheManager.delete(`transactions:${budgetId}`);
487
+ context.cacheManager.delete(`account:${accountId}`);
488
+ ```
489
+
490
+ ### 4. Missing `.js` Extensions in Imports
491
+
492
+ **Problem**: Imports without `.js` extension.
493
+
494
+ **Impact**: Build failures, runtime errors (ES modules require explicit extensions).
495
+
496
+ **Fix**: Always use `.js` extensions:
497
+
498
+ ```typescript
499
+ // BAD
500
+ import { adapt } from './adapters';
501
+
502
+ // GOOD
503
+ import { adapt } from './adapters.js';
504
+ ```
505
+
506
+ ### 5. Not Using Adapters
507
+
508
+ **Problem**: Registering handlers directly without adapters.
509
+
510
+ **Impact**: No dependency injection, missing errorHandler, no progress support, inconsistent error handling.
511
+
512
+ **Fix**: Always use adapter helpers:
513
+
514
+ ```typescript
515
+ // BAD
516
+ handler: async (input) => handleMyTool(input);
517
+
518
+ // GOOD
519
+ handler: adapt(handleMyTool, context);
520
+ ```
521
+
522
+ ### 6. Direct YNAB API Calls
523
+
524
+ **Problem**: Bypassing ToolContext and calling YNAB API directly.
525
+
526
+ **Impact**: No caching, no rate limiting, no error handling, test failures.
527
+
528
+ **Fix**: Always use `context.ynabAPI`:
529
+
530
+ ```typescript
531
+ // BAD
532
+ const api = new ynab.API(token);
533
+ const budgets = await api.budgets.getBudgets();
534
+
535
+ // GOOD
536
+ const budgets = await context.ynabAPI.budgets.getBudgets();
537
+ ```
538
+
539
+ ## Tool Categories & Annotations
540
+
541
+ All tools use MCP annotations from `toolCategories.ts`:
542
+
543
+ ### Annotation Presets
544
+
545
+ - **READ_ONLY_EXTERNAL** - Read-only YNAB API calls (idempotent)
546
+ - **WRITE_EXTERNAL_CREATE** - Create operations (non-idempotent)
547
+ - **WRITE_EXTERNAL_UPDATE** - Update operations (idempotent)
548
+ - **WRITE_EXTERNAL_DELETE** - Delete operations (destructive, idempotent)
549
+ - **UTILITY_LOCAL** - Local operations (no external API)
550
+
551
+ ### Usage
552
+
553
+ ```typescript
554
+ metadata: {
555
+ annotations: {
556
+ ...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
557
+ title: 'YNAB: Update Transaction',
558
+ },
559
+ }
560
+ ```
561
+
562
+ ## Integration Points
563
+
564
+ ### With Server (`src/server/`)
565
+
566
+ - **ToolRegistry**: All tools register via `registry.register()`
567
+ - **ToolContext**: Injected by adapters, provides ynabAPI, cacheManager, etc.
568
+ - **Error Handling**: Uses `errorHandler` from ToolContext
569
+
570
+ ### With Types (`src/types/`)
571
+
572
+ - **ToolContext**: Central DI object with all shared dependencies
573
+ - **Handler Signatures**: Handler, DeltaHandler, WriteHandler, NoInputHandler
574
+ - **Reconciliation Types**: ReconcileInput, ReconcileResult, etc.
575
+
576
+ ### With Utils (`src/utils/`)
577
+
578
+ - **Money Conversion**: `amountToMilliunits()`, `milliunitsToAmount()`
579
+ - **Date Utilities**: `formatDate()`, `isValidDate()`
580
+ - **Validation**: `validateAmount()`, `validateDate()`
581
+
582
+ ## Performance Considerations
583
+
584
+ 1. **Use Delta Requests**: For large datasets (transactions), use `adaptWithDelta`
585
+ 2. **Cache Aggressively**: Read-only tools benefit from long TTLs
586
+ 3. **Batch Operations**: Use bulk APIs (`create_transactions`, `update_transactions`) for multiple operations
587
+ 4. **Progress Notifications**: Operations >5 seconds should emit progress
588
+ 5. **Lazy Loading**: Don't fetch unnecessary related data
589
+
590
+ ## Security Considerations
591
+
592
+ 1. **Strict Schemas**: Always use `.strict()` on input schemas
593
+ 2. **Input Validation**: Validate all inputs via Zod before processing
594
+ 3. **Budget ID Validation**: Always resolve and validate budget IDs
595
+ 4. **Amount Validation**: Validate amounts are reasonable (not negative for debits, etc.)
596
+ 5. **No Secret Leakage**: Error responses never include API tokens or sensitive data
597
+
598
+ ## Related Documentation
599
+
600
+ - [Root CLAUDE.md](../../CLAUDE.md) - Project overview and architecture
601
+ - [Server CLAUDE.md](../server/CLAUDE.md) - Server components and MCP orchestration
602
+ - [Reconciliation CLAUDE.md](reconciliation/CLAUDE.md) - Reconciliation system deep-dive
603
+ - [Schemas CLAUDE.md](schemas/CLAUDE.md) - Schema definitions and validation
604
+ - [API Documentation](../../docs/reference/API.md) - Complete API reference