Kookmin MCP Stock Agent
국민대 과제 · "Hermes + MCP 자작 서버로 임팩트 끌어올리기"
지난 과제에서 만든 국내 주식 추천 Hermes 에이전트에 자작 MCP 서버를 붙여작업 퀄리티가 어떻게 변하는지 3가지 실험으로 증명한다.
🎯 무엇이 들어 있나
| 산출물 | 경로 | 설명 |
|---|---|---|
| MCP 서버 (정상) | src/mcp_stock/server.py |
FastMCP stdio, 도구 6종 |
| MCP 서버 (망가뜨린 버전) | src/mcp_stock/server_broken.py |
잘못된 description / 타임아웃 / 빈 응답 |
| 30초 동작 데모 | src/experiments/exp1_demo.py |
녹화용 시퀀스 출력 |
| 실험 ② 결과 비교 | src/experiments/exp2_quality.py |
NO MCP / GOOD / BROKEN 비교 |
| 실험 ③ 패턴 비교 | src/experiments/exp3_orchestration.py |
Single / Planner+Executor / Parallel |
| 발표 자료(spec) | slides/slides.md |
다른 AI에 그대로 붙여 PPT 생성 |
| 결과 산출물 | results/exp2_*, results/exp3_* |
자동 생성 표·CSV·로그 |
⚙️ 설치
Python 3.10+ (테스트 환경 3.13).
python -m venv .venv
source .venv/bin/activate
pip install -e .
▶️ 실행
# 1) MCP 서버 검증 (서버는 stdio라 호스트가 붙어야 의미 있음 — Ctrl+C로 종료)
python -m mcp_stock.server
# 2) 30초 동작 데모 (실제로 돌려서 녹화)
python -m experiments.exp1_demo
# 또는 ./demo/record_demo.sh
# 3) 실험 ② 성공/실패 비교 → results/exp2_* 자동 생성
python -m experiments.exp2_quality
# 4) 실험 ③ Orchestration 토큰 비교 → results/exp3_* 자동 생성
python -m experiments.exp3_orchestration
🎥 30초 데모 녹화
demo/demo_script.md에 타임코드별 행동이 정리돼 있다.가장 단순한 경로:
./demo/record_demo.sh # QuickTime/Cmd+Shift+5 로 화면 녹화하면서 실행
./demo/record_demo.sh --asciinema # 텍스트 캡처 (asciinema 필요)
🧪 실험 ① — MCP 서버 (도구 6종)
| 도구 | 입력 | 출력 |
|---|---|---|
get_market_overview(date) |
'today' / YYYY-MM-DD | {kospi:{close, changePct, tradingValueKrw}, kosdaq:{...}} |
get_top_gainers(market, top_n) |
KOSPI/KOSDAQ, 1..50 | 상위 N 종목 |
get_stock_quote(ticker) |
코드 또는 한글명 | close / changePct / volume / per / pbr |
get_recent_news(query, top_n) |
키워드 또는 종목명 | 헤드라인 + positivityScore |
get_fundamentals(ticker) |
코드 또는 한글명 | per / pbr / eps / bps / roe |
recommend_buys(market, top_n, criteria) |
KOSPI/KOSDAQ | scoreBreakdown + rationale |
데이터: Naver Finance 크롤링 단일 소스 (src/mcp_stock/sources/naver.py). 무료·키 불필요.
- 지수:
polling.finance.naver.com/api/realtime/domestic/index/{KOSPI|KOSDAQ}JSON - 등락률 상위:
finance.naver.com/sise/sise_rise.naver?sosok={0|1}HTML - 종목 상세 / PER·EPS·PBR·배당:
finance.naver.com/item/main.naver?code=...(안정적인id="_per"등 emphasis 태그) - 종목별 뉴스:
finance.naver.com/item/news_news.naver?code=... - 휴장일 / 네이버 페이지 변경 시 자동 fallback 스냅샷으로 안전 동작.
🧪 실험 ② — Tool 성공/실패 결과 퀄리티 비교
exp2_quality.py가 동일한 사용자 질문을 세 환경으로 돌리고 표·실패 로그를 자동 생성한다.
- (a) NO MCP — 도구 0개. LLM이 학습 데이터로만 답변 → 환각·근거 부재.
- (b) GOOD MCP — 정상 자작 서버. 도구 12회 호출, 4개 호재 키워드 인용.
- (c) BROKEN MCP —
server_broken.py정의대로:get_top_gainersdescription을 "하락률 상위"로 잘못 적음 → 모델 오선택get_recent_news가time.sleep(5)후TimeoutError발생get_fundamentals가 빈 dict 반환
결과:
results/exp2_quality_table.md— 비교 표results/exp2_failure_logs.md— 실패 호출 트레이스 + 답변 본문results/exp2_summary.json— 원본 통계
🧪 실험 ③ — Orchestration 3패턴
| 패턴 | 설명 | 토큰 특성 | 응답시간 특성 |
|---|---|---|---|
| Single | 한 루프 내 도구 결과 누적 | 입력 토큰 ↑↑ | 가장 느림 |
| Planner + Executor | planner가 호출 시퀀스만 짜고 executor는 결과 요약만 | 입력 토큰 ↓ | 중간 |
| Parallel sub-agents | KOSPI / KOSDAQ / NEWS sub-agent 동시 실행 | 입력 토큰 ↓↓ | 가장 빠름 |
결과:
results/exp3_benchmark.csv— 막대그래프 작성용 wide CSVresults/exp3_pattern_table.md— 표 + 회고results/exp3_summary.json— 패턴별 풀 트레이스
🤖 LLM 연동 — Hermes / 다른 호스트
이 저장소는 LLM API 키 없이도 결정적 시뮬레이션으로 토큰·트레이스가 나오도록 만들었다.실제 Hermes / Claude Desktop / Cursor에 붙이려면:
1) Hermes 호스트로 사용 (실험 ②③를 진짜 LLM으로 돌리기)
src/experiments/runner/hermes_runner.py의 _callHermes()만 채우면 된다.
# TODO(user): replace this body with the real Hermes call.
import httpx
response = httpx.post(self.endpoint, headers=..., json=...)
return response.json()
환경변수 HERMES_ENDPOINT, HERMES_API_KEY 설정 후AgentRunner 인스턴스를 HermesRunner()로 교체.
2) Claude Desktop / Cursor에서 도구만 사용
Claude Desktop의 claude_desktop_config.json 또는 Cursor MCP 설정에 추가:
{
"mcpServers": {
"kookmin-stock": {
"command": "python",
"args": ["-m", "mcp_stock.server"],
"cwd": "/path/to/Kookmin-University-MCP",
"env": { "PYTHONPATH": "/path/to/Kookmin-University-MCP/src" }
}
}
}
📑 PPT 만들기
slides/slides.md를 다른 AI에게 그대로 붙여넣으면 된다. 예시 프롬프트:
다음 markdown은 5분 발표용 12장 슬라이드 spec이야.
# Slide N헤더 단위로 PowerPoint 슬라이드를 만들어줘.### Visual블록은 가급적 mermaid 다이어그램이나 표 그대로 표현하고,### Speaker Notes는 슬라이드 노트 영역에 넣어줘.
📤 제출 흐름
python -m experiments.exp2_quality && python -m experiments.exp3_orchestration으로 결과 갱신./demo/record_demo.sh로 30초 데모 녹화 →demo/demo.mov- GitHub push (저장소 URL을 README와 slide 6에 기록)
- 이메일
[email protected]로 GitHub URL + slides + demo 영상 전송 (마감 5/14 23:59:59)
📁 디렉토리 트리
.
├── README.md
├── pyproject.toml / requirements.txt
├── demo/
│ ├── demo_script.md
│ └── record_demo.sh
├── results/ # 자동 생성
├── slides/slides.md
└── src/
├── mcp_stock/
│ ├── server.py
│ ├── server_broken.py
│ ├── data/ticker_map.py
│ ├── sources/naver.py # 네이버 금융 크롤러 (단일 데이터 소스)
│ └── tools/{market, quote, news, fundamentals, recommend}.py
├── experiments/
│ ├── exp1_demo.py
│ ├── exp2_quality.py
│ ├── exp3_orchestration.py
│ └── runner/{agent_base, mock_runner, hermes_runner}.py
└── utils/{logger, token_counter}.py
🛟 트러블슈팅
| 증상 | 원인 | 대응 |
|---|---|---|
naver detail fetch failed for XXXXXX |
네이버 페이지에 해당 종목이 없거나 구조 변경 | 자동 fallback 스냅샷 사용 — 정상 동작 |
httpx.ConnectError |
네트워크 오프라인 | 모든 도구가 fallback 스냅샷으로 안전 동작 |
| 한글 깨짐 | 터미널 폰트 | D2 Coding / Pretendard / SF Mono 권장 |
| 휴장일/주말 호출 | 영업일 아님 | 폴링 API는 마지막 종가를 그대로 반환 |