Enpass MCP

Lê e grava cofres locais do Enpass: entradas, senhas e códigos TOTP, com a senha mestra obtida do chaveiro do sistema operacional para que nunca chegue ao modelo.

Documentação

enpass-mcp

Um servidor Model Context Protocol (MCP) que dá a um assistente de IA acesso controlado e local aos seus cofres de senhas do Enpass: desbloqueie um cofre, liste cofres, e liste e leia entradas. Criar e excluir entradas também é possível, mas fica desativado até que você habilite.

Executa localmente via stdio. Seu cofre do Enpass nunca sai da sua máquina, e sua senha mestra nunca passa pelo modelo: ela é armazenada no chaveiro do seu sistema operacional e lida diretamente pelo servidor.

Por que isso é seguro

  • Senhas mestras ficam no chaveiro do SO (Keychain do macOS, Gerenciador de Credenciais do Windows, Secret Service do Linux), não em arquivos de configuração, não em variáveis de ambiente, e nunca como argumento de ferramenta. A ferramenta unlock_vault deliberadamente não aceita parâmetro de senha, então a senha nunca pode acabar no contexto do modelo ou em logs.
  • O cofre permanece local. O servidor lê o arquivo vault.enpassdb criptografado diretamente com SQLCipher. Nada é enviado para lugar algum.
  • Leituras são explícitas. Listar entradas nunca retorna senhas. Segredos só são retornados por get_item / get_password, quando você os solicita explicitamente.
  • Somente leitura, a menos que você diga o contrário. Por padrão, o servidor não pode alterar nada: as ferramentas de escrita nem são anunciadas. Defina ENPASS_MCP_ALLOW_WRITES=1 para habilitá-las (veja Escrita).

As senhas das entradas são, por design, retornadas ao assistente quando você as solicita, então conecte apenas a um assistente e cofres em que você confia.

Requisitos

  • Node.js 18 ou mais recente
  • Um cofre Enpass 6 / 7 / 8 (vault.enpassdb, formato SQLCipher)
  • No Linux: um provedor de Secret Service (GNOME Keyring ou KWallet) para armazenamento de senhas

Dependências nativas (better-sqlite3-multiple-ciphers, @napi-rs/keyring) incluem binários pré-compilados para plataformas comuns, então nenhum compilador é necessário no caso normal.

Instalação

git clone https://github.com/bitterdev/enpass-mcp.git
cd enpass-mcp
npm install
npm link   # optional: makes the `enpass-mcp` command available globally

Registre seus cofres (faça isso uma vez, em um terminal)

Este é o passo seguro que mantém a senha mestra longe do modelo. Você mesmo o executa; a senha é digitada em um prompt oculto e armazenada no chaveiro do SO.

# Find your vault files automatically
enpass-mcp discover

# Register a vault (you will be prompted for the master password)
enpass-mcp add-vault personal --path "/Users/you/Documents/Enpass/Vaults/primary/vault.enpassdb"
enpass-mcp add-vault work     --path "/path/to/work/vault.enpassdb"

# With a keyfile
enpass-mcp add-vault personal --path "/path/vault.enpassdb" --keyfile "/path/vault.keyfile"

# Manage
enpass-mcp list-vaults
enpass-mcp test-unlock personal
enpass-mcp remove-vault work

add-vault verifica se a senha realmente consegue desbloquear o cofre antes de salvá-la.

O arquivo do cofre geralmente é encontrado em:

SOLocalização típica
macOS~/Documents/Enpass/Vaults/<vault>/vault.enpassdb
Windows%USERPROFILE%\Documents\Enpass\Vaults\<vault>\vault.enpassdb
Linux~/Documents/Enpass/Vaults/<vault>/vault.enpassdb

Se você sincroniza via Dropbox / OneDrive / WebDAV, aponte --path para a cópia sincronizada.

Conecte-o ao seu assistente

O servidor fala MCP via stdio. Aponte seu cliente MCP para enpass-mcp serve.

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "enpass": {
      "command": "enpass-mcp",
      "args": ["serve"]
    }
  }
}

Se você não executou npm link, use o caminho absoluto:

{
  "mcpServers": {
    "enpass": {
      "command": "node",
      "args": ["/absolute/path/to/enpass-mcp/src/cli.js", "serve"]
    }
  }
}

Claude Code:

claude mcp add enpass -- enpass-mcp serve

Ferramentas

