@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
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CallToolResult } from
|
|
2
|
-
import * as ynab from
|
|
3
|
-
import type { SaveTransactionsResponseData } from
|
|
4
|
-
import type { DeltaCache } from
|
|
5
|
-
import type { ServerKnowledgeStore } from
|
|
6
|
-
import type {
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import type { SaveTransactionsResponseData } from "ynab/dist/models/SaveTransactionsResponseData.js";
|
|
4
|
+
import type { DeltaCache } from "../server/deltaCache.js";
|
|
5
|
+
import type { ServerKnowledgeStore } from "../server/serverKnowledgeStore.js";
|
|
6
|
+
import type { BulkCreateResponse, BulkTransactionInput, BulkTransactionResult, BulkUpdateResponse, CategorySource, CorrelationPayload, CorrelationPayloadInput, TransactionCacheInvalidationOptions } from "./transactionSchemas.js";
|
|
7
7
|
export declare function ensureTransaction<T>(transaction: T | undefined, errorMessage: string): T;
|
|
8
8
|
export declare function appendCategoryIds(source: CategorySource | undefined, target: Set<string>): void;
|
|
9
9
|
export declare function collectCategoryIdsFromSources(...sources: (CategorySource | undefined)[]): Set<string>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createHash } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { CacheManager, cacheManager } from "../server/cacheManager.js";
|
|
3
|
+
import { globalRequestLogger } from "../server/requestLogger.js";
|
|
4
|
+
import { responseFormatter } from "../server/responseFormatter.js";
|
|
5
|
+
import { ValidationError } from "../types/index.js";
|
|
6
6
|
const FULL_RESPONSE_THRESHOLD = 64 * 1024;
|
|
7
7
|
const SUMMARY_RESPONSE_THRESHOLD = 96 * 1024;
|
|
8
8
|
const MAX_RESPONSE_BYTES = 100 * 1024;
|
|
@@ -47,44 +47,44 @@ export function setsEqual(a, b) {
|
|
|
47
47
|
}
|
|
48
48
|
export const toMonthKey = (date) => `${date.slice(0, 7)}-01`;
|
|
49
49
|
export function invalidateTransactionCaches(deltaCache, knowledgeStore, budgetId, serverKnowledge, affectedAccountIds, affectedMonths, options = {}) {
|
|
50
|
-
deltaCache.invalidate(budgetId,
|
|
51
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
50
|
+
deltaCache.invalidate(budgetId, "transactions");
|
|
51
|
+
cacheManager.delete(CacheManager.generateKey("transactions", "list", budgetId));
|
|
52
52
|
for (const accountId of affectedAccountIds) {
|
|
53
|
-
const accountPrefix = CacheManager.generateKey(
|
|
53
|
+
const accountPrefix = CacheManager.generateKey("transactions", "account", budgetId, accountId);
|
|
54
54
|
cacheManager.deleteByPrefix(accountPrefix);
|
|
55
55
|
}
|
|
56
56
|
const invalidateAccountsList = options.accountTotalsChanged ?? true;
|
|
57
57
|
if (invalidateAccountsList) {
|
|
58
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
58
|
+
cacheManager.delete(CacheManager.generateKey("accounts", "list", budgetId));
|
|
59
59
|
}
|
|
60
60
|
for (const accountId of affectedAccountIds) {
|
|
61
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
61
|
+
cacheManager.delete(CacheManager.generateKey("account", "get", budgetId, accountId));
|
|
62
62
|
}
|
|
63
63
|
const affectedCategoryIds = options.affectedCategoryIds ?? new Set();
|
|
64
64
|
const shouldInvalidateCategories = options.invalidateAllCategories || affectedCategoryIds.size > 0;
|
|
65
65
|
if (shouldInvalidateCategories) {
|
|
66
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
66
|
+
cacheManager.delete(CacheManager.generateKey("categories", "list", budgetId));
|
|
67
67
|
for (const categoryId of affectedCategoryIds) {
|
|
68
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
68
|
+
cacheManager.delete(CacheManager.generateKey("category", "get", budgetId, categoryId));
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
const shouldInvalidateMonths = options.invalidateMonths ?? affectedMonths.size > 0;
|
|
72
72
|
if (shouldInvalidateMonths) {
|
|
73
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
74
|
-
deltaCache.invalidate(budgetId,
|
|
73
|
+
cacheManager.delete(CacheManager.generateKey("months", "list", budgetId));
|
|
74
|
+
deltaCache.invalidate(budgetId, "months");
|
|
75
75
|
for (const month of affectedMonths) {
|
|
76
|
-
cacheManager.delete(CacheManager.generateKey(
|
|
76
|
+
cacheManager.delete(CacheManager.generateKey("month", "get", budgetId, month));
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
if (serverKnowledge !== undefined) {
|
|
80
|
-
const transactionCacheKey = CacheManager.generateKey(
|
|
80
|
+
const transactionCacheKey = CacheManager.generateKey("transactions", "list", budgetId);
|
|
81
81
|
knowledgeStore.update(transactionCacheKey, serverKnowledge);
|
|
82
82
|
if (invalidateAccountsList) {
|
|
83
|
-
const accountsCacheKey = CacheManager.generateKey(
|
|
83
|
+
const accountsCacheKey = CacheManager.generateKey("accounts", "list", budgetId);
|
|
84
84
|
knowledgeStore.update(accountsCacheKey, serverKnowledge);
|
|
85
85
|
}
|
|
86
86
|
if (shouldInvalidateMonths && affectedMonths.size > 0) {
|
|
87
|
-
const monthsCacheKey = CacheManager.generateKey(
|
|
87
|
+
const monthsCacheKey = CacheManager.generateKey("months", "list", budgetId);
|
|
88
88
|
knowledgeStore.update(monthsCacheKey, serverKnowledge);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
@@ -94,18 +94,21 @@ export function generateCorrelationKey(transaction) {
|
|
|
94
94
|
return transaction.import_id;
|
|
95
95
|
}
|
|
96
96
|
const segments = [
|
|
97
|
-
`account:${transaction.account_id ??
|
|
98
|
-
`date:${transaction.date ??
|
|
97
|
+
`account:${transaction.account_id ?? ""}`,
|
|
98
|
+
`date:${transaction.date ?? ""}`,
|
|
99
99
|
`amount:${transaction.amount ?? 0}`,
|
|
100
|
-
`payee:${transaction.payee_id ?? transaction.payee_name ??
|
|
101
|
-
`category:${transaction.category_id ??
|
|
102
|
-
`memo:${transaction.memo ??
|
|
103
|
-
`cleared:${transaction.cleared ??
|
|
100
|
+
`payee:${transaction.payee_id ?? transaction.payee_name ?? ""}`,
|
|
101
|
+
`category:${transaction.category_id ?? ""}`,
|
|
102
|
+
`memo:${transaction.memo ?? ""}`,
|
|
103
|
+
`cleared:${transaction.cleared ?? ""}`,
|
|
104
104
|
`approved:${transaction.approved ?? false}`,
|
|
105
|
-
`flag:${transaction.flag_color ??
|
|
105
|
+
`flag:${transaction.flag_color ?? ""}`,
|
|
106
106
|
];
|
|
107
|
-
const normalized = segments.join(
|
|
108
|
-
const hash = createHash(
|
|
107
|
+
const normalized = segments.join("|");
|
|
108
|
+
const hash = createHash("sha256")
|
|
109
|
+
.update(normalized)
|
|
110
|
+
.digest("hex")
|
|
111
|
+
.slice(0, 16);
|
|
109
112
|
return `hash:${hash}`;
|
|
110
113
|
}
|
|
111
114
|
export function toCorrelationPayload(transaction) {
|
|
@@ -152,7 +155,7 @@ export function correlateResults(requests, responseData, duplicateImportIds) {
|
|
|
152
155
|
continue;
|
|
153
156
|
}
|
|
154
157
|
const key = generateCorrelationKey(transaction);
|
|
155
|
-
if (key.startsWith(
|
|
158
|
+
if (key.startsWith("hash:")) {
|
|
156
159
|
register(createdByHash, key, transaction.id);
|
|
157
160
|
}
|
|
158
161
|
else {
|
|
@@ -174,36 +177,37 @@ export function correlateResults(requests, responseData, duplicateImportIds) {
|
|
|
174
177
|
for (const [index, transaction] of requests.entries()) {
|
|
175
178
|
const normalizedRequest = toCorrelationPayload(transaction);
|
|
176
179
|
const correlationKey = generateCorrelationKey(normalizedRequest);
|
|
177
|
-
if (transaction.import_id &&
|
|
180
|
+
if (transaction.import_id &&
|
|
181
|
+
duplicateImportIds.has(transaction.import_id)) {
|
|
178
182
|
correlatedResults.push({
|
|
179
183
|
request_index: index,
|
|
180
|
-
status:
|
|
184
|
+
status: "duplicate",
|
|
181
185
|
correlation_key: correlationKey,
|
|
182
186
|
});
|
|
183
187
|
continue;
|
|
184
188
|
}
|
|
185
189
|
let transactionId;
|
|
186
|
-
if (correlationKey.startsWith(
|
|
190
|
+
if (correlationKey.startsWith("hash:")) {
|
|
187
191
|
transactionId = popId(createdByHash, correlationKey);
|
|
188
192
|
}
|
|
189
193
|
else {
|
|
190
194
|
transactionId = popId(createdByImportId, correlationKey);
|
|
191
195
|
}
|
|
192
|
-
if (!transactionId && !correlationKey.startsWith(
|
|
196
|
+
if (!transactionId && !correlationKey.startsWith("hash:")) {
|
|
193
197
|
const hashKey = generateCorrelationKey(toCorrelationPayload({ ...transaction, import_id: undefined }));
|
|
194
198
|
transactionId = popId(createdByHash, hashKey);
|
|
195
199
|
}
|
|
196
200
|
if (transactionId) {
|
|
197
201
|
const successResult = {
|
|
198
202
|
request_index: index,
|
|
199
|
-
status:
|
|
203
|
+
status: "created",
|
|
200
204
|
correlation_key: correlationKey,
|
|
201
205
|
};
|
|
202
206
|
successResult.transaction_id = transactionId;
|
|
203
207
|
correlatedResults.push(successResult);
|
|
204
208
|
continue;
|
|
205
209
|
}
|
|
206
|
-
globalRequestLogger.logError(
|
|
210
|
+
globalRequestLogger.logError("ynab:create_transactions", "correlate_results", {
|
|
207
211
|
request_index: index,
|
|
208
212
|
correlation_key: correlationKey,
|
|
209
213
|
request: {
|
|
@@ -212,19 +216,19 @@ export function correlateResults(requests, responseData, duplicateImportIds) {
|
|
|
212
216
|
amount: transaction.amount,
|
|
213
217
|
import_id: transaction.import_id,
|
|
214
218
|
},
|
|
215
|
-
},
|
|
219
|
+
}, "correlation_failed");
|
|
216
220
|
correlatedResults.push({
|
|
217
221
|
request_index: index,
|
|
218
|
-
status:
|
|
222
|
+
status: "failed",
|
|
219
223
|
correlation_key: correlationKey,
|
|
220
|
-
error_code:
|
|
221
|
-
error:
|
|
224
|
+
error_code: "correlation_failed",
|
|
225
|
+
error: "Unable to correlate request transaction with YNAB response",
|
|
222
226
|
});
|
|
223
227
|
}
|
|
224
228
|
return correlatedResults;
|
|
225
229
|
}
|
|
226
230
|
export function estimatePayloadSize(payload) {
|
|
227
|
-
return Buffer.byteLength(JSON.stringify(payload),
|
|
231
|
+
return Buffer.byteLength(JSON.stringify(payload), "utf8");
|
|
228
232
|
}
|
|
229
233
|
export function finalizeResponse(response) {
|
|
230
234
|
const appendMessage = (message, addition) => {
|
|
@@ -236,15 +240,15 @@ export function finalizeResponse(response) {
|
|
|
236
240
|
}
|
|
237
241
|
return `${message} ${addition}`;
|
|
238
242
|
};
|
|
239
|
-
const fullSize = estimatePayloadSize({ ...response, mode:
|
|
243
|
+
const fullSize = estimatePayloadSize({ ...response, mode: "full" });
|
|
240
244
|
if (fullSize <= FULL_RESPONSE_THRESHOLD) {
|
|
241
|
-
return { ...response, mode:
|
|
245
|
+
return { ...response, mode: "full" };
|
|
242
246
|
}
|
|
243
247
|
const { transactions, ...summaryResponse } = response;
|
|
244
248
|
const summaryPayload = {
|
|
245
249
|
...summaryResponse,
|
|
246
|
-
message: appendMessage(response.message,
|
|
247
|
-
mode:
|
|
250
|
+
message: appendMessage(response.message, "Response downgraded to summary to stay under size limits."),
|
|
251
|
+
mode: "summary",
|
|
248
252
|
};
|
|
249
253
|
if (estimatePayloadSize(summaryPayload) <= SUMMARY_RESPONSE_THRESHOLD) {
|
|
250
254
|
return summaryPayload;
|
|
@@ -258,13 +262,16 @@ export function finalizeResponse(response) {
|
|
|
258
262
|
correlation_key: result.correlation_key,
|
|
259
263
|
error: result.error,
|
|
260
264
|
})),
|
|
261
|
-
message: appendMessage(summaryResponse.message,
|
|
262
|
-
mode:
|
|
265
|
+
message: appendMessage(summaryResponse.message, "Response downgraded to ids_only to meet 100KB limit."),
|
|
266
|
+
mode: "ids_only",
|
|
263
267
|
};
|
|
264
268
|
if (estimatePayloadSize(idsOnlyPayload) <= MAX_RESPONSE_BYTES) {
|
|
265
269
|
return idsOnlyPayload;
|
|
266
270
|
}
|
|
267
|
-
throw new ValidationError(
|
|
271
|
+
throw new ValidationError("RESPONSE_TOO_LARGE: Unable to format bulk create response within 100KB limit", `Batch size: ${response.summary.total_requested} transactions`, [
|
|
272
|
+
"Reduce the batch size and retry",
|
|
273
|
+
"Consider splitting into multiple smaller batches",
|
|
274
|
+
]);
|
|
268
275
|
}
|
|
269
276
|
export function finalizeBulkUpdateResponse(response) {
|
|
270
277
|
const appendMessage = (message, addition) => {
|
|
@@ -278,13 +285,13 @@ export function finalizeBulkUpdateResponse(response) {
|
|
|
278
285
|
};
|
|
279
286
|
const fullSize = estimatePayloadSize(response);
|
|
280
287
|
if (fullSize <= FULL_RESPONSE_THRESHOLD) {
|
|
281
|
-
return { ...response, mode:
|
|
288
|
+
return { ...response, mode: "full" };
|
|
282
289
|
}
|
|
283
290
|
const { transactions, ...summaryResponse } = response;
|
|
284
291
|
const summaryPayload = {
|
|
285
292
|
...summaryResponse,
|
|
286
|
-
message: appendMessage(response.message,
|
|
287
|
-
mode:
|
|
293
|
+
message: appendMessage(response.message, "Response downgraded to summary to stay under size limits."),
|
|
294
|
+
mode: "summary",
|
|
288
295
|
};
|
|
289
296
|
if (estimatePayloadSize(summaryPayload) <= SUMMARY_RESPONSE_THRESHOLD) {
|
|
290
297
|
return summaryPayload;
|
|
@@ -306,38 +313,46 @@ export function finalizeBulkUpdateResponse(response) {
|
|
|
306
313
|
}
|
|
307
314
|
return simplified;
|
|
308
315
|
}),
|
|
309
|
-
message: appendMessage(summaryResponse.message,
|
|
310
|
-
mode:
|
|
316
|
+
message: appendMessage(summaryResponse.message, "Response downgraded to ids_only to meet 100KB limit."),
|
|
317
|
+
mode: "ids_only",
|
|
311
318
|
};
|
|
312
319
|
if (estimatePayloadSize(idsOnlyPayload) <= MAX_RESPONSE_BYTES) {
|
|
313
320
|
return idsOnlyPayload;
|
|
314
321
|
}
|
|
315
|
-
throw new ValidationError(
|
|
322
|
+
throw new ValidationError("RESPONSE_TOO_LARGE: Unable to format bulk update response within 100KB limit", `Batch size: ${response.summary.total_requested} transactions`, [
|
|
323
|
+
"Reduce the batch size and retry",
|
|
324
|
+
"Consider splitting into multiple smaller batches",
|
|
325
|
+
]);
|
|
316
326
|
}
|
|
317
327
|
export function handleTransactionError(error, defaultMessage) {
|
|
318
328
|
let errorMessage = defaultMessage;
|
|
319
329
|
if (error instanceof Error) {
|
|
320
|
-
if (error.message.includes(
|
|
321
|
-
|
|
330
|
+
if (error.message.includes("401") ||
|
|
331
|
+
error.message.includes("Unauthorized")) {
|
|
332
|
+
errorMessage = "Invalid or expired YNAB access token";
|
|
322
333
|
}
|
|
323
|
-
else if (error.message.includes(
|
|
324
|
-
|
|
334
|
+
else if (error.message.includes("403") ||
|
|
335
|
+
error.message.includes("Forbidden")) {
|
|
336
|
+
errorMessage = "Insufficient permissions to access YNAB data";
|
|
325
337
|
}
|
|
326
|
-
else if (error.message.includes(
|
|
327
|
-
|
|
338
|
+
else if (error.message.includes("404") ||
|
|
339
|
+
error.message.includes("Not Found")) {
|
|
340
|
+
errorMessage = "Budget, account, category, or transaction not found";
|
|
328
341
|
}
|
|
329
|
-
else if (error.message.includes(
|
|
330
|
-
|
|
342
|
+
else if (error.message.includes("429") ||
|
|
343
|
+
error.message.includes("Too Many Requests")) {
|
|
344
|
+
errorMessage = "Rate limit exceeded. Please try again later";
|
|
331
345
|
}
|
|
332
|
-
else if (error.message.includes(
|
|
333
|
-
|
|
346
|
+
else if (error.message.includes("500") ||
|
|
347
|
+
error.message.includes("Internal Server Error")) {
|
|
348
|
+
errorMessage = "YNAB service is currently unavailable";
|
|
334
349
|
}
|
|
335
350
|
}
|
|
336
351
|
return {
|
|
337
352
|
isError: true,
|
|
338
353
|
content: [
|
|
339
354
|
{
|
|
340
|
-
type:
|
|
355
|
+
type: "text",
|
|
341
356
|
text: responseFormatter.format({
|
|
342
357
|
error: {
|
|
343
358
|
message: errorMessage,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type * as ynab from "ynab";
|
|
3
|
+
import type { DeltaCache } from "../server/deltaCache.js";
|
|
4
|
+
import type { ServerKnowledgeStore } from "../server/serverKnowledgeStore.js";
|
|
5
|
+
import type { ToolRegistry } from "../server/toolRegistry.js";
|
|
6
|
+
import type { ToolContext } from "../types/toolRegistration.js";
|
|
7
|
+
import { type CreateReceiptSplitTransactionParams, type CreateTransactionParams, type CreateTransactionsParams, type DeleteTransactionParams, type UpdateTransactionParams, type UpdateTransactionsParams } from "./transactionSchemas.js";
|
|
8
|
+
export declare function handleCreateTransaction(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: CreateTransactionParams): Promise<CallToolResult>;
|
|
9
|
+
export declare function handleCreateTransaction(ynabAPI: ynab.API, params: CreateTransactionParams): Promise<CallToolResult>;
|
|
10
|
+
export declare function handleCreateReceiptSplitTransaction(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: CreateReceiptSplitTransactionParams): Promise<CallToolResult>;
|
|
11
|
+
export declare function handleCreateReceiptSplitTransaction(ynabAPI: ynab.API, params: CreateReceiptSplitTransactionParams): Promise<CallToolResult>;
|
|
12
|
+
export declare function handleUpdateTransaction(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: UpdateTransactionParams): Promise<CallToolResult>;
|
|
13
|
+
export declare function handleUpdateTransaction(ynabAPI: ynab.API, params: UpdateTransactionParams): Promise<CallToolResult>;
|
|
14
|
+
export declare function handleDeleteTransaction(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: DeleteTransactionParams): Promise<CallToolResult>;
|
|
15
|
+
export declare function handleDeleteTransaction(ynabAPI: ynab.API, params: DeleteTransactionParams): Promise<CallToolResult>;
|
|
16
|
+
export declare function handleCreateTransactions(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: CreateTransactionsParams): Promise<CallToolResult>;
|
|
17
|
+
export declare function handleCreateTransactions(ynabAPI: ynab.API, params: CreateTransactionsParams): Promise<CallToolResult>;
|
|
18
|
+
export declare function handleUpdateTransactions(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: UpdateTransactionsParams): Promise<CallToolResult>;
|
|
19
|
+
export declare function handleUpdateTransactions(ynabAPI: ynab.API, params: UpdateTransactionsParams): Promise<CallToolResult>;
|
|
20
|
+
export declare function registerTransactionWriteTools(registry: ToolRegistry, context: ToolContext): void;
|