Actual Budget MCP

Servidor MCP Docker que conecta Claude Desktop/LibreChat/LobeChat ao Actual Budget para orçamento em linguagem natural, gerenciamento de transações e insights financeiros.

Documentação

Actual MCP Server icon

Servidor Actual MCP

npm version npm downloads License: MIT Node.js Version TypeScript MCP Protocol Docker Pulls Docker Image Size Unraid Community Apps GitHub Actions CI GitHub stars

Converse com seu orçamento. Execute em qualquer lugar. Confie em produção.

O Actual MCP Server é um servidor Model Context Protocol que conecta qualquer assistente de IA compatível com MCP (como LibreChat, LobeChat, Claude Desktop e outros) diretamente à sua instância auto-hospedada do Actual Budget. Faça perguntas em linguagem natural, crie transações, analise gastos e gerencie todo o seu orçamento sem nunca abrir a interface do Actual Budget.

┌─────────────┐   MCP/HTTP    ┌──────────────────┐   Actual API   ┌──────────────┐
│  LibreChat  │ ◄───────────► │  Actual MCP      │ ◄───────────► │   Actual     │
│  LobeChat   │               │  Server          │               │   Budget     │
│  (remote)   │               │  (84 tools)      │               │   Server     │
└─────────────┘               └──────────────────┘               └──────────────┘

┌─────────────┐   MCP/stdio   ┌──────────────────┐   Actual API   ┌──────────────┐
│  Claude     │ ◄───────────► │  Actual MCP      │ ◄───────────► │   Actual     │
│  Desktop    │               │  Server          │               │   Budget     │
│  (local)    │               │  (84 tools)      │               │   Server     │
└─────────────┘               └──────────────────┘               └──────────────┘

Por que este projeto?

A maioria das implementações de MCP para Actual Budget são pontes stdio simples, projetadas para uso local de usuário único com Claude Desktop. Este projeto vai além:

  • 84 ferramentas, a cobertura mais abrangente disponível. Contas, transações, categorias, beneficiários, tags, notas, regras, orçamentos, operações em lote, sincronização bancária e muito mais. Cobre a API acessível do Actual Budget sem lacunas reais.
  • Transporte HTTP e stdio. Funciona como um servidor remoto real para LibreChat/LobeChat (--http), ou como um processo local direto para Claude Desktop (--stdio). Nenhum Docker ou servidor HTTP é necessário para uso local.
  • 6 ferramentas exclusivas com tecnologia ActualQL. Pesquise e resuma transações por mês, valor, categoria ou beneficiário usando o mecanismo de consulta nativo do Actual Budget. Resultados agregados, sem dados brutos despejados na janela de contexto da IA.
  • Alternância de múltiplos orçamentos em tempo de execução. Configure vários arquivos de orçamento e deixe a IA alternar entre eles no meio da conversa com actual_budgets_switch. Funciona em ambos os transportes: HTTP vincula o orçamento ativo à sessão MCP, e stdio (Claude Desktop, Claude Code, Cursor) obtém uma sessão sintética por processo, de modo que uma alternância é limitada àquele processo em vez de compartilhada globalmente (#348).
  • Pronto para múltiplos usuários com OIDC. Proteja cada sessão com JWTs validados por JWKS e ACLs de orçamento por usuário. Nenhum token compartilhado é necessário.
  • Confiabilidade de nível de produção em ambos os transportes. Pooling de conexões HTTP (até 15 sessões simultâneas) e um processo stdio de longa duração que faz login UMA VEZ e reutiliza essa conexão para cada chamada de ferramenta, em vez de reautenticar a cada chamada, para que Claude Desktop e Claude Code permaneçam rápidos e uma rajada de chamadas não arrisque uma tempestade de logins por chamada contra o limitador upstream. Repetição automática com backoff exponencial e uma suíte de testes completa (unitários + E2E + integração).

Verificado em funcionamento com LibreChat, LobeChat e Claude Desktop. Todas as 84 ferramentas testadas de ponta a ponta. Qualquer cliente compatível com MCP deve funcionar.


Sumário


Início Rápido

Pré-requisitos

  • Servidor Actual Budget em execução (local ou remoto)
  • Seu ID de Sincronização do Orçamento: Actual → Configurações → Mostrar Configurações Avançadas → ID de Sincronização
  • Node.js 22+ (método npm) ou Docker

Opção A: Docker (recomendado)

docker run -d \
  --name actual-mcp-server-backend \
  -p 3600:3600 \
  # Use the same URL you type in your browser to open Actual Budget:
  #   http://localhost:5006          (if Actual Budget runs on the same machine)
  #   http://192.168.1.50:5006       (if it runs on another machine on your network)
  #   https://actual.yourdomain.com  (if you use a domain name)
  #   http://actual:5006             (if both containers share a Docker network; use container name)
  -e ACTUAL_SERVER_URL=http://localhost:5006 \
  -e ACTUAL_PASSWORD=your_password \
  -e ACTUAL_BUDGET_SYNC_ID=your_sync_id \
  -e MCP_SSE_AUTHORIZATION=your_secret_token \
  -v actual-mcp-data:/app/data \        # required, see note below
  -v actual-mcp-logs:/app/logs \
  ghcr.io/agigante80/actual-mcp-server:latest

Por que o volume /app/data é necessário: O Actual Budget não expõe uma API REST. A biblioteca oficial @actual-app/api (usada internamente por este servidor) funciona baixando uma cópia local dos dados do seu orçamento, executando todas as consultas nessa cópia local e, em seguida, sincronizando as alterações de volta. O volume /app/data dá ao contêiner um local persistente e gravável para armazenar essa cópia local (é o diretório que a imagem cria e possui como usuário de execução). Sem ele, o contêiner não tem onde gravar e falhará na inicialização. Consulte a documentação da API do Actual para detalhes.

O actual-mcp não precisa ser executado na mesma máquina que o Actual Budget. Você pode ter o Actual Budget em um servidor e o actual-mcp em outro — desde que ACTUAL_SERVER_URL aponte para sua instância do Actual Budget, tudo funciona.

Verifique se está em execução:

# Quick health check
curl http://localhost:3600/health
# Expected: {"status":"ok","transport":"http","version":"..."}

# Full MCP handshake (also verifies your token)
curl -s -X POST http://localhost:3600/http \
  -H "Authorization: Bearer your_secret_token" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"cli-test","version":"1.0"}}}' \
  | python3 -m json.tool
# Success: JSON response with "protocolVersion" and "serverInfo"
# Wrong token: {"error": "Unauthorized"}
# Server not running: curl: (7) Failed to connect

Também disponível no Docker Hub: agigante80/actual-mcp-server:latest

Opção B: Docker Compose

git clone https://github.com/agigante80/actual-mcp-server.git
cd actual-mcp-server
cp .env.example .env        # fill in ACTUAL_SERVER_URL, ACTUAL_PASSWORD, ACTUAL_BUDGET_SYNC_ID

docker compose --profile production up -d   # production: MCP server listens on :3600
# or
docker compose --profile dev up -d          # dev mode with hot-reload

