Finanpy

Finanpy

MCP server for personal finance management that connects a SQLite database to any MCP client, allowing users to register, query, and analyze financial transactions through natural language.

Category
访问服务器

README

💰 Finanpy — MCP Server de Finanças Pessoais

Finanpy é um servidor MCP (Model Context Protocol) para análise e gestão de finanças pessoais. Ele conecta um banco de dados SQLite a qualquer cliente MCP compatível, permitindo registrar, consultar e analisar transações financeiras através de linguagem natural.


📁 Estrutura do Projeto

.
├── finance.db          # Banco de dados SQLite com as transações
├── database.py         # Camada de acesso ao banco de dados
├── mcp_server.py       # Servidor MCP com as ferramentas expostas
├── import_csv.py       # Script para importar extratos do Nubank (CSV)
└── sample_agent.py     # Agente de exemplo com LangChain + LangGraph

🗄️ Banco de Dados

O projeto utiliza SQLite com uma única tabela principal:

Tabela transactions

Coluna Tipo Descrição
id INTEGER Chave primária, autoincremento
identifier TEXT Identificador único da transação (evita duplicatas)
type TEXT Tipo da transação: receita ou despesa
amount REAL Valor da transação (negativo para despesas)
category TEXT Categoria da transação (padrão: sem categoria)
description TEXT Descrição ou histórico da transação
date TEXT Data da transação em ISO 8601: YYYY-MM-DD

Timezone: todas as datas são armazenadas em horário local (America/Sao_Paulo). Não há offset UTC explícito no banco.
Arredondamento: valores monetários são armazenados como REAL com 2 casas decimais, usando arredondamento half-up no momento da inserção.


⚙️ Instalação

Pré-requisitos

  • Python 3.10+
  • uv

Dependências

uv add fastmcp

Para utilizar o agente de exemplo (sample_agent.py), instale também:

uv add langchain-openai langchain-mcp-adapters langgraph python-dotenv

Configuração

  1. Clone o repositório.
  2. Inicialize o banco de dados:
python database.py
  1. (Opcional) Importe um extrato do Nubank:
# Coloque o arquivo CSV exportado do Nubank na raiz do projeto:
# extrato_nubank_05_2026.csv
python import_csv.py

🚀 Executando o Servidor MCP

python mcp_server.py

Transporte STDIO

O Finanpy utiliza transporte STDIO: o cliente MCP inicia o servidor como um processo filho e se comunica com ele via stdin/stdout usando o protocolo MCP. Não há porta de rede envolvida.

Fluxo de inicialização:

  1. O client executa python mcp_server.py como subprocesso.
  2. O servidor anuncia suas capacidades (tools, resources) via protocolo MCP pelo stdout.
  3. O client recebe o manifesto e passa a chamar ferramentas ou consultar recursos conforme necessário.
  4. O processo do servidor vive enquanto o client estiver ativo e é encerrado junto com ele.

Quando o client decide chamar cada ferramenta/recurso:

  • Consulta resumo_financeiro_atual (recurso) para orientar o raciocínio antes de responder perguntas sobre saldo ou categorias.
  • Chama registrar_transacao quando o usuário pede para registrar, lançar ou salvar uma transação.
  • Chama listar_transacoes quando o usuário pede consultas, históricos ou totais por período/categoria.

🔧 Ferramentas e Recursos MCP

Ferramenta 1 — registrar_transacao

Registra uma nova transação financeira no banco de dados de forma idempotente.

Entradas:

Parâmetro Tipo Obrigatório Descrição
type string ✅ "receita" ou "despesa"
amount float ✅ Valor absoluto da transação (sempre positivo; o sinal é inferido do type)
category string ✅ Categoria (ex: "alimentacao", "transporte", "moradia")
description string ✅ Texto livre descrevendo a transação
date string ❌ Data em ISO 8601 YYYY-MM-DD (padrão: data atual)
identifier string ❌ UUID ou chave externa para idempotência (ex: ID do extrato bancário)

Saída (sucesso):

{
  "sucesso": true,
  "id": 42,
  "normalizado": {
    "amount": 73.90,
    "date": "2026-06-23",
    "type": "despesa"
  },
  "avisos": []
}

Saída (duplicata detectada):

{
  "sucesso": false,
  "code": "DUPLICATE",
  "id_existente": 17,
  "mensagem": "Transação com este identifier já existe."
}

Erros e limites:

