# Database Query API - Read-only SQL over Postgres & DuckDB (MCP)

Open, no-auth MCP server exposing read-only SQL over Postgres (Supabase) and DuckDB (embedded) - ~2 million rows of cricket ball-by-ball data (2013-2025) - as agent tools, behind a 23-layer security stack. An Auth0-secured endpoint runs the same tools with login. Built for AI agents first, humans second: every page here has a Copy-as-Markdown button so you can hand it straight to your agent.

Kind: MCP Server (AI agents), SQL / Database API, Open + Auth0 secured
Base URL: https://db-mcp.tigzig.com
Docs: https://db-mcp.tigzig.com/docs  ·  OpenAPI: https://db-mcp.tigzig.com/openapi.json
Full page: https://www.tigzig.com/apis/database

## Overview

A security-hardened, read-only SQL query API exposing two databases as MCP tools for AI clients - an open endpoint for public use and an Auth0-secured endpoint for gated access. Connect from Claude Code, Claude Desktop, Claude.ai (web connectors), Claude in Excel, or any MCP client. Setup: https://github.com/amararun/shared-fastapi-database-mcp

AI agents: the open MCP endpoint needs no auth. Listed in the MCP directory at https://www.tigzig.com/.well-known/mcp/servers.json and the RFC 9727 API catalog at https://api.tigzig.com/.well-known/api-catalog .

## MCP endpoints

Open MCP endpoint (no auth):
- https://db-mcp.tigzig.com/v1/mcp/http - Streamable HTTP (recommended; MCP 2025-03-26).
- https://db-mcp.tigzig.com/v1/mcp/sse - SSE (2024-11-05).
- https://db-mcp.tigzig.com/mcp - original SSE endpoint (back-compat). No key, no login - safe because of the 23-layer stack.

Secured MCP endpoint (Auth0 OAuth):
- https://db-mcp.tigzig.com/v1/mcp-secure/http - Streamable HTTP, Auth0-gated.
- https://db-mcp.tigzig.com/v1/mcp-secure/sse - SSE, Auth0-gated.
- https://db-mcp.tigzig.com/mcp-secure - legacy SSE, Auth0-gated. Requires Auth0 login with an email whitelist.

## What's inside

Two databases, ~2 million rows of cricket ball-by-ball data (2013-2025):
- Postgres (Supabase) - ODI cricket, ~1M rows.
- DuckDB (embedded) - T20 cricket, ~1M rows.
- Both read-only at database + application level.
- JSON and TSV output (TSV uses ~70% fewer tokens).

## Security hardening

The open endpoint is intentionally public - anyone with the URL can query. Safe because of a 23-layer defense stack:
- Cloudflare WAF + application-level rate limiting.
- Per-IP and global concurrency caps.
- 12-layer SQL validation - prefix allowlist, keyword blocklist, resource-exhaustion blocking, self-join detection, response size limits, comment rejection.
- System-catalog + metadata-function blocking.
- Query timeouts with DuckDB engine interrupt.
- Database-level read-only enforcement (Postgres + DuckDB) + container resource limits.
- Error-message sanitization - no internal details leaked.
- Auth0 OAuth with JWT verification on the secured endpoint.

Full details: https://github.com/amararun/shared-fastapi-database-mcp#security-hardening . Broader web-app security checklist (112 items): https://www.tigzig.com/security

## Deploy your own (open source)

Source is open (Apache 2.0). Clone, configure your databases, deploy:

```
git clone https://github.com/amararun/shared-fastapi-database-mcp.git
pip install -r requirements.txt
cp .env.example .env  # add your DB connection strings
uvicorn app:app --host 0.0.0.0 --port 8000
```

Swap in your own Postgres or DuckDB. Auth0 OAuth optional - set AUTH0_* env vars to enable the secured endpoint, or leave unset for open-only.
Stack: FastAPI, asyncpg, DuckDB, fastapi-mcp, python-jose, SlowAPI.

Self-hosting a public database MCP server is your responsibility for security - read-only enforcement, SQL validation, rate limiting, abuse detection are mandatory. Full checklist: https://www.tigzig.com/security

## API Endpoints (REST / HTTP)

Base URL: `https://db-mcp.tigzig.com`

### POST /api/query/duckdb
Run read-only SQL on DuckDB - T20 Cricket ball-by-ball data
Example: curl -X POST "https://db-mcp.tigzig.com/api/query/duckdb"
### POST /api/query/postgres
Run read-only SQL on Postgres (Supabase) - ODI Cricket ball-by-ball data
Example: curl -X POST "https://db-mcp.tigzig.com/api/query/postgres"
