Server data from the Official MCP Registry
provides AI-powered PostgreSQL performance tuning capabilities.
provides AI-powered PostgreSQL performance tuning capabilities.
Valid MCP server (2 strong, 1 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry. Trust signals: trusted author (3/3 approved).
4 files analyzed · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-isdaniel-pgtuner-mcp": {
"args": [
"pgtuner-mcp"
],
"command": "uvx"
}
}
}From the project's GitHub README.
A Model Context Protocol (MCP) server that provides AI-powered PostgreSQL performance tuning capabilities. This server helps identify slow queries, recommend optimal indexes, analyze execution plans, and leverage HypoPG for hypothetical index testing.
pg_stat_statements with detailed statisticsEXPLAIN and EXPLAIN ANALYZEpip install pgtuner_mcp
Or using uv:
uv pip install pgtuner_mcp
git clone https://github.com/isdaniel/pgtuner_mcp.git
cd pgtuner_mcp
pip install -e .
| Variable | Description | Required |
|---|---|---|
DATABASE_URI | PostgreSQL connection string | Yes |
PGTUNER_EXCLUDE_USERIDS | Comma-separated list of user IDs (OIDs) to exclude from monitoring | No |
Connection String Format: postgresql://user:password@host:port/database
To run this MCP server, the PostgreSQL user requires specific permissions to query system catalogs and extensions. Below are the minimal permissions needed for different feature sets.
-- Create a dedicated monitoring user
CREATE USER pgtuner_monitor WITH PASSWORD 'secure_password';
-- Grant connection to the target database
GRANT CONNECT ON DATABASE your_database TO pgtuner_monitor;
-- Grant usage on schemas
GRANT USAGE ON SCHEMA public TO pgtuner_monitor;
GRANT USAGE ON SCHEMA pg_catalog TO pgtuner_monitor;
-- Grant SELECT on user tables and indexes (for table stats and analysis)
GRANT SELECT ON ALL TABLES IN SCHEMA public TO pgtuner_monitor;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO pgtuner_monitor;
-- Grant access to system catalog views (read-only)
GRANT pg_read_all_stats TO pgtuner_monitor; -- PostgreSQL 10+
For pgstattuple (Bloat Detection):
-- Create the extension (requires superuser or appropriate privileges)
CREATE EXTENSION IF NOT EXISTS pgstattuple;
-- Grant execution on pgstattuple functions
GRANT EXECUTE ON FUNCTION pgstattuple(regclass) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION pgstattuple_approx(regclass) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION pgstatindex(regclass) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION pgstatginindex(regclass) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION pgstathashindex(regclass) TO pgtuner_monitor;
-- Alternative: Use pg_stat_scan_tables role (PostgreSQL 14+)
GRANT pg_stat_scan_tables TO pgtuner_monitor;
For HypoPG (Hypothetical Index Testing):
-- Create the extension (requires superuser or appropriate privileges)
CREATE EXTENSION IF NOT EXISTS hypopg;
-- Grant SELECT on HypoPG views
GRANT SELECT ON hypopg_list_indexes TO pgtuner_monitor;
GRANT SELECT ON hypopg_hidden_indexes TO pgtuner_monitor;
-- Grant execution on HypoPG functions with proper signatures
GRANT EXECUTE ON FUNCTION hypopg_create_index(text) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_drop_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_reset() TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_hide_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_unhide_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_relation_size(oid) TO pgtuner_monitor;
-- Note: HypoPG operations are session-scoped and don't affect the actual database
-- 1. Create the monitoring user
CREATE USER pgtuner_monitor WITH PASSWORD 'secure_password';
-- 2. Grant connection and schema access
GRANT CONNECT ON DATABASE your_database TO pgtuner_monitor;
GRANT USAGE ON SCHEMA public TO pgtuner_monitor;
-- 3. Grant read access to user tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO pgtuner_monitor;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO pgtuner_monitor;
-- 4. Grant system statistics access
GRANT pg_read_all_stats TO pgtuner_monitor; -- PostgreSQL 10+
-- Grant access to pg_stat_statements views explicitly
GRANT SELECT ON pg_stat_statements TO pgtuner_monitor;
GRANT SELECT ON pg_stat_statements_info TO pgtuner_monitor;
-- 5. Install and grant access to extensions (as superuser)
-- pg_stat_statements (required)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- pgstattuple (for bloat detection)
CREATE EXTENSION IF NOT EXISTS pgstattuple;
GRANT pg_stat_scan_tables TO pgtuner_monitor; -- PostgreSQL 14+
-- OR grant individual functions:
-- GRANT EXECUTE ON FUNCTION pgstattuple(regclass) TO pgtuner_monitor;
-- GRANT EXECUTE ON FUNCTION pgstattuple_approx(regclass) TO pgtuner_monitor;
-- GRANT EXECUTE ON FUNCTION pgstatindex(regclass) TO pgtuner_monitor;
-- hypopg (for hypothetical index testing)
CREATE EXTENSION IF NOT EXISTS hypopg;
GRANT SELECT ON hypopg_list_indexes TO pgtuner_monitor;
GRANT SELECT ON hypopg_hidden_indexes TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_create_index(text) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_drop_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_reset() TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_hide_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_unhide_index(oid) TO pgtuner_monitor;
GRANT EXECUTE ON FUNCTION hypopg_relation_size(oid) TO pgtuner_monitor;
-- 6. Verify permissions
SET ROLE pgtuner_monitor;
SELECT * FROM pg_stat_statements LIMIT 1;
SELECT * FROM pg_stat_activity WHERE pid = pg_backend_pid();
SELECT * FROM pgstattuple('pg_class') LIMIT 1;
SELECT * FROM hypopg_list_indexes();
RESET ROLE;
You can exclude specific PostgreSQL users from being included in query analysis and monitoring results. This is useful for filtering out:
Set the PGTUNER_EXCLUDE_USERIDS environment variable with a comma-separated list of user OIDs:
# Exclude user IDs 16384, 16385, and 16386
export PGTUNER_EXCLUDE_USERIDS="16384,16385,16386"
To find the OID for a specific PostgreSQL user:
SELECT usesysid, usename FROM pg_user WHERE usename = 'monitoring_user';
When configured, the following queries are filtered:
pg_stat_activity queries (filters on usesysid column)pg_stat_statements queries (filters on userid column)This affects tools like get_slow_queries, get_active_queries, analyze_wait_events, check_database_health, and get_index_recommendations.
Add to your cline_mcp_settings.json or Claude Desktop config:
{
"mcpServers": {
"pgtuner_mcp": {
"command": "python",
"args": ["-m", "pgtuner_mcp"],
"env": {
"DATABASE_URI": "postgresql://user:password@localhost:5432/mydb"
},
"disabled": false,
"autoApprove": []
}
}
}
Or Streamable HTTP Mode
{
"mcpServers": {
"pgtuner_mcp": {
"type": "http",
"url": "http://localhost:8080/mcp"
}
}
}
# Default mode (stdio)
python -m pgtuner_mcp
# Explicitly specify stdio mode
python -m pgtuner_mcp --mode stdio
The SSE (Server-Sent Events) mode provides a web-based transport for MCP communication. It's useful for web applications and clients that need HTTP-based communication.
# Start SSE server on default host/port (0.0.0.0:8080)
python -m pgtuner_mcp --mode sse
# Specify custom host and port
python -m pgtuner_mcp --mode sse --host localhost --port 3000
# Enable debug mode
python -m pgtuner_mcp --mode sse --debug
SSE Endpoints:
| Endpoint | Method | Description |
|---|---|---|
/sse | GET | SSE connection endpoint - clients connect here to receive server events |
/messages | POST | Send messages/requests to the server |
MCP Client Configuration for SSE:
For MCP clients that support SSE transport (like Claude Desktop or custom clients):
{
"mcpServers": {
"pgtuner_mcp": {
"type": "sse",
"url": "http://localhost:8080/sse"
}
}
}
The streamable-http mode implements the modern MCP Streamable HTTP protocol with a single /mcp endpoint. It supports both stateful (session-based) and stateless modes.
# Start Streamable HTTP server in stateful mode (default)
python -m pgtuner_mcp --mode streamable-http
# Start in stateless mode (fresh transport per request)
python -m pgtuner_mcp --mode streamable-http --stateless
# Specify custom host and port
python -m pgtuner_mcp --mode streamable-http --host localhost --port 8080
# Enable debug mode
python -m pgtuner_mcp --mode streamable-http --debug
Stateful vs Stateless:
mcp-session-id header. Ideal for long-running interactions.Endpoint: http://{host}:{port}/mcp
Note: All tools focus exclusively on user/application tables and indexes. System catalog tables (
pg_catalog,information_schema,pg_toast) are automatically excluded from all analyses.
| Tool | Description |
|---|---|
get_slow_queries | Retrieve slow queries from pg_stat_statements with detailed stats (total time, mean time, calls, cache hit ratio). Excludes system catalog queries. |
analyze_query | Analyze a query's execution plan with EXPLAIN ANALYZE, including automated issue detection |
get_table_stats | Get detailed table statistics including size, row counts, dead tuples, and access patterns |
analyze_disk_io_patterns | Analyze disk I/O read/write patterns, identify hot tables, buffer cache efficiency, and I/O bottlenecks. Supports filtering by analysis type (all, buffer_pool, tables, indexes, temp_files, checkpoints). |
| Tool | Description |
|---|---|
get_index_recommendations | AI-powered index recommendations based on query workload analysis |
explain_with_indexes | Run EXPLAIN with hypothetical indexes to test improvements without creating real indexes |
manage_hypothetical_indexes | Create, list, drop, or reset HypoPG hypothetical indexes. Supports hide/unhide existing indexes. |
find_unused_indexes | Find unused and duplicate indexes that can be safely dropped |
| Tool | Description |
|---|---|
check_database_health | Comprehensive health check with scoring (connections, cache, locks, replication, wraparound, disk, checkpoints) |
get_active_queries | Monitor active queries, find long-running transactions and blocked queries. By default excludes system processes. |
analyze_wait_events | Analyze wait events to identify I/O, lock, or CPU bottlenecks. Focuses on client backend processes. |
review_settings | Review PostgreSQL settings by category with optimization recommendations |
| Tool | Description |
|---|---|
analyze_table_bloat | Analyze table bloat using pgstattuple extension. Shows dead tuple counts, free space, and wasted space percentage. |
analyze_index_bloat | Analyze B-tree index bloat using pgstatindex. Shows leaf density, fragmentation, and empty/deleted pages. Also supports GIN and Hash indexes. |
get_bloat_summary | Get a comprehensive overview of database bloat with top bloated tables/indexes, total reclaimable space, and priority maintenance actions. |
| Tool | Description |
|---|---|
monitor_vacuum_progress | Track manual VACUUM, VACUUM FULL, and autovacuum operations. Monitor progress percentage, dead tuples collected, index vacuum rounds, and estimated time remaining. Includes autovacuum configuration review and tables needing maintenance. |
limit: Maximum queries to return (default: 10)min_calls: Minimum call count filter (default: 1)min_mean_time_ms: Minimum mean (average) execution time in milliseconds filterorder_by: Sort by mean_time, calls, or rowsquery (required): SQL query to analyzeanalyze: Execute query with EXPLAIN ANALYZE (default: true)buffers: Include buffer statistics (default: true)format: Output format - json, text, yaml, xmlworkload_queries: Optional list of specific queries to analyzemax_recommendations: Maximum recommendations (default: 10)min_improvement_percent: Minimum improvement threshold (default: 10%)include_hypothetical_testing: Test with HypoPG (default: true)target_tables: Focus on specific tablesinclude_recommendations: Include actionable recommendations (default: true)verbose: Include detailed statistics (default: false)table_name: Name of a specific table to analyze (optional)schema_name: Schema name (default: public)use_approx: Use pgstattuple_approx for faster analysis on large tables (default: false)min_table_size_gb: Minimum table size in GB to include in schema-wide scan (default: 5)include_toast: Include TOAST table analysis (default: false)index_name: Name of a specific index to analyze (optional)table_name: Analyze all indexes on this table (optional)schema_name: Schema name (default: public)min_index_size_gb: Minimum index size in GB to include (default: 5)min_bloat_percent: Only show indexes with bloat above this percentage (default: 20)schema_name: Schema to analyze (default: public)top_n: Number of top bloated objects to show (default: 10)min_size_gb: Minimum object size in GB to include (default: 5)action: Action to perform - progress (monitor active vacuum operations), needs_vacuum (find tables needing vacuum), autovacuum_status (review autovacuum configuration), or recent_activity (view recent vacuum history)schema_name: Schema to analyze (default: public, used with needs_vacuum action)top_n: Number of results to return (default: 20)analysis_type: Type of I/O analysis - all (comprehensive), buffer_pool (cache hit ratios), tables (table I/O patterns), indexes (index I/O patterns), temp_files (temporary file usage), or checkpoints (checkpoint I/O statistics)schema_name: Schema to analyze (default: public)top_n: Number of top I/O-intensive objects to show (default: 20)min_size_gb: Minimum object size in GB to include (default: 1)The server includes pre-defined prompt templates for guided tuning sessions:
| Prompt | Description |
|---|---|
diagnose_slow_queries | Systematic slow query investigation workflow |
index_optimization | Comprehensive index analysis and cleanup |
health_check | Full database health assessment |
query_tuning | Optimize a specific SQL query |
performance_baseline | Generate a baseline report for comparison |
pgtuner://docs/tools - Complete tool documentationpgtuner://docs/workflows - Common tuning workflows guidepgtuner://docs/prompts - Prompt template documentationpgtuner://table/{schema}/{table_name}/stats - Table statisticspgtuner://table/{schema}/{table_name}/indexes - Table index informationpgtuner://query/{query_hash}/stats - Query performance statisticspgtuner://settings/{category} - PostgreSQL settings (memory, checkpoint, wal, autovacuum, connections, all)pgtuner://health/{check_type} - Health checks (connections, cache, locks, replication, bloat, all)HypoPG enables testing indexes without actually creating them. This is extremely useful for:
HypoPG enables testing hypothetical indexes without creating them on disk.
-- Create the extension
CREATE EXTENSION IF NOT EXISTS hypopg;
-- Verify installation
SELECT * FROM hypopg_list_indexes();
The pg_stat_statements extension is required for query performance analysis. It tracks planning and execution statistics for all SQL statements executed by a server.
Add the following to your postgresql.conf file:
# Required: Load pg_stat_statements module
shared_preload_libraries = 'pg_stat_statements'
# Required: Enable query identifier computation
compute_query_id = on
# Maximum number of statements tracked (default: 5000)
pg_stat_statements.max = 10000
# Track all statements including nested ones (default: top)
# Options: top, all, none
pg_stat_statements.track = top
# Track utility commands like CREATE, ALTER, DROP (default: on)
pg_stat_statements.track_utility = on
Note: After modifying
shared_preload_libraries, a PostgreSQL server restart is required.
-- Connect to your database and create the extension
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Verify installation
SELECT * FROM pg_stat_statements LIMIT 1;
The pgstattuple extension is required for bloat detection tools (analyze_table_bloat, analyze_index_bloat, get_bloat_summary). It provides functions to get tuple-level statistics for tables and indexes.
-- Create the extension
CREATE EXTENSION IF NOT EXISTS pgstattuple;
-- Verify installation
SELECT * FROM pgstattuple('pg_class') LIMIT 1;
| Setting | Overhead | Recommendation |
|---|---|---|
pg_stat_statements | Low (~1-2%) | Always enable |
track_io_timing | Low-Medium (~2-5%) | Enable in production, test first |
track_functions = all | Low | Enable for function-heavy workloads |
pg_stat_statements.track_planning | Medium | Enable only when investigating planning issues |
log_min_duration_statement | Low | Recommended for slow query identification |
Tip: Use
pg_test_timingto measure the timing overhead on your specific system before enablingtrack_io_timing.
# Get top 10 slowest queries
slow_queries = await get_slow_queries(limit=10, order_by="total_time")
# Analyze a specific query's execution plan
analysis = await analyze_query(
query="SELECT * FROM orders WHERE user_id = 123",
analyze=True,
buffers=True
)
# Analyze workload and get recommendations
recommendations = await get_index_recommendations(
max_recommendations=5,
min_improvement_percent=20,
include_hypothetical_testing=True
)
# Recommendations include CREATE INDEX statements
for rec in recommendations["recommendations"]:
print(rec["create_statement"])
# Run comprehensive health check
health = await check_database_health(
include_recommendations=True,
verbose=True
)
print(f"Health Score: {health['overall_score']}/100")
print(f"Status: {health['status']}")
# Review specific areas
for issue in health["issues"]:
print(f"{issue}")
# Find indexes that can be dropped
unused = await find_unused_indexes(
schema_name="public",
include_duplicates=True
)
# Get DROP statements
for stmt in unused["recommendations"]:
print(stmt)
docker pull dog830228/pgtuner_mcp
# Streamable HTTP mode (recommended for web applications)
docker run -p 8080:8080 \
-e DATABASE_URI=postgresql://user:pass@host:5432/db \
dog830228/pgtuner_mcp --mode streamable-http
# Streamable HTTP stateless mode (for serverless)
docker run -p 8080:8080 \
-e DATABASE_URI=postgresql://user:pass@host:5432/db \
dog830228/pgtuner_mcp --mode streamable-http --stateless
# SSE mode (legacy web applications)
docker run -p 8080:8080 \
-e DATABASE_URI=postgresql://user:pass@host:5432/db \
dog830228/pgtuner_mcp --mode sse
# stdio mode (for MCP clients like Claude Desktop)
docker run -i \
-e DATABASE_URI=postgresql://user:pass@host:5432/db \
dog830228/pgtuner_mcp --mode stdio
pg_stat_statements (required for query analysis)hypopg (optional, for hypothetical index testing)Core dependencies:
mcp[cli]>=1.12.0 - Model Context Protocol SDKpsycopg[binary,pool]>=3.1.0 - PostgreSQL adapter with connection poolingpglast>=7.10 - PostgreSQL query parserOptional (for HTTP modes):
starlette>=0.27.0 - ASGI frameworkuvicorn>=0.23.0 - ASGI serverContributions are welcome! Please feel free to submit a Pull Request.
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
by Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
by mcp-marketplace · Developer Tools
Scaffold, build, and publish TypeScript MCP servers to npm — conversationally
by mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.