Releases: teaguesterling/duckdb_mcp
v1.5.2
What's Changed
Bug Fixes
- Fix optional tool parameters not substituted with NULL (#20, closes #19)
- Omitted optional parameters now substitute
NULLinto SQL templates instead of leaving$paramplaceholders unsubstituted - Explicit JSON
nullvalues now substitute SQLNULLinstead of the string literal'null'
- Omitted optional parameters now substitute
- Fix parameter substitution prefix collision
$idno longer incorrectly matches inside$id_extra— word-boundary enforcement on all$paramtokens
- Rewrite parameter substitution as single-pass tokenizer
- Eliminates cross-parameter contamination where user-provided values containing
$other_paramcould be altered during substitution - Substitution map built upfront, template scanned once — injected values never re-scanned
- Eliminates cross-parameter contamination where user-provided values containing
- Fix COMMAND option test for CI environments
- Test no longer depends on security singleton state
Documentation
- Document
mcp_publish_toolfunction 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
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 viaKeywordHelper - BUG-02:
DescribeQuerybypassed 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:
ValidateAuthenticationstub always passed — now fails closed for non-HTTP transports
Process Spawning (Critical/Medium)
- BUG-07:
execvpinherited full parent environment — replaced withexecve+ sanitized env, blockingLD_PRELOADetc - BUG-08: Basename shortcut in command allowlist — removed, exact match only
- BUG-11: Pipe FDs leaked to child —
pipe2(O_CLOEXEC)on Linux,pipe()+fcntlon 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 —
SetAllowedCommandsnow always locks - BUG-10: Arbitrary config file read via
from_config_file— restricted to configured path viarealpath
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
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 viaKeywordHelper - BUG-02:
DescribeQuerybypassed 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:
ValidateAuthenticationstub always passed — now fails closed for non-HTTP transports
Process Spawning (Critical/Medium)
- BUG-07:
execvpinherited full parent environment — replaced withexecve+ sanitized env, blockingLD_PRELOADetc - BUG-08: Basename shortcut in command allowlist — removed, exact match only
- BUG-11: Pipe FDs leaked to child —
pipe2(O_CLOEXEC)on Linux,pipe()+fcntlon 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 —
SetAllowedCommandsnow always locks - BUG-10: Arbitrary config file read via
from_config_file— restricted to configured path viarealpath
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
Changes
Bug Fixes
- HTTP foreground mode: Fixed
mcp_server_startignoring{"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: falseis 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
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') -- CorrectFull changelog: v1.3.2...v1.4.3
v1.3.2
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
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
- Server no longer returns "Method not found" error for
Thanks to @mebaran for the fix!
Full Changelog
v1.3.0
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
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
What's Changed
- Try to enable all architectures by @teaguesterling in #5
- Adding additional default tools for the MCP server
- Improve documentation
Full Changelog: v1.1.0...v1.2.0