Skip to main content
Glama
JooSeunghyeon

kookmin-stock

README.md
# 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

A3.8/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: fundamentals, market overview, news, stock quote, top gainers, and a composite recommendation. No overlap or ambiguity.

Naming Consistency4/5

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.

Tool Count5/5

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.

Completeness4/5

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.

Maintenance

ActivityInactive
ResponsivenessNo issues