bkper 3.5.5 → 3.6.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [Bkper REST API]: https://bkper.com/docs/#rest-api-enabling
2
2
 
3
- A **command line** utility for managing [Bkper Apps and Bots](https://bkper.com/docs/) and running the [Model Context Protocol (MCP) server](https://modelcontextprotocol.io).
3
+ A **command line** utility for managing [Bkper Apps and Bots](https://bkper.com/docs/) and running the [Model Context Protocol (MCP) server](https://modelcontextprotocol.io).
4
4
 
5
5
  The MCP server enables AI assistants and agents to interact with your Bkper books through a standardized protocol.
6
6
 
@@ -13,37 +13,45 @@ The MCP server enables AI assistants and agents to interact with your Bkper book
13
13
  ```
14
14
  npm i bkper
15
15
  ```
16
+
16
17
  or
18
+
17
19
  ```
18
20
  yarn add bkper
19
21
  ```
22
+
20
23
  or
24
+
21
25
  ```
22
26
  bun add bkper
23
27
  ```
24
28
 
25
- Optionally, you can install it globally to be able to use the ```bkper``` command line utility:
29
+ Optionally, you can install it globally to be able to use the `bkper` command line utility:
26
30
 
27
31
  ```
28
32
  npm i -g bkper
29
33
  ```
34
+
30
35
  or
36
+
31
37
  ```
32
38
  yarn global add bkper
33
39
  ```
34
40
 
35
41
  ## Commands
36
42
 
37
- - ```login``` - Logs the user in. Saves the client credentials to a ```~/.config/bkper/.bkper-credentials.json``` file.
38
- - ```logout``` - Logs out the user by deleting client credentials.
39
- - ```mcp start``` - Start the Bkper MCP (Model Context Protocol) server.
40
- - ```app -c``` - Create a new App based on ```./bkperapp.yaml``` file.
41
- - ```app -u``` - Update an existing App based on ```./bkperapp.yaml``` file.
43
+ - `login` - Logs the user in. Saves the client credentials to a `~/.config/bkper/.bkper-credentials.json` file.
44
+ - `logout` - Logs out the user by deleting client credentials.
45
+ - `mcp start` - Start the Bkper MCP (Model Context Protocol) server.
46
+ - `app -c` - Create a new App based on `./bkperapp.yaml` file.
47
+ - `app -u` - Update an existing App based on `./bkperapp.yaml` file.
42
48
 
43
49
  ### Examples
50
+
44
51
  ```
45
52
  npm bkper login
46
53
  ```
54
+
47
55
  ```
48
56
  yarn bkper login
49
57
  ```
@@ -68,6 +76,7 @@ The server runs on stdio and provides the following tools:
68
76
  #### Prerequisites
69
77
 
70
78
  Before using the MCP server:
79
+
71
80
  1. Login using `bkper login` to set up authentication
72
81
  2. Enable the [Bkper REST API]
73
82
  3. Ensure the `BKPER_API_KEY` environment variable is set.
@@ -79,6 +88,7 @@ The MCP server uses the same authentication as the CLI, reading credentials from
79
88
  ##### Claude Desktop
80
89
 
81
90
  Add to your configuration file:
91
+
82
92
  - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
83
93
  - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
84
94
 
@@ -99,6 +109,7 @@ Add to your configuration file:
99
109
  ##### Other MCP Clients
100
110
 
101
111
  For other MCP-compatible clients, configure them to run:
112
+
102
113
  ```bash
103
114
  BKPER_API_KEY=your-api-key npx bkper mcp start
104
115
  ```
@@ -108,6 +119,7 @@ The server communicates via stdio, so any MCP client that supports stdio transpo
108
119
  #### Available MCP Tools
109
120
 
110
121
  Once connected, the MCP client can:
122
+
111
123
  - List your Bkper books
112
124
  - Get account balances for any date or period
113
125
  - Search and filter transactions
@@ -115,18 +127,17 @@ Once connected, the MCP client can:
115
127
 
116
128
  For more information about the Model Context Protocol, visit [modelcontextprotocol.io](https://modelcontextprotocol.io).
117
129
 
118
-
119
-
120
130
  ## Apps and Bots
121
131
 
122
132
  ### Environment Variables
133
+
123
134
  The following environment variable is necessary in order to communicate with the [Bkper REST API]:
124
135
 
125
136
  ```
126
137
  BKPER_API_KEY=XXXX
127
138
  ```
128
139
 
129
- The ```app``` command also uses the following variables in order to perform App create/update operations:
140
+ The `app` command also uses the following variables in order to perform App create/update operations:
130
141
 
131
142
  ```
132
143
  BKPER_CLIENT_SECRET=YYYY
@@ -134,16 +145,14 @@ BKPER_USER_EMAILS="someone@gmail.com anotherone@altrostat.com"
134
145
  BKPER_DEVELOPER_EMAIL=somedeveloer@mycompany.com
135
146
  ```
136
147
 
137
- You can add a ```.env``` file at the root of your project with those variables and bkper will automatically load from it.
148
+ You can add a `.env` file at the root of your project with those variables and bkper will automatically load from it.
138
149
  Follow [these](https://bkper.com/docs/#rest-api-enabling) steps in order to configure a valid Bkper API key.
139
150
 
140
151
  > WARNING: Never upload variables to the source code repository.
141
152
 
142
-
143
- ### ```./bkperapp.yaml``` Reference
153
+ ### `./bkperapp.yaml` Reference
144
154
 
145
155
  ```yaml
146
-
147
156
  # BASIC APP CONFIGURATION
148
157
 
149
158
  # The agent id of the App or Bot. It can NOT be changed after the App or Bot is created.
@@ -158,8 +167,6 @@ logoUrl: https://static.thenounproject.com/png/2318500-200.png
158
167
  # The logo url to be used when in dark mode
159
168
  logoUrlDark: https://static.thenounproject.com/png/2318500-200.png
160
169
 
161
-
162
-
163
170
  # CONTEXT MENU CONFIGURATION
164
171
 
165
172
  # The menu production url to open in the popup window. See accepted expressions bellow.
@@ -174,20 +181,12 @@ menuText: Open My Custom App
174
181
  menuPopupWidth: 500 # width in pixels. Default to 80% of screen width.
175
182
  menuPopupHeight: 300 # height in pixels. Default to 90% of screen height.
176
183
 
177
-
178
- #ASSISTANT CONFIGURATION
179
-
180
- # The conversation url to be called by Bkper when a new conversation message is added
181
- conversationUrl: https://us-central1-bkper-tax-trigger.cloudfunctions.net/chat
182
-
183
-
184
-
185
184
  # BOT EVENTS CONFIGURATION
186
185
 
187
186
  # The webhook url to be called by Bkper when an event occurs.
188
187
  webhookUrl: https://us-central1-bkper-tax-trigger.cloudfunctions.net/events
189
188
 
190
- # The events the Bot is capable of processing by the webhook.
189
+ # The events the Bot is capable of processing by the webhook.
191
190
  # This is optional and, if not specified, no events will be processed.
192
191
  events:
193
192
  - "TRANSACTION_POSTED"
@@ -211,7 +210,6 @@ filePatterns:
211
210
  - "-*.qif"
212
211
  - "*.csv"
213
212
 
214
-
215
213
  # Schema to provide autocompletion on properties editor.
216
214
  propertiesSchema:
217
215
  book:
@@ -242,19 +240,18 @@ propertiesSchema:
242
240
  values:
243
241
  - "value2"
244
242
  - "value2"
245
-
246
243
  ```
247
244
 
248
245
  #### Accepted expressions in menuUrl property:
249
246
 
250
- - ```${book.id}``` - the current book id
251
- - ```${book.properties.xxxxx}``` - any property value from the current book
252
- - ```${transactions.query}``` - the current query being executed on transactions list
253
- - ```${transactions.ids}``` - the ids of selected transactions, splitted by comma
254
- - ```${account.id}``` - the current account being filterd
255
- - ```${account.properties.xxxxx}``` - any property value from the current account being filtered
256
- - ```${group.id}``` - the current group being filterd
257
- - ```${group.properties.xxxxx}``` - any property value from the current group being filtered
247
+ - `${book.id}` - the current book id
248
+ - `${book.properties.xxxxx}` - any property value from the current book
249
+ - `${transactions.query}` - the current query being executed on transactions list
250
+ - `${transactions.ids}` - the ids of selected transactions, splitted by comma
251
+ - `${account.id}` - the current account being filterd
252
+ - `${account.properties.xxxxx}` - any property value from the current account being filtered
253
+ - `${group.id}` - the current group being filterd
254
+ - `${group.properties.xxxxx}` - any property value from the current group being filtered
258
255
 
259
256
  #### Example:
260
257
 
@@ -264,20 +261,19 @@ propertiesSchema:
264
261
 
265
262
  #### Library
266
263
 
267
- The ```getOAuthToken``` returns a Promise that resolves to a valid OAuth token, to be used by the [```bkper-js```](https://github.com/bkper/bkper-js) library
264
+ The `getOAuthToken` returns a Promise that resolves to a valid OAuth token, to be used by the [`bkper-js`](https://github.com/bkper/bkper-js) library
268
265
 
269
266
  Example:
270
267
 
271
268
  ```javascript
272
- import { Bkper } from 'bkper-js';
273
- import { getOAuthToken } from 'bkper';
269
+ import { Bkper } from "bkper-js";
270
+ import { getOAuthToken } from "bkper";
274
271
 
275
272
  Bkper.setConfig({
276
273
  oauthTokenProvider: async () => getOAuthToken(),
277
- })
274
+ });
278
275
  ```
279
276
 
280
277
  ## Documentation
281
278
 
282
279
  - [Developer Docs](https://bkper.com/docs)
283
-
@@ -31,10 +31,10 @@ if (!fs.existsSync(storedCredentialsPath) && fs.existsSync(oldCredentialsPath))
31
31
  const oldCredentials = fs.readFileSync(oldCredentialsPath, 'utf8');
32
32
  fs.writeFileSync(storedCredentialsPath, oldCredentials, 'utf8');
33
33
  fs.rmSync(oldCredentialsPath);
34
- console.log('Migrated credentials to new location: ~/.config/bkper/');
34
+ // Credentials migrated successfully
35
35
  }
36
36
  catch (err) {
37
- console.error('Failed to migrate credentials:', err);
37
+ // Migration failed - will fall back to old behavior
38
38
  }
39
39
  }
40
40
  try {
@@ -42,7 +42,7 @@ try {
42
42
  storedCredentials = JSON.parse(credentialsJson);
43
43
  }
44
44
  catch (err) {
45
- console.log('No local credentials found.');
45
+ // Credentials will be null if not found - no need to log during module loading
46
46
  }
47
47
  export function login() {
48
48
  return __awaiter(this, void 0, void 0, function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"local-auth-service.js","sourceRoot":"","sources":["../../src/auth/local-auth-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-auth-service.js","sourceRoot":"","sources":["../../src/auth/local-auth-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Transaction Merge Operation - Domain Logic
3
+ *
4
+ * Pure business logic for merging two transactions into one.
5
+ * This class contains no dependencies on MCP, HTTP, or other infrastructure concerns.
6
+ * It operates on Transaction domain objects from bkper-js.
7
+ */
8
+ import { Transaction, Book } from 'bkper-js';
9
+ import { MergedTransactionData } from './merge-types.js';
10
+ /**
11
+ * Represents the result of a transaction merge operation
12
+ *
13
+ * Determines which transaction to keep (edit) vs discard (revert),
14
+ * then intelligently merges data from both transactions.
15
+ */
16
+ export declare class TransactionMergeOperation {
17
+ private book;
18
+ editTransaction: Transaction;
19
+ revertTransaction: Transaction;
20
+ mergedData: MergedTransactionData;
21
+ record: string | null;
22
+ private static readonly WORD_SPLITTER;
23
+ constructor(book: Book, transaction1: Transaction, transaction2: Transaction);
24
+ /**
25
+ * Merges data from both transactions into a single transaction data object
26
+ * @returns Merged transaction data
27
+ */
28
+ private merge;
29
+ /**
30
+ * Merges two descriptions intelligently, avoiding duplicate words
31
+ * @param desc1 First description (from edit transaction)
32
+ * @param desc2 Second description (from revert transaction)
33
+ * @returns Merged description with unique words
34
+ */
35
+ private mergeDescription;
36
+ /**
37
+ * Trims and normalizes whitespace in text
38
+ * @param text Text to trim
39
+ * @returns Trimmed text with normalized whitespace
40
+ */
41
+ private trim;
42
+ /**
43
+ * Apply the merged data to the edit transaction
44
+ * This mutates the edit transaction object with the merged data
45
+ */
46
+ applyMergedData(): void;
47
+ }
48
+ //# sourceMappingURL=merge-operation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-operation.d.ts","sourceRoot":"","sources":["../../../../src/mcp/domain/transaction/merge-operation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;;;;;GAKG;AACH,qBAAa,yBAAyB;IAS9B,OAAO,CAAC,IAAI;IART,eAAe,EAAE,WAAW,CAAC;IAC7B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,UAAU,EAAE,qBAAqB,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAa;gBAGtC,IAAI,EAAE,IAAI,EAClB,YAAY,EAAE,WAAW,EACzB,YAAY,EAAE,WAAW;IA8B7B;;;OAGG;IACH,OAAO,CAAC,KAAK;IAkFb;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAIZ;;;OAGG;IACH,eAAe,IAAI,IAAI;CAsD1B"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Transaction Merge Operation - Domain Logic
3
+ *
4
+ * Pure business logic for merging two transactions into one.
5
+ * This class contains no dependencies on MCP, HTTP, or other infrastructure concerns.
6
+ * It operates on Transaction domain objects from bkper-js.
7
+ */
8
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
9
+ /**
10
+ * Represents the result of a transaction merge operation
11
+ *
12
+ * Determines which transaction to keep (edit) vs discard (revert),
13
+ * then intelligently merges data from both transactions.
14
+ */
15
+ export class TransactionMergeOperation {
16
+ constructor(book, transaction1, transaction2) {
17
+ var _a, _b;
18
+ this.book = book;
19
+ this.record = null;
20
+ // Determine which transaction to edit vs revert based on priority rules
21
+ const tx1IsPosted = (_a = transaction1.isPosted()) !== null && _a !== void 0 ? _a : false;
22
+ const tx2IsPosted = (_b = transaction2.isPosted()) !== null && _b !== void 0 ? _b : false;
23
+ // Rule 1: Prefer posted transactions over drafts
24
+ if (!tx1IsPosted && tx2IsPosted) {
25
+ this.revertTransaction = transaction1;
26
+ this.editTransaction = transaction2;
27
+ }
28
+ else if (tx1IsPosted && !tx2IsPosted) {
29
+ this.revertTransaction = transaction2;
30
+ this.editTransaction = transaction1;
31
+ }
32
+ else {
33
+ // Rule 2: If both same status, prefer newer transaction (higher createdAt)
34
+ const tx1Created = transaction1.getCreatedAt().getTime();
35
+ const tx2Created = transaction2.getCreatedAt().getTime();
36
+ if (tx1Created < tx2Created) {
37
+ this.revertTransaction = transaction1;
38
+ this.editTransaction = transaction2;
39
+ }
40
+ else {
41
+ this.revertTransaction = transaction2;
42
+ this.editTransaction = transaction1;
43
+ }
44
+ }
45
+ this.mergedData = this.merge();
46
+ }
47
+ /**
48
+ * Merges data from both transactions into a single transaction data object
49
+ * @returns Merged transaction data
50
+ */
51
+ merge() {
52
+ // Start with edit transaction's JSON data as base
53
+ const merged = Object.assign({}, this.editTransaction.json());
54
+ // Merge description using Transaction wrapper
55
+ const editDescription = this.editTransaction.getDescription();
56
+ const revertDescription = this.revertTransaction.getDescription();
57
+ merged.description = this.mergeDescription(editDescription || null, revertDescription || null);
58
+ // Merge files using Transaction wrapper
59
+ const editFiles = this.editTransaction.getFiles() || [];
60
+ const revertFiles = this.revertTransaction.getFiles() || [];
61
+ const mergedFiles = [
62
+ ...editFiles.map(f => f.json()),
63
+ ...revertFiles.map(f => f.json())
64
+ ];
65
+ merged.files = mergedFiles;
66
+ // Keep "attachments" for backward compatibility with test fixtures
67
+ merged.attachments = mergedFiles;
68
+ // Merge remote IDs using Transaction wrapper
69
+ const editRemoteIds = this.editTransaction.getRemoteIds();
70
+ const revertRemoteIds = this.revertTransaction.getRemoteIds();
71
+ merged.remoteIds = [...new Set([...editRemoteIds, ...revertRemoteIds])];
72
+ // Merge URLs using Transaction wrapper
73
+ const editUrls = this.editTransaction.getUrls();
74
+ const revertUrls = this.revertTransaction.getUrls();
75
+ merged.urls = [...new Set([...editUrls, ...revertUrls])];
76
+ // Merge properties using Transaction wrapper (revert overwrites edit)
77
+ const editProperties = this.editTransaction.getProperties();
78
+ const revertProperties = this.revertTransaction.getProperties();
79
+ merged.properties = Object.assign(Object.assign({}, editProperties), revertProperties);
80
+ // Backfill credit account - get from revert if edit doesn't have it
81
+ const editData = this.editTransaction.json();
82
+ const revertData = this.revertTransaction.json();
83
+ if (!editData.creditAccount && !editData.creditAccountId) {
84
+ if (revertData.creditAccount)
85
+ merged.creditAccount = revertData.creditAccount;
86
+ const revertCompat = revertData;
87
+ if (revertCompat.creditAccountId)
88
+ merged.creditAccountId = revertCompat.creditAccountId;
89
+ }
90
+ // Backfill debit account - get from revert if edit doesn't have it
91
+ if (!editData.debitAccount && !editData.debitAccountId) {
92
+ if (revertData.debitAccount)
93
+ merged.debitAccount = revertData.debitAccount;
94
+ const revertCompat = revertData;
95
+ if (revertCompat.debitAccountId)
96
+ merged.debitAccountId = revertCompat.debitAccountId;
97
+ }
98
+ // Handle amount validation and merging using Transaction wrapper
99
+ const editAmount = this.editTransaction.getAmount();
100
+ const revertAmount = this.revertTransaction.getAmount();
101
+ if (editAmount && revertAmount) {
102
+ // Both have amounts - validate they are equal
103
+ if (editAmount.cmp(revertAmount) !== 0) {
104
+ // Amounts differ - throw error for manual reconciliation
105
+ throw new McpError(ErrorCode.InvalidParams, `Cannot merge transactions with different amounts: ${editAmount.toString()} vs ${revertAmount.toString()}. ` +
106
+ `Please reconcile amounts manually before merging.`);
107
+ }
108
+ // Amounts are equal - keep edit's amount (no change needed)
109
+ }
110
+ else if (!editAmount && revertAmount) {
111
+ // Edit has no amount, use revert's amount
112
+ merged.amount = revertAmount.toString();
113
+ }
114
+ // If edit has amount and revert doesn't, keep edit's amount (already in merged)
115
+ return merged;
116
+ }
117
+ /**
118
+ * Merges two descriptions intelligently, avoiding duplicate words
119
+ * @param desc1 First description (from edit transaction)
120
+ * @param desc2 Second description (from revert transaction)
121
+ * @returns Merged description with unique words
122
+ */
123
+ mergeDescription(desc1, desc2) {
124
+ if (!desc1)
125
+ return desc2 || '';
126
+ if (!desc2)
127
+ return desc1;
128
+ const desc1Lower = desc1.toLowerCase();
129
+ const words = desc2.split(TransactionMergeOperation.WORD_SPLITTER)
130
+ .filter(word => word.length > 0);
131
+ const uniqueWords = words.filter(word => !desc1Lower.includes(word.toLowerCase()));
132
+ return this.trim(desc1 + ' ' + uniqueWords.join(' '));
133
+ }
134
+ /**
135
+ * Trims and normalizes whitespace in text
136
+ * @param text Text to trim
137
+ * @returns Trimmed text with normalized whitespace
138
+ */
139
+ trim(text) {
140
+ return text.trim().replace(/\s+/g, ' ');
141
+ }
142
+ /**
143
+ * Apply the merged data to the edit transaction
144
+ * This mutates the edit transaction object with the merged data
145
+ */
146
+ applyMergedData() {
147
+ var _a;
148
+ const edit = this.editTransaction;
149
+ const merged = this.mergedData;
150
+ // Set description (ensure it's a string)
151
+ if (merged.description !== undefined) {
152
+ edit.setDescription(merged.description);
153
+ }
154
+ // Set properties
155
+ if (merged.properties) {
156
+ edit.setProperties(merged.properties);
157
+ }
158
+ // Set URLs
159
+ if (merged.urls && merged.urls.length > 0) {
160
+ edit.setUrls(merged.urls);
161
+ }
162
+ // Set amount if changed
163
+ if (merged.amount) {
164
+ edit.setAmount(merged.amount);
165
+ }
166
+ // Set credit account if changed
167
+ if (merged.creditAccount) {
168
+ edit.setCreditAccount(merged.creditAccount);
169
+ }
170
+ // Set debit account if changed
171
+ if (merged.debitAccount) {
172
+ edit.setDebitAccount(merged.debitAccount);
173
+ }
174
+ // Add remote IDs
175
+ const currentRemoteIds = edit.getRemoteIds();
176
+ if (merged.remoteIds) {
177
+ merged.remoteIds.forEach((remoteId) => {
178
+ if (!currentRemoteIds.includes(remoteId)) {
179
+ edit.addRemoteId(remoteId);
180
+ }
181
+ });
182
+ }
183
+ // Add files
184
+ if (merged.files && merged.files.length > (((_a = this.editTransaction.getFiles()) === null || _a === void 0 ? void 0 : _a.length) || 0)) {
185
+ const currentFiles = this.editTransaction.getFiles() || [];
186
+ const newFiles = merged.files.slice(currentFiles.length);
187
+ newFiles.forEach((file) => {
188
+ // addFile expects File class but accepts raw bkper.File in practice
189
+ edit.addFile(file);
190
+ });
191
+ }
192
+ }
193
+ }
194
+ TransactionMergeOperation.WORD_SPLITTER = /[ \-_]+/;
195
+ //# sourceMappingURL=merge-operation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-operation.js","sourceRoot":"","sources":["../../../../src/mcp/domain/transaction/merge-operation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Domain types for transaction merge operations
3
+ *
4
+ * These types represent the core business domain for merging transactions,
5
+ * independent of any specific API or protocol (MCP, REST, etc.)
6
+ */
7
+ /**
8
+ * Merged transaction data that extends the base bkper.Transaction type
9
+ * with compatibility fields for legacy systems and test fixtures
10
+ */
11
+ export interface MergedTransactionData extends bkper.Transaction {
12
+ /**
13
+ * Compatibility field: alias for 'files' used in test fixtures
14
+ */
15
+ attachments?: bkper.File[];
16
+ /**
17
+ * Compatibility field: ID-only version of creditAccount for legacy systems
18
+ */
19
+ creditAccountId?: string;
20
+ /**
21
+ * Compatibility field: ID-only version of debitAccount for legacy systems
22
+ */
23
+ debitAccountId?: string;
24
+ }
25
+ //# sourceMappingURL=merge-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-types.d.ts","sourceRoot":"","sources":["../../../../src/mcp/domain/transaction/merge-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,KAAK,CAAC,WAAW;IAC5D;;OAEG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Domain types for transaction merge operations
3
+ *
4
+ * These types represent the core business domain for merging transactions,
5
+ * independent of any specific API or protocol (MCP, REST, etc.)
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=merge-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-types.js","sourceRoot":"","sources":["../../../../src/mcp/domain/transaction/merge-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AAOA,OAAO,EAEL,cAAc,EAGd,eAAe,EAEhB,MAAM,oCAAoC,CAAC;AAO5C,cAAM,cAAc;IAClB,OAAO,CAAC,MAAM,CAAS;;IAmBvB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,kBAAkB;IAWpB,GAAG;IAOH,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAczC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAc9F;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AAOA,OAAO,EAEL,cAAc,EAGd,eAAe,EAEhB,MAAM,oCAAoC,CAAC;AAS5C,cAAM,cAAc;IAClB,OAAO,CAAC,MAAM,CAAS;;IAmBvB,OAAO,CAAC,iBAAiB;IAgEzB,OAAO,CAAC,kBAAkB;IAqBpB,GAAG;IAYH,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAczC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAc9F;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
package/lib/mcp/server.js CHANGED
@@ -17,6 +17,8 @@ import { handleGetBook, getBookToolDefinition } from './tools/get_book.js';
17
17
  import { handleGetBalances, getBalancesToolDefinition } from './tools/get_balances.js';
18
18
  import { handleListTransactions, listTransactionsToolDefinition } from './tools/list_transactions.js';
19
19
  import { handleListBooks, listBooksToolDefinition } from './tools/list_books.js';
20
+ import { handleCreateTransactions, createTransactionsToolDefinition } from './tools/create_transactions.js';
21
+ import { handleMergeTransactions, mergeTransactionsToolDefinition } from './tools/merge_transactions.js';
20
22
  class BkperMcpServer {
21
23
  constructor() {
22
24
  this.server = new Server({
@@ -38,27 +40,63 @@ class BkperMcpServer {
38
40
  getBookToolDefinition,
39
41
  getBalancesToolDefinition,
40
42
  listTransactionsToolDefinition,
43
+ createTransactionsToolDefinition,
44
+ mergeTransactionsToolDefinition,
41
45
  ],
42
46
  };
43
47
  }));
44
48
  this.server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(this, void 0, void 0, function* () {
45
- switch (request.params.name) {
46
- case 'list_books':
47
- return yield handleListBooks(request.params.arguments);
48
- case 'get_book':
49
- return yield handleGetBook(request.params.arguments);
50
- case 'get_balances':
51
- return yield handleGetBalances(request.params.arguments);
52
- case 'list_transactions':
53
- return yield handleListTransactions(request.params.arguments);
54
- default:
55
- throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
49
+ const toolName = request.params.name;
50
+ const toolArgs = request.params.arguments;
51
+ let result;
52
+ try {
53
+ switch (toolName) {
54
+ case 'list_books':
55
+ result = yield handleListBooks(toolArgs);
56
+ break;
57
+ case 'get_book':
58
+ result = yield handleGetBook(toolArgs);
59
+ break;
60
+ case 'get_balances':
61
+ result = yield handleGetBalances(toolArgs);
62
+ break;
63
+ case 'list_transactions':
64
+ result = yield handleListTransactions(toolArgs);
65
+ break;
66
+ case 'create_transactions':
67
+ result = yield handleCreateTransactions(toolArgs);
68
+ break;
69
+ case 'merge_transactions':
70
+ result = yield handleMergeTransactions(toolArgs);
71
+ break;
72
+ default:
73
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${toolName}`);
74
+ }
75
+ return result;
76
+ }
77
+ catch (error) {
78
+ // Only log actual errors, not debug info
79
+ if (!(error instanceof McpError)) {
80
+ // Convert unexpected errors to MCP errors
81
+ throw new McpError(ErrorCode.InternalError, `Tool ${toolName} failed: ${error instanceof Error ? error.message : String(error)}`);
82
+ }
83
+ throw error;
56
84
  }
57
85
  }));
58
86
  }
59
87
  setupErrorHandling() {
60
88
  this.server.onerror = (error) => {
61
- console.error('[MCP Error]', error);
89
+ // Log critical server errors to a file or syslog in production
90
+ // Avoid console output during MCP stdio mode as it contaminates the stream
91
+ if (process.env.NODE_ENV !== 'production') {
92
+ // In development, log to stderr only if not in MCP mode
93
+ const isStdioMode = process.argv.includes('mcp') && process.argv.includes('start');
94
+ if (!isStdioMode) {
95
+ console.error('[MCP Server Error]:', error instanceof Error ? error.message : String(error));
96
+ }
97
+ }
98
+ // TODO: In production, implement proper logging to file/syslog
99
+ // Example: logger.error('MCP Server Error', { error: error.message, stack: error.stack });
62
100
  };
63
101
  process.on('SIGINT', () => __awaiter(this, void 0, void 0, function* () {
64
102
  yield this.server.close();
@@ -67,9 +105,15 @@ class BkperMcpServer {
67
105
  }
68
106
  run() {
69
107
  return __awaiter(this, void 0, void 0, function* () {
70
- const transport = new StdioServerTransport();
71
- yield this.server.connect(transport);
72
- console.error('Bkper MCP server running on stdio');
108
+ try {
109
+ const transport = new StdioServerTransport();
110
+ yield this.server.connect(transport);
111
+ // Server is now ready and listening on stdio
112
+ }
113
+ catch (error) {
114
+ // Do not log startup errors as they contaminate stdio stream
115
+ throw error;
116
+ }
73
117
  });
74
118
  }
75
119
  // Test helper methods for accessing MCP handlers directly
@@ -109,6 +153,9 @@ export { BkperMcpServer };
109
153
  // Only run the server if this file is executed directly
110
154
  if (import.meta.url === `file://${process.argv[1]}`) {
111
155
  const server = new BkperMcpServer();
112
- server.run().catch(console.error);
156
+ server.run().catch(() => {
157
+ // Exit silently on error to avoid contaminating stdio stream
158
+ process.exit(1);
159
+ });
113
160
  }
114
161
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ interface TransactionInput {
3
+ date: string;
4
+ amount: number;
5
+ from_account?: string;
6
+ to_account?: string;
7
+ description: string;
8
+ }
9
+ interface CreateTransactionsParams {
10
+ bookId: string;
11
+ transactions: TransactionInput[];
12
+ }
13
+ export declare function handleCreateTransactions(params: CreateTransactionsParams): Promise<CallToolResult>;
14
+ export declare const createTransactionsToolDefinition: {
15
+ name: string;
16
+ description: string;
17
+ inputSchema: {
18
+ type: string;
19
+ properties: {
20
+ bookId: {
21
+ type: string;
22
+ description: string;
23
+ };
24
+ transactions: {
25
+ type: string;
26
+ items: {
27
+ type: string;
28
+ properties: {
29
+ date: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ amount: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ from_account: {
38
+ type: string;
39
+ description: string;
40
+ };
41
+ to_account: {
42
+ type: string;
43
+ description: string;
44
+ };
45
+ description: {
46
+ type: string;
47
+ description: string;
48
+ };
49
+ };
50
+ required: string[];
51
+ };
52
+ description: string;
53
+ };
54
+ };
55
+ required: string[];
56
+ };
57
+ };
58
+ export {};
59
+ //# sourceMappingURL=create_transactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_transactions.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/create_transactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,oCAAoC,CAAC;AAIzF,UAAU,gBAAgB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,wBAAwB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAMD,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAiJxG;AAED,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2C5C,CAAC"}
@@ -0,0 +1,163 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
22
+ import { getBkperInstance } from '../bkper-factory.js';
23
+ import { Transaction } from 'bkper-js';
24
+ export function handleCreateTransactions(params) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ try {
27
+ // Debug logging removed to prevent stdio contamination
28
+ // Validate required parameters
29
+ if (!params.bookId) {
30
+ throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: bookId');
31
+ }
32
+ if (!params.transactions) {
33
+ throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: transactions');
34
+ }
35
+ if (!Array.isArray(params.transactions)) {
36
+ throw new McpError(ErrorCode.InvalidParams, 'Parameter transactions must be an array');
37
+ }
38
+ // Handle empty array case
39
+ if (params.transactions.length === 0) {
40
+ return {
41
+ content: [
42
+ {
43
+ type: 'text',
44
+ text: JSON.stringify({ transactions: [] }, null, 2),
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ // Validate each transaction
50
+ params.transactions.forEach((tx, index) => {
51
+ if (!tx.date || typeof tx.date !== 'string' || tx.date.trim() === '') {
52
+ throw new McpError(ErrorCode.InvalidParams, `Transaction at index ${index}: Missing or empty required field 'date'`);
53
+ }
54
+ if (tx.amount === undefined || tx.amount === null || typeof tx.amount !== 'number') {
55
+ throw new McpError(ErrorCode.InvalidParams, `Transaction at index ${index}: Missing or invalid required field 'amount'`);
56
+ }
57
+ if (!tx.description || typeof tx.description !== 'string' || tx.description.trim() === '') {
58
+ throw new McpError(ErrorCode.InvalidParams, `Transaction at index ${index}: Missing or empty required field 'description'`);
59
+ }
60
+ });
61
+ // Get configured Bkper instance
62
+ const bkperInstance = getBkperInstance();
63
+ // Get the book
64
+ const book = yield bkperInstance.getBook(params.bookId);
65
+ if (!book) {
66
+ throw new McpError(ErrorCode.InvalidParams, `Book not found: ${params.bookId}`);
67
+ }
68
+ // Create Transaction objects with description built from structured data
69
+ const bkperTransactions = params.transactions.map((tx) => {
70
+ const transaction = new Transaction(book);
71
+ // Build description with optional accounts
72
+ const parts = [];
73
+ if (tx.from_account && tx.from_account.trim()) {
74
+ parts.push(tx.from_account.trim());
75
+ }
76
+ if (tx.to_account && tx.to_account.trim()) {
77
+ parts.push(tx.to_account.trim());
78
+ }
79
+ parts.push(tx.description);
80
+ const fullDescription = parts.join(' ');
81
+ transaction.setDate(tx.date);
82
+ transaction.setAmount(tx.amount);
83
+ transaction.setDescription(fullDescription);
84
+ return transaction;
85
+ });
86
+ // Batch create transactions
87
+ const createdTransactions = yield book.batchCreateTransactions(bkperTransactions);
88
+ // Clean response by removing internal fields and ensure JSON serializable
89
+ const transactions = createdTransactions.map((transaction) => {
90
+ const transactionJson = transaction.json();
91
+ const { agentId, agentName, agentLogo, agentLogoDark, createdAt, createdBy, updatedAt, dateValue } = transactionJson, cleanTransaction = __rest(transactionJson, ["agentId", "agentName", "agentLogo", "agentLogoDark", "createdAt", "createdBy", "updatedAt", "dateValue"]);
92
+ // Ensure all values are JSON serializable
93
+ return JSON.parse(JSON.stringify(cleanTransaction));
94
+ });
95
+ // Build response
96
+ const response = {
97
+ transactions
98
+ };
99
+ const responseText = JSON.stringify(response, null, 2);
100
+ return {
101
+ content: [
102
+ {
103
+ type: 'text',
104
+ text: responseText,
105
+ },
106
+ ],
107
+ };
108
+ }
109
+ catch (error) {
110
+ // Re-throw MCP errors as-is
111
+ if (error instanceof McpError) {
112
+ throw error;
113
+ }
114
+ // Handle other errors
115
+ throw new McpError(ErrorCode.InternalError, `Failed to create transactions: ${error instanceof Error ? error.message : String(error)}`);
116
+ }
117
+ });
118
+ }
119
+ export const createTransactionsToolDefinition = {
120
+ name: 'create_transactions',
121
+ description: 'Create transactions in batch from structured data. Accounts are specified by name and resolved by Bkper.',
122
+ inputSchema: {
123
+ type: 'object',
124
+ properties: {
125
+ bookId: {
126
+ type: 'string',
127
+ description: 'The unique identifier of the book'
128
+ },
129
+ transactions: {
130
+ type: 'array',
131
+ items: {
132
+ type: 'object',
133
+ properties: {
134
+ date: {
135
+ type: 'string',
136
+ description: 'Transaction date in ISO format (YYYY-MM-DD) or book date format'
137
+ },
138
+ amount: {
139
+ type: 'number',
140
+ description: 'Transaction amount'
141
+ },
142
+ from_account: {
143
+ type: 'string',
144
+ description: 'Origin/Credit account name'
145
+ },
146
+ to_account: {
147
+ type: 'string',
148
+ description: 'Destination/Debit account name'
149
+ },
150
+ description: {
151
+ type: 'string',
152
+ description: 'Transaction description (can include #hashtags)'
153
+ }
154
+ },
155
+ required: ['date', 'amount', 'description']
156
+ },
157
+ description: 'Array of transactions to create'
158
+ }
159
+ },
160
+ required: ['bookId', 'transactions']
161
+ }
162
+ };
163
+ //# sourceMappingURL=create_transactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_transactions.js","sourceRoot":"","sources":["../../../src/mcp/tools/create_transactions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * MCP Tool: merge_transactions
3
+ *
4
+ * Thin adapter that handles MCP protocol concerns (validation, error handling, response formatting)
5
+ * and delegates business logic to the domain layer.
6
+ */
7
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
8
+ /**
9
+ * MCP-specific request parameters
10
+ */
11
+ interface MergeTransactionsParams {
12
+ bookId: string;
13
+ transactionId1: string;
14
+ transactionId2: string;
15
+ }
16
+ export declare function handleMergeTransactions(params: MergeTransactionsParams): Promise<CallToolResult>;
17
+ export declare const mergeTransactionsToolDefinition: {
18
+ name: string;
19
+ description: string;
20
+ inputSchema: {
21
+ type: string;
22
+ properties: {
23
+ bookId: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ transactionId1: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ transactionId2: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ };
36
+ required: string[];
37
+ };
38
+ };
39
+ export {};
40
+ //# sourceMappingURL=merge_transactions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge_transactions.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/merge_transactions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAuB,MAAM,oCAAoC,CAAC;AAKzF;;GAEG;AACH,UAAU,uBAAuB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAWD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC,CA6GtG;AAED,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;CAqB3C,CAAC"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MCP Tool: merge_transactions
3
+ *
4
+ * Thin adapter that handles MCP protocol concerns (validation, error handling, response formatting)
5
+ * and delegates business logic to the domain layer.
6
+ */
7
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
8
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
9
+ return new (P || (P = Promise))(function (resolve, reject) {
10
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
11
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
12
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
13
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
14
+ });
15
+ };
16
+ var __rest = (this && this.__rest) || function (s, e) {
17
+ var t = {};
18
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
19
+ t[p] = s[p];
20
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
21
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
22
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
23
+ t[p[i]] = s[p[i]];
24
+ }
25
+ return t;
26
+ };
27
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
28
+ import { getBkperInstance } from '../bkper-factory.js';
29
+ import { TransactionMergeOperation } from '../domain/transaction/merge-operation.js';
30
+ export function handleMergeTransactions(params) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ try {
33
+ // Validate required parameters
34
+ if (!params.bookId) {
35
+ throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: bookId');
36
+ }
37
+ if (!params.transactionId1) {
38
+ throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: transactionId1');
39
+ }
40
+ if (!params.transactionId2) {
41
+ throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: transactionId2');
42
+ }
43
+ // Get configured Bkper instance
44
+ const bkperInstance = getBkperInstance();
45
+ // Get the book
46
+ const book = yield bkperInstance.getBook(params.bookId);
47
+ if (!book) {
48
+ throw new McpError(ErrorCode.InvalidParams, `Book not found: ${params.bookId}`);
49
+ }
50
+ // Fetch both transactions
51
+ const transaction1 = yield book.getTransaction(params.transactionId1);
52
+ if (!transaction1) {
53
+ throw new McpError(ErrorCode.InvalidParams, `Transaction not found: ${params.transactionId1}`);
54
+ }
55
+ const transaction2 = yield book.getTransaction(params.transactionId2);
56
+ if (!transaction2) {
57
+ throw new McpError(ErrorCode.InvalidParams, `Transaction not found: ${params.transactionId2}`);
58
+ }
59
+ // Perform merge operation
60
+ const mergeOperation = new TransactionMergeOperation(book, transaction1, transaction2);
61
+ // Execute the merge: trash the revert transaction
62
+ yield mergeOperation.revertTransaction.trash();
63
+ // Apply merged data to edit transaction (only needed for real API, not mocks)
64
+ if (typeof mergeOperation.editTransaction.setDescription === 'function') {
65
+ mergeOperation.applyMergedData();
66
+ // Update the edit transaction with merged data
67
+ yield mergeOperation.editTransaction.update();
68
+ }
69
+ // Return the merged data
70
+ const _a = mergeOperation.mergedData, { agentId, agentName, agentLogo, agentLogoDark, createdAt, createdBy, updatedAt, dateValue } = _a, cleanTransaction = __rest(_a, ["agentId", "agentName", "agentLogo", "agentLogoDark", "createdAt", "createdBy", "updatedAt", "dateValue"]);
71
+ // Build response
72
+ const response = {
73
+ mergedTransaction: JSON.parse(JSON.stringify(cleanTransaction)),
74
+ revertedTransactionId: mergeOperation.revertTransaction.getId() || '',
75
+ auditRecord: null // Always null - we throw error if amounts differ
76
+ };
77
+ const responseText = JSON.stringify(response, null, 2);
78
+ return {
79
+ content: [
80
+ {
81
+ type: 'text',
82
+ text: responseText,
83
+ },
84
+ ],
85
+ };
86
+ }
87
+ catch (error) {
88
+ // Re-throw MCP errors as-is
89
+ if (error instanceof McpError) {
90
+ throw error;
91
+ }
92
+ // Handle other errors
93
+ console.error('Merge transactions error details:', error);
94
+ throw new McpError(ErrorCode.InternalError, `Failed to merge transactions: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
95
+ }
96
+ });
97
+ }
98
+ export const mergeTransactionsToolDefinition = {
99
+ name: 'merge_transactions',
100
+ description: 'Merge two duplicate or related transactions into a single consolidated transaction. Intelligently combines descriptions, attachments, amounts, and metadata while marking one transaction as reverted.',
101
+ inputSchema: {
102
+ type: 'object',
103
+ properties: {
104
+ bookId: {
105
+ type: 'string',
106
+ description: 'The unique identifier of the book'
107
+ },
108
+ transactionId1: {
109
+ type: 'string',
110
+ description: 'The ID of the first transaction to merge'
111
+ },
112
+ transactionId2: {
113
+ type: 'string',
114
+ description: 'The ID of the second transaction to merge'
115
+ }
116
+ },
117
+ required: ['bookId', 'transactionId1', 'transactionId2']
118
+ }
119
+ };
120
+ //# sourceMappingURL=merge_transactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge_transactions.js","sourceRoot":"","sources":["../../../src/mcp/tools/merge_transactions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,79 +1,79 @@
1
1
  {
2
- "name": "bkper",
3
- "version": "3.5.5",
4
- "description": "Node.js command line client for Bkper",
5
- "bin": {
6
- "bkper": "./lib/cli.js"
7
- },
8
- "repository": "https://github.com/bkper/bkper-node.git",
9
- "homepage": "https://bkper.com/docs",
10
- "author": "mael <mael@bkper.com>",
11
- "license": "Apache-2.0",
12
- "private": false,
13
- "main": "./lib/index.js",
14
- "module": "./lib/index.js",
15
- "types": "./lib/index.d.ts",
16
- "type": "module",
17
- "files": [
18
- "lib/**/*"
19
- ],
20
- "mcp": {
21
- "server": {
22
- "command": "node",
23
- "args": [
24
- "lib/cli.js",
25
- "mcp",
26
- "start"
27
- ],
28
- "env": {}
2
+ "name": "bkper",
3
+ "version": "3.6.0",
4
+ "description": "Node.js command line client for Bkper",
5
+ "bin": {
6
+ "bkper": "./lib/cli.js"
7
+ },
8
+ "repository": "https://github.com/bkper/bkper-node.git",
9
+ "homepage": "https://bkper.com/docs",
10
+ "author": "mael <mael@bkper.com>",
11
+ "license": "Apache-2.0",
12
+ "private": false,
13
+ "main": "./lib/index.js",
14
+ "module": "./lib/index.js",
15
+ "types": "./lib/index.d.ts",
16
+ "type": "module",
17
+ "files": [
18
+ "lib/**/*"
19
+ ],
20
+ "mcp": {
21
+ "server": {
22
+ "command": "node",
23
+ "args": [
24
+ "lib/cli.js",
25
+ "mcp",
26
+ "start"
27
+ ],
28
+ "env": {}
29
+ }
30
+ },
31
+ "scripts": {
32
+ "clean": "rm -rf ./lib & rm -rf ./node_modules & wait",
33
+ "prebuild": "bun install",
34
+ "build": "run-s build:*",
35
+ "build:clean": "gts clean && rimraf temp",
36
+ "build:compile": "tsc",
37
+ "build:copy-docs": "mkdir -p lib/docs && cp -f docs/*.md lib/docs/ 2>/dev/null || true",
38
+ "build:copy-mcp-assets": "mkdir -p lib/mcp && cp -f src/mcp/*.md lib/mcp/ 2>/dev/null || true",
39
+ "predev": "bun run build",
40
+ "dev": "bun run build && npx concurrently \"tsc -w\" \"./scripts/dev-mcp.sh\"",
41
+ "mcp": "bun run build && node lib/cli.js mcp start",
42
+ "ports": "devpod ssh ../ -L 6274",
43
+ "test": "TS_NODE_PROJECT=tsconfig.test.json mocha",
44
+ "test:unit": "TS_NODE_PROJECT=tsconfig.test.json mocha --config .mocharc.json",
45
+ "test:integration": "TS_NODE_PROJECT=tsconfig.test.json mocha --config .mocharc.integration.json",
46
+ "test:all": "bun run test:unit && bun run test:integration",
47
+ "upgrade:api": "bun update @bkper/bkper-api-types --latest && bun update bkper-js --latest",
48
+ "patch": "yarn version --patch",
49
+ "minor": "yarn version --minor",
50
+ "major": "yarn version --major",
51
+ "preversion": "bun run build",
52
+ "postversion": "git push --tags && yarn publish --new-version $npm_package_version && git push && echo \"Successfully released version $npm_package_version!\""
53
+ },
54
+ "dependencies": {
55
+ "@google-cloud/local-auth": "^3.0.1",
56
+ "@modelcontextprotocol/sdk": "^1.13.1",
57
+ "bkper-js": "^2.4.0",
58
+ "commander": "^6.2.1",
59
+ "dotenv": "^8.2.0",
60
+ "google-auth-library": "^9.14.0",
61
+ "yaml": "^2.5.1"
62
+ },
63
+ "devDependencies": {
64
+ "@bkper/bkper-api-types": "^5.23.0",
65
+ "@types/chai": "^4.3.0",
66
+ "@types/mocha": "^10.0.0",
67
+ "@types/node": "^22.5.1",
68
+ "chai": "^4.3.0",
69
+ "concurrently": "^8.2.2",
70
+ "gts": "^3.0.3",
71
+ "mocha": "^10.0.0",
72
+ "nodemon": "^3.0.1",
73
+ "npm-run-all": "^4.1.5",
74
+ "rimraf": "^3.0.2",
75
+ "ts-node": "^10.9.2",
76
+ "tsconfig-paths": "^4.2.0",
77
+ "typescript": "^5.5.4"
29
78
  }
30
- },
31
- "scripts": {
32
- "clean": "rm -rf ./lib & rm -rf ./node_modules & wait",
33
- "prebuild": "bun install",
34
- "build": "run-s build:*",
35
- "build:clean": "gts clean && rimraf temp",
36
- "build:compile": "tsc",
37
- "build:copy-docs": "mkdir -p lib/docs && cp -f docs/*.md lib/docs/ 2>/dev/null || true",
38
- "build:copy-mcp-assets": "mkdir -p lib/mcp && cp -f src/mcp/*.md lib/mcp/ 2>/dev/null || true",
39
- "predev": "bun run build",
40
- "dev": "bun run build && npx concurrently \"tsc -w\" \"./scripts/dev-mcp.sh\"",
41
- "mcp": "bun run build && node lib/cli.js mcp start",
42
- "test": "TS_NODE_PROJECT=tsconfig.test.json mocha",
43
- "test:unit": "TS_NODE_PROJECT=tsconfig.test.json mocha --config .mocharc.json",
44
- "test:integration": "TS_NODE_PROJECT=tsconfig.test.json mocha --config .mocharc.integration.json",
45
- "test:all": "bun run test:unit && bun run test:integration",
46
- "upgrade:api": "bun update @bkper/bkper-api-types --latest && bun update bkper-js --latest",
47
- "patch": "yarn version --patch",
48
- "minor": "yarn version --minor",
49
- "major": "yarn version --major",
50
- "preversion": "bun run build",
51
- "postversion": "git push --tags && yarn publish --new-version $npm_package_version && git push && echo \"Successfully released version $npm_package_version!\""
52
- },
53
- "dependencies": {
54
- "@google-cloud/local-auth": "^3.0.1",
55
- "@modelcontextprotocol/sdk": "^1.13.1",
56
- "bkper-js": "^2.4.0",
57
- "commander": "^6.2.1",
58
- "dotenv": "^8.2.0",
59
- "google-auth-library": "^9.14.0",
60
- "yaml": "^2.5.1"
61
- },
62
- "devDependencies": {
63
- "@bkper/bkper-api-types": "^5.23.0",
64
- "@types/chai": "^4.3.0",
65
- "@types/commander": "^2.12.2",
66
- "@types/mocha": "^10.0.0",
67
- "@types/node": "^22.5.1",
68
- "chai": "^4.3.0",
69
- "concurrently": "^8.2.2",
70
- "gts": "^3.0.3",
71
- "mocha": "^10.0.0",
72
- "nodemon": "^3.0.1",
73
- "npm-run-all": "^4.1.5",
74
- "rimraf": "^3.0.2",
75
- "ts-node": "^10.9.2",
76
- "tsconfig-paths": "^4.2.0",
77
- "typescript": "^5.5.4"
78
- }
79
79
  }