한 줄 요약
vitali87/code-graph-rag는 Tree-sitter로 멀티언어 코드를 구조적으로 분석하고, Memgraph 지식 그래프와 선택형 벡터 검색을 결합해 코드베이스를 질의·이해·편집하는 Python 기반 RAG/에이전트 도구다.[1][2]
단순 임베딩 검색만 제공하는 프로젝트가 아니라, 함수·클래스·모듈·호출·상속·import·I/O 리소스 사이의 관계를 그래프로 보존한 뒤 자연어 질문을 Cypher로 바꾸고, 그래프 결과에서 실제 소스 코드를 회수하는 구조가 중심이다.[2]
조사 기준과 저장소 현황
- 저장소:
vitali87/code-graph-rag[1] - 조사 기준:
main의 고정 커밋234816efbe6c21a4245eff30e107187c98b2656b—chore: bump version to 0.0.591.[2] - 코드에 선언된 버전:
0.0.591; 조사 시점 GitHub 최신 published release는v0.0.589였다.[2][3] - 라이선스: MIT.[1][2]
- GitHub 조회값: 별 3,160개, fork 527개, open issue 24개, 기본 브랜치
main, 주요 언어 Python.[1] - 프로젝트 홈페이지: code-graph-rag.com.[1]
- 조사 시점: 2026-08-10 14:36 KST.[2]
현재 HEAD의 버전은 최신 published release 태그보다 앞서 있다. 따라서 설치·배포 시 PyPI/릴리스 자산을 사용할지, 고정 커밋을 직접 checkout할지 먼저 결정해야 하며, 아래 보안 수정이 포함된 버전을 선택해야 한다.[2][3]
해결하려는 문제
대규모 monorepo에서는 grep이나 단순 벡터 검색만으로는 “이 함수가 어디서 호출되는가”, “이 클래스의 구현·상속·override는 무엇인가”, “이 모듈이 어떤 외부 리소스를 읽고 쓰는가”를 안정적으로 연결하기 어렵다. 이 프로젝트는 AST 구조와 실행 의미에 가까운 관계를 지식 그래프로 저장해 검색 단위를 파일·심볼·관계로 확장한다.[1][2]
프로젝트가 제공하는 기본 흐름은 다음과 같다.[2]
소스 코드
→ Tree-sitter 파싱
→ 정의·참조·호출·상속·import 관계 추출
→ Memgraph 지식 그래프 저장
→ 자연어 질문을 Cypher로 변환
→ 그래프 결과에서 코드 스니펫 회수
→ 모델 응답 또는 승인된 코드 편집아키텍처
파서와 그래프 구축
파서는 Tree-sitter 기반이며, 언어마다 다른 AST를 공통 그래프 스키마로 매핑한다. GraphUpdater는 파일 해시 캐시를 이용해 전체 재색인과 변경 파일 중심의 incremental update를 구분하고, Memgraph에 노드·엣지를 일괄 반영한다.[2]
기본 그래프는 프로젝트·패키지·폴더·파일·모듈을 계층으로 두고, 그 아래 클래스·함수·메서드·인터페이스·enum·타입 등을 연결한다. 중첩 함수와 함수 내부 클래스도 상위 scope에 DEFINES로 연결되며, 중복 qualified name은 시작 줄 suffix를 붙여 별도 노드로 보존한다.[2]
질의와 RAG
RAG 계층은 PydanticAI 기반 orchestrator와 Cypher 생성기를 분리한다. 사용자의 자연어 질문을 그래프 질의로 변환하고, 결과 심볼의 파일·줄 범위·소스 내용을 읽어 모델이 관계와 실제 구현을 함께 설명하도록 한다.[2]
orchestrator 모델과 Cypher 모델은 서로 다른 provider를 사용할 수 있다. 저장소 문서는 Google·OpenAI·Anthropic·Azure·Ollama·MiniMax·LiteLLM proxy와 혼합 구성을 지원하며, 로컬 Ollama를 사용할 경우 API 비용 없이 운영할 수 있지만 정확도가 낮아질 수 있다고 설명한다.[2]
그래프 스키마
주요 노드
| 범주 | 노드 예시 | 의미 |
|---|---|---|
| 저장소 구조 | Project, Package, Folder, File, Module | 프로젝트와 파일 시스템·모듈 계층 |
| 정의 | Class, Function, Method, Interface, Enum, Type, Union | 언어별 선언과 callable |
| 외부 경계 | ExternalPackage, ExternalModule | 저장소 밖의 stdlib·third-party 모듈·패키지 |
| 분석 결과 | Pattern, CodeSmell, SecurityIssue | 선택형 ast-grep findings |
| 데이터 흐름 | Resource | 파일·환경변수·네트워크·DB·표준 스트림 등 외부 I/O 대상 |
주요 관계
DEFINES,DEFINES_METHOD: 모듈·scope와 정의의 containment.[2]IMPORTS,EXPORTS,DEPENDS_ON_EXTERNAL: 모듈·패키지 의존 관계.[2]INHERITS,IMPLEMENTS,OVERRIDES: 타입·상속·override 관계.[2]CALLS,REFERENCES,INSTANTIATES: 호출·비호출 참조·생성 관계.[2]READS_FROM,WRITES_TO,FLOWS_TO: 외부 리소스 접근과 보수적인 데이터 흐름.[2]IMPLEMENTS_PATTERN,HAS_SMELL,HAS_VULNERABILITY: 선택형 분석 결과 연결.[2]
calls 계열은 기본 캡처에 포함되지만 io와 findings는 선택형 capture group이다. io는 환경변수 읽기나 stdout 쓰기 같은 리소스 접근을 모델링하며, FLOWS_TO는 resource→resource, caller→callee argument, callee→caller return의 세 형태로 값 흐름을 표현한다. 저장소 문서도 이 흐름 분석을 보수적·제한적 단계로 설명한다.[2]
지원 언어
문서상 완전 지원 언어는 다음 13개다.[2]
- C.[2]
- C#.[2]
- C++.[2]
- Dart.[2]
- Go.[2]
- Java.[2]
- JavaScript.[2]
- Lua.[2]
- PHP.[2]
- Python.[2]
- Rust.[2]
- TypeScript.[2]
- TypeScript/TSX.[2]
Scala는 함수·클래스·객체·trait를 파싱하는 개발 중 상태로 분류된다. 모든 언어가 동일한 그래프 스키마를 공유하므로 polyglot repository에서도 같은 방식으로 질의할 수 있지만, 언어별 parser grammar와 semantic frontend 설치 여부에 따라 분석 깊이는 달라진다.[2]
C/C++는 Tree-sitter를 기반으로 libclang을 추가하는 hybrid 모드를 제공하고, C#은 dotnet이 있으면 Roslyn 기반 semantic facts를 추가한다. 이 보강 계층이 없으면 Tree-sitter 휴리스틱으로 낮춰 동작한다.[2]
CLI·SDK·MCP 표면
CLI와 daemon
패키지는 code-graph-rag와 cgr 두 CLI entry point를 제공한다. 설치 후 일반적인 흐름은 cgr daemon up으로 Memgraph·Qdrant stack을 시작하고, .env를 설정한 뒤 cgr doctor로 의존성과 서비스 상태를 확인하는 방식이다.[2]
CLI에는 repository index/update, 자연어 query, graph export, dead-code 분석, MCP server, 설정·진단과 같은 운영 표면이 포함된다. cgr daemon up은 패키지에 포함된 compose 파일로 Memgraph와 Qdrant를 시작하며, 문서상 Memgraph는 7687, Memgraph Lab은 3000 포트를 사용한다.[2]
MCP 서버
프로젝트는 같은 코드 이해·편집 기능을 MCP 서버로 노출한다. 기본 transport는 stdio이며, Streamable HTTP도 지원한다.[2]
MCP 도구 범주는 다음과 같다.[2]
- 프로젝트 목록·삭제·DB wipe.[2]
- repository index/update.[2]
- 자연어 code-graph query.[2]
- qualified name 기반 코드 스니펫 조회.[2]
- 파일 읽기·쓰기·디렉터리 목록.[2]
- surgical code replacement.[2]
- shell command.[2]
- ast-grep 기반 structural search/replace.[2]
- 선택형 semantic search.[2]
MCP 서버는 시작할 때 대상 repository root를 환경변수 또는 현재 작업 디렉터리에서 결정하고, 프로젝트 이름을 파생해 다른 프로젝트의 graph query와 섞이지 않도록 scope를 제한한다. 또한 orchestrator·Cypher 모델 설정을 startup 단계에서 검증하고 Memgraph 연결을 연다.[2]
HTTP MCP는 기본적으로 127.0.0.1:8080/mcp에 묶인다. loopback 밖에 bind하려면 bearer token이 반드시 있어야 하며, token이 설정되면 loopback에서도 Authorization header를 검사한다. 이는 인증 없는 Streamable HTTP endpoint를 실수로 LAN에 노출하는 것을 막는 방어선이다.[2]
검색 기능
그래프 검색
그래프 검색의 강점은 이름이 같은 함수나 단순 텍스트 일치가 아니라, 파일·scope·호출자·callee·상속·import 관계를 함께 사용한다는 점이다. CALLS, INSTANTIATES, REFERENCES를 통해 “어떤 파일을 열어야 하는가”에 가까운 검색 결과를 만들 수 있다.[2]
semantic search
semantic search는 기본 의존성이 아니라 선택형 extra다. qdrant-client, torch, transformers를 설치해 UniXcoder 기반 임베딩을 사용할 수 있고, vector result를 graph context와 함께 활용하는 구성이 제공된다. 따라서 작은 환경에서는 그래프·소스 검색만 설치하고, 의미 검색이 필요한 경우에만 무거운 ML 의존성을 추가하는 선택이 가능하다.[2]
dead code·data flow
그래프의 정의·호출·override 관계를 이용해 참조되지 않는 함수·클래스·메서드 후보를 찾고, io capture를 켜면 외부 리소스의 read/write와 흐름을 분석할 수 있다. 다만 dead-code 판정과 정적 data-flow는 reflection·동적 import·런타임 생성처럼 정적 그래프가 볼 수 없는 행위를 완전히 증명하는 기능이 아니라 후보를 좁히는 분석이다.[2]
편집과 승인 경계
코드 읽기·쓰기·surgical replace·structural replace·shell command까지 에이전트 도구로 제공되므로, 이 프로젝트는 검색기라기보다 코드 작업면에 가깝다. 파일 경로는 프로젝트 root 안으로 검증하고, 파일 생성·파일 전체 교체·구조적 replace는 requires_approval=True로 표시된다.[2]
shell command도 기본적으로 명령 위험도를 분류해 승인을 요구하며, 별도 yolo 모드가 아닌 경우 승인되지 않은 위험 명령을 실행하지 않는 흐름을 갖는다. DB wipe처럼 되돌리기 어려운 MCP 동작은 confirm 인자를 요구한다.[2]
운영 시에는 MCP 서버를 신뢰할 수 있는 저장소에만 연결하고, 쓰기·shell·DB 삭제 도구를 최소 권한 계정과 명시적 승인 흐름 아래 두는 것이 안전하다. MCP HTTP를 외부 bind할 때 bearer token을 사용하더라도 네트워크 ACL과 reverse proxy 인증을 추가하는 편이 좋다.[2]
보안 업데이트와 현재 보안 판단
v0.0.589 릴리스는 ast-grep의 structural_search·structural_replace 경로에서 symlink를 따라 프로젝트 root 밖 파일을 읽거나 덮어쓸 수 있었던 path-containment escape를 수정했다. GitHub 보안 공지는 GHSA-85gg-2gfq-q95m, CWE-22/CWE-59, CVSS 7.1을 언급하며 <=0.0.588이 영향을 받고 0.0.589에서 패치됐다고 기록한다.[3]
현재 고정 HEAD v0.0.591의 should_skip_path와 프로젝트 경로 검증은 실제 경로를 resolve()한 뒤 repository root와의 상대 경로 여부를 확인한다. 이 수정이 MCP와 agent 양쪽의 structural search/replace에 영향을 주므로, 신뢰하지 않는 저장소를 다룰 때는 최소한 0.0.589 이상을 사용해야 한다.[2][3]
HTTP MCP의 loopback 기본값과 non-loopback bearer-token 강제도 같은 보안 경계의 일부다. 그러나 shell command와 파일 편집은 본질적으로 고권한 기능이므로, 패치 버전 사용만으로 안전한 sandbox가 제공된다고 해석해서는 안 된다.[2]
설치·운영 요구사항
저장소 문서가 요구하는 기본 조건은 다음과 같다.[2]
- Python 3.12 이상.[2]
- Docker 및 Docker Compose.[2]
cmake—pymgclient빌드에 필요.[2]ripgrep— shell command text search에 필요.[2]- cloud provider API key 또는 실행 중인 Ollama.[2]
uv또는pip.[2]
기본 설치는 uv sync, 전체 Tree-sitter grammar는 uv sync --extra treesitter-full, semantic search는 semantic extra를 사용한다. release binary에는 Sigstore 서명과 SLSA provenance attestation을 제공하며, 문서는 gh attestation verify와 cosign verify-blob 예시를 함께 제시한다.[2]
저장소 자체 평가 신호
저장소는 evals/에 Memgraph 없이 동작하는 in-memory evaluation harness를 포함한다. L1은 구조·containment, L2는 module-call attribution, L3는 실행 추적 기반 CALLS recall, 별도 retrieval 평가는 graph·grep·AST oracle을 비교한다.[2]
저장소가 기록한 django/django 약 2,900파일의 file-level retrieval 결과는 graph precision 0.977, recall 0.938, F1 0.957, grep_call F1 0.789, grep_name F1 0.506이다. 이는 프로젝트가 제공한 자체 benchmark 결과이지 이번 조사에서 독립 재현한 수치는 아니며, property-aware oracle과 name collision 같은 평가 한계도 문서에 적혀 있다.[2]
이번 조사에서 수행한 검증
- 고정 clone:
mainHEAD234816efbe6c21a4245eff30e107187c98b2656b; 작업 트리 clean. - Python 3.12.3로
compileall을 실행해codebase_rag,codec,cgr,evals, scripts와 examples의 구문 검사를 통과했다. uvx pygount로 저장소 규모를 측정했고, Python 972개 파일·148,483 code lines를 포함해 1,167개 스캔 파일에서 155,342 code lines가 집계됐다.git diff --check는 통과했다.- 테스트 실행은
uv lock으로 246개 패키지 해석까지 진행됐지만,pymgclientwheel build 단계에서 호스트에cmake가 없어 중단됐다. 따라서 이번 조사에서는 pytest 통과를 주장하지 않는다. - Docker/Memgraph/Qdrant와 실제 provider를 띄우지 않았으므로 graph indexing·MCP end-to-end·semantic retrieval 실행은 검증하지 않았다.
Python 3.11에서의 구문 검사는 프로젝트가 요구하는 3.12 전용 문법(type 별칭과 제네릭 함수 표기) 때문에 실패했으며, 3.12로 재실행한 구문 검사는 성공했다. 이는 코드 실패가 아니라 실행 인터프리터 불일치다.[2]
평가와 활용 판단
강점
- AST와 관계를 공통 graph schema로 보존해 grep·순수 vector search보다 구조적 질문에 강하다.[2]
- 13개 언어의 공통 모델, C/C++ libclang hybrid, C# Roslyn 보강, incremental update를 한 프로젝트 안에 묶었다.[2]
- 자연어 query, source retrieval, semantic search, dead-code·data-flow, MCP, 승인형 편집을 같은 repository context에 연결한다.[2]
- 현재 스냅샷은 0.0.589의 고위험 symlink 경로 문제를 지난 버전이므로, 오래된 release보다 안전한 출발점이다.[2][3]
트레이드오프
- Memgraph와 Docker가 핵심 런타임이고, 모델 설정도 필요해 단순
ripgrep대체보다 운영 비용이 높다.[2] pymgclient빌드에cmake가 필요하며, semantic extra는 PyTorch·Transformers·Qdrant 때문에 무겁다.[2]- 정적 그래프와 data-flow는 동적 import·reflection·생성 코드의 일부를 놓칠 수 있고, incremental update의 정확성은 별도 평가 대상이다.[2]
- MCP가 파일 쓰기와 shell까지 노출하므로, 승인·sandbox·최소권한 없이 장시간 unattended 실행하기에는 위험하다.[2][3]
Hermes Agent와의 연결 가능성
code-graph-rag는 stdio MCP 서버를 제공하므로 Hermes Agent에 MCP 서버로 붙일 수 있는 형태다. 다만 Hermes 설정만으로 끝나는 통합이 아니라, 별도의 Python 3.12 환경·Memgraph/Qdrant stack·대상 repository root·orchestrator/Cypher provider 설정이 모두 필요하다. 실제 연결을 시도할 때는 먼저 read/query 도구만 허용하고, write/shell/DB wipe는 승인 가능한 별도 profile로 분리하는 것이 적절하다.[2]
결론
code-graph-rag는 “코드베이스를 임베딩해 검색하는 도구”보다 그래프를 정본으로 두고 LLM·MCP·편집 도구를 그 위에 올린 코드 이해 실행면에 가깝다. Hermes Agent와 결합할 경우 MCP를 통해 코드 그래프 질의와 source retrieval을 보강할 수 있지만, Memgraph 운영과 모델 비용·쓰기 권한 관리가 도입 장벽이다.[2]
실사용 전 최소 기준은 0.0.589 이상 고정, Python 3.12 환경, cmake 설치, loopback MCP 또는 bearer-token HTTP, read-only 첫 단계, 그리고 실제 대상 repository에서 graph freshness와 query 품질을 별도 검증하는 것이다.[2][3]
Sources
[1] https://github.com/vitali87/code-graph-rag — vitali87/code-graph-rag repository [2] https://github.com/vitali87/code-graph-rag/tree/234816efbe6c21a4245eff30e107187c98b2656b — code-graph-rag fixed snapshot at 234816ef [3] https://github.com/vitali87/code-graph-rag/releases/tag/v0.0.589 — code-graph-rag v0.0.589 security release