Código Causa O que o client deve fazer
INVALID_DATE Data fora do formato ISO 8601 ou data futura Corrigir o formato para YYYY-MM-DD antes de reenviar
DUPLICATE identifier já existe no banco Informar o usuário; não reenviar
BAD_TYPE type diferente de "receita" ou "despesa" Normalizar para um dos dois valores antes de reenviar
INVALID_AMOUNT amount negativo, zero ou não numérico Solicitar o valor correto ao usuário; nunca inferir
DB_BUSY SQLite travado por operação concorrente Retry com backoff exponencial: 200ms, 400ms, 800ms (máx. 3x)
MISSING_FIELD Campo obrigatório ausente Solicitar o campo faltante ao usuário antes de reenviar

Atenção — sinal vs. tipo: nunca envie amount negativo com type="despesa". O servidor armazena despesas com sinal negativo internamente; a entrada esperada é sempre o valor absoluto. Se o client receber amount negativo do usuário junto com type="despesa", deve aplicar abs(amount) antes de chamar a ferramenta.


Ferramenta 2 — listar_transacoes

Lista e filtra transações financeiras armazenadas no banco.

Entradas:

Parâmetro Tipo Obrigatório Descrição
period string ❌ Período no formato YYYY-MM (ex: "2026-05")
category string ❌ Filtra pelo nome exato da categoria
type string ❌ "receita" ou "despesa"

Saída (sucesso):

[
  {
    "id": 1,
    "identifier": "69fa0c39-ca20-4683-849a-85519872249a",
    "type": "receita",
    "amount": 50.0,
    "category": "sem categoria",
    "description": "Resgate RDB",
    "date": "2026-05-05"
  }
]

Retorna uma lista vazia [] quando nenhum registro corresponde aos filtros (não é um erro).

Erros e limites:

Código Causa O que o client deve fazer
INVALID_PERIOD Formato de período inválido (ex: "05-2026") Corrigir para YYYY-MM antes de reenviar
BAD_TYPE type diferente de "receita" ou "despesa" Normalizar antes de reenviar
DB_BUSY SQLite travado por operação concorrente Retry com backoff exponencial: 200ms, 400ms, 800ms (máx. 3x)

Janela recomendada: evite consultar períodos superiores a 12 meses sem filtro de categoria, pois o retorno pode ser extenso. Prefira decompor em múltiplas chamadas mensais se necessário.


Recurso MCP — resumo_financeiro_atual

URI: finance://resumo_financeiro_atual

Recurso somente-leitura que retorna um snapshot consolidado das finanças do mês corrente. Diferente das ferramentas (que executam ações), este recurso é consultado pelo agente para orientar seu raciocínio antes de responder perguntas sobre saldo, categorias e situação financeira geral — evitando chamadas desnecessárias a listar_transacoes.

Saída:

{
  "period": "2026-06",
  "total_income": 9947.94,
  "total_expense": 9947.94,
  "balance": 0.0,
  "expenses_by_category": {
    "sem categoria": 9947.94
  }
}

Quando o client deve consultá-lo:

  • Antes de responder qualquer pergunta sobre saldo atual, total gasto ou total recebido no mês.
  • Para verificar se há dados suficientes antes de sugerir categorias ao usuário.
  • Como ponto de partida para decidir se é necessário chamar listar_transacoes com filtros mais específicos.

📥 Importação de Extrato do Nubank

O script import_csv.py importa automaticamente transações a partir do CSV exportado pelo aplicativo do Nubank.

Formato esperado do CSV:

Data Valor Identificador Descrição
05/05/2026 -50.00 69fa0c7e-... Transferência Pix
06/05/2026 188.03 69fbee60-... Resgate RDB

O tipo da transação é derivado automaticamente pelo sinal do valor:

  • Valor negativo → despesa
  • Valor positivo → receita

Transações com identifier já existente são ignoradas automaticamente (idempotência via INSERT OR IGNORE).

Categorias: todas as transações importadas via CSV chegam como "sem categoria". Use o agente para categorizá-las após a importação.


🔄 Cenário de Uso Ponta a Ponta

Mensagem do usuário:

"Quanto gastei em alimentação em maio de 2026? E registra aí um Uber de R$ 73,90 que peguei hoje."

Raciocínio do agente:

  1. A pergunta envolve o mês atual — consultar o recurso resumo_financeiro_atual para ter contexto geral antes de filtrar.
  2. Para o total de alimentação em maio, chamar listar_transacoes com filtros de período e categoria.
  3. Para registrar o Uber, chamar registrar_transacao com os dados fornecidos.

Passo 1 — Consulta ao recurso resumo_financeiro_atual

GET finance://resumo_financeiro_atual

Resposta do servidor:

{
  "period": "2026-06",
  "total_income": 1835.29,
  "total_expense": 462.75,
  "balance": 1372.54,
  "expenses_by_category": {
    "sem categoria": 462.75
  }
}

O agente identifica que o mês atual é junho — a pergunta é sobre maio, então precisa de uma chamada específica.


Passo 2 — Chamada à ferramenta listar_transacoes

