Skip to main content
Glama
rajarshi-personal

Portable Database MCP

Portable Database MCP

A Python MCP server for SQLite, PostgreSQL, MySQL/MariaDB, Oracle, SQL Server and MongoDB, with 16 tools, a database catalog resource, and an investigation prompt. Run it on a workstation, a VM or your own servers. No cloud account, managed database, or LLM is required.

Python was chosen for SQLAlchemy's database dialects, mature vendor drivers, PyMongo, and the official MCP SDK. Blocking drivers run in a bounded worker pool so they do not block the MCP event loop. Connections are created lazily and pooled. Each SQL write request owns its transaction; no transaction is held open between tool calls.

This implementation deliberately uses the supported MCP Python SDK 1.x FastMCP API, with an explicit <2 dependency boundary. It does not mix the incompatible SDK 2.x API into the application.

Quick start: no external database

Requires Python 3.11 or newer. Run commands from this repository's root.

Windows PowerShell:

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e '.[dev]'
.\.venv\Scripts\python.exe scripts/seed_demo.py
.\.venv\Scripts\python.exe examples/client.py
.\.venv\Scripts\python.exe -m pytest -q

Linux/macOS:

python3 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'
.venv/bin/python scripts/seed_demo.py
.venv/bin/python examples/client.py
.venv/bin/python -m pytest -q

The seed creates customers and orders in demo.db without deleting existing records. The example starts a real MCP subprocess, initializes a session, lists all tools and checks the demo database. The default configuration is read-only. SQLite file paths are relative to the server process working directory; use absolute URLs in desktop client configurations.

Start the server directly:

.\.venv\Scripts\dbmcp.exe --config config.yaml

The default transport is stdio. Waiting silently for a client is normal; do not type ordinary text into its input. Logs go to stderr so stdout remains an MCP protocol stream.

Related MCP server: db-mcp-server

Database configuration

Copy config.example.yaml to config.local.yaml. Delete unused aliases, then provide the environment variables for those retained. Configuration is validated strictly: unknown fields and missing environment variables fail startup. ${VARIABLE} substitution happens after YAML parsing. .env files are not automatically loaded; set environment variables in your shell or process manager.

databases:
  reporting:
    kind: sql
    url: ${REPORTING_DB_URL}
    read_only: true
    pool_size: 5
    connect_args:
      connect_timeout: 10
limits:
  max_rows: 500
  max_response_bytes: 1000000
  max_sql_chars: 50000
  timeout_seconds: 30
  max_concurrency: 8
  max_batch_statements: 20
  max_hybrid_rows: 10000
llm:
  enabled: false
  base_url: http://127.0.0.1:11434/v1
  model: qwen2.5-coder:7b
  api_key: ""
  timeout_seconds: 60

connect_args are vendor-specific SQL driver keyword arguments, not interchangeable across backends. Omit the PostgreSQL connect_timeout example when using a driver that does not accept it. MongoDB uses the configured pool and timeout settings directly. Keep secret configuration files out of version control. All configured aliases are accessible to the connected MCP client; deploy separate processes and database accounts for different trust levels.

Drivers and connection URLs

Install only the drivers you need, or combine extras, for example pip install -e '.[postgres,mongo]'.

Database

Install extra

Example URL

SQLite

Included

sqlite:///demo.db

PostgreSQL

.[postgres]

postgresql+psycopg://reader:password@localhost:5432/app

MySQL/MariaDB

.[mysql]

mysql+pymysql://reader:password@localhost:3306/app?charset=utf8mb4

Oracle

.[oracle]

oracle+oracledb://reader:password@localhost:1521/?service_name=FREEPDB1

SQL Server

.[sqlserver]

mssql+pyodbc://reader:password@localhost:1433/app?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes&TrustServerCertificate=no

MongoDB

.[mongo]

mongodb://reader:password@localhost:27017/?authSource=app

Percent-encode special characters in URL usernames/passwords. The URL is configuration, never a tool argument. Oracle uses python-oracledb's default thin mode; installations requiring Oracle thick mode need an explicit initialization extension and Instant Client. SQL Server requires the native Microsoft ODBC Driver 18 separately from the Python pyodbc package. On Linux this also requires unixODBC and the appropriate vendor packages. TLS certificate trust must match your deployment; do not disable certificate validation for production convenience.

Windows SQLite absolute URL: sqlite:///C:/data/reporting.db. Linux absolute URL: sqlite:////var/lib/dbmcp/reporting.db. Use file-backed SQLite: in-memory SQLite databases are connection/thread-local and unsuitable for this pooled worker model.

Example environment setup:

$env:REPORTING_DB_URL = 'postgresql+psycopg://reader:password@localhost:5432/app'
.\.venv\Scripts\dbmcp.exe --config config.local.yaml

DBMCP_CONFIG can set the default configuration path. --config overrides it. Configuration is loaded at startup; restart the process to change it.

Connect an MCP client

For a client accepting mcpServers JSON, use absolute paths:

{
  "mcpServers": {
    "database": {
      "command": "C:/MyWork/codebase/mcps/DBMcp/.venv/Scripts/python.exe",
      "args": ["-m", "dbmcp.server", "--config", "C:/MyWork/codebase/mcps/DBMcp/config.local.yaml"]
    }
  }
}

Client configuration formats vary. Ensure the launched process inherits the database environment variables; GUI clients do not always inherit variables set in a separate terminal. Use the client's environment configuration or your operating system's credential-aware launcher. On Linux/macOS use the absolute .venv/bin/python path.

For an interactive tool browser, use the MCP Inspector with Node.js installed:

npx -y @modelcontextprotocol/inspector .\.venv\Scripts\python.exe -m dbmcp.server --config config.yaml

Open the Inspector URL it prints, connect, list tools and call query_sql with the examples below.

Local Streamable HTTP

.\.venv\Scripts\dbmcp.exe --config config.yaml --transport streamable-http

Connect a Streamable HTTP client to http://127.0.0.1:8000/mcp. HTTP intentionally binds to loopback and has no application authentication. Use stdio for local hosts. Remote deployment requires a separately configured authenticated TLS gateway and network controls; this repository does not implement OAuth, per-user authorization or a public multi-tenant service. Do not expose the endpoint directly to an untrusted network.

Tool reference

database always means a configured alias, not an arbitrary connection string.

Tool

Purpose / primary arguments

list_databases

Aliases, backend kind and write policy; no secrets

health_check

database; connect and ping

