@dizzlkheinz/ynab-mcpb 0.12.1

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 (435) hide show
  1. package/.chunkhound.json +11 -0
  2. package/.code/agents/0427d95e-edca-431f-a214-5e53264e29c4/error.txt +8 -0
  3. package/.code/agents/0d675174-d1e1-41c3-9975-4c2e275819a9/error.txt +3 -0
  4. package/.code/agents/0d8c5afd-4787-422b-abf8-2e5943fc7e67/error.txt +3 -0
  5. package/.code/agents/0ec34a70-ed5d-4b9e-bee4-bb0e4cccbc4b/error.txt +1 -0
  6. package/.code/agents/0ef51a21-1ab1-49d7-9561-0eaa43875ebc/error.txt +12 -0
  7. package/.code/agents/15db95d7-abad-4b4d-9c3b-8446089cb61d/error.txt +1 -0
  8. package/.code/agents/19ab9acb-f675-4ff0-902a-09a5476f8149/error.txt +1 -0
  9. package/.code/agents/1ef7e12d-f6ff-4897-8a9b-152d523d898e/error.txt +5 -0
  10. package/.code/agents/2465/exec-call_lroN9KKzJVWC7t5423DK1nT9.txt +1453 -0
  11. package/.code/agents/28edb6fe-95a9-41a0-ae69-aa0100d26c0c/error.txt +8 -0
  12. package/.code/agents/2ae40cf5-b4bf-42e2-92bf-7ea350a7755e/error.txt +9 -0
  13. package/.code/agents/2bfc4e1f-ac4b-45a5-b6df-bf89d4dbb54c/error.txt +1 -0
  14. package/.code/agents/2e2e1134-eff0-49be-ba25-8e2c3468a564/error.txt +5 -0
  15. package/.code/agents/3/exec-call_203OC4TNVkLxW7z2HCVEQ1cM.txt +81 -0
  16. package/.code/agents/3/exec-call_SS5T0XSiXB4LSNzUKTl75wkh.txt +610 -0
  17. package/.code/agents/3322c003-ce5e-48e3-a342-f5049c5bf9a2/error.txt +1 -0
  18. package/.code/agents/391e9b08-1ebc-468c-9bcd-6d0cc3193b37/error.txt +1 -0
  19. package/.code/agents/3ab0aa84-b7bb-4054-afa3-40b8fd7d3be0/error.txt +1 -0
  20. package/.code/agents/3bed368d-50fe-477e-aee3-a6707eaa1ab9/error.txt +3 -0
  21. package/.code/agents/3e40b925-db12-442f-8d7a-a25fc69a6672/error.txt +8 -0
  22. package/.code/agents/414d5776-cf58-41f3-9328-a6daed503a50/error.txt +5 -0
  23. package/.code/agents/42687751-4565-4610-b240-67835b17d861/error.txt +1 -0
  24. package/.code/agents/46b98876-1a39-43c9-9e2f-507ca6d47335/error.txt +9 -0
  25. package/.code/agents/4a7d9491-b26f-43dd-850d-2ecdc49b5d1b/error.txt +1 -0
  26. package/.code/agents/4e60f00a-1b3e-447f-87f3-7faf9deddec3/error.txt +13 -0
  27. package/.code/agents/5138fc1c-4d49-4b74-a7da-ccdb3a8e44e7/error.txt +14 -0
  28. package/.code/agents/521cff39-a7a3-42e5-a557-134f0f7daaa0/error.txt +5 -0
  29. package/.code/agents/53302dc5-3857-4413-9a47-9e0f64a51dc4/error.txt +5 -0
  30. package/.code/agents/567c7c2e-6a6f-4761-a08d-d36deeb2e0ac/error.txt +5 -0
  31. package/.code/agents/57b00845-80dc-47c9-953c-3028d16275d6/error.txt +3 -0
  32. package/.code/agents/593d9005-c2a5-48fd-8813-ece0d3f2de96/error.txt +1 -0
  33. package/.code/agents/5a112e66-0e1a-42f9-877c-53af56ea3551/error.txt +1 -0
  34. package/.code/agents/5b05e8ed-7788-4738-b7ee-9faa8180f992/error.txt +5 -0
  35. package/.code/agents/5f888d6f-d7ca-4ac8-be23-9ea1bf753951/error.txt +5 -0
  36. package/.code/agents/607db3ab-e4b0-435b-b497-93e9aa525549/error.txt +8 -0
  37. package/.code/agents/67dcb2a2-900f-4c78-b3fc-80b5213e0ddf/error.txt +8 -0
  38. package/.code/agents/69ad848c-4e98-49b3-b16c-0094ac2d1759/error.txt +5 -0
  39. package/.code/agents/6c9cfc5f-0d0b-445c-b121-9f60082c4f70/error.txt +1 -0
  40. package/.code/agents/6f6f8f77-4ab0-4f6e-9f30-40e8be0bd8f5/error.txt +1 -0
  41. package/.code/agents/72a7cde4-fa8a-4024-9038-27faa550539b/error.txt +1 -0
  42. package/.code/agents/7b48335c-8247-43aa-9949-5f820ba8e199/error.txt +1 -0
  43. package/.code/agents/80944249-bea9-4ac5-87de-a666c4df306e/error.txt +1 -0
  44. package/.code/agents/826099df-1b66-4186-a915-7eb59f9db19d/error.txt +5 -0
  45. package/.code/agents/8291d158-18a8-4a92-b799-4e9a4d9cce88/error.txt +1 -0
  46. package/.code/agents/82fb71a3-20fb-4341-804a-a2fc900f95bc/error.txt +1 -0
  47. package/.code/agents/855790ea-54ee-43e4-8209-a66994e37590/error.txt +1 -0
  48. package/.code/agents/88ce3a2e-04f2-42be-9062-bf97aa798da0/error.txt +3 -0
  49. package/.code/agents/9a17e398-b6ed-4218-bb55-bc64a8d38ce8/error.txt +8 -0
  50. package/.code/agents/9a4f4bfc-a2a6-4f40-a896-9335b41a7ed1/error.txt +1 -0
  51. package/.code/agents/9b633e55-ef84-47d6-94bb-fd3dd172ad97/error.txt +1 -0
  52. package/.code/agents/9b81f3ab-c72b-4a81-9a8f-28a49ddba84a/error.txt +8 -0
  53. package/.code/agents/a35daf29-b2d1-4aef-9b42-dad63a76bd47/error.txt +3 -0
  54. package/.code/agents/a81990cc-69ee-44d2-b907-17403c9bc5d7/error.txt +5 -0
  55. package/.code/agents/ab56260a-4a83-4ad4-9410-f88a23d6520a/error.txt +1 -0
  56. package/.code/agents/ad722c31-2d1d-45f7-bae2-3f02ca455b60/error.txt +1 -0
  57. package/.code/agents/b62e8690-3324-4b97-9309-731bee79416b/error.txt +5 -0
  58. package/.code/agents/baf60a3a-752b-4ad8-99d6-df32423ed2eb/error.txt +1 -0
  59. package/.code/agents/be049042-7dcb-4ac8-9beb-c8f1aea67742/error.txt +14 -0
  60. package/.code/agents/bed1dcb4-bfce-4a9f-8594-0f994962aafd/error.txt +1 -0
  61. package/.code/agents/c324a6cf-e935-4ede-9529-b3ebc18e8d6b/error.txt +5 -0
  62. package/.code/agents/c37c06ff-dfe3-43f2-9bbc-3ec73ec8f41d/error.txt +5 -0
  63. package/.code/agents/c8cd6671-433a-456b-9f88-e51cb2df6bfc/error.txt +11 -0
  64. package/.code/agents/ca2ccb67-2f24-428e-b27d-9365beadd140/error.txt +1 -0
  65. package/.code/agents/cf08c0c8-e7f0-423e-93ba-547e8e818340/error.txt +8 -0
  66. package/.code/agents/d579c74f-874b-40a4-9d56-ced1eb6a701d/error.txt +1 -0
  67. package/.code/agents/df412c98-7378-4deb-8e1e-76c416931181/error.txt +3 -0
  68. package/.code/agents/e5134eb3-2af4-45b0-8998-051cb4afdb45/error.txt +3 -0
  69. package/.code/agents/e6308471-aa45-4e9e-9496-2e9404164d97/error.txt +8 -0
  70. package/.code/agents/e7bd8bc7-23fb-4f46-98dc-b0dcf11b75a1/error.txt +1 -0
  71. package/.code/agents/e92bec35-378d-4fe1-8ac0-6e1bb3c86911/error.txt +5 -0
  72. package/.code/agents/ed918fbf-2dc4-4aa2-bfc5-04b65d9471ea/error.txt +1 -0
  73. package/.code/agents/ef1d756f-b272-48fc-8729-f05c494674f7/error.txt +1 -0
  74. package/.code/agents/ef359853-0249-4e41-a804-c0fc459fe456/error.txt +1 -0
  75. package/.code/agents/effc7b4a-4b90-40a0-8c86-a7a99d2d5fd2/error.txt +1 -0
  76. package/.code/agents/fa15f8d5-8359-4a8b-83a3-2f2056b3ff40/error.txt +3 -0
  77. package/.code/agents/fbef4193-eadf-4c8a-83ff-4878a6310f25/error.txt +8 -0
  78. package/.code/agents/fd0a4b4a-fda4-4964-a6d6-2b8a2da387c6/error.txt +1 -0
  79. package/.dxtignore +57 -0
  80. package/.env.example +44 -0
  81. package/.gemini/settings.json +8 -0
  82. package/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  83. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  84. package/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  85. package/.github/ISSUE_TEMPLATE/release_checklist.md +31 -0
  86. package/.github/pull_request_template.md +41 -0
  87. package/.github/workflows/ci-tests.yml +41 -0
  88. package/.github/workflows/claude-code-review.yml +57 -0
  89. package/.github/workflows/claude.yml +50 -0
  90. package/.github/workflows/full-integration.yml +22 -0
  91. package/.github/workflows/pr-description-check.yml +88 -0
  92. package/.github/workflows/publish.yml +33 -0
  93. package/.github/workflows/release.yml +89 -0
  94. package/.mcpbignore +58 -0
  95. package/.prettierignore +10 -0
  96. package/.prettierrc.json +10 -0
  97. package/ADOS-2-Module-1-Complete-Manual.md +757 -0
  98. package/AGENTS.md +36 -0
  99. package/CHANGELOG.md +187 -0
  100. package/CLAUDE.md +414 -0
  101. package/CODEREVIEW_RESPONSE.md +128 -0
  102. package/LICENSE +17 -0
  103. package/NUL +1 -0
  104. package/README.md +222 -0
  105. package/SCHEMA_IMPROVEMENT_SUMMARY.md +120 -0
  106. package/TESTING_NOTES.md +217 -0
  107. package/WARP.md +245 -0
  108. package/accountactivity-merged.csv +149 -0
  109. package/bin/ynab-mcp-server.cjs +4 -0
  110. package/bin/ynab-mcp-server.js +8 -0
  111. package/bundle-analysis.html +13110 -0
  112. package/dist/bundle/index.cjs +124 -0
  113. package/dist/index.d.ts +2 -0
  114. package/dist/index.js +85 -0
  115. package/dist/server/YNABMCPServer.d.ts +264 -0
  116. package/dist/server/YNABMCPServer.js +845 -0
  117. package/dist/server/budgetResolver.d.ts +15 -0
  118. package/dist/server/budgetResolver.js +99 -0
  119. package/dist/server/cacheManager.d.ts +74 -0
  120. package/dist/server/cacheManager.js +306 -0
  121. package/dist/server/config.d.ts +3 -0
  122. package/dist/server/config.js +19 -0
  123. package/dist/server/deltaCache.d.ts +61 -0
  124. package/dist/server/deltaCache.js +206 -0
  125. package/dist/server/deltaCache.merge.d.ts +9 -0
  126. package/dist/server/deltaCache.merge.js +111 -0
  127. package/dist/server/diagnostics.d.ts +90 -0
  128. package/dist/server/diagnostics.js +163 -0
  129. package/dist/server/errorHandler.d.ts +69 -0
  130. package/dist/server/errorHandler.js +524 -0
  131. package/dist/server/prompts.d.ts +31 -0
  132. package/dist/server/prompts.js +205 -0
  133. package/dist/server/rateLimiter.d.ts +27 -0
  134. package/dist/server/rateLimiter.js +82 -0
  135. package/dist/server/requestLogger.d.ts +62 -0
  136. package/dist/server/requestLogger.js +190 -0
  137. package/dist/server/resources.d.ts +39 -0
  138. package/dist/server/resources.js +85 -0
  139. package/dist/server/responseFormatter.d.ts +14 -0
  140. package/dist/server/responseFormatter.js +42 -0
  141. package/dist/server/securityMiddleware.d.ts +87 -0
  142. package/dist/server/securityMiddleware.js +117 -0
  143. package/dist/server/serverKnowledgeStore.d.ts +11 -0
  144. package/dist/server/serverKnowledgeStore.js +42 -0
  145. package/dist/server/toolRegistry.d.ts +85 -0
  146. package/dist/server/toolRegistry.js +272 -0
  147. package/dist/tools/__tests__/deltaTestUtils.d.ts +18 -0
  148. package/dist/tools/__tests__/deltaTestUtils.js +26 -0
  149. package/dist/tools/accountTools.d.ts +37 -0
  150. package/dist/tools/accountTools.js +175 -0
  151. package/dist/tools/budgetTools.d.ts +10 -0
  152. package/dist/tools/budgetTools.js +68 -0
  153. package/dist/tools/categoryTools.d.ts +27 -0
  154. package/dist/tools/categoryTools.js +232 -0
  155. package/dist/tools/compareTransactions/formatter.d.ts +71 -0
  156. package/dist/tools/compareTransactions/formatter.js +97 -0
  157. package/dist/tools/compareTransactions/index.d.ts +30 -0
  158. package/dist/tools/compareTransactions/index.js +160 -0
  159. package/dist/tools/compareTransactions/matcher.d.ts +12 -0
  160. package/dist/tools/compareTransactions/matcher.js +140 -0
  161. package/dist/tools/compareTransactions/parser.d.ts +14 -0
  162. package/dist/tools/compareTransactions/parser.js +430 -0
  163. package/dist/tools/compareTransactions/types.d.ts +27 -0
  164. package/dist/tools/compareTransactions/types.js +1 -0
  165. package/dist/tools/compareTransactions.d.ts +1 -0
  166. package/dist/tools/compareTransactions.js +1 -0
  167. package/dist/tools/deltaFetcher.d.ts +22 -0
  168. package/dist/tools/deltaFetcher.js +137 -0
  169. package/dist/tools/deltaSupport.d.ts +20 -0
  170. package/dist/tools/deltaSupport.js +176 -0
  171. package/dist/tools/exportTransactions.d.ts +17 -0
  172. package/dist/tools/exportTransactions.js +191 -0
  173. package/dist/tools/monthTools.d.ts +16 -0
  174. package/dist/tools/monthTools.js +107 -0
  175. package/dist/tools/payeeTools.d.ts +17 -0
  176. package/dist/tools/payeeTools.js +82 -0
  177. package/dist/tools/reconcileAdapter.d.ts +25 -0
  178. package/dist/tools/reconcileAdapter.js +167 -0
  179. package/dist/tools/reconciliation/analyzer.d.ts +3 -0
  180. package/dist/tools/reconciliation/analyzer.js +567 -0
  181. package/dist/tools/reconciliation/executor.d.ts +94 -0
  182. package/dist/tools/reconciliation/executor.js +611 -0
  183. package/dist/tools/reconciliation/index.d.ts +54 -0
  184. package/dist/tools/reconciliation/index.js +249 -0
  185. package/dist/tools/reconciliation/matcher.d.ts +3 -0
  186. package/dist/tools/reconciliation/matcher.js +160 -0
  187. package/dist/tools/reconciliation/payeeNormalizer.d.ts +6 -0
  188. package/dist/tools/reconciliation/payeeNormalizer.js +77 -0
  189. package/dist/tools/reconciliation/recommendationEngine.d.ts +2 -0
  190. package/dist/tools/reconciliation/recommendationEngine.js +273 -0
  191. package/dist/tools/reconciliation/reportFormatter.d.ts +13 -0
  192. package/dist/tools/reconciliation/reportFormatter.js +214 -0
  193. package/dist/tools/reconciliation/types.d.ts +172 -0
  194. package/dist/tools/reconciliation/types.js +7 -0
  195. package/dist/tools/schemas/outputs/accountOutputs.d.ts +58 -0
  196. package/dist/tools/schemas/outputs/accountOutputs.js +24 -0
  197. package/dist/tools/schemas/outputs/budgetOutputs.d.ts +48 -0
  198. package/dist/tools/schemas/outputs/budgetOutputs.js +15 -0
  199. package/dist/tools/schemas/outputs/categoryOutputs.d.ts +93 -0
  200. package/dist/tools/schemas/outputs/categoryOutputs.js +37 -0
  201. package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +269 -0
  202. package/dist/tools/schemas/outputs/comparisonOutputs.js +181 -0
  203. package/dist/tools/schemas/outputs/index.d.ts +14 -0
  204. package/dist/tools/schemas/outputs/index.js +14 -0
  205. package/dist/tools/schemas/outputs/monthOutputs.d.ts +122 -0
  206. package/dist/tools/schemas/outputs/monthOutputs.js +51 -0
  207. package/dist/tools/schemas/outputs/payeeOutputs.d.ts +34 -0
  208. package/dist/tools/schemas/outputs/payeeOutputs.js +16 -0
  209. package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +1275 -0
  210. package/dist/tools/schemas/outputs/reconciliationOutputs.js +377 -0
  211. package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +717 -0
  212. package/dist/tools/schemas/outputs/transactionMutationOutputs.js +260 -0
  213. package/dist/tools/schemas/outputs/transactionOutputs.d.ts +98 -0
  214. package/dist/tools/schemas/outputs/transactionOutputs.js +49 -0
  215. package/dist/tools/schemas/outputs/utilityOutputs.d.ts +219 -0
  216. package/dist/tools/schemas/outputs/utilityOutputs.js +120 -0
  217. package/dist/tools/schemas/shared/commonOutputs.d.ts +24 -0
  218. package/dist/tools/schemas/shared/commonOutputs.js +27 -0
  219. package/dist/tools/toolCategories.d.ts +32 -0
  220. package/dist/tools/toolCategories.js +32 -0
  221. package/dist/tools/transactionTools.d.ts +315 -0
  222. package/dist/tools/transactionTools.js +1722 -0
  223. package/dist/tools/utilityTools.d.ts +10 -0
  224. package/dist/tools/utilityTools.js +56 -0
  225. package/dist/types/index.d.ts +20 -0
  226. package/dist/types/index.js +16 -0
  227. package/dist/types/toolAnnotations.d.ts +7 -0
  228. package/dist/types/toolAnnotations.js +1 -0
  229. package/dist/utils/amountUtils.d.ts +3 -0
  230. package/dist/utils/amountUtils.js +10 -0
  231. package/dist/utils/dateUtils.d.ts +9 -0
  232. package/dist/utils/dateUtils.js +43 -0
  233. package/dist/utils/money.d.ts +21 -0
  234. package/dist/utils/money.js +51 -0
  235. package/docs/README.md +72 -0
  236. package/docs/assets/examples/reconciliation-with-recommendations.json +68 -0
  237. package/docs/assets/schemas/reconciliation-v2.json +338 -0
  238. package/docs/getting-started/CONFIGURATION.md +175 -0
  239. package/docs/getting-started/INSTALLATION.md +333 -0
  240. package/docs/getting-started/QUICKSTART.md +282 -0
  241. package/docs/guides/ARCHITECTURE.md +650 -0
  242. package/docs/guides/DEPLOYMENT.md +189 -0
  243. package/docs/guides/INTEGRATION_TESTING.md +730 -0
  244. package/docs/guides/TESTING.md +591 -0
  245. package/docs/reconciliation-flow.md +83 -0
  246. package/docs/reference/API.md +1450 -0
  247. package/docs/reference/EXAMPLES.md +946 -0
  248. package/docs/reference/TOOLS.md +348 -0
  249. package/docs/reference/TROUBLESHOOTING.md +481 -0
  250. package/esbuild.config.mjs +68 -0
  251. package/eslint.config.js +49 -0
  252. package/fix-types.sh +17 -0
  253. package/meta.json +12550 -0
  254. package/package.json +105 -0
  255. package/package.json.tmp +105 -0
  256. package/scripts/analyze-bundle.mjs +41 -0
  257. package/scripts/create-pr-description.js +203 -0
  258. package/scripts/generate-mcpb.ps1 +96 -0
  259. package/scripts/run-domain-integration-tests.js +33 -0
  260. package/scripts/run-generate-mcpb.js +29 -0
  261. package/scripts/run-throttled-integration-tests.js +116 -0
  262. package/scripts/test-delta-params.mjs +140 -0
  263. package/scripts/test-recommendations.ts +53 -0
  264. package/scripts/tmpTransaction.ts +48 -0
  265. package/scripts/validate-env.js +122 -0
  266. package/scripts/verify-build.js +105 -0
  267. package/scripts/watch-and-restart.ps1 +50 -0
  268. package/src/__tests__/comprehensive.integration.test.ts +1196 -0
  269. package/src/__tests__/delta.performance.test.ts +80 -0
  270. package/src/__tests__/performance.test.ts +725 -0
  271. package/src/__tests__/setup.ts +449 -0
  272. package/src/__tests__/testRunner.ts +444 -0
  273. package/src/__tests__/testUtils.ts +563 -0
  274. package/src/__tests__/workflows.e2e.test.ts +1675 -0
  275. package/src/index.ts +124 -0
  276. package/src/server/.gitkeep +1 -0
  277. package/src/server/YNABMCPServer.ts +1188 -0
  278. package/src/server/__tests__/YNABMCPServer.integration.test.ts +903 -0
  279. package/src/server/__tests__/YNABMCPServer.test.ts +894 -0
  280. package/src/server/__tests__/budgetResolver.test.ts +425 -0
  281. package/src/server/__tests__/cacheManager.test.ts +880 -0
  282. package/src/server/__tests__/config.test.ts +166 -0
  283. package/src/server/__tests__/deltaCache.merge.test.ts +724 -0
  284. package/src/server/__tests__/deltaCache.swr.test.ts +168 -0
  285. package/src/server/__tests__/deltaCache.test.ts +774 -0
  286. package/src/server/__tests__/diagnostics.test.ts +823 -0
  287. package/src/server/__tests__/errorHandler.integration.test.ts +466 -0
  288. package/src/server/__tests__/errorHandler.test.ts +416 -0
  289. package/src/server/__tests__/prompts.test.ts +354 -0
  290. package/src/server/__tests__/rateLimiter.test.ts +314 -0
  291. package/src/server/__tests__/requestLogger.test.ts +408 -0
  292. package/src/server/__tests__/resources.test.ts +299 -0
  293. package/src/server/__tests__/security.integration.test.ts +426 -0
  294. package/src/server/__tests__/securityMiddleware.test.ts +449 -0
  295. package/src/server/__tests__/server-startup.integration.test.ts +477 -0
  296. package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -0
  297. package/src/server/__tests__/toolRegistry.test.ts +855 -0
  298. package/src/server/budgetResolver.ts +235 -0
  299. package/src/server/cacheManager.ts +503 -0
  300. package/src/server/config.ts +41 -0
  301. package/src/server/deltaCache.merge.ts +149 -0
  302. package/src/server/deltaCache.ts +341 -0
  303. package/src/server/diagnostics.ts +338 -0
  304. package/src/server/errorHandler.ts +756 -0
  305. package/src/server/prompts.ts +291 -0
  306. package/src/server/rateLimiter.ts +156 -0
  307. package/src/server/requestLogger.ts +344 -0
  308. package/src/server/resources.ts +168 -0
  309. package/src/server/responseFormatter.ts +51 -0
  310. package/src/server/securityMiddleware.ts +236 -0
  311. package/src/server/serverKnowledgeStore.ts +91 -0
  312. package/src/server/toolRegistry.ts +489 -0
  313. package/src/tools/.gitkeep +1 -0
  314. package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -0
  315. package/src/tools/__tests__/accountTools.integration.test.ts +117 -0
  316. package/src/tools/__tests__/accountTools.test.ts +653 -0
  317. package/src/tools/__tests__/budgetTools.delta.integration.test.ts +90 -0
  318. package/src/tools/__tests__/budgetTools.integration.test.ts +134 -0
  319. package/src/tools/__tests__/budgetTools.test.ts +423 -0
  320. package/src/tools/__tests__/categoryTools.delta.integration.test.ts +80 -0
  321. package/src/tools/__tests__/categoryTools.integration.test.ts +295 -0
  322. package/src/tools/__tests__/categoryTools.test.ts +622 -0
  323. package/src/tools/__tests__/compareTransactions/formatter.test.ts +486 -0
  324. package/src/tools/__tests__/compareTransactions/index.test.ts +383 -0
  325. package/src/tools/__tests__/compareTransactions/matcher.test.ts +410 -0
  326. package/src/tools/__tests__/compareTransactions/parser.test.ts +764 -0
  327. package/src/tools/__tests__/compareTransactions.test.ts +342 -0
  328. package/src/tools/__tests__/compareTransactions.window.test.ts +147 -0
  329. package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +76 -0
  330. package/src/tools/__tests__/deltaFetcher.test.ts +270 -0
  331. package/src/tools/__tests__/deltaSupport.test.ts +188 -0
  332. package/src/tools/__tests__/deltaTestUtils.ts +46 -0
  333. package/src/tools/__tests__/exportTransactions.test.ts +213 -0
  334. package/src/tools/__tests__/monthTools.delta.integration.test.ts +80 -0
  335. package/src/tools/__tests__/monthTools.integration.test.ts +174 -0
  336. package/src/tools/__tests__/monthTools.test.ts +523 -0
  337. package/src/tools/__tests__/payeeTools.delta.integration.test.ts +80 -0
  338. package/src/tools/__tests__/payeeTools.integration.test.ts +150 -0
  339. package/src/tools/__tests__/payeeTools.test.ts +445 -0
  340. package/src/tools/__tests__/transactionTools.integration.test.ts +762 -0
  341. package/src/tools/__tests__/transactionTools.test.ts +3521 -0
  342. package/src/tools/__tests__/utilityTools.integration.test.ts +128 -0
  343. package/src/tools/__tests__/utilityTools.test.ts +205 -0
  344. package/src/tools/accountTools.ts +283 -0
  345. package/src/tools/budgetTools.ts +112 -0
  346. package/src/tools/categoryTools.ts +366 -0
  347. package/src/tools/compareTransactions/formatter.ts +163 -0
  348. package/src/tools/compareTransactions/index.ts +228 -0
  349. package/src/tools/compareTransactions/matcher.ts +240 -0
  350. package/src/tools/compareTransactions/parser.ts +557 -0
  351. package/src/tools/compareTransactions/types.ts +60 -0
  352. package/src/tools/compareTransactions.ts +3 -0
  353. package/src/tools/deltaFetcher.ts +278 -0
  354. package/src/tools/deltaSupport.ts +293 -0
  355. package/src/tools/exportTransactions.ts +273 -0
  356. package/src/tools/monthTools.ts +164 -0
  357. package/src/tools/payeeTools.ts +140 -0
  358. package/src/tools/reconcileAdapter.ts +312 -0
  359. package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +122 -0
  360. package/src/tools/reconciliation/__tests__/adapter.test.ts +234 -0
  361. package/src/tools/reconciliation/__tests__/analyzer.test.ts +406 -0
  362. package/src/tools/reconciliation/__tests__/executor.integration.test.ts +366 -0
  363. package/src/tools/reconciliation/__tests__/executor.test.ts +779 -0
  364. package/src/tools/reconciliation/__tests__/matcher.test.ts +650 -0
  365. package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +278 -0
  366. package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +658 -0
  367. package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1000 -0
  368. package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +151 -0
  369. package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +573 -0
  370. package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +78 -0
  371. package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +47 -0
  372. package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +61 -0
  373. package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +49 -0
  374. package/src/tools/reconciliation/analyzer.ts +824 -0
  375. package/src/tools/reconciliation/executor.ts +880 -0
  376. package/src/tools/reconciliation/index.ts +400 -0
  377. package/src/tools/reconciliation/matcher.ts +269 -0
  378. package/src/tools/reconciliation/payeeNormalizer.ts +167 -0
  379. package/src/tools/reconciliation/recommendationEngine.ts +506 -0
  380. package/src/tools/reconciliation/reportFormatter.ts +363 -0
  381. package/src/tools/reconciliation/types.ts +314 -0
  382. package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +424 -0
  383. package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +310 -0
  384. package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +448 -0
  385. package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +519 -0
  386. package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +155 -0
  387. package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +288 -0
  388. package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +478 -0
  389. package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +370 -0
  390. package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +401 -0
  391. package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +213 -0
  392. package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +474 -0
  393. package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +333 -0
  394. package/src/tools/schemas/outputs/accountOutputs.ts +137 -0
  395. package/src/tools/schemas/outputs/budgetOutputs.ts +86 -0
  396. package/src/tools/schemas/outputs/categoryOutputs.ts +194 -0
  397. package/src/tools/schemas/outputs/comparisonOutputs.ts +600 -0
  398. package/src/tools/schemas/outputs/index.ts +270 -0
  399. package/src/tools/schemas/outputs/monthOutputs.ts +243 -0
  400. package/src/tools/schemas/outputs/payeeOutputs.ts +105 -0
  401. package/src/tools/schemas/outputs/reconciliationOutputs.ts +796 -0
  402. package/src/tools/schemas/outputs/transactionMutationOutputs.ts +758 -0
  403. package/src/tools/schemas/outputs/transactionOutputs.ts +243 -0
  404. package/src/tools/schemas/outputs/utilityOutputs.ts +411 -0
  405. package/src/tools/schemas/shared/commonOutputs.ts +140 -0
  406. package/src/tools/toolCategories.ts +140 -0
  407. package/src/tools/transactionTools.ts +2509 -0
  408. package/src/tools/utilityTools.ts +90 -0
  409. package/src/types/.gitkeep +1 -0
  410. package/src/types/__tests__/index.test.ts +52 -0
  411. package/src/types/index.ts +67 -0
  412. package/src/types/integration-tests.d.ts +35 -0
  413. package/src/types/toolAnnotations.ts +44 -0
  414. package/src/utils/__tests__/dateUtils.test.ts +170 -0
  415. package/src/utils/__tests__/money.test.ts +189 -0
  416. package/src/utils/amountUtils.ts +32 -0
  417. package/src/utils/dateUtils.ts +108 -0
  418. package/src/utils/money.ts +123 -0
  419. package/test-csv-sample.csv +28 -0
  420. package/test-exports/sample_bank_statement.csv +7 -0
  421. package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_09-04-53.json +23 -0
  422. package/test-exports/ynab_account_e9ddc2a6_minimal_1items_2025-11-19_10-37-42.json +23 -0
  423. package/test-exports/ynab_account_e9ddc2a6_minimal_4items_2025-11-19_09-02-09.json +44 -0
  424. package/test-exports/ynab_account_e9ddc2a6_minimal_6items_2025-11-19_10-37-52.json +58 -0
  425. package/test-exports/ynab_since_2025-11-01_account_4c18e9f0_minimal_14items_2025-11-16_10-07-10.json +115 -0
  426. package/test-reconcile-autodetect.js +40 -0
  427. package/test-reconcile-tool.js +152 -0
  428. package/test-reconcile-with-csv.cjs +89 -0
  429. package/test-statement.csv +8 -0
  430. package/test_debug.js +47 -0
  431. package/test_simple.mjs +16 -0
  432. package/tsconfig.json +31 -0
  433. package/tsconfig.prod.json +18 -0
  434. package/vitest-reporters/split-json-reporter.ts +211 -0
  435. package/vitest.config.ts +96 -0
