Code Compass é um servidor MCP + pipeline RAG para a base de código de qualquer empresa.
Ele indexa repositórios (código + docs), gera embeddings e armazena tudo em um Vector DB (Qdrant), expondo tools via MCP para agentes como Codex, Gemini e Claude consultarem a codebase com evidência (trecho + path + linha + score).
Stack definida: Node/NestJS (MCP Server) + Python (Indexer/ML Worker) + Qdrant (Vector DB)
- Node/NestJS: gateway MCP robusto, integração fácil, validação, audit trail, DX bom.
- Python Worker: onde a “IA de verdade” vive (chunking, embeddings, rerank, avaliação).
- Qdrant: roda local/offline no MVP e escala depois como serviço compartilhado sem replatform.
-
Indexer (Python)
- varre repositórios e docs
- faz chunking (AST quando possível; fallback heurístico)
- gera embeddings
- faz
upsertno Qdrant com payload rico (metadados)
-
Vector Store (Qdrant)
- coleções separadas para
codeedocs(stem viaQDRANT_COLLECTION_BASE, com sufixos__code/__docs) + payload rico (repo, commit, path, linguagem, linhas, etc.) - filtros por payload (repo/pathPrefix/lang/branch/commit)
- busca semântica + (opcional) híbrida
- coleções separadas para
-
MCP Server (Node/NestJS)
- expõe tools para clientes MCP
- faz validação/allowlist de paths
- orquestra chamadas ao Qdrant e ao filesystem/git
- retorna resultados com evidência (path/linhas)
- Docker + Docker Compose (para Qdrant local)
- Node.js (LTS recomendado)
- Python 3.11+ (recomendado)
- Acesso ao(s) repositório(s) a indexar
Crie .env.local a partir de .env.example (inclui LLM_MODEL para o comando ask).
Se usar troca de perfil via /model no chat ACP, copie também model-profiles.example.toml
para model-profiles.toml e ajuste os perfis.
model-profiles.toml é local e pode conter dados sensíveis (ex.: endpoint/chave), portanto
não deve ser versionado.
O
Makefileprioriza.env.localquando o arquivo existe.
make upEndpoint local do Qdrant: http://localhost:6333.
Healthcheck rápido:
curl -s http://localhost:6333/readyzmake indexmake devpnpm installmake upmake indexpnpm mcp:start- Abra Antigravity → MCP Servers → Manage MCP Servers → View raw config
- Cole
apps/docs/assets/antigravity-mcp.json(substitua<REPO_ROOT_AQUI>) - Salve e recarregue o server MCP na UI, se solicitado
- Teste
search_codecom termo existente no repositório - Teste
open_fileusandopath/startLine/endLinede um hit - Valide segurança com
open_fileem../../etc/passwd(deve bloquear)
Referências rápidas: apps/docs/pages/mcp-antigravity.md e apps/docs/assets/antigravity-mcp.json.
Para usar o chat no terminal (TUI) e o modo one-shot, veja apps/docs/pages/cli/ask-cli.md.
Exemplo rapido:
pnpm ask --repo code-compass
pnpm ask "onde fica o handler do search_code?" --repo code-compassNo fluxo atual, o CLI converte --repo para scope: { type: "repo", repo } ao chamar o MCP.
O projeto agora conta com um portal de documentação interativo construído com Nextra, acessível em http://localhost:3000.
- ✅ Busca Full-Text nativa com FlexSearch
- ✅ Dark Mode habilitado por padrão
- ✅ Navegação automática entre páginas
- ✅ Syntax highlighting para código
- ✅ Mobile-responsive
- ✅ Performance otimizado com geração estática (SSG)
# Desenvolvimento (localhost:3000)
pnpm docs:dev
# Build de produção
pnpm docs:build
# Preview do build
pnpm docs:startO portal organiza toda a documentação técnica do projeto:
- Arquitetura - Visão detalhada da arquitetura do sistema
- ADRs - 7 decisões arquiteturais documentadas
- Indexer & RAG - Pipeline de indexação e embeddings
- CLI - Interface de linha de comando
- MCP Integration - Integração com Model Context Protocol
Para mais detalhes, consulte o apps/docs/README.md.
O Makefile da raiz já traz os alvos operacionais mínimos para infra + indexer:
make up # sobe qdrant e aguarda readiness
make health # valida /readyz
make index # alias de indexação full
make index-full # full em apps/indexer
make index-incremental # fallback para full (incremental ainda não implementado no CLI)
make index-docker # full via container (profile indexer)
make index-docker-incremental # fallback para full via container
make index-all # indexa todos os repos de code-base/
make dev # sobe apps/mcp-server em dev
make logs # logs do qdrant
make down # derruba serviçosObservações importantes do estado atual deste repositório:
- Se
apps/indexerainda não existir,make index*falha com erro explícito de pré-requisito. - Se
apps/mcp-serverainda não existir,make devfalha com erro explícito de pré-requisito. - O
make upusa.env.local(quando existir) ou.envpara portas/imagem/path de storage. make index-docker*exige Docker e instala dependências do indexer dentro do container a cada execução.make index-incrementalemake index-docker-incrementalfazem fallback para indexação full atualmente.
pnpm ask --repo <repo>: escopo de um repositório paraask_code(via ACP, convertido emscope).python -m indexer ask --scope-repo <repo>: escopo explícito de 1 repo.python -m indexer ask --scope-repos "repo-a,repo-b": escopo explícito multi-repo.python -m indexer ask --scope-all: escopo global (requerALLOW_GLOBAL_SCOPE=true).
QDRANT_COLLECTION_BASE: stem compartilhado entre indexador e MCP (coleções finais:__codee__docs).CODEBASE_ROOT: habilita roteamento multi-repo no MCP (<CODEBASE_ROOT>/<repo>).ALLOW_GLOBAL_SCOPE=true: habilitascope: { type: "all" }emsearch_codeeask_code.INDEXER_RUN_MODULE=indexer: módulo Python usado peloMakefile/docker para indexação.MCP_COMMAND: comando customizado parapython -m indexer askchamar o MCP server.CODE_COMPASS_TIMEOUT_MS: timeout (ms) parapnpm ask(CLI/TUI).
O scanner recursivo do indexador fica em apps/indexer/indexer e retorna JSON com:
files: arquivos elegíveis (relativos aorepo_root, em formato posix)stats: métricas do scan (total_files_seen,files_kept,elapsed_ms, etc.)
Execução mínima:
cd apps/indexer
python -m indexer scanConfiguração por ambiente:
REPO_ROOT: raiz do scan. Padrão:..(um nível acima deapps/indexer).SCAN_ALLOW_EXTS: CSV opcional para sobrescrever extensões permitidas.SCAN_IGNORE_DIRS: CSV opcional para adicionar diretórios ignorados.
Ignorados por padrão:
.git,node_modules,dist,build,.next,.qdrant_storage,coverage,.venv,venv,__pycache__,.pytest_cache,.mypy_cache,.ruff_cache
Allowlist padrão de extensões:
.ts,.tsx,.js,.jsx,.py,.md,.json,.yaml,.yml
Exemplo com env inline:
cd apps/indexer
REPO_ROOT=/home/juniormartinxo/code-compass \
SCAN_ALLOW_EXTS=.py,.md,.ts,.tsx \
SCAN_IGNORE_DIRS=node_modules,dist,build,.git \
python -m indexer scan --max-files 50O comando chunk gera chunks determinísticos por linhas com overlap, chunkId estável e contentHash no payload.
Execução mínima:
cd apps/indexer
python -m indexer chunk --file path/to/fileVariáveis de ambiente:
REPO_ROOT: raiz para path canônico relativo (padrão:..).CHUNK_LINES: tamanho máximo de cada chunk em linhas (padrão:120).CHUNK_OVERLAP_LINES: overlap entre chunks consecutivos (padrão:20).
Flags relevantes:
--chunk-lines: override deCHUNK_LINES.--overlap-lines: override deCHUNK_OVERLAP_LINES.--repo-root: override deREPO_ROOT.--as-posix/--no-as-posix: controla separador do path canônico; o padrão é--as-posixpara estabilidade cross-OS e menor atrito em filtros/payload no Qdrant.
Exemplo:
cd apps/indexer
python -m indexer chunk \
--file apps/indexer/indexer/chunk.py \
--repo-root .. \
--chunk-lines 120 \
--overlap-lines 20 \
--as-posixFormato de saída (resumo):
path: path canônico relativo aorepoRoot(quando possível).pathIsRelative:truequando o arquivo está sobREPO_ROOT.chunks[]:chunkId: hash estável depath:startLine:endLine:contentHash.contentHash: SHA-256 do conteúdo completo do arquivo (debug/dedupe/incremental).startLine/endLine: range 1-based inclusivo.language: inferido por extensão.content: conteúdo textual do chunk.
Após indexar, use o comando search do indexer para debug rápido no Qdrant:
cd apps/indexer
python -m indexer search "minha query" --topk 10Com filtro por prefixo de path no payload:
cd apps/indexer
python -m indexer search "minha query" --topk 10 --path_prefix src/Saída humana esperada por resultado:
[1] score=0.7821 src/foo/bar.ts:120-168
snippet: "..."
O diretório code-base/ é o ponto central para indexar múltiplos repositórios de uma só vez. Cada subdiretório dentro dele é tratado como um repositório independente pelo pipeline de indexação.
code-base/
├── .gitkeep # garante que o diretório exista no git
├── repo-frontend/ # git clone do projeto frontend
├── repo-backend/ # git clone do projeto backend
└── shared-lib/ # git clone de uma lib compartilhada
⚠️ O conteúdo decode-base/é ignorado pelo git (veja.gitignore). Apenas o.gitkeepé versionado.
Clone os repositórios que deseja indexar dentro de code-base/:
git clone git@gitlab.empresa.com:team/repo-frontend.git code-base/repo-frontend
git clone git@gitlab.empresa.com:team/repo-backend.git code-base/repo-backendScript bash que automatiza a indexação de todos os repositórios dentro de code-base/.
O que faz:
- Carrega as variáveis de ambiente de
.env.local - Ativa o virtualenv do indexer (
apps/indexer/.venv) - Itera sobre cada subdiretório de
code-base/ - Define
REPO_ROOTe executapython -m indexer indexpara cada repo - Exibe um resumo final com contagem de sucessos e falhas
Atenção (comportamento atual do indexador):
- O comando
indexprocessa um únicorepo_rootpor execução. - O campo
payload.repoé preenchido com o nome do diretório informado em--repo-root/REPO_ROOT. - Se você rodar com
REPO_ROOT=/.../code-base, todos os pontos serão gravados compayload.repo="code-base". - Nesse cenário, o filtro por
repono MCP não consegue separar corretamenterepo-frontend,repo-backend, etc. - Para multi-repo real, indexe cada subdiretório individualmente (ex.:
scripts/index-all.sh).
Uso:
# Indexar todos os repos dentro de code-base/
./scripts/index-all.sh
# Indexar apenas repos específicos (por nome do diretório)
./scripts/index-all.sh repo-frontend shared-lib
# Ou via Makefile (garante Qdrant + venv antes)
make index-allPré-requisitos:
- Qdrant rodando (
make up) - Ollama rodando com o modelo de embedding configurado
- Virtualenv do indexer criado (
make setup-indexer) - Pelo menos um repositório clonado em
code-base/
Exit code: retorna 0 se todos os repos foram indexados com sucesso, 1 se algum falhou (útil para CI/CD).
infra/docker-compose.yml:
name: ${COMPOSE_PROJECT_NAME:-code-compass}
services:
qdrant:
container_name: code-compass-qdrant
image: ${QDRANT_IMAGE:-qdrant/qdrant:latest}
restart: unless-stopped
ports:
- "${QDRANT_HTTP_PORT:-6333}:6333" # HTTP
- "${QDRANT_GRPC_PORT:-6334}:6334" # gRPC
volumes:
- "${QDRANT_STORAGE_PATH:-./qdrant_data}:/qdrant/storage:z"
healthcheck:
test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/127.0.0.1/6333'"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15sVerificar:
curl -s http://localhost:6333/
curl -s http://localhost:6333/readyzPrioridade de carregamento no fluxo atual:
- variáveis já exportadas no shell
.env.local.env
Exemplo (base em .env.example):
# -----------------------------
# Docker Compose
# -----------------------------
COMPOSE_PROJECT_NAME=code-compass
# -----------------------------
# Qdrant (infra local)
# -----------------------------
QDRANT_IMAGE=qdrant/qdrant:latest
QDRANT_HTTP_PORT=6333
QDRANT_GRPC_PORT=6334
QDRANT_STORAGE_PATH=./qdrant_data
# -----------------------------
# Qdrant
# -----------------------------
QDRANT_URL=http://localhost:6333
QDRANT_API_KEY=
QDRANT_COLLECTION_BASE=compass_manutic_nomic_embed
QDRANT_DISTANCE=COSINE
QDRANT_UPSERT_BATCH=64
# -----------------------------
# Repos / ingestão
# -----------------------------
REPO_ROOT=/abs/path/para/repositorio
REPO_ALLOWLIST=src,packages,apps,docs
REPO_BLOCKLIST=node_modules,dist,build,.next,.git,coverage
SCAN_IGNORE_DIRS=.git,node_modules,dist,build,.next,.qdrant_storage,coverage,.venv,venv,__pycache__,.pytest_cache,.mypy_cache,.ruff_cache
SCAN_ALLOW_EXTS=.ts,.tsx,.js,.jsx,.py,.md,.json,.yaml,.yml
# -----------------------------
# Indexer (apps/indexer)
# -----------------------------
INDEXER_DIR=apps/indexer
INDEXER_PYTHON=python3
INDEXER_RUN_MODULE=indexer
INDEXER_DOCKER_PROFILE=indexer
INDEXER_DOCKER_IMAGE=python:3.11-slim
QDRANT_URL_DOCKER=http://qdrant:6333
REPO_ROOT_DOCKER=/workspace
# -----------------------------
# Embeddings (ask_code)
# -----------------------------
EMBEDDING_PROVIDER_CODE=ollama
EMBEDDING_PROVIDER_DOCS=ollama
EMBEDDING_PROVIDER_CODE_API_URL=http://localhost:11434
EMBEDDING_PROVIDER_DOCS_API_URL=http://localhost:11434
EMBEDDING_PROVIDER_CODE_API_KEY=
EMBEDDING_PROVIDER_DOCS_API_KEY=
EMBEDDING_MODEL_CODE=manutic/nomic-embed-code
EMBEDDING_MODEL_DOCS=bge-m3
EMBEDDING_BATCH_SIZE=16
EMBEDDING_MAX_RETRIES=5
EMBEDDING_BACKOFF_BASE_MS=500
EMBEDDING_TIMEOUT_SECONDS=120
LLM_MODEL_PROVIDER=ollama
LLM_MODEL=gpt-oss:latest
LLM_MODEL_API_URL=http://localhost:11434
LLM_MODEL_API_KEY=
# -----------------------------
# Chunking
# -----------------------------
CHUNK_LINES=120
CHUNK_OVERLAP_LINES=20
# -----------------------------
# MCP Server
# -----------------------------
MCP_SERVER_NAME=code-compass
MCP_SERVER_PORT=3333
CODEBASE_ROOT=/abs/path/para/code-base
ALLOW_GLOBAL_SCOPE=false
# -----------------------------
# Segurança / Governança
# -----------------------------
READ_ONLY=true
AUDIT_LOG_ENABLED=true
PATH_TRAVERSAL_GUARD=truecompass_manutic_nomic_embed(exemplo)
-
id: string única (ex.:<repo>:<commit>:<path>:<chunkHash>) -
vector: embedding -
payload:repo,branch,commitpath,languagestartLine,endLinesymbols(opcional)text(trecho do chunk) outextRef(se preferir guardar chunk fora)
Busca semântica no Qdrant com filtros por payload.
Abre um trecho do arquivo (fonte de verdade) por range de linhas.
Executa o fluxo RAG completo (embedding + busca + contexto + LLM) no servidor MCP.
V1 (opcional):
find_symbol,git_log,git_blame, rerank.
Importante: clientes MCP podem suportar diferentes transportes. O Code Compass suporta STDIO (processo local) e HTTP (endpoint JSON-RPC em
/mcp). Alguns clientes também usam HTTP/SSE; sempre siga a doc do cliente.Para exemplos prontos, veja
apps/docs/pages/mcp-client-quickstart.mde os templates emapps/docs/assets/.
A forma mais comum é registrar um servidor local no Claude Desktop (o cliente lança o processo do server). A doc oficial de “connect local servers” mostra o fluxo geral com Claude Desktop.
Padrão recomendado para Claude Desktop:
- rodar o MCP server como STDIO server (processo local)
- apontar o comando para iniciar o Code Compass
Observação: o formato exato de configuração varia por versão/método do cliente.
Dica prática:
- Use
bin/dev-mcp(launcher do projeto para STDIO sem poluirstdout). - Configure o cliente para chamar esse launcher com path absoluto.
Codex lê a config em ~/.codex/config.toml (ou em .codex/config.toml por projeto).
Exemplo de configuração (STDIO) — .codex/config.toml:
[mcp_servers.code_compass_local]
command = "/ABS/PATH/code-compass/bin/dev-mcp"
args = []
env = { QDRANT_URL = "http://localhost:6333", QDRANT_COLLECTION_BASE = "compass_manutic_nomic_embed", CODEBASE_ROOT = "/ABS/PATH/code-compass/code-base" }Template pronto: apps/docs/assets/codex-config-example.toml.
Arquivo comum de configuração:
.cursor/mcp.json(projeto) ou~/.cursor/mcp.json(global)
Template pronto: apps/docs/assets/cursor-mcp.json.
Arquivo comum de configuração por workspace:
.vscode/mcp.json
Template pronto: apps/docs/assets/vscode-mcp.json.
Fluxo comum na IDE:
SettingsTools > AI Assistant > Model Context Protocol (MCP)- Adicionar/importar config JSON
Template pronto: apps/docs/assets/jetbrains-mcp.json.
Workflow sugerido (vale para qualquer cliente):
make upmake index- configurar cliente MCP com
bin/dev-mcp - testar
search_codecom termo existente - validar
open_filecom../../etc/passwd(deve bloquear)
Use transporte HTTP quando quiser hospedar o MCP em um servidor:
pnpm -C apps/mcp-server build
pnpm -C apps/mcp-server start:httpConfigurações úteis:
MCP_HTTP_HOST(default:0.0.0.0)MCP_HTTP_PORT(default:3001)MCP_SERVER_MODE=http(alternativa ao--transport http)
Endpoint MCP: POST http://<host>:<port>/mcp (JSON-RPC 2.0).
O Gemini CLI tem suporte a MCP servers e documenta como configurar.
Aqui também é comum usar STDIO para servidor local.
Recomendação: se sua intenção é “Gemini no terminal”, Gemini CLI é o caminho mais previsível.
O Android Studio tem fluxo próprio para adicionar MCP server ao agente do Gemini. Útil se o time está muito preso em Android Studio/JetBrains e quer toolchain “na IDE”.
- Read-only por padrão
- Allowlist de diretórios/repositórios
- Proteção contra
../(path traversal) - Audit trail de tool calls (quem, quando, query, filtros, repos tocados)
- (Opcional) redator/detector de segredos antes de indexar
-
Logs estruturados no MCP Server (NestJS)
-
Métricas sugeridas:
- latência P95 do
search_code - taxa de respostas com evidência (path+linha)
- top queries / “no hits” (gaps de indexação)
- latência P95 do
- Qdrant local via Docker
- Indexer Python: full (incremental em evolução)
- MCP Server NestJS:
search_code,open_file,ask_code - Retorno com evidência (path/linha) sempre
- Busca híbrida (sparse + dense) e/ou rerank top-N
- Filtros avançados (módulo, dono, tags)
git_log/git_blame
- Grafo de símbolos (def/ref)
- Multi-tenant por time/projeto
- Avaliação automática (golden queries)
- Policy packs (compliance)
Uso interno (definir conforme política da empresa).