list_schemas

database; SQL schemas

list_tables

database, optional schema; tables and views

describe_table

database, table, optional schema; columns, PK, FK, indexes

query_sql

database, sql, optional params, limit; one SELECT

explain_query

database, sql, optional params; estimated plan

execute_sql

database, sql, optional params; one committed DML operation

execute_transaction

database, statements; atomic DML batch

list_collections

database; MongoDB collections

describe_collection

database, collection; MongoDB indexes

find_documents

database, collection, optional filter, projection, limit

aggregate_documents

database, collection, pipeline; bounded read pipeline

write_document

database, collection, operation, optional document, filter

suggest_sql

database, question, tables, optional schema; reviewable SQL draft

hybrid_query

plan; concurrent SQL/MongoDB reads, server-side joins and grouped aggregates

Read the dbmcp://catalog resource for alias discovery. The investigate_database prompt accepts a question and guides schema inspection and parameterized querying.

SQL query

Tool: query_sql

{
  "database": "demo",
  "sql": "SELECT c.name, o.total FROM customers c JOIN orders o ON o.customer_id=c.id WHERE o.total > :minimum ORDER BY o.id",
  "params": {"minimum": 40},
  "limit": 20
}

Results contain columns, rows, and truncated. Rows are arrays to preserve duplicate column names. Decimal values are strings to preserve precision, dates are ISO strings, bytes are base64 objects, and MongoDB ObjectIds are strings. Input MongoDB filters currently accept JSON values only; automatic Extended JSON/ObjectId conversion is not implemented.

SQL is parsed using the configured backend dialect, but is not translated between databases. Use :name value binds for every SQL driver. Identifiers cannot be bound as values; select them from inspected metadata and use appropriate dialect quoting. Pagination belongs in SQL (ORDER BY plus dialect-appropriate keyset or offset pagination). The tool's limit only bounds returned rows; it does not rewrite or limit server-side execution work.

SQL writes and transactions

Set read_only: false on an explicitly chosen alias and grant that database account only the necessary DML permissions. Client tool approval is recommended: tool annotations describe effects but are not an approval mechanism enforced by this server.

Tool: execute_transaction

{
  "database": "writer",
  "statements": [
    {"sql": "INSERT INTO customers (id, name) VALUES (:id, :name)", "params": {"id": 3, "name": "Lin"}},
    {"sql": "INSERT INTO orders (id, customer_id, total) VALUES (:id, :customer, :total)", "params": {"id": 3, "customer": 3, "total": 25}}
  ]
}

Only INSERT, UPDATE and DELETE are accepted. UPDATE and DELETE require a WHERE clause; that does not prevent broad predicates such as WHERE 1=1. DDL, stored procedure calls, administrative commands and arbitrary scripts are intentionally excluded. A failed SQL batch rolls back, subject to the storage engine's transaction support (use InnoDB for MySQL). Successful responses report committed and driver row counts; some drivers return -1 when counts are unavailable. A lost connection around commit leaves an uncertain outcome: verify database state before retrying. There is no automatic write retry or idempotency key service.

MongoDB

Tool: find_documents

{"database":"mongo","collection":"orders","filter":{"total":{"$gt":40}},"projection":{"_id":0,"total":1},"limit":20}

Tool: aggregate_documents

{"database":"mongo","collection":"orders","pipeline":[{"$group":{"_id":"$customer_id","total":{"$sum":"$total"}}},{"$sort":{"total":-1}}]}

Supported stages: $match, $project, $group, $sort, $limit, $skip, $unwind, $count, $addFields, $set, $unset, $replaceRoot. Maximum 30 stages, no disk spilling, and a final output limit. $lookup, $unionWith, $out, $merge, $where, $function and $accumulator are excluded. There is no arbitrary MongoDB command tool.

write_document supports insert_one, update_one with a $set document, and delete_one. Update/delete require a nonempty filter and affect at most one matching document. These are single-document atomic operations, not a cross-document transaction API.

Hybrid queries: SQL and NoSQL in one tool call

Call hybrid_query with the contents of examples/hybrid-plan.json in Inspector or using session.call_tool("hybrid_query", arguments). The server executes the whole plan and returns calculated results; the client does not need to join data itself. No LLM or additional dependencies are used.

For example, the included plan reads order totals from the SQL alias reporting, reads customer regions from the MongoDB alias mongo, joins by customer_id, and returns sales totals and customer counts by region. Configure those aliases and ensure the named tables/collections exist before running it. Each customer should occur once in the customer collection for that example.

{
  "plan": {
    "sources": [
      {"name":"orders","database":"reporting","operation":"query_sql",
       "sql":"SELECT customer_id, SUM(total) AS total FROM orders GROUP BY customer_id"},
      {"name":"customers","database":"mongo","operation":"find_documents",
       "collection":"customers","projection":{"_id":0,"customer_id":1,"region":1}}
    ],
    "joins":[{"source":"customers","left":"orders.customer_id",
              "right":"customers.customer_id","how":"left"}],
    "group_by":["customers.region"],
    "metrics":[{"name":"sales","operation":"sum","field":"orders.total"},
               {"name":"customer_count","operation":"count"}],
    "limit":100
  }
}

Example 1: try federation locally with SQLite

This example uses two reads of the existing demo alias to demonstrate the same server-side joining machinery without installing MongoDB. It is a federation demonstration, not a mixed-backend test.

Run python scripts/seed_demo.py with the virtual environment's Python, then open Inspector using the command in Connect an MCP client. Select hybrid_query. In its JSON arguments editor, paste the complete object below. If the UI displays a separate plan field, paste only the object inside plan into that field.

{
  "plan": {
    "sources": [
      {
        "name": "customers",
        "database": "demo",
        "operation": "query_sql",
        "sql": "SELECT id, name FROM customers ORDER BY id"
      },
      {
        "name": "orders",
        "database": "demo",
        "operation": "query_sql",
        "sql": "SELECT customer_id, total FROM orders WHERE total >= :minimum ORDER BY id",
        "params": {"minimum": 40}
      }
    ],
    "joins": [
      {"source": "orders", "left": "customers.id", "right": "orders.customer_id", "how": "inner"}
    ],
    "group_by": ["customers.name"],
    "metrics": [
      {"name": "sales", "operation": "sum", "field": "orders.total"},
      {"name": "order_count", "operation": "count"}
    ],
    "limit": 20
  }
}

With the original, unmodified demo data, the structured result is:

{
  "rows": [
    {"customers.name": "Ada", "sales": "42.5", "order_count": 1},
    {"customers.name": "Grace", "sales": "80", "order_count": 1}
  ],
  "truncated": false,
  "result_rows": 2,
  "joined_rows": 2,
  "sources": [
    {"name": "customers", "database": "demo", "operation": "query_sql", "rows": 2},
    {"name": "orders", "database": "demo", "operation": "query_sql", "rows": 2}
  ],
  "consistent_snapshot": false
}

sales is a decimal string; order_count is an integer. The server computes both. The MCP protocol wraps this object in structuredContent and also provides text content for compatible clients.

Example 2: SQL sales joined to MongoDB customer regions

This example uses the existing SQLite orders as its SQL source and a real MongoDB collection. Run commands from the repository root. MongoDB must be available through the included Compose service:

.\.venv\Scripts\python.exe -m pip install -e '.[mongo]'
.\.venv\Scripts\python.exe scripts/seed_demo.py
docker compose up -d --wait mongo

Save this configuration as config.local.yaml (merge these aliases if that file already contains your settings):

databases:
  reporting:
    kind: sql
    url: sqlite:///demo.db
    read_only: true
  mongo:
    kind: mongodb
    url: mongodb://dbmcp:local-dev-only@127.0.0.1:27017/?authSource=admin
    database: dbmcp_hybrid_demo
    read_only: true
limits:
  max_rows: 500
  max_hybrid_rows: 10000
llm:
  enabled: false

Seed the dedicated demo database through the MongoDB shell, outside the read-only MCP server:

docker compose exec mongo mongosh --username dbmcp --password local-dev-only --authenticationDatabase admin dbmcp_hybrid_demo

At the mongosh prompt, paste:

db.customers.updateOne(
  {_id: 1},
  {$set: {customer_id: 1, region: "West"}},
  {upsert: true}
);
db.customers.updateOne(
  {_id: 2},
  {$set: {customer_id: 2, region: "East"}},
  {upsert: true}
);
db.customers.find({}, {_id: 0, customer_id: 1, region: 1});
exit

These commands insert or update two demo documents without deleting the collection. Customer IDs are numeric in both databases. The source data is now:

SQL customer_id

SQL order total

MongoDB region

1

42.50

West

2

80

East

Start Inspector against this configuration:

npx -y @modelcontextprotocol/inspector .\.venv\Scripts\python.exe -m dbmcp.server --config config.local.yaml

Call hybrid_query with examples/hybrid-plan.json, also shown at the start of this section. Expected rows, ignoring order and insignificant trailing decimal zeros:

[
  {"customers.region": "West", "sales": "42.5", "customer_count": 1},
  {"customers.region": "East", "sales": "80", "customer_count": 1}
]

The plan aggregates SQL orders by customer before joining. customer_count therefore counts customers with orders in each region, provided MongoDB contains one matching document per customer. If no MongoDB document matches, a left join places that customer's sales in the null region group. An inner join would exclude them. Additional demo orders or customer documents can change the results.

To use PostgreSQL, Oracle, or SQL Server instead, change only the reporting connection configuration and install its driver extra. Provide an orders table with the same columns. Use SQL column aliases to ensure the returned field names match the plan; for example, Oracle queries may need AS "customer_id" and AS "total" to preserve lowercase names. The SQL must be valid for the selected backend.

Example 3: join a MongoDB aggregation to SQL customer names

Keep Example 2's configuration. In its MongoDB shell, seed three tickets:

db.tickets.updateOne({_id: 101}, {$set: {customer_id: 1, status: "open"}}, {upsert: true});
db.tickets.updateOne({_id: 102}, {$set: {customer_id: 1, status: "open"}}, {upsert: true});
db.tickets.updateOne({_id: 103}, {$set: {customer_id: 2, status: "closed"}}, {upsert: true});

Call hybrid_query with:

{
  "plan": {
    "sources": [
      {
        "name": "customers",
        "database": "reporting",
        "operation": "query_sql",
        "sql": "SELECT id, name FROM customers ORDER BY id"
      },
      {
        "name": "tickets",
        "database": "mongo",
        "operation": "aggregate_documents",
        "collection": "tickets",
        "pipeline": [
          {"$match": {"status": "open"}},
          {"$group": {"_id": "$customer_id", "open_count": {"$sum": 1}}},
          {"$project": {"_id": 0, "customer_id": "$_id", "open_count": 1}}
        ]
      }
    ],
    "joins": [
      {"source": "tickets", "left": "customers.id", "right": "tickets.customer_id", "how": "left"}
    ],
    "limit": 20
  }
}

With only the sample data present, expected rows are:

[
  {"customers": {"id": 1, "name": "Ada"}, "tickets": {"customer_id": 1, "open_count": 2}},
  {"customers": {"id": 2, "name": "Grace"}, "tickets": null}
]

There are no final metrics, so the result contains the joined source objects. tickets: null means there was no open-ticket aggregate for Grace; it is not automatically replaced with a zero-valued object. MongoDB does the ticket grouping, and the MCP server joins that result with SQL.

Call any example from a Python MCP client

Save the complete argument object for your chosen example to a JSON file. Example 2 is already available as examples/hybrid-plan.json. Save the following client as examples/run_hybrid.py:

import argparse
import asyncio
import json
import os
import sys
from pathlib import Path

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


async def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--config", required=True)
    parser.add_argument("--plan", required=True)
    args = parser.parse_args()
    arguments = json.loads(Path(args.plan).read_text(encoding="utf-8"))
    server = StdioServerParameters(
        command=sys.executable,
        args=["-m", "dbmcp.server", "--config", str(Path(args.config).resolve())],
        env=dict(os.environ),
    )
    async with stdio_client(server) as (read, write), ClientSession(read, write) as session:
        await session.initialize()
        result = await session.call_tool("hybrid_query", arguments)
        if result.isError:
            raise RuntimeError(result.content)
        print(json.dumps(result.structuredContent, indent=2))


if __name__ == "__main__":
    asyncio.run(main())

Run Example 2:

.\.venv\Scripts\python.exe examples/run_hybrid.py --config config.local.yaml --plan examples/hybrid-plan.json

For Example 1, save its JSON as examples/local-plan.json and run:

.\.venv\Scripts\python.exe examples/run_hybrid.py --config config.yaml --plan examples/local-plan.json

