Skip to main content
Glama
README.md
# hangang-code-graph

한강 조직의 모든 레포지토리 소스코드를 함수 단위로 Neo4j 그래프 DB에 인덱싱하고, MCP 서버를 통해 Graph RAG로 제공하는 시스템입니다.

## 개요

```
[인덱싱]
레포 push → GitHub Actions → 변경 파일 감지 → GPT-4o-mini(자연어 설명 생성)
→ text-embedding-3-small(벡터 임베딩) → Neo4j(그래프 + 벡터 저장)

[쿼리]
사용자 자연어 질문 → MCP 도구 호출
→ 벡터 유사도 검색(seed 함수 탐색) + 의도 기반 엣지 탐색(주변 함수)
→ 원본 소스코드 반환 → LLM 최종 답변
```

## 아키텍처

### 인덱싱 파이프라인

각 레포의 GitHub Actions가 push 시점에 변경된 파일을 직접 읽어 인덱서 서버로 POST합니다. 서버는 파일을 수신한 뒤 함수 단위로 파싱하고, GPT-4o-mini로 자연어 설명을 생성한 뒤 임베딩 벡터와 함께 Neo4j에 저장합니다.

### 그래프 구조

```
(Function)-[:CALLS]->(Function)
(Function)-[:CALLED_BY]->(Function)
(Function)-[:DEFINED_IN]->(File)
```

각 `Function` 노드는 다음을 포함합니다:
- `name`, `repo`, `file_path`, `class_name`
- `code` : 원본 소스코드
- `description` : GPT-4o-mini가 생성한 한국어 자연어 설명
- `embedding` : text-embedding-3-small 벡터 (1536차원)

### MCP 도구

| 도구 | 설명 |
|------|------|
| `search_functions` | 자연어 쿼리와 가장 유사한 함수 검색 (벡터 유사도) |
| `traverse_graph` | 지정 함수 주변을 엣지 타입별로 탐색 |
| `list_edge_types` | 사용 가능한 엣지 타입 목록 반환 |
| `list_repos` | 인덱싱된 레포 목록 반환 |

### 엣지 타입

| 엣지 | 사용 시점 |
|------|-----------|
| `CALLS` | 이 함수가 내부에서 뭘 호출하는지 파악할 때 |
| `CALLED_BY` | 이 함수를 누가 쓰는지, 수정 시 영향 범위 파악할 때 |
| `DEFINED_IN` | 소속 파일/클래스 파악할 때 |

## 디렉토리 구조

```
hangang-code-graph/
├── src/
│   ├── indexing/
│   │   ├── parser.py          # Python/TS/JS/Kotlin AST 파서
│   │   ├── nl_generator.py    # GPT-4o-mini 자연어 설명 생성
│   │   ├── embedder.py        # text-embedding-3-small 임베딩
│   │   ├── graph_writer.py    # Neo4j 노드/엣지 저장
│   │   └── pipeline.py        # 인덱싱 오케스트레이터
│   ├── mcp/
│   │   └── server.py          # FastMCP 서버 (MCP 도구 정의)
│   └── webhook/
│       └── handler.py         # FastAPI 인덱서 엔드포인트
├── cypher/
│   └── schema.cypher          # Neo4j 인덱스/제약조건 초기화
├── github-actions-template/
│   └── index-code.yml         # 각 레포에 복사할 Actions 워크플로우
├── Dockerfile
├── docker-compose.yml         # 로컬 개발용 (Neo4j 포함)
└── .env.example
```

## 설치 및 실행

### 환경변수 설정

```bash
cp .env.example .env
# .env 파일에 키 입력
```

| 변수 | 설명 |
|------|------|
| `OPENAI_API_KEY` | OpenAI API 키 |
| `NEO4J_URI` | Neo4j 접속 URI (예: `bolt://localhost:7687`) |
| `NEO4J_USERNAME` | Neo4j 사용자명 |
| `NEO4J_PASSWORD` | Neo4j 비밀번호 |
| `INDEX_API_TOKEN` | GitHub Actions에서 인덱서 호출 시 사용하는 Bearer 토큰 |

### 로컬 실행 (Docker Compose)

```bash
docker-compose up
```

Neo4j 브라우저: http://localhost:7474

### Neo4j 스키마 초기화

```bash
# Neo4j 실행 후 한 번만 실행
cat cypher/schema.cypher | cypher-shell -u neo4j -p <password>
```

### MCP 서버 단독 실행

```bash
pip install -r requirements.txt
python -m src.mcp.server
```

## Claude Code(MCP)에 연결하기

서버가 실행 중일 때 Claude Code에서 다음 명령어로 MCP를 등록합니다.

```bash
claude mcp add hangang-code-graph http://<EC2_IP>:8000/mcp
```

등록 후 Claude Code를 재시작하면 MCP 도구가 활성화됩니다. 대화 창에서 아래 프롬프트를 그대로 사용할 수 있습니다.

---

### 추천 프롬프트

**코드 검색**
```
hangang-code-graph에서 "인증 토큰 발급" 관련 함수를 찾아줘
```

**영향 범위 파악**
```
hangang-code-graph에서 process_set_quality 함수를 수정하면 어디에 영향이 가?
CALLED_BY 엣지를 따라 호출 체인을 보여줘
```

**구현 탐색**
```
hangang-code-graph에서 rep 카운팅 로직이 어디에 구현돼 있어?
관련 함수 코드도 같이 보여줘
```

**레포 전체 구조 파악**
```
hangang-code-graph에 인덱싱된 레포 목록이랑,
각 레포에서 함수가 몇 개인지 알려줘
```

---

> **팁**: 프롬프트에 `hangang-code-graph에서`를 명시하면 Claude가 MCP 도구를 우선적으로 사용합니다.

## 각 레포에 CI/CD 추가하기

`github-actions-template/index-code.yml`을 복사해서 각 레포의 `.github/workflows/index-code.yml`에 넣습니다.

GitHub 레포 **Settings → Secrets and variables → Actions**에 다음을 추가합니다:

| Secret | 값 |
|--------|----|
| `MCP_INDEX_URL` | 인덱서 서버 주소 (예: `http://1.2.3.4:8000`) |
| `MCP_INDEX_TOKEN` | `.env`의 `INDEX_API_TOKEN`과 동일한 값 |

이후 `main` 또는 `master` 브랜치에 push하면 변경된 소스파일이 자동으로 인덱싱됩니다.

## 기술 스택

| 역할 | 기술 |
|------|------|
| 그래프 DB | Neo4j 5.x Community + GDS 플러그인 |
| 자연어 생성 | GPT-4o-mini |
| 임베딩 | text-embedding-3-small (1536차원) |
| MCP 서버 | FastMCP (Python) |
| 인덱서 서버 | FastAPI + uvicorn |
| 지원 언어 | Python, TypeScript, JavaScript, Kotlin |