a2db

Acesso a múltiplos bancos de dados (PostgreSQL, SQLite, MySQL, Oracle, SQL Server) com consultas em lote, conexões pré-configuradas e segurança somente leitura imposta pelo SQLGlot

Documentação

Translation

🗄️ a2db

Agent-to-Database

Dê aos agentes de IA acesso seguro e somente leitura aos seus bancos de dados. Uma chamada, várias consultas, resultados limpos.

5 bancos de dados · consultas em lote · conexões pré-configuradas · somente leitura com SQLGlot

PyPI Python versions License CI MCP Registry

Início Rápido · Ferramentas MCP · Segurança · Comparação · Configuração


Agent: "Show me active users and their recent orders"
  ↓
a2db execute → 2 queries, 1 call, structured results
  ↓
Agent: "Got it — 847 active users, avg order $42.50"

Por que a2db?

A maioria dos servidores MCP de banco de dados faz você executar uma consulta por vez, repetir os detalhes da conexão em cada chamada e retornar resultados duplamente codificados dentro de strings JSON. O a2db resolve tudo isso:

  • Conexões pré-configuradas — defina bancos de dados em .mcp.json com --register, o agente consulta imediatamente
  • Consultas em lote — execute várias consultas nomeadas em uma única chamada de ferramenta
  • Conexão padrão — defina a conexão uma vez, use-a em todas as consultas de um lote
  • Saída limpa — envelope JSON estruturado com dados TSV compactos e tempo por consulta (veja por que TSV?)
  • Somente leitura imposto — a análise AST do SQLGlot bloqueia todas as operações de escrita
  • Todos os drivers incluídospip install a2db e pronto
  • Segredos ficam no ambiente${DB_PASSWORD} em DSNs, expandidos apenas no momento da conexão

Bancos de Dados Suportados

Banco de DadosDriverAssíncrono
PostgreSQLasyncpgnativo
SQLiteaiosqlitenativo
MySQL / MariaDBmysql-connector-pythonencapsulado
Oracleoracledbencapsulado
SQL Serverpymssqlencapsulado

Início Rápido

pip install a2db

Como um Servidor MCP (recomendado)

Claude Code (com conexão pré-configurada):

claude mcp add -s user a2db -- a2db-mcp \
  --register myapp/prod/main 'postgresql://user:${DB_PASSWORD}@host/mydb'

Claude Code (mínimo — o agente chama login sob demanda):

claude mcp add -s user a2db -- a2db-mcp

Claude Desktop / Cursor / qualquer cliente MCP (.mcp.json):

{
  "mcpServers": {
    "a2db": {
      "command": "uvx",
      "args": [
        "a2db-mcp",
        "--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/mydb"
      ],
      "env": {
        "DB_PASSWORD": "your-password-here"
      }
    }
  }
}

Múltiplos bancos de dados:

{
  "args": [
    "a2db-mcp",
    "--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/maindb",
    "--register", "myapp/prod/analytics", "postgresql://user:${DB_PASSWORD}@host/analytics"
  ]
}

--register pré-registra conexões na inicialização do servidor — o agente pode consultar imediatamente. Senhas usam a sintaxe ${ENV_VAR} e são expandidas no momento da conexão, nunca armazenadas em texto simples.

Como CLI

# Save a connection (validates immediately)
a2db login -p myapp -e prod -d main 'postgresql://user:${DB_PASSWORD}@localhost/mydb'

# Query
a2db query -p myapp -e prod -d main "SELECT * FROM users LIMIT 10"

# JSON output
a2db query -p myapp -e prod -d main -f json "SELECT * FROM users LIMIT 10"

# Explore schema
a2db schema -p myapp -e prod -d main tables
a2db schema -p myapp -e prod -d main columns -t users

# List / remove connections
a2db connections
a2db logout -p myapp -e prod -d main

Ferramentas MCP

