Skip to main content
Glama
oliverhubtech-source

MCP Database Server

README.md
# MCP Database Server

**Pilar:** Protocolos, Interoperabilidade & APIs  
**Status:** Mes 1 - essencial

Servidor MCP em Python para expor schemas, queries seguras e stored procedures a clientes LLM.

## Problema

LLMs precisam consultar bancos corporativos sem receber credenciais amplas nem liberdade para executar SQL destrutivo.

## MVP

- Servidor MCP com FastMCP
- Listagem de schemas permitidos
- Queries somente leitura
- Allowlist de stored procedures
- Auditoria de chamadas

## Arquitetura

- MCP server (`mcp.server.MCPServer`, tools registrados via `@mcp.tool()`)
- Schema registry (allowlist de tabelas/colunas, `db.py`)
- Read-only authorizer (`sqlite3.Connection.set_authorizer`, `security.py`)
- Audit logger (trilha em memoria de cada chamada de tool, `audit.py`)

## Diagrama

```mermaid
flowchart LR
    A0[MCP client] --> A1[MCP server: list_tables / describe_table / run_readonly_query]
    A1 --> A2[SQLite authorizer: allowlist + read-only]
    A2 --> A3[SQLite: invoices]
    A1 --> A4[Audit log]
```

## Stack

- Python
- `mcp` (SDK oficial do Model Context Protocol)
- SQLite (`sqlite3` da stdlib, com `set_authorizer` para o controle de acesso)
- unittest
- Docker Compose

## Como executar

Implementacao real com o SDK oficial do MCP. O controle de acesso nao usa
regex sobre o SQL (facil de burlar) - usa o `set_authorizer` do proprio
SQLite, que aprova ou nega cada tabela/coluna lida e cada tipo de statement
antes de qualquer linha rodar. Para rodar o servidor MCP:

```bash
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e .
python -m mcp_database_server   # sobe o servidor MCP via stdio
python -m unittest discover -s tests
```

## Testes

- `test_security.py`: authorizer bloqueia INSERT/UPDATE/DELETE/DROP/ALTER, ATTACH, tabelas fora do allowlist (ex.: `sqlite_master`) e statements empilhados (`SELECT 1; DROP TABLE ...`).
- `test_server.py`: logica de cada tool chamada direto (sem protocolo), incluindo que toda chamada gera um evento de auditoria.
- `test_integration.py`: sobe `python -m mcp_database_server` como subprocesso de verdade e conversa com ele via `mcp.client.stdio` + `ClientSession` - prova que o servidor fala MCP, nao so que as funcoes Python funcionam.

## Riscos e decisoes

- SQL injection e permissao excessiva: resolvido via `set_authorizer` no nivel do driver, nao regex.
- Uma unica conexao SQLite nao e thread-safe; o MCP server despacha cada tool call numa worker thread, entao `ServerState.lock` serializa o acesso (bug real encontrado e corrigido durante a implementacao, coberto por `test_integration.py`).
- Ferramentas MCP retornam `ValueError` com mensagem clara para o cliente LLM em vez de vazar stack trace.

## Proximos passos

- Trocar SQLite por PostgreSQL via SQLAlchemy quando o dado for real.
- Adicionar autenticacao/allowlist por cliente (hoje qualquer client MCP conectado tem acesso as tools).
- Persistir o audit log fora do processo (hoje e so em memoria).

Maintenance

ActivityMaintained
ResponsivenessNo issues