@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,116 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Runs the full integration suite with simple rate-limit-aware throttling.
4
+ */
5
+ import { spawn } from 'node:child_process';
6
+ import { readdirSync } from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ const RATE_LIMIT = Number(process.env['RATE_LIMIT_PER_HOUR'] ?? 200);
10
+ const RATE_LIMIT_BUFFER = Number(process.env['RATE_LIMIT_BUFFER'] ?? 20);
11
+ const RATE_LIMIT_WINDOW_MS = Number(process.env['RATE_LIMIT_WINDOW_MS'] ?? 60 * 60 * 1000);
12
+ const MAX_WAIT_MS = Number(process.env['RATE_LIMIT_MAX_WAIT_MS'] ?? 60 * 60 * 1000);
13
+ const projectRoot = process.cwd();
14
+
15
+ const testFiles = collectIntegrationTests(path.join(projectRoot, 'src'));
16
+ const toPosixPath = (value) => value.split(path.sep).join(path.posix.sep);
17
+ if (testFiles.length === 0) {
18
+ console.error('No integration test files found.');
19
+ process.exit(1);
20
+ }
21
+
22
+ const requestHistory = [];
23
+
24
+ await runSequentially(testFiles);
25
+
26
+ async function runSequentially(files) {
27
+ for (const filePath of files) {
28
+ const estimatedCalls = estimateCalls(filePath);
29
+ await throttleIfNeeded(estimatedCalls);
30
+ const relativePath = path.relative(projectRoot, filePath);
31
+ console.log(`ā–¶ļø Running ${relativePath} (estimated ${estimatedCalls} API calls)`);
32
+ await runVitestFile(relativePath);
33
+ requestHistory.push({ timestamp: Date.now(), calls: estimatedCalls });
34
+ }
35
+ }
36
+
37
+ function collectIntegrationTests(dir) {
38
+ const entries = readdirSync(dir, { withFileTypes: true });
39
+ const files = [];
40
+ for (const entry of entries) {
41
+ const fullPath = path.join(dir, entry.name);
42
+ if (entry.isDirectory()) {
43
+ files.push(...collectIntegrationTests(fullPath));
44
+ } else if (entry.isFile() && entry.name.endsWith('.integration.test.ts')) {
45
+ files.push(fullPath);
46
+ }
47
+ }
48
+ return files.sort((a, b) => a.localeCompare(b));
49
+ }
50
+
51
+ async function throttleIfNeeded(nextCalls) {
52
+ pruneHistory();
53
+ while (getRecentCalls() + nextCalls > RATE_LIMIT - RATE_LIMIT_BUFFER) {
54
+ const nextWindowTime = requestHistory[0]?.timestamp ?? Date.now();
55
+ const waitUntil = nextWindowTime + RATE_LIMIT_WINDOW_MS;
56
+ const waitMs = Math.min(Math.max(waitUntil - Date.now(), 1000), MAX_WAIT_MS);
57
+ const minutes = Math.max(1, Math.round(waitMs / 60000));
58
+ console.warn(
59
+ `ā³ Approaching rate limit (${getRecentCalls()}/${RATE_LIMIT}). Waiting ${minutes} minute${
60
+ minutes === 1 ? '' : 's'
61
+ }...`,
62
+ );
63
+ await sleep(waitMs);
64
+ pruneHistory();
65
+ }
66
+ }
67
+
68
+ function pruneHistory() {
69
+ const cutoff = Date.now() - RATE_LIMIT_WINDOW_MS;
70
+ while (requestHistory.length && requestHistory[0].timestamp < cutoff) {
71
+ requestHistory.shift();
72
+ }
73
+ }
74
+
75
+ function getRecentCalls() {
76
+ return requestHistory.reduce((sum, entry) => sum + entry.calls, 0);
77
+ }
78
+
79
+ function estimateCalls(filePath) {
80
+ const name = filePath.toLowerCase();
81
+ if (name.includes('delta')) return 15;
82
+ if (name.includes('reconciliation')) return 25;
83
+ if (name.includes('transaction')) return 12;
84
+ if (name.includes('budget')) return 8;
85
+ if (name.includes('account')) return 8;
86
+ if (name.includes('payee')) return 10;
87
+ if (name.includes('category')) return 10;
88
+ if (name.includes('month')) return 10;
89
+ return 10;
90
+ }
91
+
92
+ async function runVitestFile(testFile) {
93
+ const normalized = toPosixPath(testFile);
94
+ const vitestArgs = ['vitest', 'run', '--project', 'integration:full', normalized];
95
+ const runner = process.platform === 'win32' ? 'npx.cmd' : 'npx';
96
+ const child = spawn(runner, vitestArgs, {
97
+ stdio: 'inherit',
98
+ env: {
99
+ ...process.env,
100
+ INTEGRATION_TEST_TIER: 'full',
101
+ INTEGRATION_TEST_DOMAINS: '',
102
+ },
103
+ });
104
+
105
+ await new Promise((resolve, reject) => {
106
+ child.on('close', (code) => {
107
+ if (code === 0) resolve();
108
+ else reject(new Error(`Vitest exited with code ${code}`));
109
+ });
110
+ child.on('error', reject);
111
+ });
112
+ }
113
+
114
+ function sleep(ms) {
115
+ return new Promise((resolve) => setTimeout(resolve, ms));
116
+ }
@@ -0,0 +1,140 @@
1
+ import * as ynab from 'ynab';
2
+
3
+ const ACCESS_TOKEN = process.env.YNAB_ACCESS_TOKEN;
4
+
5
+ if (!ACCESS_TOKEN) {
6
+ console.error('Missing YNAB_ACCESS_TOKEN environment variable.');
7
+ process.exit(1);
8
+ }
9
+
10
+ const ynabAPI = new ynab.API(ACCESS_TOKEN);
11
+
12
+ const results = [];
13
+
14
+ function recordResult(name, signature, supported, notes, error) {
15
+ results.push({ name, signature, supported, notes, error: error?.message ?? null });
16
+ const status = supported ? 'āœ“' : 'āœ—';
17
+ const suffix = notes ? ` - ${notes}` : '';
18
+ console.log(`${status} ${name} (${signature})${suffix}`);
19
+ if (error) {
20
+ console.log(` Error: ${error.message}`);
21
+ }
22
+ }
23
+
24
+ async function verifySimpleEndpoint({ name, signature, fetchFull, fetchDelta }) {
25
+ try {
26
+ const full = await fetchFull();
27
+ const knowledge = full?.data?.server_knowledge;
28
+ if (typeof knowledge !== 'number') {
29
+ throw new Error('Response missing server_knowledge');
30
+ }
31
+
32
+ await fetchDelta(knowledge);
33
+ recordResult(name, signature, true, `server_knowledge=${knowledge}`);
34
+ } catch (error) {
35
+ recordResult(name, signature, false, '', error);
36
+ }
37
+ }
38
+
39
+ async function main() {
40
+ console.log('Verifying YNAB SDK delta request signatures...\n');
41
+ const budgetsResponse = await ynabAPI.budgets.getBudgets();
42
+ const budget = budgetsResponse?.data?.budgets?.[0];
43
+ if (!budget) {
44
+ throw new Error('No budget available to test.');
45
+ }
46
+ const budgetId = budget.id;
47
+ console.log(`Using budget: ${budget.name} (${budgetId})\n`);
48
+
49
+ // Budgets API
50
+ await verifySimpleEndpoint({
51
+ name: 'budgets.getBudgetById',
52
+ signature: 'getBudgetById(budgetId, lastKnowledge?)',
53
+ fetchFull: () => ynabAPI.budgets.getBudgetById(budgetId),
54
+ fetchDelta: (knowledge) => ynabAPI.budgets.getBudgetById(budgetId, knowledge),
55
+ });
56
+
57
+ // Accounts API
58
+ await verifySimpleEndpoint({
59
+ name: 'accounts.getAccounts',
60
+ signature: 'getAccounts(budgetId, lastKnowledge?)',
61
+ fetchFull: () => ynabAPI.accounts.getAccounts(budgetId),
62
+ fetchDelta: (knowledge) => ynabAPI.accounts.getAccounts(budgetId, knowledge),
63
+ });
64
+
65
+ // Categories API
66
+ await verifySimpleEndpoint({
67
+ name: 'categories.getCategories',
68
+ signature: 'getCategories(budgetId, lastKnowledge?)',
69
+ fetchFull: () => ynabAPI.categories.getCategories(budgetId),
70
+ fetchDelta: (knowledge) => ynabAPI.categories.getCategories(budgetId, knowledge),
71
+ });
72
+
73
+ // Payees API
74
+ await verifySimpleEndpoint({
75
+ name: 'payees.getPayees',
76
+ signature: 'getPayees(budgetId, lastKnowledge?)',
77
+ fetchFull: () => ynabAPI.payees.getPayees(budgetId),
78
+ fetchDelta: (knowledge) => ynabAPI.payees.getPayees(budgetId, knowledge),
79
+ });
80
+
81
+ // Months API
82
+ await verifySimpleEndpoint({
83
+ name: 'months.getBudgetMonths',
84
+ signature: 'getBudgetMonths(budgetId, lastKnowledge?)',
85
+ fetchFull: () => ynabAPI.months.getBudgetMonths(budgetId),
86
+ fetchDelta: (knowledge) => ynabAPI.months.getBudgetMonths(budgetId, knowledge),
87
+ });
88
+
89
+ // Scheduled Transactions API
90
+ await verifySimpleEndpoint({
91
+ name: 'scheduledTransactions.getScheduledTransactions',
92
+ signature: 'getScheduledTransactions(budgetId, lastKnowledge?)',
93
+ fetchFull: () => ynabAPI.scheduledTransactions.getScheduledTransactions(budgetId),
94
+ fetchDelta: (knowledge) =>
95
+ ynabAPI.scheduledTransactions.getScheduledTransactions(budgetId, knowledge),
96
+ });
97
+
98
+ // Transactions API
99
+ try {
100
+ const full = await ynabAPI.transactions.getTransactions(budgetId);
101
+ const knowledge = full?.data?.server_knowledge;
102
+ if (typeof knowledge !== 'number') {
103
+ throw new Error('Response missing server_knowledge');
104
+ }
105
+
106
+ let supported = false;
107
+ let notes = '';
108
+
109
+ try {
110
+ await ynabAPI.transactions.getTransactions(budgetId, undefined, undefined, knowledge);
111
+ supported = true;
112
+ notes = 'Signature: (budgetId, sinceDate?, type?, lastKnowledge?)';
113
+ } catch (error) {
114
+ notes = 'Failed with lastKnowledge as 4th parameter';
115
+ throw error;
116
+ }
117
+
118
+ recordResult('transactions.getTransactions', notes, supported, `server_knowledge=${knowledge}`);
119
+ } catch (error) {
120
+ recordResult(
121
+ 'transactions.getTransactions',
122
+ 'getTransactions(budgetId, since?, type?, lastKnowledge?)',
123
+ false,
124
+ '',
125
+ error,
126
+ );
127
+ }
128
+
129
+ console.log('\nSummary:\n');
130
+ for (const row of results) {
131
+ console.log(
132
+ `${row.supported ? 'āœ“' : 'āœ—'} ${row.name} -> ${row.supported ? 'supports delta' : 'no delta'} (${row.signature})`,
133
+ );
134
+ }
135
+ }
136
+
137
+ main().catch((error) => {
138
+ console.error('Verification failed:', error);
139
+ process.exit(1);
140
+ });
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Manual test script for recommendation engine
3
+ * Tests the EvoCarShare scenario from user feedback
4
+ */
5
+
6
+ import { analyzeReconciliation } from '../src/tools/reconciliation/analyzer.js';
7
+ import { DEFAULT_MATCHING_CONFIG } from '../src/tools/reconciliation/types.js';
8
+
9
+ // Test data from user's scenario
10
+ const csvContent = `Date,Description,Amount
11
+ 2024-10-30,EvoCarShare,22.22`;
12
+
13
+ const ynabTransactions = []; // No YNAB transactions
14
+
15
+ const analysis = analyzeReconciliation(
16
+ csvContent,
17
+ undefined,
18
+ ynabTransactions,
19
+ 122.22, // Statement balance
20
+ DEFAULT_MATCHING_CONFIG,
21
+ 'USD',
22
+ 'test-account',
23
+ 'test-budget',
24
+ );
25
+
26
+ console.log('=== RECONCILIATION ANALYSIS ===');
27
+ console.log(`On Track: ${analysis.balance_info.on_track}`);
28
+ console.log(`Discrepancy: ${analysis.balance_info.discrepancy.value_display}`);
29
+ console.log(`\n=== RECOMMENDATIONS (${analysis.recommendations?.length || 0}) ===`);
30
+
31
+ if (analysis.recommendations && analysis.recommendations.length > 0) {
32
+ for (const rec of analysis.recommendations) {
33
+ console.log(`\n[${rec.priority.toUpperCase()}] ${rec.message}`);
34
+ console.log(` Type: ${rec.action_type}`);
35
+ console.log(` Confidence: ${(rec.confidence * 100).toFixed(0)}%`);
36
+ console.log(` Reason: ${rec.reason}`);
37
+ console.log(` Impact: ${rec.estimated_impact.value_display}`);
38
+
39
+ if (rec.action_type === 'create_transaction') {
40
+ console.log(` Parameters:`);
41
+ console.log(` - Date: ${rec.parameters.date}`);
42
+ console.log(` - Amount: $${(rec.parameters.amount / 1000).toFixed(2)}`);
43
+ console.log(` - Payee: ${rec.parameters.payee_name}`);
44
+ console.log(` - Cleared: ${rec.parameters.cleared}`);
45
+ }
46
+ }
47
+
48
+ console.log('\nāœ… All checks passed!');
49
+ console.log('Recommendation engine is working correctly.');
50
+ } else {
51
+ console.log('āŒ No recommendations generated!');
52
+ process.exit(1);
53
+ }
@@ -0,0 +1,48 @@
1
+ import { handleCreateTransaction } from '../src/tools/transactionTools.js';
2
+ import { responseFormatter } from '../src/server/responseFormatter.js';
3
+
4
+ const mockAPI: any = {
5
+ transactions: {
6
+ createTransaction: async (_budgetId: string, _payload: any) => ({
7
+ data: {
8
+ transaction: {
9
+ id: 'transaction-3',
10
+ date: '2024-01-17',
11
+ amount: -2500,
12
+ memo: 'Test transaction',
13
+ cleared: 'uncleared',
14
+ approved: true,
15
+ flag_color: null,
16
+ account_id: 'test-account',
17
+ payee_id: null,
18
+ category_id: 'category-1',
19
+ transfer_account_id: null,
20
+ },
21
+ },
22
+ }),
23
+ },
24
+ accounts: {
25
+ getAccountById: async (_budgetId: string, _accountId: string) => ({
26
+ data: {
27
+ account: {
28
+ id: 'test-account',
29
+ balance: 1000,
30
+ cleared_balance: 1000,
31
+ uncleared_balance: 0,
32
+ },
33
+ },
34
+ }),
35
+ },
36
+ };
37
+
38
+ (async () => {
39
+ const result = await handleCreateTransaction(mockAPI, {
40
+ budget_id: 'test-budget',
41
+ account_id: 'test-account',
42
+ amount: -2500,
43
+ date: '2024-01-17',
44
+ memo: 'Test transaction',
45
+ cleared: 'uncleared',
46
+ });
47
+ console.log('result', result);
48
+ })();
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Environment Variable Validation Script
5
+ * Validates required environment variables for YNAB MCP Server
6
+ */
7
+
8
+ import { config } from 'dotenv';
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname } from 'path';
11
+
12
+ // Load environment variables from .env file
13
+ config();
14
+
15
+ // Allow CI builds to skip strict validation when packaging artifacts
16
+ if (process.env['SKIP_ENV_VALIDATION'] === 'true') {
17
+ console.log('Skipping environment validation (SKIP_ENV_VALIDATION=true)');
18
+ process.exit(0);
19
+ }
20
+
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+
24
+ const requiredEnvVars = [
25
+ {
26
+ name: 'YNAB_ACCESS_TOKEN',
27
+ description: 'YNAB Personal Access Token',
28
+ validation: (value) => {
29
+ if (!value) return 'YNAB_ACCESS_TOKEN is required';
30
+ if (typeof value !== 'string') return 'YNAB_ACCESS_TOKEN must be a string';
31
+ if (value.length < 10) return 'YNAB_ACCESS_TOKEN appears to be too short';
32
+ return null;
33
+ },
34
+ },
35
+ ];
36
+
37
+ const optionalEnvVars = [
38
+ {
39
+ name: 'NODE_ENV',
40
+ description: 'Node.js environment (development, production, test)',
41
+ default: 'development',
42
+ validation: (value) => {
43
+ const validEnvs = ['development', 'production', 'test'];
44
+ if (value && !validEnvs.includes(value)) {
45
+ return `NODE_ENV must be one of: ${validEnvs.join(', ')}`;
46
+ }
47
+ return null;
48
+ },
49
+ },
50
+ {
51
+ name: 'LOG_LEVEL',
52
+ description: 'Logging level (error, warn, info, debug)',
53
+ default: 'info',
54
+ validation: (value) => {
55
+ const validLevels = ['error', 'warn', 'info', 'debug'];
56
+ if (value && !validLevels.includes(value)) {
57
+ return `LOG_LEVEL must be one of: ${validLevels.join(', ')}`;
58
+ }
59
+ return null;
60
+ },
61
+ },
62
+ ];
63
+
64
+ function validateEnvironment() {
65
+ console.log('šŸ” Validating environment variables...\n');
66
+
67
+ let hasErrors = false;
68
+ const warnings = [];
69
+
70
+ // Validate required environment variables
71
+ for (const envVar of requiredEnvVars) {
72
+ const value = process.env[envVar.name];
73
+ const error = envVar.validation(value);
74
+
75
+ if (error) {
76
+ console.error(`āŒ ${envVar.name}: ${error}`);
77
+ console.error(` Description: ${envVar.description}\n`);
78
+ hasErrors = true;
79
+ } else {
80
+ console.log(`āœ… ${envVar.name}: Valid`);
81
+ }
82
+ }
83
+
84
+ // Validate optional environment variables
85
+ for (const envVar of optionalEnvVars) {
86
+ const value = process.env[envVar.name];
87
+
88
+ if (!value) {
89
+ warnings.push(`āš ļø ${envVar.name}: Not set (using default: ${envVar.default})`);
90
+ warnings.push(` Description: ${envVar.description}`);
91
+ } else {
92
+ const error = envVar.validation(value);
93
+ if (error) {
94
+ console.error(`āŒ ${envVar.name}: ${error}`);
95
+ console.error(` Description: ${envVar.description}\n`);
96
+ hasErrors = true;
97
+ } else {
98
+ console.log(`āœ… ${envVar.name}: ${value}`);
99
+ }
100
+ }
101
+ }
102
+
103
+ // Display warnings
104
+ if (warnings.length > 0) {
105
+ console.log('\nWarnings:');
106
+ warnings.forEach((warning) => console.log(warning));
107
+ }
108
+
109
+ if (hasErrors) {
110
+ console.error('\nāŒ Environment validation failed. Please fix the errors above.');
111
+ process.exit(1);
112
+ } else {
113
+ console.log('\nāœ… Environment validation passed!');
114
+ }
115
+ }
116
+
117
+ // Run validation if this script is executed directly
118
+ if (process.argv[1] === __filename) {
119
+ validateEnvironment();
120
+ }
121
+
122
+ export { validateEnvironment };
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Build Verification Script
5
+ * Verifies that the build output is correct and complete
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { dirname } from 'path';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ const DIST_DIR = path.join(__dirname, '..', 'dist');
17
+ const REQUIRED_FILES = [
18
+ 'index.js',
19
+ 'index.d.ts',
20
+ 'server/YNABMCPServer.js',
21
+ 'server/YNABMCPServer.d.ts',
22
+ 'tools/budgetTools.js',
23
+ 'tools/budgetTools.d.ts',
24
+ 'tools/accountTools.js',
25
+ 'tools/accountTools.d.ts',
26
+ 'tools/transactionTools.js',
27
+ 'tools/transactionTools.d.ts',
28
+ 'tools/categoryTools.js',
29
+ 'tools/categoryTools.d.ts',
30
+ 'tools/payeeTools.js',
31
+ 'tools/payeeTools.d.ts',
32
+ 'tools/monthTools.js',
33
+ 'tools/monthTools.d.ts',
34
+ 'tools/utilityTools.js',
35
+ 'tools/utilityTools.d.ts',
36
+ 'types/index.js',
37
+ 'types/index.d.ts',
38
+ ];
39
+
40
+ function verifyBuild() {
41
+ console.log('šŸ” Verifying build output...\n');
42
+
43
+ // Check if dist directory exists
44
+ if (!fs.existsSync(DIST_DIR)) {
45
+ console.error('āŒ Build directory does not exist:', DIST_DIR);
46
+ process.exit(1);
47
+ }
48
+
49
+ let missingFiles = [];
50
+ let foundFiles = [];
51
+
52
+ // Check for required files
53
+ for (const file of REQUIRED_FILES) {
54
+ const filePath = path.join(DIST_DIR, file);
55
+ if (fs.existsSync(filePath)) {
56
+ foundFiles.push(file);
57
+ console.log(`āœ… ${file}`);
58
+ } else {
59
+ missingFiles.push(file);
60
+ console.error(`āŒ Missing: ${file}`);
61
+ }
62
+ }
63
+
64
+ // Check main entry point
65
+ const mainEntry = path.join(DIST_DIR, 'index.js');
66
+ if (fs.existsSync(mainEntry)) {
67
+ const content = fs.readFileSync(mainEntry, 'utf8');
68
+ if (content.includes('YNABMCPServer')) {
69
+ console.log('āœ… Main entry point contains expected exports');
70
+ } else {
71
+ console.error('āŒ Main entry point missing expected exports');
72
+ missingFiles.push('index.js (invalid content)');
73
+ }
74
+ }
75
+
76
+ // Check TypeScript declarations
77
+ const hasDeclarations = foundFiles.some((file) => file.endsWith('.d.ts'));
78
+ if (hasDeclarations) {
79
+ console.log('āœ… TypeScript declarations generated');
80
+ } else {
81
+ console.error('āŒ No TypeScript declarations found');
82
+ }
83
+
84
+ // Summary
85
+ console.log(`\nšŸ“Š Build Verification Summary:`);
86
+ console.log(` Found files: ${foundFiles.length}`);
87
+ console.log(` Missing files: ${missingFiles.length}`);
88
+
89
+ if (missingFiles.length > 0) {
90
+ console.error('\nāŒ Build verification failed!');
91
+ console.error('Missing files:');
92
+ missingFiles.forEach((file) => console.error(` - ${file}`));
93
+ process.exit(1);
94
+ } else {
95
+ console.log('\nāœ… Build verification passed!');
96
+ console.log('All required files are present and valid.');
97
+ }
98
+ }
99
+
100
+ // Run verification if this script is executed directly
101
+ if (process.argv[1] === __filename) {
102
+ verifyBuild();
103
+ }
104
+
105
+ export { verifyBuild };
@@ -0,0 +1,50 @@
1
+ # PowerShell script to watch for file changes and restart MCP
2
+ param(
3
+ [string]$Path = ".\src",
4
+ [string]$Filter = "*.ts",
5
+ [int]$RestartDelay = 3
6
+ )
7
+
8
+ Write-Host "šŸ” Watching for changes in: $Path"
9
+ Write-Host "šŸ“ Filter: $Filter"
10
+
11
+ $watcher = New-Object System.IO.FileSystemWatcher
12
+ $watcher.Path = Resolve-Path $Path
13
+ $watcher.Filter = $Filter
14
+ $watcher.EnableRaisingEvents = $true
15
+ $watcher.IncludeSubdirectories = $true
16
+
17
+ $action = {
18
+ $path = $Event.SourceEventArgs.FullPath
19
+ $changeType = $Event.SourceEventArgs.ChangeType
20
+ Write-Host "šŸ”„ File $changeType`: $path"
21
+
22
+ # Build the project
23
+ Write-Host "šŸ—ļø Building project..."
24
+ npm run build
25
+
26
+ if ($LASTEXITCODE -eq 0) {
27
+ Write-Host "āœ… Build successful"
28
+ Start-Sleep -Seconds $RestartDelay
29
+
30
+ Write-Host "šŸ”„ Reconnecting to YNAB MCP server..."
31
+ /mcp reconnect ynab-mcp-server
32
+ Start-Sleep -Seconds 1
33
+ /mcp reconnect ynab-mcp-server
34
+ Write-Host "āœ… MCP server reconnected"
35
+ } else {
36
+ Write-Host "āŒ Build failed, skipping MCP restart"
37
+ }
38
+ }
39
+
40
+ Register-ObjectEvent -InputObject $watcher -EventName "Changed" -Action $action
41
+ Register-ObjectEvent -InputObject $watcher -EventName "Created" -Action $action
42
+
43
+ try {
44
+ Write-Host "āœ… File watcher started. Press Ctrl+C to stop."
45
+ while ($true) { Start-Sleep 1 }
46
+ }
47
+ finally {
48
+ $watcher.Dispose()
49
+ Write-Host "šŸ‘‹ File watcher stopped"
50
+ }