@dizzlkheinz/ynab-mcpb 0.16.1 → 0.17.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/.code/agents/0098661e-0fa3-4990-beb9-c0cbf3f123aa/status.txt +1 -0
- package/.code/agents/1324/exec-call_tIpx9uV1TpARbAMZonRQm8AO.txt +757 -0
- package/.code/agents/1572/exec-call_GjVFBFOWcY7lE0idc5nWlLNh.txt +781 -0
- package/.code/agents/1846/exec-call_1YNAVD18RjrMN7JnfkkQhUP3.txt +766 -0
- package/.code/agents/1846/exec-call_lh3lDzE4WJAh1lFiomiiZ73D.txt +766 -0
- package/.code/agents/2038/exec-call_DYwOukaYsL8VCONWmV2rUW5u.txt +766 -0
- package/.code/agents/2038/exec-call_c7fOQ7UrpVcTtvdfGBRM146V.txt +652 -0
- package/.code/agents/2038/exec-call_ySNyq9Mm55jWE480s54r5QcA.txt +766 -0
- package/.code/agents/2256/exec-call_AtPcRWPmFPMcmX6qOFm1fCEY.txt +766 -0
- package/.code/agents/2454/exec-call_aFJpupwjfZeOBm7ixI5Vc8z2.txt +766 -0
- package/.code/agents/2454/exec-call_wogZ4HfXTodTEXvdgXlVUBpv.txt +766 -0
- package/.code/agents/2e905864-aa07-4314-bcf9-c5b32277e4ac/result.txt +36 -0
- package/.code/agents/3073/exec-call_Peeagc9DxGYLgE6pNdMZhqIE.txt +766 -0
- package/.code/agents/3073/exec-call_d2YSE3hXF08KRSoUM3qd8Z3x.txt +766 -0
- package/.code/agents/335aa031-466d-4fb7-925f-3cd864e264d0/result.txt +191 -0
- package/.code/agents/3364/exec-call_NbhIrsM5HhyDZDmJZG5CuCYL.txt +766 -0
- package/.code/agents/3364/exec-call_cKtJg0NrXiwXEFwlsE3uPZRA.txt +766 -0
- package/.code/agents/36d98414-5cde-4d9d-9a67-a240a18c1f07/result.txt +189 -0
- package/.code/agents/4604e866-b7b8-44f5-992f-2f683b0a523b/status.txt +1 -0
- package/.code/agents/5f8dc01c-47b3-4163-b0b3-aa31be89fcdc/status.txt +1 -0
- package/.code/agents/7/exec-call_HltHpkDox0Zm1vGEjdksUgpE.txt +1120 -0
- package/.code/agents/7/exec-call_LCATrOPPAgbxW9Q1z0XaVi2E.txt +2646 -0
- package/.code/agents/7/exec-call_W8DeRfNG9hvbgVFvf0clBf6R.txt +2646 -0
- package/.code/agents/94a0ddf3-a304-4ec3-913e-3cceef509948/error.txt +1 -0
- package/.code/agents/e2c752b7-711d-423a-af57-f53c809deb84/result.txt +160 -0
- package/.code/agents/e6601719-c31f-4a0e-8c71-d70787d0ab71/status.txt +1 -0
- package/.code/agents/f250b7ed-5bd5-4036-aa8c-ce63caee7d61/result.txt +20 -0
- package/AGENTS.md +1 -36
- package/CLAUDE.md +28 -43
- package/NUL +0 -1
- package/README.md +8 -10
- package/dist/bundle/index.cjs +41 -41
- package/dist/server/YNABMCPServer.js +28 -381
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.js +1 -0
- package/dist/tools/accountTools.d.ts +2 -0
- package/dist/tools/accountTools.js +45 -0
- package/dist/tools/adapters.d.ts +12 -0
- package/dist/tools/adapters.js +25 -0
- package/dist/tools/budgetTools.d.ts +2 -0
- package/dist/tools/budgetTools.js +30 -0
- package/dist/tools/categoryTools.d.ts +2 -0
- package/dist/tools/categoryTools.js +45 -0
- package/dist/tools/monthTools.d.ts +2 -0
- package/dist/tools/monthTools.js +32 -0
- package/dist/tools/payeeTools.d.ts +2 -0
- package/dist/tools/payeeTools.js +32 -0
- package/dist/tools/reconciliation/index.d.ts +2 -0
- package/dist/tools/reconciliation/index.js +33 -0
- package/dist/tools/schemas/common.d.ts +3 -0
- package/dist/tools/schemas/common.js +3 -0
- package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
- package/dist/tools/transactionTools.d.ts +2 -0
- package/dist/tools/transactionTools.js +124 -0
- package/dist/tools/utilityTools.d.ts +3 -1
- package/dist/tools/utilityTools.js +32 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/toolRegistration.d.ts +27 -0
- package/dist/types/toolRegistration.js +1 -0
- package/package.json +2 -2
- package/scripts/run-domain-integration-tests.js +4 -1
- package/src/__tests__/workflows.e2e.test.ts +1 -7
- package/src/server/YNABMCPServer.ts +33 -519
- package/src/server/__tests__/toolRegistration.test.ts +236 -0
- package/src/server/config.ts +1 -0
- package/src/tools/__tests__/adapters.test.ts +113 -0
- package/src/tools/__tests__/utilityTools.test.ts +7 -7
- package/src/tools/accountTools.ts +53 -0
- package/src/tools/adapters.ts +74 -0
- package/src/tools/budgetTools.ts +37 -0
- package/src/tools/categoryTools.ts +53 -0
- package/src/tools/monthTools.ts +39 -0
- package/src/tools/payeeTools.ts +39 -0
- package/src/tools/reconciliation/index.ts +45 -0
- package/src/tools/schemas/common.ts +18 -0
- package/src/tools/transactionTools.ts +140 -0
- package/src/tools/utilityTools.ts +42 -2
- package/src/types/index.ts +3 -0
- package/src/types/toolRegistration.ts +88 -0
- package/.github/workflows/pr-description-check.yml +0 -88
- package/docs/README.md +0 -72
- package/docs/getting-started/CONFIGURATION.md +0 -175
- package/docs/getting-started/INSTALLATION.md +0 -333
- package/docs/getting-started/QUICKSTART.md +0 -282
- package/docs/guides/ARCHITECTURE.md +0 -533
- package/docs/guides/DEPLOYMENT.md +0 -189
- package/docs/guides/INTEGRATION_TESTING.md +0 -730
- package/docs/guides/TESTING.md +0 -591
- package/docs/reconciliation-flow.md +0 -83
- package/docs/reference/EXAMPLES.md +0 -946
- package/docs/reference/TOOLS.md +0 -348
- package/docs/reference/TROUBLESHOOTING.md +0 -481
|
@@ -11,19 +11,18 @@ import { loadConfig } from './config.js';
|
|
|
11
11
|
import { createErrorHandler, ErrorHandler } from './errorHandler.js';
|
|
12
12
|
import { BudgetResolver } from './budgetResolver.js';
|
|
13
13
|
import { SecurityMiddleware, withSecurityWrapper } from './securityMiddleware.js';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { handleGetUser, handleConvertAmount, ConvertAmountSchema } from '../tools/utilityTools.js';
|
|
14
|
+
import { registerBudgetTools } from '../tools/budgetTools.js';
|
|
15
|
+
import { registerAccountTools } from '../tools/accountTools.js';
|
|
16
|
+
import { registerTransactionTools } from '../tools/transactionTools.js';
|
|
17
|
+
import { registerReconciliationTools } from '../tools/reconciliation/index.js';
|
|
18
|
+
import { registerCategoryTools } from '../tools/categoryTools.js';
|
|
19
|
+
import { registerPayeeTools } from '../tools/payeeTools.js';
|
|
20
|
+
import { registerMonthTools } from '../tools/monthTools.js';
|
|
21
|
+
import { registerUtilityTools } from '../tools/utilityTools.js';
|
|
22
|
+
import { emptyObjectSchema } from '../tools/schemas/common.js';
|
|
24
23
|
import { cacheManager, CacheManager } from './cacheManager.js';
|
|
25
24
|
import { responseFormatter } from './responseFormatter.js';
|
|
26
|
-
import { ToolRegistry
|
|
25
|
+
import { ToolRegistry } from './toolRegistry.js';
|
|
27
26
|
import { ResourceManager } from './resources.js';
|
|
28
27
|
import { PromptManager } from './prompts.js';
|
|
29
28
|
import { DiagnosticManager } from './diagnostics.js';
|
|
@@ -31,12 +30,11 @@ import { ServerKnowledgeStore } from './serverKnowledgeStore.js';
|
|
|
31
30
|
import { DeltaCache } from './deltaCache.js';
|
|
32
31
|
import { DeltaFetcher } from '../tools/deltaFetcher.js';
|
|
33
32
|
import { ToolAnnotationPresets } from '../tools/toolCategories.js';
|
|
34
|
-
import { GetUserOutputSchema, ConvertAmountOutputSchema, GetDefaultBudgetOutputSchema, SetDefaultBudgetOutputSchema, ClearCacheOutputSchema, SetOutputFormatOutputSchema, DiagnosticInfoOutputSchema, GetBudgetOutputSchema, ListBudgetsOutputSchema, ListAccountsOutputSchema, GetAccountOutputSchema, GetTransactionOutputSchema, ExportTransactionsOutputSchema, CompareTransactionsOutputSchema, ListCategoriesOutputSchema, GetCategoryOutputSchema, ListPayeesOutputSchema, GetPayeeOutputSchema, GetMonthOutputSchema, ListMonthsOutputSchema, } from '../tools/schemas/outputs/index.js';
|
|
35
33
|
export class YNABMCPServer {
|
|
36
34
|
constructor(exitOnError = true) {
|
|
37
35
|
this.exitOnError = exitOnError;
|
|
38
36
|
this.configInstance = loadConfig();
|
|
39
|
-
this.defaultBudgetId =
|
|
37
|
+
this.defaultBudgetId = this.configInstance.YNAB_DEFAULT_BUDGET_ID;
|
|
40
38
|
this.ynabAPI = new ynab.API(this.configInstance.YNAB_ACCESS_TOKEN);
|
|
41
39
|
this.serverVersion = this.readPackageVersion() ?? '0.0.0';
|
|
42
40
|
this.server = new Server({
|
|
@@ -211,23 +209,16 @@ export class YNABMCPServer {
|
|
|
211
209
|
const register = (definition) => {
|
|
212
210
|
this.toolRegistry.register(definition);
|
|
213
211
|
};
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const result = BudgetResolver.resolveBudgetId(provided, this.defaultBudgetId);
|
|
224
|
-
if (typeof result === 'string') {
|
|
225
|
-
return { budget_id: result };
|
|
226
|
-
}
|
|
227
|
-
throw new DefaultArgumentResolutionError(result);
|
|
228
|
-
};
|
|
212
|
+
const toolContext = {
|
|
213
|
+
ynabAPI: this.ynabAPI,
|
|
214
|
+
deltaFetcher: this.deltaFetcher,
|
|
215
|
+
deltaCache: this.deltaCache,
|
|
216
|
+
serverKnowledgeStore: this.serverKnowledgeStore,
|
|
217
|
+
getDefaultBudgetId: () => this.defaultBudgetId,
|
|
218
|
+
setDefaultBudget: (budgetId) => this.setDefaultBudget(budgetId),
|
|
219
|
+
cacheManager,
|
|
220
|
+
diagnosticManager: this.diagnosticManager,
|
|
229
221
|
};
|
|
230
|
-
const emptyObjectSchema = z.object({}).strict();
|
|
231
222
|
const setDefaultBudgetSchema = z.object({ budget_id: z.string().min(1) }).strict();
|
|
232
223
|
const diagnosticInfoSchema = z
|
|
233
224
|
.object({
|
|
@@ -245,38 +236,18 @@ export class YNABMCPServer {
|
|
|
245
236
|
pretty_spaces: z.number().int().min(0).max(10).optional(),
|
|
246
237
|
})
|
|
247
238
|
.strict();
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
annotations: {
|
|
257
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
258
|
-
title: 'YNAB: List Budgets',
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
});
|
|
262
|
-
register({
|
|
263
|
-
name: 'get_budget',
|
|
264
|
-
description: 'Get detailed information for a specific budget',
|
|
265
|
-
inputSchema: GetBudgetSchema,
|
|
266
|
-
outputSchema: GetBudgetOutputSchema,
|
|
267
|
-
handler: adapt(handleGetBudget),
|
|
268
|
-
metadata: {
|
|
269
|
-
annotations: {
|
|
270
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
271
|
-
title: 'YNAB: Get Budget Details',
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
});
|
|
239
|
+
registerBudgetTools(this.toolRegistry, toolContext);
|
|
240
|
+
registerPayeeTools(this.toolRegistry, toolContext);
|
|
241
|
+
registerCategoryTools(this.toolRegistry, toolContext);
|
|
242
|
+
registerAccountTools(this.toolRegistry, toolContext);
|
|
243
|
+
registerMonthTools(this.toolRegistry, toolContext);
|
|
244
|
+
registerTransactionTools(this.toolRegistry, toolContext);
|
|
245
|
+
registerReconciliationTools(this.toolRegistry, toolContext);
|
|
246
|
+
registerUtilityTools(this.toolRegistry, toolContext);
|
|
275
247
|
register({
|
|
276
248
|
name: 'set_default_budget',
|
|
277
249
|
description: 'Set the default budget for subsequent operations',
|
|
278
250
|
inputSchema: setDefaultBudgetSchema,
|
|
279
|
-
outputSchema: SetDefaultBudgetOutputSchema,
|
|
280
251
|
handler: async ({ input }) => {
|
|
281
252
|
const { budget_id } = input;
|
|
282
253
|
await this.ynabAPI.budgets.getBudgetById(budget_id);
|
|
@@ -308,7 +279,6 @@ export class YNABMCPServer {
|
|
|
308
279
|
name: 'get_default_budget',
|
|
309
280
|
description: 'Get the currently set default budget',
|
|
310
281
|
inputSchema: emptyObjectSchema,
|
|
311
|
-
outputSchema: GetDefaultBudgetOutputSchema,
|
|
312
282
|
handler: async () => {
|
|
313
283
|
try {
|
|
314
284
|
const defaultBudget = this.getDefaultBudget();
|
|
@@ -338,331 +308,10 @@ export class YNABMCPServer {
|
|
|
338
308
|
},
|
|
339
309
|
},
|
|
340
310
|
});
|
|
341
|
-
register({
|
|
342
|
-
name: 'list_accounts',
|
|
343
|
-
description: 'List all accounts for a specific budget (uses default budget if not specified)',
|
|
344
|
-
inputSchema: ListAccountsSchema,
|
|
345
|
-
outputSchema: ListAccountsOutputSchema,
|
|
346
|
-
handler: adaptWithDelta(handleListAccounts),
|
|
347
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
348
|
-
metadata: {
|
|
349
|
-
annotations: {
|
|
350
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
351
|
-
title: 'YNAB: List Accounts',
|
|
352
|
-
},
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
register({
|
|
356
|
-
name: 'get_account',
|
|
357
|
-
description: 'Get detailed information for a specific account',
|
|
358
|
-
inputSchema: GetAccountSchema,
|
|
359
|
-
outputSchema: GetAccountOutputSchema,
|
|
360
|
-
handler: adapt(handleGetAccount),
|
|
361
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
362
|
-
metadata: {
|
|
363
|
-
annotations: {
|
|
364
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
365
|
-
title: 'YNAB: Get Account Details',
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
});
|
|
369
|
-
register({
|
|
370
|
-
name: 'create_account',
|
|
371
|
-
description: 'Create a new account in the specified budget',
|
|
372
|
-
inputSchema: CreateAccountSchema,
|
|
373
|
-
outputSchema: LooseObjectSchema,
|
|
374
|
-
handler: adaptWrite(handleCreateAccount),
|
|
375
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
376
|
-
metadata: {
|
|
377
|
-
annotations: {
|
|
378
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_CREATE,
|
|
379
|
-
title: 'YNAB: Create Account',
|
|
380
|
-
},
|
|
381
|
-
},
|
|
382
|
-
});
|
|
383
|
-
register({
|
|
384
|
-
name: 'list_transactions',
|
|
385
|
-
description: 'List transactions for a budget with optional filtering',
|
|
386
|
-
inputSchema: ListTransactionsSchema,
|
|
387
|
-
outputSchema: LooseObjectSchema,
|
|
388
|
-
handler: adaptWithDelta(handleListTransactions),
|
|
389
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
390
|
-
metadata: {
|
|
391
|
-
annotations: {
|
|
392
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
393
|
-
title: 'YNAB: List Transactions',
|
|
394
|
-
},
|
|
395
|
-
},
|
|
396
|
-
});
|
|
397
|
-
register({
|
|
398
|
-
name: 'export_transactions',
|
|
399
|
-
description: 'Export all transactions to a JSON file with descriptive filename',
|
|
400
|
-
inputSchema: ExportTransactionsSchema,
|
|
401
|
-
outputSchema: ExportTransactionsOutputSchema,
|
|
402
|
-
handler: adapt(handleExportTransactions),
|
|
403
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
404
|
-
metadata: {
|
|
405
|
-
annotations: {
|
|
406
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
407
|
-
title: 'YNAB: Export Transactions',
|
|
408
|
-
},
|
|
409
|
-
},
|
|
410
|
-
});
|
|
411
|
-
register({
|
|
412
|
-
name: 'compare_transactions',
|
|
413
|
-
description: 'Compare bank transactions from CSV with YNAB transactions to find missing entries',
|
|
414
|
-
inputSchema: CompareTransactionsSchema,
|
|
415
|
-
outputSchema: CompareTransactionsOutputSchema,
|
|
416
|
-
handler: adapt(handleCompareTransactions),
|
|
417
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
418
|
-
metadata: {
|
|
419
|
-
annotations: {
|
|
420
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
421
|
-
title: 'YNAB: Compare Transactions',
|
|
422
|
-
},
|
|
423
|
-
},
|
|
424
|
-
});
|
|
425
|
-
register({
|
|
426
|
-
name: 'reconcile_account',
|
|
427
|
-
description: 'Guided reconciliation workflow with human narrative, insight detection, and optional execution (create/update/unclear). Set include_structured_data=true to also get full JSON output (large).',
|
|
428
|
-
inputSchema: ReconcileAccountSchema,
|
|
429
|
-
outputSchema: LooseObjectSchema,
|
|
430
|
-
handler: adaptWithDelta(handleReconcileAccount),
|
|
431
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
432
|
-
metadata: {
|
|
433
|
-
annotations: {
|
|
434
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
|
|
435
|
-
title: 'YNAB: Reconcile Account',
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
});
|
|
439
|
-
register({
|
|
440
|
-
name: 'get_transaction',
|
|
441
|
-
description: 'Get detailed information for a specific transaction',
|
|
442
|
-
inputSchema: GetTransactionSchema,
|
|
443
|
-
outputSchema: GetTransactionOutputSchema,
|
|
444
|
-
handler: adapt(handleGetTransaction),
|
|
445
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
446
|
-
metadata: {
|
|
447
|
-
annotations: {
|
|
448
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
449
|
-
title: 'YNAB: Get Transaction Details',
|
|
450
|
-
},
|
|
451
|
-
},
|
|
452
|
-
});
|
|
453
|
-
register({
|
|
454
|
-
name: 'create_transaction',
|
|
455
|
-
description: 'Create a new transaction in the specified budget and account',
|
|
456
|
-
inputSchema: CreateTransactionSchema,
|
|
457
|
-
outputSchema: LooseObjectSchema,
|
|
458
|
-
handler: adaptWrite(handleCreateTransaction),
|
|
459
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
460
|
-
metadata: {
|
|
461
|
-
annotations: {
|
|
462
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_CREATE,
|
|
463
|
-
title: 'YNAB: Create Transaction',
|
|
464
|
-
},
|
|
465
|
-
},
|
|
466
|
-
});
|
|
467
|
-
register({
|
|
468
|
-
name: 'create_transactions',
|
|
469
|
-
description: 'Create multiple transactions in a single batch (1-100 items) with duplicate detection, dry-run validation, and automatic response size management with correlation metadata.',
|
|
470
|
-
inputSchema: CreateTransactionsSchema,
|
|
471
|
-
outputSchema: LooseObjectSchema,
|
|
472
|
-
handler: adaptWrite(handleCreateTransactions),
|
|
473
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
474
|
-
metadata: {
|
|
475
|
-
annotations: {
|
|
476
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_CREATE,
|
|
477
|
-
title: 'YNAB: Create Multiple Transactions',
|
|
478
|
-
},
|
|
479
|
-
},
|
|
480
|
-
});
|
|
481
|
-
register({
|
|
482
|
-
name: 'update_transactions',
|
|
483
|
-
description: 'Update multiple transactions in a single batch (1-100 items) with dry-run validation, automatic cache invalidation, and response size management. Supports optional original_account_id and original_date metadata for efficient cache invalidation.',
|
|
484
|
-
inputSchema: UpdateTransactionsSchema,
|
|
485
|
-
outputSchema: LooseObjectSchema,
|
|
486
|
-
handler: adaptWrite(handleUpdateTransactions),
|
|
487
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
488
|
-
metadata: {
|
|
489
|
-
annotations: {
|
|
490
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
|
|
491
|
-
title: 'YNAB: Update Multiple Transactions',
|
|
492
|
-
},
|
|
493
|
-
},
|
|
494
|
-
});
|
|
495
|
-
register({
|
|
496
|
-
name: 'create_receipt_split_transaction',
|
|
497
|
-
description: 'Create a split transaction from receipt items with proportional tax allocation',
|
|
498
|
-
inputSchema: CreateReceiptSplitTransactionSchema,
|
|
499
|
-
outputSchema: LooseObjectSchema,
|
|
500
|
-
handler: adaptWrite(handleCreateReceiptSplitTransaction),
|
|
501
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
502
|
-
metadata: {
|
|
503
|
-
annotations: {
|
|
504
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_CREATE,
|
|
505
|
-
title: 'YNAB: Create Split Transaction from Receipt',
|
|
506
|
-
},
|
|
507
|
-
},
|
|
508
|
-
});
|
|
509
|
-
register({
|
|
510
|
-
name: 'update_transaction',
|
|
511
|
-
description: 'Update an existing transaction',
|
|
512
|
-
inputSchema: UpdateTransactionSchema,
|
|
513
|
-
outputSchema: LooseObjectSchema,
|
|
514
|
-
handler: adaptWrite(handleUpdateTransaction),
|
|
515
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
516
|
-
metadata: {
|
|
517
|
-
annotations: {
|
|
518
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
|
|
519
|
-
title: 'YNAB: Update Transaction',
|
|
520
|
-
},
|
|
521
|
-
},
|
|
522
|
-
});
|
|
523
|
-
register({
|
|
524
|
-
name: 'delete_transaction',
|
|
525
|
-
description: 'Delete a transaction from the specified budget',
|
|
526
|
-
inputSchema: DeleteTransactionSchema,
|
|
527
|
-
outputSchema: LooseObjectSchema,
|
|
528
|
-
handler: adaptWrite(handleDeleteTransaction),
|
|
529
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
530
|
-
metadata: {
|
|
531
|
-
annotations: {
|
|
532
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_DELETE,
|
|
533
|
-
title: 'YNAB: Delete Transaction',
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
});
|
|
537
|
-
register({
|
|
538
|
-
name: 'list_categories',
|
|
539
|
-
description: 'List all categories for a specific budget',
|
|
540
|
-
inputSchema: ListCategoriesSchema,
|
|
541
|
-
outputSchema: ListCategoriesOutputSchema,
|
|
542
|
-
handler: adaptWithDelta(handleListCategories),
|
|
543
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
544
|
-
metadata: {
|
|
545
|
-
annotations: {
|
|
546
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
547
|
-
title: 'YNAB: List Categories',
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
});
|
|
551
|
-
register({
|
|
552
|
-
name: 'get_category',
|
|
553
|
-
description: 'Get detailed information for a specific category',
|
|
554
|
-
inputSchema: GetCategorySchema,
|
|
555
|
-
outputSchema: GetCategoryOutputSchema,
|
|
556
|
-
handler: adapt(handleGetCategory),
|
|
557
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
558
|
-
metadata: {
|
|
559
|
-
annotations: {
|
|
560
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
561
|
-
title: 'YNAB: Get Category Details',
|
|
562
|
-
},
|
|
563
|
-
},
|
|
564
|
-
});
|
|
565
|
-
register({
|
|
566
|
-
name: 'update_category',
|
|
567
|
-
description: 'Update the budgeted amount for a category in the current month',
|
|
568
|
-
inputSchema: UpdateCategorySchema,
|
|
569
|
-
outputSchema: LooseObjectSchema,
|
|
570
|
-
handler: adaptWrite(handleUpdateCategory),
|
|
571
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
572
|
-
metadata: {
|
|
573
|
-
annotations: {
|
|
574
|
-
...ToolAnnotationPresets.WRITE_EXTERNAL_UPDATE,
|
|
575
|
-
title: 'YNAB: Update Category Budget',
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
});
|
|
579
|
-
register({
|
|
580
|
-
name: 'list_payees',
|
|
581
|
-
description: 'List all payees for a specific budget',
|
|
582
|
-
inputSchema: ListPayeesSchema,
|
|
583
|
-
outputSchema: ListPayeesOutputSchema,
|
|
584
|
-
handler: adaptWithDelta(handleListPayees),
|
|
585
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
586
|
-
metadata: {
|
|
587
|
-
annotations: {
|
|
588
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
589
|
-
title: 'YNAB: List Payees',
|
|
590
|
-
},
|
|
591
|
-
},
|
|
592
|
-
});
|
|
593
|
-
register({
|
|
594
|
-
name: 'get_payee',
|
|
595
|
-
description: 'Get detailed information for a specific payee',
|
|
596
|
-
inputSchema: GetPayeeSchema,
|
|
597
|
-
outputSchema: GetPayeeOutputSchema,
|
|
598
|
-
handler: adapt(handleGetPayee),
|
|
599
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
600
|
-
metadata: {
|
|
601
|
-
annotations: {
|
|
602
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
603
|
-
title: 'YNAB: Get Payee Details',
|
|
604
|
-
},
|
|
605
|
-
},
|
|
606
|
-
});
|
|
607
|
-
register({
|
|
608
|
-
name: 'get_month',
|
|
609
|
-
description: 'Get budget data for a specific month',
|
|
610
|
-
inputSchema: GetMonthSchema,
|
|
611
|
-
outputSchema: GetMonthOutputSchema,
|
|
612
|
-
handler: adapt(handleGetMonth),
|
|
613
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
614
|
-
metadata: {
|
|
615
|
-
annotations: {
|
|
616
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
617
|
-
title: 'YNAB: Get Month Budget Data',
|
|
618
|
-
},
|
|
619
|
-
},
|
|
620
|
-
});
|
|
621
|
-
register({
|
|
622
|
-
name: 'list_months',
|
|
623
|
-
description: 'List all months summary data for a budget',
|
|
624
|
-
inputSchema: ListMonthsSchema,
|
|
625
|
-
outputSchema: ListMonthsOutputSchema,
|
|
626
|
-
handler: adaptWithDelta(handleListMonths),
|
|
627
|
-
defaultArgumentResolver: resolveBudgetId(),
|
|
628
|
-
metadata: {
|
|
629
|
-
annotations: {
|
|
630
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
631
|
-
title: 'YNAB: List Months',
|
|
632
|
-
},
|
|
633
|
-
},
|
|
634
|
-
});
|
|
635
|
-
register({
|
|
636
|
-
name: 'get_user',
|
|
637
|
-
description: 'Get information about the authenticated user',
|
|
638
|
-
inputSchema: emptyObjectSchema,
|
|
639
|
-
outputSchema: GetUserOutputSchema,
|
|
640
|
-
handler: adaptNoInput(handleGetUser),
|
|
641
|
-
metadata: {
|
|
642
|
-
annotations: {
|
|
643
|
-
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
644
|
-
title: 'YNAB: Get User Information',
|
|
645
|
-
},
|
|
646
|
-
},
|
|
647
|
-
});
|
|
648
|
-
register({
|
|
649
|
-
name: 'convert_amount',
|
|
650
|
-
description: 'Convert between dollars and milliunits with integer arithmetic for precision',
|
|
651
|
-
inputSchema: ConvertAmountSchema,
|
|
652
|
-
outputSchema: ConvertAmountOutputSchema,
|
|
653
|
-
handler: async ({ input }) => handleConvertAmount(input),
|
|
654
|
-
metadata: {
|
|
655
|
-
annotations: {
|
|
656
|
-
...ToolAnnotationPresets.UTILITY_LOCAL,
|
|
657
|
-
title: 'YNAB: Convert Amount',
|
|
658
|
-
},
|
|
659
|
-
},
|
|
660
|
-
});
|
|
661
311
|
register({
|
|
662
312
|
name: 'diagnostic_info',
|
|
663
313
|
description: 'Get comprehensive diagnostic information about the MCP server',
|
|
664
314
|
inputSchema: diagnosticInfoSchema,
|
|
665
|
-
outputSchema: DiagnosticInfoOutputSchema,
|
|
666
315
|
handler: async ({ input }) => {
|
|
667
316
|
return this.diagnosticManager.collectDiagnostics(input);
|
|
668
317
|
},
|
|
@@ -677,7 +326,6 @@ export class YNABMCPServer {
|
|
|
677
326
|
name: 'clear_cache',
|
|
678
327
|
description: 'Clear the in-memory cache (safe, no YNAB data is modified)',
|
|
679
328
|
inputSchema: emptyObjectSchema,
|
|
680
|
-
outputSchema: ClearCacheOutputSchema,
|
|
681
329
|
handler: async () => {
|
|
682
330
|
cacheManager.clear();
|
|
683
331
|
return {
|
|
@@ -695,7 +343,6 @@ export class YNABMCPServer {
|
|
|
695
343
|
name: 'set_output_format',
|
|
696
344
|
description: 'Configure default JSON output formatting (minify or pretty spaces)',
|
|
697
345
|
inputSchema: setOutputFormatSchema,
|
|
698
|
-
outputSchema: SetOutputFormatOutputSchema,
|
|
699
346
|
handler: async ({ input }) => {
|
|
700
347
|
const options = {};
|
|
701
348
|
if (typeof input.default_minify === 'boolean') {
|
package/dist/server/config.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import 'dotenv/config';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
declare const envSchema: z.ZodObject<{
|
|
4
4
|
YNAB_ACCESS_TOKEN: z.ZodString;
|
|
5
|
+
YNAB_DEFAULT_BUDGET_ID: z.ZodOptional<z.ZodString>;
|
|
5
6
|
MCP_PORT: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
6
7
|
LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
|
|
7
8
|
error: "error";
|
|
@@ -17,6 +18,7 @@ export declare function loadConfig(env?: NodeJS.ProcessEnv): AppConfig;
|
|
|
17
18
|
export declare const config: {
|
|
18
19
|
YNAB_ACCESS_TOKEN: string;
|
|
19
20
|
LOG_LEVEL: "error" | "warn" | "info" | "debug" | "trace" | "fatal";
|
|
21
|
+
YNAB_DEFAULT_BUDGET_ID?: string | undefined;
|
|
20
22
|
MCP_PORT?: number | undefined;
|
|
21
23
|
};
|
|
22
24
|
export {};
|
package/dist/server/config.js
CHANGED
|
@@ -4,6 +4,7 @@ import { fromZodError } from 'zod-validation-error';
|
|
|
4
4
|
import { ValidationError } from '../utils/errors.js';
|
|
5
5
|
const envSchema = z.object({
|
|
6
6
|
YNAB_ACCESS_TOKEN: z.string().trim().min(1, 'YNAB_ACCESS_TOKEN must be a non-empty string'),
|
|
7
|
+
YNAB_DEFAULT_BUDGET_ID: z.string().uuid('YNAB_DEFAULT_BUDGET_ID must be a valid UUID').optional(),
|
|
7
8
|
MCP_PORT: z.coerce.number().int().positive().optional(),
|
|
8
9
|
LOG_LEVEL: z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal']).default('info'),
|
|
9
10
|
});
|
|
@@ -4,6 +4,7 @@ import { z } from 'zod/v4';
|
|
|
4
4
|
import type { DeltaFetcher } from './deltaFetcher.js';
|
|
5
5
|
import type { DeltaCache } from '../server/deltaCache.js';
|
|
6
6
|
import type { ServerKnowledgeStore } from '../server/serverKnowledgeStore.js';
|
|
7
|
+
import type { ToolFactory } from '../types/toolRegistration.js';
|
|
7
8
|
export declare const ListAccountsSchema: z.ZodObject<{
|
|
8
9
|
budget_id: z.ZodString;
|
|
9
10
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
@@ -35,3 +36,4 @@ export declare function handleListAccounts(ynabAPI: ynab.API, params: ListAccoun
|
|
|
35
36
|
export declare function handleGetAccount(ynabAPI: ynab.API, params: GetAccountParams): Promise<CallToolResult>;
|
|
36
37
|
export declare function handleCreateAccount(ynabAPI: ynab.API, deltaCache: DeltaCache, knowledgeStore: ServerKnowledgeStore, params: CreateAccountParams): Promise<CallToolResult>;
|
|
37
38
|
export declare function handleCreateAccount(ynabAPI: ynab.API, params: CreateAccountParams): Promise<CallToolResult>;
|
|
39
|
+
export declare const registerAccountTools: ToolFactory;
|
|
@@ -5,6 +5,8 @@ import { milliunitsToAmount } from '../utils/amountUtils.js';
|
|
|
5
5
|
import { cacheManager, CACHE_TTLS, CacheManager } from '../server/cacheManager.js';
|
|
6
6
|
import { CacheKeys } from '../server/cacheKeys.js';
|
|
7
7
|
import { resolveDeltaFetcherArgs, resolveDeltaWriteArgs } from './deltaSupport.js';
|
|
8
|
+
import { createAdapters, createBudgetResolver } from './adapters.js';
|
|
9
|
+
import { ToolAnnotationPresets } from './toolCategories.js';
|
|
8
10
|
export const ListAccountsSchema = z
|
|
9
11
|
.object({
|
|
10
12
|
budget_id: z.string().min(1, 'Budget ID is required'),
|
|
@@ -174,3 +176,46 @@ export async function handleCreateAccount(ynabAPI, deltaCacheOrParams, knowledge
|
|
|
174
176
|
};
|
|
175
177
|
}, 'ynab:create_account', 'creating account');
|
|
176
178
|
}
|
|
179
|
+
export const registerAccountTools = (registry, context) => {
|
|
180
|
+
const { adapt, adaptWithDelta, adaptWrite } = createAdapters(context);
|
|
181
|
+
const budgetResolver = createBudgetResolver(context);
|
|
182
|
+
registry.register({
|
|
183
|
+
name: 'list_accounts',
|
|
184
|
+
description: 'List all accounts for a specific budget',
|
|
185
|
+
inputSchema: ListAccountsSchema,
|
|
186
|
+
handler: adaptWithDelta(handleListAccounts),
|
|
187
|
+
defaultArgumentResolver: budgetResolver(),
|
|
188
|
+
metadata: {
|
|
189
|
+
annotations: {
|
|
190
|
+
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
191
|
+
title: 'YNAB: List Accounts',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
registry.register({
|
|
196
|
+
name: 'get_account',
|
|
197
|
+
description: 'Get detailed information for a specific account',
|
|
198
|
+
inputSchema: GetAccountSchema,
|
|
199
|
+
handler: adapt(handleGetAccount),
|
|
200
|
+
defaultArgumentResolver: budgetResolver(),
|
|
201
|
+
metadata: {
|
|
202
|
+
annotations: {
|
|
203
|
+
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
204
|
+
title: 'YNAB: Get Account Details',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
registry.register({
|
|
209
|
+
name: 'create_account',
|
|
210
|
+
description: 'Create a new account in the specified budget',
|
|
211
|
+
inputSchema: CreateAccountSchema,
|
|
212
|
+
handler: adaptWrite(handleCreateAccount),
|
|
213
|
+
defaultArgumentResolver: budgetResolver(),
|
|
214
|
+
metadata: {
|
|
215
|
+
annotations: {
|
|
216
|
+
...ToolAnnotationPresets.WRITE_EXTERNAL_CREATE,
|
|
217
|
+
title: 'YNAB: Create Account',
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import type { ToolExecutionPayload, DefaultArgumentResolver } from '../server/toolRegistry.js';
|
|
3
|
+
import type { ToolContext, Handler, DeltaHandler, WriteHandler, NoInputHandler } from '../types/toolRegistration.js';
|
|
4
|
+
export declare function createAdapters(context: ToolContext): {
|
|
5
|
+
adapt: <TInput extends Record<string, unknown>>(handler: Handler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
6
|
+
adaptNoInput: (handler: NoInputHandler) => (_payload: ToolExecutionPayload<Record<string, unknown>>) => Promise<CallToolResult>;
|
|
7
|
+
adaptWithDelta: <TInput extends Record<string, unknown>>(handler: DeltaHandler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
8
|
+
adaptWrite: <TInput extends Record<string, unknown>>(handler: WriteHandler<TInput>) => ({ input }: ToolExecutionPayload<TInput>) => Promise<CallToolResult>;
|
|
9
|
+
};
|
|
10
|
+
export declare function createBudgetResolver(context: ToolContext): <TInput extends {
|
|
11
|
+
budget_id?: string | undefined;
|
|
12
|
+
}>() => DefaultArgumentResolver<TInput>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BudgetResolver } from '../server/budgetResolver.js';
|
|
2
|
+
import { DefaultArgumentResolutionError } from '../server/toolRegistry.js';
|
|
3
|
+
export function createAdapters(context) {
|
|
4
|
+
const { ynabAPI, deltaFetcher, deltaCache, serverKnowledgeStore } = context;
|
|
5
|
+
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
|
+
adaptWrite: (handler) => async ({ input }) => handler(ynabAPI, deltaCache, serverKnowledgeStore, input),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function createBudgetResolver(context) {
|
|
13
|
+
return () => {
|
|
14
|
+
return ({ rawArguments }) => {
|
|
15
|
+
const provided = typeof rawArguments['budget_id'] === 'string' && rawArguments['budget_id'].length > 0
|
|
16
|
+
? rawArguments['budget_id']
|
|
17
|
+
: undefined;
|
|
18
|
+
const result = BudgetResolver.resolveBudgetId(provided, context.getDefaultBudgetId());
|
|
19
|
+
if (typeof result === 'string') {
|
|
20
|
+
return { budget_id: result };
|
|
21
|
+
}
|
|
22
|
+
throw new DefaultArgumentResolutionError(result);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -2,9 +2,11 @@ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
|
2
2
|
import * as ynab from 'ynab';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
import type { DeltaFetcher } from './deltaFetcher.js';
|
|
5
|
+
import type { ToolFactory } from '../types/toolRegistration.js';
|
|
5
6
|
export declare const GetBudgetSchema: z.ZodObject<{
|
|
6
7
|
budget_id: z.ZodString;
|
|
7
8
|
}, z.core.$strict>;
|
|
8
9
|
export type GetBudgetParams = z.infer<typeof GetBudgetSchema>;
|
|
9
10
|
export declare function handleListBudgets(ynabAPI: ynab.API, deltaFetcherOrParams?: DeltaFetcher | Record<string, unknown>, maybeParams?: Record<string, unknown>): Promise<CallToolResult>;
|
|
10
11
|
export declare function handleGetBudget(ynabAPI: ynab.API, params: GetBudgetParams): Promise<CallToolResult>;
|
|
12
|
+
export declare const registerBudgetTools: ToolFactory;
|
|
@@ -2,6 +2,9 @@ import { z } from 'zod/v4';
|
|
|
2
2
|
import { withToolErrorHandling } from '../types/index.js';
|
|
3
3
|
import { responseFormatter } from '../server/responseFormatter.js';
|
|
4
4
|
import { resolveDeltaFetcherArgs } from './deltaSupport.js';
|
|
5
|
+
import { createAdapters } from './adapters.js';
|
|
6
|
+
import { ToolAnnotationPresets } from './toolCategories.js';
|
|
7
|
+
import { emptyObjectSchema } from './schemas/common.js';
|
|
5
8
|
export const GetBudgetSchema = z
|
|
6
9
|
.object({
|
|
7
10
|
budget_id: z.string().min(1, 'Budget ID is required'),
|
|
@@ -66,3 +69,30 @@ export async function handleGetBudget(ynabAPI, params) {
|
|
|
66
69
|
};
|
|
67
70
|
}, 'ynab:get_budget', 'getting budget details');
|
|
68
71
|
}
|
|
72
|
+
export const registerBudgetTools = (registry, context) => {
|
|
73
|
+
const { adapt, adaptWithDelta } = createAdapters(context);
|
|
74
|
+
registry.register({
|
|
75
|
+
name: 'list_budgets',
|
|
76
|
+
description: "List all budgets associated with the user's account",
|
|
77
|
+
inputSchema: emptyObjectSchema,
|
|
78
|
+
handler: adaptWithDelta(handleListBudgets),
|
|
79
|
+
metadata: {
|
|
80
|
+
annotations: {
|
|
81
|
+
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
82
|
+
title: 'YNAB: List Budgets',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
registry.register({
|
|
87
|
+
name: 'get_budget',
|
|
88
|
+
description: 'Get detailed information for a specific budget',
|
|
89
|
+
inputSchema: GetBudgetSchema,
|
|
90
|
+
handler: adapt(handleGetBudget),
|
|
91
|
+
metadata: {
|
|
92
|
+
annotations: {
|
|
93
|
+
...ToolAnnotationPresets.READ_ONLY_EXTERNAL,
|
|
94
|
+
title: 'YNAB: Get Budget Details',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
};
|