safedb-mcp
Enables secure, read-only querying and inspection of MariaDB databases with configurable table allowlists, denylists, row limits, and PII masking.
Enables secure, read-only querying and inspection of MySQL databases with configurable table allowlists, denylists, row limits, and PII masking.
Enables secure, read-only querying and inspection of SQLite database files with configurable table allowlists, denylists, row limits, and PII masking.
SafeDB MCP
SafeDB MCP is a secure Model Context Protocol server that lets AI agents inspect and query Postgres, MySQL, MariaDB, and SQLite with strict read-only guardrails. It is designed for teams that want useful database access without handing an agent unrestricted production credentials.
Direct database credentials are dangerous for agents because a single bad prompt, tool call, or generated SQL statement can mutate data, exfiltrate sensitive columns, or run expensive queries. SafeDB MCP puts a policy layer between the agent and your database: only configured schemas and tables are visible, SQL is parsed and validated before execution, row counts are capped, results are masked, and every query attempt is audited.
This project is an MVP. It prefers false positives and blocked queries over unsafe access, and it does not claim perfect SQL security.
Features
MCP tools:
list_schemas,list_tables,describe_table,run_readonly_query,explain_query,get_safedb_policyPostgres support through
pgMySQL and MariaDB support through
mysql2SQLite file support through
sql.jsYAML or JSON config with environment expansion
AST-backed read-only SQL guardrails for
SELECT,WITH ... SELECT,UNION, andEXPLAIN SELECTTable detection through joins, CTEs, nested subqueries, aliases, and unions
Column projection checks that block masked fields selected through aliases or expressions
Configurable table allowlists, denylists, row limits, and statement timeout
PII masking:
redact,email,partial, and deterministichashJSONL audit log with no raw result data
CLI binary:
safedb-mcpTypeScript, Vitest, ESLint, Prettier
Related MCP server: Thoth MCP
Quickstart
npx @safedb/safedb-mcp init --output safedb.yaml
DATABASE_URL=postgres://readonly:password@localhost:5432/app npx @safedb/safedb-mcp validate-config --config safedb.yaml
DATABASE_URL=postgres://readonly:password@localhost:5432/app npx @safedb/safedb-mcp test-connection --config safedb.yaml
DATABASE_URL=postgres://readonly:password@localhost:5432/app npx @safedb/safedb-mcp --config safedb.yamlUse a dedicated database role with read-only permissions. SafeDB MCP is a defense-in-depth layer, not a replacement for least-privilege database credentials.
Docker
A Docker image packages SafeDB MCP with Node.js and its production dependencies so it can run the same way on any host with Docker.
Build the image locally:
docker build -t safedb-mcp .Run the MCP server with a mounted config file:
docker run --rm -i \
-e DATABASE_URL=postgres://readonly:password@host.docker.internal:5432/app \
-v "$PWD/safedb.yaml:/config/safedb.yaml:ro" \
safedb-mcpPass CLI commands after the image name:
docker run --rm \
-e DATABASE_URL=postgres://readonly:password@host.docker.internal:5432/app \
-v "$PWD/safedb.yaml:/config/safedb.yaml:ro" \
safedb-mcp --config /config/safedb.yaml validate-configExample Config
database:
type: postgres
url: ${DATABASE_URL}
safety:
default_limit: 100
max_limit: 1000
statement_timeout_ms: 5000
allow_explain: true
access:
schemas:
public:
allow_tables:
- users
- orders
- products
deny_tables:
- secrets
column_masks:
users.email: email
users.phone: partial
users.password_hash: redact
users.ssn: redact
audit:
path: safedb-audit.jsonlFor MySQL or MariaDB, set database.type and use the database name as the access schema:
database:
type: mysql
url: ${DATABASE_URL}
access:
schemas:
app:
allow_tables:
- users
- orders
deny_tables:
- secretsFor SQLite, set database.type to sqlite, point database.path at the .db file, and use main as the access schema:
database:
type: sqlite
path: ./app.db
access:
schemas:
main:
allow_tables:
- users
- orders
deny_tables:
- secretsMCP Client Config
Claude Desktop:
{
"mcpServers": {
"safedb": {
"command": "safedb-mcp",
"args": ["--config", "/absolute/path/to/safedb.yaml"],
"env": {
"DATABASE_URL": "postgres://readonly:password@localhost:5432/app"
}
}
}
}Cursor or Hermes-style MCP config:
{
"servers": {
"safedb": {
"command": "safedb-mcp",
"args": ["--config", "/absolute/path/to/safedb.yaml"],
"env": {
"DATABASE_URL": "postgres://readonly:password@localhost:5432/app"
}
}
}
}Security Guarantees
SafeDB MCP aims to guarantee that:
Only configured schemas and tables are inspectable or queryable through the MCP tools.
SQL is parsed before execution, and mutating statement types or multiple statements are blocked.
Table access policy is checked against real tables found through joins, CTEs, nested subqueries, aliases, and unions.
Masked columns cannot be selected through aliases or expressions that would bypass response masking.
Query execution happens inside a read-only transaction with a local statement timeout where the driver supports it.
Returned rows are capped by an outer
LIMIT.Configured PII fields are masked before tool responses are returned.
Audit logs record attempts, decisions, detected tables, row counts, and duration without logging raw result rows.
Passwords and secrets are not intentionally logged.
Non-Goals
Formal proof of query safety.
Support for every valid dialect-specific read-only SQL construct.
Write operations, migrations, stored procedure execution, or
COPY.
Development
npm install
npm run build
npm test
npm run lintRoadmap
Per-tool and per-table rate limits.
Optional OpenTelemetry traces.
Signed audit logs.
Published Docker image and Helm chart.
License
MIT
Available Tools
6 toolsdescribe_tableB
Describe columns for an allowed table and show configured masks.
| Name | Required | Description | Default |
|---|---|---|---|
| schema | No | Schema name. Defaults to public. | |
| table | Yes | Table name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description bears full burden. It states the action but does not disclose behavioral traits such as read-only nature, side effects, or authorization needs. The description is minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with purpose, no unnecessary words. Efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple nature of the tool with two parameters and no output schema, the description adequately covers what the tool does. Could optionally mention return value details, but not necessary.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter descriptions. The description adds no new meaning beyond the schema, meeting the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'describe' and the resource 'columns for an allowed table', and adds 'show configured masks', distinguishing it from sibling tools like list_tables or explain_query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when or when not to use the tool. It does not mention alternatives or context for selecting this tool over siblings like list_tables or explain_query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_queryA
Run a guarded EXPLAIN SELECT query against allowed tables.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | EXPLAIN SELECT query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. The word 'guarded' hints at restrictions, but it does not explain whether the operation is read-only, what happens on disallowed queries, or any side effects. More detail is needed for a tool with zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence of 8 words that immediately conveys the core purpose. Every word is necessary and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (1 parameter, no output schema, no annotations), the description covers the basic purpose and constraint. However, it lacks details on output format, error handling, and how to specify the table name within the query. A slightly more complete description would improve usability.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single parameter, which describes the query string as 'EXPLAIN SELECT query.' The description adds the context of 'guarded' and 'allowed tables', which provides additional semantic meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('run'), the specific query type ('EXPLAIN SELECT'), and the scope ('against allowed tables'), which distinguishes it from sibling tools like run_readonly_query that run general read-only queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies that this tool should be used specifically for EXPLAIN SELECT queries on permitted tables, and not for other query types or tables. It does not explicitly mention when to avoid or provide alternatives, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_safedb_policyA
Return the effective SafeDB safety policy without secrets.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry behavioral disclosure. It mentions 'without secrets' but does not indicate read-only behavior, authentication needs, or error conditions for a getter with no parameters.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no wasted words, and it is front-loaded with the action and resource.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description is reasonably complete, specifying the resource and the exclusion of secrets. It could mention the return format or default behavior, but it is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, and the schema coverage is 100%. The description does not need to add parameter information, meeting the baseline expectation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Return the effective SafeDB safety policy without secrets' using a specific verb and resource, and it is distinct from siblings which are about tables, queries, and schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives, though the distinct purpose from siblings is implied. The description lacks when-not-to-use or prerequisite information.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_schemasA
List database schemas allowed by the SafeDB policy.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must bear the burden. It states the schemas are filtered by policy, which is a behavioral aspect. However, it does not disclose potential issues like empty results or policy change effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no wasted words. Perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter tool with no output schema, the description is mostly complete. It could mention the return format (e.g., list of schema names), but the tool name and description imply that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so baseline 4 applies. The description adds no parameter info because none are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists database schemas allowed by SafeDB policy. It uses a specific verb 'List' and resource 'schemas', and distinguishes from siblings like list_tables and describe_table.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives. It does not mention that it only returns schemas allowed by policy, which is implicit, but no explicit when-not-to-use or comparison with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesB
List allowed tables in an allowed schema.
| Name | Required | Description | Default |
|---|---|---|---|
| schema | No | Schema name. Defaults to public. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description must fully disclose behavior. It mentions 'allowed' tables/schema, hinting at permission filtering, but does not explain how 'allowed' is determined or what happens on invalid input.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise single sentence with no wasted words. However, it could benefit from a brief note on behavior, such as what 'allowed' means.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one parameter and no output schema, the description is minimally complete. It lacks explanation of the 'allowed' restriction and assumes agent understanding of permissions, leaving gaps for first-time users.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage for one parameter. The description adds the default value 'public' for the schema parameter, which is not in the schema description, adding useful meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists tables in a schema, with the specific scope of 'allowed' tables and schema. It is distinct from siblings like 'describe_table' or 'list_schemas', but does not explicitly differentiate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like 'describe_table' or 'list_schemas'. Lacks explicit context on prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_readonly_queryA
Run a guarded read-only SELECT query against allowed tables.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | SELECT or WITH ... SELECT query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description must disclose behaviors. It states 'guarded read-only' and 'allowed tables', indicating safety constraints but does not specify what guards apply (e.g., limits, errors). Vague but adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence without unnecessary words. It is front-loaded with the core action and constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and no output schema, the description covers the essential behavior. It could add details about what 'guarded' means, but it is largely complete given the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (query parameter documented). The tool description adds context about read-only and table restrictions, surpassing the schema's own description. This adds value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it runs a guarded read-only SELECT query against allowed tables, with a specific verb and resource. It distinguishes from siblings like describe_table or list_tables.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for read-only queries on allowed tables but does not explicitly state when not to use it or alternatives. The sibling list provides context, but the description lacks clear when-to-use guidance.
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. Dates show when Glama detected each change.
6 tool updates
v0.1.0- First observed
describe_table - First observed
explain_query - First observed
get_safedb_policy - First observed
list_schemas - First observed
list_tables - First observed
run_readonly_query
TDQS
Each tool targets a distinct aspect of database safety: listing schemas/tables, describing columns, running queries, explaining queries, and retrieving policy. No overlapping purposes.
All tool names follow a consistent verb_noun pattern (describe_table, explain_query, get_safedb_policy, list_schemas, list_tables, run_readonly_query). No deviations.
Six tools cover the core functionality of a read-only safe database interface without being excessive or sparse. Each tool serves a clear and necessary role.
The tool set provides full lifecycle for read-only access: listing schemas/tables, describing structure, executing queries with EXPLAIN, and fetching policy. No obvious gaps for the stated purpose.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceA governed analytics MCP server that provides LLM agents with safe, read-only access to data warehouses through a layered safety pipeline including AST validation, column/row governance, PII masking, cost limits, and audit.-
- AlicenseNot gradedqualityBmaintenanceA security-first, read-only MCP server for AI assistants to safely query MySQL, PostgreSQL, and Redis with layered safety checks.1MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server that provides safe, read-only SQL access for AI agents to query databases (PostgreSQL, MySQL, SQLite) with schema awareness and guardrails.12MIT
- FlicenseAqualityBmaintenanceAn MCP server that enables AI agents to securely interact with PostgreSQL databases with least-privilege scopes, PII masking, and human approval for writes.4-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/narekmalk/safedb-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server