Skip to main content
Glama
derricksiawor

PostgreSQL MCP Server

README.md
# PostgreSQL MCP Server

A comprehensive Model Context Protocol (MCP) server for PostgreSQL database access. Provides 36 tools for querying, managing, and interacting with PostgreSQL databases through the MCP interface.

## Features

- **36 Database Tools**: Complete set of read-only and write operations
- **PostgreSQL-Specific Features**: Schema support, JSONB operations, extensions, functions, triggers, views, sequences
- **Full SSL/TLS Support**: CA certificates, client certificates, configurable TLS versions
- **Security First**: Query validation, rate limiting, blocked dangerous operations
- **Connection Pooling**: Efficient connection management with configurable limits
- **Audit Logging**: Track all database operations

## Installation

```bash
# Clone or copy to your tools directory
cd /path/to/tools/mav-postgresql-mcp-server

# Install dependencies
npm install

# Build the server
npm run build
```

## Configuration

Copy `.env.example` to `.env` and configure your PostgreSQL connection:

```bash
cp .env.example .env
```

### Required Settings

| Variable | Description | Default |
|----------|-------------|---------|
| `PG_HOST` | PostgreSQL server hostname | `localhost` |
| `PG_PORT` | PostgreSQL server port | `5432` |
| `PG_USER` | Database username | `postgres` |
| `PG_PASSWORD` | Database password | - |
| `PG_DATABASE` | Target database name | - |
| `PG_SCHEMA` | Default schema | `public` |

### SSL Configuration

| Variable | Description | Options |
|----------|-------------|---------|
| `PG_SSL_MODE` | SSL connection mode | `disable`, `require`, `verify-ca`, `verify-full` |
| `PG_SSL_REJECT_UNAUTHORIZED` | Reject self-signed certs | `true`, `false` |
| `PG_SSL_CA_PATH` | Path to CA certificate | - |
| `PG_SSL_CERT_PATH` | Path to client certificate | - |
| `PG_SSL_KEY_PATH` | Path to client key | - |
| `PG_SSL_MIN_VERSION` | Minimum TLS version | `TLSv1.2`, `TLSv1.3` |

### Security Settings

| Variable | Description | Default |
|----------|-------------|---------|
| `ALLOW_WRITE_OPERATIONS` | Enable INSERT/UPDATE/DELETE | `false` |
| `CONNECTION_LIMIT` | Max pool connections | `10` |
| `QUERY_TIMEOUT` | Query timeout (ms) | `30000` |
| `MAX_RESULTS` | Maximum rows returned | `1000` |

### Rate Limiting

| Variable | Description | Default |
|----------|-------------|---------|
| `RATE_LIMIT_PER_MINUTE` | Queries per minute | `60` |
| `RATE_LIMIT_PER_HOUR` | Queries per hour | `1000` |
| `RATE_LIMIT_CONCURRENT` | Concurrent queries | `10` |

## Usage

