@gabrielerandelli/minus-tracker 0.6.0 → 0.8.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
@@ -16,10 +16,22 @@ Il tool elabora i dati partendo direttamente dal formato CSV esportato da DEGIRO
16
16
  - Calcolo di plusvalenze e minusvalenze con gestione dei lotti via **LIFO o FIFO** (configurabile)
17
17
  - **Parser integrato** per i file CSV di DEGIRO
18
18
  - Gestione **multivaluta** con tassi storici BCE (EUR, USD, GBP, CHF)
19
+ - **Classificazione a due categorie** (Bucket A/B) degli strumenti finanziari — azioni, ETF, titoli
20
+ di stato, derivati — con classificazione automatica via OpenFIGI e sidecar JSON persistente
21
+ - **Modello Redditi PF**: genera Quadro RT (redditi diversi) e Quadro RM (redditi di capitale) a
22
+ partire dai lotti calcolati, con riporto delle minusvalenze pregresse (regola dei 4 anni)
19
23
  - Suite di test allineata alle **FAQ dell'Agenzia delle Entrate**
20
24
  - Output disponibile in **italiano** (default) o **inglese** (`--lang en`)
21
25
  - Disponibile come pacchetto NPM con supporto CLI
22
26
 
27
+ **Novità in v0.8.0:**
28
+
29
+ - **Modalità stateless per `Classifier`**: `classify()` può ora funzionare senza alcun accesso al
30
+ filesystem (nessun sidecar), utile per l'integrazione in agenti/automazioni
31
+ - **Server MCP** (`minus-tracker-mcp`): espone `parse_transactions`, `classify_instruments` e
32
+ `calculate_gains` come tool MCP su stdio, per l'uso diretto da parte di agenti AI — vedi la
33
+ sezione [Server MCP](#server-mcp) più sotto
34
+
23
35
  ### Avvio rapido
24
36
 
25
37
  Se non hai ancora un export di DEGIRO a disposizione, puoi testare il tool con il file di esempio incluso nel pacchetto.
@@ -85,15 +97,16 @@ npx @gabrielerandelli/minus-tracker calc trades.csv
85
97
 
86
98
  ### Utilizzo CLI
87
99
 
88
- | Comando | Flag principali | Note |
89
- | ---------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------- |
90
- | `calc <file.csv>` | `--method LIFO\|FIFO` (default: LIFO), `--lang it\|en`, `--json` | Aggiorna i tassi BCE automaticamente se la snapshot ha più di 7 giorni |
91
- | `validate <file.csv>` | `--lang it\|en` | Exit 0 con avvisi; exit 1 in caso di errori bloccanti |
92
- | `rates --check` | | Mostra la copertura della snapshot BCE in locale |
93
- | `rates --update` | — | Scarica i tassi aggiornati dall'API BCE |
94
- | `config --lang it\|en` | — | Salva la lingua preferita |
95
- | `config --show` | — | Mostra la lingua correntemente impostata |
96
- | `stress-test` | `--range N-M`, `--keep`, `--json`, `--output-dir` | Documentato in fondo |
100
+ | Comando | Flag principali | Note |
101
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
102
+ | `calc <file.csv>` | `--method LIFO\|FIFO` (default: LIFO), `--lang it\|en`, `--json`, `--export-dichiarazione [path]`, `--carry-forward` | Aggiorna i tassi BCE automaticamente se la snapshot ha più di 7 giorni; usa il sidecar di `classify` se presente |
103
+ | `classify <file.csv>` | `--offline` | Classifica gli strumenti (Bucket A/B) e crea/aggiorna il sidecar `*.classify.json` |
104
+ | `validate <file.csv>` | `--lang it\|en` | Exit 0 con avvisi; exit 1 in caso di errori bloccanti |
105
+ | `rates --check` | — | Mostra la copertura della snapshot BCE in locale |
106
+ | `rates --update` | — | Scarica i tassi aggiornati dall'API BCE |
107
+ | `config --lang it\|en` | — | Salva la lingua preferita |
108
+ | `config --show` | — | Mostra la lingua correntemente impostata |
109
+ | `stress-test` | `--range N-M`, `--keep`, `--json`, `--output-dir` | Documentato in fondo |
97
110
 
98
111
  Precedenza lingua: `--lang` > lingua salvata > italiano (default).
99
112
 
@@ -128,6 +141,7 @@ npm install @gabrielerandelli/minus-tracker
128
141
  import {
129
142
  DEGIROParser,
130
143
  Calculator,
144
+ Classifier,
131
145
  ParseError,
132
146
  CalculationError,
133
147
  } from "@gabrielerandelli/minus-tracker";
@@ -140,19 +154,25 @@ if (parser.warnings.length > 0) {
140
154
  console.warn("Righe saltate:", parser.warnings);
141
155
  }
142
156
 
143
- // 2. Calcolo
144
- const method: LotMethod = "LIFO"; // oppure "FIFO"
145
- const report: GainsReport = new Calculator(
157
+ // 2. Classificazione (Bucket A/B) — facoltativa, abilita Quadro RT/RM nel report
158
+ const classification = await new Classifier().classify(
146
159
  transactions,
147
- parser.warnings,
148
- ).calculateGains(method);
160
+ "trades.classify.json", // sidecar persistente; omettilo per la modalità stateless
161
+ );
162
+
163
+ // 3. Calcolo
164
+ const method: LotMethod = "LIFO"; // oppure "FIFO"
165
+ const report: GainsReport = new Calculator(transactions, parser.warnings, {
166
+ classification,
167
+ }).calculateGains(method);
149
168
 
150
169
  console.log(report.plusvalenze); // numero in EUR
151
170
  console.log(report.minusvalenze); // numero in EUR (valore assoluto)
152
171
  console.log(report.netResult); // plusvalenze - minusvalenze
153
172
  console.log(report.lots); // MatchedLot[] — dettaglio per lotto
173
+ console.log(report.dichiarazione); // Quadro RT/RM, se classification è stata passata
154
174
 
155
- // 3. Gestione errori
175
+ // 4. Gestione errori
156
176
  try {
157
177
  const txs = parser.parse(csvString);
158
178
  const r = new Calculator(txs, parser.warnings).calculateGains("LIFO");
@@ -177,6 +197,46 @@ try {
177
197
 
178
198
  **Prerequisiti:** Node.js ≥ 24 ([nodejs.org](https://nodejs.org))
179
199
 
200
+ ### Server MCP
201
+
202
+ A partire dalla v0.8.0, minus-tracker include un binario `minus-tracker-mcp` che espone un
203
+ [server MCP](https://modelcontextprotocol.io) su stdio, pensato per l'uso diretto da parte di
204
+ agenti AI (senza passare dalla CLI):
205
+
206
+ ```bash
207
+ npx -p @gabrielerandelli/minus-tracker minus-tracker-mcp
208
+ ```
209
+
210
+ Configurazione tipica per un client MCP (es. Claude Desktop, `claude_desktop_config.json`):
211
+
212
+ ```json
213
+ {
214
+ "mcpServers": {
215
+ "minus-tracker": {
216
+ "command": "npx",
217
+ "args": [
218
+ "-y",
219
+ "-p",
220
+ "@gabrielerandelli/minus-tracker",
221
+ "minus-tracker-mcp"
222
+ ]
223
+ }
224
+ }
225
+ }
226
+ ```
227
+
228
+ Il server espone 3 tool:
229
+
230
+ | Tool | Descrizione |
231
+ | ---------------------- | ------------------------------------------------------------------------------ |
232
+ | `parse_transactions` | Effettua il parsing di un CSV DEGIRO in `transactions`/`warnings`/`incomeRows` |
233
+ | `classify_instruments` | Classifica gli ISIN in Bucket A/B (modalità stateless — nessun sidecar) |
234
+ | `calculate_gains` | Calcola plusvalenze/minusvalenze (LIFO/FIFO) e, se disponibile, Quadro RT/RM |
235
+
236
+ `classify_instruments` supporta `existingClassification`, `overrides` e `offline: true` per
237
+ funzionare senza rete e senza accesso al filesystem — pensato per essere invocato ripetutamente
238
+ da un agente su più chiamate, mantenendo lo stato lato client.
239
+
180
240
  ### Domande frequenti
181
241
 
182
242
  **Il CSV viene rifiutato con "colonna mancante" o "CSV non valido"**
@@ -251,10 +311,22 @@ It loads data following the CSV format used by DEGIRO.
251
311
  - Capital-gains/loss calculation with configurable **LIFO and FIFO** lot matching
252
312
  - **DEGIRO CSV parser**
253
313
  - **Multi-currency** handling with historical ECB rates (EUR, USD, GBP, CHF)
314
+ - **Two-bucket classification** (Bucket A/B) of financial instruments — stocks, ETFs, government
315
+ bonds, derivatives — with automatic OpenFIGI-backed classification and a persistent JSON sidecar
316
+ - **Modello Redditi PF** generation: Quadro RT (capital gains) and Quadro RM (capital income) built
317
+ from the calculated lots, with prior-year loss carryforward (4-year rule)
254
318
  - Test suite based on **Agenzia Entrate FAQ**
255
319
  - Output in **Italian** (default) or **English** (`--lang en`)
256
320
  - minus-tracker is an NPM package with CLI support
257
321
 
322
+ **New in v0.8.0:**
323
+
324
+ - **Stateless mode for `Classifier`**: `classify()` can now run with zero filesystem access (no
325
+ sidecar file), useful for embedding in agents/automations
326
+ - **MCP server** (`minus-tracker-mcp`): exposes `parse_transactions`, `classify_instruments`, and
327
+ `calculate_gains` as MCP tools over stdio, for direct use by AI agents — see the
328
+ [MCP Server](#mcp-server) section below
329
+
258
330
  ### Quick Start
259
331
 
260
332
  Don't have a DEGIRO export yet? Use the sample file bundled with the package.
@@ -321,15 +393,16 @@ npx @gabrielerandelli/minus-tracker calc trades.csv
321
393
 
322
394
  ### CLI Usage
323
395
 
324
- | Command | Key flags | Notes |
325
- | ---------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------- |
326
- | `calc <file.csv>` | `--method LIFO\|FIFO` (default: LIFO), `--lang it\|en`, `--json` | Auto-fetches ECB rates if snapshot is more than 7 days old |
327
- | `validate <file.csv>` | `--lang it\|en` | Exit 0 with warnings; exit 1 on hard errors |
328
- | `rates --check` | | Shows bundled ECB snapshot coverage |
329
- | `rates --update` | — | Fetches fresh rates from the ECB API |
330
- | `config --lang it\|en` | — | Saves language preference |
331
- | `config --show` | — | Shows current language setting |
332
- | `stress-test` | `--range N-M`, `--keep`, `--json`, `--output-dir` | Documented below |
396
+ | Command | Key flags | Notes |
397
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
398
+ | `calc <file.csv>` | `--method LIFO\|FIFO` (default: LIFO), `--lang it\|en`, `--json`, `--export-dichiarazione [path]`, `--carry-forward` | Auto-fetches ECB rates if snapshot is more than 7 days old; uses `classify`'s sidecar when present |
399
+ | `classify <file.csv>` | `--offline` | Classifies instruments (Bucket A/B) and creates/updates the `*.classify.json` sidecar |
400
+ | `validate <file.csv>` | `--lang it\|en` | Exit 0 with warnings; exit 1 on hard errors |
401
+ | `rates --check` | — | Shows bundled ECB snapshot coverage |
402
+ | `rates --update` | — | Fetches fresh rates from the ECB API |
403
+ | `config --lang it\|en` | — | Saves language preference |
404
+ | `config --show` | — | Shows current language setting |
405
+ | `stress-test` | `--range N-M`, `--keep`, `--json`, `--output-dir` | Documented below |
333
406
 
334
407
  Language precedence: `--lang` flag > saved config > Italian (default).
335
408
 
@@ -364,6 +437,7 @@ npm install @gabrielerandelli/minus-tracker
364
437
  import {
365
438
  DEGIROParser,
366
439
  Calculator,
440
+ Classifier,
367
441
  ParseError,
368
442
  CalculationError,
369
443
  } from "@gabrielerandelli/minus-tracker";
@@ -376,19 +450,25 @@ if (parser.warnings.length > 0) {
376
450
  console.warn("Skipped rows:", parser.warnings);
377
451
  }
378
452
 
379
- // 2. Calculate
380
- const method: LotMethod = "LIFO"; // or "FIFO"
381
- const report: GainsReport = new Calculator(
453
+ // 2. Classify (Bucket A/B) — optional, enables Quadro RT/RM in the report
454
+ const classification = await new Classifier().classify(
382
455
  transactions,
383
- parser.warnings,
384
- ).calculateGains(method);
456
+ "trades.classify.json", // persistent sidecar; omit for stateless mode
457
+ );
458
+
459
+ // 3. Calculate
460
+ const method: LotMethod = "LIFO"; // or "FIFO"
461
+ const report: GainsReport = new Calculator(transactions, parser.warnings, {
462
+ classification,
463
+ }).calculateGains(method);
385
464
 
386
465
  console.log(report.plusvalenze); // EUR capital gains (number)
387
466
  console.log(report.minusvalenze); // EUR capital losses (number, absolute value)
388
467
  console.log(report.netResult); // plusvalenze - minusvalenze
389
468
  console.log(report.lots); // MatchedLot[] — per-lot breakdown
469
+ console.log(report.dichiarazione); // Quadro RT/RM, when classification was passed
390
470
 
391
- // 3. Error handling
471
+ // 4. Error handling
392
472
  try {
393
473
  const txs = parser.parse(csvString);
394
474
  const r = new Calculator(txs, parser.warnings).calculateGains("LIFO");
@@ -411,6 +491,46 @@ minus-tracker is **pure tax math** — no UI, auth, database, or PDF.
411
491
 
412
492
  **Prerequisites:** Node.js ≥ 24 ([nodejs.org](https://nodejs.org))
413
493
 
494
+ ### MCP Server
495
+
496
+ As of v0.8.0, minus-tracker ships a `minus-tracker-mcp` binary exposing an
497
+ [MCP server](https://modelcontextprotocol.io) over stdio, for direct use by AI agents (no need to
498
+ go through the CLI):
499
+
500
+ ```bash
501
+ npx -p @gabrielerandelli/minus-tracker minus-tracker-mcp
502
+ ```
503
+
504
+ Typical MCP client configuration (e.g. Claude Desktop, `claude_desktop_config.json`):
505
+
506
+ ```json
507
+ {
508
+ "mcpServers": {
509
+ "minus-tracker": {
510
+ "command": "npx",
511
+ "args": [
512
+ "-y",
513
+ "-p",
514
+ "@gabrielerandelli/minus-tracker",
515
+ "minus-tracker-mcp"
516
+ ]
517
+ }
518
+ }
519
+ }
520
+ ```
521
+
522
+ The server exposes 3 tools:
523
+
524
+ | Tool | Description |
525
+ | ---------------------- | --------------------------------------------------------------------- |
526
+ | `parse_transactions` | Parses a DEGIRO CSV into `transactions`/`warnings`/`incomeRows` |
527
+ | `classify_instruments` | Classifies ISINs into Bucket A/B (stateless mode — no sidecar file) |
528
+ | `calculate_gains` | Calculates gains/losses (LIFO/FIFO) and, when available, Quadro RT/RM |
529
+
530
+ `classify_instruments` supports `existingClassification`, `overrides`, and `offline: true` to run
531
+ without network access or filesystem access — designed to be called repeatedly by an agent across
532
+ multiple calls, with state kept client-side.
533
+
414
534
  ### FAQ / Troubleshooting
415
535
 
416
536
  **My CSV is rejected with "missing column" or "invalid CSV"**