Install
$ agentstack add mcp-ineersa-mcp-sql-server ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Database MCP Server
A PHP/Symfony Model Context Protocol (MCP) server for executing read-only SQL queries against multiple databases.
Supports: MySQL, MariaDB, PostgreSQL, SQLite, SQL Server
Table of Contents
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Environment Variables](#environment-variables)
- [Database Configuration File](#database-configuration-file)
- [MCP Client Setup](#mcp-client-setup)
- [Available Tools](#available-tools)
- [PII Detection & Redaction](#pii-detection--redaction)
- [Enabling PII Protection](#enabling-pii-protection)
- [Model Setup](#model-setup)
- [Security](#security)
- [Development](#development)
- [License](#license)
Quick Start
Using Docker (Recommended)
The Docker image includes all database drivers. Just 3 steps:
1. Download the example configuration:
curl -L https://raw.githubusercontent.com/ineersa/mcp-sql-server/refs/heads/main/docker-compose.example.yaml -o docker-compose.yaml
2. Create your databases.yaml with your database connections:
doctrine:
dbal:
connections:
mydb:
url: "mysql://user:password@127.0.0.1:3306/mydb"
3. Configure your MCP client (see [MCP Client Setup](#mcp-client-setup))
That's it! Your MCP client will spawn the server automatically.
Without Docker
Requires PHP 8.4+ with database extensions installed:
git clone https://github.com/ineersa/mcp-sql-server.git
cd mcp-sql-server
composer install --no-dev
Configuration
Environment Variables
| Variable | Default | Description | | ---------------------- | ----------------------- | ---------------------------------------------- | | DATABASE_CONFIG_FILE | required | Path to the database configuration YAML file | | APP_ENV | prod | Application environment | | APP_DEBUG | false | Enable debug mode | | LOG_LEVEL | warning | Log level: debug, info, warning, error | | APP_LOG_DIR | /tmp/database-mcp/log | Directory for log files |
Database Configuration File
Database connections are defined in a YAML file (path set via DATABASE_CONFIG_FILE).
Configuration follows Doctrine DBAL standards with DSN and environment variable support.
Example Configuration
doctrine:
dbal:
connections:
# SQLite with explicit path
local:
driver: "pdo_sqlite"
path: "var/test.sqlite"
# MySQL with URL/DSN format and PII redaction enabled
products:
url: "mysql://user:password@127.0.0.1:3306/mydb?serverVersion=8.0&charset=utf8mb4"
# PostgreSQL with environment variable
users:
url: "%env(POSTGRES_DSN)%"
# SQL Server with explicit parameters and driver options
analytics:
driver: "pdo_sqlsrv"
host: "127.0.0.1"
port: 1433
dbname: "analytics"
user: "sa"
password: "MyPassword123"
serverVersion: "2019"
options:
TrustServerCertificate: "yes"
Supported Databases
| Database | Driver | URL Scheme | | ------------- | ------------ | ------------------------- | | MySQL/MariaDB | pdo_mysql | mysql://, mysql2:// | | PostgreSQL | pdo_pgsql | postgres://, pgsql:// | | SQLite | pdo_sqlite | sqlite:// | | SQL Server | pdo_sqlsrv | sqlsrv://, mssql:// |
MCP Client Setup
Add this to your MCP client's configuration (e.g., mcp.json or Claude Desktop settings).
Docker Compose (Recommended)
{
"database": {
"command": "docker",
"args": [
"compose",
"-f",
"/path/to/docker-compose.yaml",
"run",
"--rm",
"database-mcp"
]
}
}
Opencode
{
"mcp": {
"database": {
"type": "local",
"command": [
"docker",
"compose",
"-f",
"/path/to/docker-compose.yaml",
"run",
"--rm",
"database-mcp"
],
"enabled": true
}
}
}
Local Installation
{
"database": {
"command": "/path/to/bin/database-mcp",
"args": [],
"env": {
"DATABASE_CONFIG_FILE": "/path/to/databases.yaml",
"LOG_LEVEL": "info",
"APP_LOG_DIR": "/tmp/database-mcp/log"
}
}
}
Testing Your Setup
Verify your configuration works:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | \
docker compose run --rm database-mcp
You should see a JSON response with server capabilities.
Viewing Logs
# View recent logs
docker compose run --rm logs
# View a specific log entry by line number
docker compose run --rm logs --id=42
# View more entries
docker compose run --rm logs --limit=100
Updating
docker compose pull
Available Tools
Response format (all tools below):
- TOON text payload: Results are returned as TOON-encoded data in
content[].text
query
Executes read-only SQL queries against a specified database connection.
Before querying information_schema/system catalogs for metadata or object definitions, prefer the schema tool with detail: "full" and relevant include flags.
Parameters:
| Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------------------------------------------- | | connection | string | Yes | Name of the database connection to use | | query | string | Yes | SQL query to execute (semicolon-separated for multiple queries) |
Example:
{
"name": "query",
"arguments": {
"connection": "production",
"query": "SELECT id, name, email FROM users LIMIT 10"
}
}
schema
Inspects database schema metadata for a specified connection.
Use detail: "full" + includeRoutines: true + includeViews: true as the default for trigger/function/procedure/view definitions. Prefer this over raw catalog queries.
Parameters:
| Parameter | Type | Required | Description | | ----------------- | ------- | -------- | ------------------------------------------------------------------------------------------------ | | connection | string | Yes | Name of the database connection to inspect | | filter | string | No | Optional object-name filter ("" for all) | | detail | string | No | Detail level: summary (default), columns, or full | | matchMode | string | No | Filter matching mode: contains (default), prefix, exact, or glob | | includeViews | boolean | No | Include views in output | | includeRoutines | boolean | No | Include routines/triggers in output |
matchMode: "exact" matches by logical object name across quote and schema variants. For example, these are treated equivalently for exact matching:
active_users"active_users"public.active_users"public"."active_users"- `
activeusers/[activeusers]`
When detail is full, view/trigger/routine definitions are included in the response.
Object coverage in full detail:
- Tables: columns, indexes, foreign keys, check constraints, triggers (with trigger definitions)
- Views: SQL definition (when
includeViewsistrue) - Routines: function/procedure definitions (when
includeRoutinesistrue)
For columns and full, use a narrow filter whenever possible. Large payloads are rejected with ToolUsageError.
If matchMode is exact, filter is non-empty, and no object matches, the response includes diagnostics with normalized names and near matches:
diagnostics.status(no_exact_match)diagnostics.normalized_filterdiagnostics.normalized_names_trieddiagnostics.top_near_matches
Example:
{
"name": "schema",
"arguments": {
"connection": "production",
"filter": "users",
"detail": "columns",
"matchMode": "contains",
"includeViews": false,
"includeRoutines": false
}
}
PII Detection & Redaction
This server includes built-in PII (Personally Identifiable Information) detection and redaction using GLiNER models in ONNX format via the native gliner-rs-php extension.
1. Download Models
The server supports any GLiNER model in ONNX format. While any compatible model can be used, we recommend and provide a helper for our tested GLiNER PII ONNX model (~1.8GB).
Using Docker (Recommended):
docker compose run --rm download-models
Using PHP:
php bin/console download-models
This downloads model.onnx and tokenizer.json to your local ./models directory.
2. Enable on Specific Connections
PII redaction is configured per-connection in your databases.yaml. When enabled, query results are automatically scanned and sensitive data is replaced with [REDACTED_type] markers (e.g., [REDACTED_email], [REDACTED_ssn]).
doctrine:
dbal:
connections:
production:
url: "mysql://..."
pii_enabled: true # Redact PII in query results
development:
url: "mysql://..."
# pii_enabled defaults to false
3. Optionally Customize PII Settings
You can fine-tune the detection threshold and entity types in your databases.yaml:
pii:
threshold: 0.6 # Confidence threshold (0.0-1.0)
# Note: Default is 0.6. For higher recall (especially on dates), you can lower this to e.g. 0.2.
# Optional: Custom model paths (defaults to models/ in project root)
# tokenizer_path: "models/tokenizer.json"
# model_path: "models/model.onnx"
# Optional: Limit detection to specific entity types for better performance
labels:
- email
- phone_number
- credit_debit_card
- ssn
View all 64 supported PII labels
labels:
# Personal
# - first_name
# - last_name
# - name
# - date_of_birth
# - age
# - gender
# - sexuality
# - race_ethnicity
# - religious_belief
# - political_view
# - occupation
# - employment_status
# - education_level
# Contact
- email
- phone_number
# - street_address
# - city
# - county
# - state
# - country
# - coordinate
# - zip_code
# - po_box
# Financial
- credit_debit_card
# - cvv
# - bank_routing_number
# - account_number
# - iban
# - swift_bic
# - pin
- ssn
# - tax_id
# - ein
# Government
# - passport_number
# - driver_license
# - license_plate
# - national_id
# - voter_id
# Digital/Technical
# - ipv4
# - ipv6
# - mac_address
# - url
# - user_name
# - password
# - device_identifier
# - imei
# - serial_number
# - api_key
# - secret_key
# Healthcare/PHI
# - medical_record_number
# - health_plan_beneficiary_number
# - blood_type
# - biometric_identifier
# - health_condition
# - medication
# - insurance_policy_number
# Temporal
# - date
# - time
# - date_time
# Organization
# - company_name
# - employee_id
# - customer_id
# - certificate_license_number
# - vehicle_identifier
Manual Extension Installation (non-Docker):
Install the gliner-rs-php extension:
curl -fsSL -o gliner.tar.gz \
https://github.com/ineersa/gliner-rs-php/releases/download/0.0.6/gliner-rs-php-0.0.6-linux-x86_64.tar.gz
tar -xzf gliner.tar.gz
cp libgliner_rs_php.so /usr/local/lib/php/extensions/
echo "extension=/usr/local/lib/php/extensions/libgliner_rs_php.so" > /usr/local/etc/php/conf.d/gliner.ini
Security
Read-Only Enforcement
This server enforces read-only mode through multiple layers:
- SQL Keyword Validation — Blocks forbidden keywords (
INSERT,UPDATE,DELETE,DROP,CREATE,ALTER,TRUNCATE, etc.) before execution - Platform SET Commands — Database-level read-only enforcement:
- MySQL/MariaDB:
SET SESSION transaction_read_only = 1 - PostgreSQL:
SET default_transaction_read_only = on - SQLite:
PRAGMA query_only = ON - SQL Server:
ApplicationIntent=ReadOnly
- Sandboxed Execution — All queries run in a transaction that is always rolled back
> Best Practice: Always use a database user with read-only permissions for additional security.
SQL Server Note
ApplicationIntent=ReadOnly only works for Always On Availability Groups and Azure SQL Database. For standalone instances, configure a read-only database user.
Development
Setup
git clone https://github.com/ineersa/mcp-sql-server.git
cd mcp-sql-server
composer install
Testing with MCP Inspector
npx @modelcontextprotocol/inspector ./bin/database-mcp
Code Quality
composer cs-fix # Fix code style
composer phpstan # Static analysis
composer tests # Run tests
Building Docker Image
composer docker-build # Build the image
composer docker-rebuild # Rebuild without cache
Project Structure
src/
├── Command/ # Symfony console commands
├── Enum/ # PII entity types and groups
├── ReadOnly/ # DBAL middleware for read-only enforcement
├── Service/ # Core services (including PIIAnalyzerService)
└── Tools/ # MCP tool implementations
stubs/ # PHP extension stubs for IDE support
tests/ # PHPUnit test suites
config/ # Symfony configuration
License
MIT License — see [LICENSE](LICENSE) for details.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ineersa
- Source: ineersa/mcp-sql-server
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.