ynab-mcp-deluxe 0.1.9

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.
@@ -0,0 +1,257 @@
1
+ /**
2
+ * YNAB API client wrapper with caching and enrichment
3
+ */
4
+ import type { AccountSelector, BudgetSelector, CategorySelector, CreateTransactionInput, EnrichedAccount, EnrichedBudgetMonthDetail, EnrichedBudgetSummary, EnrichedCategory, EnrichedMonthCategory, EnrichedMonthSummary, EnrichedPayee, EnrichedScheduledTransaction, EnrichedTransaction, GetLocalBudgetOptions, LocalBudget, PayeeSelector, TransactionUpdate } from './types.js';
5
+ import { type AccountType, type CategoryGroupWithCategories, type CurrencyFormat } from 'ynab';
6
+ /**
7
+ * Check if the server is running in read-only mode
8
+ */
9
+ export declare function isReadOnlyMode(): boolean;
10
+ /**
11
+ * Assert that write operations are allowed
12
+ * @throws Error if read-only mode is enabled
13
+ */
14
+ export declare function assertWriteAllowed(operation: string): void;
15
+ /**
16
+ * Get the configured sync interval in milliseconds.
17
+ * Configured via YNAB_SYNC_INTERVAL_SECONDS environment variable.
18
+ * Default: 600 seconds (10 minutes)
19
+ * Set to 0 to always sync before every operation.
20
+ */
21
+ export declare function getSyncIntervalMs(): number;
22
+ /**
23
+ * Logger interface matching FastMCP's context log
24
+ */
25
+ interface ContextLog {
26
+ debug: (message: string, data?: unknown) => void;
27
+ error: (message: string, data?: unknown) => void;
28
+ info: (message: string, data?: unknown) => void;
29
+ warn: (message: string, data?: unknown) => void;
30
+ }
31
+ /**
32
+ * YNAB client with local budget sync
33
+ */
34
+ declare class YnabClient {
35
+ private api;
36
+ private budgets;
37
+ private localBudgets;
38
+ /** Store previous full API responses for drift snapshot collection */
39
+ private previousBudgetDetails;
40
+ private lastUsedBudgetId;
41
+ private syncProvider;
42
+ /**
43
+ * Get the YNAB API instance, creating it if necessary
44
+ */
45
+ private getApi;
46
+ /**
47
+ * Get the sync provider, creating it if necessary
48
+ */
49
+ private getSyncProvider;
50
+ /**
51
+ * Determine what kind of sync is needed based on policy.
52
+ * Returns both the sync type and the reason for logging.
53
+ */
54
+ private determineSyncNeeded;
55
+ /**
56
+ * Get a local budget, syncing with YNAB if needed.
57
+ *
58
+ * SYNC STRATEGY (Drift Collection Mode):
59
+ * - Always fetch full budget (guaranteed correct)
60
+ * - Also fetch delta and merge to build "merged" version for comparison
61
+ * - Run drift detection comparing merged vs full
62
+ * - If drift detected (at sample rate), save artifacts for later analysis
63
+ * - Return the full budget (source of truth)
64
+ *
65
+ * This approach unblocks development while passively collecting drift data.
66
+ *
67
+ * @param budgetId - The budget ID
68
+ * @param options - Sync options (forceSync: 'full' | 'delta' | undefined)
69
+ * @param log - Logger for debug output
70
+ * @returns The LocalBudget
71
+ */
72
+ getLocalBudgetWithSync(budgetId: string, options?: GetLocalBudgetOptions, contextLog?: ContextLog): Promise<LocalBudget>;
73
+ /**
74
+ * Mark a budget as needing sync (called after write operations).
75
+ * The next read operation will trigger a delta sync.
76
+ */
77
+ markNeedsSync(budgetId: string): void;
78
+ /**
79
+ * Get all budgets
80
+ */
81
+ getBudgets(): Promise<EnrichedBudgetSummary[]>;
82
+ /**
83
+ * Resolve a budget selector to a budget ID
84
+ *
85
+ * IMPORTANT: If YNAB_BUDGET_ID is set, it acts as a HARD CONSTRAINT.
86
+ * Only that budget can be accessed - any attempt to use a different
87
+ * budget will throw an error. This is a safety mechanism for testing.
88
+ */
89
+ resolveBudgetId(selector?: BudgetSelector): Promise<string>;
90
+ /**
91
+ * Get the local budget for internal use.
92
+ * This is a convenience wrapper around getLocalBudgetWithSync() for methods
93
+ * that don't have access to a logger context.
94
+ */
95
+ private getLocalBudget;
96
+ /**
97
+ * Build CategoryGroupWithCategories array from LocalBudget data.
98
+ * The full budget endpoint returns categories and groups separately,
99
+ * so we need to join them for compatibility with some existing methods.
100
+ */
101
+ private buildCategoryGroupsWithCategories;
102
+ /**
103
+ * Convert milliunits to currency amount
104
+ */
105
+ private toCurrency;
106
+ /**
107
+ * Enrich a transaction with resolved names.
108
+ * Used for TransactionDetail (from individual transaction endpoints),
109
+ * which already has payee_name, category_name, account_name, and
110
+ * inline subtransactions[].
111
+ */
112
+ private enrichTransaction;
113
+ /**
114
+ * Enrich a TransactionSummary (from full budget endpoint) with resolved names.
115
+ *
116
+ * The full budget endpoint returns TransactionSummary[] which only has IDs,
117
+ * not resolved names. This method looks up names from the LocalBudget's
118
+ * lookup maps and joins subtransactions from the flat subtransactions array.
119
+ *
120
+ * @param tx - The TransactionSummary from LocalBudget.transactions
121
+ * @param localBudget - The LocalBudget with lookup maps and subtransactions
122
+ * @returns An EnrichedTransaction with resolved names and subtransactions
123
+ */
124
+ private enrichTransactionSummary;
125
+ /**
126
+ * Get transactions with optional filters.
127
+ *
128
+ * Reads from LocalBudget.transactions and applies filters locally.
129
+ * No API call is made - data comes from the synced local budget.
130
+ */
131
+ getTransactions(budgetId: string, options?: {
132
+ accountId?: string;
133
+ sinceDate?: string;
134
+ type?: 'uncategorized' | 'unapproved';
135
+ }): Promise<EnrichedTransaction[]>;
136
+ /**
137
+ * Resolve an account selector to an account ID
138
+ */
139
+ resolveAccountId(budgetId: string, selector: AccountSelector): Promise<string>;
140
+ /**
141
+ * Get all accounts for a budget
142
+ */
143
+ getAccounts(budgetId: string, includeClosed?: boolean): Promise<EnrichedAccount[]>;
144
+ /**
145
+ * Get all categories for a budget
146
+ */
147
+ getCategories(budgetId: string, includeHidden?: boolean): Promise<{
148
+ flat: EnrichedCategory[];
149
+ groups: CategoryGroupWithCategories[];
150
+ }>;
151
+ /**
152
+ * Get all payees for a budget
153
+ */
154
+ getPayees(budgetId: string): Promise<EnrichedPayee[]>;
155
+ /**
156
+ * Update multiple transactions using the bulk PATCH endpoint
157
+ */
158
+ updateTransactions(budgetId: string, updates: TransactionUpdate[]): Promise<{
159
+ updated: EnrichedTransaction[];
160
+ }>;
161
+ /**
162
+ * Get currency format for a budget
163
+ */
164
+ getCurrencyFormat(budgetId: string): Promise<CurrencyFormat | null>;
165
+ /**
166
+ * Get budget info (name, id) for journaling
167
+ */
168
+ getBudgetInfo(budgetId: string): Promise<{
169
+ id: string;
170
+ name: string;
171
+ }>;
172
+ /**
173
+ * Get raw budget detail for backup purposes
174
+ * Returns the complete budget data as returned by YNAB API
175
+ * (effectively a full budget export per YNAB docs)
176
+ */
177
+ getBudgetByIdRaw(budgetId: string): Promise<{
178
+ budget: unknown;
179
+ server_knowledge: number;
180
+ }>;
181
+ /**
182
+ * Resolve a category selector to a category ID
183
+ */
184
+ resolveCategoryId(budgetId: string, selector: CategorySelector): Promise<string>;
185
+ /**
186
+ * Resolve a payee selector to a payee ID
187
+ */
188
+ resolvePayeeId(budgetId: string, selector: PayeeSelector): Promise<string | null>;
189
+ /**
190
+ * Get a single transaction by ID.
191
+ *
192
+ * Reads from LocalBudget.transactions - no API call is made.
193
+ */
194
+ getTransaction(budgetId: string, transactionId: string): Promise<EnrichedTransaction>;
195
+ /**
196
+ * Get scheduled transactions.
197
+ *
198
+ * Reads from LocalBudget.scheduledTransactions - no API call is made.
199
+ */
200
+ getScheduledTransactions(budgetId: string): Promise<EnrichedScheduledTransaction[]>;
201
+ /**
202
+ * Get budget months list.
203
+ *
204
+ * Reads from LocalBudget.months - no API call is made.
205
+ */
206
+ getBudgetMonths(budgetId: string): Promise<EnrichedMonthSummary[]>;
207
+ /**
208
+ * Get budget month detail with categories.
209
+ *
210
+ * Reads from LocalBudget.months - no API call is made.
211
+ */
212
+ getBudgetMonth(budgetId: string, month: string): Promise<EnrichedBudgetMonthDetail>;
213
+ /**
214
+ * Create one or more transactions
215
+ */
216
+ createTransactions(budgetId: string, transactions: CreateTransactionInput[]): Promise<{
217
+ created: EnrichedTransaction[];
218
+ duplicates: string[];
219
+ }>;
220
+ /**
221
+ * Delete a transaction
222
+ */
223
+ deleteTransaction(budgetId: string, transactionId: string): Promise<{
224
+ deleted: EnrichedTransaction;
225
+ }>;
226
+ /**
227
+ * Import transactions from linked accounts
228
+ */
229
+ importTransactions(budgetId: string): Promise<{
230
+ imported_count: number;
231
+ transaction_ids: string[];
232
+ }>;
233
+ /**
234
+ * Create a new account
235
+ */
236
+ createAccount(budgetId: string, name: string, type: AccountType, balance: number): Promise<EnrichedAccount>;
237
+ /**
238
+ * Update category budget for a month
239
+ */
240
+ updateCategoryBudget(budgetId: string, month: string, categoryId: string, budgeted: number): Promise<EnrichedMonthCategory>;
241
+ /**
242
+ * Clear all local budgets (useful for testing or forcing full re-sync)
243
+ */
244
+ clearLocalBudgets(): void;
245
+ /**
246
+ * Force sync for a specific budget or all budgets.
247
+ * If budgetId provided, marks that budget as needing sync.
248
+ * If no budgetId provided, clears all local budgets (forcing full re-sync on next access).
249
+ *
250
+ * @deprecated Use markNeedsSync() for individual budgets. This method
251
+ * is kept for backwards compatibility but will be removed in a future version.
252
+ */
253
+ invalidateCache(budgetId?: string): void;
254
+ }
255
+ export declare const ynabClient: YnabClient;
256
+ export {};
257
+ //# sourceMappingURL=ynab-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ynab-client.d.ts","sourceRoot":"","sources":["../src/ynab-client.ts"],"names":[],"mappings":"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"}