FerramentaDescrição
loginSalva uma conexão — valida conectando primeiro
logoutRemove uma conexão salva
list_connectionsLista conexões (sem expor segredos)
executeExecuta consultas nomeadas em lote com paginação
search_objectsExplora o esquema — tabelas, colunas, com níveis de detalhe

execute — a ferramenta central

Dict nomeado com conexão padrão (preferido):

{
  "connection": {"project": "myapp", "env": "prod", "db": "main"},
  "queries": {
    "active_users": {"sql": "SELECT id, name FROM users WHERE active = true"},
    "recent_orders": {"sql": "SELECT id, total FROM orders ORDER BY created_at DESC LIMIT 5"}
  }
}

Formato de lista (nomeados automaticamente q1, q2, ...):

{
  "connection": {"project": "myapp", "env": "prod", "db": "main"},
  "queries": [
    {"sql": "SELECT COUNT(*) AS cnt FROM users"},
    {"sql": "SELECT AVG(total) AS avg_order FROM orders"}
  ]
}

Resposta (formato TSV — padrão):

{
  "active_users": {
    "data": "id\tname\n1\tAlice\n2\tBob\n3\tCharlie",
    "rows": 3,
    "truncated": false,
    "time_ms": 12
  },
  "recent_orders": {
    "data": "id\ttotal\n501\t129.00\n500\t49.99",
    "rows": 2,
    "truncated": false,
    "time_ms": 8
  }
}

Sem conversões ::text — inteiros, floats, timestamps, arrays, NULLs funcionam nativamente.

Contexto de erro

Quando uma consulta falha com erro de coluna, o a2db enriquece a mensagem:

column "nme" does not exist
Did you mean: name?
Available columns: id (integer), name (text), email (text), active (integer)

Por que TSV?

Janelas de contexto de LLM são caras. Dados de linha em JSON são verbosos — cada linha repete o nome de cada coluna, adiciona chaves, vírgulas e aspas. TSV é uma grade plana: uma linha de cabeçalho, depois apenas valores separados por tabulações.

Para um conjunto de resultados de 100 linhas e 5 colunas, TSV normalmente usa 40-60% menos tokens que o formato JSON de linhas. O envelope JSON estruturado ainda fornece metadados (contagem de linhas, status de truncamento) — apenas o payload de linhas é TSV.

Defina format="json" se precisar de saída totalmente estruturada com nomes de colunas em cada linha.

Segurança

Imposição de Somente Leitura

Cada consulta é analisada por SQLGlot antes da execução:

  • Bloqueados: INSERT, UPDATE, DELETE, DROP, TRUNCATE, ALTER, CREATE, GRANT, REVOKE
  • À prova de bypass: ataques de múltiplas instruções e escritas envolvidas em comentários são detectados no nível da AST, não apenas por correspondência de palavras-chave
  • Permitidos: SELECT, UNION, EXPLAIN, SHOW, DESCRIBE, PRAGMA

Isto é defesa em profundidade — você também deve usar um usuário de banco de dados somente leitura, mas o a2db não deixa escritas passarem mesmo que o usuário tenha permissões de escrita.

Suporte a escrita está implementado no núcleo, mas ainda não exposto via MCP. Planejado: permissões de escrita por conexão, habilitadas explicitamente pelo operador humano — não pelo agente. Veja TODO.md.

Armazenamento de Credenciais

Conexões são salvas em ~/.config/a2db/connections/ como arquivos TOML.

  • Sintaxe ${DB_PASSWORD} — referências a variáveis de ambiente são armazenadas literalmente e expandidas apenas no momento da conexão. Segredos permanecem no seu ambiente, não no disco.
  • Sem segredos na saída de listagemlist_connections mostra projeto/env/db e tipo de banco de dados, nunca DSNs ou senhas
  • Arquivos de conexão são locais à sua máquina e fora de qualquer repositório

Escopo de Implantação