O arquivo compose define apenas os perfis dev e production. O servidor MCP escuta em :3600 diretamente: não há proxy reverso integrado nem servidor Actual Budget integrado, então aponte ACTUAL_SERVER_URL para sua própria instância do Actual. Para TLS, habilite HTTPS nativo com MCP_ENABLE_HTTPS=true (mais MCP_HTTPS_CERT e MCP_HTTPS_KEY), ou coloque o servidor atrás do seu próprio proxy reverso.

Opção C: npm (servidor HTTP)

Requer Node.js 22+. npm e npx não impõem isso, então verifique com node --version primeiro. Em um Node mais antigo, o servidor se recusa a iniciar e informa isso. Observe que npx executa qualquer node que estiver primeiro no seu PATH, que nem sempre é o que você instalou mais recentemente.

# Quick start via npx (no clone needed):
ACTUAL_SERVER_URL=http://localhost:5006 \
ACTUAL_PASSWORD=your_password \
ACTUAL_BUDGET_SYNC_ID=your-sync-id \
MCP_SSE_AUTHORIZATION=your_token \
npx actual-mcp-server --http

# Or clone for development / custom config:
git clone https://github.com/agigante80/actual-mcp-server.git
cd actual-mcp-server
npm install
cp .env.example .env        # fill in required values
npm run build
npm run dev -- --http

O servidor inicia em http://localhost:3600/http por padrão (a porta de escuta é MCP_BRIDGE_PORT, padrão 3600).

Opção D: stdio (Claude Desktop nativo, sem Docker ou servidor HTTP necessário)

O transporte stdio executa o servidor MCP como um processo filho. O Claude Desktop o inicia diretamente e se comunica via stdin/stdout. Nenhuma porta de rede, token de autenticação ou Docker é necessário. Nenhum clone é necessário: npx baixa e armazena em cache o pacote automaticamente.

Adicione a claude_desktop_config.json (consulte docs/guides/MCP_CLIENTS_SETUP.md para a localização do arquivo de configuração e todas as opções de cliente):

{
  "mcpServers": {
    "actual-budget": {
      "command": "npx",
      "args": ["-y", "actual-mcp-server", "--stdio"],
      "env": {
        "ACTUAL_SERVER_URL": "http://localhost:5006",
        "ACTUAL_PASSWORD": "your_actual_password",
        "ACTUAL_BUDGET_SYNC_ID": "your-sync-id-here",
        "MCP_BRIDGE_DATA_DIR": "/absolute/path/to/data-dir"
      }
    }
  }
}

Nenhum token necessário. O stdio é executado como um processo local de propriedade do seu usuário. O próprio transporte é o limite de segurança. Todas as 84 ferramentas estão disponíveis.

MCP_BRIDGE_DATA_DIR deve ser um caminho absoluto. Sem um, o diretório de dados é resolvido em relação a onde o cliente inicia o processo, o que pode ser imprevisível. O diretório é criado automaticamente na primeira execução.

Opção E: Unraid (Aplicativos da Comunidade)

Unraid Community Applications

O Actual MCP Server está publicado na loja Community Applications do Unraid: ca.unraid.net/apps/actual-mcp-server. Isso executa o transporte HTTP, a escolha certa para LibreChat, LobeChat e outros clientes MCP remotos.

Instale-o na aba Apps (Community Applications):

  1. Abra a aba Apps e pesquise por actual-mcp-server, depois clique em Instalar.
  2. Preencha URL do servidor Actual, senha do servidor Actual e ID de Sincronização do servidor Actual (o ID de Sincronização está no Actual Budget: abra o orçamento, Configurações, Mostrar configurações avançadas, ID de Sincronização).
  3. Defina um token de autenticação MCP forte. Gere um com openssl rand -hex 32. Um token em branco desativa toda a autenticação HTTP e expõe seus dados financeiros sem autenticação na LAN, então isso é obrigatório (consulte Transporte e Autenticação).
  4. Deixe PUID=99 e PGID=100 (nobody:users) para que o contêiner possa gravar nos diretórios de Dados e Logs do appdata, depois inicie-o.
  5. Alcance o endpoint de saúde pelo link WebUI do contêiner (porta 3600); aponte seu cliente MCP para http://[server-ip]:3600/http com o token Bearer.

O modelo do Unraid está em unraid/actual-mcp-server.xml. Para o fluxo de publicação, consulte docs/UNRAID_CA_PUBLISHING.md.

Conecte um cliente de IA

LibreChat / LobeChat: adicione a librechat.yaml (ou configurações do plugin MCP do LobeChat):

mcpServers:
  actual-mcp:
    type: "streamable-http"
    url: "http://actual-mcp-server-backend:3600/http"
    headers:
      Authorization: "Bearer YOUR_TOKEN_HERE"
    serverInstructions: true
    timeout: 600000

Consulte docs/guides/AI_CLIENT_SETUP.md para configuração completa de LibreChat, LobeChat, rede e proxy HTTPS/TLS.

Claude Desktop via HTTP (quando o servidor já está em execução como contêiner Docker):

{
  "mcpServers": {
    "actual-budget": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "http://localhost:3600/http",
        "--header",
        "Authorization: Bearer YOUR_TOKEN_HERE"
      ]
    }
  }
}

Claude Desktop via stdio (nativo, sem servidor HTTP necessário; consulte a Opção D acima):

{
  "mcpServers": {
    "actual-budget": {
      "command": "node",
      "args": ["/absolute/path/to/actual-mcp-server/dist/src/index.js", "--stdio"],
      "env": {
        "ACTUAL_SERVER_URL": "http://localhost:5006",
        "ACTUAL_PASSWORD": "your_password",
        "ACTUAL_BUDGET_SYNC_ID": "your-sync-id",
        "MCP_BRIDGE_DATA_DIR": "/absolute/path/to/actual-mcp-server/actual-data"
      }
    }
  }
}

Consulte docs/guides/MCP_CLIENTS_SETUP.md para todas as opções (incluindo Cursor, VS Code, Gemini CLI), correções de caminho Linux/NVM e solução de problemas.


Atualização

Docker (Opção A)

docker pull ghcr.io/agigante80/actual-mcp-server:latest
docker stop actual-mcp-server-backend
docker rm actual-mcp-server-backend
# Re-run the original docker run command with the same flags and volumes

Também disponível no Docker Hub: docker pull agigante80/actual-mcp-server:latest

Docker Compose (Opção B)

docker compose pull
docker compose --profile production up -d

npm / repositório clonado (Opção C)

git pull
npm install
npm run build
# Then restart the server

npx / stdio (Opções C e D)

Se você executar npx actual-mcp-server sem uma versão instalada globalmente, o npx buscará a versão mais recente do registro automaticamente. Mas se você instalou globalmente anteriormente (npm install -g actual-mcp-server), a instalação global tem precedência, então você deve atualizá-la explicitamente:

# Upgrade the global install
npm install -g actual-mcp-server

# Or force the registry version without touching your global install
npx actual-mcp-server@latest --http

Para Claude Desktop (stdio), reinicie o Claude após a atualização.


Ferramentas Disponíveis

84 ferramentas em todas as categorias. Todas as ferramentas usam a convenção de nomenclatura actual_<category>_<action>.

Contas (12)

