Skip to content

Releases: teaguesterling/duckdb_mcp

v1.5.2

27 Feb 18:53

Choose a tag to compare

What's Changed

Bug Fixes

  • Fix optional tool parameters not substituted with NULL (#20, closes #19)
    • Omitted optional parameters now substitute NULL into SQL templates instead of leaving $param placeholders unsubstituted
    • Explicit JSON null values now substitute SQL NULL instead of the string literal 'null'
  • Fix parameter substitution prefix collision
    • $id no longer incorrectly matches inside $id_extra — word-boundary enforcement on all $param tokens
  • Rewrite parameter substitution as single-pass tokenizer
    • Eliminates cross-parameter contamination where user-provided values containing $other_param could be altered during substitution
    • Substitution map built upfront, template scanned once — injected values never re-scanned
  • Fix COMMAND option test for CI environments
    • Test no longer depends on security singleton state

Documentation

  • Document mcp_publish_tool function signatures (closes #21)
    • Both overloads (5-arg and 6-arg) with named parameters
    • VARCHAR type requirement (not JSON type) with common pitfall warning
    • Optional parameter NULL substitution behavior

Security

  • Comprehensive parameter substitution security tests (SQL injection, prefix collision, cross-parameter contamination, type validation)

New Features (from v1.5.1)

  • PRAGMA functions for server introspection (mcp_tools, mcp_resources, mcp_prompts, mcp_server_info)
  • Config mode for deferred server configuration
  • COMMAND option in ATTACH for custom executable paths

Improvements

  • Security hardening improvements
  • WebMCP transport for browser-native MCP tool registration

Full Changelog: v1.5.1...v1.5.2

v1.5.1 — WASM Compatibility + DuckDB v1.5 + Security Audit

24 Feb 01:33
a40e341

Choose a tag to compare

What's New in v1.5.1

WASM/Emscripten Compatibility (PR #16)

The extension now loads and runs in DuckDB-WASM. Conditional compilation (#ifdef __EMSCRIPTEN__) gates out WASM-incompatible code (process spawning, file I/O, threading, HTTP server) while preserving full server-side functionality via the memory transport.

  • CMake: 11 native-only source files excluded from WASM builds
  • Server-side works in WASM: mcp_server_start('memory'), mcp_publish_table, mcp_publish_query, mcp_publish_resource, mcp_publish_tool, prompt templates, mcp_server_test — all functional
  • Client-side excluded in WASM: ATTACH, MCPFS, stdio/HTTP transports, connection registry
  • Header guards: 12 headers updated with #ifndef __EMSCRIPTEN__ around native-only class declarations
  • All 3 WASM variants pass CI: wasm_mvp, wasm_eh, wasm_threads
  • All native builds unaffected: linux (amd64, arm64, musl), macOS (amd64, arm64), Windows (amd64, mingw)

This enables future WebMCP integration (navigator.modelContext.registerTool()) in Chrome 146+ where DuckDB-WASM can expose tables and queries as MCP resources directly in the browser.


What's New in v1.5.0

DuckDB v1.5 Upgrade

  • Bumped duckdb and extension-ci-tools to v1.5-variegata
  • Updated APIs for v1.5 compatibility
  • Added v1.4/v1.5 compat for StorageExtension registration

Security Audit — All 15 Bugs Fixed

A full codebase security audit identified 15 true bugs and 6 controllable behaviors. All 15 bugs are now fixed:

SQL Injection (Critical/High)

  • BUG-01: Unquoted table name in DescribeTable — now quoted via KeywordHelper
  • BUG-02: DescribeQuery bypassed query allowlist/denylist — now enforced
  • BUG-03: Arbitrary file write via ExportToolHandler — path escaped, query validated
  • BUG-04: Unescaped filters in ListTablesToolHandler — now escaped
  • BUG-05: Unvalidated non-string params in SQLToolHandler — full-string numeric/boolean validation

Authentication (Critical)

  • BUG-06: ValidateAuthentication stub always passed — now fails closed for non-HTTP transports

Process Spawning (Critical/Medium)

  • BUG-07: execvp inherited full parent environment — replaced with execve + sanitized env, blocking LD_PRELOAD etc
  • BUG-08: Basename shortcut in command allowlist — removed, exact match only
  • BUG-11: Pipe FDs leaked to child — pipe2(O_CLOEXEC) on Linux, pipe()+fcntl on macOS, FD cleanup in child
  • BUG-12: Zombie processes from non-blocking waitpid — SIGTERM → wait → SIGKILL escalation

Security Config (High)

  • BUG-09: Permissive mode default allowed all commands — SetAllowedCommands now always locks
  • BUG-10: Arbitrary config file read via from_config_file — restricted to configured path via realpath

Output Sanitization (Medium)

  • BUG-13: Timing attack on HTTP auth token — constant-time comparison
  • BUG-14: Unescaped data in JSON output — EscapeJsonString() helper applied everywhere
  • BUG-15: Exception messages leaked to HTTP clients — generic error messages returned

Testing

  • 69-assertion offensive security regression test suite (mcp_security_regression.test)
  • All 14 existing test suites pass (567 assertions)

Remaining Work

6 controllable behaviors (CTRL-01 through CTRL-06) remain as future design decisions — see SECURITY_AUDIT.md for details.

v1.5.0 — DuckDB v1.5 + Security Audit Fixes

23 Feb 19:42
ee0806b

Choose a tag to compare

What's New

DuckDB v1.5 Upgrade

  • Bumped duckdb and extension-ci-tools to v1.5-variegata
  • Updated APIs for v1.5 compatibility
  • Added v1.4/v1.5 compat for StorageExtension registration

Security Audit — All 15 Bugs Fixed

A full codebase security audit identified 15 true bugs and 6 controllable behaviors. All 15 bugs are now fixed:

SQL Injection (Critical/High)

  • BUG-01: Unquoted table name in DescribeTable — now quoted via KeywordHelper
  • BUG-02: DescribeQuery bypassed query allowlist/denylist — now enforced
  • BUG-03: Arbitrary file write via ExportToolHandler — path escaped, query validated
  • BUG-04: Unescaped filters in ListTablesToolHandler — now escaped
  • BUG-05: Unvalidated non-string params in SQLToolHandler — full-string numeric/boolean validation

Authentication (Critical)

  • BUG-06: ValidateAuthentication stub always passed — now fails closed for non-HTTP transports

Process Spawning (Critical/Medium)

  • BUG-07: execvp inherited full parent environment — replaced with execve + sanitized env, blocking LD_PRELOAD etc
  • BUG-08: Basename shortcut in command allowlist — removed, exact match only
  • BUG-11: Pipe FDs leaked to child — pipe2(O_CLOEXEC) on Linux, pipe()+fcntl on macOS, FD cleanup in child
  • BUG-12: Zombie processes from non-blocking waitpid — SIGTERM → wait → SIGKILL escalation

Security Config (High)

  • BUG-09: Permissive mode default allowed all commands — SetAllowedCommands now always locks
  • BUG-10: Arbitrary config file read via from_config_file — restricted to configured path via realpath

Output Sanitization (Medium)

  • BUG-13: Timing attack on HTTP auth token — constant-time comparison
  • BUG-14: Unescaped data in JSON output — EscapeJsonString() helper applied everywhere
  • BUG-15: Exception messages leaked to HTTP clients — generic error messages returned

Testing

  • 69-assertion offensive security regression test suite (mcp_security_regression.test)
  • All 14 existing test suites pass (567 assertions)

Remaining Work

6 controllable behaviors (CTRL-01 through CTRL-06) remain as future design decisions — see SECURITY_AUDIT.md for details.

v1.4.4 - HTTP Foreground Mode Fix

07 Feb 22:13
dce4761

Choose a tag to compare

Changes

Bug Fixes

  • HTTP foreground mode: Fixed mcp_server_start ignoring {"background": false} for HTTP transport (#11, #12)
    • Previously, HTTP servers always ran in background mode regardless of the config setting
    • Now correctly blocks the calling thread when background: false is specified, matching stdio transport behavior

Details

When starting an HTTP server with {"background": false}, the mcp_server_start function now properly blocks until the server is stopped, consistent with stdio transport behavior.

-- Now correctly blocks until server is stopped
SELECT mcp_server_start('http', 'localhost', 8080, '{"background": false}');

Full changelog: v1.4.3...v1.4.4

v1.4.3 - SQL Parameter Quoting Fix

29 Jan 22:28

Choose a tag to compare

Changes

Bug Fixes

  • SQL parameter quoting: String parameters in custom tools are now properly quoted and escaped for SQL safety
  • Custom tools registration: Fixed custom tools not registering in foreground stdio mode
  • CI workflow: Updated for DuckDB v1.4.4

Details

Custom SQL tools defined with mcp_publish_tool() now correctly handle string parameters. Previously, string values were substituted literally without SQL quoting, causing syntax errors.

Example:

-- Tool template
SELECT file FROM glob($pattern)

-- Before: SELECT file FROM glob(/path/to/files)  -- Syntax error!
-- After:  SELECT file FROM glob('/path/to/files') -- Correct

Full changelog: v1.3.2...v1.4.3

v1.3.2

26 Jan 21:56

Choose a tag to compare

New Features

mcp_publish_resource Function

  • New SQL function for publishing static content as MCP resources
  • Parameters: (uri, content, mime_type, description)

Publish Before Server Starts (Queuing)

  • All publish functions can now be called before the server starts
  • Registrations are queued and automatically applied when the server starts

Improved Parameter Handling

  • SQL tool parameters now correctly handle all JSON types (integer, boolean, string)

Bug Fixes

  • Fixed SQL parameter substitution for non-string JSON values in custom tools

See full changelog: https://duckdb-mcp.readthedocs.io/changelog/

v1.3.1 - MCP Notifications Fix

17 Jan 00:17
77578ed

Choose a tag to compare

Bug Fixes

  • Fix MCP notifications handling (Issue #9, PR #10)
    • Server no longer returns "Method not found" error for notifications/initialized
    • Notifications don't receive responses per JSON-RPC 2.0 / MCP spec
    • Fixes compatibility with Codex and other MCP clients that send notifications

Thanks to @mebaran for the fix!

Full Changelog

v1.3.0...v1.3.1

v1.3.0

09 Dec 13:44

Choose a tag to compare

New Features

Memory Transport for Testing

  • Added mcp_server_start('memory') transport for in-process testing
  • New mcp_server_send_request() function for sending JSON-RPC requests directly to a running server
  • Enables comprehensive unit testing without external processes

Markdown Output Format

  • Query tool now supports format parameter with options: json (default), markdown, csv
  • Markdown format is more token-efficient for LLM contexts - column names appear once in headers rather than repeated per row
  • Server configuration option default_result_format to set default format

Server Configuration Options

  • New JSON config parameter for mcp_server_start():
    • enable_query_tool, enable_describe_tool, enable_list_tables_tool
    • enable_database_info_tool, enable_export_tool, enable_execute_tool
    • default_result_format: "json" | "markdown" | "csv"
  • Fine-grained control over which tools are exposed to MCP clients

mcp_publish_tool Function

  • New SQL function for publishing custom parameterized tools
  • 5-param version: (name, description, sql_template, properties_json, required_json)
  • 6-param version: adds optional format (json, csv, markdown)
  • Parameters in SQL template use $name syntax

Server Statistics

  • mcp_server_status() now reports requests_received, responses_sent, and errors_returned counters

Shared ResultFormatter Utility

  • Consolidated JSON/CSV/Markdown formatting code used by both tool handlers and resource providers

Bug Fixes

  • MCP protocol compliance for Claude Code compatibility (critical)
    • Initialize response now includes protocolVersion and serverInfo at top level
    • Capabilities changed from booleans to objects with listChanged/subscribe sub-fields per MCP spec
    • tools/list inputSchema is now a nested object instead of escaped string
    • tools/list properties follow JSON Schema compliance (object with property names as keys)
    • JSON-typed values are now parsed and inlined instead of escaped as strings
  • Format validation returns errors instead of silent fallback (Issue #8)
    • Unsupported formats (jsonl, table, box, parquet for inline) now return clear error messages
    • Previously would silently fall back to confusing tab-separated output
  • Fixed describe tool for query schema inspection
    • The describe tool's query argument was broken (used PREPARE + DESCRIBE stmt which DuckDB doesn't support)
    • Changed to use DESCRIBE () syntax
  • Examples work without icu extension
    • Replaced CURRENT_DATE with NOW()::TIMESTAMP::DATE in all examples

Examples & Documentation

  • Simplified examples (01-10) to use direct DuckDB invocation instead of wrapper scripts
  • Added specialized agent examples (07-devops, 08-web-api, 09-docs, 10-developer)
  • Added Claude Code agent definitions for IDE integration
  • Updated README with server tools documentation
  • Improved 05-custom-tools example with macro tables, mcp_publish_tool usage, and JSON-RPC examples

Testing

  • Added comprehensive memory transport tests (mcp_memory_transport.test)
  • Added server configuration tests (mcp_server_config.test)
  • Added resource publishing tests (mcp_resource_publishing.test)
  • Added MCP spec compliance tests for initialize and tools/list responses
  • Test coverage increased from ~223 to 324+ assertions

Internal Changes

  • Centralized version constant (DUCKDB_MCP_VERSION)
  • Standardized on JSON for MCP protocol internally
  • Simplified stdio transport by extracting common server logic
  • Refactored tool_handlers.cpp and resource_providers.cpp to use shared ResultFormatter

v1.2.1

08 Dec 21:10

Choose a tag to compare

New Features

Memory Transport for Testing

  • Added mcp_server_start('memory') transport for in-process testing
  • New mcp_server_send_request() function for sending JSON-RPC requests directly to a running server
  • Enables comprehensive unit testing without external processes

Markdown Output Format

  • Query tool now supports format parameter with options: json (default), markdown, csv
  • Markdown format is more token-efficient for LLM contexts - column names appear once in headers rather than repeated per row
  • Server configuration option default_result_format to set default format

Server Configuration Options

  • New JSON config parameter for mcp_server_start():
    • enable_query_tool, enable_describe_tool, enable_list_tables_tool
    • enable_database_info_tool, enable_export_tool, enable_execute_tool
    • default_result_format: "json" | "markdown" | "csv"
  • Fine-grained control over which tools are exposed to MCP clients

Request/Response Statistics

  • mcp_server_status() now reports requests_received and responses_sent counters

Bug Fixes

  • Fixed describe tool for query schema inspection: The describe tool's query argument was broken (used PREPARE + DESCRIBE stmt which DuckDB doesn't support). Changed to use DESCRIBE () syntax.

Examples & Documentation

  • Simplified examples (01-10) to use direct DuckDB invocation instead of wrapper scripts
  • Added specialized agent examples (07-devops, 08-web-api, 09-docs, 10-developer)
  • Added Claude Code agent definitions for IDE integration
  • Updated README with server tools documentation

Testing

  • Added comprehensive memory transport tests (mcp_memory_transport.test)
  • Added server configuration tests (mcp_server_config.test)
  • Test coverage increased from ~223 to 324 assertions (+45%)

Internal Changes

  • Centralized version constant (DUCKDB_MCP_VERSION)
  • Standardized on JSON for MCP protocol internally
  • Simplified stdio transport by extracting common server logic

Full Changelog: v1.2.0...v1.2.1

v1.2.0

30 Nov 20:44

Choose a tag to compare

What's Changed

Full Changelog: v1.1.0...v1.2.0