FerramentaDescrição
list_vaultsLista cofres registrados, se o arquivo existe, se uma senha está armazenada e se estão desbloqueados.
unlock_vaultDesbloqueia um cofre usando a senha mestra do chaveiro do SO. Aceita apenas um nome de cofre, nunca uma senha.
lock_vaultBloqueia um cofre e limpa sua chave derivada da memória.
list_itemsLista entradas (título, nome de usuário, URL). Nunca retorna senhas. Suporta query, category, folder, limit.
get_itemRetorna uma entrada completa, incluindo todos os valores de campos (senha, TOTP, etc.) e sua lista de anexos.
get_passwordRetorna a senha e, se presente, o código TOTP atual de uma entrada.
get_otpGera o código TOTP / 2FA de uso único atual para uma entrada, com os segundos até a rotação.
list_attachmentsLista os anexos de arquivo de uma entrada (nome, tamanho, MIME).
export_attachmentDescriptografa um anexo; grava-o em disco e retorna o caminho (ou base64 inline para arquivos pequenos).
sync_statusLista os cofres que usam sincronização de pasta do Enpass e se a cópia na pasta de sincronização é mais recente.

Com ENPASS_MCP_ALLOW_WRITES=1, mais três ferramentas aparecem (veja Escrita):

FerramentaDescrição
create_itemCria uma entrada, incluindo campos personalizados; valores sensíveis são criptografados da forma que o Enpass faz.
delete_itemExclui uma entrada, ou a move para a lixeira, deixando o tombstone que o Enpass usa para que a exclusão seja sincronizada.
sync_pullAceita uma cópia mais recente da pasta de sincronização, após fazer backup do cofre local.

list_items / get_item funcionam para todos os tipos de entrada do Enpass (logins, cartões de crédito, notas seguras, identidades, etc.), não apenas logins, e retornam todos os campos.

Um fluxo típico de assistente: list_vaultsunlock_vaultlist_itemsget_password.

Como funciona

O Enpass armazena cada cofre como um banco de dados SQLCipher padrão (vault.enpassdb). A chave de criptografia bruta é derivada da sua senha mestra (opcionalmente combinada com um keyfile) e do salt de 16 bytes no início do arquivo:

  • PBKDF2-HMAC-SHA512, 100000 iterações (cofres mais antigos) ou 320000 (cofres mais novos), os primeiros 32 bytes usados como chave SQLCipher bruta
  • aberto com cipher_compatibility 4 (Enpass 6.8+) ou 3 (cofres mais antigos)

O servidor tenta essas combinações automaticamente, então funciona em todas as versões de cofre do Enpass. A chave derivada é mantida apenas em memória, durante a vida útil do processo do servidor, e nunca é gravada em disco ou retornada ao modelo.

Referências: Enpass Security Whitepaper, hazcod/enpass-cli.

Criptografia de campos por item

O Enpass criptografa cada valor marcado como "sensível" uma segunda vez, por baixo do SQLCipher, com uma chave que pertence à entrada, não ao cofre. Campos que carregam essa camada têm itemfield.algo_version = 1:

PeçaOndeLayout
Chave e nonceitem.key44 bytes: chave AES-256 de 32 bytes, depois um nonce GCM de 12 bytes
Valoritemfield.valuehex de ciphertext || 16-byte GCM tag
Dados adicionaiso uuid da entradahífens removidos, hex-decodificado para 16 bytes brutos

Vincular o AAD ao uuid da entrada é o que torna um valor inutilizável se for copiado para outra entrada. O Enpass não re-criptografou entradas existentes quando introduziu essa camada, então um cofre mistura texto cifrado e texto puro sob o mesmo algo_version; um valor é tratado como criptografado apenas quando tem a forma de um payload (hex puro, bytes inteiros, mais longo que o tag sozinho).

Um valor que parece criptografado, mas falha na autenticação, é retornado como null com decryptionFailed: true, nunca como o conteúdo bruto da coluna: texto cifrado armazenado é uma string de aparência plausível, e devolvê-lo passaria silenciosamente um segredo errado como se fosse real.

Códigos de dois fatores (TOTP)