O a2db atualmente roda como um servidor MCP stdio local. Ele herda variáveis de ambiente do processo que o inicia (seu shell, Claude Code, Docker). Este é o modelo padrão para servidores MCP locais — a mesma abordagem usada por DBHub, Google Toolbox e outros.

Planejado: transporte HTTP remoto com OAuth 2.1 conforme a especificação MCP. Por enquanto, se rodando em Docker, injete segredos via variáveis de ambiente no tempo de execução do contêiner.

Comparação

Recursoa2dbDBHubGoogle ToolboxPGMCPSupabase MCP
Bancos de dados5 (PG, SQLite, MySQL, Oracle, MSSQL)5 (PG, MySQL, MSSQL, MariaDB, SQLite)40+ (nuvem + OSS)somente PGPG (Supabase)
Consultas em loteDict nomeado + listaSeparado por ponto e vírgulaNãoNãoNão
Conexão padrãoDefina uma vez, use para todasPor consultaN/ABanco únicoProjeto único
Somente leituraSQLGlot AST (imposto)Verificação de palavras-chave (config)Dica/anotaçãoTransação somente leitura + regexFlag de configuração
Suporte a escritaPlanejado (por conexão)Flag de configuraçãoVia definição de ferramentaNãoFlag de configuração
SaídaJSON + dados TSVTexto estruturadoProtocolo MCPTabela / JSON / CSVJSON
Descoberta de esquema3 níveis de detalheFerramenta dedicadaFerramentas prontasVia NL-para-SQLFerramentas dedicadas
Pré-configurado--register na configuração MCPArquivo de configuraçãoConfig YAMLVariável de ambienteGerenciado na nuvem
Credenciais${ENV_VAR} em DSNStrings DSNVariáveis de ambiente + IAM GCPVariável de ambienteOAuth 2.1
Drivers incluídosTodos incluídosTodos incluídosVariadosIntegradosGerenciados
CLISimNãoSimSimNão
Contexto de erroSugestões de coluna + tiposNãoNãoNãoNão
LicençaApache 2.0MITApache 2.0Apache 2.0Apache 2.0

Quando usar o quê:

  • a2db — consultas em lote multi-banco com saída limpa, design agent-first, configuração rápida
  • DBHub — ferramentas personalizadas via configuração TOML, interface web de workbench
  • Google Toolbox — ecossistema GCP, integração IAM, 40+ fontes
  • PGMCP — linguagem natural para SQL no PostgreSQL (requer chave OpenAI)
  • Supabase MCP — gerenciamento completo da plataforma Supabase (edge functions, branch, storage)

Configuração por Ambiente

Local (macOS / Linux)

pip install a2db

# CLI
a2db login -p myapp -e dev -d main 'postgresql://user:pass@localhost/mydb'

# Or add as MCP server (see Quick Start)

Docker

FROM python:3.12-slim
RUN pip install a2db
CMD ["a2db-mcp", "--register", "myapp/prod/main", "postgresql://user:${DB_PASSWORD}@host/mydb"]
docker run -e DB_PASSWORD=secret -i my-a2db-image

Segredos são injetados como variáveis de ambiente em tempo de execução — nunca gravados na imagem.

CI / Automação

pip install a2db

# Pre-configured — no login needed
a2db-mcp --register myapp/ci/main "postgresql://ci_user:${CI_DB_PASSWORD}@db-host/mydb"

# Or use CLI directly
a2db login -p myapp -e ci -d main "postgresql://ci_user:${CI_DB_PASSWORD}@db-host/mydb"
a2db query -p myapp -e ci -d main "SELECT COUNT(*) FROM migrations"

Desenvolvimento

make bootstrap   # Install deps + hooks
make check       # Lint + test + security (full gate)
make test        # Tests with coverage (90% minimum)
make lint        # Lint only (never modifies files)
make fix         # Auto-fix + lint

Licença

Apache 2.0


🗄️ Acesso a banco de dados agent-first desde 2025.

Construído por Denis Tomilin