Upload README.md with huggingface_hub
Browse files
README.md
CHANGED
|
@@ -1,176 +1,81 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
-
|
| 10 |
-
-
|
| 11 |
-
-
|
| 12 |
-
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
```bash
|
| 29 |
pip install mcp-database-universal
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
pip install "mcp-database-universal[
|
| 33 |
-
pip install "mcp-database-universal[mysql]"
|
| 34 |
-
pip install "mcp-database-universal[mssql]"
|
| 35 |
-
# or everything:
|
| 36 |
-
pip install "mcp-database-universal[all]"
|
| 37 |
```
|
| 38 |
|
| 39 |
-
## Quick
|
| 40 |
|
| 41 |
-
Run
|
| 42 |
|
| 43 |
```bash
|
| 44 |
DATABASE_URL=sqlite:///app.db python -m mcp_database_universal
|
| 45 |
```
|
| 46 |
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
```
|
| 50 |
-
sqlite:///path/to/db.db SQLite (file)
|
| 51 |
-
sqlite:///:memory: SQLite (in-memory)
|
| 52 |
-
postgresql://user:pass@host:5432/db PostgreSQL
|
| 53 |
-
mysql://user:pass@host:3306/db MySQL
|
| 54 |
-
mssql://user:pass@host:1433/db MSSQL (uses ODBC Driver 18)
|
| 55 |
-
```
|
| 56 |
-
|
| 57 |
-
## Docker
|
| 58 |
|
| 59 |
```bash
|
| 60 |
-
docker
|
| 61 |
-
|
| 62 |
-
# Mount a SQLite database read-only:
|
| 63 |
-
docker run --rm -i \
|
| 64 |
-
-v /host/path/app.db:/data/app.db:ro \
|
| 65 |
-
-e DATABASE_URL=sqlite:////data/app.db \
|
| 66 |
-
mcp-db
|
| 67 |
-
|
| 68 |
-
# Or in-memory:
|
| 69 |
-
docker run --rm -i -e DATABASE_URL=sqlite:///:memory: mcp-db
|
| 70 |
```
|
| 71 |
|
| 72 |
-
## Configuration
|
| 73 |
-
|
| 74 |
-
All configuration is done through environment variables.
|
| 75 |
|
| 76 |
-
| Variable
|
| 77 |
-
|-----------------------------
|
| 78 |
-
| `DATABASE_URL`
|
| 79 |
-
| `DATABASE_READ_ONLY`
|
| 80 |
-
| `DATABASE_WRITE_ENABLED`
|
| 81 |
-
| `DATABASE_MAX_ROWS`
|
| 82 |
-
| `DATABASE_MAX_QUERY_TIME`
|
| 83 |
-
| `DATABASE_MAX_OUTPUT_BYTES` |
|
| 84 |
-
| `
|
| 85 |
-
| `
|
| 86 |
-
| `OPENAI_API_KEY` | β | API key for the LLM-backed `natural_query` mode. |
|
| 87 |
-
| `ANTHROPIC_API_KEY` | β | API key for the LLM-backed `natural_query` mode. |
|
| 88 |
|
| 89 |
## Tools
|
| 90 |
|
| 91 |
-
| Tool | Description
|
| 92 |
-
|--------------------|----------------------------------------------------------
|
| 93 |
-
| `test_connection` |
|
| 94 |
-
| `list_tables` | Overview of
|
| 95 |
-
| `inspect_table` | Full
|
| 96 |
-
| `query` |
|
| 97 |
-
| `natural_query` | Ask
|
| 98 |
-
| `profile_database` |
|
| 99 |
-
| `schema_graph` | Mermaid ER diagram of
|
| 100 |
-
|
| 101 |
-
### Example: `query` with parameters
|
| 102 |
-
|
| 103 |
-
```json
|
| 104 |
-
{
|
| 105 |
-
"sql": "SELECT * FROM users WHERE id = :id AND active = :active",
|
| 106 |
-
"params": "{\"id\": 42, \"active\": true}"
|
| 107 |
-
}
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
Parameters use `:name` placeholders; pass the values as a JSON string in `params`.
|
| 111 |
-
|
| 112 |
-
### Example: `natural_query`
|
| 113 |
-
|
| 114 |
-
```text
|
| 115 |
-
question: "How many users are there?"
|
| 116 |
-
-> SELECT COUNT(*) FROM users
|
| 117 |
-
question: "Show me all orders"
|
| 118 |
-
-> SELECT * FROM orders LIMIT 100
|
| 119 |
-
```
|
| 120 |
-
|
| 121 |
-
A working example against a small sample database is in [`examples/`](examples/) together with ready-to-use configuration snippets for common MCP clients.
|
| 122 |
-
|
| 123 |
-
## MCP client configuration
|
| 124 |
-
|
| 125 |
-
### Claude Desktop (`claude_desktop_config.json`)
|
| 126 |
-
|
| 127 |
-
```json
|
| 128 |
-
{
|
| 129 |
-
"mcpServers": {
|
| 130 |
-
"database": {
|
| 131 |
-
"command": "python",
|
| 132 |
-
"args": ["-m", "mcp_database_universal"],
|
| 133 |
-
"env": {"DATABASE_URL": "sqlite:///C:/data/app.db"}
|
| 134 |
-
}
|
| 135 |
-
}
|
| 136 |
-
}
|
| 137 |
-
```
|
| 138 |
-
|
| 139 |
-
### Cursor / other CLI-based clients
|
| 140 |
-
|
| 141 |
-
```json
|
| 142 |
-
{
|
| 143 |
-
"mcpServers": {
|
| 144 |
-
"database": {
|
| 145 |
-
"command": "uvx",
|
| 146 |
-
"args": ["mcp-database-universal"],
|
| 147 |
-
"env": {"DATABASE_URL": "sqlite:///C:/data/app.db"}
|
| 148 |
-
}
|
| 149 |
-
}
|
| 150 |
-
}
|
| 151 |
-
```
|
| 152 |
-
|
| 153 |
-
> **Windows note**: the async Postgres driver requires the Windows selector event loop. The package sets this policy automatically on `win32`, so no extra configuration is needed.
|
| 154 |
-
|
| 155 |
-
## Development
|
| 156 |
-
|
| 157 |
-
```bash
|
| 158 |
-
pip install -e ".[dev]"
|
| 159 |
-
pytest
|
| 160 |
-
```
|
| 161 |
-
|
| 162 |
-
Integration tests for PostgreSQL/MySQL use Docker Compose and are skipped automatically if the servers are unreachable:
|
| 163 |
-
|
| 164 |
-
```bash
|
| 165 |
-
docker compose -f tests/integration/docker-compose.yml up -d
|
| 166 |
-
pytest
|
| 167 |
-
```
|
| 168 |
-
|
| 169 |
-
## Safety model
|
| 170 |
-
|
| 171 |
-
- The server is **read-only by default**; `INSERT`/`UPDATE`/`DELETE`/`DROP`/`ALTER` and other write statements are blocked.
|
| 172 |
-
- Writes are only possible when the operator explicitly sets `DATABASE_READ_ONLY=false` **and** `DATABASE_WRITE_ENABLED=true`.
|
| 173 |
-
- Query results are capped by row count, timeout, and output size β runaway queries are prevented.
|
| 174 |
|
| 175 |
## License
|
| 176 |
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
+
tags:
|
| 5 |
+
- mcp
|
| 6 |
+
- model-context-protocol
|
| 7 |
+
- ai-tools
|
| 8 |
+
- database
|
| 9 |
+
- sqlite
|
| 10 |
+
- postgresql
|
| 11 |
+
- mysql
|
| 12 |
+
- mssql
|
| 13 |
+
library_name: mcp-database-universal
|
| 14 |
+
license: mit
|
| 15 |
+
---
|
| 16 |
+
|
| 17 |
+
# MCP Database Universal
|
| 18 |
+
|
| 19 |
+
A reasoning interface for databases β not a thin execution wrapper. Designed so LLM agents understand *what* the data means, not just how to fetch it.
|
| 20 |
+
|
| 21 |
+
## What it does
|
| 22 |
+
|
| 23 |
+
- **7 tools** designed for agent thinking: `test_connection`, `list_tables`, `inspect_table`, `query`, `natural_query`, `profile_database`, `schema_graph`
|
| 24 |
+
- **4 database engines**: SQLite (built-in), PostgreSQL, MySQL, MSSQL (optional extras)
|
| 25 |
+
- **Read-only by default** β write operations only with `DATABASE_WRITE_ENABLED=true`
|
| 26 |
+
- **Safety layer** β SQL injection detection, read-only classification, LIMIT enforcement, query timeout, row limits
|
| 27 |
+
- **LLM formatter** β type translation (e.g. `VARCHAR(255)` β "text, max 255 chars"), NULL β `(empty)`, output size cap
|
| 28 |
+
- **Schema inspector** β relationship discovery + Mermaid ER diagram generation
|
| 29 |
+
- **Zero-config SQLite** via `DATABASE_URL=sqlite:///path/to.db`
|
| 30 |
+
|
| 31 |
+
## Installation
|
| 32 |
|
| 33 |
```bash
|
| 34 |
pip install mcp-database-universal
|
| 35 |
+
pip install "mcp-database-universal[postgres]" # PostgreSQL support
|
| 36 |
+
pip install "mcp-database-universal[mysql]" # MySQL support
|
| 37 |
+
pip install "mcp-database-universal[mssql]" # MSSQL support
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
```
|
| 39 |
|
| 40 |
+
## Quick Start
|
| 41 |
|
| 42 |
+
### Run locally
|
| 43 |
|
| 44 |
```bash
|
| 45 |
DATABASE_URL=sqlite:///app.db python -m mcp_database_universal
|
| 46 |
```
|
| 47 |
|
| 48 |
+
### Run with Docker
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
```bash
|
| 51 |
+
docker run -i -e DATABASE_URL=sqlite:////data/app.db \
|
| 52 |
+
-v ./data:/data mcp-database-universal:latest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
```
|
| 54 |
|
| 55 |
+
## Configuration (env vars)
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
| Variable | Description | Default |
|
| 58 |
+
|---------------------------|---------------------------------------------------------|------------|
|
| 59 |
+
| `DATABASE_URL` | `sqlite:///path.db`, `postgresql://...`, `mysql://...`, `mssql://...` | required |
|
| 60 |
+
| `DATABASE_READ_ONLY` | Enforce read-only mode | `true` |
|
| 61 |
+
| `DATABASE_WRITE_ENABLED` | Allow write operations (INSERT/UPDATE/DELETE) | `false` |
|
| 62 |
+
| `DATABASE_MAX_ROWS` | Max rows returned per query | `1000` |
|
| 63 |
+
| `DATABASE_MAX_QUERY_TIME` | Query timeout in seconds | `30` |
|
| 64 |
+
| `DATABASE_MAX_OUTPUT_BYTES` | Cap on result payload size | `50000` |
|
| 65 |
+
| `OPENAI_API_KEY` | API key for the LLM-backed `natural_query` mode | β |
|
| 66 |
+
| `ANTHROPIC_API_KEY` | API key for the LLM-backed `natural_query` mode | β |
|
|
|
|
|
|
|
| 67 |
|
| 68 |
## Tools
|
| 69 |
|
| 70 |
+
| Tool | Description |
|
| 71 |
+
|--------------------|----------------------------------------------------------|
|
| 72 |
+
| `test_connection` | Verify connection, get engine type, version, size |
|
| 73 |
+
| `list_tables` | Overview of tables with row counts and relationships |
|
| 74 |
+
| `inspect_table` | Full table structure: columns, types, keys, sample data |
|
| 75 |
+
| `query` | Execute parametrized, safety-checked SQL |
|
| 76 |
+
| `natural_query` | Ask in plain language, get SQL + results + explanation |
|
| 77 |
+
| `profile_database` | Value distributions, NULL rates, relationships, sizes |
|
| 78 |
+
| `schema_graph` | Mermaid ER diagram of relationships |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
## License
|
| 81 |
|