@@ -0,0 +1,176 @@
1
+ import { cacheManager } from '../server/cacheManager.js';
2
+ import { DeltaCache } from '../server/deltaCache.js';
3
+ import { ServerKnowledgeStore } from '../server/serverKnowledgeStore.js';
4
+ import { DeltaFetcher } from './deltaFetcher.js';
5
+ let sharedDeltaContext;
6
+ export function setSharedDeltaSupport(options) {
7
+ if (!options) {
8
+ sharedDeltaContext = undefined;
9
+ return;
10
+ }
11
+ sharedDeltaContext = {
12
+ ...options,
13
+ manuallyConfigured: true,
14
+ };
15
+ }
16
+ export function getSharedDeltaSupport() {
17
+ if (!sharedDeltaContext) {
18
+ return undefined;
19
+ }
20
+ const result = {};
21
+ if (sharedDeltaContext.deltaFetcher) {
22
+ result.deltaFetcher = sharedDeltaContext.deltaFetcher;
23
+ }
24
+ if (sharedDeltaContext.deltaCache) {
25
+ result.deltaCache = sharedDeltaContext.deltaCache;
26
+ }
27
+ if (sharedDeltaContext.knowledgeStore) {
28
+ result.knowledgeStore = sharedDeltaContext.knowledgeStore;
29
+ }
30
+ return result;
31
+ }
32
+ function resolveSharedDeltaFetcher(ynabAPI) {
33
+ if (sharedDeltaContext &&
34
+ !sharedDeltaContext.manuallyConfigured &&
35
+ sharedDeltaContext.ynabAPI &&
36
+ sharedDeltaContext.ynabAPI !== ynabAPI) {
37
+ sharedDeltaContext = undefined;
38
+ }
39
+ if (sharedDeltaContext?.deltaFetcher) {
40
+ return sharedDeltaContext.deltaFetcher;
41
+ }
42
+ const context = sharedDeltaContext ? { ...sharedDeltaContext } : {};
43
+ if (context.manuallyConfigured === undefined) {
44
+ context.manuallyConfigured = false;
45
+ }
46
+ if (!context.deltaCache) {
47
+ if (!context.knowledgeStore) {
48
+ context.knowledgeStore = new ServerKnowledgeStore();
49
+ }
50
+ context.deltaCache = new DeltaCache(cacheManager, context.knowledgeStore);
51
+ }
52
+ const deltaFetcher = new DeltaFetcher(ynabAPI, context.deltaCache);
53
+ context.deltaFetcher = deltaFetcher;
54
+ if (!context.ynabAPI) {
55
+ context.ynabAPI = ynabAPI;
56
+ }
57
+ sharedDeltaContext = context;
58
+ return deltaFetcher;
59
+ }
60
+ function isDeltaFetcher(value) {
61
+ return (value !== null &&
62
+ typeof value === 'object' &&
63
+ value instanceof DeltaFetcher &&
64
+ typeof value.fetchAccounts === 'function' &&
65
+ typeof value.fetchCategories === 'function');
66
+ }
67
+ function isDeltaCache(value) {
68
+ return (value !== null &&
69
+ typeof value === 'object' &&
70
+ value instanceof DeltaCache &&
71
+ typeof value.fetchWithDelta === 'function');
72
+ }
73
+ function isServerKnowledgeStore(value) {
74
+ return (value !== null &&
75
+ typeof value === 'object' &&
76
+ value instanceof ServerKnowledgeStore &&
77
+ typeof value.get === 'function' &&
78
+ typeof value.update === 'function');
79
+ }
80
+ function isParamsObject(value) {
81
+ return (value !== null &&
82
+ typeof value === 'object' &&
83
+ !Array.isArray(value) &&
84
+ (value.constructor === Object || value.constructor === undefined));
85
+ }
86
+ function getTypeName(value) {
87
+ if (value === null)
88
+ return 'null';
89
+ if (value === undefined)
90
+ return 'undefined';
91
+ const type = typeof value;
92
+ if (type !== 'object')
93
+ return type;
94
+ const constructorName = value.constructor?.name;
95
+ return constructorName ? `${type} (${constructorName})` : type;
96
+ }
97
+ export function resolveDeltaFetcherArgs(ynabAPI, deltaFetcherOrParams, maybeParams) {
98
+ if (maybeParams !== undefined) {
99
+ if (!isDeltaFetcher(deltaFetcherOrParams)) {
100
+ throw new Error('resolveDeltaFetcherArgs: When providing 3 arguments, the second argument must be a DeltaFetcher instance. ' +
101
+ `Got: ${getTypeName(deltaFetcherOrParams)}`);
102
+ }
103
+ if (!isParamsObject(maybeParams)) {
104
+ throw new Error('resolveDeltaFetcherArgs: When providing 3 arguments, the third argument must be a params object. ' +
105
+ `Got: ${getTypeName(maybeParams)}`);
106
+ }
107
+ return {
108
+ deltaFetcher: deltaFetcherOrParams,
109
+ params: maybeParams,
110
+ };
111
+ }
112
+ if (isDeltaFetcher(deltaFetcherOrParams)) {
113
+ throw new Error('resolveDeltaFetcherArgs: When providing 2 arguments, the second argument must be a params object, not a DeltaFetcher. ' +
114
+ 'To use a custom DeltaFetcher, provide all 3 arguments: (ynabAPI, deltaFetcher, params)');
115
+ }
116
+ if (!isParamsObject(deltaFetcherOrParams)) {
117
+ throw new Error('resolveDeltaFetcherArgs: When providing 2 arguments, the second argument must be a params object. ' +
118
+ `Got: ${getTypeName(deltaFetcherOrParams)}`);
119
+ }
120
+ return {
121
+ deltaFetcher: resolveSharedDeltaFetcher(ynabAPI),
122
+ params: deltaFetcherOrParams,
123
+ };
124
+ }
125
+ export function resolveDeltaWriteArgs(deltaCacheOrParams, knowledgeStoreOrParams, maybeParams) {
126
+ if (maybeParams !== undefined) {
127
+ if (!isDeltaCache(deltaCacheOrParams)) {
128
+ throw new Error('resolveDeltaWriteArgs: When providing 3 arguments, the first argument must be a DeltaCache instance. ' +
129
+ `Got: ${getTypeName(deltaCacheOrParams)}`);
130
+ }
131
+ if (!isServerKnowledgeStore(knowledgeStoreOrParams)) {
132
+ throw new Error('resolveDeltaWriteArgs: When providing 3 arguments, the second argument must be a ServerKnowledgeStore instance. ' +
133
+ `Got: ${getTypeName(knowledgeStoreOrParams)}`);
134
+ }
135
+ if (!isParamsObject(maybeParams)) {
136
+ throw new Error('resolveDeltaWriteArgs: When providing 3 arguments, the third argument must be a params object. ' +
137
+ `Got: ${getTypeName(maybeParams)}`);
138
+ }
139
+ return {
140
+ deltaCache: deltaCacheOrParams,
141
+ knowledgeStore: knowledgeStoreOrParams,
142
+ params: maybeParams,
143
+ };
144
+ }
145
+ if (knowledgeStoreOrParams !== undefined) {
146
+ const isKnowledgeStore = isServerKnowledgeStore(knowledgeStoreOrParams);
147
+ const isParams = isParamsObject(knowledgeStoreOrParams);
148
+ if (!isKnowledgeStore && !isParams) {
149
+ throw new Error('resolveDeltaWriteArgs: When providing 2 arguments, the second argument must be either a ServerKnowledgeStore or a params object. ' +
150
+ `Got: ${getTypeName(knowledgeStoreOrParams)}`);
151
+ }
152
+ if (isParams) {
153
+ throw new Error('resolveDeltaWriteArgs: Invalid argument combination. When providing 2 arguments where the second is a params object, ' +
154
+ 'this is ambiguous. Either provide 1 argument (params only) or 3 arguments (deltaCache, knowledgeStore, params).');
155
+ }
156
+ if (isKnowledgeStore) {
157
+ throw new Error('resolveDeltaWriteArgs: When providing DeltaCache and ServerKnowledgeStore, you must also provide params as the third argument. ' +
158
+ 'Got 2 arguments, expected 3: (deltaCache, knowledgeStore, params)');
159
+ }
160
+ }
161
+ if (isDeltaCache(deltaCacheOrParams)) {
162
+ throw new Error('resolveDeltaWriteArgs: When providing only 1 argument, it must be a params object, not a DeltaCache. ' +
163
+ 'To use a custom DeltaCache, provide all 3 arguments: (deltaCache, knowledgeStore, params)');
164
+ }
165
+ if (!isParamsObject(deltaCacheOrParams)) {
166
+ throw new Error('resolveDeltaWriteArgs: When providing only 1 argument, it must be a params object. ' +
167
+ `Got: ${getTypeName(deltaCacheOrParams)}`);
168
+ }
169
+ const fallbackKnowledgeStore = new ServerKnowledgeStore();
170
+ const fallbackDeltaCache = new DeltaCache(cacheManager, fallbackKnowledgeStore);
171
+ return {
172
+ deltaCache: fallbackDeltaCache,
173
+ knowledgeStore: fallbackKnowledgeStore,
174
+ params: deltaCacheOrParams,
175
+ };
176
+ }
@@ -0,0 +1,17 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import * as ynab from 'ynab';
3
+ import { z } from 'zod/v4';
4
+ export declare const ExportTransactionsSchema: z.ZodObject<{
5
+ budget_id: z.ZodString;
6
+ account_id: z.ZodOptional<z.ZodString>;
7
+ category_id: z.ZodOptional<z.ZodString>;
8
+ since_date: z.ZodOptional<z.ZodString>;
9
+ type: z.ZodOptional<z.ZodEnum<{
10
+ uncategorized: "uncategorized";
11
+ unapproved: "unapproved";
12
+ }>>;
13
+ filename: z.ZodOptional<z.ZodString>;
14
+ minimal: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15
+ }, z.core.$strict>;
16
+ export type ExportTransactionsParams = z.infer<typeof ExportTransactionsSchema>;
17
+ export declare function handleExportTransactions(ynabAPI: ynab.API, params: ExportTransactionsParams): Promise<CallToolResult>;
@@ -0,0 +1,191 @@
1
+ import { z } from 'zod/v4';
2
+ import { withToolErrorHandling } from '../types/index.js';
3
+ import { responseFormatter } from '../server/responseFormatter.js';
4
+ import { writeFileSync, mkdirSync } from 'fs';
5
+ import { format } from 'date-fns';
6
+ import { join, resolve } from 'path';
7
+ import { homedir } from 'os';
8
+ export const ExportTransactionsSchema = z
9
+ .object({
10
+ budget_id: z.string().min(1, 'Budget ID is required'),
11
+ account_id: z.string().optional(),
12
+ category_id: z.string().optional(),
13
+ since_date: z
14
+ .string()
15
+ .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in ISO format (YYYY-MM-DD)')
16
+ .optional(),
17
+ type: z.enum(['uncategorized', 'unapproved']).optional(),
18
+ filename: z.string().optional(),
19
+ minimal: z.boolean().optional().default(true),
20
+ })
21
+ .strict();
22
+ function generateExportFilename(params, transactionCount) {
23
+ if (params.filename) {
24
+ return params.filename.endsWith('.json') ? params.filename : `${params.filename}.json`;
25
+ }
26
+ const timestamp = format(new Date(), 'yyyy-MM-dd_HH-mm-ss');
27
+ let description = 'transactions';
28
+ const filters = [];
29
+ if (params.since_date) {
30
+ filters.push(`since_${params.since_date}`);
31
+ }
32
+ if (params.account_id) {
33
+ filters.push(`account_${params.account_id.substring(0, 8)}`);
34
+ }
35
+ if (params.category_id) {
36
+ filters.push(`category_${params.category_id.substring(0, 8)}`);
37
+ }
38
+ if (params.type) {
39
+ filters.push(params.type);
40
+ }
41
+ if (params.minimal !== false) {
42
+ filters.push('minimal');
43
+ }
44
+ if (filters.length > 0) {
45
+ description = filters.join('_');
46
+ }
47
+ return `ynab_${description}_${transactionCount}items_${timestamp}.json`;
48
+ }
49
+ function getDefaultExportPath() {
50
+ const platform = process.platform;
51
+ const home = homedir();
52
+ switch (platform) {
53
+ case 'win32':
54
+ return join(home, 'Downloads');
55
+ case 'darwin':
56
+ return join(home, 'Downloads');
57
+ case 'linux':
58
+ case 'freebsd':
59
+ case 'openbsd':
60
+ case 'sunos':
61
+ case 'aix':
62
+ return process.env['XDG_DOCUMENTS_DIR'] || join(home, 'Documents');
63
+ default:
64
+ return join(home, 'Downloads');
65
+ }
66
+ }
67
+ function getExportPath() {
68
+ const exportPath = process.env['YNAB_EXPORT_PATH']?.trim();
69
+ let targetPath;
70
+ if (!exportPath) {
71
+ targetPath = getDefaultExportPath();
72
+ }
73
+ else {
74
+ if (exportPath.startsWith('~/')) {
75
+ targetPath = join(homedir(), exportPath.slice(2));
76
+ }
77
+ else {
78
+ targetPath = resolve(exportPath);
79
+ }
80
+ }
81
+ try {
82
+ mkdirSync(targetPath, { recursive: true });
83
+ }
84
+ catch (error) {
85
+ console.warn(`Failed to create export directory ${targetPath}, using platform default:`, error);
86
+ const fallbackPath = getDefaultExportPath();
87
+ try {
88
+ mkdirSync(fallbackPath, { recursive: true });
89
+ return fallbackPath;
90
+ }
91
+ catch (fallbackError) {
92
+ console.warn('Failed to create default folder, using current directory:', fallbackError);
93
+ return process.cwd();
94
+ }
95
+ }
96
+ return targetPath;
97
+ }
98
+ export async function handleExportTransactions(ynabAPI, params) {
99
+ return await withToolErrorHandling(async () => {
100
+ let response;
101
+ if (params.account_id) {
102
+ response = await ynabAPI.transactions.getTransactionsByAccount(params.budget_id, params.account_id, params.since_date);
103
+ }
104
+ else if (params.category_id) {
105
+ response = await ynabAPI.transactions.getTransactionsByCategory(params.budget_id, params.category_id, params.since_date);
106
+ }
107
+ else {
108
+ response = await ynabAPI.transactions.getTransactions(params.budget_id, params.since_date, params.type);
109
+ }
110
+ const transactions = response.data.transactions;
111
+ const exportDir = getExportPath();
112
+ const filename = generateExportFilename(params, transactions.length);
113
+ const fullPath = join(exportDir, filename);
114
+ const exportData = {
115
+ export_info: {
116
+ exported_at: new Date().toISOString(),
117
+ total_transactions: transactions.length,
118
+ minimal: params.minimal !== false,
119
+ filters: {
120
+ budget_id: params.budget_id,
121
+ account_id: params.account_id || null,
122
+ category_id: params.category_id || null,
123
+ since_date: params.since_date || null,
124
+ type: params.type || null,
125
+ },
126
+ },
127
+ transactions: transactions.map((transaction) => {
128
+ if (params.minimal !== false) {
129
+ return {
130
+ id: transaction.id,
131
+ date: transaction.date,
132
+ amount: transaction.amount,
133
+ payee_name: transaction.payee_name,
134
+ cleared: transaction.cleared,
135
+ };
136
+ }
137
+ else {
138
+ return {
139
+ id: transaction.id,
140
+ date: transaction.date,
141
+ amount: transaction.amount,
142
+ memo: transaction.memo,
143
+ cleared: transaction.cleared,
144
+ approved: transaction.approved,
145
+ flag_color: transaction.flag_color,
146
+ account_id: transaction.account_id,
147
+ payee_id: transaction.payee_id,
148
+ category_id: transaction.category_id,
149
+ transfer_account_id: transaction.transfer_account_id,
150
+ transfer_transaction_id: transaction.transfer_transaction_id,
151
+ matched_transaction_id: transaction.matched_transaction_id,
152
+ import_id: transaction.import_id,
153
+ deleted: transaction.deleted,
154
+ account_name: transaction.account_name,
155
+ payee_name: transaction.payee_name,
156
+ category_name: transaction.category_name,
157
+ };
158
+ }
159
+ }),
160
+ };
161
+ writeFileSync(fullPath, JSON.stringify(exportData, null, 2), 'utf-8');
162
+ const previewCount = Math.min(10, transactions.length);
163
+ const preview = transactions.slice(0, previewCount);
164
+ return {
165
+ content: [
166
+ {
167
+ type: 'text',
168
+ text: responseFormatter.format({
169
+ message: `Successfully exported ${transactions.length} transactions${params.minimal !== false ? ' (minimal fields)' : ' (full fields)'}`,
170
+ filename: filename,
171
+ full_path: fullPath,
172
+ export_directory: exportDir,
173
+ export_mode: params.minimal !== false ? 'minimal' : 'full',
174
+ minimal_fields: params.minimal !== false ? 'id, date, amount, payee_name, cleared' : null,
175
+ filename_explanation: 'Filename format: ynab_{filters}_{count}items_{timestamp}.json - identifies what data was exported, when, and how many transactions',
176
+ preview_count: previewCount,
177
+ total_count: transactions.length,
178
+ preview_transactions: preview.map((transaction) => ({
179
+ id: transaction.id,
180
+ date: transaction.date,
181
+ amount: transaction.amount,
182
+ memo: transaction.memo,
183
+ payee_name: transaction.payee_name,
184
+ category_name: transaction.category_name,
185
+ })),
186
+ }),
187
+ },
188
+ ],
189
+ };
190
+ }, 'ynab:export_transactions', 'exporting transactions');
191
+ }
@@ -0,0 +1,16 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import * as ynab from 'ynab';
3
+ import { z } from 'zod/v4';
4
+ import type { DeltaFetcher } from './deltaFetcher.js';
5
+ export declare const GetMonthSchema: z.ZodObject<{
6
+ budget_id: z.ZodString;
7
+ month: z.ZodString;
8
+ }, z.core.$strict>;
9
+ export type GetMonthParams = z.infer<typeof GetMonthSchema>;
10
+ export declare const ListMonthsSchema: z.ZodObject<{
11
+ budget_id: z.ZodString;
12
+ }, z.core.$strict>;
13
+ export type ListMonthsParams = z.infer<typeof ListMonthsSchema>;
14
+ export declare function handleGetMonth(ynabAPI: ynab.API, params: GetMonthParams): Promise<CallToolResult>;
15
+ export declare function handleListMonths(ynabAPI: ynab.API, deltaFetcher: DeltaFetcher, params: ListMonthsParams): Promise<CallToolResult>;
16
+ export declare function handleListMonths(ynabAPI: ynab.API, params: ListMonthsParams): Promise<CallToolResult>;
@@ -0,0 +1,107 @@
1
+ import { z } from 'zod/v4';
2
+ import { withToolErrorHandling } from '../types/index.js';
3
+ import { responseFormatter } from '../server/responseFormatter.js';
4
+ import { milliunitsToAmount } from '../utils/amountUtils.js';
5
+ import { cacheManager, CACHE_TTLS, CacheManager } from '../server/cacheManager.js';
6
+ import { resolveDeltaFetcherArgs } from './deltaSupport.js';
7
+ export const GetMonthSchema = z
8
+ .object({
9
+ budget_id: z.string().min(1, 'Budget ID is required'),
10
+ month: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Month must be in YYYY-MM-DD format'),
11
+ })
12
+ .strict();
13
+ export const ListMonthsSchema = z
14
+ .object({
15
+ budget_id: z.string().min(1, 'Budget ID is required'),
16
+ })
17
+ .strict();
18
+ export async function handleGetMonth(ynabAPI, params) {
19
+ return await withToolErrorHandling(async () => {
20
+ const cacheKey = CacheManager.generateKey('month', 'get', params.budget_id, params.month);
21
+ const wasCached = cacheManager.has(cacheKey);
22
+ const month = await cacheManager.wrap(cacheKey, {
23
+ ttl: CACHE_TTLS.MONTHS,
24
+ loader: async () => {
25
+ const response = await ynabAPI.months.getBudgetMonth(params.budget_id, params.month);
26
+ return response.data.month;
27
+ },
28
+ });
29
+ return {
30
+ content: [
31
+ {
32
+ type: 'text',
33
+ text: responseFormatter.format({
34
+ month: {
35
+ month: month.month,
36
+ note: month.note,
37
+ income: milliunitsToAmount(month.income),
38
+ budgeted: milliunitsToAmount(month.budgeted),
39
+ activity: milliunitsToAmount(month.activity),
40
+ to_be_budgeted: milliunitsToAmount(month.to_be_budgeted),
41
+ age_of_money: month.age_of_money,
42
+ deleted: month.deleted,
43
+ categories: month.categories?.map((category) => ({
44
+ id: category.id,
45
+ category_group_id: category.category_group_id,
46
+ category_group_name: category.category_group_name,
47
+ name: category.name,
48
+ hidden: category.hidden,
49
+ original_category_group_id: category.original_category_group_id,
50
+ note: category.note,
51
+ budgeted: milliunitsToAmount(category.budgeted),
52
+ activity: milliunitsToAmount(category.activity),
53
+ balance: milliunitsToAmount(category.balance),
54
+ goal_type: category.goal_type,
55
+ goal_creation_month: category.goal_creation_month,
56
+ goal_target: category.goal_target,
57
+ goal_target_month: category.goal_target_month,
58
+ goal_percentage_complete: category.goal_percentage_complete,
59
+ goal_months_to_budget: category.goal_months_to_budget,
60
+ goal_under_funded: category.goal_under_funded,
61
+ goal_overall_funded: category.goal_overall_funded,
62
+ goal_overall_left: category.goal_overall_left,
63
+ deleted: category.deleted,
64
+ })),
65
+ },
66
+ cached: wasCached,
67
+ cache_info: wasCached
68
+ ? 'Data retrieved from cache for improved performance'
69
+ : 'Fresh data retrieved from YNAB API',
70
+ }),
71
+ },
72
+ ],
73
+ };
74
+ }, 'ynab:get_month', 'getting month data');
75
+ }
76
+ export async function handleListMonths(ynabAPI, deltaFetcherOrParams, maybeParams) {
77
+ const { deltaFetcher, params } = resolveDeltaFetcherArgs(ynabAPI, deltaFetcherOrParams, maybeParams);
78
+ return await withToolErrorHandling(async () => {
79
+ const result = await deltaFetcher.fetchMonths(params.budget_id);
80
+ const months = result.data;
81
+ const wasCached = result.wasCached;
82
+ const usedDelta = result.usedDelta;
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text',
87
+ text: responseFormatter.format({
88
+ months: months.map((month) => ({
89
+ month: month.month,
90
+ note: month.note,
91
+ income: milliunitsToAmount(month.income),
92
+ budgeted: milliunitsToAmount(month.budgeted),
93
+ activity: milliunitsToAmount(month.activity),
94
+ to_be_budgeted: milliunitsToAmount(month.to_be_budgeted),
95
+ age_of_money: month.age_of_money,
96
+ deleted: month.deleted,
97
+ })),
98
+ cached: wasCached,
99
+ cache_info: wasCached
100
+ ? `Data retrieved from cache for improved performance${usedDelta ? ' (delta merge applied)' : ''}`
101
+ : 'Fresh data retrieved from YNAB API',
102
+ }),
103
+ },
104
+ ],
105
+ };
106
+ }, 'ynab:list_months', 'listing months');
107
+ }
@@ -0,0 +1,17 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import * as ynab from 'ynab';
3
+ import { z } from 'zod/v4';
4
+ import type { DeltaFetcher } from './deltaFetcher.js';
5
+ export declare const ListPayeesSchema: z.ZodObject<{
6
+ budget_id: z.ZodString;
7
+ limit: z.ZodOptional<z.ZodNumber>;
8
+ }, z.core.$strict>;
9
+ export type ListPayeesParams = z.infer<typeof ListPayeesSchema>;
10
+ export declare const GetPayeeSchema: z.ZodObject<{
11
+ budget_id: z.ZodString;
12
+ payee_id: z.ZodString;
13
+ }, z.core.$strict>;
14
+ export type GetPayeeParams = z.infer<typeof GetPayeeSchema>;
15
+ export declare function handleListPayees(ynabAPI: ynab.API, deltaFetcher: DeltaFetcher, params: ListPayeesParams): Promise<CallToolResult>;
16
+ export declare function handleListPayees(ynabAPI: ynab.API, params: ListPayeesParams): Promise<CallToolResult>;
17
+ export declare function handleGetPayee(ynabAPI: ynab.API, params: GetPayeeParams): Promise<CallToolResult>;
@@ -0,0 +1,82 @@
1
+ import { z } from 'zod/v4';
2
+ import { withToolErrorHandling } from '../types/index.js';
3
+ import { responseFormatter } from '../server/responseFormatter.js';
4
+ import { cacheManager, CACHE_TTLS, CacheManager } from '../server/cacheManager.js';
5
+ import { resolveDeltaFetcherArgs } from './deltaSupport.js';
6
+ export const ListPayeesSchema = z
7
+ .object({
8
+ budget_id: z.string().min(1, 'Budget ID is required'),
9
+ limit: z.number().int().positive().optional(),
10
+ })
11
+ .strict();
12
+ export const GetPayeeSchema = z
13
+ .object({
14
+ budget_id: z.string().min(1, 'Budget ID is required'),
15
+ payee_id: z.string().min(1, 'Payee ID is required'),
16
+ })
17
+ .strict();
18
+ export async function handleListPayees(ynabAPI, deltaFetcherOrParams, maybeParams) {
19
+ const { deltaFetcher, params } = resolveDeltaFetcherArgs(ynabAPI, deltaFetcherOrParams, maybeParams);
20
+ return await withToolErrorHandling(async () => {
21
+ const result = await deltaFetcher.fetchPayees(params.budget_id);
22
+ let payees = result.data;
23
+ const wasCached = result.wasCached;
24
+ const totalCount = payees.length;
25
+ if (params.limit !== undefined) {
26
+ payees = payees.slice(0, params.limit);
27
+ }
28
+ return {
29
+ content: [
30
+ {
31
+ type: 'text',
32
+ text: responseFormatter.format({
33
+ payees: payees.map((payee) => ({
34
+ id: payee.id,
35
+ name: payee.name,
36
+ transfer_account_id: payee.transfer_account_id,
37
+ deleted: payee.deleted,
38
+ })),
39
+ total_count: totalCount,
40
+ returned_count: payees.length,
41
+ cached: wasCached,
42
+ cache_info: wasCached
43
+ ? `Data retrieved from cache for improved performance${result.usedDelta ? ' (delta merge applied)' : ''}`
44
+ : 'Fresh data retrieved from YNAB API',
45
+ }),
46
+ },
47
+ ],
48
+ };
49
+ }, 'ynab:list_payees', 'listing payees');
50
+ }
51
+ export async function handleGetPayee(ynabAPI, params) {
52
+ return await withToolErrorHandling(async () => {
53
+ const cacheKey = CacheManager.generateKey('payee', 'get', params.budget_id, params.payee_id);
54
+ const wasCached = cacheManager.has(cacheKey);
55
+ const payee = await cacheManager.wrap(cacheKey, {
56
+ ttl: CACHE_TTLS.PAYEES,
57
+ loader: async () => {
58
+ const response = await ynabAPI.payees.getPayeeById(params.budget_id, params.payee_id);
59
+ return response.data.payee;
60
+ },
61
+ });
62
+ return {
63
+ content: [
64
+ {
65
+ type: 'text',
66
+ text: responseFormatter.format({
67
+ payee: {
68
+ id: payee.id,
69
+ name: payee.name,
70
+ transfer_account_id: payee.transfer_account_id,
71
+ deleted: payee.deleted,
72
+ },
73
+ cached: wasCached,
74
+ cache_info: wasCached
75
+ ? 'Data retrieved from cache for improved performance'
76
+ : 'Fresh data retrieved from YNAB API',
77
+ }),
78
+ },
79
+ ],
80
+ };
81
+ }, 'ynab:get_payee', 'getting payee details');
82
+ }
@@ -0,0 +1,25 @@
1
+ import type { ReconciliationAnalysis } from './reconciliation/types.js';
2
+ import type { LegacyReconciliationResult } from './reconciliation/executor.js';
3
+ interface AdapterOptions {
4
+ accountName?: string;
5
+ accountId?: string;
6
+ currencyCode?: string;
7
+ csvFormat?: CsvFormatPayload;
8
+ auditMetadata?: Record<string, unknown>;
9
+ }
10
+ interface DualChannelPayload {
11
+ human: string;
12
+ structured: Record<string, unknown>;
13
+ }
14
+ interface CsvFormatPayload {
15
+ delimiter: string;
16
+ decimal_separator: string;
17
+ thousands_separator: string | null;
18
+ date_format: string;
19
+ header_row: boolean;
20
+ date_column: string | null;
21
+ amount_column: string | null;
22
+ payee_column: string | null;
23
+ }
24
+ export declare const buildReconciliationPayload: (analysis: ReconciliationAnalysis, options?: AdapterOptions, execution?: LegacyReconciliationResult) => DualChannelPayload;
25
+ export {};