FerramentaDescrição
actual_accounts_listListar todas as contas
actual_accounts_createCriar nova conta
actual_accounts_updateAtualizar detalhes da conta. Um id que não existe é recusado em vez de criar um registro parcial
actual_accounts_deleteExcluir conta permanentemente
actual_accounts_closeFechar conta. Uma conta SEM transações é REMOVIDA pelo Actual, não fechada
actual_accounts_reopenReabrir conta fechada. Um id que não é uma conta é recusado em vez de criar uma
actual_accounts_get_balanceObter saldo da conta em uma data
actual_account_flow_summaryExplicar a mudança exata de saldo em um conjunto de contas em um intervalo de datas: renda externa, saída de despesas, créditos, entradas não categorizadas e transferências para dentro, para fora ou dentro da seleção, com uma reconciliação exata
actual_account_groups_listListar os grupos de contas personalizados usados para organizar contas na barra lateral (Actual 26.9.0+)
actual_account_groups_createCriar um grupo de contas. Atribuir contas a ele é uma chamada separada de actual_accounts_update
actual_account_groups_updateRenomear um grupo de contas ou alterar sua posição na barra lateral. Um grupo que não existe é recusado, sem gravar nada
actual_account_groups_deleteExcluir um grupo de contas. Suas contas NÃO são excluídas, elas ficam sem grupo

Transações (17)

Padrão (7)

FerramentaDescrição
actual_transactions_getObter transações de uma conta
actual_transactions_filterFiltrar com critérios avançados
actual_transactions_createCriar nova(s) transação(ões), incluindo divisões (passe um array subtransactions)
actual_transactions_importImportar e reconciliar transações
actual_transactions_updateAtualizar uma transação, dividir uma simples no lugar ou editar os filhos de uma divisão existente via subtransactions
actual_transactions_deleteExcluir uma transação
actual_transactions_mergeMesclar duas transações da mesma conta e mesmo valor (por exemplo, um duplicado importado do banco e um lançamento manual). O upstream mantém uma (a importada primeiro) e EXCLUI a outra, preenchendo apenas os campos vazios de beneficiário, categoria, notas e agendamento da linha mantida e seus flags falsos de compensado e reconciliado; irreversível

Transações divididas: passe um array subtransactions (cada filho precisa de um amount em centavos inteiros; category e notes são opcionais). Os valores dos filhos devem somar o amount do pai (o servidor não aplica isso, então a ferramenta o faz). Um pai dividido não carrega categoria própria: coloque as categorias nos filhos. actual_transactions_update com subtransactions edita os filhos de uma transação que já é dividida, ou divide uma transação simples NO MESMO LUGAR: mantém seu id, imported_id e estado de compensação, para que uma transação sincronizada com o banco possa ser dividida sem quebrar a correspondência de importação. Sua própria categoria é limpa, e um filho que não nomeia categoria a herda. Um filho dividido não pode ser dividido novamente. Nota: actual_transactions_import encaminha um array subtransactions para a API, mas NÃO aplica a verificação de soma, então use actual_transactions_create para divisões com saldo garantido.

Utilitário (2)

FerramentaDescrição
actual_transactions_uncategorizedResumo de transações não categorizadas (totalCount, totalAmount, detalhamento por conta); passe includeTransactions:true para linhas paginadas
actual_transactions_update_batchAplica muitas atualizações de transações em UMA chamada (updates: [{ id, fields }]); retorna contagens de sucesso e falha por item

Exclusivo com ActualQL (8), único deste servidor MCP

FerramentaDescrição
actual_transactions_aggregateTotais determinísticos em centavos inteiros agrupados por mês, categoria, grupo de categorias, beneficiário ou conta; transferências excluídas via transfer_id e filhos divididos contados uma vez
actual_transactions_search_by_monthBusca por mês usando a transformação $month
actual_transactions_search_by_amountEncontra por faixa de valor
actual_transactions_search_by_categoryBusca por nome de categoria
actual_transactions_search_by_payeeEncontra por beneficiário/fornecedor
actual_transactions_summary_by_categoryResumo de gastos agrupado por categoria
actual_transactions_summary_by_payeePrincipais fornecedores com totais e contagens
actual_recurring_expenses_summaryDetecta cobranças recorrentes (assinaturas, contas) a partir do histórico lançado: cadência (com tolerância a variação de data e fim do mês), valor mais recente, mudanças de preço, ocorrências, custo anualizado e estado ativo ou inativo

Transferências (1)

FerramentaDescrição
actual_transfers_createCria uma transferência pareada entre duas contas (débito + crédito vinculados por transfer_id, idêntico ao "Fazer Transferência" da interface)

Nota: Use actual_transfers_create para qualquer movimentação entre contas, não actual_transactions_create. A ferramenta dedicada cria ambos os lados (débito e crédito) atomicamente para que os livros permaneçam equilibrados. Limitações: ambas as contas devem existir e estar abertas, e from_account deve ser diferente de to_account.

Categorias (4)

actual_categories_get · actual_categories_create · actual_categories_update · actual_categories_delete

Grupos de Categorias (4)

actual_category_groups_get · actual_category_groups_create · actual_category_groups_update · actual_category_groups_delete

Beneficiários (7)

actual_payees_get · actual_payees_common_list · actual_payees_create · actual_payees_update · actual_payees_delete · actual_payees_merge · actual_payee_rules_get

Etiquetas (4)

actual_tags_list · actual_tags_create · actual_tags_update · actual_tags_delete

FerramentaDescrição
actual_tags_listLista todas as etiquetas (id, palavra da etiqueta, cor e descrição opcionais)
actual_tags_createCria ou faz upsert de uma etiqueta por nome; retorna o UUID da etiqueta
actual_tags_updateAtualiza nome, cor ou descrição da etiqueta por UUID
actual_tags_deleteExclusão suave de uma etiqueta por UUID

Notas (2)

actual_notes_get · actual_notes_update

FerramentaDescrição
actual_notes_getObtém a nota de qualquer entidade (UUID de conta/categoria/grupo de categorias/beneficiário, ou orçamento-AAAA-MM)
actual_notes_updateDefine ou limpa a nota de qualquer entidade; valida se a entidade existe ou corresponde ao padrão orçamento-AAAA-MM

Preferências (1)

FerramentaDescrição
actual_preferences_getLê as preferências de exibição sincronizadas do orçamento (formato de número, formato de data, moeda, primeiro dia da semana). Somente exibição: todos os valores permanecem em centavos inteiros

Orçamentos (12)

FerramentaDescrição
actual_budgets_list_availableLista todos os arquivos de orçamento configurados
actual_budgets_switchAlterna o orçamento ativo (multi-orçamento)
actual_budgets_get_allLista os arquivos de orçamento disponíveis
actual_budgets_getMonthsLista os meses do orçamento
actual_budgets_getMonthObtém o orçamento de um mês específico
actual_budgets_setAmountDefine o valor do orçamento da categoria. O mês deve ser um que o orçamento possua (veja actual_budgets_getMonths)
actual_budgets_transferTransfere valor entre categorias
actual_budgets_setCarryoverAtiva/desativa o repasse (carryover)
actual_budgets_holdForNextMonthReserva fundos para o próximo mês. O Actual limita a reserva ao que resta para orçar, então a resposta informa o valor realmente reservado
actual_budgets_resetHoldRedefine o estado da reserva
actual_budgets_exportExporta o orçamento ativo como um .zip para ACTUAL_EXPORT_DIR; retorna caminho, tamanho em bytes e sha256, nunca o conteúdo do arquivo
actual_budgets_importRestaura um orçamento a partir de um .zip do Actual ou de uma exportação YNAB4/YNAB5. Destrutivo: o id do orçamento vem do arquivo, então reimportar uma exportação substitui os dados desse orçamento em vez de fazer uma cópia. Também carrega o orçamento importado, alterando o orçamento ativo da sessão

