The all-seeing watchman of the bridge between AI and Data.
Heimdall is a Universal Multi-Database MCP (Model Context Protocol) Server written in Go. It sits between AI models and your databases, enforcing granular permissions, data masking, and query safety — so models can query data without unrestricted access.
# Build
go build -o heimdall ./cmd/heimdall
# Run
./heimdall -config heimdall.yaml
# Verify database connectivity
./heimdall -config heimdall.yaml -verifyAdd Heimdall to your Claude Desktop MCP configuration (claude_desktop_config.json):
{
"mcpServers": {
"heimdall": {
"command": "/path/to/heimdall",
"args": ["-config", "/path/to/heimdall.yaml"]
}
}
}Heimdall communicates over stdio using JSON-RPC. Claude Desktop will see dynamically generated tools for each configured database (e.g., inspect_finance_db, read_finance_db, task_finance_db).
Heimdall is configured via a YAML file. See examples/heimdall.yaml for a fully commented example.
version: "1.0"
databases:
- id: my_db
type: sqlite
dsn: "file:./data.db"version: "1.0"
server:
port: 3000 # Currently unused (stdio transport)
log_level: "info" # debug, info, warn, error — logs go to stderr
defaults:
read_timeout: "30s" # Default query timeout per database
max_rows: 1000 # Default row limit injected into SELECT queries
databases:
- id: "finance_db" # Unique identifier (alphanumeric + underscore)
type: "postgres" # postgres, mysql, mssql, oracle, sqlite
dsn: "postgres://user:pass@host:5432/db"
allowed_operations: # Default: [SELECT]
- SELECT
- INSERT
allow_list: # Restrict to specific tables (empty = all)
- transactions
- accounts
masking:
salt: "your-secret-salt" # For deterministic hashing
rules:
- table: users
column: email
action: redact # Replaces with [REDACTED]
- table: transactions
column: account_id
action: hash # Salted SHA-256 hash
resources: # Custom MCP resource endpoints
- name: daily_summary
description: "Daily transaction summary"
sql: "SELECT date, SUM(amount) FROM transactions GROUP BY date"
read_timeout: "5s" # Overrides defaults.read_timeout
max_rows: 200 # Overrides defaults.max_rowsDSN strings support environment variable expansion:
dsn: "postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:5432/mydb"| Database | Driver | Read-Only Session |
|---|---|---|
| PostgreSQL / CockroachDB | github.com/jackc/pgx/v5 |
SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY |
| MySQL / MariaDB | github.com/go-sql-driver/mysql |
SET SESSION TRANSACTION READ ONLY |
| SQL Server | github.com/microsoft/go-mssqldb |
Not supported (AST enforcement only) |
| Oracle | github.com/sijms/go-ora/v2 |
Not supported (AST enforcement only) |
| SQLite | modernc.org/sqlite |
PRAGMA query_only = ON |
All drivers are pure Go — no CGO required. The binary cross-compiles for Mac, Windows, and Linux.
Heimdall enforces a multi-layered security pipeline (SafeGuard) on every query:
- AST Parsing — SQL is parsed into an AST (vitess-based parser) to identify statement type. No keyword matching.
- Operation Enforcement — Statement type checked against the per-database
allowed_operationswhitelist. - Table Allow-List — If configured, only queries targeting listed tables are permitted.
- Multi-Statement Rejection — Semicolon-separated queries are blocked.
- Read-Only Session — When only SELECT is allowed, the database connection is set to read-only mode (where supported) as defense-in-depth.
- Auto-Limit Injection — Row limits injected using dialect-specific syntax (
LIMIT,TOP,FETCH FIRST). Existing limits abovemax_rowsare replaced. - Context Timeout — Every query is wrapped in a context with a configurable deadline.
- Data Masking — Sensitive columns are redacted (
[REDACTED]) or hashed (salted SHA-256) before results reach the AI model.
For each configured database, Heimdall dynamically generates MCP tools:
| Tool | Purpose | Registered When |
|---|---|---|
inspect_<id> |
Schema introspection (tables, columns, types) | Always |
read_<id> |
Execute SELECT queries | SELECT in allowed_operations |
task_<id> |
Execute mutations (INSERT/UPDATE/DELETE) | Any non-SELECT operation allowed |
The inspect tool implements token economy protection — if the database has more than 50 tables, it returns only table names with a hint to filter, avoiding context window bloat.
Each database also exposes MCP resource endpoints:
<id>://schema— Full schema as JSON<id>://<resource_name>— Results of custom queries defined in configresources
The -verify flag pings all configured databases and reports health:
./heimdall -config heimdall.yaml -verifyOutput goes to stderr as JSON followed by a human-readable summary. Exit code 0 if all databases are healthy, 1 if any failed.
- Go 1.21+
- Docker (for integration tests)
# Unit tests
go test ./...
# Static analysis
go vet ./...
# All integration tests (requires Docker for Testcontainers)
go test -tags integration ./integration/...
# Single-dialect integration tests
go test -tags integration -run TestPostgres ./integration/...
go test -tags integration -run TestMySQL ./integration/...
go test -tags integration -run TestMSSQL ./integration/...
go test -tags integration -run TestOracle ./integration/...
go test -tags integration -run TestSQLite ./integration/...
# Full MCP protocol integration test
go test -tags integration -run TestMCP ./integration/...Integration tests use testcontainers-go to spin up real database instances. Oracle tests may take longer due to container startup time.
cmd/heimdall/ Entry point and CLI
internal/
config/ YAML config loading and validation
database/ Dialect registry, driver abstraction, connection manager
safeguard/ SQL analyzer, enforcer, limiter, timeout
execution/ Query execution pipeline
masking/ Data masking (redact/hash)
mcp/ MCP server wrapper
tools/ Dynamic tool registration
resources/ MCP resource endpoints
verify/ Health check for --verify
integration/ Testcontainers-based integration tests
testdata/ Test configuration files
examples/ Example configuration
| Flag | Description |
|---|---|
-config <path> |
Path to YAML config file (required) |
-verify |
Ping all databases and report health, then exit |
-version |
Print version and exit |
See LICENSE for details.