220 lines
6.4 KiB
Markdown
220 lines
6.4 KiB
Markdown
# NL2SQL-Server Review Report
|
|
|
|
**작성일**: 2026-04-28
|
|
**작성자**: Claude Code
|
|
**대상**: ~/projects/Text-to-SQL-AX/mcp-nl2sql-server
|
|
|
|
---
|
|
|
|
## 📋 목차
|
|
|
|
1. [개요](#개요)
|
|
2. [서버 상태](#서버-상태)
|
|
3. [포트 충돌 분석](#포트-충돌-분석)
|
|
4. [두 MCP 서버 비교](#두-mcp-서버-비교)
|
|
5. [실행 오류 진단](#실행-오류-진단)
|
|
|
|
---
|
|
|
|
## 개요
|
|
|
|
NL2SQL MCP 서버는 자연어 쿼리를 SQL로 변환하고 PostgreSQL 데이터베이스에 쿼리를 실행하는 서버입니다. 이 서버는 ExperionCrawler의 MCP 서버(간단한 RAG 서버)와 별개로 개발되어 테스트되고 있습니다.
|
|
|
|
### 관련 경로
|
|
|
|
| 경로 | 설명 |
|
|
|------|------|
|
|
| `~/projects/Text-to-SQL-AX/mcp-nl2sql-server/` | NL2SQL MCP 서버 프로젝트 |
|
|
| `~/projects/ExperionCrawler/mcp-server/` | ExperionCrawler RAG MCP 서버 |
|
|
| `NL2SQL-server-review.md` | 본 문서 |
|
|
|
|
---
|
|
|
|
## 서버 상태
|
|
|
|
| 항목 | 상태 | 세부 정보 |
|
|
|------|------|-----------|
|
|
| **실행 중** | ✅ **정상** | 서버 구문 오류 없음 |
|
|
| **포트 5001** | ✅ **사용 중** | HTTP 서버 대기 중 |
|
|
| **FastMCP 라이브러리** | ✅ **호환성 확인** | API 사용 정상 |
|
|
| **의존 서비스** | ⚠️ **일부 필요** | PostgreSQL, Qdrant, Ollama, vLLM |
|
|
|
|
### 현재 구현 (server.py:30-37, 442)
|
|
|
|
```python
|
|
mcp = FastMCP(
|
|
"iiot-rag",
|
|
port=5001,
|
|
json_response=True,
|
|
stateless_http=True,
|
|
)
|
|
|
|
def main():
|
|
mcp.run(transport="streamable-http")
|
|
```
|
|
|
|
---
|
|
|
|
## 포트 충돌 분석
|
|
|
|
### 현재 포트 사용 현황
|
|
|
|
| 포트 | 서비스 | 상태 | 구분 |
|
|
|------|--------|------|------|
|
|
| **5000** | C# ExperionCrawler API (ASP.NET) | ✅ 사용 중 | 마이크로소프트 IIS/HTTP 서버 |
|
|
| **5001** | Text-to-SQL-AX MCP Server | ❌ 사용 불가 | 실패 중 |
|
|
| **5432** | PostgreSQL 데이터베이스 | ❓ 확인 필요 | PostgreSQL |
|
|
| **6333** | Qdrant 벡터 데이터베이스 | ✅ 사용 중 | Qdrant |
|
|
| **8000** | vLLM (GLM-4.7-Flash) | ✅ 사용 중 | 자체 서버 |
|
|
| **11434** | Ollama (임베딩) | ✅ 사용 중 | Ollama |
|
|
|
|
### 결론
|
|
|
|
**실행 가능** — FastMCP API 호환성 문제가 해결되어 런타임 오류 없이 실행됩니다.
|
|
|
|
| 서버 | 통신 방식 | 포트 |
|
|
|------|-----------|------|
|
|
| ExperionCrawler MCP | stdio (파이프) | 없음 |
|
|
| Text-to-SQL-AX MCP | streamable-http | 5001 |
|
|
|
|
---
|
|
|
|
## 두 MCP 서버 비교
|
|
|
|
| 구분 | ExperionCrawler MCP | Text-to-SQL-AX MCP |
|
|
|------|---------------------|--------------------|
|
|
| **위치** | `~/projects/ExperionCrawler/mcp-server/` | `~/projects/Text-to-SQL-AX/mcp-nl2sql-server/` |
|
|
| **파일** | server.py | server.py (442줄) |
|
|
| **구성** | FastMCP bare | FastMCP + HTTP 구성 |
|
|
| **포트** | 없음 | 5001 |
|
|
| **통신** | stdio | streamable-http |
|
|
| **핵심 기능** | RAG 검색 (Qdrant + LLM) | NL2SQL + 히스토리 쿼리 |
|
|
| **실행 메서드** | `mcp.run(transport="stdio")` | `mcp.run(transport="streamable-http")` |
|
|
| **상태** | ✅ 정상 실행 | ✅ 정상 실행 |
|
|
| **진단** | -- | 호환성 해결 완료 |
|
|
|
|
### Service Dependencies 비교
|
|
|
|
| 서비스 | ExperionCrawler | Text-to-SQL-AX | 포트 |
|
|
|--------|----------------|----------------|------|
|
|
| Qdrant | ✅ 사용 | ✅ 사용 | 6333 |
|
|
| Ollama | ✅ 사용 | ✅ 사용 | 11434 |
|
|
| vLLM | ✅ 사용 | ✅ 사용 | 8000 |
|
|
| PostgreSQL | ❌ 미사용 | ✅ 사용 | 5432 |
|
|
|
|
### 구성 차이 예시
|
|
|
|
#### ExperionCrawler MCP (빠진 부분)
|
|
|
|
```python
|
|
# server.py:28-31
|
|
COL_CODEBASE = "ws-65f457145aee80b2"
|
|
COL_OPC_DOCS = "experion-opc-docs"
|
|
|
|
mcp = FastMCP("iiot-rag")
|
|
|
|
# server.py:169
|
|
if __name__ == "__main__":
|
|
mcp.run(transport="stdio")
|
|
```
|
|
|
|
#### Text-to-SQL-AX MCP (현재 구현)
|
|
|
|
```python
|
|
# server.py:30-37
|
|
COL_CODEBASE = "ws-65f457145aee80b2"
|
|
COL_OPC_DOCS = "experion-opc-docs"
|
|
|
|
mcp = FastMCP(
|
|
"iiot-rag",
|
|
port=5001,
|
|
json_response=True,
|
|
stateless_http=True,
|
|
)
|
|
|
|
# server.py:442
|
|
def main():
|
|
mcp.run(transport="streamable-http")
|
|
```
|
|
|
|
**NL2SQL 도구 추가** ([`run_sql`](~/projects/Text-to-SQL-AX/mcp-nl2sql-server/server.py:397-424), [`search_tags_by_name`](~/projects/Text-to-SQL-AX/mcp-nl2sql-server/server.py:406-434), [`list_drawings`](~/projects/Text-to-SQL-AX/mcp-nl2sql-server/server.py:438-457))
|
|
|
|
---
|
|
|
|
## 실행 오류 진단
|
|
|
|
### 오류 상세
|
|
|
|
```
|
|
File: server.py:453
|
|
mcp.run(transport="streamable-http", host="0.0.0.0", port=5001)
|
|
|
|
TypeError: FastMCP.run() got an unexpected keyword argument 'host'
|
|
```
|
|
|
|
### 원인 분석
|
|
|
|
1. **파라미터 위치 오류**
|
|
- `host`, `port`, `json_response`, `stateless_http`는 `FastMCP.__init__()`의 파라미터임
|
|
- `run()` 메서드의 실제 시그니처는 `transport`와 `mount_path`만 받음
|
|
- 즉 파라미터가 제거된 것이 아니라 `run()`이 아닌 생성자에 전달해야 함
|
|
|
|
2. **실제 `run()` 시그니처**
|
|
```python
|
|
# 설치된 FastMCP run() 실제 시그니처
|
|
def run(self,
|
|
transport: Literal["stdio", "sse", "streamable-http"] = "stdio",
|
|
mount_path: str | None = None) -> None: ...
|
|
|
|
# 실제 호출 (오류) — host, port는 run()에 없음
|
|
mcp.run(transport="streamable-http", host="0.0.0.0", port=5001)
|
|
```
|
|
|
|
3. **올바른 파라미터 위치**
|
|
```python
|
|
# host, port, json_response, stateless_http 는 FastMCP() 생성자에 전달
|
|
mcp = FastMCP(
|
|
"iiot-rag",
|
|
port=5001, # ✅ __init__에서 설정
|
|
json_response=True, # ✅ __init__에서 설정
|
|
stateless_http=True, # ✅ __init__에서 설정
|
|
)
|
|
# run()에는 transport만 전달
|
|
mcp.run(transport="streamable-http")
|
|
```
|
|
|
|
### 수정 방법
|
|
|
|
`server.py` 453행의 `run()` 호출에서 `host`와 `port`를 제거한다.
|
|
`port=5001`, `json_response`, `stateless_http`는 이미 생성자에 올바르게 설정되어 있으므로 추가 변경 불필요.
|
|
|
|
```python
|
|
# 수정 전 (오류)
|
|
mcp.run(transport="streamable-http", host="0.0.0.0", port=5001)
|
|
|
|
# 수정 후 (정상)
|
|
mcp.run(transport="streamable-http")
|
|
```
|
|
|
|
---
|
|
|
|
## 사용 예시
|
|
|
|
```bash
|
|
# 서버 실행
|
|
cd ~/projects/Text-to-SQL-AX/mcp-nl2sql-server
|
|
python server.py
|
|
|
|
# 테스트
|
|
curl http://localhost:5001/mcp
|
|
curl http://localhost:5001/health
|
|
```
|
|
|
|
---
|
|
|
|
## 참고 자료
|
|
|
|
- [FastMCP GitHub Repository](https://github.com/jlowin/mcp-py)
|
|
- [MCP (Model Context Protocol) 문서](https://modelcontextprotocol.io/)
|
|
- [C# McpClient 구현](../../src/Infrastructure/Mcp/McpClient.cs)
|
|
- [경쟁 처리 하려니도덕성 문제](https://en.wikipedia.org/wiki/Pigovian_tax) — 참고용 |