Regras (6)

actual_rules_get · actual_rules_create · actual_rules_update · actual_rules_delete

FerramentaDescrição
actual_rules_create_or_updateUpsert idempotente: cria uma regra, ou atualiza a existente que corresponde às mesmas condições, em uma única chamada. Use isto em vez de obter-depois-criar ao reexecutar uma configuração de categorização, para que execuções repetidas não acumulem regras duplicadas
actual_rules_create_batchCria de 1 a 50 regras em uma chamada, cada uma exatamente como a entrada de actual_rules_create. Melhor esforço, não atômico (veja Operações em Lote): uma regra que falha em suas próprias verificações, nomeia uma categoria, beneficiário ou conta que não existe, ou é rejeitada pelo Actual é reportada com seu índice enquanto o restante continua

Agendamentos (4)

FerramentaDescrição
actual_schedules_getLista transações agendadas, com sua próxima data de ocorrência
actual_schedules_createCria um agendamento (único ou recorrente); a recorrência é uma configuração tipada, veja src/lib/schemas/recur.ts
actual_schedules_updateAtualiza valor, beneficiário, conta ou recorrência de um agendamento existente
actual_schedules_deleteExclui um agendamento

Consulta Avançada e Sincronização (2)

FerramentaDescrição
actual_query_runExecuta consulta ActualQL personalizada
actual_bank_syncDispara sincronização bancária (GoCardless/SimpleFIN)

Operações em Lote (1)

Quatro ferramentas aceitam muitos itens em uma chamada, para clientes que permitem apenas algumas chamadas de ferramenta por turno. Elas compartilham UM contrato: cada item é aplicado de forma independente e não atômica. Não há rollback, então itens aplicados antes de uma falha permanecem aplicados; um item ruim é reportado pelo seu índice e o restante continua; uma falha de infraestrutura (conexão perdida, timeout) falha a chamada inteira, e então você deve reler os dados antes de tentar novamente qualquer coisa. Um caminho em lote nunca tenta uma criação por conta própria.

  • actual_transactions_update_batch (contado em Transações): atualiza até 50 transações, {id, fields} cada. Resultado: { succeeded: [{id}], failed: [{id, error}], total, successCount, failureCount }. Itens marcados como "não tentados" nunca foram enviados. Releia com actual_transactions_get antes de tentar novamente qualquer item.
  • actual_transactions_import (contado em Transações): criação em lote com semântica de importação (deduplicação e reconciliação com transações existentes, regras opcionalmente aplicadas). Use para adicionar muitas transações de uma vez.
  • actual_budget_updates_batch: define valores de orçamento e/ou flags de repasse para 1 a 100 pares mês/categoria, e a forma de reequilibrar categorias: leia o mês com actual_budgets_getMonth, depois envie um lote de valores absolutos. Cada operação precisa de pelo menos um de amount (centavos inteiros) ou carryover. Resultado: { succeeded: [{index, month, categoryId}], failed: [{index, month, categoryId, error}], total, successCount, failureCount }. Uma categoria desconhecida, um mês fora do intervalo ou um repasse em uma categoria de renda falha apenas naquele item. Após um timeout, leia os meses de volta com actual_budgets_getMonth antes de tentar novamente.
  • actual_rules_create_batch (contado em Regras): cria de 1 a 50 regras, cada uma exatamente como a entrada de actual_rules_create. Resultado: { succeeded: [{index, id}], failed: [{index, error}], total, successCount, failureCount }. Itens marcados como "não tentados" nunca foram enviados. Releia com actual_rules_get antes de tentar novamente qualquer item.

Informações do Servidor e Consulta (5)

FerramentaDescrição
actual_server_infoStatus do servidor, versão, informações de build
actual_server_get_versionVersão do servidor Actual Budget
actual_get_contextRecupera contas abertas, grupos de categorias com categorias aninhadas e beneficiários (ordenados por nome, limitados por payeeLimit) em uma única chamada
actual_get_id_by_nameResolve um nome exato → UUID para contas, categorias, beneficiários
actual_entities_searchEncontra contas/categorias/beneficiários por um padrão de nome (contém/começaCom/terminaCom/exato/aproximado). Corrige "beneficiário não encontrado" a partir de um nome parcial ou digitado incorretamente

Gerenciamento de Sessão (2)

actual_session_list · actual_session_close


Configuração

Toda a configuração é feita por variáveis de ambiente. Copie .env.example para .env para começar.

Referência Completa de Variáveis de Ambiente

