@dizzlkheinz/ynab-mcpb 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/fix-types.sh DELETED
@@ -1,17 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Fix index.ts errors
4
-
5
- # Fix currency_code -> iso_code
6
- sed -i 's/currency_format?.currency_code/currency_format?.iso_code/g' src/tools/reconciliation/index.ts
7
-
8
- # Fix exact optional property types in index.ts
9
- # The csvFormat can be undefined, so we need to handle that properly
10
-
11
- # Fix coerceString calls to handle null properly
12
- sed -i "s/coerceString(format.thousands_separator ?? null, null)/coerceString(format.thousands_separator ?? null, '')/g" src/tools/reconciliation/index.ts
13
- sed -i "s/coerceString(format.date_column ?? null, null)/coerceString(format.date_column ?? null, '')/g" src/tools/reconciliation/index.ts
14
- sed -i "s/coerceString(format.amount_column ?? null, null)/coerceString(format.amount_column ?? null, '')/g" src/tools/reconciliation/index.ts
15
- sed -i "s/coerceString(format.description_column ?? null, null)/coerceString(format.description_column ?? null, '')/g" src/tools/reconciliation/index.ts
16
-
17
- echo "Type fixes applied"
@@ -1,28 +0,0 @@
1
- Date,Description,Amount,Balance
2
- 2024-01-15,"GROCERY STORE PURCHASE",-45.67,1234.56
3
- 2024-01-16,"PAYCHECK DEPOSIT",2500.00,3734.56
4
- 2024-01-17,"COFFEE SHOP",-4.25,3730.31
5
- 2024-01-18,"ATM WITHDRAWAL",-60.00,3670.31
6
- 2024-01-19,"ONLINE PURCHASE - AMAZON",-23.45,3646.86
7
- 2024-01-20,"RESTAURANT DINNER",-78.90,3567.96
8
- 2024-01-22,"GAS STATION",-52.34,3515.62
9
- 2024-01-23,"PHARMACY",-12.67,3502.95
10
- 2024-01-24,"UTILITY PAYMENT",-125.00,3377.95
11
- 2024-01-25,"GROCERY STORE PURCHASE",-67.89,3310.06
12
- 2024-01-26,"MOBILE PHONE BILL",-85.00,3225.06
13
- 2024-01-29,"RESTAURANT LUNCH",-18.45,3206.61
14
- 2024-01-30,"BANK INTEREST EARNED",2.15,3208.76
15
- 2024-01-31,"MONTHLY RENT",-1200.00,2008.76
16
- 2024-02-01,"COFFEE SHOP",-4.75,2004.01
17
- 2024-02-02,"GROCERY STORE PURCHASE",-89.23,1914.78
18
- 2024-02-03,"MOVIE THEATER",-24.00,1890.78
19
- 2024-02-05,"ONLINE SUBSCRIPTION",-9.99,1880.79
20
- 2024-02-06,"RESTAURANT DINNER",-56.78,1823.01
21
- 2024-02-07,"GAS STATION",-48.90,1774.11
22
- 2024-02-08,"PHARMACY",-15.67,1758.44
23
- 2024-02-09,"GROCERY STORE PURCHASE",-34.56,1723.88
24
- 2024-02-12,"PAYCHECK DEPOSIT",2500.00,4223.88
25
- 2024-02-13,"INSURANCE PAYMENT",-150.00,4073.88
26
- 2024-02-14,"RESTAURANT VALENTINE",-95.67,3978.21
27
- 2024-02-15,"DUPLICATE AMOUNT TEST",-45.67,3932.54
28
- 2024-02-16,"PENDING TRANSACTION",-123.45,3809.09
@@ -1,7 +0,0 @@
1
- Date,Amount,Description
2
- 01/15/2025,25.50,Coffee Shop Purchase
3
- 01/16/2025,-100.00,ATM Withdrawal
4
- 01/17/2025,45.75,Grocery Store
5
- 01/18/2025,15.99,Netflix Subscription
6
- 01/19/2025,200.00,Paycheck Deposit
7
- 01/20/2025,32.45,Gas Station
@@ -1,40 +0,0 @@
1
- /**
2
- * Test the auto-detect date range functionality
3
- */
4
-
5
- import {
6
- extractDateRangeFromCSV,
7
- autoDetectCSVFormat,
8
- } from './dist/tools/compareTransactions/parser.js';
9
-
10
- const csvContent = `Date,Description,Debit,Credit,Balance
11
- 11/10/2025,DOLLARAMA # 109,10.91,,
12
- 10/15/2025,Uber Trip,30.50,,
13
- 09/22/2025,CIRCLE K # 05844 A,18.84,,`;
14
-
15
- console.log('Testing auto-detection...');
16
-
17
- try {
18
- // Test 1: Auto-detect format
19
- console.log('\n1. Auto-detecting CSV format...');
20
- const csvFormat = autoDetectCSVFormat(csvContent);
21
- console.log(' ✓ Format detected:', JSON.stringify(csvFormat, null, 2));
22
-
23
- // Test 2: Extract date range
24
- console.log('\n2. Extracting date range...');
25
- const { minDate, maxDate } = extractDateRangeFromCSV(csvContent, csvFormat);
26
- console.log(` ✓ Date range: ${minDate} to ${maxDate}`);
27
-
28
- // Test 3: Calculate buffer date
29
- console.log('\n3. Calculating YNAB fetch date with 7-day buffer...');
30
- const minDateObj = new Date(minDate);
31
- minDateObj.setDate(minDateObj.getDate() - 7);
32
- const fetchDate = minDateObj.toISOString().split('T')[0];
33
- console.log(` ✓ YNAB fetch from: ${fetchDate}`);
34
-
35
- console.log('\n✅ All tests passed!');
36
- } catch (error) {
37
- console.error('\n❌ ERROR:', error.message);
38
- console.error(error.stack);
39
- process.exit(1);
40
- }
@@ -1,152 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Test script for reconcile_account_v2 tool
4
- *
5
- * Usage:
6
- * node test-reconcile-tool.js <csv-file> <budget-id> <account-id> <statement-balance>
7
- *
8
- * Example:
9
- * node test-reconcile-tool.js test.csv last-used checking -1500.00
10
- */
11
-
12
- import { API } from 'ynab';
13
- import { handleReconcileAccountV2 } from './dist/tools/reconciliation/index.js';
14
- import { readFileSync } from 'fs';
15
-
16
- async function testReconciliation() {
17
- // Parse arguments
18
- const csvFile = process.argv[2];
19
- const budgetId = process.argv[3] || 'last-used';
20
- const accountId = process.argv[4];
21
- const statementBalance = parseFloat(process.argv[5] || '0');
22
-
23
- if (!csvFile || !accountId) {
24
- console.error(
25
- 'Usage: node test-reconcile-tool.js <csv-file> <budget-id> <account-id> <statement-balance>',
26
- );
27
- console.error('Example: node test-reconcile-tool.js test.csv last-used checking -1500.00');
28
- process.exit(1);
29
- }
30
-
31
- // Check for YNAB token
32
- const token = process.env.YNAB_ACCESS_TOKEN;
33
- if (!token) {
34
- console.error('❌ YNAB_ACCESS_TOKEN environment variable not set');
35
- process.exit(1);
36
- }
37
-
38
- // Initialize YNAB API
39
- const ynabAPI = new API(token);
40
-
41
- console.log('🔍 Testing reconcile_account_v2...\n');
42
- console.log(`CSV File: ${csvFile}`);
43
- console.log(`Budget ID: ${budgetId}`);
44
- console.log(`Account ID: ${accountId}`);
45
- console.log(`Statement Balance: $${statementBalance}`);
46
- console.log('\n---\n');
47
-
48
- try {
49
- // Read CSV content
50
- const csvContent = readFileSync(csvFile, 'utf-8');
51
-
52
- // Call the tool
53
- const result = await handleReconcileAccountV2(ynabAPI, {
54
- budget_id: budgetId,
55
- account_id: accountId,
56
- csv_data: csvContent,
57
- statement_balance: statementBalance,
58
- date_tolerance_days: 2,
59
- amount_tolerance_cents: 1,
60
- auto_match_threshold: 90,
61
- suggestion_threshold: 60,
62
- });
63
-
64
- // Parse and display results
65
- const analysis = JSON.parse(result.content[0].text);
66
-
67
- console.log('✅ Analysis Complete!\n');
68
- console.log('📊 Summary:');
69
- console.log(` Bank Transactions: ${analysis.summary.bank_transactions_count}`);
70
- console.log(` YNAB Transactions: ${analysis.summary.ynab_transactions_count}`);
71
- console.log(` Auto-Matched: ${analysis.summary.auto_matched} (≥90% confidence)`);
72
- console.log(` Suggested Matches: ${analysis.summary.suggested_matches} (60-89% confidence)`);
73
- console.log(` Unmatched Bank: ${analysis.summary.unmatched_bank}`);
74
- console.log(` Unmatched YNAB: ${analysis.summary.unmatched_ynab}`);
75
- console.log('\n💰 Balance:');
76
- console.log(` Current Cleared: $${analysis.balance_info.current_cleared.toFixed(2)}`);
77
- console.log(` Target Statement: $${analysis.balance_info.target_statement.toFixed(2)}`);
78
- console.log(` Discrepancy: $${analysis.balance_info.discrepancy.toFixed(2)}`);
79
- console.log(` On Track: ${analysis.balance_info.on_track ? '✅' : '❌'}`);
80
-
81
- if (analysis.auto_matches.length > 0) {
82
- console.log('\n✨ Auto-Matched Transactions:');
83
- analysis.auto_matches.slice(0, 5).forEach((match, i) => {
84
- console.log(
85
- ` ${i + 1}. ${match.bank_transaction.payee} - $${match.bank_transaction.amount.toFixed(2)}`,
86
- );
87
- console.log(` → Matched to YNAB: ${match.ynab_transaction.payee_name}`);
88
- console.log(` Confidence: ${match.confidence_score}%`);
89
- });
90
- if (analysis.auto_matches.length > 5) {
91
- console.log(` ... and ${analysis.auto_matches.length - 5} more`);
92
- }
93
- }
94
-
95
- if (analysis.suggested_matches.length > 0) {
96
- console.log('\n💡 Suggested Matches (need review):');
97
- analysis.suggested_matches.slice(0, 3).forEach((match, i) => {
98
- console.log(
99
- ` ${i + 1}. ${match.bank_transaction.payee} - $${match.bank_transaction.amount.toFixed(2)}`,
100
- );
101
- if (match.candidates && match.candidates.length > 0) {
102
- console.log(
103
- ` Top candidate: ${match.candidates[0].ynab_transaction.payee_name} (${match.candidates[0].confidence}%)`,
104
- );
105
- }
106
- });
107
- if (analysis.suggested_matches.length > 3) {
108
- console.log(` ... and ${analysis.suggested_matches.length - 3} more`);
109
- }
110
- }
111
-
112
- if (analysis.unmatched_bank.length > 0) {
113
- console.log('\n❓ Unmatched Bank Transactions (not in YNAB):');
114
- analysis.unmatched_bank.slice(0, 3).forEach((txn, i) => {
115
- console.log(` ${i + 1}. ${txn.payee} - $${txn.amount.toFixed(2)} on ${txn.date}`);
116
- });
117
- if (analysis.unmatched_bank.length > 3) {
118
- console.log(` ... and ${analysis.unmatched_bank.length - 3} more`);
119
- }
120
- }
121
-
122
- if (analysis.insights && analysis.insights.length > 0) {
123
- console.log('\n💡 Insights:');
124
- analysis.insights.forEach((insight) => {
125
- const icon =
126
- insight.severity === 'critical' ? '🔴' : insight.severity === 'warning' ? '⚠️' : 'ℹ️';
127
- console.log(` ${icon} ${insight.title}`);
128
- console.log(` ${insight.description}`);
129
- });
130
- }
131
-
132
- console.log('\n📋 Next Steps:');
133
- analysis.next_steps.forEach((step, i) => {
134
- console.log(` ${i + 1}. ${step}`);
135
- });
136
-
137
- console.log('\n✅ Test complete!');
138
- console.log('\nFull results saved to: reconcile-analysis-result.json');
139
-
140
- // Save full results
141
- require('fs').writeFileSync(
142
- 'reconcile-analysis-result.json',
143
- JSON.stringify(analysis, null, 2),
144
- );
145
- } catch (error) {
146
- console.error('❌ Error:', error.message);
147
- console.error(error);
148
- process.exit(1);
149
- }
150
- }
151
-
152
- testReconciliation();
@@ -1,89 +0,0 @@
1
- /**
2
- * Test reconciliation with merged CSV data
3
- * Run this script using the YNAB MCP server in your other context
4
- */
5
-
6
- const fs = require('fs');
7
- const path = require('path');
8
-
9
- // Read the CSV files
10
- const downloadsPath = path.join(process.env.USERPROFILE, 'Downloads');
11
- const csv1Path = path.join(downloadsPath, 'accountactivity.csv');
12
- const csv2Path = path.join(downloadsPath, 'accountactivity1.csv');
13
- const csv3Path = path.join(downloadsPath, 'accountactivity2.csv');
14
-
15
- let csv1, csv2, csv3;
16
- try {
17
- csv1 = fs.readFileSync(csv1Path, 'utf-8');
18
- csv2 = fs.readFileSync(csv2Path, 'utf-8');
19
- csv3 = fs.readFileSync(csv3Path, 'utf-8');
20
- } catch (error) {
21
- console.error('Error reading CSV files:', error.message);
22
- process.exit(1);
23
- }
24
- // Merge CSVs (skip header from second and third files)
25
- const lines1 = csv1.split('\n');
26
- const lines2 = csv2.split('\n');
27
- const lines3 = csv3.split('\n');
28
-
29
- // Get header from first file
30
- const header = lines1[0];
31
-
32
- // Get data rows (skip header from all files, skip empty lines)
33
- const data1 = lines1.slice(1).filter(line => line.trim());
34
- const data2 = lines2.slice(1).filter(line => line.trim());
35
- const data3 = lines3.slice(1).filter(line => line.trim());
36
-
37
- // Combine and deduplicate
38
- const allData = [...data1, ...data2, ...data3];
39
- const uniqueData = [...new Set(allData)];
40
-
41
- // Reconstruct CSV
42
- const mergedCsv = [header, ...uniqueData].join('\n');
43
-
44
- const BUDGET_ID = process.env.YNAB_BUDGET_ID || '00dd8b56-cca8-4a1f-a3ea-02b13df8c2ff';
45
- const ACCOUNT_ID = process.env.YNAB_ACCOUNT_ID || '083f96c0-ed01-497d-93ab-f94c5ba89509';
46
- const STATEMENT_BALANCE = parseFloat(process.env.STATEMENT_BALANCE || '-1234.91');
47
- if (isNaN(STATEMENT_BALANCE)) {
48
- console.error('Invalid STATEMENT_BALANCE value');
49
- process.exit(1);
50
- }const STATEMENT_DATE = process.env.STATEMENT_DATE || '2025-01-11';
51
-
52
- const reconciliationCall = {
53
- tool: 'reconcile_account',
54
- params: {
55
- budget_id: BUDGET_ID,
56
- account_id: ACCOUNT_ID,
57
- statement_balance: STATEMENT_BALANCE,
58
- statement_date: STATEMENT_DATE,
59
- csv_data: mergedCsv,
60
- csv_format: {
61
- date_column: 'Transaction Date',
62
- description_column: 'Description',
63
- amount_column: 'Amount',
64
- date_format: 'YYYY-MM-DD',
65
- has_header: true,
66
- delimiter: ','
67
- },
68
- dry_run: false,
69
- auto_create_transactions: true,
70
- auto_update_cleared_status: true,
71
- auto_unclear_missing: true,
72
- include_structured_data: false
73
- }
74
- }; auto_update_cleared_status: true,
75
- auto_unclear_missing: true,
76
- include_structured_data: false
77
- }
78
- };
79
- const mergedCsvPath = path.join(downloadsPath, 'accountactivity-merged.csv');
80
- try {
81
- fs.writeFileSync(mergedCsvPath, mergedCsv);
82
- console.log(`\n\nMerged CSV saved to: ${mergedCsvPath}`);
83
- } catch (error) {
84
- console.error('Error saving merged CSV:', error.message);
85
- }
86
- // Also save the merged CSV for reference
87
- const mergedCsvPath = path.join(downloadsPath, 'accountactivity-merged.csv');
88
- fs.writeFileSync(mergedCsvPath, mergedCsv);
89
- console.log(`\n\nMerged CSV saved to: ${mergedCsvPath}`);
@@ -1,8 +0,0 @@
1
- Date,Description,Amount
2
- 2025-10-23,EvoCarShare,-2.24
3
- 2025-10-22,Amazon.ca*NU6MP0D91,-23.47
4
- 2025-10-22,Amazon.ca*NU1G88CB2,-9.49
5
- 2025-10-20,OXIO.CA,-54.88
6
- 2025-10-20,PAYMENT - THANK YOU,1097.27
7
- 2025-10-20,BURGER KING # 6271,-23.09
8
- 2025-10-30,EvoCarShare,-22.22
package/test_debug.js DELETED
@@ -1,47 +0,0 @@
1
- import { handleCreateTransaction } from './dist/tools/transactionTools.js';
2
- import * as ynab from 'ynab';
3
- import { vi } from 'vitest';
4
-
5
- const mockYnabAPI = {
6
- transactions: {
7
- createTransaction: async () => ({
8
- data: {
9
- transaction: {
10
- id: 'new-transaction-123',
11
- date: '2024-01-01',
12
- amount: -50000,
13
- memo: null,
14
- cleared: 'cleared',
15
- approved: true,
16
- flag_color: 'red',
17
- account_id: 'account-456',
18
- },
19
- },
20
- }),
21
- },
22
- accounts: {
23
- getAccountById: async () => ({
24
- data: {
25
- account: {
26
- id: 'account-456',
27
- balance: 100000,
28
- cleared_balance: 95000,
29
- },
30
- },
31
- }),
32
- },
33
- };
34
-
35
- const params = {
36
- budget_id: 'budget-123',
37
- account_id: 'account-456',
38
- amount: -50000,
39
- date: '2024-01-01',
40
- };
41
-
42
- try {
43
- const result = await handleCreateTransaction(mockYnabAPI, params);
44
- console.log('Result:', JSON.stringify(result, null, 2));
45
- } catch (error) {
46
- console.error('Error:', error);
47
- }
@@ -1,75 +0,0 @@
1
- import { spawn } from 'child_process';
2
-
3
- const server = spawn('node', ['dist/index.js'], {
4
- stdio: ['pipe', 'pipe', 'inherit'],
5
- env: process.env,
6
- });
7
-
8
- // Send initialize request
9
- const initRequest = {
10
- jsonrpc: '2.0',
11
- id: 1,
12
- method: 'initialize',
13
- params: {
14
- protocolVersion: '2024-11-05',
15
- capabilities: {},
16
- clientInfo: {
17
- name: 'test-client',
18
- version: '1.0.0',
19
- },
20
- },
21
- };
22
-
23
- // Send list tools request
24
- const listToolsRequest = {
25
- jsonrpc: '2.0',
26
- id: 2,
27
- method: 'tools/list',
28
- params: {},
29
- };
30
-
31
- let buffer = '';
32
- server.stdout.on('data', (data) => {
33
- buffer += data.toString();
34
- const lines = buffer.split('\n');
35
- buffer = lines.pop() || '';
36
-
37
- for (const line of lines) {
38
- if (line.trim()) {
39
- try {
40
- const response = JSON.parse(line);
41
- console.log('Response:', JSON.stringify(response, null, 2));
42
-
43
- if (response.id === 1) {
44
- // After init, send list tools
45
- server.stdin.write(JSON.stringify(listToolsRequest) + '\n');
46
- } else if (response.id === 2) {
47
- // Got tools list
48
- if (response.result && response.result.tools) {
49
- console.log(`\n✅ Found ${response.result.tools.length} tools`);
50
- response.result.tools.forEach((tool) => {
51
- const desc = tool.description.substring(0, 60);
52
- console.log(` - ${tool.name}: ${desc}...`);
53
- });
54
- } else {
55
- console.log('\n❌ No tools found in response');
56
- }
57
- server.kill();
58
- }
59
- } catch (e) {
60
- // Ignore parse errors for non-JSON output
61
- }
62
- }
63
- }
64
- });
65
-
66
- setTimeout(() => {
67
- console.log('\n⏱️ Timeout - sending requests');
68
- server.stdin.write(JSON.stringify(initRequest) + '\n');
69
- }, 1000);
70
-
71
- setTimeout(() => {
72
- console.log('❌ Test timed out');
73
- server.kill();
74
- process.exit(1);
75
- }, 10000);
package/test_simple.mjs DELETED
@@ -1,16 +0,0 @@
1
- // Simplified test to debug the issue
2
- const mockResponse = {
3
- data: {
4
- transaction: {
5
- id: 'new-transaction-123',
6
- date: '2024-01-01',
7
- amount: -50000,
8
- account_id: 'account-456',
9
- },
10
- server_knowledge: 1,
11
- },
12
- };
13
-
14
- console.log('Mock response:', JSON.stringify(mockResponse, null, 2));
15
- console.log('Transaction:', mockResponse.data.transaction);
16
- console.log('Server knowledge:', mockResponse.data.server_knowledge);