readonly-db-mcp
Allows AI agents to run read-only queries (SELECT) and inspect schema, indexes, and foreign keys on MySQL databases.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@readonly-db-mcpshow me the users table schema"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
readonly-db-mcp
Let an AI agent explore your MySQL database — safely. A Model Context
Protocol server that gives Claude (or any MCP
client) the ability to run SELECT queries and inspect schema, indexes, and
foreign keys on your databases, with write-protection enforced mechanically at
three independent layers. Credentials never appear in tool input/output, logs,
git, or the conversation.
Point an LLM at a real database and the obvious fear is that it writes — a stray
UPDATE, aDROPin a hallucinated migration, aDELETEwithout aWHERE. This server makes that structurally impossible, not merely discouraged: even a query that slips past the parser is rejected by the database engine itself.
Why this exists
AI agents are great at "why is this row wrong?", "what does this schema look like?", and "which index would help this query?" — but you don't want to hand them write access to find out. Existing options force a bad trade: give the agent full DB credentials (scary), or copy data out into a sandbox (stale, high-effort, and a fresh PII surface).
readonly-db-mcp is the third option: a thin, auditable boundary that lets the
agent read live data and metadata while making writes impossible by
construction.
Related MCP server: mysql-mcp
The guarantee — three independent layers
A query reaches your data only if it survives all three. They are independent on purpose: each would hold even if the others were bypassed.
Layer | Catches | Enforced by |
AST validation ( | DDL, DML, statement stacking, | this code, via sqlglot |
| any | the MySQL engine |
|
| the PyMySQL driver |
Plus max_execution_time per statement and output caps (rows / cell width /
total characters) so a SELECT * can't hang the DB or flood the model's context
window.
Prove it yourself before trusting it — scripts/verify_boundary.py bypasses
the parser and confirms the engine rejects writes against your real database
(everything is rolled back). See Verifying the boundary.
Honest limits (read these)
Defense-in-depth, not magic. The boundary protects data integrity; it does not protect:
Query load. A read-only transaction still lets a giant
SELECTtable- scan a huge table. Point connections at a read replica where one exists, and keepmax_rows/statement_timeout_mstight. Use read-only DB credentials as a fourth, belt-and-suspenders layer.Data confidentiality. Query results are sent to your MCP client's model provider, like any other tool output. If a connection holds PII, treat it accordingly — mark it
require_opt_in(below) so it's off until you deliberately enable it.
Quickstart
You don't need to install anything or create a file — uvx
runs the published package on demand. Pick the path that fits you.
Fastest: one connection, zero files (great for a local DB)
Put the connection in your MCP client's env block. For Claude Code:
claude mcp add --scope user readonly-db \
--env RODB_HOST=127.0.0.1 \
--env RODB_USER=root \
--env RODB_PASSWORD=secret \
--env RODB_DATABASE=mydb \
-- uvx readonly-db-mcpThat's the whole setup — no config file, no ~/.config, no keyring. If
RODB_HOST/RODB_USER are set and there's no config file, the server runs as a
single connection built from those vars.
Guided: the init wizard (for a saved config file)
uvx readonly-db-mcp init # prompts for host/user/password/db, writes the file,
# and prints exactly where it went + the next commandManual / multiple databases
pipx install readonly-db-mcp # or: pip install readonly-db-mcp
mkdir -p ~/.config/readonly-db-mcp
cp config.example.toml ~/.config/readonly-db-mcp/config.toml # then edit itSee Configuration for the file format and where passwords come from.
Once registered, open Claude Code, run /mcp to confirm readonly-db is
connected, and ask questions in English — "what columns does the orders table
have?", "show me the 10 newest customers", "why is this query slow?".
Working from a clone instead of the published package? Replace
uvx readonly-db-mcpwithuv run --directory /path/to/readonly-db-mcp readonly-db-mcp.
Tools
Tool | What it does |
| Run a validated, read-only |
|
|
| The servers you can query: default schema, described schemas, gated/enabled state |
| The schemas (databases) visible on a connection's server |
| Tables/views in a schema (name, type, engine, approx rows) |
| Columns: type, nullability, key, default, comment |
| Indexes: columns, uniqueness, type, cardinality |
| Outbound + inbound foreign keys |
| Approx rows, data/index size, engine, timestamps |
connection defaults to your default_connection; schema defaults to that
connection's default_schema. The agent typically calls list_connections
first to discover what's available.
Configuration
Two concepts, one file (~/.config/readonly-db-mcp/config.toml):
Connection — a named server you can query (
host,port,user, creds). The name is yours to choose; there is intentionally no built-in notion of "production".Schema — a namespace inside a server (MySQL's "schema"/"database"). One connection exposes many; queries can join across schemas on the same server.
default_connection = "shop"
[limits] # global; per-connection limits can override
max_rows = 1000
statement_timeout_ms = 15000
[connections.shop]
host = "db.example.com"
user = "readonly"
default_schema = "shop_core"
description = "Main application server"
[connections.shop.schemas.shop_core]
description = "Customers, orders, products" # shown to the agent in list_schemas
[connections.warehouse]
host = "warehouse.example.com"
user = "readonly"
require_opt_in = true # off until you enable it (see below)
[connections.warehouse.limits]
max_rows = 200The opt-in gate (default-safe)
Any connection with require_opt_in = true is refused unless you name it in
the RODB_ENABLE_GATED allowlist on the process that launches the server:
| Effect |
unset / | all gated connections refused (default) |
| every gated connection enabled |
| only |
| both enabled |
This is a neutral mechanism — a PII or production database is the canonical
thing you'd gate, but it works for anything you want off-by-default. With Claude
Code, set it on the registration: claude mcp add ... --env RODB_ENABLE_GATED=warehouse ....
Where secrets come from
Connections are non-secret and safe to commit. Only the password is a secret,
resolved per connection, in order: RODB_PASSWORD_<CONNECTION> env →
OS keyring (readonly-db-mcp / connection name) → password in the config.
A .env beside config.toml (or RODB_ENV_FILE) is loaded first and can supply
the env var (see .env.example). Discovery is cwd-independent — an MCP server's
working directory is the client's, so a project-relative .env would silently
not load.
No config file at all (single connection)
If no config file exists but RODB_HOST and RODB_USER are set, the server runs
as one connection built entirely from the environment — this is the zero-file
quickstart path. An explicit config file always takes precedence.
Var | Purpose |
| server host (enables the zero-file path) |
| server port (default |
| username |
| password for the single env connection |
| default schema for the single env connection |
Environment variables (all)
Var | Purpose |
| path to config.toml (default |
| path to a |
| the zero-file single connection (above) |
| password for a named connection in the config file |
| allowlist of gated connections to enable |
| audit-log directory (default |
| set to |
Verifying the boundary
readonly-db-mcp-verify # the default connection
readonly-db-mcp-verify --connection warehouse
readonly-db-mcp-verify --all # every connection
# from a clone: uv run python scripts/verify_boundary.py [--all]It connects to your real DB, deliberately attempts writes with the AST layer
bypassed, and confirms the MySQL engine itself rejects them (ERROR 1792, or a
read-only grant / replica). It reports which layer caught each attempt and rolls
everything back. Expected ending: ALL BOUNDARIES PROVEN.
Audit log
Every query that reaches a DB — and every blocked (gated) attempt — is appended
as one JSON line to <config dir>/logs/<connection>.log: timestamp, connection,
schema, tool, the SQL, row count, duration, outcome. Result data is never
logged, so the log is not a PII sink. Files are created 0600.
Development
uv run pytest # safety + config + formatting tests; no DB requiredThe test suite runs entirely without a database — the boundary's AST layer and the config resolution are pure functions. CI runs it on every push.
License
MIT — see LICENSE.
Available Tools
9 toolsdescribe_tableC
Columns of a table: name, type, nullability, key, default, extra, comment.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, and the description does not disclose error behavior, prerequisites, or default schema/connection handling. It only lists output columns, leaving important behavioral gaps.
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: one short sentence that front-loads the purpose and lists output fields. No wasted words.
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?
With 3 parameters, no output schema, and no annotations, the description is insufficient. It lacks detail on parameter usage, return format beyond a list, and edge cases.
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 0%, and the tool description adds no meaning to parameters beyond their names and types. It does not explain the role of schema or connection.
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 returns column metadata (name, type, nullability, key, default, extra, comment) for a table, distinguishing it from siblings like get_foreign_keys or get_indexes. The verb is implicit but clear.
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 such as explain or get_foreign_keys. The description only lists output fields, not usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explainA
EXPLAIN FORMAT=JSON for a SELECT — query plan (indexes, join order, estimated rows) without executing it. Same connection/schema routing as run_select.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that the tool returns a query plan in JSON format and that it does not execute the SQL, implying a read-only, non-destructive operation. It also reveals that connection and schema routing mirror run_select, which is helpful. However, it does not explicitly state that it is read-only or safe, nor does it discuss error behavior.
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 concise with two sentences. The first sentence front-loads the core purpose (EXPLAIN FORMAT=JSON for SELECT, query plan, no execution). The second adds routing context. Every sentence adds value, and there is no fluff.
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 complexity of an EXPLAIN tool with no output schema, the description adequately covers the output contents (indexes, join order, estimated rows) and the JSON format. It ties routing to run_select, which leverages existing knowledge. However, it omits details like whether only SELECT is supported, error handling, or how the JSON is returned (string vs parsed). Still, it is fairly complete for an experienced database user.
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 0%, so the description must compensate. It only mentions that schema and connection follow the same routing as run_select, but does not explain their individual roles or constraints. The sql parameter is implied to be a SELECT statement, but no validation or format details are given. This lack of parameter guidance makes it difficult for the agent to use parameters correctly.
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 that the tool executes an EXPLAIN FORMAT=JSON for a SELECT statement to show the query plan (indexes, join order, estimated rows) without executing it. It distinguishes itself from run_select by explicitly noting it does not execute, and from other siblings like describe_table by focusing on query planning.
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 contrasts with run_select by stating 'without executing it,' which implies use when you want the plan without execution. It also mentions 'Same connection/schema routing as run_select,' providing context for parameter usage. However, it does not explicitly state when not to use or list alternative tools for other EXPLAIN formats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_foreign_keysB
Foreign keys on a table (outbound) and FKs pointing to it (inbound).
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that both outbound and inbound foreign keys are returned. However, without annotations, it should also mention permissions, side effects, or limitations, which it does not.
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?
Very short and to the point, but the single sentence could be improved by structuring it as bullet points or adding slight elaboration.
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 no output schema and low parameter coverage, the description is adequate for a simple retrieval task but lacks usage context and parameter details.
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 0%, so the description must explain parameters. Only 'table' is implied; 'schema' and 'connection' are not described at all, leaving ambiguity.
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 specifies that the tool retrieves foreign keys: outbound (from the table) and inbound (pointing to it). It distinguishes from siblings like get_indexes and describe_table, but could be more explicit about the relational aspect.
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 such as describe_table or get_indexes. No conditions or prerequisites are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_indexesC
Indexes of a table: name, columns (in order), uniqueness, type, cardinality.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explains the output fields (name, columns, etc.) but omits any mention of side effects, permissions, or limitations. The read-only nature is implied but not explicit.
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. It gets straight to the point, though it could benefit from more structure or explanation.
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 3 parameters, no output schema, and no annotations, the description is too brief. It doesn't specify how the parameters affect the results or what the output looks like beyond the listed fields. The tool's behavior in different scenarios (e.g., schema specified or not) is unclear.
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 description does not explain any of the 3 parameters ('table', 'schema', 'connection'). With 0% schema description coverage, the description fails to add meaning beyond the schema, leaving the agent without guidance on how to use them.
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 indicates the tool returns index details for a table, listing attributes like name, columns, uniqueness, type, and cardinality. However, it does not explicitly differentiate from sibling tools like 'describe_table' which may also provide index info.
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 provides no guidance on when to use this tool versus alternatives (e.g., 'get_foreign_keys', 'describe_table'). No context about prerequisites or context is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_connectionsA
List the connections you can query, with each one's default schema, any described schemas, whether it is gated (require_opt_in) and currently enabled.
Call this FIRST when unsure what to target. Query one with run_select(..., connection=, schema=). Gated connections show enabled=false until RODB_ENABLE_GATED opts them in.
| 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 carries full burden. It discloses the return details including schema, gated status, and enabled status. Explains that gated connections show enabled=false until opted in. Does not mention any side effects or limitations, but for a listing tool, this is 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?
Two sentences, concise and well-structured. Front-loads main purpose, then adds usage guidance. No unnecessary words.
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 zero parameters, no output schema, and simple listing functionality, the description covers what is returned, how to use results, and the special case of gated connections. Could mention that it returns a list of connection objects but is still complete enough.
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 is 4. Description adds no parameter info, which is expected. Schema coverage is 100% by default since no properties.
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 'List' and the resource 'connections', and details the specific information provided (default schema, described schemas, gated status, enabled status). It also distinguishes from siblings by recommending to call this first when unsure what to target.
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?
Provides explicit when-to-use guidance ('Call this FIRST when unsure what to target') and explains how to proceed with querying connections using run_select. Also describes the behavior of gated connections and how to enable them. Lacks explicit when-not-to-use, 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.
list_schemasA
List the schemas (databases) visible on a connection's server, with any
descriptions you configured. System schemas are hidden. Use this to discover
which schema to pass to the other tools.
| Name | Required | Description | Default |
|---|---|---|---|
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries the burden. It mentions hiding system schemas but lacks details on connection parameter behavior (e.g., default connection) and return format. Could be more transparent.
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?
Two sentences with no wasted words. First sentence defines action, second provides usage guidance. 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?
Given no output schema and one simple parameter, the description covers essentials (what it lists, hidden schemas, purpose). Could mention return type or ordering, but overall 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?
Only one parameter 'connection', which is self-explanatory. The description adds context by referring to 'a connection's server', but doesn't elaborate on its default or null behavior. Schema coverage is 0%, but the parameter name is clear.
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 lists schemas (databases) on a connection's server, with descriptions, and hides system schemas. It 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?
Explicitly advises using this to discover which schema to pass to other tools, providing clear context. However, it doesn't explicitly mention when not to use it or alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesB
List tables and views in the resolved schema (name, type, engine, approx rows).
| Name | Required | Description | Default |
|---|---|---|---|
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description must disclose behavior. It only states a read operation without mentioning permissions, side effects, or limits like connection requirements.
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 single sentence is concise and focused, with no wasted words. It could benefit from a slightly more structured format but is efficient.
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 and lack of output schema, the description minimally covers what it returns. Missing context on 'resolved schema' but adequate for a basic listing.
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 0%, and the description does not explain the 'schema' or 'connection' parameters. It adds no meaning beyond their names.
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 and views with specific attributes (name, type, engine, approx rows). It distinguishes from siblings like describe_table or get_foreign_keys.
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 when-to-use or when-not guidance is provided. The description implies schema exploration, but does not mention alternatives or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_selectA
Run a single read-only SELECT (or WITH...SELECT / UNION) against a database.
connection is a named server from your config (defaults to the configured
default_connection). schema sets the default database/namespace for the query
(defaults to that connection's default_schema); table names can still be schema-
qualified to read across schemas on the same connection. Call list_connections()
if unsure what's available, list_schemas(connection) to see schemas on one.
Writes, DDL, multiple statements, INTO OUTFILE and dangerous functions are
rejected. Output is capped; when truncated is true, pass the suggested
offset to page.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| offset | No | ||
| schema | No | ||
| max_rows | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavioral traits: rejects writes, DDL, multiple statements, INTO OUTFILE, and dangerous functions; output is capped with pagination via offset; explains default connection and schema behavior. This is comprehensive.
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 paragraph, front-loaded with the main purpose, followed by parameter explanations and restrictions. Every sentence adds necessary information without redundancy.
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 complexity (arbitrary SQL), no output schema, and no annotations, the description covers all essential aspects: purpose, limitations, parameter defaults, pagination, and references to sibling tools for discovery. It is sufficiently complete for correct tool invocation.
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 0%, so the description compensates by explaining connection and schema parameters in detail, including defaults and cross-schema access. It mentions offset for pagination but does not explicitly describe the max_rows parameter. Overall, adds significant 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 explicitly states the tool runs a read-only SELECT/WITH...SELECT/UNION query against a database, specifying the verb 'Run' and resource 'SELECT query'. It clearly distinguishes from sibling tools like list_tables or describe_table by focusing on arbitrary read-only SQL execution.
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 guides the agent to call list_connections() and list_schemas() for discovery, and states that writes/DDL are rejected. However, it does not explicitly exclude alternatives like explain or describe_table for specific use cases, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
table_statsC
Approximate size of a table: row estimate, data/index bytes, engine, timestamps.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes | ||
| schema | No | ||
| connection | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description mentions 'approximate' indicating inexactness, but with no annotations, it fails to disclose other behavioral traits like performance, required permissions, or side 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 is concise and front-loaded with key output info, but lacks depth and structure for a multi-parameter tool.
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 3 parameters with zero schema coverage, no output schema, and no annotations, the description is insufficient for an agent to correctly invoke the tool. Parameter guidance and return value details are missing.
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 has 0% coverage (no descriptions), and the tool description does not explain the meaning or format of any parameters (table, schema, connection), leaving the agent without necessary context.
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?
Description clearly states the tool provides approximate table size including row estimate, data/index bytes, engine, and timestamps. It implicitly differentiates from siblings like describe_table by focusing on size metrics, though not explicitly.
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. The description implies it's for size estimates but does not address when not to use it or mention sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose: metadata retrieval (describe, indexes, foreign keys, schemas, tables, stats), query planning (explain), and query execution (run_select). No overlap or ambiguity.
Names consistently use snake_case and mostly follow a verb_noun pattern (describe_table, list_tables, run_select). 'table_stats' is a minor deviation (noun_noun) but remains clear.
9 tools are well-scoped for a read-only database server, covering discovery, introspection, and querying without redundancy or bloat.
The tool set covers all essential operations for a read-only database interface: listing available connections/schemas/tables, describing columns, indexes, and foreign keys, running EXPLAIN and SELECT queries, and retrieving table statistics.
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
AI agents propose database changes as reviewable requests — no direct write access.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
AI-security knowledge as MCP: standards-mapped tools (OWASP, NIST, MITRE) for AI agents.
An agent-native database over MCP: shared, validated, structured records in every AI chat.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceAn MCP server that enables AI agents to safely explore and interact with MySQL databases through dynamic tool generation from stored procedures. It provides database discovery capabilities and intelligent procedure categorization while enforcing security restrictions to prevent data modification.
- AlicenseAqualityDmaintenanceEnables AI agents to query and manage MySQL databases through a structured MCP interface, supporting SQL execution, table inspection, and database operations.917MIT
- AlicenseNot gradedqualityDmaintenanceA robust MCP server for interacting with MySQL databases through AI agents, providing tools for schema analysis, query execution, and dynamic connection management with read-only security.121MIT
- FlicenseNot gradedqualityFmaintenanceA read-only MCP server that enables AI agents to explore database schemas and execute safe queries on PostgreSQL and MySQL.
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/mir-shakir/readonly-db-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server