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 instructions in the README.
MCP endpoints
Open MCP endpoint (no auth)
https://db-mcp.tigzig.com/v1/mcp/http- Streamable HTTP (recommended; MCP spec 2025-03-26).https://db-mcp.tigzig.com/v1/mcp/sse- SSE (2024-11-05).https://db-mcp.tigzig.com/mcp- original SSE endpoint, kept for back-compat. No API key, no login on any open endpoint - safe because of the 23-layer stack below.
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. All secured endpoints require Auth0 login with an email whitelist - same databases and tools, with authentication on top.
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 and 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. This is safe because of a 23-layer defense stack covering:
- 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 and metadata-function blocking.
- Query timeouts with DuckDB engine interrupt.
- Database-level read-only enforcement (Postgres + DuckDB) and container resource limits.
- Error-message sanitization - no internal details leaked.
- Auth0 OAuth with JWT verification on the secured endpoint.
Full details in the README. For the broader web-app security checklist (112 items across all stacks), see tigzig.com/security.
Deploy your own (open source)
The source is open (Apache 2.0). Clone, configure your databases, and 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 databases. Auth0 OAuth is optional - set the AUTH0_* environment variables to enable the secured endpoint, or leave them unset for open-only.
Stack: FastAPI, asyncpg, DuckDB, fastapi-mcp, python-jose, SlowAPI.
API Endpoints (REST / HTTP)
https://db-mcp.tigzig.comPrepend this to every path listed below (e.g. /series becomes https://db-mcp.tigzig.com/series). The curl example on each card shows the full URL.Generated from the live OpenAPI spec - always in sync with the API. Try them interactively in Swagger.
/api/query/duckdb
Run read-only SQL on DuckDB - T20 Cricket ball-by-ball data
Execute a read-only SQL query against the DuckDB database. Contains ~1M rows of T20 (Twenty20) cricket ball-by-ball data from 2013 onwards. Table: ball_by_ball. Columns: match_id, season, start_date, venue, innings, ball, batting_team, bowling_team, striker, non_striker, bowler, runs_off_bat, extras, wides, noballs, byes, legbyes, penalty, wicket_type, player_dismissed, other_wicket_type, other_player_dismissed, match_type. Supports JSON (default) and TSV response formats. TSV uses shortened headers and is ~70% smaller (better for AI context windows).
curl -X POST "https://db-mcp.tigzig.com/api/query/duckdb"/api/query/postgres
Run read-only SQL on Postgres (Supabase) - ODI Cricket ball-by-ball data
Execute a read-only SQL query against the Supabase Postgres database. Contains ~1M rows of ODI (One Day International) cricket ball-by-ball data from 2013 onwards. Table: odi_cricket_ball_by_ball. Columns: match_id, season, start_date, venue, innings, ball, batting_team, bowling_team, striker, non_striker, bowler, runs_off_bat, extras, wides, noballs, byes, legbyes, penalty, wicket_type, player_dismissed, other_wicket_type, other_player_dismissed, match_type. Supports JSON (default) and TSV response formats. TSV uses shortened headers and is ~70% smaller (better for AI context windows).
curl -X POST "https://db-mcp.tigzig.com/api/query/postgres"