Skip to main content
Glama
jatindagar32-ui

DB Graph MCP Server

DB Graph MCP Server

An MCP (Model Context Protocol) server that connects to a SQL database and returns query results as chart images. Any MCP-compatible AI client (Claude Desktop, Claude.ai, Claude Code, etc.) can call it and display the chart directly in the conversation.

How it works

  • list_tables — lets the AI see what tables/columns exist in your database.

  • query_and_visualize — runs a SELECT query you (or the AI) provide, then renders the result as a bar / line / scatter / pie / histogram chart and returns it inline as a PNG image. Use this with GUI-based MCP clients (Claude Desktop, Claude.ai, Claude Code) that can display an image directly in the conversation.

  • query_and_visualize_to_file — same chart types and query logic, but saves the PNG to disk and returns the file path instead of sending the image inline. Use this with terminal-based MCP clients (e.g. Gemini CLI) that can't render images in the chat — the AI will tell you the path, and you open it separately.

Related MCP server: mcp-plots

1. Install dependencies

pip install -r requirements.txt

If you're connecting to Postgres or MySQL, also install the driver:

pip install psycopg2-binary   # Postgres
# or
pip install pymysql           # MySQL

2. Point it at your database

Copy .env.example to .env and fill in your real connection string:

cp .env.example .env

Then edit .env:

# SQLite (good for local testing)
DB_URL=sqlite:///./example.db

# Postgres
DB_URL=postgresql+psycopg2://user:password@host:5432/dbname

# MySQL
DB_URL=mysql+pymysql://user:password@host:3306/dbname

.env is git-ignored, so credentials won't get committed. The server loads it automatically on startup. You can also set DB_URL as a real OS environment variable, or via the env block in your MCP client config (e.g. Claude Desktop) — any of these work, and an OS/config-level value takes priority over .env.

If DB_URL isn't set anywhere, it defaults to a local SQLite file example.db.

3. Test it locally

Run the automated test suite (spins up a temporary SQLite DB, doesn't touch your real DB_URL):

pytest test_server.py -v

This covers the happy path plus edge cases: blocked destructive/chained queries, invalid chart types, empty results, mismatched columns, non-numeric columns for pie/scatter, and row-limit truncation.

You can also use the MCP inspector to interactively test tool calls (requires Node.js/npx):

mcp dev server.py

4. Connect it to an AI tool

Your server can run two ways, and which one you need depends on the client:

  • stdio mode (default) — the client launches server.py directly as a local process. Used by Claude Desktop, Gemini CLI, and most desktop MCP clients.

  • HTTP mode — the server runs as a standalone web service that remote clients connect to over a URL. Required for ChatGPT and Gemini Enterprise, which only support remote MCP servers, not local ones.

Claude Desktop (stdio)

Edit your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add an entry like this:

{
  "mcpServers": {
    "db-graph-server": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "DB_URL": "postgresql+psycopg2://user:password@host:5432/dbname"
      }
    }
  }
}

Restart Claude Desktop. You should see db-graph-server listed under available tools (hammer icon).

Gemini CLI (stdio)

Gemini CLI uses a similar config format. Add this to your Gemini CLI settings (typically ~/.gemini/settings.json or via mcp_config.json — check the Gemini CLI docs for your version):

{
  "mcpServers": {
    "db-graph-server": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"],
      "env": {
        "DB_URL": "postgresql+psycopg2://user:password@host:5432/dbname"
      }
    }
  }
}

ChatGPT / Claude.ai custom connectors / any remote-only client (HTTP)

