next-finance-mcp 0.9.2 → 0.9.4
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/dist/client.js +43 -20
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -377,9 +377,11 @@ function slimConta(c) {
|
|
|
377
377
|
const _id = o["Id"] ?? o["IdConta"] ?? o["id"] ?? o["idConta"];
|
|
378
378
|
const _idTipo = o["IdTipoConta"];
|
|
379
379
|
// Nível 1 — Moeda (ex: "BRL", "USD")
|
|
380
|
+
// REST retorna NomeMoeda; web retorna apenas IdMoeda (moeda tratada como vazia no fallback)
|
|
380
381
|
const moeda = String(o["NomeMoeda"] ?? o["Moeda"] ?? o["SiglaMoeda"] ?? o["CodigoMoeda"] ?? "").trim();
|
|
381
382
|
// Nível 2 — Portfolio (ex: "Tesouraria", "Renda Variável", "Previdência")
|
|
382
|
-
|
|
383
|
+
// REST e web usam NomeTipoPortfolio
|
|
384
|
+
const portfolio = String(o["NomeTipoPortfolio"] ?? o["NomePortfolio"] ?? o["Portfolio"] ?? o["NomeGrupo"] ?? o["Grupo"] ?? "").trim();
|
|
383
385
|
// Nível 3 — Tipo de Conta (ex: "Conta Corrente", "Ações", "CDB")
|
|
384
386
|
let tipoConta = String(o["NomeTipoConta"] ?? "").trim();
|
|
385
387
|
if (!tipoConta && o["TipoConta"] && typeof o["TipoConta"] === "object") {
|
|
@@ -388,7 +390,7 @@ function slimConta(c) {
|
|
|
388
390
|
// Nível 4 — Nome da Conta
|
|
389
391
|
const nome = String(o["Nome"] ?? o["NomeConta"] ?? o["Descricao"] ?? "").trim();
|
|
390
392
|
const slim = {};
|
|
391
|
-
// Campos internos (nunca
|
|
393
|
+
// Campos internos (prefixo _, nunca exibidos ao usuário final)
|
|
392
394
|
if (_id !== undefined)
|
|
393
395
|
slim["_id"] = _id;
|
|
394
396
|
if (_idTipo !== undefined)
|
|
@@ -402,17 +404,35 @@ function slimConta(c) {
|
|
|
402
404
|
slim["tipo_conta"] = tipoConta;
|
|
403
405
|
if (nome)
|
|
404
406
|
slim["nome"] = nome;
|
|
405
|
-
// Campos financeiros extras
|
|
407
|
+
// Campos financeiros extras — REST e web usam campos diferentes
|
|
406
408
|
if (o["Saldo"] !== undefined && o["Saldo"] !== null)
|
|
407
409
|
slim["saldo"] = o["Saldo"];
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (
|
|
411
|
-
slim["
|
|
412
|
-
|
|
413
|
-
|
|
410
|
+
// Banco: REST = NomeBanco, web = NomeBanco também
|
|
411
|
+
const banco = o["NomeBanco"] ?? o["Banco"];
|
|
412
|
+
if (banco && typeof banco === "string" && banco.trim())
|
|
413
|
+
slim["banco"] = banco.trim();
|
|
414
|
+
// Agência: REST = NumeroAgencia, web = NumeroAgencia também
|
|
415
|
+
const agencia = o["NumeroAgencia"] ?? o["Agencia"];
|
|
416
|
+
if (agencia && typeof agencia === "string" && agencia.trim())
|
|
417
|
+
slim["agencia"] = agencia.trim();
|
|
418
|
+
// Conta bancária: REST = NumeroContaBancaria + DigitoContaBancaria, web = NumeroContaBancaria
|
|
419
|
+
const numConta = o["NumeroContaBancaria"] ?? o["Numero"];
|
|
420
|
+
const digConta = o["DigitoContaBancaria"];
|
|
421
|
+
if (numConta && typeof numConta === "string" && numConta.trim()) {
|
|
422
|
+
slim["numero"] = digConta ? `${numConta.trim()}-${String(digConta).trim()}` : numConta.trim();
|
|
423
|
+
}
|
|
414
424
|
return slim;
|
|
415
425
|
}
|
|
426
|
+
/** Retorna true se a conta está ativa (não encerrada). */
|
|
427
|
+
function isContaAtiva(c) {
|
|
428
|
+
// Encerrada === true → conta encerrada (campo presente em REST e web)
|
|
429
|
+
if (c["Encerrada"] === true)
|
|
430
|
+
return false;
|
|
431
|
+
// Ativo === false → inativa (campo legado, só em alguns endpoints)
|
|
432
|
+
if (c["Ativo"] === false)
|
|
433
|
+
return false;
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
416
436
|
/** Tenta endpoints em ordem até encontrar um que responda com dados */
|
|
417
437
|
async function fetchContas() {
|
|
418
438
|
// Todos os endpoints REST agora apontam para api.finance.net.br via apiGet()
|
|
@@ -446,8 +466,8 @@ async function fetchContas() {
|
|
|
446
466
|
}
|
|
447
467
|
export async function listarContas(filtro = {}) {
|
|
448
468
|
const { contas: raw } = await fetchContas();
|
|
449
|
-
// Apenas contas ativas (
|
|
450
|
-
const ativas = raw.filter(c => c
|
|
469
|
+
// Apenas contas ativas (Encerrada !== true e Ativo !== false)
|
|
470
|
+
const ativas = raw.filter(c => isContaAtiva(c));
|
|
451
471
|
let contas = ativas.map(slimConta);
|
|
452
472
|
// Nível 4 — filtro por nome da conta
|
|
453
473
|
if (filtro.busca?.trim()) {
|
|
@@ -826,13 +846,18 @@ export async function buscarLancamentos(opts) {
|
|
|
826
846
|
if (opts.nomeConta?.trim()) {
|
|
827
847
|
const { contas } = await fetchContas();
|
|
828
848
|
const termo = opts.nomeConta.trim().toLowerCase();
|
|
829
|
-
const
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
849
|
+
const ativas = contas.map(c => c).filter(isContaAtiva);
|
|
850
|
+
const matches = ativas.filter(c => String(c["Nome"] ?? c["NomeConta"] ?? "").toLowerCase().includes(termo));
|
|
851
|
+
if (matches.length === 0) {
|
|
852
|
+
throw new Error(`Conta "${opts.nomeConta}" não encontrada. Use listar_contas para ver as contas disponíveis.`);
|
|
853
|
+
}
|
|
854
|
+
// Preferir match exato; se ainda ambíguo, listar as opções
|
|
855
|
+
const exata = matches.find(c => String(c["Nome"] ?? c["NomeConta"] ?? "").toLowerCase() === termo);
|
|
856
|
+
const encontrada = exata ?? (matches.length === 1 ? matches[0] : null);
|
|
857
|
+
if (!encontrada) {
|
|
858
|
+
const nomes = matches.map(c => String(c["Nome"] ?? c["NomeConta"] ?? "")).join(", ");
|
|
859
|
+
throw new Error(`"${opts.nomeConta}" corresponde a ${matches.length} contas: ${nomes}. Informe um nome mais específico.`);
|
|
860
|
+
}
|
|
836
861
|
idContaResolvido = String(encontrada["Id"] ?? encontrada["IdConta"] ?? encontrada["id"] ?? encontrada["idConta"] ?? "");
|
|
837
862
|
}
|
|
838
863
|
let lancamentos;
|
|
@@ -863,8 +888,6 @@ export async function buscarLancamentos(opts) {
|
|
|
863
888
|
if (r.status !== 200)
|
|
864
889
|
throw new Error(`Erro ${r.status} ao buscar lançamentos (endpoint legado).`);
|
|
865
890
|
const raw = JSON.parse(r.text);
|
|
866
|
-
// O endpoint legado retorna { Lancamentos: [...], SaldosPorMes: [...], ... }
|
|
867
|
-
// Extraímos explicitamente o campo Lancamentos para não confundir com SaldosPorMes
|
|
868
891
|
if (Array.isArray(raw)) {
|
|
869
892
|
lancamentos = raw;
|
|
870
893
|
}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
8
8
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
9
9
|
import * as client from "./client.js";
|
|
10
10
|
import { openLoginUI } from "./login-server.js";
|
|
11
|
-
const server = new Server({ name: "next-finance-mcp", version: "0.9.
|
|
11
|
+
const server = new Server({ name: "next-finance-mcp", version: "0.9.4" }, { capabilities: { tools: {} } });
|
|
12
12
|
// ── Ferramentas ─────────────────────────────────────────────────────────────
|
|
13
13
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
14
14
|
tools: [
|
|
@@ -361,6 +361,6 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
361
361
|
async function main() {
|
|
362
362
|
const transport = new StdioServerTransport();
|
|
363
363
|
await server.connect(transport);
|
|
364
|
-
console.error("NEXT Finance MCP server v0.9.
|
|
364
|
+
console.error("NEXT Finance MCP server v0.9.3 iniciado.");
|
|
365
365
|
}
|
|
366
366
|
main().catch((err) => { console.error("Erro fatal:", err); process.exit(1); });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-finance-mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"mcpName": "io.github.paivapiovesan/next-finance",
|
|
5
5
|
"description": "MCP Server para o NEXT Finance (finance.net.br) — login via browser, listagem de carteiras, contas e lançamentos",
|
|
6
6
|
"type": "module",
|