Skip to content

ineersa/mcp-sql-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

118 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

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)

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"
  • `active_users` / [active_users]

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 includeViews is true)
  • Routines: function/procedure definitions (when includeRoutines is true)

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_filter
  • diagnostics.normalized_names_tried
  • diagnostics.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:

  1. SQL Keyword Validation — Blocks forbidden keywords (INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, TRUNCATE, etc.) before execution
  2. 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
  3. 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 for details.

About

MySQL MCP server

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors