Skip to main content
Glama
narekmalk

safedb-mcp

by narekmalk

SafeDB MCP

CI npm version safedb-mcp MCP server

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_policy

  • Postgres support through pg

  • MySQL and MariaDB support through mysql2

  • SQLite file support through sql.js

  • YAML or JSON config with environment expansion

  • AST-backed read-only SQL guardrails for SELECT, WITH ... SELECT, UNION, and EXPLAIN SELECT

  • Table 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 deterministic hash

  • JSONL audit log with no raw result data

  • CLI binary: safedb-mcp

  • TypeScript, 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.yaml

Use 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-mcp

Pass 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-config

Example 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.jsonl

For 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:
        - secrets

For 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:
        - secrets

MCP 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 lint

Roadmap

  • Per-tool and per-table rate limits.

  • Optional OpenTelemetry traces.

  • Signed audit logs.

  • Published Docker image and Helm chart.

License

MIT

Available Tools

6 tools
describe_tableB

Describe columns for an allowed table and show configured masks.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaNoSchema name. Defaults to public.
tableYesTable name.

TDQS

B3.4/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesEXPLAIN SELECT query.

TDQS

A3.9/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
schemaNoSchema name. Defaults to public.

TDQS

B3.1/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesSELECT or WITH ... SELECT query.

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 6 tool updatesv0.1.0
    • First observeddescribe_table
    • First observedexplain_query
    • First observedget_safedb_policy
    • First observedlist_schemas
    • First observedlist_tables
    • First observedrun_readonly_query

TDQS

A4/5.0
Disambiguation5/5

Each tool targets a distinct aspect of database safety: listing schemas/tables, describing columns, running queries, explaining queries, and retrieving policy. No overlapping purposes.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivityInactive
ResponsivenessNo issues

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A 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.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    A security-first, read-only MCP server for AI assistants to safely query MySQL, PostgreSQL, and Redis with layered safety checks.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that provides safe, read-only SQL access for AI agents to query databases (PostgreSQL, MySQL, SQLite) with schema awareness and guardrails.
    12
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    An 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

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