# 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