VariávelPadrãoObrigatórioDescrição
Conexão com o Actual Budget
ACTUAL_SERVER_URL(nenhum)SimURL do seu servidor Actual Budget. Use a mesma URL que você digita no navegador: http://localhost:5006 (local), http://192.168.1.x:5006 (rede), https://actual.yourdomain.com (domínio) ou http://actual:5006 (nome do contêiner se estiver na mesma rede Docker)
ACTUAL_PASSWORD(nenhum)SimSenha de login do seu servidor Actual Budget, aquela que você digita na própria tela de login. Não é a mesma que ACTUAL_BUDGET_PASSWORD (que descriptografa um orçamento criptografado E2E) e não tem relação com AUTH_PROVIDER=oidc (que controla como os clientes MCP autenticam neste servidor, não como este servidor autentica no Actual). Este servidor sempre faz login no Actual com uma senha, portanto o login por senha upstream deve permanecer habilitado
ACTUAL_BUDGET_SYNC_ID(nenhum)SimID de sincronização do orçamento do Actual (Configurações e depois ID de sincronização)
ACTUAL_BUDGET_PASSWORD(nenhum)NãoSenha de criptografia opcional para orçamentos criptografados
ALLOW_INSECURE_UPSTREAMfalseNãoPermitir um upstream http:// mesmo quando ACTUAL_BUDGET_PASSWORD está definido (#161). Desativado por padrão para que um upstream em texto simples com senha de criptografia seja recusado
ACTUAL_OP_TIMEOUT_MS30000NãoTempo limite por operação (ms) para cada chamada de API upstream do Actual (inicialização, download do orçamento, sincronização e cada operação de ferramenta). Uma chamada travada é rejeitada após esse limite para não segurar o mutex global da API para sempre e travar chamadas subsequentes de ferramentas (#270). Defina como 0 para desativar
ACTUAL_IMPORT_TIMEOUT_MS600000NãoTempo limite separado e maior (ms) para importação de orçamento, que é legitimamente longa em vez de travada. Uma importação é uma carga rastreada, então todas as outras sessões esperam por ela; limitá-la ao tempo limite geral de operação transformou a importação grande de um locatário em uma paralisação em todo o processo (#407). Defina como 0 para desativar
Configurações do Servidor MCP
MCP_BRIDGE_PORT3600NãoPorta para o servidor MCP escutar
MCP_BRIDGE_BIND_HOST0.0.0.0NãoEndereço do host para vincular o servidor (0.0.0.0 = todas as interfaces)
MCP_BRIDGE_DATA_DIR./actual-dataNãoDiretório para armazenar dados locais do Actual Budget (SQLite). Obrigatório ser um caminho persistente. A biblioteca @actual-app/api baixa uma cópia local do seu orçamento aqui para executar consultas; use um volume montado no Docker para persistir entre reinicializações
ACTUAL_EXPORT_DIR(não definido)NãoDiretório onde actual_budgets_export grava arquivos de .zip do orçamento. Não definido significa <MCP_BRIDGE_DATA_DIR>/exports, que é gravável e persistido na imagem Docker. Deve ser gravável pelo usuário em tempo de execução
MCP_BRIDGE_PUBLIC_HOSTdetectado automaticamenteNãoHostname/IP público para o servidor (mostrado nos logs)
MCP_BRIDGE_PUBLIC_SCHEMEdetectado automaticamenteNãoEsquema público (http ou https)
MCP_BRIDGE_USE_TLSfalseNãoDefina como true para anunciar https:// na URL do servidor (para configurações de proxy reverso onde o TLS é encerrado upstream)
Configuração de Transporte
MCP_TRANSPORT_MODE--httpNãoModo de transporte. Apenas --http é um valor válido; stdio é selecionado via a flag CLI --stdio, não esta variável
MCP_HTTP_PATH/httpNãoCaminho de roteamento do endpoint HTTP
MCP_BRIDGE_HTTP_PATHigual a MCP_HTTP_PATHNãoCaminho HTTP anunciado mostrado aos clientes (definido quando um proxy reverso reescreve o caminho)
MCP_HTTP_BODY_LIMIT512kbNãoTamanho máximo aceito do corpo da solicitação JSON-RPC (ex.: 512kb, 1mb, 1048576). Validado na inicialização: um tamanho inválido, zero ou estourado recusa iniciar nomeando a variável (#466)
Superfície de Ferramentas
MCP_TOOLSETSallNãoGrupos de conjuntos de ferramentas separados por vírgula (context, transactions, analysis, budget, rules, schedules, structure, query, admin) e predefinições (chat) para publicar; all publica todas as ferramentas. Nomes desconhecidos recusam iniciar. Veja Reduzindo a superfície de ferramentas
MCP_TOOLS(vazio)NãoFerramentas extras para adicionar além de MCP_TOOLSETS, pelo nome registrado completo (ex.: actual_accounts_list). Nomes desconhecidos recusam iniciar
MCP_READ_ONLYfalseNãotrue oculta e recusa as 47 ferramentas com capacidade de escrita. Apenas true ou false (sem diferenciar maiúsculas/minúsculas) são aceitos; qualquer outro valor recusa iniciar
Gerenciamento de Sessões
USE_CONNECTION_POOLtrueNãoHabilitar pool de conexões baseado em sessão
MAX_CONCURRENT_SESSIONS15NãoMáximo de sessões MCP simultâneas permitidas
SESSION_IDLE_TIMEOUT_MINUTES5NãoMinutos antes da limpeza de sessões ociosas
Segurança e Autenticação
AUTH_PROVIDERnoneNãoModo de autenticação: none (Bearer estático) ou oidc (JWT validado por JWKS)
MCP_SSE_AUTHORIZATION(nenhum)NãoToken Bearer estático (AUTH_PROVIDER=none; altamente recomendado em produção)
MCP_ALLOW_UNAUTHENTICATEDfalseNãoOpt-out para autenticação HTTP obrigatória por padrão (#242). Em um bind não-loopback sem token e sem OIDC, o servidor recusa iniciar; defina como true para executar aberto deliberadamente (ex.: atrás do seu próprio proxy)
OIDC_ISSUER(nenhum)Se OIDCURL do emissor OIDC (ex.: https://sso.example.com)
OIDC_ALLOW_INSECURE_ISSUERfalseNãoPermitir um emissor OIDC em texto simples (http) em uma rede confiável (#244). Desativado por padrão (emissor http recusado na inicialização); defina true apenas para testes locais/LAN
OIDC_RESOURCE(nenhum)Se OIDCURL canônica deste servidor, o identificador de recurso RFC 9728 e o aud esperado (#461). Use a URL completa do endpoint público MCP, ex.: https://actual-mcp.example.com/http, sem barra final. Deve ser uma URL http(s) absoluta (um client id simples recusa iniciar); coloque um aud de client-id em OIDC_ACCEPTED_AUDIENCES em vez disso
OIDC_ACCEPTED_AUDIENCES(nenhum)NãoValores extras aceitos de aud além de OIDC_RESOURCE, separados por vírgula (#245). Para IdPs que colocam o client-id em aud (ex.: Authentik) ou a URI de redirecionamento do cliente OAuth (Cloudflare Access for SaaS). Lista de permissões estrita, nunca um curinga
OIDC_JWKS_TRUSTED_HOSTS(nenhum)NãoHosts JWKS entre origens opt-in, separados por vírgula host ou host:port (#254). Para IdPs cujo jwks_uri vive em outro host, ex.: Google precisa de www.googleapis.com. Correspondência exata, sem curingas; padrão vazio mantém apenas mesma origem
OIDC_JWKS_URI(nenhum)NãoURL JWKS direta que ignora a descoberta OpenID (#462), para emissores sem documento de descoberta (Cloudflare Access: https://<team>.cloudflareaccess.com/cdn-cgi/access/certs). Mesmas regras de https, credenciais e origem ou host confiável que um jwks_uri descoberto, além de sem query ou fragmento. Quando definido, /.well-known/oauth-authorization-server não é servido e AUTH_BUDGET_ACL_IDENTITY_SOURCE=userinfo é recusado
OIDC_TOKEN_SOURCEauthorizationNãoOnde o JWT Bearer é lido (#462): authorization (padrão) ou cf-access-jwt-assertion para um servidor MCP atrás do Cloudflare Access com Managed OAuth (o edge encaminha o Access JWT assinado nesse cabeçalho; Authorization nunca é consultado, OIDC_SCOPES deve estar vazio, OIDC_SCOPES_SUPPORTED é permitido e a origem deve ser alcançável apenas via Cloudflare). Veja a receita do Cloudflare em docs/guides/AI_CLIENT_SETUP.md
OIDC_SCOPES(nenhum)NãoEscopos obrigatórios (aplicados) separados por vírgula, também anunciados. Deixe vazio quando os JWTs do IdP não carregam claim scope (Cloudflare Access for SaaS, ou Casdoor quando o cliente não solicita escopo)
OIDC_SCOPES_SUPPORTED(nenhum)NãoEscopos separados por vírgula anunciados em scopes_supported mas não aplicados. Use quando os JWTs do IdP não carregam claim scope mas o cliente precisa de um escopo como offline_access anunciado (ex.: Gemini com Cloudflare Access for SaaS). Escopos obrigatórios de OIDC_SCOPES também são sempre anunciados. Anunciar offline_access desbloqueia um refresh token que este servidor não pode revogar: veja Limitando um refresh token vazado
AUTH_BUDGET_ACL(nenhum)NãoACL de orçamento por usuário; veja Configuração de Clientes de IA. Validado na inicialização: um valor que não seja um objeto JSON de arrays de strings recusa iniciar (#551). Não definido ou {} significa sem restrições
AUTH_BUDGET_ACL_SOURCEstaticNãostatic usa o mapa AUTH_BUDGET_ACL acima. actual deriva a ACL da própria lista de acesso por arquivo do servidor Actual, então revogar alguém no Actual tem efeito aqui sem edição de configuração. Requer um servidor Actual multiusuário (OpenID) que foi inicializado com senha primeiro
AUTH_BUDGET_ACL_CLAIMautoNãoQual claim do token identifica o principal quando a fonte é actual. auto espelha a própria precedência do Actual (preferred_username, login, email, id, sub) e corresponde o resultado ao userName do Actual. Defina um único nome de claim para fixar um em vez disso
AUTH_BUDGET_ACL_IDENTITY_MAP(vazio)NãoLigações explícitas de <sub>=<Actual userName>, separadas por vírgula, usadas quando a fonte é actual. Consultadas antes da precedência de claims e autoritativas: um sub vinculado cujo alvo não corresponde a nenhum arquivo de orçamento é negado em vez de cair para um claim. Use quando seu token de acesso não carrega o claim que o Actual armazenou, ou após uma renomeação no lado do IdP
AUTH_BUDGET_ACL_IDENTITY_SOURCEtokenNãoOnde a ACL lê claims de identidade quando a fonte é actual. token usa o token de acesso verificado (sem chamada de rede). userinfo chama o endpoint UserInfo do IdP, que é o mesmo documento do qual o Actual deriva userName, e corrige implantações onde o token de acesso não tem o claim que o Actual armazenou. Opt-in porque torna o IdP uma dependência rígida da autorização
AUTH_BUDGET_ACL_USERINFO_TIMEOUT_MS5000NãoTempo limite para a solicitação UserInfo, limitado entre 250ms e 60s. Sem valor de desativação: uma chamada sem limite no caminho de autenticação transforma um IdP lento em uma interrupção
MCP_ENABLE_HTTPSfalseNãoHabilitar TLS nativo. Requer MCP_HTTPS_CERT e MCP_HTTPS_KEY
MCP_HTTPS_CERT(nenhum)NãoCaminho para o arquivo de certificado PEM (obrigatório quando MCP_ENABLE_HTTPS=true)
MCP_HTTPS_KEY(nenhum)NãoCaminho para o arquivo de chave privada PEM (obrigatório quando MCP_ENABLE_HTTPS=true)
Configuração de Logging
MCP_BRIDGE_STORE_LOGSfalseNãoHabilitar logging em arquivo (vs apenas console)
MCP_BRIDGE_LOG_DIRapp/logs (ao lado da instalação)NãoDiretório para arquivos de log (se STORE_LOGS=true). .env.example e Docker definem explicitamente (ex.: ./logs, /app/logs)
MCP_BRIDGE_LOG_LEVELdebug (dev) / info (prod)NãoNível de log: error, warn, info, debug
LOG_FORMATautomáticoNãoFormato de saída de log: json ou pretty. Precedência: LOG_FORMAT explícito vence, senão NODE_ENV=production seleciona json, senão pretty
MCP_SERVICE_NAMEactual-mcp-serverNãoNome do serviço carimbado em cada registro de log estruturado (json)
Rotação de Logs (quando MCP_BRIDGE_STORE_LOGS=true)
MCP_BRIDGE_MAX_FILES14dNãoManter logs rotacionados por N dias (ex.: 14d, 30d)
MCP_BRIDGE_MAX_LOG_SIZE20mNãoRotacionar quando o arquivo atingir o tamanho (ex.: 20m, 100m)
MCP_BRIDGE_ROTATE_DATEPATTERNYYYY-MM-DDNãoPadrão de data para nomes de arquivos de log rotacionados
Desenvolvimento e Depuração
DEBUG(nenhum)NãoHabilitar modo de depuração (logging verboso) quando definido para qualquer valor verdadeiro
LOG_LEVEL(nenhum)NãoAlternância de detecção de depuração: defina como debug para habilitar saída extra de depuração de transporte. Distinto de MCP_BRIDGE_LOG_LEVEL (o nível do winston); não tem padrão e não é em si um nível de log
MCP_BRIDGE_DEBUG_TRANSPORTfalseNãoHabilitar registro de depuração em nível de transporte
Avançado/Interno
ACTUAL_API_CONCURRENCY5NãoMáximo de operações simultâneas da API do Actual
NODE_ENV(nenhum) / productionNãoAmbiente do Node. Sem padrão do aplicativo; a imagem Docker define production, que seleciona logs JSON e oculta rastreamentos de pilha em respostas de erro
VERSIONdetectado automaticamenteNãoVersão do servidor (definida automaticamente pelo build/Docker)
TZUTCNãoFuso horário para carimbos de data/hora (ex.: America/New_York)

Reduzindo a superfície de ferramentas

Todas as 84 ferramentas são publicadas por padrão. Clientes de chat com um orçamento de ferramentas pequeno (Gemini, LibreChat) se saem melhor com menos, então a superfície pode ser reduzida na inicialização. Uma ferramenta que não é publicada também é recusada se um cliente a chamar pelo nome, e a recusa nomeia a configuração responsável.

Conjunto de ferramentasFerramentasConteúdo
context14Orientação, consultas e informações do servidor
transactions13Leitura de transações, criação, atualização, exclusão, importação e transferências
analysis7Resumos, agregações e saldos
budget10Meses de orçamento, valores, saldo remanescente, retenções, transferências, atualizações em lote e notas
rules7Regras e regras de beneficiário, incluindo actual_rules_create_batch
schedules4Transações agendadas
structure21Contas, grupos de contas, categorias, grupos de categorias, beneficiários e tags
query1actual_query_run (somente SELECT)
admin6Alternância de orçamento, importação, exportação, sincronização bancária e gerenciamento de sessão

Cada ferramenta está em exatamente um grupo. O preset chat corta entre eles e publica 12 ferramentas: actual_get_context, actual_query_run, actual_transactions_create, actual_transactions_update, actual_transactions_delete, actual_transactions_update_batch, actual_rules_create, actual_rules_create_batch, actual_budget_updates_batch, actual_budgets_transfer, actual_budgets_setAmount e actual_budgets_getMonth. Medido no payload tools/list, todas as 84 ferramentas têm 108.164 bytes e o preset chat tem 25.949 bytes (cerca de 6,5 mil tokens economizados, uma redução de 76%).

MCP_READ_ONLY=true adicionalmente oculta e recusa toda ferramenta com capacidade de escrita (47 das 83, incluindo actual_bank_sync, actual_budgets_export, actual_budgets_switch e actual_session_close), deixando 36. actual_session_list permanece disponível em somente leitura. Consulte Segurança e Privacidade.

Exemplo: um assistente de chat.

MCP_TOOLSETS=chat
MCP_TOOLS=actual_accounts_list,actual_payees_get

Exemplo: um assistente doméstico somente leitura.

MCP_TOOLSETS=context,analysis,query
MCP_READ_ONLY=true

Uma configuração que resulta em zero ferramentas se recusa a iniciar.


Alternância de Múltiplos Orçamentos

Configure vários arquivos do Actual Budget para que a IA possa alternar entre eles em tempo de execução usando actual_budgets_list_available e actual_budgets_switch.

BUDGET_N_SERVER_URL e BUDGET_N_PASSWORD recorrem a ACTUAL_SERVER_URL / ACTUAL_PASSWORD quando omitidos.

VariávelObrigatóriaPadrão
BUDGET_DEFAULT_NAMENão"Default"
BUDGET_N_NAMESim (habilita grupo)(nenhum)
BUDGET_N_SYNC_IDSim(nenhum)
BUDGET_N_SERVER_URLNãoACTUAL_SERVER_URL
BUDGET_N_PASSWORDNãoACTUAL_PASSWORD
BUDGET_N_ENCRYPTION_PASSWORDNão(nenhum)
# Default budget
ACTUAL_SERVER_URL=http://actual:5006
ACTUAL_PASSWORD=my-password
ACTUAL_BUDGET_SYNC_ID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
BUDGET_DEFAULT_NAME=Personal

# Budget 1 (same server, same password)
BUDGET_1_NAME=Family
BUDGET_1_SYNC_ID=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb

# Budget 2 (different server)
BUDGET_2_NAME=Business
BUDGET_2_SERVER_URL=https://actual-office.example.com
BUDGET_2_PASSWORD=office-password
BUDGET_2_SYNC_ID=cccccccc-cccc-cccc-cccc-cccccccccccc

Transporte e Autenticação

O servidor suporta dois modos de transporte:

ModoFlagCaso de usoAutenticação
HTTP--httpLibreChat, LobeChat, Docker, implantações multiusuárioToken Bearer ou OIDC
stdio--stdioClaude Desktop, Cursor, uso local de usuário únicoNenhuma (isolamento de processo do SO)

Os dois modos são mutuamente exclusivos. Passe exatamente uma flag ao iniciar o servidor.

Transporte stdio

stdio é a maneira mais simples de conectar o Claude Desktop diretamente ao Actual Budget. O servidor MCP roda como um processo filho; o Claude Desktop o inicia, comunica-se via stdin/stdout usando NDJSON (o formato de transmissão MCP), e o processo encerra limpo quando o Claude Desktop fecha.

Propriedades principais do modo stdio:

  • Sem porta de rede. O transporte é um pipe, não um socket.
  • Sem token de autenticação. A propriedade do processo é o limite de segurança.
  • Todos os logs vão para stderr para nunca corromper o enquadramento JSON-RPC no stdout
  • O processo encerra quando o stdin fecha (Claude Desktop desligando)
  • Todas as 84 ferramentas estão disponíveis, idênticas ao modo HTTP

Inicie manualmente para verificar:

cd /path/to/actual-mcp-server
ACTUAL_SERVER_URL=http://localhost:5006 \
ACTUAL_PASSWORD=your_password \
ACTUAL_BUDGET_SYNC_ID=your-sync-id \
node dist/src/index.js --stdio

Envie uma solicitação de teste (mantenha o stdin aberto com sleep):

{ echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'; sleep 5; } \
| ACTUAL_SERVER_URL=http://localhost:5006 ACTUAL_PASSWORD=your_password ACTUAL_BUDGET_SYNC_ID=your-sync-id \
  node dist/src/index.js --stdio 2>/dev/null

Configuração do Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "actual-budget": {
      "command": "node",
      "args": ["/absolute/path/to/actual-mcp-server/dist/src/index.js", "--stdio"],
      "env": {
        "ACTUAL_SERVER_URL": "http://localhost:5006",
        "ACTUAL_PASSWORD": "your_actual_password",
        "ACTUAL_BUDGET_SYNC_ID": "your-sync-id-here",
        "MCP_BRIDGE_DATA_DIR": "/absolute/path/to/actual-mcp-server/actual-data"
      }
    }
  }
}

O caminho deve ser absoluto. O Claude Desktop não herda PATH do shell, então node também deve ser absoluto se você usar NVM ou uma instalação não padrão: /home/youruser/.nvm/versions/node/v22.x.x/bin/node.

Consulte docs/guides/MCP_CLIENTS_SETUP.md para todas as opções de conexão (stdio nativo, mcp-remote via HTTP/HTTPS), outros clientes (Cursor, VS Code, Gemini CLI, Claude Code), correções de caminho no Linux e solução de problemas.

Transporte HTTP

Transporte HTTP usa o endpoint /http (StreamableHTTP) com token Bearer opcional ou autenticação OIDC.

Token Bearer estático (usuário único)

# Generate a token
openssl rand -hex 32

# Add to .env
MCP_SSE_AUTHORIZATION=your_token_here

Os clientes enviam: Authorization: Bearer your_token_here

OIDC (multiusuário)

AUTH_PROVIDER=oidc
OIDC_ISSUER=https://sso.yourdomain.com
OIDC_RESOURCE=https://actual-mcp.yourdomain.com/http   # this server's public MCP URL (the expected 'aud')
OIDC_ACCEPTED_AUDIENCES=your-client-id                  # only if your IdP puts the client id in 'aud' (#245)
OIDC_SCOPES=                                            # leave empty when the tokens carry no scope claim
# OIDC_SCOPES_SUPPORTED=openid,offline_access           # extra scopes advertised in discovery without enforcement (#472)

OIDC_RESOURCE é a URL canônica deste servidor MCP (a "URI canônica do servidor" da especificação de autorização MCP e o identificador de recurso RFC 9728), não um ID de cliente IdP: a rota de metadados de recurso protegido e o público de token esperado são ambos derivados dela, e um valor que não é uma URL http(s) absoluta se recusa a iniciar com uma mensagem nomeando a variável (#461). Use a URL completa do endpoint público (https://host/http, ou o que MCP_BRIDGE_HTTP_PATH / MCP_HTTP_PATH anunciar) em vez da origem nua: com a forma de endpoint, o servidor publica tanto o documento específico do caminho (canônico) quanto uma cópia raiz para clientes que olham apenas a raiz (#473), e ele avisa na inicialização quando o caminho do recurso e o caminho anunciado discordam.

Endpoints de descoberta OAuth (automáticos no modo OIDC). Quando AUTH_PROVIDER=oidc, o servidor publica os dois documentos de metadados que um cliente OAuth precisa para inicializar um login, então mcp-remote e o conector nativo do Claude.ai podem descobrir o fluxo sem configuração manual de endpoint:

  • GET /.well-known/oauth-protected-resource[<path>] (RFC 9728): identifica este servidor como um recurso protegido e aponta para seu OIDC_ISSUER como o servidor de autorização. A rota segue OIDC_RESOURCE: com https://host/http, o documento canônico é servido em /.well-known/oauth-protected-resource/http (RFC 9728 seção 3.1) e uma cópia raiz também é servida em /.well-known/oauth-protected-resource para clientes que pulam a URL específica do caminho (ex.: Google Gemini, #473); a origem nua serve apenas o caminho raiz. O SDK MCP oficial tenta a URL específica do caminho primeiro e recorre à raiz.
  • GET /.well-known/oauth-authorization-server (RFC 8414, #285): os metadados do servidor de autorização (seus authorization_endpoint / token_endpoint / registration_endpoint), re-servidos do próprio documento de descoberta OpenID do seu IdP. Isso está aqui porque vários clientes o procuram na origem do servidor de recursos, e alguns IdPs (ex.: Authentik) não o expõem onde esses clientes procuram. É buscado uma vez na inicialização e servido literalmente, expõe apenas endpoints que seu IdP já publica publicamente e não requer autenticação (um cliente o lê antes de ter um token). Nenhuma configuração extra é necessária; está ausente quando AUTH_PROVIDER não é oidc.

De onde vem a ACL de orçamento por usuário. Por padrão, a ACL é o mapa AUTH_BUDGET_ACL que você mantém manualmente. Desde v0.10.x, ela pode ser derivada da própria lista de acesso por arquivo do servidor Actual, então conceder ou revogar alguém no Actual tem efeito aqui sem edição de configuração e reinicialização:

AUTH_BUDGET_ACL_SOURCE=actual   # default: static (the AUTH_BUDGET_ACL map)
AUTH_BUDGET_ACL_CLAIM=auto      # default: mirrors Actual's own claim precedence

Como funciona a correspondência. O Actual não armazena o sub do seu IdP. Quando um usuário faz login, o Actual resolve sua identidade como o primeiro não vazio de preferred_username, login, email, id, sub, salva essa string como o userName do usuário e gera seu próprio UUID não relacionado como userId. A ACL, portanto, corresponde seu token contra userName, usando essa mesma precedência. AUTH_BUDGET_ACL_CLAIM=auto (o padrão) faz exatamente isso; defina-o para um único nome de claim para fixar um em vez disso.

Três coisas para saber antes de habilitar:

  • Requer um servidor Actual multiusuário, ou seja, um configurado com ACTUAL_OPENID_*. Em um servidor somente com senha, não existem usuários nomeados e todo principal resolve para nada.
  • Seu servidor Actual deve ter sido inicializado com uma SENHA antes de o OpenID ser adicionado. Este é um pré-requisito rígido deste servidor MCP em geral, não apenas deste recurso: @actual-app/api autentica com uma senha, e um servidor Actual configurado com OpenID do zero recusa login por senha, então este servidor não pode se conectar a ele de forma alguma. Uma senha não pode ser adicionada depois.
  • A identidade é tão confiável quanto o claim por trás dela. OIDC garante que sub é único e nunca reatribuído; preferred_username e email não carregam tal garantia e são frequentemente editáveis pelo usuário. Essa exposição é herdada do Actual, que chaveia suas próprias contas da mesma forma, não introduzida aqui: qualquer um que possa definir seu preferred_username para o seu pode se passar por você no login do Actual também. Se isso importa para você, fixe AUTH_BUDGET_ACL_CLAIM a um claim que seu IdP não permite que usuários editem e certifique-se de que esse é o claim que seu IdP usa para preencher o user_name do Actual.

É opt-in e falha fechada: se a lista de orçamentos não puder ser lida, ou o principal não corresponder a nenhum arquivo, o acesso é negado em vez de concedido.

Consulte Configuração de Cliente de IA, OIDC para o formato AUTH_BUDGET_ACL, notas sobre Casdoor e a receita Cloudflare Access for SaaS + Gemini.


Testes

ComandoO Que TestaRequer Servidor Ativo
npm run buildCompilação TypeScriptNão
npm run test:unit-jsTeste de fumaça de 84 ferramentas, validação de esquema, ACL de autenticaçãoNão
npm run test:adapterAdaptador, lógica de repetição, concorrênciaNão
npm run test:e2eConformidade com o protocolo MCP (Playwright)Não
npm run test:e2e:docker:fullIntegração de pilha completaSim (Docker)
npm run test:integrationVerificações de sanidade do servidor ativoSim
npm run test:integration:fullSuíte completa de integração ativaSim

Níveis de teste de integração (tests/manual/): sanity → smoke → normal → extended → full → cleanup

Consulte tests/manual/README.md e tests/e2e/README.md para detalhes.


Documentação

DocumentoConteúdo
docs/guides/MCP_CLIENTS_SETUP.mdComece aqui para conectar Claude Desktop, Cursor, VS Code (Copilot), Gemini CLI ou Claude Code
docs/guides/AI_CLIENT_SETUP.mdConfiguração do LibreChat e LobeChat, rede Docker, proxy HTTPS/TLS, OIDC
docs/guides/DEPLOYMENT.mdDocker, perfis Docker Compose, configuração de produção, Kubernetes
docs/ARCHITECTURE.mdCamadas de componentes, fluxo de dados, protocolos de transporte
docs/SECURITY_AND_PRIVACY.mdModelos de autenticação, modelo de ameaça, endurecimento
docs/TESTING_AND_RELIABILITY.mdEstratégia de teste, cobertura, padrões de confiabilidade
docs/NEW_TOOL_CHECKLIST.mdGuia passo a passo para adicionar uma nova ferramenta MCP
CONTRIBUTING.mdConfiguração de desenvolvimento, padrões de código, processo de PR
.env.exampleReferência de variáveis de ambiente totalmente anotada

Contribuindo

Contribuições são bem-vindas! Consulte CONTRIBUTING.md para configuração de desenvolvimento, padrões de código e o processo de PR.

Fluxo rápido:

  1. Fork → git checkout -b feature/my-feature
  2. Faça alterações + adicione testes
  3. npm run build && npm run test:unit-js deve passar
  4. Abra um Pull Request

Arquitetura

  • Runtime: Node.js 22 (Alpine Linux no Docker)
  • Linguagem: TypeScript (ESM, resolução de módulo NodeNext)
  • SDK MCP: @modelcontextprotocol/sdk
  • API Actual: @actual-app/api
  • Validação: Zod (tipos em runtime + JSON Schema para entradas de ferramentas)
  • Transportes: Express + StreamableHTTP (--http) · StdioServerTransport (--stdio)
  • Registro: Winston com rotação diária (toda saída roteada para stderr no modo stdio) Toda chamada à API do Actual passa pelo wrapper withActualApi() em src/lib/actual-adapter.ts, que gerencia o ciclo de vida de init/shutdown, tentativas (3 tentativas, backoff exponencial) e limitação de concorrência. Consulte docs/ARCHITECTURE.md para a documentação completa do design.

Licença

MIT. Consulte LICENSE para detalhes.


Agradecimentos


Aviso Legal

Este projeto começou como um exercício pessoal de aprendizado para explorar a tecnologia Model Context Protocol. É um projeto independente de código aberto, não afiliado, endossado ou apoiado pelo Actual Budget ou qualquer outra organização.

O software é fornecido como está, sem garantia de qualquer tipo. O autor não aceita responsabilidade por como ele é usado, por qualquer perda de dados, erros financeiros ou outras consequências decorrentes do seu uso. Se você conectá-lo a dados financeiros reais, faz isso inteiramente por sua conta e risco.


Suporte

  • GitHub Issues: relatórios de bugs, solicitações de recursos, perguntas e ideias

Versão: 0.22.46 | Número de Ferramentas: 84 (compatibilidade LibreChat verificada)

Patrocínio

Eu construo e mantenho isso no meu próprio tempo. É gratuito, permanece gratuito e é mantido de qualquer forma.

Se isso economizou seu tempo e você quiser agradecer, pode fazê-lo em github.com/sponsors/agigante80. Totalmente opcional, e nada sobre o projeto muda de qualquer forma.