On Linux/macOS use .venv/bin/python in place of .\.venv\Scripts\python.exe. The client starts and closes its own MCP subprocess; no separately running MCP server or model is required. Docker/MongoDB must remain running for Examples 2 and 3.

Common hybrid errors and corrections

Error or unexpected result

Cause

Correction

Source ... is truncated

A source has more than max_rows results

Filter or aggregate at the source; raise the configured limit only when appropriate. Final output limit does not change source limits.

Hybrid join exceeds max_hybrid_rows

Too many matching combinations

Deduplicate or pre-aggregate by join key; check for many-to-many matches.

Missing field

Field absent, incorrectly cased, or removed by projection

Inspect query output and explicitly project/alias every referenced field.

No matches for apparently equal IDs

For example, numeric 1 versus string "1"

Normalize the source data or query types. The join does not coerce strings to numbers.

Sales unexpectedly multiplied

Multiple customer documents match one sales row

Ensure the right-side key is unique or aggregate to the intended grain first.

Hybrid output limit exceeds max_rows

Plan limit exceeds the configured maximum

Lower the plan's limit. With max_rows below 100, override the default plan limit too.

truncated: true in a successful response

Final joined rows or groups exceed the output limit

Aggregation used all fetched inputs; raise output limit within max_rows to return more groups.

Plan semantics and limits

  • Supply 1–8 named sources. Supported operations are query_sql (sql, optional params), find_documents (collection, optional filter and projection), and aggregate_documents (collection, optional pipeline). Sources may use different aliases or reuse one alias. Existing adapter policies apply; hybrid writes are not supported.

  • Independent reads run concurrently under the server's existing worker limit. Start with the first source; each join introduces one unused source. Every source must be joined. Inner and left equality joins are supported; no Cartesian joins or arbitrary expressions.

  • Field references use source.field, including nested MongoDB paths such as customers.address.region. Give SQL columns unique aliases without dots. Missing fields produce an error rather than silently being treated as zero. Explicit null values are allowed; null keys never join. String "1" does not join numeric 1; normalize types in source queries when needed.

  • Omit metrics and group_by to return joined rows as nested source objects. Otherwise, group_by defines groups and metrics support count, sum, avg, min, max. Count without a field counts rows; count with a field ignores nulls. Numeric metrics ignore nulls and accept numbers or decimal strings; their results are decimal strings. Empty numeric aggregates return null. An empty global count is zero. Decimal arithmetic uses Python's default 28-digit precision, so averages and very large totals can round.

  • Joins preserve duplicate matches. One-to-many joins can repeat amounts and inflate totals; pre-aggregate or deduplicate the sources to the intended business grain before joining.

  • Source results must be complete within max_rows. Any truncated source or failed source fails the entire request. This avoids presenting partial aggregates as complete. Explicit filters/LIMIT clauses in source queries still define the selected dataset; the server cannot infer omitted business data.

  • Configure limits.max_hybrid_rows (default 10,000) to cap total fetched rows and each join's intermediate rows. Join expansion beyond this cap fails. Each source and the final response also respect max_response_bytes; this is not a strict process memory cap.

  • The final limit defaults to 100 and must not exceed max_rows. It is applied after aggregation. result_rows, joined_rows, source row counts and truncated explain the output. There is no final sort option; sort source queries when applicable, or sort the returned aggregates in the client.

  • Reads do not share a distributed snapshot: consistent_snapshot is always false. Data can change between source reads. This is a bounded federation tool, not a distributed transaction engine.

The caller supplies the structured plan, normally after inspecting source schemas. Natural-language plan generation and prose answers are still the MCP host's responsibility; the server performs the actual retrieval, joins and calculations. Default tests exercise real SQLite plus a mocked MongoDB driver, and a real MCP subprocess with two SQL sources. Live mixed-backend execution requires your configured databases.

Optional LLM assistance

The MCP host can use its own model without enabling the server's LLM integration. For server-side SQL suggestions, configure an endpoint implementing the common /v1/chat/completions request/response format. It can be a local model service or a self-hosted or remote compatible provider; no vendor SDK or cloud dependency is required.

llm:
  enabled: true
  base_url: http://127.0.0.1:11434/v1
  model: qwen2.5-coder:7b
  api_key: ""
  timeout_seconds: 60

Run your model service and load that model separately. Use ${LLM_API_KEY} if the endpoint requires credentials. base_url must include the API prefix (typically /v1), not /chat/completions.

{"database":"demo","question":"Which customers have orders above a supplied minimum?","tables":["customers","orders"]}

suggest_sql sends the question and metadata for 1–10 selected tables to that endpoint. It does not fetch or send table rows or database credentials. Metadata can include sensitive names, comments or defaults; enable this only for an approved endpoint. The response is parsed as a SELECT and returned with executed: false and review_required: true. Review semantics and supply bind values yourself. The model is neither a SQL correctness oracle nor an authorization layer. Disabled LLM mode makes no model network requests.

Safety, efficiency and operational limits

  • Read-only is the default. Use real read-only database credentials with table/view grants, restricted routine execution privileges and row-level policies where needed. SQL parsing is a guardrail, not a security sandbox: SELECT can invoke vendor functions with effects. The process exposes every object its database account can access; there is no schema/table allowlist.

  • SQLite uses query_only; PostgreSQL and MySQL/MariaDB use read-only transactions for read-only aliases. Oracle and SQL Server require read-only database grants. Read tools on a write-enabled alias still share that alias's more powerful credentials.

  • PostgreSQL gets a statement timeout; SQLite gets a progress deadline; Oracle gets a driver call timeout; SQL Server gets a driver query timeout; MongoDB gets operation and server-side query limits. MySQL/MariaDB should use driver socket timeouts in connect_args and server resource policies. These mechanisms differ: there is no universal hard end-to-end cancellation guarantee, and connect/pool/metadata time may differ from query execution time.

  • Concurrency is bounded globally and SQL connections are pooled per alias. Worker cancellation does not abandon a running driver thread and release its concurrency slot prematurely. Long-running work can still occupy capacity until the driver/database stops it.

  • At most max_rows + 1 rows are fetched to detect truncation. max_response_bytes rejects oversized serialized responses, but is checked after fetching: it is not a strict peak-memory cap for huge BLOBs/documents. Select needed columns, avoid large binary data, and configure database workload limits. Metadata lists are also subject to the response byte cap.

  • Audit logs contain alias, operation, duration and status. SQL, parameters, results, credentials and raw driver errors are excluded. Client errors are intentionally generic for driver failures. Diagnose details through protected database-side logs. Treat all database contents as untrusted, including instructions embedded in text fields.

  • Explain supports SQLite, PostgreSQL, MySQL/MariaDB and never requests ANALYZE. Oracle and SQL Server explain workflows are intentionally unsupported because they need different session/plan handling.

