나는 당신의 코드를 이해하고 70% 토큰을 절약하는 작은 MCP를 만들었습니다
Source: Dev.to
(번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.)
Source: …
소개
모든 코딩‑에이전트 데모는 마법처럼 보이지만… 실제 코드베이스에 적용하면 상황이 달라집니다. 그때는 보통 다음과 같은 문제가 발생합니다:
- 컨텍스트 윈도우에 걸리다
- 오래된 코드를 두고 환각을 일으키다
- 너무 느려져서 그냥
grep을 쓰는 것이 낫다
저는 대규모 Rust, Python, TypeScript 레포지토리로 AI 워크플로를 구축하면서 이 벽에 부딪혔고, 그래서 제 스택에 딱 맞는 것을 직접 만들었습니다: 코드베이스에서 바로 작동하는 초경량 AST‑기반 임베디드 MCP. 이름은 cocoindex‑code이며, 이미 토큰을 약 70 % 절감하고 대기 시간을 크게 줄여주고 있습니다.
Claude, Codex, Cursor, 혹은 MCP‑친화적인 코딩 에이전트를 사용하고 있다면, 이 글이 바로 당신을 위한 것입니다.
왜 cocoindex‑code는 다를까
전형적인 “코드 RAG” 설정은 인프라 프로젝트처럼 느껴집니다: 벡터 DB를 띄우고, ETL 파이프라인을 작성하고, 스키마 드리프트와 싸우고, 청크링을 튜닝하고, 워커를 유지보수하고, 모든 것이 동기화된 상태를 기도하듯 바라보는 것이죠.
cocoindex‑code는 정반대 접근 방식을 취합니다:
| 기능 | 설명 |
|---|---|
| Embedded MCP | 별도의 DB 없이 로컬에서 MCP 서버로 실행됩니다. |
| AST‑based indexing | Tree‑sitter를 사용해 코드 구조를 이해하고, 무작위 200줄 창이 아니라 의미 있는 청크(함수, 클래스, 블록)를 제공합니다. |
| Incremental updates | Rust 기반 CocoIndex 엔진 위에 구축되어 변경된 파일만 다시 색인합니다. |
| Multi‑language support | Python, JavaScript/TypeScript, Rust, Go, Java, C/C++, C#, SQL, Shell 등 다양한 언어를 지원합니다. |
| Local embeddings by default | sentence‑transformers/all‑MiniLM‑L6‑v2를 로컬에서 SentenceTransformers를 통해 사용합니다. |
| Optional power‑ups | LiteLLM이 지원하는 어떤 임베딩 모델이라도 교체 가능 (OpenAI, Gemini, Mistral, Voyage for code, Ollama 등). |
목표: 에이전트에게 질문을 하면 필요한 코드를 정확히 찾아서, 컨텍스트 창을 폭발시키지 않고 제공하는 것입니다.
설치
먼저 uv가 아직 설치되지 않았다면 설치하세요:
curl -LsSf https://astral.sh/uv/install.sh | sh
선호하는 에이전트(Claude, Codex 등)에 MCP를 추가합니다:
claude mcp add cocoindex-code \
-- uvx --prerelease=explicit --with \
"cocoindex>=1.0.0a16" \
cocoindex-code@latest
codex mcp add cocoindex-code \
-- uvx --prerelease=explicit --with \
"cocoindex>=1.0.0a16" \
cocoindex-code@latest
또는 대화형으로 수행합니다:
opencode mcp add
# MCP server name: cocoindex-code
# type: local
# command:
# uvx --prerelease=explicit --with cocoindex>=1.0.0a16 cocoindex-code@latest
이것으로 끝입니다. 에이전트를 저장소에 연결하면 이제 MCP 도구로 코드베이스에 대한 의미 검색을 사용할 수 있습니다.
검색 도구 사용하기
연결이 완료되면 MCP는 search 도구를 제공합니다:
search(
query: str, # 자연어 또는 코드 스니펫
limit: int = 10, # 1‑100
offset: int = 0, # 페이지네이션
refresh_index: bool = True # 쿼리 전에 인덱스 재생성
)
각 결과에는 다음이 포함됩니다:
- 파일 경로
- 언어
- 코드 내용
- 시작/끝 라인 번호
- 유사도 점수
일반적인 사용 사례
- X의 실제 구현 찾기 – 레포에 비슷한 이름의 함수가 여러 개 있을 때.
- JWT 리프레시와 관련된 모든 인증 로직 표시.
- 스택 트레이스 스니펫과 일치하는 코드 찾기.
인덱스가 증분 방식으로 최신 상태를 유지하므로, 리팩터링하거나 테스트를 실행한 뒤에도 거대한 오프라인 작업을 다시 실행하지 않고도 새로운 코드 구조에 대해 즉시 에이전트를 사용할 수 있습니다.
언어 매트릭스
cocoindex‑code는 다음 언어를 지원합니다:
C, C++, C#, CSS/SCSS, Go, HTML, Java, JavaScript/TypeScript/TSX,
JSON/YAML/TOML, Kotlin, Markdown/MDX, Pascal, PHP, Python, R,
Ruby, Rust, Scala, Solidity, SQL, Swift, XML
또한 __pycache__, node_modules, target, dist와 같은 잡음 디렉터리와 vendored 의존성을 자동으로 제외합니다.
루트 경로는 .cocoindex_code/, .git/을 통해 자동으로 탐지되며, 없을 경우 현재 작업 디렉터리를 기본값으로 사용합니다. 실제로는 환경 변수를 설정할 필요가 거의 없습니다.
Embedding models
Out of the box the project uses a local SentenceTransformers model:
- Default:
sbert/sentence-transformers/all-MiniLM-L6-v2
No API key, no billing surprises, completely local.
If you need stronger semantic understanding for code‑heavy repos, set COCOINDEX_CODE_EMBEDDING_MODEL to any LiteLLM‑supported embedding model, e.g.:
- Ollama (local)
- OpenAI / Azure OpenAI
- Gemini
- Mistral
- Voyage (code‑optimized)
- Cohere
- AWS Bedrock
- Nebius
Start with the free local model and upgrade only if/when you actually need it.
고급 사용법
내부적으로, cocoindex‑code는 CocoIndex라는 Rust 기반 인덱싱 엔진을 사용합니다. 이 엔진은 대규모, 증분 데이터 워크플로에 맞게 설계되었습니다. 더 큰 조직 환경에서는 다음과 같은 작업을 할 수 있습니다:
- 모든 머신에서 다시 인덱싱하는 대신 팀원 간에 인덱스를 공유합니다.
- 중복 작업을 방지하기 위해 브랜치 중복 제거와 같은 기능을 사용합니다.
- CocoIndex 위에 구축된 더 큰 데이터/인덱싱 플랫폼의 일부로 실행합니다.
어떻게 도울 수 있나요
If this sounds useful, here’s a small but meaningful way to contribute:
- ⭐ Star the repo:
cocoindex-codeand the underlyingcocoindex. - Try it on your main (messy) project, not just a toy example.
- Open issues or pull requests with feedback, bugs, or ideas.
I’m especially interested in:
- Repos where existing “code RAG” tools failed you.
- Languages or frameworks you want better support for.
- Workflows where you want your coding agent to feel 10× more context‑aware.
If you do try it, let me know in the comments what stack you used it on—I’d love to feature a few real‑world examples in a follow‑up post.