Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.

README.md

PlainQuery

Ask your database questions in plain English. PlainQuery connects PostgreSQL databases to Claude, Cursor, or VS Code — and answers with real, structured data instead of guesses.

![MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.Jarvis-27/mcp-db-agent) ![CI](https://github.com/Jarvis-27/mcp-db-agent/actions/workflows/ci.yml) !Python

<p align="center"> <img src="docs/PlainQuery_GIF.gif" alt="PlainQuery demo — querying a database in plain English from an MCP client" width="800"> </p>

---

What it does

You connect a database once. Then, from any MCP client, you ask questions like:

_"How many orders did we ship in March?"_ _"Which 5 customers spent the most last year?"_ _"What's the average order value by month?"_

PlainQuery introspects your schema, generates SQL with an LLM, validates it for safety, runs it, and returns structured JSON. If a query fails, it reads the error and retries automatically.

Why PlainQuery

  • Natural language, real answers — no SQL required; results come from your actual data, not a hallucination.
  • Read-only and safe by design — every query is checked before it runs: writes (INSERT/UPDATE/DELETE/DDL) are blocked, dangerous functions and patterns are scanned out, and a LIMIT is injected automatically.
  • Self-correcting — when a generated query errors, the agent feeds the error back to the LLM and retries (up to a configurable limit).
  • Schema-aware — automatically introspects and caches your schema, so questions map to the right tables and columns.
  • Works with any MCP client — Claude Desktop, Cursor, VS Code Copilot, or anything that speaks MCP.
  • Secure multi-tenant hosting — database URLs and LLM keys are Fernet-encrypted at rest; user-supplied connection strings are SSRF-guarded; every request is tenant-scoped.
  • Hosted or self-hosted — use the managed service, or run the whole stack yourself with Docker.
  • Bring your own LLM — Anthropic Claude or Groq.

How it works

Your question
   → Schema introspection      (reads tables/columns, cached)
   → SQL generation            (schema + question → LLM → SQL)
   → Safety validation         (blocks writes, scans dangerous patterns, injects LIMIT)
   → Execution                 (runs read-only, with a timeout)
   → Self-correction retry     (on error: feed it back to the LLM, fix, re-run)
   → Structured JSON result

Architecture

<p align="center"> <img src="docs/diagram/plainquery-architecture.png" alt="PlainQuery architecture diagram showing clients, Next.js frontend, Starlette/FastAPI backend, FastMCP endpoint, query pipeline, LLM provider, and customer database" width="900"> </p>

---

Quick start

Option 1 — Use the hosted service (no install)

  1. Sign up at https://plainquery.in and verify your email.
  2. Connect your PostgreSQL database and create an API key.
  3. Add the server to your MCP client (see Connect your MCP client).

That's it — start asking questions.

Option 2 — Run it yourself

See Self-hosting & local development below.

Connect your MCP client

PlainQuery is published on the official MCP Registry as io.github.Jarvis-27/mcp-db-agent, so registry-aware clients can discover it directly.

To configure a client manually, point it at the MCP endpoint and pass your API key:

{
  "mcpServers": {
    "plainquery": {
      "url": "https://plainquery.in/mcp",
      "headers": { "X-API-Key": "mdbk_your_key_here" }
    }
  }
}

The backend can also generate ready-to-paste config for VS Code, Cursor, and generic HTTP clients — call POST /api/v1/account/setup-payloads (see Setup payloads). MCP clients can authenticate with an OAuth 2.1 bearer token or an API key, depending on MCP_AUTH_MODE.

---

Self-hosting & local development

Prerequisites

  • Python 3.12+
  • uv
  • Node.js 20+ and pnpm for the frontend
  • At least one LLM API key (ANTHROPIC_API_KEY or GROQ_API_KEY)

Backend

uv sync
cp .env.example .env

Edit .env with at least:

  • CREDENTIAL_ENCRYPTION_KEYS
  • REGISTRATION_OPEN=true
  • one LLM provider key plus LLM_PROVIDER

Run the backend:

uv run uvicorn src.app:app --reload --host 0.0.0.0 --port 8000

The backend mounts:

  • REST API at http://localhost:8000/api
  • MCP endpoint at http://localhost:8000/mcp

Frontend

cd frontend
pnpm install
pnpm dev

Open http://localhost:3000, sign up, complete setup, link your OAuth identity via account settings, then connect an MCP client at http://localhost:8000/mcp. The client will complete the OAuth flow automatically, or you can use an API key in api_key_only / hybrid mode.

Runtime model

  • Backend API: FastAPI/Starlette at src.app:app
  • Frontend: Next.js app in frontend/
  • Auth: passwordless email verification and login links
  • MCP auth: OAuth 2.1 bearer tokens (oauth_only), API keys (api_key_only), or both (hybrid) — set via MCP_AUTH_MODE
  • Setup payloads: POST /api/v1/account/setup-payloads
  • Billing: Stripe Checkout, Customer Portal, and webhook-confirmed Free/Pro entitlements

The product model is single-account and user-scoped: signup → verify email → connect database → link OAuth identity → use /mcp → upgrade with Stripe

Security

<p align="center"> <img src="docs/diagram/plainquery-security.png" alt="PlainQuery security diagram showing URL validation, SSRF protection, encrypted credential storage, MCP authentication, per-request isolation, SQL validation, rate limits, and controlled execution" width="900"> </p>

  • User-supplied database URLs are validated against SSRF, path traversal, private IPs, and DNS rebinding before any connection attempt.
  • Database URLs and LLM keys are Fernet-encrypted at rest, with support for key rotation.
  • Generated SQL is validated before execution: single-statement guard, forbidden-function scan, dangerous-pattern scan, write/DDL block, table-existence check, and automatic LIMIT injection.
  • Per-request context scoping prevents cross-tenant data leaks.
  • Per-user rate limits and fallback-LLM quotas limit cost abuse.

Important environment variables

| Variable | Description | |---|---| | AUTH_DATABASE_URL | Auth/account database used by the hosted product | | CREDENTIAL_ENCRYPTION_KEYS | Encrypts stored database URLs and other secrets | | REGISTRATION_OPEN | Enables or disables public signup | | ANTHROPIC_API_KEY / GROQ_API_KEY | LLM credentials for SQL generation | | LLM_PROVIDER | Active provider name | | APP_BASE_URL | Base URL used in setup payloads | | FRONTEND_BASE_URL | Base URL used in email links | | STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET | Stripe API and webhook credentials | | STRIPE_PRO_PRICE_ID | Stripe Price ID that maps to the Pro plan | | STRIPE_CHECKOUT_SUCCESS_URL / STRIPE_CHECKOUT_CANCEL_URL | Optional Checkout redirect overrides | | STRIPE_CUSTOMER_PORTAL_RETURN_URL | Optional Customer Portal return URL override |

See .env.example for the current full set.

API surface

Auth

  • POST /api/v1/auth/signup
  • GET /api/v1/auth/verify-email
  • POST /api/v1/auth/request-login-link
  • GET /api/v1/auth/exchange-login-link
  • POST /api/v1/auth/logout

Account (session-authenticated)

All account routes use session token auth (x-session-token: <session-token> or Authorization: Bearer <session-token>):

  • GET /api/v1/account
  • GET /api/v1/account/status
  • PUT /api/v1/account/database
  • GET /api/v1/account/api-keys
  • POST /api/v1/account/api-keys
  • DELETE /api/v1/account/api-keys/{id}
  • POST /api/v1/account/api-keys/{id}/rotate
  • POST /api/v1/account/setup-payloads
  • GET /api/v1/account/dashboard
  • GET /api/v1/account/usage/recent

Billing

  • GET /api/v1/account/billing
  • POST /api/v1/account/billing/checkout-session
  • POST /api/v1/account/billing/portal-session
  • POST /api/v1/billing/webhook

Stripe webhooks are the source of truth for plan transitions. Checkout or subscription activation moves a user to plan_code=pro; canceled, unpaid, or past-due states restrict paid entitlements without deleting database setup.

OAuth MCP account linking (session-authenticated)

  • GET /api/v1/account/mcp-oauth/status
  • POST /api/v1/account/mcp-oauth/start
  • GET /api/v1/account/mcp-oauth/callback
  • DELETE /api/v1/account/mcp-oauth/link

MCP

  • POST /mcp
  • Auth: OAuth 2.1 bearer token, API key, or both — controlled by MCP_AUTH_MODE

Setup payloads

POST /api/v1/account/setup-payloads returns client configuration material for VS Code, Cursor, generic HTTP MCP clients, and the current ChatGPT placeholder.

curl -X POST http://localhost:8000/api/v1/account/setup-payloads \
  -H "Authorization: Bearer <session-token>" \
  -H "Content-Type: application/json" \
  -d '{"raw_api_key":"mdbk_..."}'

The backend never stores raw API keys after creation. A raw key is only embedded in setup payloads when you explicitly send it in the request.

Tests

uv run pytest tests/ -m "not integration"
uv run pytest tests/ -m integration
uv run ruff check .
uv run mypy src --ignore-missing-imports

Deployment smoke test

After each hosted deploy, verify the public MCP OAuth discovery surface:

uv run python scripts/smoke_mcp_deployment.py \
  --mcp-url https://mcp.example.com/mcp \
  --issuer-url https://YOUR_DOMAIN.auth0.com/

The smoke test checks the unauthenticated /mcp challenge, protected resource metadata, ChatGPT/Claude well-known discovery routes, and issuer metadata. To also verify authenticated MCP initialize, tools/list, and resources/list, pass a linked user's access token with --access-token or MCP_SMOKE_ACCESS_TOKEN.

Docker

Run the hosted HTTP stack:

docker compose up --build

The container image serves only the hosted HTTP runtime. The MCP endpoint remains http://localhost:8000/mcp.

License

MIT © 2026 PlainQuery

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Databases servers.