query-executor
Allows AI agents to execute SQL queries, inspect schemas, and analyze query performance on one or more PostgreSQL databases registered as named projects.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@query-executordescribe the schema for the default project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Query Executor MCP Server
A Model Context Protocol server that gives AI agents read (and optionally write) access to one or more PostgreSQL databases. Each database is registered as a named project — the agent picks the right one per call via project_id.
How it works
flowchart TD
A[AI Agent\nClaude / Cursor / etc.] -->|MCP stdio| B[Query Executor\nMCP Server]
B --> C{Resolve project_id}
C -->|default| D[(default DB)]
C -->|project-alpha| E[(project-alpha DB)]
C -->|project-beta| F[(project-beta DB)]
subgraph Tools
T1[describe_postgres_schema]
T2[execute_postgres]
T3[explain_postgres]
T4[pg_stat_statements]
end
B --> Tools
Tools --> CsequenceDiagram
participant Agent
participant Server as MCP Server
participant Config as databases.json
participant DB as PostgreSQL
Agent->>Server: tool call (project_id, sql)
Server->>Config: resolve project_id → DSN + mode
Config-->>Server: { dsn, mode }
alt mode = readonly
Server->>Server: assert first token is SELECT/WITH
end
Server->>DB: execute query
DB-->>Server: rows
Server-->>Agent: JSON { rows, row_count }Related MCP server: mcp-postgres
Features
Multi-project — connect to any number of PostgreSQL databases simultaneously; each call targets one via
project_idPer-project mode —
readonlyblocks all writes at the first SQL token;readwriteallows all SQLSafe fallback — omitting
project_idroutes to the configured default projectFour tools — schema inspection, query execution, EXPLAIN ANALYZE, and slow-query analysis
stdio transport — works with any MCP client (Claude Desktop, Cursor, Claude Code, etc.)
Docker-ready — single image, credentials baked in at build time from gitignored files
Project layout
query-executor/
├── Dockerfile
├── Makefile
├── pyproject.toml
├── uv.lock
├── main.py # connection check entrypoint
├── .env # gitignored — copy from .env.example
├── databases.json # gitignored — copy from databases.example.json
├── .env.example
├── databases.example.json
└── query_executor/
├── config.py # loads .env + databases.json; single source of truth
├── query_connector.py # raw asyncpg functions (no MCP imports)
├── tools.py # Pydantic input models + tool implementations
└── server.py # FastMCP bootstrap + entrypointQuick start
1. Install dependencies
uv sync2. Configure
cp .env.example .env
cp databases.example.json databases.jsonEdit databases.json with your real connection strings:
{
"default": {
"dsn": "postgresql://user:password@localhost:5432/mydb",
"mode": "readonly"
},
"staging": {
"dsn": "postgresql://user:password@staging-host:5432/stagingdb",
"mode": "readwrite"
}
}
| Behaviour |
| Only |
| All SQL is permitted. Use only on non-production databases. |
If a project does not specify mode, it defaults to readonly.
3. Check connections
make checkWelcome to Query Executor!
Default project : default
• default [readonly] (default)
• staging [readwrite]
Testing database connections...
[default] mode=readonly ... OK — PostgreSQL 15.4
[staging] mode=readwrite ... OK — PostgreSQL 15.4
All 2 connection(s) OK.4. Build the Docker image
make buildMCP client configuration
The server runs over stdio — the MCP client spawns the process and communicates via stdin/stdout.
Claude Desktop
Config file: ~/Library/Application Support/Claude/claude_desktop_config.json
With UV (local):
{
"mcpServers": {
"query-executor": {
"command": "uv",
"args": ["run", "python", "-m", "query_executor.server"],
"cwd": "/Users/niteshnandan/workspace/2026/query-executor"
}
}
}With Docker:
{
"mcpServers": {
"query-executor": {
"command": "docker",
"args": ["run", "-i", "--rm", "query-executor"]
}
}
}Cursor
Global config: ~/.cursor/mcp.json
Project config: .cursor/mcp.json
With UV (local):
{
"mcpServers": {
"query-executor": {
"command": "uv",
"args": ["run", "python", "-m", "query_executor.server"],
"cwd": "/Users/niteshnandan/workspace/2026/query-executor"
}
}
}With Docker:
{
"mcpServers": {
"query-executor": {
"command": "docker",
"args": ["run", "-i", "--rm", "query-executor"]
}
}
}Claude Code
Add to your project's .claude/mcp.json:
With UV (local):
{
"mcpServers": {
"query-executor": {
"type": "stdio",
"command": "uv",
"args": ["run", "python", "-m", "query_executor.server"],
"cwd": "/Users/niteshnandan/workspace/2026/query-executor"
}
}
}With Docker:
{
"mcpServers": {
"query-executor": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "query-executor"]
}
}
}Note: Replace
/Users/niteshnandan/workspace/2026/query-executorwith the actual path on your machine if sharing config with others.
Tools reference
describe_postgres_schema
Inspect tables, columns, foreign keys, and indexes for a given schema.
Call this first before writing any query — it gives you exact column names and types so you write correct SQL on the first attempt.
Parameter | Type | Default | Description |
| string |
| Schema to inspect |
| string | default project | Target database |
Returns { columns, foreign_keys, indexes }.
execute_postgres
Run a SQL query and get rows back as JSON.
Parameter | Type | Required | Description |
| string | yes | SQL to execute. In |
| string | no | Target database |
Returns { rows: [...], row_count: N }.
explain_postgres
Run EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) on a query and return the execution plan.
Parameter | Type | Required | Description |
| string | yes | SELECT query to analyse (do not include |
| string | no | Target database |
Returns { plan: [...] }. Key things to check in the plan:
Seq Scan on a large table → missing index on the
WHEREcolumnActual rows ≫ Plan rows → stale statistics; run
ANALYZE <table>High shared_blks_read → I/O-bound; working set does not fit in
shared_buffers
pg_stat_statements
Return the top N query patterns ranked by total cumulative execution time.
Parameter | Type | Default | Description |
| integer | 20 | Number of queries to return (max 100) |
| string | no | Target database |
Returns rows with total_exec_sec, mean_exec_sec, max_exec_sec, calls, shared_blks_hit, shared_blks_read.
Requires the pg_stat_statements extension. Enabled by default on AWS RDS, GCP Cloud SQL, and Supabase. On self-hosted Postgres: CREATE EXTENSION pg_stat_statements;
Recommended workflows
Explore an unknown database
describe_postgres_schema → execute_postgresDebug a slow query
describe_postgres_schema (check what indexes exist)
→ explain_postgres (verify the planner uses them)
→ execute_postgres (run once plan looks correct)Performance audit
pg_stat_statements (find the most expensive patterns)
→ explain_postgres (drill into the worst offender)
→ describe_postgres_schema (check if a missing index would help)Environment variables
Variable | Default | Description |
|
| Path to the databases registry file |
|
| Fallback project when |
|
| Python logging level |
|
| asyncpg connection timeout in seconds |
|
| Statement timeout for EXPLAIN ANALYZE in milliseconds |
|
| Default row limit for |
Available Tools
5 toolsdescribe_postgres_schemaA
Inspect a PostgreSQL schema and return its full structure as JSON.
Call this before writing any query, JOIN, or EXPLAIN — it gives you exact table/column names and indexes so you don't guess.
Returns a JSON object:
"columns": table_name, column_name, data_type, is_nullable, column_default
"foreign_keys": which columns reference which tables (use for JOINs)
"indexes": full CREATE INDEX definitions (check before running EXPLAIN)
Large schemas (100+ tables) return a lot of JSON — filter by table_name client-side rather than calling this multiple times.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It describes the return structure and warns about large schemas, but does not explicitly state read-only nature, required permissions, or error handling. The word 'Inspect' implies read-only, but more explicit disclosure would improve transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (about 100 words) and front-loaded with purpose. It uses bullet-style formatting for the return structure. There is no unnecessary verbosity, but it could be slightly tighter by condensing the usage advice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and the presence of an output schema, the description covers key aspects: purpose, when to use, return format, and large schema handling. Minor gaps include not specifying behavior for nonexistent schemas or error conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is high (both parameters have descriptions in the schema), so baseline is 3. The tool description does not mention parameters or provide additional semantics beyond what the schema already offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Inspect a PostgreSQL schema and return its full structure as JSON'. It differentiates from sibling tools like execute_postgres (execution), explain_postgres (query plan), list_projects (project listing), and pg_stat_statements (statistics), all of which have distinct purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises 'Call this before writing any query, JOIN, or EXPLAIN — it gives you exact table/column names and indexes so you don't guess'. It also recommends filtering client-side for large schemas, though it doesn't explicitly state when not to use or list alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_postgresA
Execute a SQL query against a PostgreSQL database and return rows as JSON.
Returns: {"rows": [...], "row_count": N}
Mode behaviour (per project in databases.json):
readonly — only SELECT/WITH accepted; writes are blocked before reaching the DB.
readwrite — all SQL allowed; use only on non-production projects.
Call describe_postgres_schema first to confirm table/column names. If row_count equals your LIMIT, there are likely more rows.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses key behaviors: mode enforcement (readonly blocks writes), return format with row_count, type casting for non-serialisable types, and the indicator that row_count equal to LIMIT suggests more rows. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise and well-structured: purpose, return format, mode behavior, prerequisite call, and a caution about LIMIT. Every sentence adds value and the most critical info is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers prerequisites, mode details, common pitfalls (LIMIT), and return format. With an output schema present (context signal), description does not need to explain return values further. No gaps identified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema already provides parameter descriptions (sql and project_id). The description adds context about mode behavior affecting the sql parameter and suggests LIMIT usage, but does not elaborate on parameter syntax or format beyond the schema. Given low schema description coverage (0%), it compensates partially but not fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool executes SQL queries on a PostgreSQL database and returns rows as JSON. Distinguishes from siblings like 'describe_postgres_schema' and 'explain_postgres' by focusing on execution rather than schema inspection or query planning.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes explicit guidance: call 'describe_postgres_schema' first, explains mode behavior (readonly vs readwrite) with conditions, and advises adding LIMIT for unfamiliar tables. Effectively helps agents decide when and how to use this tool vs alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_postgresA
Run EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) on a query and return the plan.
The query executes to collect real timing; results are discarded — only the plan is returned. A statement timeout prevents runaway queries.
Returns: {"plan": []}
Use before running a slow or unfamiliar query on a large table. Check describe_postgres_schema first to see what indexes exist. Write queries are blocked.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that the query executes to collect real timing, results are discarded, a statement timeout prevents runaway, and write queries are blocked. With no annotations, the description fully covers behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with the main action, followed by execution details, return format, and usage guidance. Every sentence adds value with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool does, how it works (including execution and timeout), return format, when to use, and what is blocked. With an output schema present (not shown but referenced), the return information is sufficient. All necessary context for an agent to use the tool correctly is provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides detailed parameter descriptions. The tool description adds context like the automatic prepending of EXPLAIN and the 'write queries blocked' constraint, but does not repeat parameter definitions. Given schema coverage appears to be limited (per context signals), the description could have added more direct parameter guidance, but it is adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it runs EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) on a query and returns the plan. Distinguishes from sibling tools like execute_postgres (which runs queries) and describe_postgres_schema (which describes schema).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises using this tool before slow/unfamiliar queries on large tables, and to check describe_postgres_schema first for indexes. Also states write queries are blocked, guiding the agent away from using it for writes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectsA
List all configured database projects and their access modes.
Call this first when you don't know which project_id to use. Returns every project registered in databases.json, including which one is the default (used when project_id is omitted).
Returns a JSON object: { "default_project": "", "projects": [ {"project_id": "", "mode": "readonly|readwrite", "is_default": true|false}, ... ] }
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It discloses the return type (JSON object) and data source (databases.json), listing fields like 'default_project' and 'projects'. It does not mention authorization or side effects, but for a read-only listing tool, this level of transparency is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with three short segments: purpose, usage advice, and return format. It front-loads the key action and resource, and every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and an output schema described inline, the description is complete. It fully explains the tool's behavior, when to call it, and the structure of results, leaving no ambiguity for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, and schema description coverage is 100% (empty schema). The description adds context about the returned structure, which enhances understanding beyond the schema, earning a baseline score of 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists all configured database projects and their access modes, using specific verb 'list' and resource 'database projects'. It distinguishes itself from sibling tools like 'execute_postgres' or 'describe_postgres_schema' which target different operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises 'Call this first when you don't know which project_id to use', providing a clear usage scenario. However, it does not mention when not to use it or suggest alternatives, but given the context, this guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pg_stat_statementsA
Return the top N most expensive queries from pg_stat_statements.
Best starting point for a performance audit — shows which query patterns cost the most cumulative time across the application.
Returns: {"rows": [{query, calls, total_exec_sec, mean_exec_sec, max_exec_sec, total_rows, shared_blks_hit, shared_blks_read}], "row_count": N}
Query text uses $1/$2 placeholders (pg_stat_statements normalises literals). Requires the pg_stat_statements extension (enabled by default on RDS, Cloud SQL, Supabase; otherwise: CREATE EXTENSION pg_stat_statements).
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It explains that query text uses $1/$2 placeholders (normalization), notes the extension requirement with deployment-specific details, and outlines the return format. It is transparent about the read-only nature and typical usage, but does not explicitly declare non-destructiveness.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (about 4 sentences), front-loaded with the purpose, and well-structured with a clear breakdown of return format, normalization behavior, and extension requirements. A minor quibble is the inline return schema which adds some verbosity, but overall it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of a database performance tool and the presence of an output schema (not shown but referenced), the description covers purpose, return format, normalization, and extension prerequisites. It lacks parameter explanation but the input schema covers that. Overall it is complete enough for an agent to understand the tool's role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not explain the parameters (limit and project_id) at all. Given the schema description coverage is 0%, the description should compensate, but it fails to add any meaning beyond the schema's own parameter descriptions. The agent must infer the limit from 'top N' and is left uninformed about project_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Return the top N most expensive queries from pg_stat_statements,' specifying a specific verb and resource. It further positions this as the 'best starting point for a performance audit,' which distinguishes it from sibling tools like execute_postgres or explain_postgres.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for use ('Best starting point for a performance audit') and implies it is for identifying costly query patterns. It does not explicitly state when not to use it or name alternatives, but the context and sibling tool names make the intended usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose: schema inspection, query execution, explain planning, project listing, and performance analysis. No overlap exists.
Tools follow a mostly consistent verb_noun pattern (describe_, execute_, explain_, list_), except pg_stat_statements which is a fixed PostgreSQL function name. Overall, naming is clear and predictable.
Five tools is ideal for a query executor, covering key operations without unnecessary overhead. Each tool serves a specific need.
The tool set covers essential operations: schema inspection, query execution with read-only/write modes, explain analysis, project management, and performance monitoring. No obvious gaps for the domain.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
PostgreSQL, MySQL, OpenAPI/Swagger, and shared Agent Memory with scoped access.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely explore, analyze, and maintain PostgreSQL databases with read-only mode by default, SQL injection prevention, query performance analysis, and optional write operations.63Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with PostgreSQL databases through schema intelligence, query execution, and DBA tooling including index analysis and health monitoring. Features configurable access levels and audit logging for secure database operations.751MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with PostgreSQL databases through natural language queries, schema inspection, and safe SQL execution.101
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to safely interact with PostgreSQL databases, perform queries, inspect schemas, and analyze query performance.2
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Nitesh-Nandan/query-executor'
If you have feedback or need assistance with the MCP directory API, please join our Discord server