duckdb-mcp
A fast, persistent DuckDB MCP server that enables AI assistants to query and manage local and cloud data. It supports:
SQL Querying: Execute
SELECTstatements and get results as text tables.SQL DDL/DML: Run write operations (
INSERT,UPDATE,DELETE,CREATE,DROP) without returning rows.Data Loading: Ingest CSV and Parquet files (local or
s3://) into tables.Introspection: List catalogs, databases, schemas, tables, columns, and loaded extensions.
Environment Inspection: List environment variables with masked values for security.
Version Check: Report the DuckDB version.
Initialization: Run custom SQL scripts on startup via
--init-sql.Security: Optional read-only mode, masking of secrets, and HTTP bearer token auth.
Extensibility: Enable unsigned community extensions.
Deployment: Available over stdio or HTTP.
Provides tools for querying DuckDB databases, loading CSV and Parquet files, and listing catalogs, schemas, tables, columns, extensions, environment variables, and DuckDB version.
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., "@duckdb-mcpLoad sales.csv and show total revenue by region"
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.
๐ฆ DuckDB MCP Server
Give your AI assistant a blazing-fast, persistent SQL engine.
A minimal Model Context Protocol server that plugs DuckDB straight into Claude โ query CSVs, Parquet, and cloud data in plain language, at in-process speed.
โก ~10 ms / query ยท ๐ชถ 2 runtime deps ยท ๐งฐ 12 tools ยท ๐ read-only & secret-safe
โจ Why this one?
โก Fast | One persistent connection for the whole session โ no subprocess spawn, no reconnect. ~10 ms per query. |
๐ชถ Tiny | A focused |
๐งฐ Complete | 12 tools covering query, write, CSV/Parquet loading, and full catalog/schema/table introspection. |
๐ Safe by default | Engine-enforced |
โ๏ธ Cloud-ready | Query |
๐งฉ Extensible | Opt-in unsigned/community extensions (e.g. TA-Lib) via a single flag or env var. |
๐ Local or remote | Run over stdio (Claude Desktop) or streamable HTTP โ one |
๐ Token auth | Protect the HTTP transport with a bearer token from a single env var. |
โ Trustworthy | Fully typed, linted, and tested โ CI runs black + ruff + mypy + pytest on Python 3.12 & 3.13. |
Related MCP server: mcp-server-motherduck
๐ Quick start
1. Run it โ no install needed (via uv):
uvx --from git+https://github.com/wuqunfei/duckdb-mcp-mini duckdb-mcp --db :memory:2. Point Claude Desktop at it โ add this to claude_desktop_config.json and restart Claude:
{
"mcpServers": {
"duckdb": {
"command": "uvx",
"args": ["--from", "git+https://github.com/wuqunfei/duckdb-mcp-mini", "duckdb-mcp", "--db", ":memory:"]
}
}
}3. Ask away ๐ฌ
"Load
~/data/sales.csvand show me total revenue by region."
That's it. Tools are available immediately. ๐
๐ฆ Install
pip install . # from a clone, into the current environment
pip install -e ".[dev]" # for development (editable + dev tools)Or run straight from Git without installing:
uvx --from git+https://github.com/wuqunfei/duckdb-mcp-mini duckdb-mcp --db :memory:โน๏ธ This package is not published to PyPI โ install from source or run from Git as shown above.
Requirements: ๐ Python 3.11โ3.14 ยท ๐ฆ DuckDB 1.5.2 (pinned in pyproject.toml, easy to change) ยท ๐ MCP SDK 2.0.0+
๐ Run
The installed console script is duckdb-mcp. It speaks MCP over stdio, so you'll normally launch it from an MCP client โ but you can start it directly too:
duckdb-mcp # in-memory, read-write
duckdb-mcp --db /path/to/analytics.duckdb --schema main
duckdb-mcp --db analytics.duckdb --init-sql init.sql
duckdb-mcp --db analytics.duckdb --read-only
python -m duckdb_mcp.cli --db :memory: # module form
uv run duckdb-mcp --db :memory: # via uv, no installCLI arguments
Flag | Description |
| Database path ( |
| Default schema. Default: |
| Path to a SQL file executed once on startup |
| Open the database read-only (default: read-write) |
| Allow unsigned/community extensions (default: off; env: |
|
|
| Bind host for the |
| Bind port for the |
| Log level to stderr: |
๐ Debugging: run with
--log-level DEBUG(orLOG_LEVEL=DEBUG) to log every incoming tool request โ name and arguments โ to stderr, so you can see exactly what a client sends:DEBUG duckdb_mcp: tool request: query args={'sql': 'SELECT 42 AS answer'}Logs always go to stderr (never stdout, which is the protocol channel in stdio mode).
๐ Read-only mode
--read-only opens the connection via DuckDB's own read-only flag, so writes are blocked at the engine level (not by inspecting SQL):
โ
SELECTworks normally๐ซ
INSERT/UPDATE/DELETE/CREATE/DROPare rejected by DuckDB๐ก Perfect for shared analytics/reporting databases where accidental writes must be impossible
๐ Transports
The server speaks two MCP transports โ pick with --transport:
Transport | Flag | Use it for |
stdio (default) |
| Local clients that launch the process, e.g. Claude Desktop |
streamable HTTP |
| Remote / networked clients โ the current MCP HTTP transport (single |
# stdio (default) โ the process talks over stdin/stdout
duckdb-mcp --db analytics.duckdb๐ Run an HTTP server
Configuration splits cleanly in two: args set the database and network binding, environment variables carry secrets and toggles (so they stay out of ps and shell history).
# 1) Environment โ secrets & toggles
export MCP_AUTH_TOKEN="a-long-random-secret" # require Bearer auth (recommended)
export ALLOW_UNSIGNED_EXTENSIONS=true # optional: allow community extensions
export AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" # optional: for s3:// queries
export AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}"
# 2) Args โ database + network binding
duckdb-mcp \
--transport http \
--host 0.0.0.0 \
--port 8000 \
--db /data/analytics.duckdb \
--init-sql /data/init.sql \
--read-only
# โ serving at http://0.0.0.0:8000/mcp--init-sql runs a SQL file once, when the connection opens. Combined with --read-only it must be read-only-safe (loading extensions or setting options is fine โ creating tables is not):
-- /data/init.sql
INSTALL httpfs; LOAD httpfs; -- read remote/S3 data
SET memory_limit = '4GB';Drop
--read-onlyif your init script needs to create tables or views.
No install? Run the same thing straight from Git:
MCP_AUTH_TOKEN="a-long-random-secret" \
uvx --from git+https://github.com/wuqunfei/duckdb-mcp-mini duckdb-mcp \
--transport http --host 0.0.0.0 --port 8000 --db :memory:Setting | Kind | Notes |
| arg | Required to serve over HTTP |
| arg | Bind address (default |
| arg | Same as stdio mode |
| env | Require |
| env | Community extensions (or the |
| env | Cloud credentials for |
| both |
|
Verify it's up (with MCP_AUTH_TOKEN set, a missing/wrong token returns 401):
curl -s -o /dev/null -w '%{http_code}\n' \
-X POST http://127.0.0.1:8000/mcp \
-H 'Authorization: Bearer a-long-random-secret' \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
# 401 = missing/invalid token ยท 400 = reached the server (a real client does the full MCP handshake)๐ Bearer token
Setting MCP_AUTH_TOKEN turns on auth for the HTTP transport:
๐ฑ Environment only โ read from
MCP_AUTH_TOKEN, never a CLI flag, so it stays out ofpsand shell history.๐ HTTP only โ ignored for
stdio(the client owns the process); setting it there prints a warning.โ ๏ธ Access control, not identity โ every caller with the token gets full database access. Pair it with
--read-onlyand network controls; it is not per-user auth.
๐
--hostdefaults to127.0.0.1(localhost only). Bind to0.0.0.0only on a trusted network, and always withMCP_AUTH_TOKENset.
๐ Connect a client
MCP client config (Claude Desktop or any client that supports an HTTP URL) โ omit headers if you didn't set a token:
{
"mcpServers": {
"duckdb": {
"url": "http://127.0.0.1:8000/mcp",
"headers": { "Authorization": "Bearer a-long-random-secret" }
}
}
}From Python (the mcp client libraries ship httpx2):
import asyncio
import httpx2
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
URL = "http://127.0.0.1:8000/mcp"
HEADERS = {"Authorization": "Bearer a-long-random-secret"} # omit if no MCP_AUTH_TOKEN
async def main():
async with httpx2.AsyncClient(headers=HEADERS) as http:
async with streamable_http_client(URL, http_client=http) as streams:
read, write = streams[0], streams[1]
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print("tools:", [t.name for t in tools.tools])
result = await session.call_tool("query", {"sql": "SELECT 42 AS answer"})
print(result.content[0].text)
asyncio.run(main())๐ฅ๏ธ Configure Claude Desktop
Add one of the following to your claude_desktop_config.json, then restart Claude.
Run from Git (no install):
{
"mcpServers": {
"duckdb": {
"command": "uvx",
"args": ["--from", "git+https://github.com/wuqunfei/duckdb-mcp-mini", "duckdb-mcp", "--db", ":memory:"]
}
}
}Run from a local clone:
{
"mcpServers": {
"duckdb": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/duckdb-mcp-mini", "duckdb-mcp", "--db", "/home/user/analytics.duckdb", "--schema", "main"]
}
}
}After pip install . (command on PATH):
{
"mcpServers": {
"duckdb": {
"command": "duckdb-mcp",
"args": ["--db", "/home/user/analytics.duckdb", "--read-only"]
}
}
}๐ Config file locations
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
๐ Multiple servers
Add more entries under mcpServers with distinct names (e.g. duckdb-dev, duckdb-prod), each with its own --db/--schema.
โ๏ธ Environment variables & cloud data
Any variables set in the client's env block are available to DuckDB during connection (handy for S3/cloud credentials). Values support ${VAR_NAME} interpolation, so you can reference the system environment instead of hardcoding secrets into the config file:
{
"mcpServers": {
"duckdb": {
"command": "uvx",
"args": ["--from", "git+https://github.com/wuqunfei/duckdb-mcp-mini", "duckdb-mcp", "--db", ":memory:"],
"env": {
"AWS_ACCESS_KEY_ID": "${AWS_ACCESS_KEY_ID}",
"AWS_SECRET_ACCESS_KEY": "${AWS_SECRET_ACCESS_KEY}",
"AWS_REGION": "${AWS_REGION}",
"S3_BUCKET": "my-data-bucket"
}
}
}
}Set the referenced variables in your shell first:
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
export AWS_REGION="us-east-1"Then query cloud data directly:
SELECT * FROM read_parquet('s3://my-data-bucket/data.parquet')๐ Interpolation happens before the DuckDB connection is opened, so credentials are ready in time for connection setup and any
--init-sql. Use thelist_environmentstool to confirm what's set โ values are always masked.
๐งฉ Community & unsigned extensions
DuckDB only loads signed extensions by default. To use community or self-hosted extensions, enable unsigned extensions with the --allow-unsigned-extensions flag or the ALLOW_UNSIGNED_EXTENSIONS environment variable (default: off):
duckdb-mcp --db :memory: --allow-unsigned-extensions
# or
ALLOW_UNSIGNED_EXTENSIONS=true duckdb-mcp --db :memory:In a Claude Desktop config:
{
"mcpServers": {
"duckdb": {
"command": "uvx",
"args": ["--from", "git+https://github.com/wuqunfei/duckdb-mcp-mini", "duckdb-mcp", "--db", ":memory:", "--allow-unsigned-extensions"]
}
}
}The flag is applied as a connection-time setting, so it's already on โ just INSTALL and LOAD through the execute tool. For example, neuesql/atm_talib (TA-Lib for DuckDB):
INSTALL talib FROM 'https://neuesql.github.io/atm_talib';
LOAD talib;โ ๏ธ Unsigned extensions run native code with full trust. Only enable this for extensions from sources you trust.
๐งฐ Tools (12)
Category | Tool | Purpose |
๐ Core |
| Run a |
โ๏ธ Core |
| Run a write statement ( |
๐ฅ File I/O |
| Load a CSV file into a table ( |
๐ฅ File I/O |
| Load a Parquet file into a table ( |
๐ Introspection |
| List catalogs |
๐ Introspection |
| List databases |
๐ Introspection |
| List schemas |
๐ Introspection |
| List tables in the current schema |
๐ Introspection |
| Describe a table's columns |
๐ Introspection |
| List loaded extensions |
๐ Introspection |
| List environment variables as |
๐ท๏ธ Introspection |
| Report the DuckDB version |
query vs execute โ query is for reads (fetches rows, formats a table); execute is for writes/DDL (runs the statement, returns "Executed successfully").
๐๏ธ Architecture
launch (cli.main)
โ
DuckDBSession(...) # src/duckdb_mcp/session.py
โโ interpolate ${VAR} across os.environ โ runs BEFORE connecting
โโ duckdb.connect(db, read_only=...) โ one persistent connection
โโ run --init-sql (if provided) โ falls back to :memory: on error
โ
create_server(session) # src/duckdb_mcp/server.py
โโ registers 12 tools on an mcp MCPServer; each calls dispatch_tool()
โ
_serve(session, transport=...) # src/duckdb_mcp/cli.py
โโ run_stdio_async() | run_streamable_http_async()๐งฉ
session.pyholdsDuckDBSessionwith no MCP imports, so the connection/formatting logic is unit-testable with onlyduckdb.๐๏ธ
server.pyholds the_HANDLERSregistry (single source of truth for the tool set) plusdispatch_tool()and the thin typed MCP registrations.๐๏ธ
cli.pyparses args, builds the session, and serves.
Good to know:
๐ If connecting to
--db(or running--init-sql) fails, the session degrades to an in-memory read-write connection rather than crashing.โ ๏ธ SQL is f-string interpolated (table names, filepaths). This is intentional for a local single-user tool โ inputs are not sanitized.
๐ ๏ธ Development
pip install -e ".[dev]" # or: uv sync --extra dev
black --check src tests # format (drop --check to apply)
ruff check src tests # lint
mypy src # type check
pytest # tests
pytest tests/test_server.py::test_dispatch_query # run a single test๐ Project layout
duckdb-mcp-mini/
โโโ src/duckdb_mcp/
โ โโโ __init__.py # package version + DuckDBSession export
โ โโโ session.py # persistent DuckDB session (no MCP deps)
โ โโโ server.py # tool registry + dispatch + MCP server wiring
โ โโโ cli.py # argument parsing + entrypoint
โโโ tests/ # pytest suite
โโโ .github/workflows/
โ โโโ ci.yml # lint + type + test on py3.11โ3.14
โ โโโ release.yml # build on tag (PyPI publish disabled)
โโโ pyproject.toml
โโโ LICENSE
โโโ README.md๐ CI / CD
CI (
.github/workflows/ci.yml) runs black, ruff, mypy, and pytest on Python 3.11, 3.12, 3.13, and 3.14 for every push/PR tomain, and checks thatduckdb-mcp --helpworks.CD (
.github/workflows/release.yml) builds the sdist/wheel on av*tag and attaches them to the GitHub Release. PyPI publishing is intentionally disabled โ thepublish-pypijob is gated behindif: false; see the comments in that file to enable it later.
๐ค Contributing
Issues and PRs are welcome! Please keep the footprint small (the minimalism is a feature ๐ชถ), and make sure black / ruff / mypy / pytest all pass before opening a PR.
Built with ๐ฆ + ๐ ยท Licensed under MIT
Available Tools
12 toolscheck_versionA
Check the DuckDB version.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the burden. It only states 'Check the DuckDB version' without disclosing that it is read-only, the return format, or any potential side effects or 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 a single, clear sentence with no unnecessary words. It is appropriately sized and 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?
The tool is very simple and has an output schema, so the description is mostly sufficient. However, a brief mention of the returned value (e.g., version string) would be helpful, though the output schema likely covers this.
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 tool has zero parameters, so the input schema fully documents its inputs. The description adds no parameter-specific meaning, but the baseline for 0 parameters is 4.
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's function: checking the DuckDB version. It uses a specific verb and resource, and it is distinct from sibling tools that query or list metadata.
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 like execute, nor does it mention any context or prerequisites. There is no explicit 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.
executeA
Execute a SQL statement (INSERT, UPDATE, DELETE, CREATE, ...) without returning rows.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses that the tool returns no rows and lists potentially destructive operations (DELETE, CREATE). However, it does not explicitly warn about irreversible side effects, transaction handling, or permission requirements. It offers basic transparency but lacks the depth expected for a mutation-capable tool.
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, front-loaded sentence with no redundant words. It states the action, the object, and the key behavioral distinction ('without returning rows') efficiently.
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 one-parameter tool with an output schema (per context signals), the description covers the core purpose and return behavior. It does not mention error handling or transaction behavior, but these are less critical given the tool's simplicity and the presence of an output schema explaining return values.
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 0%, so the description must compensate. It indirectly clarifies that the 'sql' parameter is the SQL statement to execute, but adds no explicit detail about the parameter's format, constraints, or examples. For a single self-named parameter it is adequate but not outstanding.
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 uses a specific verb 'Execute' and names the resource 'SQL statement', with clear scoping: 'without returning rows'. This distinguishes it from sibling tools like 'query' that return rows. The explicit list of statement types (INSERT, UPDATE, DELETE, CREATE) further clarifies its purpose.
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 phrase 'without returning rows' provides clear context that this tool is for non-query SQL statements, implying that 'query' should be used for statements that return rows. However, it does not explicitly name an alternative or state when not to use this tool, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_catalogsA
List all catalogs.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosure, but it only repeats the operation ('List') without detailing read-only status, side effects, or other behavioral traits. The implicit read-only nature is not explicitly stated.
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, short sentence with no filler words. It is perfectly front-loaded and concise, containing only the essential information.
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โno parameters, no side effectsโand the presence of an output schema to define return values, the description is fully adequate. Nothing else is needed for a basic list operation.
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 tool has zero parameters, so there is nothing for the description to explain. The baseline of 4 applies as no compensation is 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 uses the specific verb 'List' and clearly identifies the resource 'all catalogs'. It effectively distinguishes this tool from sibling tools that list databases, schemas, tables, or other entities.
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 is given on when to use this tool versus its alternatives. The description only states the function, without any contextual cues or exclusions, leaving the agent to infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_columnsB
List the columns of a table.
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full responsibility for describing behavior, but it only says 'List the columns.' It does not disclose whether the operation is read-only (though implied), error behavior on missing tables, or whether column types are included. Minimal transparency.
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 filler. Every word is useful.
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 low complexity (one parameter, output schema present) the description is minimally functional, but it lacks usage context and guidance on how the columns are represented. It does not mention whether the output is just names or full metadata, relying on the output schema for completeness.
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 phrase 'of a table' maps to the table_name parameter, providing some semantic linkage. However, schema description coverage is 0%, and the description does not add details like expected format (e.g., qualified name) or constraints. The single parameter is self-explanatory, so partial compensation.
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 uses a specific verb ('List') and resource ('columns of a table'), clearly differentiating it from sibling tools like list_tables and list_schemas. It unambiguously states what the tool does.
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 is provided on when to use this tool vs alternatives. There is no mention of prerequisites (e.g., table must exist) or how it relates to sibling tools like list_tables or query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_databasesA
List all databases.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description bears the full burden of behavioral disclosure, but it merely restates the tool's function. It does not mention read-only nature, potential side effects, or access requirements, offering little beyond a tautology.
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 sentence that directly states the tool's purpose with no redundant information. It is concise and appropriately sized for such a simple operation.
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 absence of parameters and the presence of an output schema, the description is sufficient for invocation. However, it lacks differentiation from sibling list tools, which could help an agent choose the correct tool in a hierarchy.
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 tool has zero parameters, and the schema coverage is 100% (vacuously). Therefore, the description need not add parameter details; the baseline of 4 applies.
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 'List all databases' clearly identifies the action (list) and the target resource (databases), with 'all' defining scope. This distinguishes it from sibling tools like list_catalogs and list_schemas, which operate at different levels.
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. It does not mention exclusions, prerequisites, or context for selection, leaving the agent to rely solely on the tool name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_environmentsA
List environment variables as key: value, with values masked (**** / empty).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full transparency burden. It discloses the key behavioral trait of masking values (**** / empty), which is critical for a tool dealing with environment variables. However, it does not mention other behaviors like ordering, scope, or permissions, though these are less critical for a simple list operation.
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, front-loaded sentence that states the action, resource, and key behavior. Every word earns its place, and there is no redundancy or filler.
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 (no parameters, output schema present), the description is complete enough for correct use. It clearly indicates what is listed and how values are masked, without needing to explain return structure beyond what the output schema provides.
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 tool has zero parameters, so the baseline is 4. The description adds meaning by indicating the output format (key: value with masked values), which is relevant to what the user will receive even though no parameters exist.
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 environment variables in a key: value format with masked values. This specific verb-resource combination distinguishes it from sibling list_* tools which target database objects like catalogs, schemas, and 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 provides no explicit guidance on when to use this tool versus alternatives. While the sibling context implies it is for inspecting environment variables, there is no mention of use cases, prerequisites, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_extensionsA
List loaded extensions.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must communicate behavioral traits. The word 'List' implies a read-only operation, but no further behavior is disclosed (e.g., whether the list is sorted, whether extensions can be filtered). This is minimal but sufficient for a simple listing operation.
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, four-word sentence that conveys the entire purpose without waste. Every word earns its place, and it is appropriately sized for a zero-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 the tool's simplicity (no parameters, no side effects) and the presence of an output schema, the description is complete. It clearly states what the tool does, and no additional context is necessary for an AI agent to invoke it correctly.
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 tool has zero parameters, so the baseline is 4. The description adds no parameter information because none exist, and the schema already confirms this with 0 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 uses a specific verb 'List' with resource 'extensions', clearly distinguishing it from sibling tools like list_catalogs or list_tables. It is unambiguous and directly states the tool's function.
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 listing loaded extensions but provides no explicit guidance on when to use this versus alternatives, nor any exclusions. Given the sibling tool names, the usage context is inferred rather than clearly stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_schemasA
List all schemas.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
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. 'List' strongly implies a read-only operation with no side effects, but the description does not explicitly state this or mention any permission requirements or return characteristics. For a trivial read operation, this is adequate but not enriched.
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, highly efficient sentence with zero filler. Every word conveys meaning. For a tool this simple, additional structure would be unnecessary.
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 minimal complexity, zero parameters, and existing output schema, the description is nearly complete. It could be improved by adding a note about the context (e.g., schemas within the current catalog/database) or clarifying if all schemas includes system schemas, but these are minor gaps. Overall, it is sufficient for the intended use.
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 tool has zero parameters, and the schema coverage is 100% (trivially, as there is nothing to describe). The description adds no parameter-level detail, which is appropriate. The baseline for zero-parameter tools is 4, and there is no deficiency to lower the score.
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 'List all schemas' is a specific verb+resource pair that clearly identifies the tool's function. It distinguishes itself from sibling tools like list_tables or list_databases by naming the exact resource type (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?
The implied usage is clear: use this tool when you need to retrieve available schemas. However, there is no explicit when-to-use versus alternatives, nor any mention of exclusions or prerequisites. The simplicity of the tool makes the lack of guidance less detrimental, but it remains implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesA
List all tables in the current schema.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden. It clearly implies a read-only operation via 'List', but it does not disclose details like whether system tables are included, what 'current schema' exactly means in all contexts, or potential edge cases. It is minimally transparent but not rich.
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, focused sentence that conveys the essential information without any filler. It is perfectly concise and well-structured.
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 simplicity of the tool (no parameters, output schema exists), the description is complete. It specifies the exact scope and action, and the output schema covers return values. No additional context is 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?
There are zero parameters, so the baseline is 4. The description adds meaning by defining the scope ('current schema'), which is a contextual constraint understood beyond the empty schema. No additional parameter descriptions 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 uses a specific verb 'List' with a clear resource 'all tables' and a defined scope 'current schema'. This clearly distinguishes it from sibling tools like list_schemas and list_columns.
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?
While the description gives a clear context ('current schema'), it does not explicitly mention alternatives or when not to use the tool. However, for a zero-parameter tool with a self-explanatory name, the usage is clear enough, fitting the 'clear context, no exclusions' criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queryB
Execute a SQL SELECT query and return the results.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
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 of behavioral disclosure. It only states that it executes a SELECT query and returns results, without mentioning whether the query is strictly read-only, any execution limits, error behavior, or permission 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 description is a single, front-loaded sentence that says exactly what the tool does without any unnecessary words or redundancy. Every word earns its place.
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 one-parameter tool, the description is minimally complete: it states the action and outcome, and an output schema exists so return format need not be explained. However, it lacks usage context, such as how this tool relates to the many sibling data-access tools, and does not provide behavioral details that would help an agent decide when to invoke it.
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 0% description coverage, so the description must compensate. It does clarify that the 'sql' parameter is a SQL SELECT query, which adds meaning beyond the bare field name. However, it does not specify syntax, examples, or constraints, so the compensation is partial.
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 'Execute' and the resource 'a SQL SELECT query', and mentions returning results. It implies a read-only query tool, which distinguishes it from the sibling 'execute' (which might handle other SQL statements), though it does not explicitly name or contrast with alternatives.
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 is provided on when to use this tool versus alternatives like 'execute' or 'read_csv'. The word 'SELECT' implies read-only, but there is no explicit 'use for this, not for that' instruction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_csvC
Read a CSV file into a table.
| Name | Required | Description | Default |
|---|---|---|---|
| filepath | Yes | ||
| table_name | No | data |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, and the description does not disclose any behavioral traits beyond the bare operation. It does not mention side effects like table creation/overwriting, error behavior, permissions, or schema inference. The agent cannot judge the tool's safety or 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?
The description is a single, concise sentence with no wasted words. It is front-loaded and easy to parse, though arguably too short. However, the brevity is appropriate for a simple tool, and the under-specification is penalized in other dimensions.
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 output schema exists, the return format need not be described, but the description still lacks essential context: filepath handling, table_name meaning, comparison with read_parquet, and error scenarios. With no annotations, this sparse description is not sufficient for an agent to invoke the tool reliably.
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 says nothing about the parameters filepath and table_name. With 0% schema description coverage, the description does not compensate; it fails to clarify the filepath format, table_name semantics, or default behavior.
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 'Read a CSV file into a table' clearly states the verb (read), resource (CSV file), and outcome (into a table). It distinguishes from the sibling tool read_parquet by specifying the CSV format, making the purpose unambiguous.
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 is provided on when to use this tool vs alternatives like read_parquet or query. There are no usage contexts, prerequisites, or exclusions mentioned, leaving the agent without direction on choosing this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_parquetC
Read a Parquet file into a table.
| Name | Required | Description | Default |
|---|---|---|---|
| filepath | Yes | ||
| table_name | No | data |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It only states the basic function and does not disclose side effects, whether it creates a new table or overwrites existing data, or if it is read-only. No behavioral traits beyond the name are revealed.
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 unnecessary words. It is appropriately sized for a simple tool, though perhaps too sparse to be fully helpful.
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?
Despite the output schema existing, the description is incomplete. It does not explain the 'table' concept, the purpose of table_name, or any constraints on filepath. Given the low schema coverage, the description should provide more context.
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 adds no meaning to the parameters filepath and table_name. Schema coverage is 0%, so the description must compensate, but it does not mention either parameter or clarify their roles.
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 (read) and the resource (Parquet file) and the result (into a table). It is specific enough to distinguish from sibling tools like query or list_tables, though it does not explicitly contrast with read_csv.
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 is provided about when to use this tool versus alternatives. There is no mention of prerequisites, such as whether this should be used for local files vs. remote, or how it relates to read_csv or query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct action or resource: query vs execute clearly separate read vs write operations, read_csv vs read_parquet handle different file formats, and the list_* tools each inspect a unique metadata level (catalogs, databases, schemas, tables, columns, extensions, environments). There is no overlap or ambiguity.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_tables, read_csv, check_version). The verbs vary appropriately for the action, but the naming style is uniform and predictable.
With 12 tools, the server is well-scoped for a DuckDB interface. The set covers querying, executing statements, file ingestion, and metadata inspection without being bloated or too sparse.
Core workflows are covered: SQL query/execute, CSV/Parquet ingestion, and full metadata listing. Minor gaps exist, such as no write_csv/write_parquet output tools and no extension management beyond listing, but these are not critical for most DuckDB use cases.
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
Query, join, profile, clean and convert CSV/JSON/Parquet with server-side DuckDB over MCP.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
- mcpOAuthcom.gibsonai
GibsonAI MCP server: manage your databases with natural language
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server implementation that connects AI assistants to DuckDB, enabling them to query and analyze data from various sources including CSV, Parquet, JSON, and cloud storage through SQL.18MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables SQL analytics on DuckDB and MotherDuck databases, allowing AI assistants and IDEs to query and analyze data.MIT
- AlicenseAqualityDmaintenanceA local MCP server implementation that interacts with DuckDB and MotherDuck databases, providing SQL analytics capabilities to AI Assistants and IDEs.1MIT
- AlicenseNot gradedqualityDmaintenanceA local MCP server enabling AI assistants to query and analyze data via DuckDB SQL engine, supporting local files, memory, S3, and MotherDuck.16Apache 2.0
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/wuqunfei/duckdb-mcp-mini'
If you have feedback or need assistance with the MCP directory API, please join our Discord server