Entradas com um segredo de senha de uso único (armazenado pelo Enpass como uma URI otpauth://) podem produzir um código 2FA ao vivo: get_otp retorna o código atual de 6 dígitos e os segundos até a rotação, e get_password inclui o código atual junto com a senha. Isso permite que um assistente preencha tanto a senha quanto o prompt de 2FA.

Anexos

O Enpass mantém anexos de arquivo criptografados. Arquivos pequenos (até 1 KB) ficam inline no cofre; arquivos maiores ficam em arquivos <uuid>.enpassattach SQLCipher separados ao lado do cofre, cada um criptografado com sua própria chave armazenada no cofre. export_attachment lida com ambos: descriptografa o arquivo e, por padrão, grava-o em disco e retorna o caminho, então funciona para arquivos de qualquer tamanho sem enviar dados binários pelo modelo.

O tratamento de anexos externos é implementado a partir do formato documentado do Enpass. Se você encontrar um cofre cujos anexos não descriptografam, abra uma issue com o esquema (não secreto) da sua tabela attachment.

Escrita (opt-in)

A escrita está desativada por padrão. Um cofre de senhas é o último lugar onde uma ferramenta deveria poder alterar dados só porque um modelo decidiu, então o servidor inicia somente leitura e nem lista create_item, delete_item e sync_pull até que você os ative:

ENPASS_MCP_ALLOW_WRITES=1

Defina-o no ambiente do servidor (na configuração do seu cliente MCP, ou no .env ao lado de vaults.json). Nada mais muda: a leitura funciona exatamente da mesma forma de qualquer maneira.

O Enpass deve estar fechado durante a escrita. O aplicativo mantém o banco de dados em memória e gravaria sua própria cópia em cache por cima de qualquer alteração feita por baixo. Toda ferramenta de escrita se recusa a executar enquanto o Enpass estiver aberto.

Versões anteriores deste README afirmavam que a escrita era impossível porque cofres recentes (schema versão 6) travam o Enpass quando entradas são inseridas diretamente. O travamento era real, o diagnóstico estava errado. Três regras concretas fazem funcionar, todas derivadas do que o próprio Enpass grava:

  1. O Enpass nunca armazena NULL. O travamento é EXC_BAD_ACCESS em strlen em um ponteiro nulo: uma coluna omitida do INSERT assume o padrão NULL, e o aplicativo chama strlen nela. Toda coluna é gravada explicitamente, strings vazias em vez de NULL.
  2. Um template tem um conjunto fixo de campos. login.default sempre carrega os mesmos nove campos, na mesma ordem, com os mesmos uids de campo, mesmo quando a maioria está vazia. Gravar apenas os campos para os quais você tem um valor produz uma entrada que o aplicativo não consegue renderizar.
  3. A chave por item é reproduzível. item.key é uma chave AES-256 de 32 bytes mais um nonce GCM de 12 bytes, armazenada como hex(ciphertext || tag) com o UUID do item como dados autenticados adicionais. Nada nela está ligado a internals do Enpass, então uma chave aleatória nova por item é suficiente.

Verificado de ponta a ponta contra um cofre real: gravado, lido de volta, descriptografado para o original, excluído, sincronizado em ambas as direções, e o Enpass abre o cofre sem travar.

Configuração

As senhas mestras estão no chaveiro do SO; apenas dados não secretos (nomes e caminhos de cofres) são armazenados em um pequeno vaults.json:

  • macOS: ~/Library/Application Support/enpass-mcp/vaults.json
  • Windows: %APPDATA%\enpass-mcp\vaults.json
  • Linux: ~/.config/enpass-mcp/vaults.json

Substitua o diretório com ENPASS_MCP_CONFIG_DIR.

Variáveis de ambiente:

VariávelEfeito
ENPASS_MCP_ALLOW_WRITES1, true, yes ou on habilita as ferramentas de escrita. Qualquer outra coisa, incluindo não definida, mantém o servidor somente leitura.
ENPASS_MCP_CONFIG_DIROnde vaults.json e o opcional .env ficam.
ENPASS_MASTER_PASSWORDSenha mestra de fallback opcional para cofres sem entrada no chaveiro. Prefira o chaveiro.
ENPASS_MASTER_PASSWORD_<VAULT>O mesmo, para um cofre específico.

Desenvolvimento

npm test                    # runs against genuine SQLCipher fixtures in test/fixtures

# Rebuild the fixtures from scratch with real SQLCipher (vault + entries + attachments)
npm install --no-save @journeyapps/sqlcipher
npm run generate-fixtures

CI (GitHub Actions) cria um cofre do zero com SQLCipher real, semeia entradas e anexos, e então executa a suíte de testes completa somente leitura no Node 18/20/22.

Notas de segurança e limitações

  • Qualquer pessoa que possa falar com este servidor MCP pode ler todas as senhas de um cofre uma vez que ele esteja desbloqueado. Conecte apenas clientes confiáveis.
  • O servidor não implementa sincronização do Enpass, histórico de itens ou lixeira.
  • O servidor é somente leitura e nunca modifica um cofre. Criar ou editar entradas não é suportado intencionalmente, porque gravações diretas no banco de dados travam cofres recentes do Enpass (veja Por que não há suporte a escrita).
  • Este é um projeto independente e não é afiliado ou endossado pelo Enpass.

Licença

MIT © Fabian Bitter