@dizzlkheinz/ynab-mcpb 0.18.4 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +87 -8
- package/bin/ynab-mcp-server.cjs +2 -2
- package/bin/ynab-mcp-server.js +3 -3
- package/biome.json +39 -0
- package/dist/bundle/index.cjs +67 -67
- package/dist/index.d.ts +1 -1
- package/dist/index.js +27 -27
- package/dist/server/YNABMCPServer.d.ts +3 -4
- package/dist/server/YNABMCPServer.js +111 -116
- package/dist/server/budgetResolver.d.ts +6 -5
- package/dist/server/budgetResolver.js +46 -36
- package/dist/server/cacheKeys.js +6 -6
- package/dist/server/cacheManager.js +14 -11
- package/dist/server/completions.d.ts +2 -2
- package/dist/server/completions.js +20 -15
- package/dist/server/config.d.ts +10 -5
- package/dist/server/config.js +24 -7
- package/dist/server/deltaCache.d.ts +2 -2
- package/dist/server/deltaCache.js +22 -16
- package/dist/server/deltaCache.merge.d.ts +2 -2
- package/dist/server/diagnostics.d.ts +4 -4
- package/dist/server/diagnostics.js +38 -32
- package/dist/server/errorHandler.d.ts +5 -12
- package/dist/server/errorHandler.js +219 -217
- package/dist/server/prompts.d.ts +2 -2
- package/dist/server/prompts.js +45 -45
- package/dist/server/rateLimiter.js +4 -4
- package/dist/server/requestLogger.d.ts +1 -1
- package/dist/server/requestLogger.js +40 -35
- package/dist/server/resources.d.ts +3 -3
- package/dist/server/resources.js +55 -52
- package/dist/server/responseFormatter.js +6 -6
- package/dist/server/securityMiddleware.d.ts +2 -2
- package/dist/server/securityMiddleware.js +22 -20
- package/dist/server/serverKnowledgeStore.js +1 -1
- package/dist/server/toolRegistry.d.ts +3 -3
- package/dist/server/toolRegistry.js +47 -40
- package/dist/tools/__tests__/deltaTestUtils.d.ts +3 -3
- package/dist/tools/__tests__/deltaTestUtils.js +2 -2
- package/dist/tools/accountTools.d.ts +9 -8
- package/dist/tools/accountTools.js +47 -47
- package/dist/tools/adapters.d.ts +13 -8
- package/dist/tools/adapters.js +21 -11
- package/dist/tools/budgetTools.d.ts +8 -7
- package/dist/tools/budgetTools.js +22 -22
- package/dist/tools/categoryTools.d.ts +9 -8
- package/dist/tools/categoryTools.js +68 -59
- package/dist/tools/compareTransactions/formatter.d.ts +3 -3
- package/dist/tools/compareTransactions/formatter.js +9 -9
- package/dist/tools/compareTransactions/index.d.ts +6 -6
- package/dist/tools/compareTransactions/index.js +58 -43
- package/dist/tools/compareTransactions/matcher.d.ts +1 -1
- package/dist/tools/compareTransactions/matcher.js +28 -15
- package/dist/tools/compareTransactions/parser.d.ts +2 -2
- package/dist/tools/compareTransactions/parser.js +144 -138
- package/dist/tools/compareTransactions/types.d.ts +4 -4
- package/dist/tools/compareTransactions.d.ts +1 -1
- package/dist/tools/compareTransactions.js +1 -1
- package/dist/tools/deltaFetcher.d.ts +2 -2
- package/dist/tools/deltaFetcher.js +16 -15
- package/dist/tools/deltaSupport.d.ts +4 -4
- package/dist/tools/deltaSupport.js +35 -41
- package/dist/tools/exportTransactions.d.ts +5 -4
- package/dist/tools/exportTransactions.js +61 -59
- package/dist/tools/monthTools.d.ts +7 -6
- package/dist/tools/monthTools.js +31 -29
- package/dist/tools/payeeTools.d.ts +7 -6
- package/dist/tools/payeeTools.js +28 -28
- package/dist/tools/reconcileAdapter.d.ts +2 -2
- package/dist/tools/reconcileAdapter.js +19 -12
- package/dist/tools/reconciliation/analyzer.d.ts +4 -4
- package/dist/tools/reconciliation/analyzer.js +73 -59
- package/dist/tools/reconciliation/csvParser.d.ts +3 -3
- package/dist/tools/reconciliation/csvParser.js +128 -104
- package/dist/tools/reconciliation/executor.d.ts +4 -4
- package/dist/tools/reconciliation/executor.js +148 -109
- package/dist/tools/reconciliation/index.d.ts +10 -10
- package/dist/tools/reconciliation/index.js +96 -83
- package/dist/tools/reconciliation/matcher.d.ts +3 -3
- package/dist/tools/reconciliation/matcher.js +17 -16
- package/dist/tools/reconciliation/payeeNormalizer.js +19 -8
- package/dist/tools/reconciliation/recommendationEngine.d.ts +1 -1
- package/dist/tools/reconciliation/recommendationEngine.js +40 -40
- package/dist/tools/reconciliation/reportFormatter.d.ts +2 -2
- package/dist/tools/reconciliation/reportFormatter.js +59 -58
- package/dist/tools/reconciliation/signDetector.d.ts +1 -1
- package/dist/tools/reconciliation/types.d.ts +16 -16
- package/dist/tools/reconciliation/ynabAdapter.d.ts +2 -2
- package/dist/tools/schemas/common.d.ts +1 -1
- package/dist/tools/schemas/common.js +1 -1
- package/dist/tools/schemas/outputs/accountOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/accountOutputs.js +24 -18
- package/dist/tools/schemas/outputs/budgetOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/budgetOutputs.js +14 -11
- package/dist/tools/schemas/outputs/categoryOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/categoryOutputs.js +49 -29
- package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/comparisonOutputs.js +12 -12
- package/dist/tools/schemas/outputs/index.d.ts +14 -14
- package/dist/tools/schemas/outputs/index.js +14 -14
- package/dist/tools/schemas/outputs/monthOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/monthOutputs.js +56 -41
- package/dist/tools/schemas/outputs/payeeOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/payeeOutputs.js +10 -10
- package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +2 -2
- package/dist/tools/schemas/outputs/reconciliationOutputs.js +45 -45
- package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/transactionMutationOutputs.js +28 -22
- package/dist/tools/schemas/outputs/transactionOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/transactionOutputs.js +43 -35
- package/dist/tools/schemas/outputs/utilityOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/utilityOutputs.js +5 -3
- package/dist/tools/schemas/shared/commonOutputs.d.ts +1 -1
- package/dist/tools/schemas/shared/commonOutputs.js +15 -9
- package/dist/tools/transactionReadTools.d.ts +11 -0
- package/dist/tools/transactionReadTools.js +202 -0
- package/dist/tools/transactionSchemas.d.ts +7 -7
- package/dist/tools/transactionSchemas.js +77 -57
- package/dist/tools/transactionTools.d.ts +6 -24
- package/dist/tools/transactionTools.js +7 -1499
- package/dist/tools/transactionUtils.d.ts +6 -6
- package/dist/tools/transactionUtils.js +78 -63
- package/dist/tools/transactionWriteTools.d.ts +20 -0
- package/dist/tools/transactionWriteTools.js +1342 -0
- package/dist/tools/utilityTools.d.ts +5 -4
- package/dist/tools/utilityTools.js +11 -11
- package/dist/types/index.d.ts +7 -7
- package/dist/types/index.js +6 -6
- package/dist/types/reconciliation.d.ts +1 -1
- package/dist/types/toolRegistration.d.ts +14 -12
- package/dist/utils/amountUtils.js +1 -1
- package/dist/utils/dateUtils.js +4 -4
- package/dist/utils/errors.d.ts +3 -3
- package/dist/utils/errors.js +4 -4
- package/dist/utils/money.d.ts +2 -2
- package/dist/utils/money.js +8 -8
- package/dist/utils/validationError.d.ts +1 -1
- package/dist/utils/validationError.js +1 -1
- package/docs/assets/examples/reconciliation-with-recommendations.json +66 -66
- package/docs/assets/schemas/reconciliation-v2.json +360 -336
- package/esbuild.config.mjs +53 -50
- package/meta.json +12548 -12548
- package/package.json +98 -111
- package/scripts/analyze-bundle.mjs +33 -30
- package/scripts/create-pr-description.js +169 -120
- package/scripts/run-all-tests.js +178 -169
- package/scripts/run-domain-integration-tests.js +28 -18
- package/scripts/run-generate-mcpb.js +19 -17
- package/scripts/run-throttled-integration-tests.js +92 -83
- package/scripts/test-delta-params.mjs +149 -120
- package/scripts/test-recommendations.ts +36 -32
- package/scripts/tmpTransaction.ts +80 -43
- package/scripts/validate-env.js +98 -91
- package/scripts/verify-build.js +78 -76
- package/src/__tests__/comprehensive.integration.test.ts +1281 -1154
- package/src/__tests__/performance.test.ts +723 -671
- package/src/__tests__/setup.ts +442 -395
- package/src/__tests__/smoke.e2e.test.ts +41 -39
- package/src/__tests__/testRunner.ts +314 -295
- package/src/__tests__/testUtils.ts +456 -364
- package/src/__tests__/tools/reconciliation/csvParser.integration.test.ts +109 -107
- package/src/__tests__/tools/reconciliation/real-world.integration.test.ts +41 -41
- package/src/index.ts +68 -59
- package/src/server/CLAUDE.md +480 -0
- package/src/server/YNABMCPServer.ts +821 -794
- package/src/server/__tests__/YNABMCPServer.integration.test.ts +929 -893
- package/src/server/__tests__/YNABMCPServer.test.ts +903 -899
- package/src/server/__tests__/budgetResolver.test.ts +466 -423
- package/src/server/__tests__/cacheManager.test.ts +891 -874
- package/src/server/__tests__/completions.integration.test.ts +115 -106
- package/src/server/__tests__/completions.test.ts +334 -313
- package/src/server/__tests__/config.test.ts +98 -86
- package/src/server/__tests__/deltaCache.merge.test.ts +774 -703
- package/src/server/__tests__/deltaCache.swr.test.ts +198 -153
- package/src/server/__tests__/deltaCache.test.ts +946 -759
- package/src/server/__tests__/diagnostics.test.ts +825 -792
- package/src/server/__tests__/errorHandler.integration.test.ts +512 -462
- package/src/server/__tests__/errorHandler.test.ts +402 -397
- package/src/server/__tests__/prompts.test.ts +424 -347
- package/src/server/__tests__/rateLimiter.test.ts +313 -309
- package/src/server/__tests__/requestLogger.test.ts +443 -403
- package/src/server/__tests__/resources.template.test.ts +196 -185
- package/src/server/__tests__/resources.test.ts +294 -288
- package/src/server/__tests__/security.integration.test.ts +487 -421
- package/src/server/__tests__/securityMiddleware.test.ts +519 -444
- package/src/server/__tests__/server-startup.integration.test.ts +509 -490
- package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -173
- package/src/server/__tests__/toolRegistration.test.ts +239 -210
- package/src/server/__tests__/toolRegistry.test.ts +907 -845
- package/src/server/budgetResolver.ts +221 -181
- package/src/server/cacheKeys.ts +6 -6
- package/src/server/cacheManager.ts +498 -484
- package/src/server/completions.ts +267 -243
- package/src/server/config.ts +35 -14
- package/src/server/deltaCache.merge.ts +146 -128
- package/src/server/deltaCache.ts +352 -309
- package/src/server/diagnostics.ts +257 -242
- package/src/server/errorHandler.ts +747 -744
- package/src/server/prompts.ts +181 -176
- package/src/server/rateLimiter.ts +131 -129
- package/src/server/requestLogger.ts +350 -322
- package/src/server/resources.ts +442 -374
- package/src/server/responseFormatter.ts +41 -37
- package/src/server/securityMiddleware.ts +223 -205
- package/src/server/serverKnowledgeStore.ts +67 -67
- package/src/server/toolRegistry.ts +508 -474
- package/src/tools/CLAUDE.md +604 -0
- package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -111
- package/src/tools/__tests__/accountTools.integration.test.ts +129 -111
- package/src/tools/__tests__/accountTools.test.ts +685 -638
- package/src/tools/__tests__/adapters.test.ts +142 -108
- package/src/tools/__tests__/budgetTools.delta.integration.test.ts +73 -73
- package/src/tools/__tests__/budgetTools.integration.test.ts +132 -124
- package/src/tools/__tests__/budgetTools.test.ts +442 -413
- package/src/tools/__tests__/categoryTools.delta.integration.test.ts +76 -68
- package/src/tools/__tests__/categoryTools.integration.test.ts +314 -288
- package/src/tools/__tests__/categoryTools.test.ts +656 -625
- package/src/tools/__tests__/compareTransactions/formatter.test.ts +535 -462
- package/src/tools/__tests__/compareTransactions/index.test.ts +378 -358
- package/src/tools/__tests__/compareTransactions/matcher.test.ts +497 -398
- package/src/tools/__tests__/compareTransactions/parser.test.ts +765 -747
- package/src/tools/__tests__/compareTransactions.test.ts +352 -332
- package/src/tools/__tests__/compareTransactions.window.test.ts +150 -146
- package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +69 -65
- package/src/tools/__tests__/deltaFetcher.test.ts +325 -265
- package/src/tools/__tests__/deltaSupport.test.ts +211 -184
- package/src/tools/__tests__/deltaTestUtils.ts +37 -33
- package/src/tools/__tests__/exportTransactions.test.ts +205 -200
- package/src/tools/__tests__/monthTools.delta.integration.test.ts +68 -68
- package/src/tools/__tests__/monthTools.integration.test.ts +178 -166
- package/src/tools/__tests__/monthTools.test.ts +561 -512
- package/src/tools/__tests__/payeeTools.delta.integration.test.ts +68 -68
- package/src/tools/__tests__/payeeTools.integration.test.ts +158 -142
- package/src/tools/__tests__/payeeTools.test.ts +486 -434
- package/src/tools/__tests__/transactionSchemas.test.ts +1202 -1186
- package/src/tools/__tests__/transactionTools.integration.test.ts +875 -825
- package/src/tools/__tests__/transactionTools.test.ts +4923 -4366
- package/src/tools/__tests__/transactionUtils.test.ts +1004 -977
- package/src/tools/__tests__/utilityTools.integration.test.ts +32 -32
- package/src/tools/__tests__/utilityTools.test.ts +68 -58
- package/src/tools/accountTools.ts +293 -271
- package/src/tools/adapters.ts +120 -63
- package/src/tools/budgetTools.ts +121 -116
- package/src/tools/categoryTools.ts +379 -339
- package/src/tools/compareTransactions/formatter.ts +131 -119
- package/src/tools/compareTransactions/index.ts +249 -214
- package/src/tools/compareTransactions/matcher.ts +259 -209
- package/src/tools/compareTransactions/parser.ts +517 -487
- package/src/tools/compareTransactions/types.ts +38 -38
- package/src/tools/compareTransactions.ts +1 -1
- package/src/tools/deltaFetcher.ts +281 -260
- package/src/tools/deltaSupport.ts +264 -259
- package/src/tools/exportTransactions.ts +230 -218
- package/src/tools/monthTools.ts +180 -165
- package/src/tools/payeeTools.ts +152 -140
- package/src/tools/reconcileAdapter.ts +297 -252
- package/src/tools/reconciliation/CLAUDE.md +506 -0
- package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +133 -124
- package/src/tools/reconciliation/__tests__/adapter.test.ts +249 -230
- package/src/tools/reconciliation/__tests__/analyzer.test.ts +408 -400
- package/src/tools/reconciliation/__tests__/csvParser.test.ts +71 -69
- package/src/tools/reconciliation/__tests__/executor.integration.test.ts +348 -323
- package/src/tools/reconciliation/__tests__/executor.progress.test.ts +503 -457
- package/src/tools/reconciliation/__tests__/executor.test.ts +898 -831
- package/src/tools/reconciliation/__tests__/matcher.test.ts +667 -663
- package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +296 -276
- package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +692 -624
- package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1008 -989
- package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +187 -146
- package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +583 -533
- package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +75 -74
- package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +70 -62
- package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +102 -88
- package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +56 -55
- package/src/tools/reconciliation/__tests__/signDetector.test.ts +209 -206
- package/src/tools/reconciliation/__tests__/ynabAdapter.test.ts +66 -60
- package/src/tools/reconciliation/analyzer.ts +564 -504
- package/src/tools/reconciliation/csvParser.ts +656 -609
- package/src/tools/reconciliation/executor.ts +1290 -1128
- package/src/tools/reconciliation/index.ts +580 -528
- package/src/tools/reconciliation/matcher.ts +256 -240
- package/src/tools/reconciliation/payeeNormalizer.ts +92 -78
- package/src/tools/reconciliation/recommendationEngine.ts +357 -345
- package/src/tools/reconciliation/reportFormatter.ts +343 -307
- package/src/tools/reconciliation/signDetector.ts +89 -83
- package/src/tools/reconciliation/types.ts +164 -159
- package/src/tools/reconciliation/ynabAdapter.ts +17 -15
- package/src/tools/schemas/CLAUDE.md +546 -0
- package/src/tools/schemas/common.ts +1 -1
- package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +410 -409
- package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +305 -299
- package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +431 -430
- package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +510 -495
- package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +179 -153
- package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +293 -254
- package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +457 -457
- package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +362 -356
- package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +402 -399
- package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +225 -211
- package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +457 -454
- package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +316 -315
- package/src/tools/schemas/outputs/accountOutputs.ts +40 -34
- package/src/tools/schemas/outputs/budgetOutputs.ts +24 -19
- package/src/tools/schemas/outputs/categoryOutputs.ts +76 -56
- package/src/tools/schemas/outputs/comparisonOutputs.ts +192 -169
- package/src/tools/schemas/outputs/index.ts +163 -163
- package/src/tools/schemas/outputs/monthOutputs.ts +95 -80
- package/src/tools/schemas/outputs/payeeOutputs.ts +18 -18
- package/src/tools/schemas/outputs/reconciliationOutputs.ts +386 -373
- package/src/tools/schemas/outputs/transactionMutationOutputs.ts +259 -231
- package/src/tools/schemas/outputs/transactionOutputs.ts +81 -71
- package/src/tools/schemas/outputs/utilityOutputs.ts +90 -84
- package/src/tools/schemas/shared/commonOutputs.ts +27 -19
- package/src/tools/toolCategories.ts +114 -114
- package/src/tools/transactionReadTools.ts +327 -0
- package/src/tools/transactionSchemas.ts +322 -291
- package/src/tools/transactionTools.ts +84 -2246
- package/src/tools/transactionUtils.ts +507 -422
- package/src/tools/transactionWriteTools.ts +2110 -0
- package/src/tools/utilityTools.ts +46 -41
- package/src/types/CLAUDE.md +477 -0
- package/src/types/__tests__/index.test.ts +51 -51
- package/src/types/index.ts +43 -39
- package/src/types/integration-tests.d.ts +26 -26
- package/src/types/reconciliation.ts +29 -29
- package/src/types/toolAnnotations.ts +30 -30
- package/src/types/toolRegistration.ts +43 -32
- package/src/utils/CLAUDE.md +508 -0
- package/src/utils/__tests__/dateUtils.test.ts +174 -168
- package/src/utils/__tests__/money.test.ts +193 -187
- package/src/utils/amountUtils.ts +5 -5
- package/src/utils/baseError.ts +5 -5
- package/src/utils/dateUtils.ts +29 -26
- package/src/utils/errors.ts +14 -14
- package/src/utils/money.ts +66 -52
- package/src/utils/validationError.ts +1 -1
- package/tsconfig.json +29 -29
- package/tsconfig.prod.json +16 -16
- package/vitest-reporters/split-json-reporter.ts +247 -204
- package/vitest.config.ts +99 -95
- package/.prettierignore +0 -10
- package/.prettierrc.json +0 -10
- package/eslint.config.js +0 -49
package/dist/tools/adapters.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import type { CallToolResult } from
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { type ErrorHandler } from "../server/errorHandler.js";
|
|
3
|
+
import type { DefaultArgumentResolver, ProgressCallback, ToolExecutionPayload } from "../server/toolRegistry.js";
|
|
4
|
+
import type { DeltaHandler, Handler, NoInputHandler, ToolContext, WriteHandler } from "../types/toolRegistration.js";
|
|
5
|
+
import type { DeltaFetcher } from "./deltaFetcher.js";
|
|
5
6
|
export declare function createAdapters(context: ToolContext): {
|
|
6
|
-
adapt: <TInput extends Record<string, unknown>>(handler: Handler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
7
|
+
adapt: <TInput extends Record<string, unknown>>(handler: Handler<TInput>) => ({ input, }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
7
8
|
adaptNoInput: (handler: NoInputHandler) => (_payload: ToolExecutionPayload<Record<string, unknown>>) => Promise<CallToolResult>;
|
|
8
|
-
adaptWithDelta: <TInput extends Record<string, unknown>>(handler: DeltaHandler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
9
|
-
adaptWithDeltaAndProgress: <TInput extends Record<string, unknown>>(handler: (api: import("ynab").API, deltaFetcher: DeltaFetcher, params: TInput, sendProgress?: ProgressCallback) => Promise<CallToolResult>) => ({ input, context }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
10
|
-
adaptWrite: <TInput extends Record<string, unknown>>(handler: WriteHandler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
9
|
+
adaptWithDelta: <TInput extends Record<string, unknown>>(handler: DeltaHandler<TInput>) => ({ input, }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
10
|
+
adaptWithDeltaAndProgress: <TInput extends Record<string, unknown>>(handler: (api: import("ynab").API, deltaFetcher: DeltaFetcher, params: TInput, sendProgress?: ProgressCallback, errorHandler?: ErrorHandler) => Promise<CallToolResult>) => ({ input, context: execContext, }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
11
|
+
adaptWrite: <TInput extends Record<string, unknown>>(handler: WriteHandler<TInput>) => ({ input, }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
12
|
+
};
|
|
13
|
+
export declare function createErrorHelpers(context: ToolContext): {
|
|
14
|
+
withToolErrorHandling: <T>(operation: () => Promise<T>, toolName: string, operationName: string) => Promise<T | CallToolResult>;
|
|
15
|
+
handleToolError: (error: unknown, toolName: string, operation: string) => CallToolResult;
|
|
11
16
|
};
|
|
12
17
|
export declare function createBudgetResolver(context: ToolContext): <TInput extends {
|
|
13
18
|
budget_id?: string | undefined;
|
package/dist/tools/adapters.js
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import { BudgetResolver } from
|
|
2
|
-
import {
|
|
1
|
+
import { BudgetResolver } from "../server/budgetResolver.js";
|
|
2
|
+
import { handleToolError as _handleToolError, withToolErrorHandling as _withToolErrorHandling, } from "../server/errorHandler.js";
|
|
3
|
+
import { DefaultArgumentResolutionError } from "../server/toolRegistry.js";
|
|
3
4
|
export function createAdapters(context) {
|
|
4
5
|
const { ynabAPI, deltaFetcher, deltaCache, serverKnowledgeStore } = context;
|
|
6
|
+
const { errorHandler } = context;
|
|
5
7
|
return {
|
|
6
|
-
adapt: (handler) => async ({ input }) => handler(ynabAPI, input),
|
|
7
|
-
adaptNoInput: (handler) => async (_payload) => handler(ynabAPI),
|
|
8
|
-
adaptWithDelta: (handler) => async ({ input }) => handler(ynabAPI, deltaFetcher, input),
|
|
9
|
-
adaptWithDeltaAndProgress: (handler) => async ({ input, context }) => handler(ynabAPI, deltaFetcher, input,
|
|
10
|
-
adaptWrite: (handler) => async ({ input }) => handler(ynabAPI, deltaCache, serverKnowledgeStore, input),
|
|
8
|
+
adapt: (handler) => async ({ input, }) => handler(ynabAPI, input, errorHandler),
|
|
9
|
+
adaptNoInput: (handler) => async (_payload) => handler(ynabAPI, errorHandler),
|
|
10
|
+
adaptWithDelta: (handler) => async ({ input, }) => handler(ynabAPI, deltaFetcher, input, errorHandler),
|
|
11
|
+
adaptWithDeltaAndProgress: (handler) => async ({ input, context: execContext, }) => handler(ynabAPI, deltaFetcher, input, execContext.sendProgress, errorHandler),
|
|
12
|
+
adaptWrite: (handler) => async ({ input, }) => handler(ynabAPI, deltaCache, serverKnowledgeStore, input, errorHandler),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function createErrorHelpers(context) {
|
|
16
|
+
const { errorHandler } = context;
|
|
17
|
+
return {
|
|
18
|
+
withToolErrorHandling: (operation, toolName, operationName) => _withToolErrorHandling(operation, toolName, operationName, errorHandler),
|
|
19
|
+
handleToolError: (error, toolName, operation) => _handleToolError(error, toolName, operation, errorHandler),
|
|
11
20
|
};
|
|
12
21
|
}
|
|
13
22
|
export function createBudgetResolver(context) {
|
|
14
23
|
return () => {
|
|
15
24
|
return ({ rawArguments }) => {
|
|
16
|
-
const provided = typeof rawArguments[
|
|
17
|
-
|
|
25
|
+
const provided = typeof rawArguments["budget_id"] === "string" &&
|
|
26
|
+
rawArguments["budget_id"].length > 0
|
|
27
|
+
? rawArguments["budget_id"]
|
|
18
28
|
: undefined;
|
|
19
|
-
const result = BudgetResolver.resolveBudgetId(provided, context.getDefaultBudgetId());
|
|
20
|
-
if (typeof result ===
|
|
29
|
+
const result = BudgetResolver.resolveBudgetId(provided, context.getDefaultBudgetId(), context.errorHandler);
|
|
30
|
+
if (typeof result === "string") {
|
|
21
31
|
return { budget_id: result };
|
|
22
32
|
}
|
|
23
33
|
throw new DefaultArgumentResolutionError(result);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import * as ynab from
|
|
3
|
-
import { z } from
|
|
4
|
-
import type {
|
|
5
|
-
import type { ToolFactory } from
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
import type { ErrorHandler } from "../server/errorHandler.js";
|
|
5
|
+
import type { ToolFactory } from "../types/toolRegistration.js";
|
|
6
|
+
import type { DeltaFetcher } from "./deltaFetcher.js";
|
|
6
7
|
export declare const GetBudgetSchema: z.ZodObject<{
|
|
7
8
|
budget_id: z.ZodString;
|
|
8
9
|
}, z.core.$strict>;
|
|
9
10
|
export type GetBudgetParams = z.infer<typeof GetBudgetSchema>;
|
|
10
|
-
export declare function handleListBudgets(ynabAPI: ynab.API, deltaFetcherOrParams?: DeltaFetcher | Record<string, unknown>, maybeParams?: Record<string, unknown
|
|
11
|
-
export declare function handleGetBudget(ynabAPI: ynab.API, params: GetBudgetParams): Promise<CallToolResult>;
|
|
11
|
+
export declare function handleListBudgets(ynabAPI: ynab.API, deltaFetcherOrParams?: DeltaFetcher | Record<string, unknown>, maybeParams?: Record<string, unknown>, errorHandler?: ErrorHandler): Promise<CallToolResult>;
|
|
12
|
+
export declare function handleGetBudget(ynabAPI: ynab.API, params: GetBudgetParams, errorHandler?: ErrorHandler): Promise<CallToolResult>;
|
|
12
13
|
export declare const registerBudgetTools: ToolFactory;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { responseFormatter } from "../server/responseFormatter.js";
|
|
3
|
+
import { withToolErrorHandling } from "../types/index.js";
|
|
4
|
+
import { createAdapters } from "./adapters.js";
|
|
5
|
+
import { resolveDeltaFetcherArgs } from "./deltaSupport.js";
|
|
6
|
+
import { emptyObjectSchema } from "./schemas/common.js";
|
|
7
|
+
import { ToolAnnotationPresets } from "./toolCategories.js";
|
|
8
8
|
export const GetBudgetSchema = z
|
|
9
9
|
.object({
|
|
10
|
-
budget_id: z.string().min(1,
|
|
10
|
+
budget_id: z.string().min(1, "Budget ID is required"),
|
|
11
11
|
})
|
|
12
12
|
.strict();
|
|
13
|
-
export async function handleListBudgets(ynabAPI, deltaFetcherOrParams, maybeParams) {
|
|
13
|
+
export async function handleListBudgets(ynabAPI, deltaFetcherOrParams, maybeParams, errorHandler) {
|
|
14
14
|
const { deltaFetcher } = resolveDeltaFetcherArgs(ynabAPI, (deltaFetcherOrParams ?? {}), maybeParams);
|
|
15
15
|
return await withToolErrorHandling(async () => {
|
|
16
16
|
const result = await deltaFetcher.fetchBudgets();
|
|
@@ -19,7 +19,7 @@ export async function handleListBudgets(ynabAPI, deltaFetcherOrParams, maybePara
|
|
|
19
19
|
return {
|
|
20
20
|
content: [
|
|
21
21
|
{
|
|
22
|
-
type:
|
|
22
|
+
type: "text",
|
|
23
23
|
text: responseFormatter.format({
|
|
24
24
|
budgets: budgets.map((budget) => ({
|
|
25
25
|
id: budget.id,
|
|
@@ -32,22 +32,22 @@ export async function handleListBudgets(ynabAPI, deltaFetcherOrParams, maybePara
|
|
|
32
32
|
})),
|
|
33
33
|
cached: wasCached,
|
|
34
34
|
cache_info: wasCached
|
|
35
|
-
? `Data retrieved from cache for improved performance${result.usedDelta ?
|
|
36
|
-
:
|
|
35
|
+
? `Data retrieved from cache for improved performance${result.usedDelta ? " (delta merge applied)" : ""}`
|
|
36
|
+
: "Fresh data retrieved from YNAB API",
|
|
37
37
|
}),
|
|
38
38
|
},
|
|
39
39
|
],
|
|
40
40
|
};
|
|
41
|
-
},
|
|
41
|
+
}, "ynab:list_budgets", "listing budgets", errorHandler);
|
|
42
42
|
}
|
|
43
|
-
export async function handleGetBudget(ynabAPI, params) {
|
|
43
|
+
export async function handleGetBudget(ynabAPI, params, errorHandler) {
|
|
44
44
|
return await withToolErrorHandling(async () => {
|
|
45
45
|
const response = await ynabAPI.budgets.getBudgetById(params.budget_id);
|
|
46
46
|
const budget = response.data.budget;
|
|
47
47
|
return {
|
|
48
48
|
content: [
|
|
49
49
|
{
|
|
50
|
-
type:
|
|
50
|
+
type: "text",
|
|
51
51
|
text: responseFormatter.format({
|
|
52
52
|
budget: {
|
|
53
53
|
id: budget.id,
|
|
@@ -61,37 +61,37 @@ export async function handleGetBudget(ynabAPI, params) {
|
|
|
61
61
|
categories_count: budget.categories?.length ?? 0,
|
|
62
62
|
payees_count: budget.payees?.length ?? 0,
|
|
63
63
|
months_count: budget.months?.length ?? 0,
|
|
64
|
-
message:
|
|
64
|
+
message: "Use list_accounts, list_categories, list_payees, and list_months to get detailed lists",
|
|
65
65
|
},
|
|
66
66
|
}),
|
|
67
67
|
},
|
|
68
68
|
],
|
|
69
69
|
};
|
|
70
|
-
},
|
|
70
|
+
}, "ynab:get_budget", "getting budget details", errorHandler);
|
|
71
71
|
}
|
|
72
72
|
export const registerBudgetTools = (registry, context) => {
|
|
73
73
|
const { adapt, adaptWithDelta } = createAdapters(context);
|
|
74
74
|
registry.register({
|
|
75
|
-
name:
|
|
75
|
+
name: "list_budgets",
|
|
76
76
|
description: "List all budgets associated with the user's account",
|
|
77
77
|
inputSchema: emptyObjectSchema,
|
|
78
78
|
handler: adaptWithDelta(handleListBudgets),
|
|
79
79
|
metadata: {
|
|
80
80
|
annotations: {
|
|
81
81
|
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
82
|
-
title:
|
|
82
|
+
title: "YNAB: List Budgets",
|
|
83
83
|
},
|
|
84
84
|
},
|
|
85
85
|
});
|
|
86
86
|
registry.register({
|
|
87
|
-
name:
|
|
88
|
-
description:
|
|
87
|
+
name: "get_budget",
|
|
88
|
+
description: "Get detailed information for a specific budget",
|
|
89
89
|
inputSchema: GetBudgetSchema,
|
|
90
90
|
handler: adapt(handleGetBudget),
|
|
91
91
|
metadata: {
|
|
92
92
|
annotations: {
|
|
93
93
|
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
94
|
-
title:
|
|
94
|
+
title: "YNAB: Get Budget Details",
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
97
|
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import * as ynab from
|
|
3
|
-
import { z } from
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import type { ServerKnowledgeStore } from
|
|
7
|
-
import type { ToolFactory } from
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
import type { DeltaCache } from "../server/deltaCache.js";
|
|
5
|
+
import type { ErrorHandler } from "../server/errorHandler.js";
|
|
6
|
+
import type { ServerKnowledgeStore } from "../server/serverKnowledgeStore.js";
|
|
7
|
+
import type { ToolFactory } from "../types/toolRegistration.js";
|
|
8
|
+
import type { DeltaFetcher } from "./deltaFetcher.js";
|
|
8
9
|
export declare const ListCategoriesSchema: z.ZodObject<{
|
|
9
10
|
budget_id: z.ZodString;
|
|
10
11
|
}, z.core.$strict>;
|
|
@@ -23,7 +24,7 @@ export declare const UpdateCategorySchema: z.ZodObject<{
|
|
|
23
24
|
export type UpdateCategoryParams = z.infer<typeof UpdateCategorySchema>;
|
|
24
25
|
export declare function handleListCategories(ynabAPI: ynab.API, deltaFetcher: DeltaFetcher, params: ListCategoriesParams): Promise<CallToolResult>;
|
|
25
26
|
export declare function handleListCategories(ynabAPI: ynab.API, params: ListCategoriesParams): Promise<CallToolResult>;
|
|
26
|
-
export declare function handleGetCategory(ynabAPI: ynab.API, params: GetCategoryParams): Promise<CallToolResult>;
|
|
27
|
+
export declare function handleGetCategory(ynabAPI: ynab.API, params: GetCategoryParams, errorHandler?: ErrorHandler): Promise<CallToolResult>;
|
|
27
28
|
export declare function handleUpdateCategory(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: UpdateCategoryParams): Promise<CallToolResult>;
|
|
28
29
|
export declare function handleUpdateCategory(ynabAPI: ynab.API, params: UpdateCategoryParams): Promise<CallToolResult>;
|
|
29
30
|
export declare const registerCategoryTools: ToolFactory;
|
|
@@ -1,34 +1,38 @@
|
|
|
1
|
-
import { z } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ToolAnnotationPresets } from
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { CacheKeys } from "../server/cacheKeys.js";
|
|
3
|
+
import { CACHE_TTLS, CacheManager, cacheManager, } from "../server/cacheManager.js";
|
|
4
|
+
import { responseFormatter } from "../server/responseFormatter.js";
|
|
5
|
+
import { withToolErrorHandling } from "../types/index.js";
|
|
6
|
+
import { milliunitsToAmount } from "../utils/amountUtils.js";
|
|
7
|
+
import { createAdapters, createBudgetResolver } from "./adapters.js";
|
|
8
|
+
import { resolveDeltaFetcherArgs, resolveDeltaWriteArgs, } from "./deltaSupport.js";
|
|
9
|
+
import { ToolAnnotationPresets } from "./toolCategories.js";
|
|
10
10
|
export const ListCategoriesSchema = z
|
|
11
11
|
.object({
|
|
12
|
-
budget_id: z.string().min(1,
|
|
12
|
+
budget_id: z.string().min(1, "Budget ID is required"),
|
|
13
13
|
})
|
|
14
14
|
.strict();
|
|
15
15
|
export const GetCategorySchema = z
|
|
16
16
|
.object({
|
|
17
|
-
budget_id: z.string().min(1,
|
|
18
|
-
category_id: z.string().min(1,
|
|
17
|
+
budget_id: z.string().min(1, "Budget ID is required"),
|
|
18
|
+
category_id: z.string().min(1, "Category ID is required"),
|
|
19
19
|
})
|
|
20
20
|
.strict();
|
|
21
21
|
export const UpdateCategorySchema = z
|
|
22
22
|
.object({
|
|
23
|
-
budget_id: z.string().min(1,
|
|
24
|
-
category_id: z.string().min(1,
|
|
25
|
-
budgeted: z
|
|
23
|
+
budget_id: z.string().min(1, "Budget ID is required"),
|
|
24
|
+
category_id: z.string().min(1, "Category ID is required"),
|
|
25
|
+
budgeted: z
|
|
26
|
+
.number()
|
|
27
|
+
.int("Budgeted amount must be an integer in milliunits"),
|
|
26
28
|
dry_run: z.boolean().optional(),
|
|
27
29
|
})
|
|
28
30
|
.strict();
|
|
29
31
|
function convertGoalFields(category) {
|
|
30
32
|
return {
|
|
31
|
-
goal_target: category.goal_target != null
|
|
33
|
+
goal_target: category.goal_target != null
|
|
34
|
+
? milliunitsToAmount(category.goal_target)
|
|
35
|
+
: undefined,
|
|
32
36
|
goal_under_funded: category.goal_under_funded != null
|
|
33
37
|
? milliunitsToAmount(category.goal_under_funded)
|
|
34
38
|
: undefined,
|
|
@@ -40,7 +44,7 @@ function convertGoalFields(category) {
|
|
|
40
44
|
: undefined,
|
|
41
45
|
};
|
|
42
46
|
}
|
|
43
|
-
export async function handleListCategories(ynabAPI, deltaFetcherOrParams, maybeParams) {
|
|
47
|
+
export async function handleListCategories(ynabAPI, deltaFetcherOrParams, maybeParams, errorHandler) {
|
|
44
48
|
const { deltaFetcher, params } = resolveDeltaFetcherArgs(ynabAPI, deltaFetcherOrParams, maybeParams);
|
|
45
49
|
return await withToolErrorHandling(async () => {
|
|
46
50
|
const result = await deltaFetcher.fetchCategories(params.budget_id);
|
|
@@ -66,7 +70,7 @@ export async function handleListCategories(ynabAPI, deltaFetcherOrParams, maybeP
|
|
|
66
70
|
return {
|
|
67
71
|
content: [
|
|
68
72
|
{
|
|
69
|
-
type:
|
|
73
|
+
type: "text",
|
|
70
74
|
text: responseFormatter.format({
|
|
71
75
|
categories: allCategories,
|
|
72
76
|
category_groups: categoryGroups.map((group) => ({
|
|
@@ -77,17 +81,17 @@ export async function handleListCategories(ynabAPI, deltaFetcherOrParams, maybeP
|
|
|
77
81
|
})),
|
|
78
82
|
cached: wasCached,
|
|
79
83
|
cache_info: wasCached
|
|
80
|
-
? `Data retrieved from cache for improved performance${result.usedDelta ?
|
|
81
|
-
:
|
|
84
|
+
? `Data retrieved from cache for improved performance${result.usedDelta ? " (delta merge applied)" : ""}`
|
|
85
|
+
: "Fresh data retrieved from YNAB API",
|
|
82
86
|
}),
|
|
83
87
|
},
|
|
84
88
|
],
|
|
85
89
|
};
|
|
86
|
-
},
|
|
90
|
+
}, "ynab:list_categories", "listing categories", errorHandler);
|
|
87
91
|
}
|
|
88
|
-
export async function handleGetCategory(ynabAPI, params) {
|
|
92
|
+
export async function handleGetCategory(ynabAPI, params, errorHandler) {
|
|
89
93
|
return await withToolErrorHandling(async () => {
|
|
90
|
-
const cacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES,
|
|
94
|
+
const cacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES, "get", params.budget_id, params.category_id);
|
|
91
95
|
const wasCached = cacheManager.has(cacheKey);
|
|
92
96
|
const category = await cacheManager.wrap(cacheKey, {
|
|
93
97
|
ttl: CACHE_TTLS.CATEGORIES,
|
|
@@ -99,7 +103,7 @@ export async function handleGetCategory(ynabAPI, params) {
|
|
|
99
103
|
return {
|
|
100
104
|
content: [
|
|
101
105
|
{
|
|
102
|
-
type:
|
|
106
|
+
type: "text",
|
|
103
107
|
text: responseFormatter.format({
|
|
104
108
|
category: {
|
|
105
109
|
id: category.id,
|
|
@@ -119,27 +123,27 @@ export async function handleGetCategory(ynabAPI, params) {
|
|
|
119
123
|
},
|
|
120
124
|
cached: wasCached,
|
|
121
125
|
cache_info: wasCached
|
|
122
|
-
?
|
|
123
|
-
:
|
|
126
|
+
? "Data retrieved from cache for improved performance"
|
|
127
|
+
: "Fresh data retrieved from YNAB API",
|
|
124
128
|
}),
|
|
125
129
|
},
|
|
126
130
|
],
|
|
127
131
|
};
|
|
128
|
-
},
|
|
132
|
+
}, "ynab:get_category", "getting category", errorHandler);
|
|
129
133
|
}
|
|
130
|
-
export async function handleUpdateCategory(ynabAPI, deltaCacheOrParams, knowledgeStoreOrParams, maybeParams) {
|
|
134
|
+
export async function handleUpdateCategory(ynabAPI, deltaCacheOrParams, knowledgeStoreOrParams, maybeParams, _errorHandler) {
|
|
131
135
|
const { deltaCache, knowledgeStore, params } = resolveDeltaWriteArgs(deltaCacheOrParams, knowledgeStoreOrParams, maybeParams);
|
|
132
136
|
try {
|
|
133
137
|
if (params.dry_run) {
|
|
134
138
|
const currentDate = new Date();
|
|
135
|
-
const currentMonth = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2,
|
|
139
|
+
const currentMonth = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, "0")}-01`;
|
|
136
140
|
return {
|
|
137
141
|
content: [
|
|
138
142
|
{
|
|
139
|
-
type:
|
|
143
|
+
type: "text",
|
|
140
144
|
text: responseFormatter.format({
|
|
141
145
|
dry_run: true,
|
|
142
|
-
action:
|
|
146
|
+
action: "update_category",
|
|
143
147
|
request: {
|
|
144
148
|
budget_id: params.budget_id,
|
|
145
149
|
category_id: params.category_id,
|
|
@@ -152,28 +156,28 @@ export async function handleUpdateCategory(ynabAPI, deltaCacheOrParams, knowledg
|
|
|
152
156
|
};
|
|
153
157
|
}
|
|
154
158
|
const currentDate = new Date();
|
|
155
|
-
const currentMonth = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2,
|
|
159
|
+
const currentMonth = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, "0")}-01`;
|
|
156
160
|
const response = await ynabAPI.categories.updateMonthCategory(params.budget_id, currentMonth, params.category_id, { category: { budgeted: params.budgeted } });
|
|
157
161
|
const category = response.data.category;
|
|
158
|
-
const categoriesListCacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES,
|
|
159
|
-
const specificCategoryCacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES,
|
|
162
|
+
const categoriesListCacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES, "list", params.budget_id);
|
|
163
|
+
const specificCategoryCacheKey = CacheManager.generateKey(CacheKeys.CATEGORIES, "get", params.budget_id, params.category_id);
|
|
160
164
|
cacheManager.delete(categoriesListCacheKey);
|
|
161
165
|
cacheManager.delete(specificCategoryCacheKey);
|
|
162
|
-
const monthsListCacheKey = CacheManager.generateKey(CacheKeys.MONTHS,
|
|
163
|
-
const currentMonthCacheKey = CacheManager.generateKey(CacheKeys.MONTHS,
|
|
166
|
+
const monthsListCacheKey = CacheManager.generateKey(CacheKeys.MONTHS, "list", params.budget_id);
|
|
167
|
+
const currentMonthCacheKey = CacheManager.generateKey(CacheKeys.MONTHS, "get", params.budget_id, currentMonth);
|
|
164
168
|
cacheManager.delete(monthsListCacheKey);
|
|
165
169
|
cacheManager.delete(currentMonthCacheKey);
|
|
166
170
|
deltaCache.invalidate(params.budget_id, CacheKeys.CATEGORIES);
|
|
167
171
|
deltaCache.invalidate(params.budget_id, CacheKeys.MONTHS);
|
|
168
172
|
const serverKnowledge = response.data.server_knowledge;
|
|
169
|
-
if (typeof serverKnowledge ===
|
|
173
|
+
if (typeof serverKnowledge === "number") {
|
|
170
174
|
knowledgeStore.update(categoriesListCacheKey, serverKnowledge);
|
|
171
175
|
knowledgeStore.update(monthsListCacheKey, serverKnowledge);
|
|
172
176
|
}
|
|
173
177
|
return {
|
|
174
178
|
content: [
|
|
175
179
|
{
|
|
176
|
-
type:
|
|
180
|
+
type: "text",
|
|
177
181
|
text: responseFormatter.format({
|
|
178
182
|
category: {
|
|
179
183
|
id: category.id,
|
|
@@ -198,48 +202,48 @@ export async function handleUpdateCategory(ynabAPI, deltaCacheOrParams, knowledg
|
|
|
198
202
|
};
|
|
199
203
|
}
|
|
200
204
|
catch (error) {
|
|
201
|
-
return handleCategoryError(error,
|
|
205
|
+
return handleCategoryError(error, "Failed to update category");
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
export const registerCategoryTools = (registry, context) => {
|
|
205
209
|
const { adapt, adaptWithDelta, adaptWrite } = createAdapters(context);
|
|
206
210
|
const budgetResolver = createBudgetResolver(context);
|
|
207
211
|
registry.register({
|
|
208
|
-
name:
|
|
209
|
-
description:
|
|
212
|
+
name: "list_categories",
|
|
213
|
+
description: "List all categories for a specific budget",
|
|
210
214
|
inputSchema: ListCategoriesSchema,
|
|
211
215
|
handler: adaptWithDelta(handleListCategories),
|
|
212
216
|
defaultArgumentResolver: budgetResolver(),
|
|
213
217
|
metadata: {
|
|
214
218
|
annotations: {
|
|
215
219
|
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
216
|
-
title:
|
|
220
|
+
title: "YNAB: List Categories",
|
|
217
221
|
},
|
|
218
222
|
},
|
|
219
223
|
});
|
|
220
224
|
registry.register({
|
|
221
|
-
name:
|
|
222
|
-
description:
|
|
225
|
+
name: "get_category",
|
|
226
|
+
description: "Get detailed information for a specific category",
|
|
223
227
|
inputSchema: GetCategorySchema,
|
|
224
228
|
handler: adapt(handleGetCategory),
|
|
225
229
|
defaultArgumentResolver: budgetResolver(),
|
|
226
230
|
metadata: {
|
|
227
231
|
annotations: {
|
|
228
232
|
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
229
|
-
title:
|
|
233
|
+
title: "YNAB: Get Category Details",
|
|
230
234
|
},
|
|
231
235
|
},
|
|
232
236
|
});
|
|
233
237
|
registry.register({
|
|
234
|
-
name:
|
|
235
|
-
description:
|
|
238
|
+
name: "update_category",
|
|
239
|
+
description: "Update the budgeted amount for a category in the current month",
|
|
236
240
|
inputSchema: UpdateCategorySchema,
|
|
237
241
|
handler: adaptWrite(handleUpdateCategory),
|
|
238
242
|
defaultArgumentResolver: budgetResolver(),
|
|
239
243
|
metadata: {
|
|
240
244
|
annotations: {
|
|
241
245
|
...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
|
|
242
|
-
title:
|
|
246
|
+
title: "YNAB: Update Category Budget",
|
|
243
247
|
},
|
|
244
248
|
},
|
|
245
249
|
});
|
|
@@ -247,26 +251,31 @@ export const registerCategoryTools = (registry, context) => {
|
|
|
247
251
|
function handleCategoryError(error, defaultMessage) {
|
|
248
252
|
let errorMessage = defaultMessage;
|
|
249
253
|
if (error instanceof Error) {
|
|
250
|
-
if (error.message.includes(
|
|
251
|
-
|
|
254
|
+
if (error.message.includes("401") ||
|
|
255
|
+
error.message.includes("Unauthorized")) {
|
|
256
|
+
errorMessage = "Invalid or expired YNAB access token";
|
|
252
257
|
}
|
|
253
|
-
else if (error.message.includes(
|
|
254
|
-
|
|
258
|
+
else if (error.message.includes("403") ||
|
|
259
|
+
error.message.includes("Forbidden")) {
|
|
260
|
+
errorMessage = "Insufficient permissions to access YNAB data";
|
|
255
261
|
}
|
|
256
|
-
else if (error.message.includes(
|
|
257
|
-
|
|
262
|
+
else if (error.message.includes("404") ||
|
|
263
|
+
error.message.includes("Not Found")) {
|
|
264
|
+
errorMessage = "Budget or category not found";
|
|
258
265
|
}
|
|
259
|
-
else if (error.message.includes(
|
|
260
|
-
|
|
266
|
+
else if (error.message.includes("429") ||
|
|
267
|
+
error.message.includes("Too Many Requests")) {
|
|
268
|
+
errorMessage = "Rate limit exceeded. Please try again later";
|
|
261
269
|
}
|
|
262
|
-
else if (error.message.includes(
|
|
263
|
-
|
|
270
|
+
else if (error.message.includes("500") ||
|
|
271
|
+
error.message.includes("Internal Server Error")) {
|
|
272
|
+
errorMessage = "YNAB service is currently unavailable";
|
|
264
273
|
}
|
|
265
274
|
}
|
|
266
275
|
return {
|
|
267
276
|
content: [
|
|
268
277
|
{
|
|
269
|
-
type:
|
|
278
|
+
type: "text",
|
|
270
279
|
text: responseFormatter.format({
|
|
271
280
|
error: {
|
|
272
281
|
message: errorMessage,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import * as ynab from
|
|
3
|
-
import { BankTransaction,
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import type { BankTransaction, TransactionMatch, YNABTransaction } from "./types.js";
|
|
4
4
|
export declare function findSuggestedPayee(description: string, payees: ynab.Payee[]): {
|
|
5
5
|
suggested_payee_id?: string;
|
|
6
6
|
suggested_payee_name?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { responseFormatter } from
|
|
1
|
+
import { responseFormatter } from "../../server/responseFormatter.js";
|
|
2
2
|
export function findSuggestedPayee(description, payees) {
|
|
3
3
|
if (!description) {
|
|
4
4
|
return {};
|
|
@@ -15,12 +15,12 @@ export function findSuggestedPayee(description, payees) {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
const suggested_name = description
|
|
18
|
-
.replace(/\d+/g,
|
|
19
|
-
.replace(/\s+/g,
|
|
18
|
+
.replace(/\d+/g, "")
|
|
19
|
+
.replace(/\s+/g, " ")
|
|
20
20
|
.trim();
|
|
21
21
|
return {
|
|
22
22
|
suggested_payee_name: suggested_name,
|
|
23
|
-
suggestion_reason:
|
|
23
|
+
suggestion_reason: "No matching payee found. Suggested new payee name from description.",
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
export function buildSummary(bankTransactions, ynabTransactions, matches, unmatchedBank, unmatchedYnab, parameters, dateRange) {
|
|
@@ -39,10 +39,10 @@ export function buildSummary(bankTransactions, ynabTransactions, matches, unmatc
|
|
|
39
39
|
}
|
|
40
40
|
export function formatMatches(matches) {
|
|
41
41
|
return matches.map((match) => ({
|
|
42
|
-
bank_date: match.bank_transaction.date.toISOString().split(
|
|
42
|
+
bank_date: match.bank_transaction.date.toISOString().split("T")[0],
|
|
43
43
|
bank_amount: (match.bank_transaction.amount / 1000).toFixed(2),
|
|
44
44
|
bank_description: match.bank_transaction.description,
|
|
45
|
-
ynab_date: match.ynab_transaction.date.toISOString().split(
|
|
45
|
+
ynab_date: match.ynab_transaction.date.toISOString().split("T")[0],
|
|
46
46
|
ynab_amount: (match.ynab_transaction.amount / 1000).toFixed(2),
|
|
47
47
|
ynab_payee: match.ynab_transaction.payee_name,
|
|
48
48
|
ynab_transaction: {
|
|
@@ -57,7 +57,7 @@ export function formatUnmatchedBank(unmatchedBank, payees) {
|
|
|
57
57
|
return unmatchedBank.map((txn) => {
|
|
58
58
|
const payeeSuggestion = findSuggestedPayee(txn.description, payees);
|
|
59
59
|
return {
|
|
60
|
-
date: txn.date.toISOString().split(
|
|
60
|
+
date: txn.date.toISOString().split("T")[0],
|
|
61
61
|
amount: (txn.amount / 1000).toFixed(2),
|
|
62
62
|
description: txn.description,
|
|
63
63
|
row_number: txn.row_number,
|
|
@@ -68,7 +68,7 @@ export function formatUnmatchedBank(unmatchedBank, payees) {
|
|
|
68
68
|
export function formatUnmatchedYNAB(unmatchedYnab) {
|
|
69
69
|
return unmatchedYnab.map((txn) => ({
|
|
70
70
|
id: txn.id,
|
|
71
|
-
date: txn.date.toISOString().split(
|
|
71
|
+
date: txn.date.toISOString().split("T")[0],
|
|
72
72
|
amount: (txn.amount / 1000).toFixed(2),
|
|
73
73
|
payee_name: txn.payee_name,
|
|
74
74
|
memo: txn.memo,
|
|
@@ -84,7 +84,7 @@ export function buildComparisonResult(matchResults, bankTransactions, ynabTransa
|
|
|
84
84
|
return {
|
|
85
85
|
content: [
|
|
86
86
|
{
|
|
87
|
-
type:
|
|
87
|
+
type: "text",
|
|
88
88
|
text: responseFormatter.format({
|
|
89
89
|
summary,
|
|
90
90
|
matches: formattedMatches,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import * as ynab from
|
|
3
|
-
import { z } from
|
|
4
|
-
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import { z } from "zod/v4";
|
|
4
|
+
import type { ErrorHandler } from "../../server/errorHandler.js";
|
|
5
|
+
export type { BankTransaction, YNABTransaction, TransactionMatch, } from "./types.js";
|
|
5
6
|
export declare const CompareTransactionsSchema: z.ZodObject<{
|
|
6
7
|
budget_id: z.ZodString;
|
|
7
8
|
account_id: z.ZodString;
|
|
8
9
|
csv_file_path: z.ZodOptional<z.ZodString>;
|
|
9
10
|
csv_data: z.ZodOptional<z.ZodString>;
|
|
10
|
-
date_range_days: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
11
11
|
amount_tolerance: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
12
12
|
date_tolerance_days: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
13
13
|
enable_chronology_bonus: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -27,4 +27,4 @@ export declare const CompareTransactionsSchema: z.ZodObject<{
|
|
|
27
27
|
}, z.core.$strict>>>;
|
|
28
28
|
}, z.core.$strict>;
|
|
29
29
|
export type CompareTransactionsParams = z.infer<typeof CompareTransactionsSchema>;
|
|
30
|
-
export declare function handleCompareTransactions(ynabAPI: ynab.API, params: CompareTransactionsParams): Promise<CallToolResult>;
|
|
30
|
+
export declare function handleCompareTransactions(ynabAPI: ynab.API, params: CompareTransactionsParams, errorHandler?: ErrorHandler): Promise<CallToolResult>;
|