Tests and real-environment verification

.\.venv\Scripts\python.exe -m pytest -q
.\.venv\Scripts\ruff.exe check .

The default suite uses real SQLite connections and an actual stdio MCP subprocess. It checks initialization, discovery, tool calls, query parameter binding, truncation, transaction rollback, write restrictions, read-only enforcement, parser guards, configuration, response caps and error redaction. External database tests skip unless explicitly configured.

Local PostgreSQL and MongoDB integration

With Docker Compose installed:

docker compose up -d --wait
.\.venv\Scripts\python.exe -m pip install -e '.[dev,postgres,mongo]'
$env:DBMCP_LIVE_CONFIG = 'config.compose.yaml'
.\.venv\Scripts\python.exe -m pytest tests/test_live.py -q
.\.venv\Scripts\python.exe examples/client.py --config config.compose.yaml --database postgres
.\.venv\Scripts\python.exe examples/client.py --config config.compose.yaml --database mongo
docker compose down

The Compose credentials are development-only and privileged. Create restricted users before treating this as a production configuration. The included live checks perform connectivity, metadata discovery and a SQL constant SELECT; they do not insert data or validate every backend capability.

Oracle, SQL Server and other existing databases

  1. Provision a nonproduction schema/database and a least-privilege test account.

  2. Install the corresponding Python extra and any native driver prerequisites.

  3. Create config.local.yaml with the correct URL, database/service name, TLS and connection arguments.

  4. Set DBMCP_LIVE_CONFIG=config.local.yaml and run tests/test_live.py.

  5. Run examples/client.py --config config.local.yaml --database <alias> to verify the actual MCP transport.

  6. Use Inspector to inspect a known table, execute a parameterized SELECT and check a limited result. Test explain only on supported dialects.

  7. For write verification, use a separate write-enabled alias and disposable transactional table. Test a successful two-statement batch and a batch whose second statement violates a constraint, then verify that the first statement rolled back. Do not perform write tests against production records.

On Linux/macOS, set export DBMCP_LIVE_CONFIG=config.local.yaml and use .venv/bin/python. External servers and a model endpoint are not bundled or automatically contacted during default tests. Compatibility for a specific vendor version, auth method and network environment must be verified there; adapter support is not a claim that every vendor was exercised locally.

Project layout and extension

src/dbmcp/config.py   Strict settings, secrets and environment expansion
src/dbmcp/policy.py   SQL AST and MongoDB operation guards
src/dbmcp/sql.py      SQLAlchemy pooling, metadata, queries and transactions
src/dbmcp/mongo.py    PyMongo discovery, read pipelines and single writes
src/dbmcp/hybrid.py   Read-only federation plans, joins and aggregate calculations
src/dbmcp/server.py   MCP tools, resource, prompt, auditing and optional LLM
examples/client.py   Real MCP client example
scripts/seed_demo.py  Repeatable local SQLite demo
tests/               Local, protocol and opt-in live checks

To add a SQLAlchemy-supported backend, install its dialect/driver, add its SQLGlot dialect mapping, implement appropriate timeout/read-only handling, and run live metadata/query/rollback tests. Another NoSQL backend should get an adapter with explicit operations and policy checks, a configuration kind, and corresponding typed MCP tools. Do not map arbitrary client-provided commands directly into a driver.

For deployment, install the package into an isolated environment and launch dbmcp under your process manager with controlled environment variables and database permissions. Resolve and pin dependencies in your deployment pipeline; the project specifies compatibility ranges, not a universal cross-platform lockfile.

Troubleshooting

Symptom

Check

Configuration cannot be loaded

File path, YAML fields, all referenced environment variables

SQLite table missing

Absolute database file path and server working directory

Driver import error

Correct optional extra installed in the server's Python environment

SQL Server cannot open driver

Native ODBC driver installed; exact driver name matches URL

Oracle connection fails

Listener, service name, supported thin authentication and network settings

Database operation failed

DB grants, bind values, SQL dialect, connectivity, protected DB logs

Writes disabled

Correct alias, explicit read_only: false, appropriate database grants

Response exceeds byte limit

Fewer selected columns/rows; exclude large documents/BLOBs

LLM invalid response

Compatible endpoint, available model, SQL-only output without code fences

Server appears idle

stdio server is awaiting an MCP client

License

This project is licensed under the MIT License.

Copyright (c) 2026 Rajarshi Ray rajarshir@gmail.com.

Third-party dependencies, database servers, drivers, and optional models retain their own licenses.

Primary references

Available Tools

16 tools
aggregate_documentsB
Read-only

Run a bounded read aggregation using supported stages; no joins, writes or JS.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes
pipelineYes
collectionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds that the operation is bounded and excludes writes/JS, but never enumerates which pipeline stages are 'supported' — the single most important behavioral fact for an aggregation tool — nor any limits or cost characteristics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the read/bounded framing comes first and each clause adds a distinct constraint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, but for a pipeline-based tool the description omits the supported-stage list and pipeline formatting entirely, leaving the agent unable to construct a valid call without guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across all three parameters, so the description carries the full burden and largely fails it: pipeline stage syntax, the fact that 'supported stages' is a restricted whitelist, and the meaning of database/collection vs. the sibling list_collections tools are all left unstated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource ('Run a bounded read aggregation') and scopes it with exclusions (no joins, writes or JS), which separates it from mutation and SQL siblings. It stops short of naming an alternative tool explicitly, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states negative constraints ('no joins, writes or JS') that implicitly tell when not to use it, but never says when this tool is preferred over find_documents or query_sql, nor what 'bounded' means in practice. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

describe_collectionC
Read-only

Inspect MongoDB indexes; MongoDB documents need not share a schema.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes
collectionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The note that MongoDB documents need not share a schema is genuinely useful context for interpreting results, but it is the only behavioral detail offered and says nothing about scope, cost, or sampling behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two brief clauses with no waste, but the semicolon-joined second clause about schemas is not clearly tied to the first and reads as filler rather than front-loaded purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, but a describe tool with two undocumented required params and no statement of what is described (structure? indexes? samples?) leaves the agent guessing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Both required parameters (database, collection) have 0% schema description coverage, and the description adds no meaning to either – no format, no examples, no required-scoping explanation. With two undocumented params, the description fails to compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The name says describe_collection, but the description claims the tool 'Inspects MongoDB indexes' – a narrower and potentially different purpose. An agent comparing this against describe_table, list_collections, or list_schemas gets a conflicting signal about what is actually returned.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus the many siblings (describe_table, list_collections, list_schemas, find_documents). The schema-flexibility remark is background trivia, not a usage condition or exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