### With Claude Desktop

Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "postgresql": {
      "command": "node",
      "args": ["/path/to/mav-postgresql-mcp-server/build/index.js"],
      "env": {
        "PG_HOST": "localhost",
        "PG_PORT": "5432",
        "PG_USER": "your_user",
        "PG_PASSWORD": "your_password",
        "PG_DATABASE": "your_database",
        "PG_SCHEMA": "public",
        "ALLOW_WRITE_OPERATIONS": "false"
      }
    }
  }
}
```

### With MCP Inspector

```bash
npx @anthropic/mcp-inspector node build/index.js
```

## Available Tools

### Core Read-Only Tools (7)

| Tool | Description |
|------|-------------|
| `query` | Execute SELECT queries |
| `list_tables` | List all tables in schema |
| `describe_table` | Get table structure and columns |
| `database_info` | Get database version and settings |
| `show_indexes` | List indexes on a table |
| `explain_query` | Get query execution plan |
| `show_constraints` | List table constraints |

### PostgreSQL-Specific Read-Only Tools (14)

| Tool | Description |
|------|-------------|
| `list_schemas` | List all schemas in database |
| `get_current_schema` | Get current search path |
| `list_extensions` | List installed extensions |
| `extension_info` | Get detailed extension information |
| `list_functions` | List user-defined functions |
| `list_triggers` | List triggers on a table |
| `list_views` | List views in schema |
| `list_sequences` | List sequences in schema |
| `table_stats` | Get table statistics |
| `connection_info` | Get current connection details |
| `database_size` | Get database/table sizes |
| `jsonb_query` | Query JSONB columns |
| `jsonb_path_query` | Execute JSON path queries |

### Write Operation Tools (15)

*Requires `ALLOW_WRITE_OPERATIONS=true`*

| Tool | Description |
|------|-------------|
| `insert` | Insert a single row |
| `update` | Update rows with conditions |
| `delete` | Delete rows with conditions |
| `create_table` | Create a new table |
| `alter_table` | Modify table structure |
| `drop_table` | Drop a table |
| `bulk_insert` | Insert multiple rows |
| `execute_procedure` | Call stored procedures |
| `add_index` | Create an index |
| `drop_index` | Remove an index |
| `rename_table` | Rename a table |
| `set_search_path` | Change schema search path |
| `create_schema` | Create a new schema |
| `drop_schema` | Drop a schema |
| `jsonb_update` | Update JSONB fields |
| `vacuum_analyze` | Optimize table statistics |

## MCP Resources

The server exposes database schema as MCP resources:

- `pg://database/schema` - List all tables and columns
- `pg://database/info` - Database information
- `pg://table/{schema}.{table}` - Individual table schema

## Security Features

### Blocked Operations

The server blocks dangerous operations by default:

- File system operations (`COPY FROM/TO`, `pg_read_file`, etc.)
- Permission modifications (`GRANT`, `REVOKE`, `ALTER ROLE`)
- Administrative commands (`CREATE ROLE`, `DROP DATABASE`, etc.)
- System catalog modifications

### Protected Tables

Access to sensitive system tables is blocked:

- `pg_catalog.pg_authid`
- `pg_catalog.pg_shadow`
- `pg_catalog.pg_auth_members`

### Query Validation

- All identifiers are validated (max 63 characters, safe characters only)
- Query timeouts prevent long-running operations
- Rate limiting prevents abuse

## Setting Up a Read-Only User

For production use, create a dedicated read-only PostgreSQL user:

```bash
# Run as PostgreSQL superuser
psql -U postgres -f setup-readonly-user.sql
```

Or manually:

```sql
-- Create user
CREATE USER mcp_readonly WITH PASSWORD 'secure_password';

-- Grant connect
GRANT CONNECT ON DATABASE your_database TO mcp_readonly;

-- Grant schema usage
GRANT USAGE ON SCHEMA public TO mcp_readonly;

-- Grant read access to all tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;

-- Set default privileges for future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT SELECT ON TABLES TO mcp_readonly;
```

## Development

```bash
# Run in development mode
npm run dev

# Build for production
npm run build

# Type checking
npm run typecheck
```

## Troubleshooting

### Connection Issues

1. Verify PostgreSQL is running: `pg_isready -h localhost -p 5432`
2. Check credentials: `psql -h localhost -U your_user -d your_database`
3. Enable debug mode: `MCP_DEBUG=true`

### SSL Issues

1. Verify certificate paths are correct
2. Check certificate permissions (readable by the user running the server)
3. Try `PG_SSL_MODE=require` first, then upgrade to `verify-ca` or `verify-full`

### Rate Limiting

If you're hitting rate limits:
1. Increase `RATE_LIMIT_PER_MINUTE` and `RATE_LIMIT_PER_HOUR`
2. Batch operations where possible
3. Use more specific queries to reduce call volume

## License

MIT