Metadata-Version: 2.4
Name: duckquery-mcp
Version: 0.3.1
Summary: MCP server for a locally-running DuckQuery backend
Project-URL: Homepage, https://github.com/Chenkeliang/duckdb-query
Project-URL: Repository, https://github.com/Chenkeliang/duckdb-query
Project-URL: Issues, https://github.com/Chenkeliang/duckdb-query/issues
Author: Chen
License: MIT
Keywords: data-analysis,duckdb,duckquery,mcp,sql
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp<2.0,>=1.2.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# duckquery-mcp

An MCP server that exposes a locally-running DuckQuery backend to MCP clients
(Claude Code, Cursor, Codex). Start DuckQuery first (desktop app, Docker, or
`uvicorn main:app --port 48001`); this server auto-discovers it.

## Run

```bash
uvx duckquery-mcp            # zero-install
# or: pipx run duckquery-mcp
```

Env:
- `DUCKQUERY_API_BASE` — explicit backend URL (e.g. `http://127.0.0.1:48001`). Optional; auto-discovered otherwise (runtime.json, then probes 48001/8000/8001).
- `DUCKQUERY_MCP_MODE` — `read-only` | `normal` (default) | `full`.

## Add to a CLI

Claude Code:
```bash
claude mcp add duckquery -- uvx duckquery-mcp
```

Cursor / Codex (`mcp.json`):
```json
{
  "mcpServers": {
    "duckquery": {
      "command": "uvx",
      "args": ["duckquery-mcp"],
      "env": { "DUCKQUERY_MCP_MODE": "normal" }
    }
  }
}
```

Claude Desktop — add the same `mcpServers` block to `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`,
Windows: `%APPDATA%\Claude\claude_desktop_config.json`):
```json
{
  "mcpServers": {
    "duckquery": {
      "command": "uvx",
      "args": ["duckquery-mcp"]
    }
  }
}
```

## Tools

High-level tools (query, the AI agent tools below, discover, add sources,
configure LLM, transform, export) plus a generic `duckquery_request` passthrough.
Safety mode gates which tools are exposed:

The AI tools all call the backend's unified Agent Engine (`POST /api/ai/agent/run`,
one thin tool per `mode`), replacing the removed single-purpose LLM services:
- `ask_agent` (`mode=data_qa`) — conversational data agent. Runs **bounded,
  read-only** probe queries — inspecting schemas, verifying real column values,
  and dry-running row-capped SELECTs — over local tables and, when you pass
  `attach_databases`, attached MySQL/PostgreSQL/SQLite/DuckDB tables, before
  answering. Any returned `sql` is a draft; the agent never executes writes.
- `generate_sql` (`mode=generate_sql`) — NL → an `EXPLAIN`-validated SQL draft (not executed).
- `repair_sql` (`mode=repair_sql`) — error doctor: failing SQL + error → a fix.
- `explain_sql` (`mode=explain_sql`) — plain-language explanation of a statement.
- `suggest_chart` (`mode=suggest_chart`) — a chart spec for a result set.

All five are `read`-tier tools — exposed in every safety mode — and never execute writes.
- `read-only` — hides all mutating tools; non-GET `duckquery_request` calls are
  hard-blocked (`confirm` cannot override).
- `normal` (default) — mutating tools are exposed, but changing tables,
  saving connections, importing data, running mutating SQL, and non-GET
  `duckquery_request` calls each require `confirm=true`.
- `full` — bypasses the MCP confirmation gates above; backend safeguards still
  apply.

The AI-settings tools (`configure_llm`, `test_llm_provider`) are write-tier:
hidden in `read-only`, and in `normal` mode they take the same `confirm=true`
parameter as every other write tool.
