kookmin-stock
# 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).
```bash
python -m venv .venv
source .venv/bin/activate
pip install -e .
```
## ▶️ 실행
```bash
# 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`에 타임코드별 행동이 정리돼 있다.
가장 단순한 경로:
```bash
./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_gainers` description을 "하락률 상위"로 잘못 적음 → 모델 오선택
- `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 CSV
- `results/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()`만 채우면 된다.
```python
# 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 설정에 추가:
```json
{
"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`는 슬라이드 노트 영역에 넣어줘.
## 📤 제출 흐름
1. `python -m experiments.exp2_quality && python -m experiments.exp3_orchestration` 으로 결과 갱신
2. `./demo/record_demo.sh` 로 30초 데모 녹화 → `demo/demo.mov`
3. GitHub push (저장소 URL을 README와 slide 6에 기록)
4. 이메일 `kts123@kookmin.ac.kr` 로 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는 마지막 종가를 그대로 반환 |
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: fundamentals, market overview, news, stock quote, top gainers, and a composite recommendation. No overlap or ambiguity.
Most tools follow a 'get_' prefix verb_noun pattern (e.g., get_fundamentals, get_market_overview). The exception is recommend_buys, which is still verb_noun but lacks the prefix, creating a minor inconsistency.
With 6 tools covering fundamental data, market overview, news, quotes, top gainers, and a recommend feature, the count is well-scoped for a stock information server.
The tool surface covers core stock information needs (fundamentals, quotes, news, top gainers, overview, and a composite recommendation). Minor gaps like historical prices or sector data are not critical for the stated purpose.