Content
# db-tool-mcp
[](examples/db-tool-mcp.png)
> **Execute SQL queries with sandboxed Perl code filtering — the only MCP server with built-in Safe sandbox for row-level data processing.**
[](https://www.perl.org/)
[](https://modelcontextprotocol.io)
[](LICENSE)
## Features
- **SQL queries** — SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, PRAGMA, and more
- **Sandboxed Perl code (`code` parameter)** — filter and transform rows **on the server side** using Perl's built-in `Safe` module. The code runs in an isolated environment — no other language offers this out of the box.
- **List tables** — show all tables in the database
- **Inspect tables** — show column names, types, and metadata
- **Transactions** — `begin_work`, `commit`, `rollback`
- **Bind parameters** — safe parameterized queries
- **Multiple database engines** — SQLite, MySQL, PostgreSQL, and any DBI-supported driver
- **Lazy connection** — connects once, reuses across requests
- **Zero external dependencies** for the core sandbox — `perl`, `JSON`, `DBI`, and `DBD::*` are all you need
## Why Perl?
| Feature | Perl | Python | JavaScript | Lua |
|---------|------|--------|------------|-----|
| Built-in sandbox | ✅ `Safe` module in core | ❌ No built-in sandbox | ❌ `vm` module is leaky | ❌ No built-in sandbox |
| Row-level filtering | ✅ `code` parameter | ❌ Must install extra libs | ❌ Must write own sandbox | ❌ Must write own sandbox |
| Executable | One file, zero build | Needs venv | Needs npm install | Needs luarocks |
| DBI support | ✅ SQLite, MySQL, Pg, etc. | ✅ (separate drivers) | ✅ (separate libs) | ✅ (separate libs) |
**Perl's `Safe` module is the only built-in, production-tested sandbox among all major dynamic languages.** It has been part of Perl since 1994 and is audited for security.
## Installation
### Prerequisites
```bash
# Perl modules
sudo cpan JSON DBI
# Or on Arch Linux:
sudo pacman -S perl-json perl-dbi perl-dbd-sqlite
# For other database drivers (MySQL, PostgreSQL):
sudo cpan DBD::mysql DBD::Pg
```
### Setup
1. Clone the repository:
```bash
git clone https://github.com/kirill-scherba/db-tool-mcp.git
cd db-tool-mcp
chmod +x db-tool-mcp.pl
```
2. Add to your MCP settings file (usually `cline_mcp_settings.json` for Cline, or `claude_desktop_config.json` for Claude Desktop app):
```json
{
"mcpServers": {
"db-tool": {
"command": "perl",
"args": ["/path/to/db-tool-mcp/db-tool-mcp.pl"],
"env": {},
"disabled": false,
"autoApprove": []
}
}
}
```
## Usage
### Basic SQL Query
```json
{
"query": "SELECT * FROM users LIMIT 10",
"db_name": "/path/to/database.db"
}
```
### List Tables
```json
{
"list_tables": true,
"db_name": "/path/to/database.db"
}
```
### Inspect Table Schema
```json
{
"inspect_table": { "table": "users" },
"db_name": "/path/to/database.db"
}
```
### Sandboxed Perl Code Filtering (`code` — the killer feature)
The `code` parameter allows AI assistants to pass Perl code that runs **for each row** in a sandboxed environment. This offloads filtering to the database server, reducing data transfer.
```json
{
"query": "SELECT * FROM users",
"db_name": "/path/to/database.db",
"code": "length($row->{name}) > 5 && $row->{id} % 2 == 1"
}
```
**How it works:**
```
Client (AI) MCP Server (Perl)
│ │
│ tools/call │
│ { query, code } │
│──────────────────────────────────> │
│ │
│ execute SQL
│ fetch rows one by one
│ for each row:
│ eval $code in Safe sandbox
│ if true → keep
│ if false → skip
│ │
│ { count: 3, data: [...] } │
│<────────────────────────────────── │
```
**More `code` examples:**
```perl
# Filter by string length
length($row->{name}) > 5
# Case-insensitive regex match
lc($row->{email}) =~ /\@company\.com$/
# Numeric comparison
$row->{price} < 500 && $row->{rating} > 4.0
# Array/list size (if the column is a delimited string)
scalar(split(',', $row->{tags})) >= 3
# Date comparison
$row->{created_at} gt '2026-01-01'
# String transformation
ucfirst(lc($row->{name}))
```
### Transactions
```json
{
"begin_work": true,
"db_name": "/path/to/database.db"
}
{
"query": "INSERT INTO users (name) VALUES (?)",
"bind": ["Alice"],
"db_name": "/path/to/database.db"
}
{
"commit": true,
"db_name": "/path/to/database.db"
}
```
### Using Different Database Engines
```json
{
"query": "SELECT * FROM products",
"db_driver": "mysql",
"db_host": "localhost",
"db_port": 3306,
"db_name": "shop",
"db_user": "root",
"db_password": "secret"
}
```
## Quick Test
```bash
cd /path/to/db-tool-mcp
# Create a test database
sqlite3 test.db "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT); INSERT INTO test VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie');"
# Test the server with a single request
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}' | perl db-tool-mcp.pl 2>/dev/null
# Or run a full test sequence
printf '{"jsonrpc":"2.0","id":1,"method":"initialize"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"db_execute","arguments":{"query":"SELECT * FROM test","db_name":"test.db"}}}
' | perl db-tool-mcp.pl 2>/dev/null
```
## Architecture
```
┌──────────────────────────────────────────────────────────┐
│ MCP Client (AI) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │initialize│ │tools/list│ │tools/call│ │tools/call│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ JSON-RPC 2.0 over stdin/stdout │
└──────────────────────────┬───────────────────────────────┘
│
┌──────────────────────────▼───────────────────────────────┐
│ db-tool-mcp (Perl) │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ MCP Main │──>│ Request │──>│ Database │ │
│ │ Loop │ │ Dispatcher │ │ (DBI -> SQLite) │ │
│ │ │ │ │ │ │ │
│ │ while │ │ • list_tables│ │ + Safe sandbox │ │
│ │ <STDIN> │ │ • inspect │ │ for code param │ │
│ │ │ │ • query +code│ │ │ │
│ │ │ │ • transaction│ │ │ │
│ └──────────┘ └──────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
## Protocol
This server implements the **Model Context Protocol (MCP)** using **JSON-RPC 2.0** over stdin/stdout.
| Method | Description |
|--------|-------------|
| `initialize` | Handshake with protocol version and capabilities |
| `ping` | Health check |
| `tools/list` | Returns the `db_execute` tool definition with full JSON Schema |
| `tools/call` | Executes `db_execute` with provided arguments |
All logging goes to **stderr**, leaving **stdout** clean for JSON-RPC messages.
## Security
- The `code` parameter runs inside Perl's `Safe` compartment, which restricts file operations, system calls, and other dangerous operations
- Only whitelisted Perl modules are allowed (`MIME::Base64`, `Digest::MD5`, `URI::Escape`)
- The code parameter is designed for **AI assistant use only** — the AI generates the Perl code, not the end user
## Contributing
Contributions are welcome! Feel free to open issues or submit pull requests.
## License
MIT © Kirill Scherba
---
*Built with 🐪 — because only Perl has `Safe` in its core.*
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
markitdown
Python tool for converting files and office documents to Markdown.
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
TrendRadar
TrendRadar: Your hotspot assistant for real news in just 30 seconds.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.