테이블 조인해서 가져와 보자.
import sqlite3
import os
def init_advanced_db():
db_path = 'enterprise.db'
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# 테이블 초기화 (기존 데이터 삭제 후 재생성)
cursor.execute('DROP TABLE IF EXISTS projects')
cursor.execute('DROP TABLE IF EXISTS employees')
cursor.execute('DROP TABLE IF EXISTS departments')
# 1. 부서 테이블 (부서명, 예산)
cursor.execute('CREATE TABLE departments (dept_id INTEGER PRIMARY KEY, dept_name TEXT, budget INTEGER)')
# 2. 사원 테이블 (사원번호, 성함, 부서명, 직급) - 제공해주신 형식
cursor.execute('CREATE TABLE employees (emp_id INTEGER PRIMARY KEY, name TEXT, dept_name TEXT, position TEXT)')
# 3. 프로젝트 테이블 (프로젝트명, 담당 사원번호)
cursor.execute('CREATE TABLE projects (proj_id INTEGER PRIMARY KEY, proj_name TEXT, lead_emp_id INTEGER)')
# 데이터 삽입 (제공해주신 사원 정보 기준)
departments = [(1, '개발팀', 8000), (2, '인사팀', 3000), (3, 'UI팀', 5000)]
employees = [
(101, '이개발', '개발팀', '대리'),
(102, '김인사', '인사팀', '과장'),
(103, '박디자', 'UI팀', '사원')
]
projects = [
(501, '차세대 ERP 구축', 101),
(502, '모바일 앱 개편', 103)
]
cursor.executemany('INSERT INTO departments VALUES (?,?,?)', departments)
cursor.executemany('INSERT INTO employees VALUES (?,?,?,?)', employees)
cursor.executemany('INSERT INTO projects VALUES (?,?,?)', projects)
conn.commit()
conn.close()
print(f"데이터 정합성 완료: {os.path.abspath(db_path)}")
if __name__ == "__main__":
init_advanced_db()
import sqlite3
import os
import sys
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("AdvancedDataAgent")
DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "enterprise.db")
@mcp.tool()
def get_project_and_dept_info(project_name: str) -> str:
"""프로젝트명을 입력받아 담당자(직급 포함)와 해당 부서의 예산을 조회합니다."""
try:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# 3중 Join: Projects -> Employees -> Departments
query = """
SELECT p.proj_name, e.name, e.position, e.dept_name, d.budget
FROM projects p
JOIN employees e ON p.lead_emp_id = e.emp_id
JOIN departments d ON e.dept_name = d.dept_name
WHERE p.proj_name LIKE ?
"""
cursor.execute(query, (f"%{project_name}%",))
result = cursor.fetchone()
conn.close()
if result:
p_name, e_name, pos, d_name, budget = result
return (f"[{p_name}] 프로젝트 상세 리포트\n"
f"- 담당자: {e_name} {pos}\n"
f"- 소속 부서: {d_name}\n"
f"- 부서 가용 예산: {budget}만원")
else:
return f"'{project_name}' 프로젝트에 대한 정보를 찾을 수 없습니다."
except Exception as e:
return f"데이터 조회 오류: {str(e)}"
if __name__ == "__main__":
# 서버 실행 시 시동 확인 로그 (stderr)
print("--- Enterprise Join Agent Online ---", file=sys.stderr)
mcp.run()
"adv-db-agent": {
"command": "C:/dev/llm/llm_env/Scripts/python.exe",
"args": ["C:/dev/llm/join_server.py"]
}
질문: "차세대 ERP 프로젝트 담당자가 누구야? 그 팀 예산은 얼마인지도 알려줘."
기대 답변: "차세대 ERP 구축 프로젝트의 담당자는 이개발 대리이며, 소속된 개발팀의 예산은 8,000만원입니다."


포인트
데이터 매핑: projects에는 사원 번호(101)만 있지만, 조인을 통해 이개발이라는 이름과 대리라는 직급을 찾아오는 과정을 설명하세요.
비즈니스 로직의 추상화: 신입사원들에게 "사용자는 SQL 조인문을 몰라도 '예산'과 '담당자'를 동시에 물어볼 수 있고, 에이전트가 이를 해석해 기술(Tool)을 사용한다"는 점을 강조하세요.
예외 처리: 만약 '인사팀'이 담당하는 프로젝트를 물어보면(현재 데이터엔 없음), 에이전트가 "해당 프로젝트를 찾을 수 없다"고 정확히 답변하는지 확인하게 하세요.