{
  "period": "2026-05",
  "category": "alimentacao",
  "type": "despesa"
}

Resposta do servidor:

[
  {
    "id": 8,
    "identifier": "nubank-2026-05-12-ifood",
    "type": "despesa",
    "amount": -49.90,
    "category": "alimentacao",
    "description": "iFood - Pizza",
    "date": "2026-05-12"
  },
  {
    "id": 15,
    "identifier": "nubank-2026-05-22-mercado",
    "type": "despesa",
    "amount": -312.40,
    "category": "alimentacao",
    "description": "Mercado Extra",
    "date": "2026-05-22"
  }
]

Total calculado pelo agente: R$ 362,30.


Passo 3 — Chamada à ferramenta registrar_transacao

{
  "type": "despesa",
  "amount": 73.90,
  "category": "transporte",
  "description": "Uber",
  "date": "2026-06-23",
  "identifier": "manual-2026-06-23-uber-001"
}

Resposta do servidor:

{
  "sucesso": true,
  "id": 27,
  "normalizado": {
    "amount": 73.90,
    "date": "2026-06-23",
    "type": "despesa"
  },
  "avisos": []
}

Resposta final ao usuário:

"Em maio de 2026 você gastou R$ 362,30 em alimentação (iFood R$ 49,90 + Mercado Extra R$ 312,40). Sua despesa de Uber de R$ 73,90 foi registrada em transporte para hoje, 23/06/2026. ✅"


🤖 Agente de Exemplo

O arquivo sample_agent.py demonstra como integrar o servidor MCP com um agente LangChain + LangGraph usando GPT-4o-mini como modelo de linguagem, via transporte STDIO.

Configuração

Crie um arquivo .env na raiz do projeto:

OPENAI_API_KEY=sua_chave_aqui

Executando o agente

python sample_agent.py

Exemplo de interação real:

Finanpy - Assistente Financeiro Pessoal
Digite 'sair' para encerrar.

Você: Poderia categorizar as minhas transações realizadas? E também fazer uma somatória transacionada para cada categoria?

Finanpy: processando...

Finanpy: Aqui está a categorização das suas transações e a somatória para cada categoria:

### Receitas
1. Resgate RDB: R$ 50,00
2. Resgate RDB: R$ 188,03
...
**Total de Receitas**: R$ 9.882,74

### Despesas
1. Transferência enviada pelo Pix: R$ -50,00
...
**Total de Despesas**: R$ -10.188,84

🧩 Integração com Claude Desktop

Para usar o Finanpy diretamente no Claude Desktop, adicione ao arquivo de configuração do MCP (claude_desktop_config.json):

{
  "mcpServers": {
    "finanpy": {
      "command": "python",
      "args": ["/caminho/absoluto/para/mcp_server.py"]
    }
  }
}

O campo "transport" pode ser omitido — o Claude Desktop usa STDIO por padrão. Use o caminho absoluto para o mcp_server.py para evitar erros de working directory.

Após reiniciar o Claude Desktop, as ferramentas e recursos do Finanpy estarão disponíveis automaticamente.


🔒 Segurança e Privacidade

  • Dados sensíveis (PII): o banco contém informações financeiras pessoais, incluindo descrições de transações que podem conter nomes de pessoas (ex: transferências Pix). Não compartilhe o arquivo finance.db publicamente.
  • Logs: evite ativar logging detalhado em produção, pois descrições de transações podem aparecer nos logs. Em desenvolvimento, use nível WARNING ou superior.
  • Acesso ao banco: o SQLite não tem autenticação nativa. Garanta que o arquivo finance.db tenha permissões restritas ao usuário do sistema que executa o servidor (chmod 600 finance.db).
  • Variáveis de ambiente: nunca comite o arquivo .env com chaves de API no repositório. Adicione-o ao .gitignore.

📌 Observações Técnicas

  • Datas: o campo date é armazenado como texto em formato YYYY-MM-DD (ISO 8601). Entradas no formato DD/MM/YYYY (como as do CSV do Nubank) são convertidas internamente. O client deve sempre enviar datas em ISO 8601.
  • Categorias: não há validação de categoria no servidor — qualquer string é aceita. Para padronizar, consulte o recurso resumo_financeiro_atual para ver as categorias já existentes antes de registrar uma nova transação.
  • Idempotência: o campo identifier garante que a mesma transação não seja inserida duas vezes (INSERT OR IGNORE). Ao importar extratos, use sempre o ID original do banco como identifier.
  • Concorrência: SQLite não suporta múltiplos escritores simultâneos. Se múltiplos agentes estiverem ativos, implemente retry com backoff exponencial em caso de DB_BUSY.
  • Banco de dados: o arquivo finance.db é criado automaticamente na raiz do projeto ao executar database.py ou mcp_server.py.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选