An MCP database gateway for LLM agents: read freely, preview writes, approve explicitly.
securedblink gives an LLM a controlled, auditable way to inspect and query databases through the Model Context Protocol. Read-only work runs immediately; every mutating statement must be previewed, bound to a single-use token, and explicitly approved before it touches the database. Credentials live in your OS credential manager — never in chat history, logs, or tool responses.
Table of Contents
- About
- How it works
- Getting started
- Configure an MCP client
- What it protects
- Supported databases
- Tools
- Credential vault
- Configuration
- Source checkout
- Development
- Security
- License
About
securedblink is a local MCP server that sits between your agent and your databases. You declare connections as DB_<NAME> environment variables — the suffix becomes the connection name exposed to the agent. The server classifies every statement: SELECT, EXPLAIN, SHOW/DESCRIBE, and safe WITH run through query; everything else (INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE…) is forced through the gated path.
Stack: Python 3.12+, SQLAlchemy 2.0, MCP 1.x, structlog, keyring. PostgreSQL and SQLite work out of the box; other dialects load via optional drivers.
Who it's for: engineers who want to let an agent explore schemas and run reads autonomously, but keep every write visible and reversible — ideal for analytics databases, staging environments, and local development.
How it works
Read lane — free. query executes immediately and returns rows capped by DB_MAX_ROWS (default 500).
Write lane — gated. The flow is deliberately visible:
1. Agent → preview_mutation(connection, sql) → securedblink returns plan + one-time token
2. Agent shows preview and asks for confirmation
3. Human approves in the MCP client
4. Agent → execute_mutation(connection, sql, token) → securedblink validates token
5. securedblink executes, consumes the token, returns the result
The token binds the exact SQL string and connection name (SHA-256), expires after 5 minutes, and is single-use. A mismatched connection, altered SQL, expired token, or replay is rejected — even if the agent tries.
Vault lane — isolated. Aliases registered with securedblink register or register-from-path are stored in the OS credential manager (macOS Keychain, Linux Secret Service, Windows Credential Manager). The agent sees only the alias; values are redacted from logs and tool output.
Getting started
1. Install the command
Pick one distribution. The binary is the primary entry point for terminals and MCP clients.
macOS / Linux — standalone binary (recommended):
curl -fsSL https://raw.githubusercontent.com/paulushcgcj/securedblink/main/install.sh | bash
Windows (PowerShell):
irm https://raw.githubusercontent.com/paulushcgcj/securedblink/main/install.ps1 | iex
PyPI / uv — all platforms (use when you need extra drivers):
uv tool install securedblink
# optional drivers
uv tool install 'securedblink[oracle]'
uv tool install 'securedblink[mysql]'
uv tool install 'securedblink[mssql]'
Standalone installers bundle PostgreSQL support only. Install via PyPI/
uv toolwhen you need Oracle, MySQL, or MSSQL drivers.
2. Connect a database
Set one or more DB_<NAME> variables. The suffix becomes the MCP connection name.
export DB_LOCAL=sqlite:///./local.db
export DB_ANALYTICS=postgresql://user:password@db.example.com:5432/analytics
export DB_MAX_ROWS=500 # optional; defaults to 500
Prefer the credential vault for secrets (see below) rather than exporting passwords in plain text. Never commit real credentials.
3. Run it
securedblink
An MCP client can now discover local and analytics, list tables, describe schemas, and run reads. Writes will surface a preview and wait for your explicit approval.
Configure an MCP client
The binary must be on the MCP client's PATH. If it isn't, replace securedblink with its absolute path (e.g. /usr/local/bin/securedblink).
OpenCode
Add to ~/.config/opencode/opencode.jsonc or .opencode.json in a project:
{
"mcp": {
"securedblink": {
"type": "local",
"command": ["securedblink"],
"environment": {
"DB_ANALYTICS": "postgresql://user:password@host:5432/analytics",
"DB_LOCAL": "sqlite:///./local.db",
"DB_MAX_ROWS": "500"
}
}
}
}
VS Code Copilot
Add to .vscode/mcp.json or ~/.vscode/mcp.json:
{
"servers": {
"securedblink": {
"type": "stdio",
"command": "securedblink",
"env": {
"DB_ANALYTICS": "postgresql://user:password@host:5432/analytics",
"DB_LOCAL": "sqlite:///./local.db",
"DB_MAX_ROWS": "500"
}
}
}
}
Keep connection values in your MCP client's environment block or in the vault. Do not commit real credentials to config files.
What it protects
| Operation | Behavior |
|---|---|
SELECT, EXPLAIN, SHOW, DESCRIBE, safe WITH |
Runs immediately through query |
INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, and other writes |
Requires preview_mutation → human approval → execute_mutation |
| Approval token | Binds the exact SQL and connection; 5-minute expiry; single-use |
| Credentials | Vault values stay in the system credential manager and never appear in tool responses or logs |
Supported databases
Any SQLAlchemy-compatible dialect works once its driver is installed. PostgreSQL and SQLite need no extra setup.
| Database | URL example | Install |
|---|---|---|
| PostgreSQL | postgresql://user:pass@host:5432/db |
Included |
| SQLite | sqlite:///./path/to/file.db |
Built in |
| Oracle | oracle+oracledb://user:pass@host:1521/service |
uv tool install 'securedblink[oracle]' |
| MySQL | mysql+pymysql://user:pass@host:3306/db |
uv tool install 'securedblink[mysql]' |
| SQL Server | mssql+pyodbc://user:pass@host/db?driver=... |
uv tool install 'securedblink[mssql]' |
| Snowflake | snowflake://user:pass@account/db/schema |
Install snowflake-sqlalchemy manually |
Tools
| Tool | Purpose |
|---|---|
list_connections |
List environment and vault connections |
list_tables |
List tables and views |
describe_table |
Show columns, keys, foreign keys, and indexes |
query |
Execute read-only SQL |
preview_mutation |
Preview a write and issue an approval token |
execute_mutation |
Execute an approved write |
vault_register_connection |
Store a connection in the credential vault |
vault_register_from_path |
Import a connection from .env, .properties, or YAML |
vault_list |
List vault aliases and metadata |
vault_revoke |
Remove a vault alias |
Credential vault
The vault stores credentials in the platform's secure store so the agent can use an alias without ever receiving the username or password.
Register from the terminal:
securedblink register \
--alias analytics \
--jdbc-url "postgresql://host:5432/analytics" \
--username user \
--password password \
--driver org.postgresql.Driver
securedblink list
Import from a file — allow-list the directory first:
export SECUREDBLINK_ALLOWED_ROOTS="/path/to/configs"
securedblink register-from-path \
--alias analytics \
--file-path /path/to/configs/analytics.env
Supported formats: .env, .properties, and Spring Boot-style .yml/.yaml. Paths outside SECUREDBLINK_ALLOWED_ROOTS are rejected; values are redacted from logs and errors.
Configuration
| Variable | Default | Description |
|---|---|---|
DB_<NAME> |
— | SQLAlchemy URL for a named connection |
DB_MAX_ROWS |
500 |
Maximum rows returned by query |
SECUREDBLINK_ALLOWED_ROOTS |
— | Colon-separated roots allowed for vault file imports |
Source checkout
Use run.sh for development — it syncs the project, reads .env, detects drivers from DB_* URLs, and installs missing drivers before starting:
DB_LOCAL=sqlite:///./local.db ./run.sh
The installed binary does no setup preparation; configure its environment and optional drivers explicitly.
Development
Requirements: Python 3.12+ and uv.
uv sync
uv run pytest -q
uv run ruff check .
uv run mypy --strict securedblink
See CONTRIBUTING.md for the full workflow and release process.
Security
Please report vulnerabilities according to SECURITY.md. Never place real database credentials in issues, pull requests, or committed config files.
License
Distributed under GPL-3.0.
Built for teams who let agents read, but never write silently.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file securedblink-0.8.0.tar.gz.
File metadata
- Download URL: securedblink-0.8.0.tar.gz
- Upload date:
- Size: 169.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae0b0f10247b1fb6021dddb89f8fa8cf455aaca6aa896c02b53eb53bb2f52319
|
|
| MD5 |
ec830ea95ca1b5661891146d8b00e99e
|
|
| BLAKE2b-256 |
072fc5ef287d00a949d0fc60a8ce290980b631cc532843000c3ba5f8b35f9435
|
File details
Details for the file securedblink-0.8.0-py3-none-any.whl.
File metadata
- Download URL: securedblink-0.8.0-py3-none-any.whl
- Upload date:
- Size: 44.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d2ab200a9ad72b252bf830b1e6420efbb9a5543de7ced515485732735be7f89
|
|
| MD5 |
404395b5341aa36e345c1a0ebcb64b71
|
|
| BLAKE2b-256 |
049ba76b8d2c5fa007b6a5f02baba417c891686a1a145a3f4284b681857cd90b
|