Skip to main content
Glama
suprkco

MCP SQL Analytics

by suprkco

MCP SQL Analytics

CI

A real MCP stdio server exposing bounded, read-only queries over synthetic retail data.

Problem

An assistant with SQL access should not receive unrestricted database privileges. This prototype exposes schema inspection and one-query analytics with database-enforced guardrails and explicit resource limits.

Related MCP server: DB Insights MCP Server

Demo

Run python -m analytics.demo after installing dependencies. Recorded output comes from 120 deterministic synthetic orders:

Region

Revenue (cents)

North

50,000

South

250,000

West

120,000

The same demo attempts DELETE FROM orders and reports blocked. This is synthetic currency-denominated test data, not business performance. Interview walkthrough.

Architecture

flowchart LR
    A[MCP client] --> B[stdio / MCPServer]
    B --> C[Schema inspection]
    B --> D[Parameter and query budgets]
    D --> E[SQLite authorizer]
    E --> F[Read-only database connection]
    F --> G[Row and response limits]
    G --> A

Tech stack

Python, the official MCP Python SDK v2, SQLite, pytest, and GitHub Actions. No LLM is required to run or test this tool server.

Quickstart

The standalone demo is one command with Docker:

docker compose up --build

For a real MCP session:

python -m venv .venv
# Activate .venv, then:
pip install -r requirements.txt -r requirements-dev.txt
python -m analytics.seed
python -m analytics.server

The last command waits for MCP JSON-RPC on stdin; it is not a conversational terminal. Configure your MCP client's stdio transport to launch the environment's Python with -m analytics.server, working directory set to this repository, and ANALYTICS_DB pointing to the generated database. If your client cannot set a working directory, use python -m analytics.server with PYTHONPATH set to this repository's absolute path.

Tools: inspect_schema() and query_readonly(sql, parameters). Example query:

SELECT region, SUM(revenue_cents) AS revenue_cents
FROM orders WHERE region = ? GROUP BY region

Use ["North"] as the parameter list. The server never accepts a database path from a tool call. .env.example documents process configuration; no automatic dotenv loading is performed.

Evaluation

Recorded locally on 2026-09-29, Python 3.10.4:

Check

Observed result

pytest suite

24 passed

Disallowed SQL cases

15/15 rejected, database hash unchanged

Real MCP stdio handshake, discovery, SELECT and rejected DROP

Passed

Output truncation

100 of 120 rows, explicit truncated=true

Expensive cross join

Interrupted by execution budget

Reproduce with pytest -q and ruff check .. These cases are a regression suite, not a security certification or proof against every SQLite resource-exhaustion strategy.

Design choices

  • Enforce below the prompt. mode=ro, query_only, disabled extension loading and a deny-by-default SQLite authorizer are independent of model behavior.

  • Allow only the intended data. orders and products are the only readable tables. Functions are explicitly allowlisted; schema access through user SQL, attachment, PRAGMAs and recursive CTEs are rejected.

  • Bound work and output. 8,000 SQL characters, 100 parameters, a default 250 ms progress-handler budget, 100 rows and a 100 KB serialized result cap. The timeout is cooperative, not a hard OS sandbox.

  • Keep MCP stdout clean. Audit records go to stderr and contain a query hash, status and timing; no SQL text, parameters or result values are logged.

Limitations and next steps

This is a local stdio prototype using synthetic data. It does not implement remote authentication, tenant isolation or row-level permissions. The allowlist is at table level: every column of those tables is readable. A local user who can replace the database or modify the process environment is trusted. Python 3.11+ adds SQLite value-size limits; Python 3.10 still enforces serialized output limits but not the same allocation limit.

Next: fuzz SQL policy, isolate workers for hard memory/time limits, test additional SQLite versions, and design a separate least-privilege PostgreSQL adapter. No employer or client database is used. Code was developed with AI assistance.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables read-only SQL database access for AI assistants, allowing schema exploration and safe query execution without risk of data modification.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to query SQL databases safely with read-only access, allowing schema discovery and SELECT queries while blocking writes and DDL operations.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to explore and query SQLite databases through read-only tools, with defense-in-depth sandboxing preventing any data modifications.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Lets AI clients ask natural-language questions about a SQL database with production-safe guardrails, schema grounding, and read-only enforcement.
    MIT