describe_tableC
Read-only

Inspect columns, primary/foreign keys and indexes.

ParametersJSON Schema
NameRequiredDescriptionDefault
tableYes
schemaNo
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description usefully specifies what is returned (columns, keys, indexes), but says nothing about the database/schema resolution behavior or engine-specific caveats. With annotations carrying the safety burden, this is adequate but thin.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short, front-loaded sentence with no filler. It is efficient, though borderline under-specified rather than over-long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values needn't be explained, but for a three-parameter tool with 0% schema coverage the description gives no help on parameter roles, on supported databases, or on when to prefer this over list_tables/describe_collection. Substantial gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description never mentions the database, table, or optional schema parameters. It does not explain the database-vs-schema distinction or why the optional schema argument exists (disambiguation), leaving all three parameters undocumented in prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (inspect) and enumerates the resources inspected (columns, primary/foreign keys, indexes), which clearly distinguishes it from list_tables and describe_collection. It does not explicitly reference any sibling, but the object of inspection makes the scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no mention of alternatives such as list_tables or describe_collection. The agent must infer that this is the tool to call to learn a table's structure before writing SQL.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

execute_sqlA
Destructive

Commit one DML statement on a write-enabled alias. UPDATE/DELETE require WHERE.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so safety is covered structurally. The description adds genuinely new context: only ONE statement is allowed and the statement is committed (no rollback), plus the mandatory WHERE guard on UPDATE/DELETE, which tells the agent about irreversibility and bulk-write protection.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the core scope constraint ('one DML statement') front-loaded before the safety precondition. Nothing repeats the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, and annotations cover the destructiveness profile. What remains thin is parameter-level detail: with 0% schema coverage, the agent gets no guidance on parameter binding, statement dialect, or error/transaction handling beyond the commit semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for all three parameters, so the description must carry the load. It constrains what goes in `sql` (a single DML statement) and hints at `database` (must be a write-enabled alias), but the `params` binding parameter is never mentioned and no format/syntax or placeholder convention is given for the SQL string.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (commit/execute), resource (one DML statement), and scope constraint (single statement, write-enabled alias). It implicitly separates itself from read-only query_sql and from multi-statement execute_transaction, but never names a sibling explicitly, so the routing signal is inferred rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'one DML statement' plus 'write-enabled alias' implies when this tool is appropriate (single write against a writable database) and 'UPDATE/DELETE require WHERE' gives a hard precondition. However, no alternative tool is named and no when-not condition is spelled out, so usage is implied rather than directed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

execute_transactionA
Destructive

Commit a bounded list of {sql, params} DML statements atomically; rollback on failure.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes
statementsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false and destructiveHint=true, so the safety profile is covered. The description adds genuinely new behavior: it commits atomically and rolls back on failure, which tells the agent about failure semantics not present in the annotations. Remaining gaps (what "bounded" means, size cap, partial-failure details) are minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single compact sentence with the core action (atomic commit) front-loaded and the failure behavior appended. Every clause carries information; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described, and annotations carry the destructive/non-idempotent profile. The description supplies the essential atomic-commit/rollback contract for a mutation tool. It falls just short by not clarifying the database parameter or what bounds the statement list.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It adds real meaning by defining the item shape as {sql, params}, which the opaque schema (additionalProperties: true) does not convey. However, it never explains the required "database" parameter or the semantics/limits of the statements array, leaving the compensation partial.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (commit) and resource (a list of {sql, params} DML statements) with the atomicity qualifier, so the agent understands this is multi-statement transactional execution. It does not explicitly name or contrast with the sibling execute_sql, which likely handles single statements, so sibling differentiation is only implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Atomically" and "bounded list" imply the use case (multiple DML statements that must succeed or fail together), but there is no explicit when-to-use guidance, no contrast with execute_sql/query_sql, and no stated prerequisites or limits. Usage must be inferred from the atomicity wording.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

explain_queryB
Read-only

Get an estimated query plan on SQLite/PostgreSQL/MySQL/MariaDB; never ANALYZE.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
paramsNo
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds a meaningful behavioral constraint by stating 'never ANALYZE,' which rules out statistics updates, but it does not disclose return format, pagination, or other operational details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence that states the action and the key constraint. It is appropriately terse for a short tool definition, though its brevity leaves important gaps elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists and annotations cover safety, so return values need not be explained. However, with 0% parameter description coverage and no alternative routing, the definition is only minimally complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description does not explain the `sql`, `params`, or `database` parameters. Mentioning SQL dialect support does not clarify how any parameter should be supplied.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get an estimated query plan') and lists supported database engines. It does not explicitly differentiate from sibling tools such as query_sql or execute_sql, so it remains clear but not fully routing-aware.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies the use case (obtain a query plan) and includes a negative constraint ('never ANALYZE'), but it gives no explicit guidance on when to choose this over query_sql, execute_sql, or suggest_sql. Usage is therefore only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_documentsC
Read-only

Find bounded MongoDB documents using a filter and optional projection.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
filterNo
databaseYes
collectionYes
projectionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds that results are "bounded," hinting at a capped result set, but does not say how bounding works (default limit, pagination, max size), leaving the one genuinely useful trait underspecified.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with no wasted words and the core action front-loaded. It is arguably too terse for a 5-parameter tool, but structurally it is clean.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Reply format need not be explained since an output schema exists, and annotations cover safety, but with 0% parameter documentation, no usage guidance versus the 15 siblings, and an unexplained "bounded" claim, the definition is under-specified for a 5-param query tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the burden. It mentions only filter and projection and says nothing about the two required parameters (database, collection) or the limit parameter, leaving half the parameters undocumented anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource ("Find ... MongoDB documents") and names the mechanisms (filter, projection). However it gives no differentiation from the sibling aggregate_documents, which is the main competing read path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance at all: no mention of when to prefer this over aggregate_documents, hybrid_query, or query_sql, and no prerequisites. The reader must infer usage purely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

health_checkC
Read-only

