hangang-code-graph
by asm-hangang
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 |
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing