PostgreSQL MCP Server
PostgreSQL MCP 서버
사용자가 자연어를 통해 PostgreSQL 데이터베이스와 상호작용할 수 있도록 지원하는 프로덕션급 Model Context Protocol (MCP) 서버입니다. 이 서버는 FastMCP를 기반으로 구축되었으며, 자연어 질문을 안전한 SQL 쿼리로 변환하고, 쿼리를 실행하며, 결과를 검증합니다. 참고 문서:
Python Postgres MCP 요구사항 연구 : https://gemini.google.com/share/c87a73f0969b
SQLGlot 심층 연구 계획 : https://gemini.google.com/share/cc5e45c76c8f
주요 기능
자연어-SQL 변환: GPT-5.2-mini를 사용하여 일반 영어 질문을 최적화된 PostgreSQL 쿼리로 변환
보안 우선: 읽기 전용 강제 적용, 위험 함수 차단, SQL 인젝션 방지, 쿼리 타임아웃 제어
결과 검증: AI 기반 결과 검증 및 신뢰도 점수 제공
지능형 스키마: 자동 스키마 캐싱 및 TTL 기반 새로고침 메커니즘
프로덕션 준비 완료: 커넥션 풀 관리, 서킷 브레이커, 속도 제한, 포괄적인 지표 수집
MCP 호환: Claude Desktop 및 모든 MCP 호환 클라이언트 지원
Related MCP server: PostgreSQL MCP Server
빠른 시작
사전 요구 사항
Python 3.14+
PostgreSQL 12+
OpenAI API 키 (GPT-5.2-mini용)
UV 패키지 관리자 (권장) 또는 pip
설치
UV 사용 (권장)
# 克隆仓库
git clone <repository-url>
cd pg-mcp
# 安装依赖
uv sync
# 复制环境配置模板
cp .env.example .env
# 编辑 .env 并配置参数
vi .envpip 사용
# 克隆仓库
git clone <repository-url>
cd pg-mcp
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate # Windows 系统: .venv\Scripts\activate
# 安装依赖
pip install -e .
# 复制环境配置模板
cp .env.example .env
# 编辑 .env 并配置参数
vi .env설정
.env 파일을 편집하여 설정을 구성하세요:
# 数据库配置
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=your_database
DATABASE_USER=your_user
DATABASE_PASSWORD=your_password
# OpenAI 配置
OPENAI_API_KEY=sk-your-api-key-here
OPENAI_MODEL=gpt-5.2-mini
# 安全设置(可选,显示默认值)
SECURITY_ALLOW_WRITE_OPERATIONS=false
SECURITY_MAX_ROWS=10000
SECURITY_MAX_EXECUTION_TIME=30전체 설정 옵션은 .env.example을 참조하세요.
서버 실행
독립 실행 모드
# 使用 UV
uv run python main.py
# 或使用 pip
python main.pyClaude Desktop과 통합
Claude Desktop MCP 설정 파일에 다음 구성을 추가하세요:
macOS/Linux: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"postgres": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/pg-mcp",
"run",
"python",
"main.py"
],
"env": {
"DATABASE_HOST": "localhost",
"DATABASE_NAME": "your_database",
"DATABASE_USER": "your_user",
"DATABASE_PASSWORD": "your_password",
"OPENAI_API_KEY": "sk-your-api-key-here"
}
}
}
}자세한 설정 설명은 Claude Desktop 설정을 참조하세요.
사용 방법
쿼리 예시
Claude Desktop 또는 기타 MCP 클라이언트를 통해 연결한 후, 자연어로 질문할 수 있습니다:
간단한 쿼리
How many tables are in the database?
→ SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public'
Show me all users
→ SELECT * FROM users LIMIT 10000
What are the column names in the products table?
→ SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'products'분석 쿼리
What are the top 10 products by sales?
→ SELECT product_name, SUM(quantity * price) as total_sales
FROM orders
GROUP BY product_name
ORDER BY total_sales DESC
LIMIT 10
How many users registered in the last 30 days?
→ SELECT COUNT(*) FROM users
WHERE created_at > CURRENT_DATE - INTERVAL '30 days'SQL 전용 모드
실행하지 않고 SQL만 요청할 수도 있습니다:
Generate SQL to find duplicate emails
Return Type: sql
→ Returns: SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1반환 유형
서버는 두 가지 반환 유형을 지원합니다:
result(기본값): 쿼리를 실행하고 결과를 반환sql: SQL을 생성 및 검증하되 실행하지 않음
응답 형식
성공적인 쿼리 응답
{
"success": true,
"generated_sql": "SELECT COUNT(*) FROM users",
"data": {
"columns": ["count"],
"rows": [[1523]],
"row_count": 1,
"execution_time": 0.023
},
"confidence": 95,
"tokens_used": 234
}SQL 전용 응답
{
"success": true,
"generated_sql": "SELECT * FROM users WHERE created_at > CURRENT_DATE - INTERVAL '30 days'",
"confidence": 90,
"tokens_used": 156
}오류 응답
{
"success": false,
"error": {
"code": "SECURITY_VIOLATION",
"message": "Query contains blocked operation: DELETE",
"details": {
"blocked_operation": "DELETE"
}
}
}아키텍처
핵심 구성 요소
┌─────────────────────────────────────────────────────────────┐
│ MCP Server (FastMCP) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Query Orchestrator │
│ - Coordinates all components │
│ - Manages retry logic │
│ - Handles error recovery │
└─────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────┐ ┌────────────┐ ┌──────────────┐
│ SQL │ │ SQL │ │ SQL │
│ Generator │────▶│ Validator │────▶│ Executor │
│ (LLM) │ │ (Security) │ │ (Database) │
└───────────┘ └────────────┘ └──────────────┘
│ │
▼ ▼
┌───────────┐ ┌──────────────┐
│ Schema │ │ Result │
│ Cache │ │ Validator │
└───────────┘ │ (LLM) │
└──────────────┘보안 기능
읽기 전용 강제 적용: 기본적으로 SELECT 쿼리만 허용
위험 함수 차단: 블랙리스트에 위험한 PostgreSQL 함수(pg_sleep, 파일 I/O 등) 포함
SQL 파싱: sqlglot을 사용하여 정확한 SQL 구조 검증
인젝션 방지: 파라미터화된 쿼리 및 입력 정제
리소스 제한:
행 수 제한 (기본값: 10,000)
쿼리 타임아웃 (기본값: 30초)
커넥션 풀 관리
트랜잭션 격리: 모든 쿼리는 읽기 전용 트랜잭션에서 실행
탄력성 기능
서킷 브레이커: LLM API 장애 전파 방지
속도 제한: API 할당량 소진 방지
재시도 로직: 지수 백오프를 사용한 일시적 오류 자동 재시도
커넥션 풀: 효율적인 데이터베이스 연결 재사용
스키마 캐싱: TTL 기반 캐싱으로 데이터베이스 메타데이터 쿼리 감소
설정 참조
데이터베이스 설정
변수 | 설명 | 기본값 |
| PostgreSQL 호스트 |
|
| PostgreSQL 포트 |
|
| 데이터베이스 이름 | 필수 |
| 데이터베이스 사용자 | 필수 |
| 데이터베이스 비밀번호 | 필수 |
| 풀 내 최소 연결 수 |
|
| 풀 내 최대 연결 수 |
|
| 쿼리 타임아웃 (초) |
|
OpenAI 설정
변수 | 설명 | 기본값 |
| OpenAI API 키 | 필수 |
| 사용할 모델 |
|
| 요청당 최대 토큰 수 |
|
| 모델 온도 |
|
| API 타임아웃 (초) |
|
보안 설정
변수 | 설명 | 기본값 |
| INSERT/UPDATE/DELETE 허용 |
|
| 쉼표로 구분된 함수 블랙리스트 | .env.example 참조 |
| 쿼리당 최대 행 수 |
|
| 쿼리 타임아웃 (초) |
|
캐시 설정
변수 | 설명 | 기본값 |
| 스키마 캐싱 활성화 |
|
| 스키마 캐시 TTL (초) |
|
| 최대 캐시 스키마 수 |
|
탄력성 설정
변수 | 설명 | 기본값 |
| 최대 재시도 횟수 |
|
| 초기 재시도 지연 (초) |
|
| 지수 백오프 배수 |
|
| 서킷 브레이커 임계값 |
|
| 서킷 브레이커 타임아웃 (초) |
|
관측 가능성 설정
변수 | 설명 | 기본값 |
| Prometheus 지표 활성화 |
|
| 지표 HTTP 포트 |
|
| 로그 레벨 |
|
| 로그 형식 (json/text) |
|
개발
개발 환경 설정
# 安装开发依赖
uv sync --all-extras
# 安装 pre-commit 钩子(可选)
pre-commit install테스트 실행
# 运行所有测试
uv run pytest
# 运行并生成覆盖率报告
uv run pytest --cov=src --cov-report=html
# 运行特定测试类别
uv run pytest tests/unit/ # 仅单元测试
uv run pytest tests/integration/ # 集成测试
uv run pytest tests/e2e/ # 端到端测试
uv run pytest -m integration # 标记为集成的测试코드 품질
# 类型检查
uv run mypy src
# Lint 和格式化
uv run ruff check --fix .
uv run ruff format .
# 运行所有质量检查
uv run pytest --cov=src --cov-fail-under=80
uv run mypy src
uv run ruff check .프로젝트 구조
pg-mcp/
├── src/pg_mcp/
│ ├── cache/ # Schema 缓存
│ ├── config/ # 配置管理
│ ├── db/ # 数据库连接池
│ ├── models/ # 数据模型
│ ├── observability/ # 日志、指标、追踪
│ ├── prompts/ # LLM Prompt 模板
│ ├── resilience/ # 熔断器、限流器
│ ├── services/ # 核心业务逻辑
│ │ ├── orchestrator.py # 查询协调
│ │ ├── sql_generator.py # 基于 LLM 的 SQL 生成
│ │ ├── sql_validator.py # 安全验证
│ │ ├── sql_executor.py # 查询执行
│ │ └── result_validator.py # 结果验证
│ └── server.py # FastMCP 服务器
├── tests/
│ ├── unit/ # 单元测试
│ ├── integration/ # 集成测试
│ └── e2e/ # 端到端测试
├── fixtures/ # 测试数据库 fixture
├── .env.example # 环境模板
├── pyproject.toml # 项目配置
└── main.py # 入口点Docker 배포
이미지 빌드
docker build -t pg-mcp:latest .컨테이너 실행
docker run -d \
--name pg-mcp \
-e DATABASE_HOST=your-db-host \
-e DATABASE_NAME=your-db \
-e DATABASE_USER=your-user \
-e DATABASE_PASSWORD=your-password \
-e OPENAI_API_KEY=sk-your-key \
-p 9090:9090 \
pg-mcp:latestDocker Compose
# 启动所有服务(PostgreSQL + pg-mcp)
docker-compose up -d
# 查看日志
docker-compose logs -f pg-mcp
# 停止服务
docker-compose down자세한 설정은 docker-compose.yml을 참조하세요.
모니터링
지표
서버는 9090 포트(설정 가능)에서 Prometheus 지표를 노출합니다:
curl http://localhost:9090/metrics사용 가능한 지표:
pg_mcp_queries_total- 처리된 총 쿼리 수pg_mcp_query_duration_seconds- 쿼리 실행 시간 히스토그램pg_mcp_sql_generation_duration_seconds- SQL 생성 시간pg_mcp_sql_validation_failures_total- 검증 실패 횟수pg_mcp_database_errors_total- 데이터베이스 오류 수pg_mcp_llm_tokens_used_total- LLM 토큰 사용 총량
로그
구조화된 JSON 로그(또는 텍스트 형식)가 표준 출력으로 출력됩니다:
{
"timestamp": "2025-12-20T10:30:00.123Z",
"level": "INFO",
"message": "Query executed successfully",
"database": "mydb",
"execution_time": 0.023,
"row_count": 42
}문제 해결
일반적인 문제
연결 거부
Error: Connection to database failed해결 방법: PostgreSQL이 실행 중이고 자격 증명이 올바른지 확인하세요:
psql -h $DATABASE_HOST -U $DATABASE_USER -d $DATABASE_NAMEOpenAI API 오류
Error: OpenAI API request failed해결 방법:
API 키가 유효하고 잔액이 있는지 확인
네트워크 연결 확인
요청 시간이 초과되면
OPENAI_TIMEOUT설정 확인
쿼리 타임아웃
Error: Query execution timeout exceeded해결 방법:
SECURITY_MAX_EXECUTION_TIME증가데이터베이스 최적화 (인덱스 추가, VACUUM)
쿼리 단순화 또는 필터 조건 추가
스키마 캐시 문제
Error: Schema not found in cache해결 방법:
서버를 재시작하여 스키마 다시 로드
데이터베이스 사용자가 스키마 읽기 권한을 가지고 있는지 확인
CACHE_ENABLED가true로 설정되어 있는지 확인
디버그 모드
디버그 로그 활성화:
export OBSERVABILITY_LOG_LEVEL=DEBUG
uv run python main.pyClaude Desktop 설정
macOS/Linux 설정
~/Library/Application Support/Claude/claude_desktop_config.json 편집:
{
"mcpServers": {
"postgres": {
"command": "uv",
"args": [
"--directory",
"/Users/yourname/projects/pg-mcp",
"run",
"python",
"main.py"
],
"env": {
"DATABASE_HOST": "localhost",
"DATABASE_PORT": "5432",
"DATABASE_NAME": "mydb",
"DATABASE_USER": "postgres",
"DATABASE_PASSWORD": "your-password",
"OPENAI_API_KEY": "sk-your-api-key-here",
"OPENAI_MODEL": "gpt-5.2-mini",
"SECURITY_MAX_ROWS": "10000",
"CACHE_ENABLED": "true",
"OBSERVABILITY_LOG_LEVEL": "INFO"
}
}
}
}Windows 설정
%APPDATA%\Claude\claude_desktop_config.json 편집:
{
"mcpServers": {
"postgres": {
"command": "uv",
"args": [
"--directory",
"C:\\Users\\YourName\\projects\\pg-mcp",
"run",
"python",
"main.py"
],
"env": {
"DATABASE_HOST": "localhost",
"DATABASE_NAME": "mydb",
"DATABASE_USER": "postgres",
"DATABASE_PASSWORD": "your-password",
"OPENAI_API_KEY": "sk-your-api-key-here"
}
}
}
}Python Virtualenv 사용
UV를 사용하지 않는 경우, Python을 직접 설정하세요:
{
"mcpServers": {
"postgres": {
"command": "/absolute/path/to/pg-mcp/.venv/bin/python",
"args": ["main.py"],
"cwd": "/absolute/path/to/pg-mcp",
"env": {
"DATABASE_HOST": "localhost",
...
}
}
}
}Claude Desktop 재시작
설정 편집 후:
Claude Desktop 완전히 종료
Claude Desktop 재시작
PostgreSQL MCP 서버 사용 가능
보안 고려 사항
프로덕션 환경 배포
읽기 전용 데이터베이스 사용자 사용: SELECT 권한만 가진 전용 PostgreSQL 사용자 생성:
CREATE USER pg_mcp_readonly WITH PASSWORD 'secure-password';
GRANT CONNECT ON DATABASE your_database TO pg_mcp_readonly;
GRANT USAGE ON SCHEMA public TO pg_mcp_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO pg_mcp_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO pg_mcp_readonly;API 키 보호: 환경 변수 또는 비밀 관리 시스템 사용, 버전 제어에 절대 커밋하지 마세요.
네트워크 격리: 격리된 네트워크에서 서버를 실행하고 IP 제한을 통해 데이터베이스 접근을 제한하세요.
사용량 모니터링: 지표를 활성화하고 비정상적인 패턴에 대한 알림을 설정하세요.
속도 제한: 오용을 방지하기 위해 적절한 속도 제한 매개변수를 구성하세요.
로그 정제: 민감한 데이터는 로그에서 자동으로 필터링됩니다.
라이선스
[귀하의 라이선스 정보]
기여
기여를 환영합니다! 가이드라인은 CONTRIBUTING.md를 참조하세요.
지원
질문이나 문의 사항:
GitHub Issues: [repository-url]/issues
문서: 상세 설계 문서는
specs/w5/디렉토리 확인
감사의 말
Available Tools
1 tooladdA
Add two numbers
| Name | Required | Description | Default |
|---|---|---|---|
| a | Yes | ||
| b | Yes |
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 behavioral burden. 'Add two numbers' accurately and sufficiently communicates a pure arithmetic operation, with no indication of side effects or hidden behavior.
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 four words long, contains zero filler, and conveys the complete operation. It is front-loaded and every word 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?
For a simple two-integer addition tool with an output schema and no siblings, this description is nearly complete. It could mention the return value or pure behavior explicitly, but the output schema and inherent simplicity reduce that need.
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 0%, so the description must compensate. It clarifies that both parameters are numbers to be added, but it does not name them or describe each parameter individually. Since addition is commutative, the lack of role differentiation is a minor gap.
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 states a precise verb ('add') and a clear resource ('two numbers'), making the tool's purpose immediately obvious. With no sibling tools, there is no ambiguity to resolve.
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 intended use is clear: this tool is for summing two numbers. It does not explicitly discuss when not to use it, but with no sibling tools and only two integer parameters, the context is straightforward.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.2.1- First observed
add
TDQS
Scored across 1 tool
Only one tool exists, so no ambiguity between tools.
With a single tool, naming consistency is inherently maintained.
A single trivial arithmetic tool is extremely thin for a PostgreSQL MCP server, fitting the description of an extreme mismatch.
The server's name suggests database-related functionality, but the only tool adds two numbers, leaving the entire database surface missing.
Maintenance
Related MCP Connectors
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Query Postgres, MySQL, SQL Server, Oracle, BigQuery, ClickHouse and Redshift from your AI client.
Ask data questions in natural language. Get SQL, insights, and charts from your databases.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceEnables secure read-only interactions with PostgreSQL databases through natural language. Provides database inspection, table listing, and SQL query execution with built-in security validation.-
- AlicenseAqualityBmaintenanceEnables read-only interaction with PostgreSQL databases through natural language queries, supporting dynamic connections and secure query validation.3134 npm2MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with PostgreSQL databases through natural language queries, schema inspection, and safe SQL execution.6 npm1-
- FlicenseNot gradedqualityDmaintenanceConverts natural language to safe SQL queries for PostgreSQL databases with read-only access and multi-layer security validation. Provides tools for running validated SELECT queries, retrieving schema, and sampling table data.-