Check one database connection; connects lazily.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds a useful behavioral detail ('connects lazily'), but does not describe other traits like authentication requirements, timeout behavior, or what a failed check returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with the key verb first and no filler. Both clauses ('Check one database connection', 'connects lazily') are relevant, though the extreme brevity leaves important details unstated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple health-check tool with an output schema present (so return values need not be explained), the description still omits critical parameter format details and any usage context. The 0% schema coverage for the only parameter is a notable gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0% for the single required 'database' parameter, the description must compensate but does not explain the expected format (e.g., name, connection string, alias). It only implies the parameter selects one database, adding minimal meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Check') and resource ('one database connection'), making the core purpose clear. It does not explicitly differentiate from sibling tools like list_databases or query_sql, but the health-check intent is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus alternatives such as query_sql or list_databases. The description does not state prerequisites, timing, or exclusions, leaving the agent to infer context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

hybrid_queryA
Read-only

Run SQL/MongoDB reads concurrently, join and aggregate on the server.

Supply named sources and inner/left equijoins using source.field keys. Optional group_by and count/sum/avg/min/max metrics operate on the full join. Truncated inputs fail rather than producing misleading totals. No writes, natural-language planning, or cross-database snapshot guarantee.

ParametersJSON Schema
NameRequiredDescriptionDefault
planYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description goes further by disclosing concurrency behavior, server-side join/aggregation, truncation-safe failure (fails rather than reporting misleading totals), and the absence of a cross-database snapshot guarantee. These are meaningful traits not derivable from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, purpose front-loaded, no filler. The dense trailing exclusion sentence packs three distinct caveats, which is efficient though slightly compressed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. For a complex nested plan, the description covers the plan's shape and key caveats adequately, with the remaining gap being per-source field semantics that the description only gestures at.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden and largely does: it explains that the single plan param holds named sources, equijoin specs keyed by source.field, and optional group_by/metrics. It omits how per-source fields (database, operation, filter/params/pipeline) shape a source, so compensation is good but not complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: run concurrent SQL/MongoDB reads, then join and aggregate server-side. This is a distinctive hybrid capability that reads clearly as its own thing. It does not name the sibling tools it overlaps with (query_sql, aggregate_documents, find_documents), so an agent must infer the boundary itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives construction guidance (named sources, inner/left equijoins on source.field keys) and a negative clause (no writes, no NL planning, no cross-database snapshot guarantee). However it never says when to prefer this over the single-source siblings like query_sql or aggregate_documents, leaving the routing decision to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_collectionsC
Read-only

List MongoDB collections.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds nothing beyond that—no note on return ordering, count behavior, or what happens for an empty/nonexistent database—so it contributes no behavioral value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with no filler and the operation front-loaded. It is efficient, though it errs toward under-specification rather than redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, but for a tool with a required, zero-coverage parameter the definition remains thin: no database semantics and no usage context. It is only marginally adequate given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the one required parameter (database) is undocumented in both schema and description. The description never explains what 'database' should contain or whether it accepts names versus connection strings, so it fails to compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (MongoDB collections), so an agent immediately knows the operation. It does not, however, distinguish itself from siblings like list_databases, list_tables, list_schemas, or describe_collection, leaving the agent to infer which listing scope applies.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus list_databases, list_schemas, or describe_collection, and no mention of any prerequisite such as needing a valid database name. The single sentence offers no context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_databasesA
Read-only

List configured aliases and capabilities without disclosing credentials.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds valuable behavioral context by stating it operates 'without disclosing credentials,' which is a security-relevant constraint not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no wasted words. It conveys the core action and the credential-safety constraint efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only listing tool with an output schema and thorough annotations, the description is complete enough. It explains what is listed and adds a security constraint; return details are covered by the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the baseline is 4. The description correctly does not discuss parameters, and the schema is empty.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List') and resources ('configured aliases and capabilities'), making the tool's function clear. It does not explicitly distinguish itself from sibling listing tools like list_schemas or list_tables, but the noun 'aliases' is reasonably specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives such as list_schemas, list_tables, or health_check. The context implies a discovery role, but no conditions, exclusions, or alternatives are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_schemasB
Read-only

List SQL schemas visible to the configured database principal.

ParametersJSON Schema
NameRequiredDescriptionDefault
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds the meaningful scoping fact that results are limited to what the configured database principal can see, which is a genuine behavioral trait beyond the annotations, though it says nothing about ordering or volume.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler. Every word (list, SQL schemas, visible to the configured principal) earns its place and nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and annotations cover the safety profile. However, the lone parameter is undocumented and there is no routing to alternative listing tools, so the definition is adequate but not fully complete for a multi-sibling catalog.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single required parameter 'database' has 0% schema description coverage, so the description must compensate and it does not. It never clarifies whether 'database' is a name, fully qualified identifier, or connection target, leaving the lone parameter undocumented across both structured and prose fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (list SQL schemas) with a scope qualifier (visible to the configured database principal). It is clear on its own, but it does not differentiate itself from related siblings like list_databases or list_tables, which an agent might reach for instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no when-to-use context, no prerequisites, and no mention of the sibling enumeration tools (list_databases, list_tables, describe_table). The agent gets no routing guidance to distinguish this from adjacent listing tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tablesC
Read-only

List SQL tables and views in a schema.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaNo
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. Beyond that the description adds almost nothing: it does not say whether the result includes system tables, how it behaves when schema is null, or whether listing is scoped to the connected database.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single efficient sentence with no filler, front-loading the verb and resource. It is appropriately short, though its brevity contributes to the parameter ambiguity noted elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described. But for a two-parameter tool with 0% schema coverage, the description omits the required database argument and the semantics of the optional schema argument, leaving the agent with real ambiguity about how to scope the call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only loosely references 'schema' without explaining that it is optional/defaults to null or what a null value means (e.g., all schemas). It also never mentions the required 'database' parameter. With two undocumented params, the description fails to compensate for the coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb+resource ('List SQL tables and views'), and it distinguishes itself from siblings like list_databases and list_schemas by naming tables and views. However, it does not explicitly differentiate from describe_table or explain how it relates to list_schemas, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no alternatives named, and no mention of prerequisites such as whether a connection or database must exist first. The agent must infer usage entirely from the name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_sqlA
Read-only

Execute one SELECT using :name bind parameters. Limit caps returned rows, not DB work.

