fin-app-mcp 2.3.3 → 3.0.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.
Files changed (2) hide show
  1. package/index.mjs +362 -69
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -343,14 +343,14 @@ REGRAS DE NEGÓCIO:
343
343
  // ── Mutações ──────────────────────────────────────────────────────
344
344
  {
345
345
  name: "fin_criar_despesa",
346
- description: `Cria uma despesa. Também usada para lançar ESTORNOS em cartão de crédito (via reversal_of_id). Suporta parcelamento automático.
346
+ description: `Cria uma despesa. Suporta parcelamento automático e multi-moeda.
347
347
 
348
348
  QUANDO USAR:
349
349
  - Lançar uma despesa normal (compra, conta, assinatura).
350
- - Lançar um ESTORNO/CANCELAMENTO em cartão de crédito — usar com reversal_of_id.
351
350
  - Lançar uma compra parcelada — usar com installments.
352
351
 
353
352
  NÃO USAR QUANDO:
353
+ - Quiser lançar ESTORNO/CANCELAMENTO em cartão — usar fin_criar_estorno (rota dedicada, valida ownership e invariants atomicamente).
354
354
  - Quiser lançar receita (usar fin_criar_receita).
355
355
  - Quiser registrar pagamento de fatura de cartão (usar fin_pagar_fatura).
356
356
  - Quiser transferir entre contas (usar fin_criar_transferencia).
@@ -365,15 +365,11 @@ CAMPOS:
365
365
  - essential: boolean — se é despesa essencial.
366
366
  - installments: number — número de parcelas (2-48). Gera N transações separadas automaticamente.
367
367
  - current_installment: number — parcela inicial (default: 1). Passar 1 é equivalente ao default — o sistema cria todas as N parcelas começando da primeira. Use valores > 1 APENAS quando registrando uma compra parcelada que já está em andamento e você quer criar apenas as parcelas futuras (ex: installments=10, current_installment=3 cria 8 transações, da parcela 3 à 10).
368
- - reversal_of_id: string UUID ID da transação original para estorno.
369
- - reversal_kind: string — 'full' ou 'partial' (obrigatório quando reversal_of_id é informado).
370
-
371
- REGRAS DE NEGÓCIOESTORNO:
372
- - Para estorno em cartão: criar despesa com reversal_of_id = UUID da transação original.
373
- - O amount_cents é POSITIVO — o sistema inverte automaticamente na fatura.
374
- - O account_name DEVE ser o mesmo cartão da transação original.
375
- - NUNCA usar fin_criar_receita para estorno em cartão — receita SOMA na fatura em vez de subtrair.
376
- - A transação original deve existir, ser expense, e não ser outro estorno.
368
+ - tags: string[]tags livres pra cortes ortogonais (ex: ["TDAH-tracking", "Lou-shared"]).
369
+ - original_purchase_date: string YYYY-MM-DD data REAL da compra (use junto com installments>1 e current_installment>1 em cartão para o FIN colocar cada parcela na fatura certa a partir do cutoff do cartão).
370
+ - original_amount_cents: number — valor na moeda estrangeira (ex: 2000 = US$ 20,00). Use quando a despesa foi em USD.
371
+ - original_currency: 'BRL' | 'USD' moeda de original_amount_cents.
372
+ - exchange_rate: number — cotação em decimal (5.1023 = R$ 5,1023 por 1 USD). Opcional; use quando NÃO passar amount_cents (backend deriva BRL).
377
373
 
378
374
  REGRAS DE NEGÓCIO — PARCELAMENTO:
379
375
  - installments: N gera N transações separadas, cada uma em um mês consecutivo.
@@ -385,17 +381,33 @@ REGRAS DE NEGÓCIO — CICLO DE FATURA:
385
381
  - invoice_cycle_end: força a transação a pertencer a um ciclo de fatura específico, independente da tx_date. Usar quando o banco lista um cancelamento/estorno em uma fatura diferente da compra original. O valor é a data de fechamento do ciclo (YYYY-MM-DD), NÃO o reference_month.
386
382
  - Ver seção 8 do guia (fin://docs/guia) para cenários de conciliação complexa.
387
383
 
384
+ REGRAS DE NEGÓCIO — MULTI-MOEDA (USD):
385
+ - amount_cents é SEMPRE em BRL. Para despesas em USD, pergunte à pessoa: "cotação automática ou valor exato em BRL que saiu?".
386
+ - Conta USD EXIGE original_amount_cents + original_currency: "USD". Passar só amount_cents numa conta USD retorna 422.
387
+ - Modo (a) — pessoa informa o BRL exato: passar amount_cents (BRL) + original_amount_cents + original_currency. O backend grava BRL como fonte da verdade e deriva exchange_rate.
388
+ - Modo (b) — pessoa só sabe a cotação: passar original_amount_cents + original_currency + exchange_rate (sem amount_cents). Backend calcula amount_cents = original_amount * rate.
389
+ - Modo (c) — despesa BRL normal: só passar amount_cents.
390
+
391
+ REGRAS DE NEGÓCIO — PARCELAMENTO DE COMPRA ANTIGA:
392
+ - Pra lançar uma compra já em andamento (ex: "Ray-Ban 10x, estou na parcela 4"), passe original_purchase_date (data REAL da compra), installments (10), current_installment (4). O backend usa o cutoff/due_day do cartão pra colocar a parcela 4 na fatura corrente e as próximas nas faturas futuras. SEM esse campo, você precisa passar tx_date como "data da primeira parcela a cair" (anti-intuitivo).
393
+
388
394
  EXEMPLO — despesa simples:
389
395
  { "description": "Almoço", "amount_cents": 3500, "account_name": "Nubank", "category_name": "Alimentação" }
390
396
 
391
- EXEMPLO — estorno:
392
- { "description": "Cancelamento Rappi", "amount_cents": 1474, "account_name": "Latam Itaú", "category_name": "Alimentação", "reversal_of_id": "uuid-da-transacao-original", "reversal_kind": "partial" }
393
-
394
397
  EXEMPLO — parcelamento:
395
398
  { "description": "Óculos Fozoco", "amount_cents": 36792, "account_name": "Nubank", "category_name": "Saúde", "installments": 4 }
396
399
 
397
- EXEMPLO — forçar ciclo:
398
- { "description": "Cancelamento GoDaddy", "amount_cents": 59322, "account_name": "Latam Itaú", "category_name": "Tecnologia", "reversal_of_id": "uuid-original", "reversal_kind": "full", "invoice_cycle_end": "2026-05-01" }`,
400
+ EXEMPLO — forçar ciclo (caso raro — banco lista compra em fatura diferente do esperado pela data):
401
+ { "description": "Compra retroativa", "amount_cents": 59322, "account_name": "Latam Itaú", "category_name": "Tecnologia", "invoice_cycle_end": "2026-05-01" }
402
+
403
+ EXEMPLO — compra USD com BRL exato (modo a):
404
+ { "description": "Camiseta NY", "amount_cents": 10200, "original_amount_cents": 2000, "original_currency": "USD", "account_name": "Wise USD", "category_name": "Pessoal", "subcategory_name": "Vestuário" }
405
+
406
+ EXEMPLO — compra USD via cotação (modo b):
407
+ { "description": "Café", "original_amount_cents": 500, "original_currency": "USD", "exchange_rate": 5.20, "account_name": "Wise USD", "category_name": "Alimentação" }
408
+
409
+ EXEMPLO — Ray-Ban 10x, parcela 4 em cartão Caixa (compra dez/2025, hoje abril/2026):
410
+ { "description": "Ray-Ban", "amount_cents": 137000, "account_name": "Caixa Cartão", "category_name": "Pessoal", "subcategory_name": "Acessórios", "installments": 10, "current_installment": 4, "original_purchase_date": "2025-12-23" }`,
399
411
  inputSchema: {
400
412
  type: "object",
401
413
  properties: {
@@ -414,20 +426,34 @@ EXEMPLO — forçar ciclo:
414
426
  type: "number",
415
427
  description: "Parcela inicial (default: 1). Usar para entrar no meio de parcelamento existente.",
416
428
  },
417
- reversal_of_id: {
429
+ invoice_cycle_end: {
418
430
  type: "string",
419
- description: "UUID da transação original para estornos/créditos em cartão",
431
+ description: "YYYY-MM-DD data de fechamento do ciclo. Força a transação pra uma fatura específica.",
432
+ },
433
+ tags: {
434
+ type: "array",
435
+ items: { type: "string" },
436
+ description: "Tags livres pra cortes ortogonais (max 20).",
420
437
  },
421
- reversal_kind: {
438
+ original_purchase_date: {
422
439
  type: "string",
423
- description: "'full' ou 'partial' obrigatório quando reversal_of_id é informado",
440
+ description: "YYYY-MM-DD data REAL da compra. Use com installments>1 + current_installment>1 em cartão pra colocar cada parcela na fatura certa.",
424
441
  },
425
- invoice_cycle_end: {
442
+ original_amount_cents: {
443
+ type: "number",
444
+ description: "Valor em centavos na moeda estrangeira (ex: 2000 = US$ 20,00).",
445
+ },
446
+ original_currency: {
426
447
  type: "string",
427
- description: "YYYY-MM-DD — data de fechamento do ciclo. Força a transação pra uma fatura específica.",
448
+ enum: ["BRL", "USD"],
449
+ description: "Moeda de original_amount_cents. Use 'USD' pra despesas em dólar.",
450
+ },
451
+ exchange_rate: {
452
+ type: "number",
453
+ description: "Cotação em decimal: 5.1023 = R$ 5,1023 por 1 USD. Use quando NÃO passar amount_cents.",
428
454
  },
429
455
  },
430
- required: ["description", "amount_cents"],
456
+ required: ["description"],
431
457
  },
432
458
  },
433
459
  {
@@ -436,7 +462,7 @@ EXEMPLO — forçar ciclo:
436
462
 
437
463
  QUANDO USAR: lançar salário, freelance, dividendos, reembolso em conta corrente.
438
464
  NÃO USAR QUANDO:
439
- - Quiser lançar estorno em cartão de crédito — usar fin_criar_despesa com reversal_of_id.
465
+ - Quiser lançar estorno em cartão de crédito — usar fin_criar_estorno.
440
466
  - Quiser transferir entre contas — usar fin_criar_transferencia.
441
467
 
442
468
  CAMPOS:
@@ -446,6 +472,7 @@ CAMPOS:
446
472
  - category_name: string — nome da categoria (deve ser flow 'income').
447
473
  - subcategory_name: string — subcategoria.
448
474
  - tx_date: string YYYY-MM-DD — data (default: hoje).
475
+ - tags: string[] — tags livres pra cortes ortogonais.
449
476
 
450
477
  REGRAS DE NEGÓCIO:
451
478
  - Valores em centavos.
@@ -459,6 +486,11 @@ REGRAS DE NEGÓCIO:
459
486
  category_name: { type: "string" },
460
487
  subcategory_name: { type: "string" },
461
488
  tx_date: { type: "string", description: "YYYY-MM-DD (default: hoje)" },
489
+ tags: {
490
+ type: "array",
491
+ items: { type: "string" },
492
+ description: "Tags livres pra cortes ortogonais (max 20).",
493
+ },
462
494
  },
463
495
  required: ["description", "amount_cents"],
464
496
  },
@@ -534,30 +566,30 @@ NÃO USAR QUANDO: quiser deletar (usar fin_deletar_transacao) ou criar nova (usa
534
566
 
535
567
  CAMPOS:
536
568
  - transaction_id: string UUID — ID da transação (obrigatório).
537
- - new_amount_cents: number — novo valor em centavos.
538
- - new_description: string — nova descrição.
539
- - new_category_name: string — nova categoria (por nome).
540
- - new_subcategory_name: string — nova subcategoria (por nome).
541
- - new_account_name: string — nova conta (por nome).
542
- - new_date: string YYYY-MM-DD — nova data.
543
- - new_invoice_cycle_end: string YYYY-MM-DD — força a transação pra uma fatura específica (data de fechamento do ciclo).
569
+ - amount_cents: number — novo valor em centavos.
570
+ - description: string — nova descrição.
571
+ - category_name: string — nova categoria (por nome).
572
+ - subcategory_name: string — nova subcategoria (por nome).
573
+ - account_name: string — nova conta (por nome).
574
+ - tx_date: string YYYY-MM-DD — nova data.
575
+ - invoice_cycle_end: string YYYY-MM-DD — força a transação pra uma fatura específica (data de fechamento do ciclo).
544
576
 
545
577
  REGRAS DE NEGÓCIO:
546
578
  - Valores em centavos.
547
579
  - Campos omitidos não são alterados.
548
580
  - O transaction_id é um UUID (usar fin_buscar_transacoes ou fin_todas_transacoes para encontrar).
549
- - new_invoice_cycle_end: usar para mover uma transação entre faturas (ex: estorno que o banco listou em fatura diferente da compra).`,
581
+ - invoice_cycle_end: usar para mover uma transação entre faturas (ex: estorno que o banco listou em fatura diferente da compra).`,
550
582
  inputSchema: {
551
583
  type: "object",
552
584
  properties: {
553
585
  transaction_id: { type: "string", description: "UUID da transação" },
554
- new_amount_cents: { type: "number" },
555
- new_description: { type: "string" },
556
- new_category_name: { type: "string" },
557
- new_subcategory_name: { type: "string" },
558
- new_account_name: { type: "string" },
559
- new_date: { type: "string", description: "YYYY-MM-DD" },
560
- new_invoice_cycle_end: { type: "string", description: "YYYY-MM-DD — data de fechamento do ciclo da fatura" },
586
+ amount_cents: { type: "number" },
587
+ description: { type: "string" },
588
+ category_name: { type: "string" },
589
+ subcategory_name: { type: "string" },
590
+ account_name: { type: "string" },
591
+ tx_date: { type: "string", description: "YYYY-MM-DD" },
592
+ invoice_cycle_end: { type: "string", description: "YYYY-MM-DD — data de fechamento do ciclo da fatura" },
561
593
  },
562
594
  required: ["transaction_id"],
563
595
  },
@@ -592,7 +624,7 @@ QUANDO USAR:
592
624
  - O banco lista um estorno na fatura mas NÃO desconta do total. Criar ajuste POSITIVO pra anular o efeito do refund no net_total.
593
625
 
594
626
  NÃO USAR QUANDO:
595
- - O estorno/crédito se comporta normalmente (abate do total na mesma fatura que a compra). Nesse caso, basta lançar o estorno com fin_criar_despesa + reversal_of_id.
627
+ - O estorno/crédito se comporta normalmente (abate do total na mesma fatura que a compra). Nesse caso, basta lançar o estorno com fin_criar_estorno.
596
628
  - Quiser mover uma transação entre faturas (usar invoice_cycle_end em fin_criar_despesa ou fin_editar_transacao).
597
629
 
598
630
  CAMPOS:
@@ -731,60 +763,85 @@ NÃO USAR QUANDO: quiser ver transações gerais (usar fin_todas_transacoes) ou
731
763
 
732
764
  CAMPOS:
733
765
  - month: string YYYY-MM — mês de referência (default: mês atual).
766
+ - status: string — filtro opcional. Aceita um valor ('pending', 'overdue', 'paid', 'paid_late'), lista separada por vírgula ('pending,overdue'), ou o atalho 'unpaid' (= pending+overdue).
734
767
 
735
768
  REGRAS DE NEGÓCIO:
736
769
  - Status: 'pending' (aguardando vencimento), 'overdue' (vencida e não paga), 'paid' (paga no prazo), 'paid_late' (paga em atraso).
737
770
  - Ocorrências são geradas automaticamente para cada bill ativa no mês consultado.
738
771
  - amount_cents: valor definido para esta ocorrência (null se ainda não definido — usar default_amount_cents da bill).
739
772
  - transaction_id: preenchido quando a conta foi paga (link para a transação de despesa).
773
+ - Ocorrências pagas vêm com account_name, category_name, subcategory_name, tx_description, invoice_cycle_end resolvidos via JOIN com a transação.
774
+ - Resposta inclui summary com total_*_cents e count_* por status (agregado sobre o mês inteiro, ignorando status filter).
740
775
  - Valores em centavos.
741
776
 
742
777
  EXEMPLO:
743
778
  { "month": "2026-04" }
779
+ { "month": "2026-04", "status": "unpaid" }
744
780
 
745
- Retorno: [{ bill_name: "Light", status: "pending", due_date: "2026-04-01", amount_cents: null }, ...]`,
781
+ Retorno: { summary: {...}, occurrences: [{ bill_name: "Light", status: "pending", due_date: "2026-04-01", amount_cents: null, account_name, category_name, notes }, ...] }`,
746
782
  inputSchema: {
747
783
  type: "object",
748
784
  properties: {
749
785
  month: { type: "string", description: "YYYY-MM (default: mês atual)" },
786
+ status: { type: "string", description: "Filtro opcional: 'pending', 'overdue', 'paid', 'paid_late', 'unpaid' (pending+overdue), ou lista separada por vírgula." },
750
787
  },
751
788
  },
752
789
  },
753
790
  {
754
791
  name: "fin_pagar_bill",
755
- description: `Marca uma conta a pagar como paga e cria a transação de despesa automaticamente.
792
+ description: `Marca uma conta a pagar como paga. Dois modos:
793
+ (1) CRIAR nova transação de despesa (default); ou
794
+ (2) LINKAR a uma transação já existente no extrato (passando transaction_id) — útil quando você importou o OFX antes de cadastrar a bill.
756
795
 
757
- QUANDO USAR: ao conciliar extrato e encontrar pagamento de uma conta recorrente (Light, condomínio, faxina, etc.). Use fin_bills_do_mes primeiro para obter o occurrence_id.
796
+ QUANDO USAR: ao conciliar extrato e encontrar pagamento de uma conta recorrente. Use fin_bills_do_mes primeiro para obter occurrence_id.
758
797
  NÃO USAR QUANDO: quiser lançar despesa avulsa que não é conta recorrente (usar fin_criar_despesa).
759
798
 
760
799
  CAMPOS:
761
- - occurrence_id: string UUID — ID da ocorrência (obrigatório, obter via fin_bills_do_mes).
762
- - amount_cents: numbervalor pago em centavos (obrigatório).
763
- - account_name: stringconta de onde saiu o dinheiro (obrigatório, match parcial).
764
- - category_name: string — categoria da despesa (opcional, usa default da bill se omitido).
765
- - subcategory_name: string subcategoria (opcional).
766
- - payment_date: string YYYY-MM-DD — data do pagamento (default: hoje).
800
+ - occurrence_id: string UUID (obrigatório).
801
+ - transaction_id: string UUID se passado, LINKA em vez de criar. A transação é fonte da verdade (account/amount/date vêm dela). Zero duplicação. Não combina com amount_cents/account_name/fee_cents.
802
+ - amount_cents: numbervalor em centavos. Obrigatório quando transaction_id NÃO é passado.
803
+ - account_name: string — obrigatório quando transaction_id NÃO é passado.
804
+ - category_name / subcategory_name: opcionais (usa default da bill).
805
+ - payment_date: YYYY-MM-DD (default: hoje).
806
+ - fee_cents: number — multa/juros em centavos. Cria uma 2ª transação de despesa em "Taxas, Juros & Impostos > Multa" (ou na categoria que você especificar). Só funciona no modo CRIAR.
807
+ - fee_category_name / fee_subcategory_name: sobrescreve a categoria default da multa.
808
+ - is_catch_up: boolean — marca este pagamento como sendo de um mês PASSADO (ex: Vivo atrasada de março paga junto com abril). Exige catch_up_reference_month.
809
+ - catch_up_reference_month: YYYY-MM — mês que esse pagamento referencia quando is_catch_up=true. Se já existe ocorrência pendente nesse mês, ela é paga; senão, uma nova é criada.
767
810
 
768
811
  REGRAS DE NEGÓCIO:
769
- - Se a ocorrência foi paga, retorna erro.
770
- - Cria transação de despesa automaticamente (não precisa chamar fin_criar_despesa).
771
- - Se category_name não for informado, usa a categoria default cadastrada na bill.
812
+ - Modo LINK (transaction_id): valida ownership, exige tipo expense, bloqueia se transação já está linkada a outra ocorrência. Retorna warning 'transaction_date_outside_occurrence_month' se tx.date não cair no mês da ocorrência.
813
+ - Modo CRIAR: se occurrence foi paga, retorna erro (a menos que is_catch_up=true pra um mês diferente).
814
+ - Catch-up: cria/reaproveita uma ocorrência do mês catch_up_reference_month, deixando a ocorrência corrente intacta.
772
815
  - Valores em centavos.
773
- - Não suporta multa/juros no momento.
774
816
 
775
- EXEMPLO:
776
- { "occurrence_id": "uuid-da-ocorrencia", "amount_cents": 35000, "account_name": "Itaú", "payment_date": "2026-04-01" }`,
817
+ EXEMPLO — criar nova tx:
818
+ { "occurrence_id": "uuid", "amount_cents": 35000, "account_name": "Itaú", "payment_date": "2026-04-01" }
819
+
820
+ EXEMPLO — linkar a tx já importada do OFX:
821
+ { "occurrence_id": "uuid", "transaction_id": "uuid-da-tx-do-extrato" }
822
+
823
+ EXEMPLO — pagar com multa:
824
+ { "occurrence_id": "uuid", "amount_cents": 10000, "account_name": "C6", "fee_cents": 500 }
825
+
826
+ EXEMPLO — catch-up (pagou março junto com abril):
827
+ { "occurrence_id": "uuid-de-abril-qualquer", "amount_cents": 8000, "account_name": "C6", "is_catch_up": true, "catch_up_reference_month": "2026-03" }`,
777
828
  inputSchema: {
778
829
  type: "object",
779
830
  properties: {
780
831
  occurrence_id: { type: "string", description: "UUID da ocorrência (de fin_bills_do_mes)" },
781
- amount_cents: { type: "number", description: "Valor pago em centavos" },
782
- account_name: { type: "string", description: "Nome da conta" },
832
+ transaction_id: { type: "string", description: "UUID de uma transação já existente pra LINKAR em vez de criar nova." },
833
+ amount_cents: { type: "number", description: "Valor pago em centavos (obrigatório sem transaction_id)" },
834
+ account_name: { type: "string", description: "Nome da conta (obrigatório sem transaction_id)" },
783
835
  category_name: { type: "string", description: "Categoria (opcional, usa default da bill)" },
784
836
  subcategory_name: { type: "string", description: "Subcategoria (opcional)" },
785
837
  payment_date: { type: "string", description: "YYYY-MM-DD (default: hoje)" },
838
+ fee_cents: { type: "number", description: "Multa/juros em centavos. Cria 2ª transação em 'Taxas, Juros & Impostos > Multa'. Só no modo CRIAR." },
839
+ fee_category_name: { type: "string", description: "Sobrescreve categoria default da multa." },
840
+ fee_subcategory_name: { type: "string", description: "Sobrescreve subcategoria default da multa." },
841
+ is_catch_up: { type: "boolean", description: "True quando pagando ref. a um mês passado (precisa catch_up_reference_month)." },
842
+ catch_up_reference_month: { type: "string", description: "YYYY-MM — mês referência quando is_catch_up=true." },
786
843
  },
787
- required: ["occurrence_id", "amount_cents", "account_name"],
844
+ required: ["occurrence_id"],
788
845
  },
789
846
  },
790
847
  {
@@ -802,14 +859,21 @@ CAMPOS:
802
859
  - account_name: string — conta default de pagamento (match parcial).
803
860
  - category_name: string — categoria default.
804
861
  - subcategory_name: string — subcategoria default.
862
+ - notes: string — contexto livre (ex: "reajusta em janeiro", "plano expira dez/2026").
863
+ - tags: string[] — tags pra cortes ortogonais.
864
+ - review_after: YYYY-MM-DD — lembrete pra revisar essa bill depois dessa data.
865
+ - end_date: YYYY-MM-DD — último mês (inclusive) que gera ocorrência (ex: IPTU 10x até out/2026).
866
+ - max_occurrences: number — alternativa a end_date: para depois de N ocorrências geradas.
805
867
 
806
868
  REGRAS DE NEGÓCIO:
807
869
  - amount_type 'fixed' = valor fixo todo mês (ex: condomínio R$1.383).
808
870
  - amount_type 'variable' = valor muda (ex: Light). Definido no momento do pagamento.
871
+ - POST de bill já cria a ocorrência do mês atual e retorna em current_month_occurrence.
809
872
  - Valores em centavos.
810
873
 
811
874
  EXEMPLO:
812
- { "name": "Light", "due_day": 1, "amount_type": "variable", "category_name": "Moradia", "account_name": "Itaú" }`,
875
+ { "name": "Light", "due_day": 1, "amount_type": "variable", "category_name": "Moradia", "account_name": "Itaú" }
876
+ { "name": "IPTU", "due_day": 10, "amount_type": "fixed", "default_amount_cents": 38000, "end_date": "2026-10-10", "notes": "10x jan-out/2026" }`,
813
877
  inputSchema: {
814
878
  type: "object",
815
879
  properties: {
@@ -820,6 +884,11 @@ EXEMPLO:
820
884
  account_name: { type: "string", description: "Conta default de pagamento" },
821
885
  category_name: { type: "string", description: "Categoria default" },
822
886
  subcategory_name: { type: "string", description: "Subcategoria default" },
887
+ notes: { type: "string", description: "Contexto livre (max 2000 chars)." },
888
+ tags: { type: "array", items: { type: "string" }, description: "Tags livres (max 20)." },
889
+ review_after: { type: "string", description: "YYYY-MM-DD — lembrete pra revisar a bill." },
890
+ end_date: { type: "string", description: "YYYY-MM-DD — último mês que gera ocorrência." },
891
+ max_occurrences: { type: "number", description: "Para depois de N ocorrências geradas." },
823
892
  },
824
893
  required: ["name", "due_day"],
825
894
  },
@@ -832,18 +901,14 @@ QUANDO USAR: mudar configurações de uma conta existente ou desativar.
832
901
 
833
902
  CAMPOS:
834
903
  - bill_id: string UUID — ID da bill (obrigatório, obter via fin_listar_bills).
835
- - name: stringnovo nome.
836
- - due_day: numbernovo dia de vencimento (1-31).
837
- - amount_type: string'fixed' ou 'variable'.
838
- - default_amount_cents: number — novo valor padrão em centavos.
839
- - account_name: string — nova conta default.
840
- - category_name: string — nova categoria default.
841
- - subcategory_name: string — nova subcategoria default.
842
- - is_active: boolean — false para desativar (soft delete).
904
+ - name / due_day / amount_type / default_amount_cents / account_name / category_name / subcategory_name editáveis.
905
+ - is_active: booleanfalse para soft-delete (preserva histórico).
906
+ - notes / tags / review_after / end_date / max_occurrences editáveis (null pra limpar).
843
907
 
844
908
  REGRAS DE NEGÓCIO:
845
909
  - Campos omitidos não são alterados.
846
910
  - is_active: false desativa a bill (não gera novas ocorrências, mas mantém histórico).
911
+ - Pra HARD-delete (apagar de verdade) a bill, use fin_deletar_bill — só funciona se nenhuma ocorrência foi paga ainda.
847
912
  - Valores em centavos.`,
848
913
  inputSchema: {
849
914
  type: "object",
@@ -857,6 +922,11 @@ REGRAS DE NEGÓCIO:
857
922
  category_name: { type: "string", description: "Nova categoria default" },
858
923
  subcategory_name: { type: "string", description: "Nova subcategoria default" },
859
924
  is_active: { type: "boolean", description: "false para desativar" },
925
+ notes: { type: "string", description: "Contexto livre (null pra limpar)." },
926
+ tags: { type: "array", items: { type: "string" }, description: "Tags livres (null pra limpar)." },
927
+ review_after: { type: "string", description: "YYYY-MM-DD (null pra limpar)." },
928
+ end_date: { type: "string", description: "YYYY-MM-DD (null pra limpar)." },
929
+ max_occurrences: { type: "number", description: "Máximo de ocorrências (null pra limpar)." },
860
930
  },
861
931
  required: ["bill_id"],
862
932
  },
@@ -930,14 +1000,19 @@ CAMPOS:
930
1000
  - closing_day: number — novo dia de fechamento (1-28).
931
1001
  - due_day: number — novo dia de vencimento (1-28).
932
1002
  - credit_limit_cents: number — novo limite de crédito em centavos.
1003
+ - currency: string — 'BRL' ou 'USD'. SÓ FUNCIONA quando a conta não tem nenhuma transação vinculada. Se tiver, retorna 409 com transactions_count — caller deve deletar/mover as transações antes.
933
1004
 
934
1005
  REGRAS DE NEGÓCIO:
935
1006
  - Valores em centavos.
936
1007
  - Campos omitidos não são alterados.
937
1008
  - Use initial_invoice_date: null para remover o cutoff histórico de um cartão (caso transações antigas estejam aparecendo fora da fatura no app).
1009
+ - currency é imutável quando há transações.
938
1010
 
939
1011
  EXEMPLO — remover cutoff de um cartão criado errado:
940
- { "account_id": "uuid-do-cartao", "initial_invoice_date": null, "initial_invoice_amount_cents": 0 }`,
1012
+ { "account_id": "uuid-do-cartao", "initial_invoice_date": null, "initial_invoice_amount_cents": 0 }
1013
+
1014
+ EXEMPLO — corrigir moeda de uma conta recém-criada (sem transações):
1015
+ { "account_id": "uuid-da-conta", "currency": "USD" }`,
941
1016
  inputSchema: {
942
1017
  type: "object",
943
1018
  properties: {
@@ -951,6 +1026,7 @@ EXEMPLO — remover cutoff de um cartão criado errado:
951
1026
  closing_day: { type: "number", description: "Novo dia de fechamento (1-28)" },
952
1027
  due_day: { type: "number", description: "Novo dia de vencimento (1-28)" },
953
1028
  credit_limit_cents: { type: "number", description: "Novo limite de crédito em centavos" },
1029
+ currency: { type: "string", description: "'BRL' ou 'USD'. Só funciona se a conta não tem transações." },
954
1030
  },
955
1031
  required: ["account_id"],
956
1032
  },
@@ -1087,6 +1163,199 @@ REGRAS DE NEGÓCIO:
1087
1163
  required: ["subcategory_id"],
1088
1164
  },
1089
1165
  },
1166
+ // ── Bugs #17/#15/#16/#18-34 — new tools ───────────────────────────
1167
+ {
1168
+ name: "fin_patrimonio",
1169
+ description: `Retorna patrimônio consolidado multi-moeda (cash + checking) em uma moeda de exibição.
1170
+
1171
+ QUANDO USAR: responder "quanto eu tenho hoje no total em reais?" — pergunta básica de dashboard.
1172
+ NÃO USAR QUANDO: quiser ver saldos nativos por conta (usar fin_saldos).
1173
+
1174
+ CAMPOS:
1175
+ - display_currency: 'BRL' | 'USD' — moeda em que o total é exibido (default: BRL).
1176
+
1177
+ REGRAS DE NEGÓCIO:
1178
+ - Usa getBalanceService (mesmo dado de fin_saldos).
1179
+ - Converte USD→BRL via cotação 1h-cached (AwesomeAPI / exchangerate.host).
1180
+ - Se a cotação está off: retorna total BRL PARCIAL + partial: true + warning 'partial_total_exchange_rate_unavailable'.
1181
+ - Retorno: { as_of, display_currency, exchange_rates, total_cents, partial, breakdown_by_currency: { BRL: {...}, USD: {...} }, breakdown_by_account: [{ account_id, account_name, currency, balance_cents, balance_in_display_cents }] }
1182
+ - ATENÇÃO: essa tool usa cotação DINÂMICA. Pra transações individuais (gastos em dólar), o caller deve informar a cotação real paga — ver fin_criar_despesa.`,
1183
+ inputSchema: {
1184
+ type: "object",
1185
+ properties: {
1186
+ display_currency: { type: "string", description: "'BRL' (default) ou 'USD'." },
1187
+ },
1188
+ },
1189
+ },
1190
+ {
1191
+ name: "fin_criar_estorno",
1192
+ description: `Cria um estorno atômico de uma despesa. Rota canônica — chama POST /api/genius/reversals, que valida ownership e invariants atomicamente.
1193
+
1194
+ QUANDO USAR: quando já sabe o UUID da transação original que quer estornar (ex: achou via fin_buscar_transacoes ou fin_fatura_transacoes). A tool herda account/category/subcategory da original automaticamente.
1195
+ NÃO USAR QUANDO: quiser fazer uma nova despesa sem relação com estorno (usar fin_criar_despesa).
1196
+
1197
+ CAMPOS:
1198
+ - original_transaction_id: string UUID (obrigatório) — transação original.
1199
+ - amount_cents: number (obrigatório) — valor em centavos. Pode ser parcial (ex: 7216 de uma compra de 10000).
1200
+ - tx_date: YYYY-MM-DD — data do estorno (default: hoje).
1201
+ - description: string — descrição custom (default: "Estorno: <descrição original>").
1202
+
1203
+ REGRAS DE NEGÓCIO:
1204
+ - A original precisa ser tipo 'expense'. Retorna 422 senão.
1205
+ - amount_cents não pode exceder o valor da original. Retorna 422 se exceder.
1206
+ - reversal_kind é derivado: 'full' se amount == original, 'partial' senão.
1207
+ - account/category/subcategory são HERDADOS da original — sem precisar informar.
1208
+ - Retorna o mesmo shape de fin_criar_despesa.
1209
+
1210
+ EXEMPLO — estorno parcial:
1211
+ { "original_transaction_id": "uuid-original", "amount_cents": 7216, "description": "Devolução parcial defeito" }
1212
+
1213
+ EXEMPLO — estorno total:
1214
+ { "original_transaction_id": "uuid-original", "amount_cents": 10000 }`,
1215
+ inputSchema: {
1216
+ type: "object",
1217
+ properties: {
1218
+ original_transaction_id: { type: "string", description: "UUID da transação original" },
1219
+ amount_cents: { type: "number", description: "Valor do estorno em centavos (pode ser parcial)" },
1220
+ tx_date: { type: "string", description: "YYYY-MM-DD (default: hoje)" },
1221
+ description: { type: "string", description: "Descrição custom (default: 'Estorno: ...')" },
1222
+ },
1223
+ required: ["original_transaction_id", "amount_cents"],
1224
+ },
1225
+ },
1226
+ {
1227
+ name: "fin_classificar_linha_extrato",
1228
+ description: `Classifica uma linha de extrato bancário em uma das 5 categorias semânticas.
1229
+
1230
+ QUANDO USAR: em skills que importam OFX/CNAB/CSV e precisam decidir se cada linha é despesa, receita, transfer, pagamento de fatura, ou saque ATM. Evita reinventar heurística cliente-side.
1231
+ NÃO USAR QUANDO: a skill já sabe o tipo (ex: acabou de chamar fin_criar_despesa).
1232
+
1233
+ CAMPOS:
1234
+ - description: string (obrigatório) — descrição da linha do extrato.
1235
+ - amount_cents: number (obrigatório) — valor em centavos. Negativo = débito, positivo = crédito.
1236
+ - account_id: string UUID (obrigatório) — conta do extrato que está sendo importado.
1237
+ - trntype: string — hint OFX (ATM, XFER, PAYMENT, DEBIT, CREDIT). Opcional.
1238
+ - fitid: string — FITID OFX, pass-through no retorno pra idempotência.
1239
+
1240
+ REGRAS DE NEGÓCIO:
1241
+ - Retorna { type, confidence, reason, details, from_account_id, from_account_name, fitid }
1242
+ - type ∈ { 'expense', 'income', 'transfer', 'payment_invoice', 'atm_withdrawal' }
1243
+ - details:
1244
+ - atm_withdrawal → { suggested_cash_account_id: UUID pra conta "Dinheiro" se existir }
1245
+ - payment_invoice → { suggested_card_account_id: UUID do cartão se der pra adivinhar pelo nome na descrição }
1246
+ - transfer → { suggested_counterparty_account_id: UUID da outra conta do user se bateu pelo nome }
1247
+ - expense/income → {}
1248
+ - O caller orquestra: recebe a classificação e chama fin_criar_despesa / fin_criar_transferencia / fin_pagar_fatura conforme.
1249
+ - Matching de nomes de conta tem blocklist de palavras genéricas (PIX, TED, DOC, etc) pra evitar falso positivo.
1250
+
1251
+ EXEMPLO:
1252
+ { "description": "SAQUE 24H BANCO X", "amount_cents": -20000, "account_id": "uuid-c6", "trntype": "ATM" }
1253
+ → { type: "atm_withdrawal", confidence: "high", details: { suggested_cash_account_id: "uuid-dinheiro" } }`,
1254
+ inputSchema: {
1255
+ type: "object",
1256
+ properties: {
1257
+ description: { type: "string" },
1258
+ amount_cents: { type: "number", description: "Centavos (negativo = débito, positivo = crédito)" },
1259
+ account_id: { type: "string", description: "UUID da conta sendo importada" },
1260
+ trntype: { type: "string", description: "Hint OFX (ATM, XFER, PAYMENT, DEBIT, CREDIT)" },
1261
+ fitid: { type: "string", description: "FITID OFX, pass-through no retorno" },
1262
+ },
1263
+ required: ["description", "amount_cents", "account_id"],
1264
+ },
1265
+ },
1266
+ {
1267
+ name: "fin_criar_transacoes_batch",
1268
+ description: `Cria múltiplas transações (despesa/receita/transferência) em uma única chamada. Max 100 por batch.
1269
+
1270
+ QUANDO USAR:
1271
+ - Conciliação de extrato com várias transações que não passaram pelo parser automático.
1272
+ - Lançamento em lote de parcelas avulsas (ex: várias compras parceladas antigas).
1273
+ - Qualquer cenário que geraria N chamadas individuais de criar_despesa/criar_receita/criar_transferencia.
1274
+ NÃO USAR QUANDO: uma única transação atômica com rollback é necessária (essa tool é "partial success by design").
1275
+
1276
+ CAMPOS:
1277
+ - transactions: array — cada item é um objeto com type + campos do tipo correspondente. Discriminated union:
1278
+ - { type: "expense", amount_cents, description, account_name?, category_name?, subcategory_name?, tx_date?, essential?, invoice_cycle_end?, tags? }
1279
+ - { type: "income", amount_cents, description, account_name?, category_name?, subcategory_name?, tx_date?, tags? }
1280
+ - { type: "transfer", amount_cents, description, account_from, account_to, tx_date? }
1281
+
1282
+ REGRAS DE NEGÓCIO:
1283
+ - Loop sequencial (não-transacional). Falha no meio NÃO reverte as anteriores.
1284
+ - Resposta: { ok: true, total, created: [{ index, transaction_id, type }], failed: [{ index, error }] }.
1285
+ - Caller decide o que fazer com 'failed' (retry, logar, abortar).
1286
+ - Max 100 rows por chamada pra limitar memória de request.
1287
+
1288
+ EXEMPLO:
1289
+ {
1290
+ "transactions": [
1291
+ { "type": "expense", "amount_cents": 5000, "description": "Almoço", "account_name": "C6" },
1292
+ { "type": "income", "amount_cents": 500000, "description": "Salário", "account_name": "Itaú" },
1293
+ { "type": "transfer", "amount_cents": 10000, "description": "pra poupança", "account_from": "C6", "account_to": "Poupança" }
1294
+ ]
1295
+ }`,
1296
+ inputSchema: {
1297
+ type: "object",
1298
+ properties: {
1299
+ transactions: {
1300
+ type: "array",
1301
+ description: "Lista de transações a criar (max 100)",
1302
+ items: { type: "object" },
1303
+ },
1304
+ },
1305
+ required: ["transactions"],
1306
+ },
1307
+ },
1308
+ {
1309
+ name: "fin_deletar_bill",
1310
+ description: `Hard-delete de uma bill recorrente. Só funciona se NENHUMA ocorrência foi paga.
1311
+
1312
+ QUANDO USAR: remover bill criada por engano (nome/categoria errada) antes de qualquer pagamento.
1313
+ NÃO USAR QUANDO: a bill já tem ocorrências pagas — use fin_editar_bill com is_active: false (soft-delete, preserva histórico).
1314
+
1315
+ CAMPOS:
1316
+ - bill_id: string UUID (obrigatório).
1317
+
1318
+ REGRAS DE NEGÓCIO:
1319
+ - Se a bill tem ≥1 ocorrência com transaction_id != null, retorna 409 com soft_delete_hint.
1320
+ - Ocorrências NÃO pagas são deletadas em cascata (FK ON DELETE CASCADE).`,
1321
+ inputSchema: {
1322
+ type: "object",
1323
+ properties: {
1324
+ bill_id: { type: "string", description: "UUID da bill" },
1325
+ },
1326
+ required: ["bill_id"],
1327
+ },
1328
+ },
1329
+ {
1330
+ name: "fin_editar_occurrence",
1331
+ description: `Edita uma ocorrência específica de bill (amount_cents, due_date, notes) sem alterar o template mãe.
1332
+
1333
+ QUANDO USAR:
1334
+ - Bill 'fixed' teve valor diferente em UM mês (multa, reajuste retroativo).
1335
+ - Data de vencimento mudou num mês específico (feriado, dia não-útil).
1336
+ - Anotar contexto local (ex: "pago com desconto pontual").
1337
+ NÃO USAR QUANDO: quiser mudar o default permanente da bill (usar fin_editar_bill).
1338
+
1339
+ CAMPOS:
1340
+ - occurrence_id: string UUID (obrigatório).
1341
+ - amount_cents: number — novo valor em centavos.
1342
+ - due_date: string YYYY-MM-DD — novo dia de vencimento.
1343
+ - notes: string | null — anotação livre (null pra limpar).
1344
+
1345
+ REGRAS DE NEGÓCIO:
1346
+ - Se a ocorrência já foi paga (tem transaction_id) e você tenta editar amount_cents: retorna 409 (a transação é a fonte da verdade; use fin_editar_transacao).
1347
+ - Outros campos podem ser editados mesmo em ocorrência paga.`,
1348
+ inputSchema: {
1349
+ type: "object",
1350
+ properties: {
1351
+ occurrence_id: { type: "string", description: "UUID da ocorrência" },
1352
+ amount_cents: { type: "number", description: "Novo valor em centavos" },
1353
+ due_date: { type: "string", description: "YYYY-MM-DD" },
1354
+ notes: { type: ["string", "null"], description: "Anotação livre (null pra limpar)" },
1355
+ },
1356
+ required: ["occurrence_id"],
1357
+ },
1358
+ },
1090
1359
  ];
1091
1360
 
1092
1361
  // ── Tool handlers ───────────────────────────────────────────────────
@@ -1200,7 +1469,10 @@ async function handleTool(name, args) {
1200
1469
  return ok(await api("GET", `/api/genius/bills`));
1201
1470
  }
1202
1471
  case "fin_bills_do_mes": {
1203
- const qs = args.month ? `?month=${args.month}` : "";
1472
+ const params = new URLSearchParams();
1473
+ if (args.month) params.set("month", args.month);
1474
+ if (args.status) params.set("status", args.status);
1475
+ const qs = params.toString() ? `?${params}` : "";
1204
1476
  return ok(await api("GET", `/api/genius/bills/occurrences${qs}`));
1205
1477
  }
1206
1478
  case "fin_pagar_bill": {
@@ -1261,6 +1533,27 @@ async function handleTool(name, args) {
1261
1533
  const { subcategory_id, ...body } = args;
1262
1534
  return ok(await api("PATCH", `/api/genius/subcategories/${subcategory_id}`, body));
1263
1535
  }
1536
+ // ── Bugs #17/#15/#16/#18-34 — new tool handlers ───────────────
1537
+ case "fin_patrimonio": {
1538
+ const qs = args.display_currency ? `?display_currency=${args.display_currency}` : "";
1539
+ return ok(await api("GET", `/api/genius/patrimony${qs}`));
1540
+ }
1541
+ case "fin_criar_estorno": {
1542
+ return ok(await api("POST", `/api/genius/reversals`, args));
1543
+ }
1544
+ case "fin_classificar_linha_extrato": {
1545
+ return ok(await api("POST", `/api/genius/classify-statement-line`, args));
1546
+ }
1547
+ case "fin_criar_transacoes_batch": {
1548
+ return ok(await api("POST", `/api/genius/transactions/batch`, args));
1549
+ }
1550
+ case "fin_deletar_bill": {
1551
+ return ok(await api("DELETE", `/api/genius/bills/${args.bill_id}`));
1552
+ }
1553
+ case "fin_editar_occurrence": {
1554
+ const { occurrence_id, ...body } = args;
1555
+ return ok(await api("PATCH", `/api/genius/bills/occurrences/${occurrence_id}`, body));
1556
+ }
1264
1557
  default:
1265
1558
  return err(`Tool desconhecida: ${name}`);
1266
1559
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fin-app-mcp",
3
- "version": "2.3.3",
3
+ "version": "3.0.0",
4
4
  "description": "MCP server para o FIN App — finanças pessoais. Expõe tools para agents LLM operarem contas, despesas, faturas de cartão, bills recorrentes e mais.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",