These clients connect to your server over a URL from their own cloud infrastructure (not from your machine), so it must be:

  1. Running in HTTP mode

  2. Reachable on the public internet (once actually deployed/hosted)

  3. Protected with an API key — required, since anything reachable from the internet needs it

  4. Set an API key and run the server in HTTP mode:

    MCP_TRANSPORT=http MCP_API_KEY=your-long-random-key PORT=8000 python server.py

    Or set MCP_API_KEY in your .env file (see .env.example).

  5. For local testing only, tunnel it:

    ngrok http 8000

    For real use, deploy the server somewhere with a persistent public URL (a cloud VM, Render, Railway, Fly.io, etc.) — this part is typically handled by whoever manages your team's infrastructure.

  6. Connect the client:

    • Claude.ai: Customize → Connectors → "+" → Add custom connector → paste your server's URL → under Advanced settings, add your API key as a Bearer token / custom header if the UI supports it, or use the OAuth fields if you've set up OAuth instead.

    • ChatGPT: Settings → Apps & Connectors → Advanced → enable Developer Mode (requires ChatGPT Plus/Pro/Business/Enterprise/Edu), then add your server's URL as a new connector, including the API key.

Every request to the server must include the key as either:

X-API-Key: your-long-random-key

or

Authorization: Bearer your-long-random-key

Requests without a matching key get a 401 Unauthorized response.

⚠️ If MCP_API_KEY is not set, the server logs a warning and runs without authentication — fine for local testing, but do not deploy it that way to a real, internet-reachable environment.

Other MCP clients

Any client that supports the standard MCP stdio transport can launch this the same way as Claude Desktop — point it at python /absolute/path/to/server.py with the DB_URL environment variable set. Any client that only supports remote servers can connect the same way as ChatGPT, using HTTP mode.

5. Example usage

Once connected, you can ask the AI something like:

"What tables are in the database?" "Show me total sales by month as a bar chart."

The AI will call list_tables to explore the schema, then call query_and_visualize with a generated SQL query and chart type, and the resulting chart image will appear inline.

Safety and validation

  • Only a single read-only SELECT statement is allowed. The server rejects: non-SELECT statements, chained statements (e.g. SELECT ...; DROP TABLE ...), and queries containing write/DDL keywords (INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, ATTACH, PRAGMA) anywhere in the text. For production use, also connect with a dedicated read-only DB user as a second layer of defense.

  • Query results are capped at 100 rows (MAX_ROWS in server.py). The cap is enforced with a SQL-level LIMIT wrapped around your query, not just applied after fetching — so a query against a huge table won't pull everything into memory first. The chart title notes when results were truncated.

  • x_column/y_column are validated against the actual query result columns before charting, with a clear error if they don't match.

  • scatter and pie charts require a numeric y_column; a clear error is raised otherwise.

  • Database connection and query failures are caught and re-raised as clear RuntimeError/ValueError messages instead of leaking raw stack traces.

Notes / next steps

  • Authentication for HTTP mode: implemented via MCP_API_KEY. Set a long random value before deploying anywhere reachable from the internet. This is a simple shared-secret check — for stricter needs (per-user access, revocable tokens), consider upgrading to real OAuth, which Claude.ai's custom connectors support natively.

  • Supports bar, line, scatter, pie, and histogram charts. Easy to extend _render_chart in server.py with more chart types (e.g. heatmap) if needed.

  • Two tools, one for inline display (query_and_visualize) and one for file output (query_and_visualize_to_file) — the AI picks whichever fits the client it's running in, or you can ask for a specific one by name.

  • For NoSQL databases (MongoDB, etc.), the SQLAlchemy layer won't work as-is — you'd swap the engine/list_tables/query_and_visualize internals for a driver like pymongo, but the MCP tool interface stays the same.

Before submitting

  • Run pytest test_server.py -v and confirm all tests pass.

  • Remove local scratch artifacts (test_chart.png, example.db) if they're not meant to ship — test_server.py itself is fine to keep, it's now a proper automated test suite, not a throwaway script.

  • Double check DB_URL (in .env or your Claude Desktop config) points to the real database, not the local test SQLite file.

  • Make sure .env is not committed to git if you're using version control — .gitignore already excludes it.

  • Read through this README top to bottom as if you're a teammate seeing it for the first time.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jatindagar32-ui/mcp-graph-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server