ParametersJSON Schema
NameRequiredDescriptionDefault
sqlYes
limitNo
paramsNo
databaseYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safe read-only profile is covered. The description adds useful behavioral context beyond the annotations: bind parameters use :name syntax, and the limit parameter caps returned rows rather than reducing database work. It does not describe pagination or result delivery semantics, but those are partly covered by the output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, tightly front-loaded with the core action and then the important limit caveat. Every sentence adds value, and there is no redundant or filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the core execution constraint and the non-obvious limit behavior, and annotations plus the output schema cover safety and return formatting. However, it omits guidance on the required database parameter and does not differentiate this tool from related siblings like execute_sql or explain_query, leaving routing gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains the params object via ':name bind parameters' and clarifies the limit parameter ('Limit caps returned rows, not DB work'). It does not explain the database parameter or add detail about the sql parameter beyond 'one SELECT', leaving gaps for a 4-parameter tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Execute one SELECT'. It also constrains the SQL to a single SELECT statement. However, it does not distinguish this tool from siblings such as execute_sql or suggest_sql, so sibling differentiation is missing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: use this tool to run a single SELECT with bind parameters. There is no explicit when-to-use or when-not-to-use guidance, and no alternative sibling tools are mentioned. An agent can infer the intended read-query use case, but routing decisions are left to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

suggest_sqlA
Read-only

Send selected schema metadata and question to configured LLM; never execute its SQL.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaNo
tablesYes
databaseYes
questionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint=true annotation is consistent with 'never execute its SQL,' and the description reinforces it. It also adds genuinely useful context beyond annotations: the operation depends on a configured LLM and ships selected schema metadata off-box, which matches openWorldHint=true and matters for data-egress decisions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence, front-loading the core behavior and ending on the key safety boundary. No filler; every clause carries weight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because an output schema exists, return values need not be described, and annotations already cover safety. However, with 4 parameters at 0% schema coverage and no explicit when-to-use guidance, the definition leaves real gaps for an agent deciding how to populate tables/database/schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 4 parameters, so the description is the only place parameter meaning could be added. It loosely gestures at 'schema metadata' and 'question' but says nothing about the database, tables, or optional schema parameters, leaving the required inputs under-explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action (send schema metadata + question to a configured LLM) and draws a hard boundary against execution ('never execute its SQL'), which separates it from execute_sql and query_sql. It is clear what the tool produces, though it never explicitly names the output as SQL suggestions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the 'never execute' clause hints you would use this when you want SQL generated rather than run, but it never states when to prefer suggest_sql over explain_query or the execute_* siblings, nor what prerequisites (configured LLM) exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_documentB
Destructive

Write one MongoDB document. Updates support $set; update/delete require a filter.

ParametersJSON Schema
NameRequiredDescriptionDefault
filterNo
databaseYes
documentNo
operationYes
collectionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=false, so the risk profile is covered structurally. The description adds genuinely useful behavior context — that updates use $set and that update/delete need a filter — but says nothing about irreversibility of delete_one or what happens to unmatched filters, so it only partially exceeds the annotation baseline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the core action, and each sentence adds a distinct constraint. Nothing is wasted or repeated from the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be described, and annotations cover the safety profile. However, for a destructive multi-operation tool with zero schema description coverage, the omission of per-operation parameter requirements (document for insert, filter for update/delete beyond a passing mention) leaves meaningful gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden, yet it only touches two of five parameters: the filter requirement for update/delete and $set syntax for updates. database, collection, and document semantics (e.g., that document is required for insert and ignored for delete) are left entirely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Write one MongoDB document") that clearly separates it from the read-only sibling find_documents. It does not explicitly name sibling alternatives, but the write/read distinction is unambiguous from the verb.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives operational prerequisites ("update/delete require a filter") which tell the agent how to call the tool, but never states when to prefer it over siblings like execute_sql or execute_transaction. Usage is implied by the operation enum rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 16 tool updatesv0.1.0
    • First observedaggregate_documents
    • First observeddescribe_collection
    • First observeddescribe_table
    • First observedexecute_sql
    • First observedexecute_transaction
    • First observedexplain_query
    • First observedfind_documents
    • First observedhealth_check
    • First observedhybrid_query
    • First observedlist_collections
    • First observedlist_databases
    • First observedlist_schemas
    • First observedlist_tables
    • First observedquery_sql
    • First observedsuggest_sql
    • First observedwrite_document

TDQS

B3.2/5.0

Scored across 16 tools

Disambiguation5/5

Each tool targets a distinct resource and action across SQL and MongoDB: find vs aggregate vs write for Mongo, query vs execute vs explain for SQL, and separate list/describe tools for schemas, tables, collections, and databases. Hybrid_query and suggest_sql are unique in purpose. No two tools overlap in a way that would cause misselection.

Naming Consistency4/5

Most tool names follow a consistent verb_noun snake_case pattern (find_documents, aggregate_documents, write_document, list_schemas, describe_table, query_sql, execute_sql, etc.). Minor deviations are health_check (noun_noun) and hybrid_query (adjective_noun), but overall the convention is clear and predictable.

Tool Count4/5

16 tools is slightly above the typical 3-15 sweet spot, but the dual SQL/MongoDB scope justifies separate read, write, schema, transaction, and hybrid operations. Each tool earns its place with no obvious redundancy, though a few could theoretically be merged (e.g., schema listing tools).

Completeness4/5

The surface covers core CRUD and lifecycle operations for both SQL and MongoDB: connect, inspect schemas/tables/collections, query, write, transact, explain, and hybrid join. Minor gaps include no DDL (create/alter/drop), no index management, and no bulk MongoDB writes, but common agent workflows are well supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A versatile MCP server that connects to multiple relational databases (MySQL, PostgreSQL, Oracle, SQL Server, SQLite) and enables secure read-only SQL query execution and metadata access.
    4
    -
  • A
    license
    A
    quality
    D
    maintenance
    A multi-database MCP server supporting MySQL, PostgreSQL, MongoDB, and SQLite with read-only and read-write query capabilities, schema inspection, and SSH tunneling, all without Docker.
    5
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that connects to SQL databases (SQLite, PostgreSQL, MSSQL, MySQL) and provides tools to run read-only queries, list schemas/tables, and manage connections via stdio transport.
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Universal MCP server for readonly-first access to Oracle, SQL Server, PostgreSQL, MySQL/MariaDB, SQLite, MongoDB, and Qdrant vector search.
    116 npm
    1
    MIT