# PostgreSQL MCP Server Setup

This document describes the configuration and troubleshooting for the PostgreSQL MCP server integration with Claude Code.

## Status

✅ **WORKING** - Successfully configured and tested on 2026-01-22

- **Server Name**: `devdb`
- **Database**: `flyer_crawler_dev` (68 tables)
- **Connection**: Verified working
- **Tool Prefix**: `mcp__devdb__*`
- **Configuration**: Project-level `.mcp.json`

## Overview

The PostgreSQL MCP server (`@modelcontextprotocol/server-postgres`) provides database query capabilities directly from Claude Code, enabling:

- Running SQL queries against the development database
- Exploring database schema and tables
- Testing queries before implementation
- Debugging data issues

## Configuration

### Project-Level Configuration (Recommended)

The PostgreSQL MCP server is configured in the project-level `.mcp.json` file:

```json
{
  "mcpServers": {
    "devdb": {
      "command": "D:\\nodejs\\npx.cmd",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://postgres:postgres@127.0.0.1:5432/flyer_crawler_dev"
      ]
    }
  }
}
```

**Key Configuration Details:**

| Parameter   | Value                                   | Notes                                   |
| ----------- | --------------------------------------- | --------------------------------------- |
| Server Name | `devdb`                                 | Distinct name to avoid collision issues |
| Package     | `@modelcontextprotocol/server-postgres` | Official MCP PostgreSQL server          |
| Host        | `127.0.0.1`                             | Use IP address, not `localhost`         |
| Port        | `5432`                                  | Default PostgreSQL port                 |
| Database    | `flyer_crawler_dev`                     | Development database name               |
| User        | `postgres`                              | Default superuser for dev               |
| Password    | `postgres`                              | Default password for dev                |

### Why Project-Level Configuration?

Based on troubleshooting experience with other MCP servers (documented in `BUGSINK-MCP-TROUBLESHOOTING.md`), **localhost MCP servers work more reliably in project-level `.mcp.json`** than in global `settings.json`.

Issues observed with global configuration:

- MCP servers silently not loading
- No error messages in logs
- Tools not appearing in available tool list

Project-level configuration bypasses these issues entirely.

### Connection String Format

```
postgresql://[user]:[password]@[host]:[port]/[database]
```

Examples:

```
# Development (local container)
postgresql://postgres:postgres@127.0.0.1:5432/flyer_crawler_dev

# Test database (if needed)
postgresql://flyer_crawler_test:password@127.0.0.1:5432/flyer_crawler_test
```

## Available Tools

Once configured, the following tools become available (prefix `mcp__devdb__`):

| Tool    | Description                            |
| ------- | -------------------------------------- |
| `query` | Execute SQL queries and return results |

## Usage Examples

### Basic Query

```typescript
// List all tables
mcp__devdb__query("SELECT tablename FROM pg_tables WHERE schemaname = 'public'");

// Count records in a table
mcp__devdb__query('SELECT COUNT(*) FROM flyers');

// Check table structure
mcp__devdb__query(
  "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'flyers'",
);
```

### Debugging Data Issues

```typescript
// Find recent flyers
mcp__devdb__query('SELECT id, name, created_at FROM flyers ORDER BY created_at DESC LIMIT 10');

// Check job queue status
mcp__devdb__query('SELECT state, COUNT(*) FROM bullmq_jobs GROUP BY state');

// Verify user data
mcp__devdb__query("SELECT id, email, created_at FROM users WHERE email LIKE '%test%'");
```

## Prerequisites

### 1. PostgreSQL Container Running

The PostgreSQL container must be running and healthy:

```bash
# Check container status
podman ps | grep flyer-crawler-postgres

# Expected output shows "healthy" status
# flyer-crawler-postgres ... Up N hours (healthy) ...
```

### 2. Port Accessible from Host

PostgreSQL port 5432 must be mapped to the host:

```bash
# Verify port mapping
podman port flyer-crawler-postgres
# Expected: 5432/tcp -> 0.0.0.0:5432
```

### 3. Database Exists

Verify the database exists:

```bash
podman exec flyer-crawler-postgres psql -U postgres -c "\l" | grep flyer_crawler_dev
```

## Troubleshooting

### Tools Not Available

**Symptoms:**

- `mcp__devdb__*` tools not in available tool list
- No error messages displayed

**Solutions:**

1. **Restart Claude Code** - MCP config changes require restart
2. **Check container status** - Ensure PostgreSQL container is running
3. **Verify port mapping** - Confirm port 5432 is accessible
4. **Test connection manually**:
   ```bash
   podman exec flyer-crawler-postgres psql -U postgres -d flyer_crawler_dev -c "SELECT 1"
   ```

### Connection Refused

**Symptoms:**

- Connection error when using tools
- "Connection refused" in error message

**Solutions:**

1. **Check container health**:

   ```bash
   podman ps | grep flyer-crawler-postgres
   ```

2. **Restart the container**:

   ```bash
   podman restart flyer-crawler-postgres
   ```

3. **Check for port conflicts**:
   ```bash
   netstat -an | findstr 5432
   ```

### Authentication Failed

**Symptoms:**

- "password authentication failed" error

**Solutions:**

1. **Verify credentials** in container environment:

   ```bash
   podman exec flyer-crawler-dev env | grep DB_
   ```

2. **Check PostgreSQL users**:

   ```bash
   podman exec flyer-crawler-postgres psql -U postgres -c "\du"
   ```

3. **Update connection string** in `.mcp.json` if credentials differ

### Database Does Not Exist

**Symptoms:**

- "database does not exist" error

**Solutions:**

1. **List available databases**:

   ```bash
   podman exec flyer-crawler-postgres psql -U postgres -c "\l"
   ```

2. **Create database if missing**:
   ```bash
   podman exec flyer-crawler-postgres createdb -U postgres flyer_crawler_dev
   ```

## Security Considerations

### Development Only

The default credentials (`postgres:postgres`) are for **development only**. Never use these in production.

### Connection String in Config

The connection string includes the password in plain text. This is acceptable for:

- Local development
- Container environments

For production MCP access (if ever needed):

- Use environment variables
- Consider connection pooling
- Implement proper access controls

### Query Permissions

The MCP server executes queries as the configured user (`postgres` in dev). Be aware that:

- `postgres` is a superuser with full access
- For restricted access, create a dedicated MCP user with limited permissions:

```sql
-- Example: Create read-only MCP user
CREATE USER mcp_reader WITH PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE flyer_crawler_dev TO mcp_reader;
GRANT USAGE ON SCHEMA public TO mcp_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_reader;
```

## Database Information

### Development Environment

| Property              | Value                     |
| --------------------- | ------------------------- |
| Container             | `flyer-crawler-postgres`  |
| Image                 | `postgis/postgis:15-3.4`  |
| Host (from Windows)   | `127.0.0.1` / `localhost` |
| Host (from container) | `postgres`                |
| Port                  | `5432`                    |
| Database              | `flyer_crawler_dev`       |
| User                  | `postgres`                |
| Password              | `postgres`                |

### Schema Reference

The database uses PostGIS for geographic data. Key tables include:

- `users` - User accounts
- `stores` - Store definitions
- `store_locations` - Store geographic locations
- `flyers` - Uploaded flyer metadata
- `flyer_items` - Extracted deal items
- `watchlists` - User watchlists
- `shopping_lists` - User shopping lists
- `recipes` - Recipe definitions

For complete schema, see `sql/master_schema_rollup.sql`.

## Related Documentation

- [CLAUDE.md - MCP Servers Section](../CLAUDE.md#mcp-servers)
- [BUGSINK-MCP-TROUBLESHOOTING.md](./BUGSINK-MCP-TROUBLESHOOTING.md) - Similar MCP setup patterns
- [sql/master_schema_rollup.sql](../sql/master_schema_rollup.sql) - Database schema

## Changelog

### 2026-01-21

- Initial configuration added to project-level `.mcp.json`
- Server named `devdb` to avoid naming collisions
- Using `127.0.0.1` instead of `localhost` based on Bugsink MCP experience
- Documentation created
