PlainQuery | MCP DB Agent

io.github.Jarvis-27Published by GitHub account Jarvis-27v1.0.1Updated Oct 24, 2026

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

The publisher's own server: Plain Insurance

VerifiedStreamable HTTPWeb executableDatabasesData & Analytics

Overview

AI-generated overview

Hosted MCP server that lets an assistant ask questions of a connected PostgreSQL database in plain English and get structured JSON results.

What you can do
  • Ask natural-language questions about a connected PostgreSQL database and receive structured JSON answers.
  • The server introspects and caches the schema, generates SQL with an LLM, validates it for safety, runs it read-only with a timeout, and retries automatically when a query errors.
  • Manage the account side through the REST API: register, verify email, connect or update the database, and create, list, rotate or delete API keys.
  • Generate ready-to-paste client configuration for VS Code, Cursor and generic HTTP MCP clients.
  • Check usage, dashboard and billing status, and start Stripe checkout or customer-portal sessions.
When to use it
Useful when you want an assistant to answer data questions against a PostgreSQL database without writing SQL yourself, especially for ad-hoc reporting such as counts, top customers or monthly averages. It fits teams that prefer a managed service over running their own query tooling.
Requirements
Remote endpoint at plainquery.in over streamable HTTP; no local install for the hosted option. Requires an account with verified email, a connected PostgreSQL database, and an API key sent in the X-API-Key header (OAuth 2.1 bearer tokens are also supported depending on server auth mode). Self-hosting needs Python 3.12+, uv, Node.js 20+ with pnpm, and an LLM key such as ANTHROPIC_API_KEY or GROQ_API_KEY.
Before you install
The hosted service stores your database connection URL and LLM keys on its servers, encrypted at rest, and sends schema and questions to an LLM provider. Generated SQL is validated and writes are blocked, but results still come from your real data, so review what the assistant can reach. The API key in X-API-Key grants access to your account and database; keep it secret and rotate it if exposed. Paid plans are billed through Stripe.

Installation

In SourceWeft

  1. Open PlainQuery | MCP DB Agent in the dashboard and add it to a workspace.
  2. Connect X-API-Key credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.Jarvis-27%2Fmcp-db-agent/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "plainquery-db-agent": {
      "type": "http",
      "url": "https://plainquery.in/mcp/",
      "headers": {
        "X-API-Key": "<YOUR_API_KEY>"
      }
    }
  }
}

README

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] [CI] [Python]

[PlainQuery demo — querying a database in plain English from an MCP client]


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

[PlainQuery architecture diagram showing clients, Next.js frontend, Starlette/FastAPI backend, FastMCP endpoint, query pipeline, LLM provider, and customer database]


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:

json
{  "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

bash
uv synccp .env.example .env

Edit .env with at least:

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

Run the backend:

bash
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

bash
cd frontendpnpm installpnpm 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

[PlainQuery security diagram showing URL validation, SSRF protection, encrypted credential storage, MCP authentication, per-request isolation, SQL validation, rate limits, and controlled execution]

  • 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

VariableDescription
AUTH_DATABASE_URLAuth/account database used by the hosted product
CREDENTIAL_ENCRYPTION_KEYSEncrypts stored database URLs and other secrets
REGISTRATION_OPENEnables or disables public signup
ANTHROPIC_API_KEY / GROQ_API_KEYLLM credentials for SQL generation
LLM_PROVIDERActive provider name
APP_BASE_URLBase URL used in setup payloads
FRONTEND_BASE_URLBase URL used in email links
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRETStripe API and webhook credentials
STRIPE_PRO_PRICE_IDStripe Price ID that maps to the Pro plan
STRIPE_CHECKOUT_SUCCESS_URL / STRIPE_CHECKOUT_CANCEL_URLOptional Checkout redirect overrides
STRIPE_CUSTOMER_PORTAL_RETURN_URLOptional 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.

bash
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

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

Deployment smoke test

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

bash
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:

bash
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

Source: README.md at commit 90db627

Tools

0
This server asks for a credential such as an API key, so SourceWeft could not read its tools without one and has not indexed them.

Version history

1
  1. v1.0.1LatestSep 16, 2026

Score

60% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declaredRequired10 pts
  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

Other Plain integrations