Every request passes schema validation, a role policy and a parameterised query builder before it reaches the database, and an unknown entity returns an error listing the real ones — feedback the model can act on. Tenant isolation is the strongest reason to choose this over a plain SQL tool: a row filter attached to the role is appended to every query, so there is no path to another tenant's data even when the model asks for one.
A layer between a model and a SQL database. The model emits a structured intent — an operation, an entity, filters, fields, sorting — which is validated against the schema, checked against your access policies, turned into a parameterised SQLAlchemy query, and returned in a shape a model can read. Any SQLAlchemy backend works: PostgreSQL, MySQL, SQLite, SQL Server, Oracle, BigQuery.
- Tables and columns discovered from the database at connect time, with no registration step, and a describe call that hands the whole schema to a system prompt
- Reads and writes as intents: list, get by primary key, count, aggregate, create, update and delete, plus bulk insert, upsert and set operations
- Filters with operator suffixes for comparisons, LIKE, IN, BETWEEN and null checks, and a nested form for AND, OR and NOT, EXISTS and subqueries
- Joins with dot-notation field references, self-joins by alias, GROUP BY with HAVING, and ROLLUP, CUBE and GROUPING SETS
- Computed fields: CASE expressions, window functions, and scalar functions such as coalesce, cast, concat and extract
- Common table expressions referenced from filters
- A policy engine per role — allowed and denied fields, a row limit, which operations are permitted, and a row filter injected into every query for tenant isolation
- Field masking that returns a masked value rather than rejecting the query, with strategies for emails, trailing characters, hashes and full redaction, or a function of your own
- A read-only mode set globally, independent of the policies
- A dry-run flag on any intent that returns the compiled SQL and its parameters without executing, with schema and policy checks still applied
- Errors that name what went wrong and list the entities that do exist, so a model that hallucinated a table can correct itself
Python with SQLAlchemy and Pydantic, plus whichever database driver you use. A database URL is the only configuration; a bundled command starts it as a server for MCP clients.
One command plus a key — pip install mdbp, then supply credentials
