@rpcajr/smart-graph-indexer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/rules/antigravity-rtk-rules.md +32 -0
- package/README.md +116 -0
- package/dist/graph.d.ts +32 -0
- package/dist/graph.js +86 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -0
- package/dist/mcp_server.d.ts +48 -0
- package/dist/mcp_server.js +433 -0
- package/dist/parser.d.ts +42 -0
- package/dist/parser.js +529 -0
- package/dist/stats.d.ts +43 -0
- package/dist/stats.js +146 -0
- package/dist/ui.d.ts +2 -0
- package/dist/ui.js +1003 -0
- package/dist/vector.d.ts +66 -0
- package/dist/vector.js +144 -0
- package/dist/wasm/tree-sitter-c.wasm +0 -0
- package/dist/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/wasm/tree-sitter-go.wasm +0 -0
- package/dist/wasm/tree-sitter-java.wasm +0 -0
- package/dist/wasm/tree-sitter-python.wasm +0 -0
- package/dist/wasm/tree-sitter-ruby.wasm +0 -0
- package/dist/wasm/tree-sitter-rust.wasm +0 -0
- package/dist/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/wasm/tree-sitter.wasm +0 -0
- package/dist/watcher.d.ts +36 -0
- package/dist/watcher.js +166 -0
- package/mcp-config-example.json +12 -0
- package/mcp_smart_indexer_implementation_spec.md +366 -0
- package/package.json +35 -0
- package/src/graph.ts +93 -0
- package/src/index.ts +216 -0
- package/src/mcp_server.ts +454 -0
- package/src/parser.ts +484 -0
- package/src/stats.ts +156 -0
- package/src/ui.ts +956 -0
- package/src/vector.ts +166 -0
- package/src/watcher.ts +144 -0
- package/test_project/App.java +16 -0
- package/test_project/BillingService.cs +31 -0
- package/test_project/auth.ts +18 -0
- package/test_project/config.ts +11 -0
- package/test_project/database.ts +21 -0
- package/test_project/index.ts +13 -0
- package/test_project/main.go +11 -0
- package/test_project/main.py +21 -0
- package/test_project/processor.py +12 -0
- package/test_project/utils.py +13 -0
- package/tsconfig.json +16 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# Especificação de Implementação: MCP Smart Code Indexer
|
|
2
|
+
## Servidor MCP de Alta Performance, Git-Aware e Baixo Consumo de Contexto (Tokens)
|
|
3
|
+
|
|
4
|
+
Este documento descreve detalhadamente as especificações arquiteturais, de design e os passos de implementação para construir o **MCP Smart Code Indexer**. Ele foi projetado para que ferramentas de IA de fronteira (como Claude Code, Google Antigravity CLI, Cursor, Cline) consigam interpretar, codificar e implantar o sistema completo de forma autônoma e incremental.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Visão Geral e Objetivos do Projeto
|
|
9
|
+
|
|
10
|
+
### 1.1 O Problema
|
|
11
|
+
Ao interagir com bases de código corporativas ou legadas gigantes (1M+ linhas de código), ferramentas de desenvolvimento baseadas em IA sofrem com:
|
|
12
|
+
1. **Desperdício de Contexto (Token Bleeding):** Varreduras cegas via `grep` ou abertura de arquivos inteiros consomem dezenas de milhares de tokens desnecessários.
|
|
13
|
+
2. **Invalidação Ineficiente de Cache:** Sistemas que exigem varredura completa a cada alteração travam a máquina do desenvolvedor e geram dados obsoletos rapidamente.
|
|
14
|
+
3. **Falta de Contexto Semântico e Arquitetural:** A IA não compreende a hierarquia e o relacionamento (grafo) entre as classes, resultando em correções isoladas que quebram dependências indiretas.
|
|
15
|
+
|
|
16
|
+
### 1.2 A Solução
|
|
17
|
+
O **MCP Smart Code Indexer** atua como um intermediário de busca semântica, sintática e estrutural por meio de:
|
|
18
|
+
* **AST (Abstract Syntax Tree) Skeletons:** Extração instantânea apenas de assinaturas e cabeçalhos de código (sem os blocos internos), reduzindo a leitura em até 95%.
|
|
19
|
+
* **Git-Backed Delta Tracking:** Monitoramento em tempo real do sistema de arquivos alinhado à árvore de estados do Git, indexando incrementalmente apenas os deltas.
|
|
20
|
+
* **Grafo de Dependências In-Memory:** Mapeamento em RAM dos relacionamentos do projeto.
|
|
21
|
+
* **RAG Híbrido Local (Semântico + Léxico):** Mecanismo de busca ultraleve rodando embeddings de assinaturas localmente via CPU (ONNX), gerando economia drástica de tokens e respostas em milissegundos.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Visão de Arquitetura do Sistema
|
|
26
|
+
|
|
27
|
+
O diagrama abaixo descreve a comunicação assíncrona orientada a eventos do sistema:
|
|
28
|
+
|
|
29
|
+
```mermaid
|
|
30
|
+
graph TD
|
|
31
|
+
User([Desenvolvedor / Git]) -->|Modifica Código| FS[Sistema de Arquivos / Git Status]
|
|
32
|
+
FS -->|FS Event / git diff| Watcher[Git-Aware Delta Engine]
|
|
33
|
+
Watcher -->|Somente Arquivos Modificados| Parser[Parser AST: Tree-sitter]
|
|
34
|
+
Parser -->|Assinaturas Públicas / Docstrings| Indexer[Incremental Indexer Engine]
|
|
35
|
+
|
|
36
|
+
Indexer -->|Atualiza Grafo| Graph[In-Memory Dependency Graph]
|
|
37
|
+
Indexer -->|Vetoriza Assinaturas / ONNX| VectorStore[Local Vector Store]
|
|
38
|
+
|
|
39
|
+
IA[Ferramenta de IA: Claude/Antigravity] -->|JSON-RPC via stdio| MCP[MCP Server]
|
|
40
|
+
MCP -->|Busca Semântica / Tags| VectorStore
|
|
41
|
+
MCP -->|Navegação de Relações| Graph
|
|
42
|
+
MCP -->|Extração JIT do Código| JIT[Just-In-Time Code Extractor]
|
|
43
|
+
JIT -->|Somente Linhas Solicitadas| IA
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2.1 Decisões de Engenharia Críticas
|
|
47
|
+
1. **Linguagem de Implementação:** **Rust** (Recomendado) ou **Go**. Se construído em **Rust**, utilizar empacotamento nativo. Rust garante inicialização em milissegundos, consumo de RAM desprezível (< 50MB para grafos grandes) e suporte perfeito a parseamento paralelo multitheading. *(Nota: Caso o ecossistema C# .NET 9 com Native AOT seja preferido pelo desenvolvedor, a mesma arquitetura se aplica usando C# nativo e pinvoke para Tree-Sitter).*
|
|
48
|
+
2. **Parser Sintático:** **Tree-sitter** (bindings em C/Rust/Go). Evita a necessidade de compilação ou runtimes específicos das linguagens do projeto analisado.
|
|
49
|
+
3. **Embeddings Locais:** **ONNX Runtime** rodando o modelo `all-MiniLM-L6-v2` (ou similar de ~22MB a 45MB de tamanho), gerando vetores de 384 dimensões diretamente na CPU.
|
|
50
|
+
4. **Protocolo de Comunicação:** MCP (Model Context Protocol) usando transporte por entrada/saída padrão (`stdio`) baseado em JSON-RPC 2.0.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 3. Estrutura de Pastas Sugerida (Rust)
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
mcp-smart-indexer/
|
|
58
|
+
├── Cargo.toml
|
|
59
|
+
├── README.md
|
|
60
|
+
├── build.rs # Para compilar e vincular gramáticas do tree-sitter
|
|
61
|
+
├── models/
|
|
62
|
+
│ └── all-miniLM-L6-v2.onnx # Modelo de embedding local pré-baixado
|
|
63
|
+
├── src/
|
|
64
|
+
│ ├── main.rs # Orquestrador do CLI e entrada principal
|
|
65
|
+
│ ├── mcp/
|
|
66
|
+
│ │ ├── mod.rs
|
|
67
|
+
│ │ ├── protocol.rs # Protocolo JSON-RPC do MCP
|
|
68
|
+
│ │ └── tools.rs # Implementação das Ferramentas MCP (schemas)
|
|
69
|
+
│ ├── indexer/
|
|
70
|
+
│ │ ├── mod.rs
|
|
71
|
+
│ │ ├── watcher.rs # Watcher FS integrado com Git
|
|
72
|
+
│ │ ├── parser.rs # Extração de Skeletons via Tree-sitter
|
|
73
|
+
│ │ └── delta.rs # Verificador de diferenças incrementais
|
|
74
|
+
│ ├── search/
|
|
75
|
+
│ │ ├── mod.rs
|
|
76
|
+
│ │ ├── vector.rs # Gerenciamento de vetores locais e ONNX
|
|
77
|
+
│ │ └── graph.rs # Grafo de dependências na memória RAM
|
|
78
|
+
│ └── utils/
|
|
79
|
+
│ ├── mod.rs
|
|
80
|
+
│ └── git.rs # Auxiliares de parsing de .gitignore e git diff
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 4. Fases de Implementação (Passo a Passo)
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Fase 1: Scaffold do Projeto, CLI e Setup de Dependências
|
|
90
|
+
|
|
91
|
+
#### Objetivo
|
|
92
|
+
Criar o esqueleto do projeto em Rust, configurar as dependências cruciais de processamento assíncrono, parser e serialização, e implementar a interface CLI inicial.
|
|
93
|
+
|
|
94
|
+
#### Dependências Necessárias (`Cargo.toml`)
|
|
95
|
+
```toml
|
|
96
|
+
[package]
|
|
97
|
+
name = "mcp-smart-indexer"
|
|
98
|
+
version = "0.1.0"
|
|
99
|
+
edition = "2021"
|
|
100
|
+
|
|
101
|
+
[dependencies]
|
|
102
|
+
tokio = { version = "1.35", features = ["full"] }
|
|
103
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
104
|
+
serde_json = "1.0"
|
|
105
|
+
notify = "6.1" # Monitoramento de arquivos nativo do OS
|
|
106
|
+
tree-sitter = "0.20" # Parser AST core
|
|
107
|
+
# Adicionar gramáticas populares
|
|
108
|
+
tree-sitter-c-sharp = "0.20"
|
|
109
|
+
tree-sitter-typescript = "0.20"
|
|
110
|
+
tree-sitter-python = "0.20"
|
|
111
|
+
ort = { version = "1.16" } # ONNX Runtime para embeddings locais na CPU
|
|
112
|
+
ndarray = "0.15" # Para manipular os tensores de embedding
|
|
113
|
+
anyhow = "1.0" # Tratamento amigável de erros
|
|
114
|
+
clap = { version = "4.4", features = ["derive"] } # CLI Parser
|
|
115
|
+
ignore = "0.4" # Respeito rápido a regras do .gitignore
|
|
116
|
+
petgraph = "0.6" # Estrutura de dados de grafo em memória
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Requisitos de Código (CLI)
|
|
120
|
+
O binário deve aceitar os seguintes comandos via CLI:
|
|
121
|
+
* `mcp-indexer start --path <diretorio>`: Inicia o servidor MCP via `stdio`.
|
|
122
|
+
* `mcp-indexer index --path <diretorio>`: Executa apenas a indexação inicial do projeto de forma síncrona e exporta um report estrutural em formato JSON para debug.
|
|
123
|
+
* O comando de inicialização deve ler o arquivo `.gitignore` do diretório-alvo e ignorar pastas não versionadas por padrão.
|
|
124
|
+
|
|
125
|
+
#### Definição de Done (Fase 1)
|
|
126
|
+
1. Executar `cargo build` com sucesso.
|
|
127
|
+
2. Comando `mcp-indexer index --path .` executa sem crashar, listando caminhos de arquivos válidos respeitando o `.gitignore`.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### Fase 2: Git-Aware Delta Engine (Watcher Inteligente)
|
|
132
|
+
|
|
133
|
+
#### Objetivo
|
|
134
|
+
Criar um motor de monitoramento de alterações que consome zero recursos em repouso e sabe diferenciar arquivos modificados de arquivos novos usando o Git e eventos do Sistema de Arquivos (FS).
|
|
135
|
+
|
|
136
|
+
#### Especificação Técnica
|
|
137
|
+
1. **Mapeamento Base (Warm Start):**
|
|
138
|
+
* Ao iniciar no diretório, o MCP deve rodar `git status --porcelain` para identificar imediatamente arquivos alterados localmente (staged ou unstaged) em relação ao último commit.
|
|
139
|
+
* Se o projeto for um repositório Git limpo, o estado inicial de indexação é carregado a partir de um cache serializado rápido (`.mcp/cache.bin`).
|
|
140
|
+
2. **FileSystem Watcher Ativo:**
|
|
141
|
+
* Instanciar um monitor dinâmico usando a crate `notify`.
|
|
142
|
+
* Sempre que um evento de escrita (`Write`) ou criação (`Create`) for detectado, o caminho do arquivo deve ser passado pela biblioteca `ignore` para checar se ele não está no `.gitignore`.
|
|
143
|
+
* O watcher não dispara reindexação imediata na primeira modificação de caractere. Ele deve aplicar um **debounce de 1.5 segundos**. Se novas escritas ocorrerem dentro desse intervalo, o cronômetro reinicia. Isso evita micro-reindexações durante a digitação ativa do desenvolvedor.
|
|
144
|
+
3. **Invalidação de Cache:**
|
|
145
|
+
* O cache do arquivo alterado só é invalidado se o hash MD5 (ou SHA-1) do conteúdo atualizado diferir do hash armazenado no cache.
|
|
146
|
+
|
|
147
|
+
#### Definição de Done (Fase 2)
|
|
148
|
+
1. Modificar um arquivo ignorado pelo `.gitignore` não deve disparar nenhuma ação no console.
|
|
149
|
+
2. Modificar um arquivo de código válido (`.cs`, `.ts`, `.py`) deve disparar o evento debounced de reindexação e atualizar o hash interno do arquivo em memória.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Fase 3: Parser AST de Skeletons (Tree-sitter Engine)
|
|
154
|
+
|
|
155
|
+
#### Objetivo
|
|
156
|
+
Extrair a "casca" estrutural do código (nomes de classes, estruturas, métodos, propriedades, assinaturas e comentários/docstrings anexos) sem armazenar ou processar o bloco de implementação interno das funções.
|
|
157
|
+
|
|
158
|
+
#### Estruturas de Dados (Modelos de Símbolos)
|
|
159
|
+
```rust
|
|
160
|
+
#[derive(Debug, Serialize, DeserializeClone)]
|
|
161
|
+
pub struct SymbolSkeleton {
|
|
162
|
+
pub name: String,
|
|
163
|
+
pub kind: SymbolKind, // Enum: Class, Struct, Method, Property, Interface
|
|
164
|
+
pub signature: String, // Ex: "public void ProcessOrder(Order order, decimal discount)"
|
|
165
|
+
pub docstring: Option<String>, // Comentários acima do método/classe
|
|
166
|
+
pub start_line: usize,
|
|
167
|
+
pub end_line: usize, // Mapeia exatamente de onde a onde o método existe no arquivo original
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#[derive(Debug, Serialize, Deserialize)]
|
|
171
|
+
pub struct FileSkeleton {
|
|
172
|
+
pub file_path: String,
|
|
173
|
+
pub file_hash: String,
|
|
174
|
+
pub symbols: Vec<SymbolSkeleton>,
|
|
175
|
+
pub dependencies: Vec<String>, // Namespaces ou arquivos importados diretamente
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Regras de Parsing por Linguagem
|
|
180
|
+
O Parser deve conter módulos de consulta (Queries AST do Tree-sitter) customizados para extrair símbolos das seguintes linguagens principais:
|
|
181
|
+
|
|
182
|
+
##### 1. C# (`.cs`)
|
|
183
|
+
* **Classes / Interfaces:** Capturar o cabeçalho `public class <Nome> : <Base>` ou `public interface <Nome>`.
|
|
184
|
+
* **Métodos:** Capturar a assinatura completa excluindo o nó `block` (chaves `{ ... }`). Capturar comentários de documentação XML (`/// <summary>...`).
|
|
185
|
+
|
|
186
|
+
##### 2. TypeScript/JavaScript (`.ts`, `.js`, `.tsx`)
|
|
187
|
+
* **Classes / Funções Exportadas:** Capturar declarações `export class`, `export function`, `export const <ArrowFunction>`.
|
|
188
|
+
* **Assinaturas:** Capturar os tipos de parâmetros e retornos. Capturar comentários JSDoc (`/** ... */`).
|
|
189
|
+
|
|
190
|
+
##### 3. Python (`.py`)
|
|
191
|
+
* **Classes / Funções:** Capturar `class <Nome>:` e `def <Nome>(...):`.
|
|
192
|
+
* **Docstrings:** Capturar as strings literais triplas (`"""...""\``) imediatamente após a declaração.
|
|
193
|
+
|
|
194
|
+
#### Definição de Done (Fase 3)
|
|
195
|
+
* Um teste unitário que recebe um arquivo C# ou TS de 500 linhas e gera um `FileSkeleton` contendo apenas as assinaturas exatas, omitindo todo o corpo dos loops e condicionais internos dos métodos. As linhas de início e fim dos métodos devem bater perfeitamente com o arquivo original.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### Fase 4: Grafo de Dependências e RAG Semântico Local
|
|
200
|
+
|
|
201
|
+
#### Objetivo
|
|
202
|
+
Montar em memória RAM as conexões estruturais entre os arquivos indexados e criar um mecanismo de busca vetorial para permitir que a IA encontre símbolos por contexto conceitual sem precisar de buscas textuais de alto consumo de tokens.
|
|
203
|
+
|
|
204
|
+
#### 1. O Grafo de Dependências (In-Memory Graph)
|
|
205
|
+
* Utilizar `petgraph` para modelar o grafo direcionado do projeto.
|
|
206
|
+
* **Vértices (Nodes):** Representam os arquivos do projeto (ex: `BillingService.cs`, `IUserRepository.cs`).
|
|
207
|
+
* **Arestas (Edges):** Representam conexões de dependência através de diretivas de importação (ex: `using`, `import`, `require`).
|
|
208
|
+
* O grafo permite buscar relações bidirecionais:
|
|
209
|
+
* **Dependências Diretas (Out-edges):** *"Quais arquivos este arquivo consome?"*
|
|
210
|
+
* **Dependentes (In-edges):** *"Se eu alterar a interface X, quais arquivos do projeto podem ser impactados por tabela?"*
|
|
211
|
+
|
|
212
|
+
#### 2. Vector Store e Embedding Engine (ONNX Local)
|
|
213
|
+
* **Inicialização:** No boot do MCP, instanciar a sessão `ort` com o modelo de embedding local `all-miniLM-L6-v2.onnx` rodando em threads dedicadas na CPU.
|
|
214
|
+
* **Payload de Vetorização:** O texto que vai para a geração de embeddings de cada símbolo **NUNCA** é o código completo. Ele deve seguir o seguinte template sintético:
|
|
215
|
+
```text
|
|
216
|
+
File: <Caminho> | Symbol: <Nome> (<Kind>) | Signature: <Assinatura> | Doc: <Docstring ou Comentário>
|
|
217
|
+
```
|
|
218
|
+
*Exemplo:*
|
|
219
|
+
```text
|
|
220
|
+
File: Src/Services/TaxService.cs | Symbol: CalculateVAT (Method) | Signature: public decimal CalculateVAT(Invoice invoice, Region region) | Doc: Calcula o imposto sobre valor agregado com base na regiao de faturamento
|
|
221
|
+
```
|
|
222
|
+
* **Armazenamento de Vetores:** Como o número de assinaturas em projetos gigantes raramente passa de 10.000 símbolos, armazenar os embeddings diretamente em um vetor plano em memória (`Vec<(SymbolId, Vec<f32>)>`). A busca por similaridade de cosseno (Cosine Similarity) para essa escala em memória leva menos de **5 milissegundos**.
|
|
223
|
+
* **Busca Híbrida:** A busca semântica por cosseno deve ser opcionalmente combinada com busca textual exata e rápida (usando filtro de substring simples) para termos específicos e nomes exatos de métodos.
|
|
224
|
+
|
|
225
|
+
#### Definição de Done (Fase 4)
|
|
226
|
+
* Executar uma busca semântica pela frase *"cálculo de imposto"* e obter como primeiro resultado o símbolo `CalculateVAT` mesmo sem que o termo exato "VAT" tenha sido digitado no prompt de busca.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
### Fase 5: Protocolo MCP JSON-RPC Server
|
|
231
|
+
|
|
232
|
+
#### Objetivo
|
|
233
|
+
Implementar o canal de comunicação via `stdio` que escuta as mensagens JSON-RPC 2.0 das ferramentas de IA clientes e executa as ações de busca e extração.
|
|
234
|
+
|
|
235
|
+
#### Ferramentas (Tools) que o MCP DEVE Expor ao Cliente de IA
|
|
236
|
+
|
|
237
|
+
O servidor MCP deve expor as seguintes ferramentas cruciais com os respectivos schemas JSON:
|
|
238
|
+
|
|
239
|
+
##### 1. `search_symbols`
|
|
240
|
+
* **Descrição:** Realiza busca híbrida (semântica via vetor + sintática por texto) sobre a base de assinaturas indexadas.
|
|
241
|
+
* **Parâmetros:**
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"type": "object",
|
|
245
|
+
"properties": {
|
|
246
|
+
"query": { "type": "string", "description": "Termo de busca ou descrição funcional da lógica que deseja encontrar" },
|
|
247
|
+
"limit": { "type": "integer", "default": 5, "description": "Número máximo de correspondências a retornar" }
|
|
248
|
+
},
|
|
249
|
+
"required": ["query"]
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
##### 2. `get_file_skeleton`
|
|
254
|
+
* **Descrição:** Retorna a estrutura (esqueleto) completa de um arquivo específico sem as implementações internas. Permite à IA entender a estrutura do arquivo instantaneamente consumindo pouquíssimos tokens.
|
|
255
|
+
* **Parâmetros:**
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"type": "object",
|
|
259
|
+
"properties": {
|
|
260
|
+
"file_path": { "type": "string", "description": "Caminho relativo do arquivo no projeto" }
|
|
261
|
+
},
|
|
262
|
+
"required": ["file_path"]
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
##### 3. `get_dependencies`
|
|
267
|
+
* **Descrição:** Consulta o grafo em memória e retorna o mapa de conexões de um arquivo específico. Auxilia a IA a entender o impacto arquitetural de uma alteração.
|
|
268
|
+
* **Parâmetros:**
|
|
269
|
+
```json
|
|
270
|
+
{
|
|
271
|
+
"type": "object",
|
|
272
|
+
"properties": {
|
|
273
|
+
"file_path": { "type": "string", "description": "Caminho do arquivo de origem" },
|
|
274
|
+
"direction": { "type": "string", "enum": ["incoming", "outgoing", "both"], "default": "both" }
|
|
275
|
+
},
|
|
276
|
+
"required": ["file_path"]
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
##### 4. `read_symbol_body`
|
|
281
|
+
* **Descrição:** Extração JIT (Just-In-Time). Retorna o código-fonte real e completo de um método ou classe específico baseado nas linhas de início e fim fornecidas pelo esqueleto.
|
|
282
|
+
* **Parâmetros:**
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"type": "object",
|
|
286
|
+
"properties": {
|
|
287
|
+
"file_path": { "type": "string", "description": "Caminho relativo do arquivo" },
|
|
288
|
+
"symbol_name": { "type": "string", "description": "Nome exato da classe ou método a ler" }
|
|
289
|
+
},
|
|
290
|
+
"required": ["file_path", "symbol_name"]
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Especificação de Resposta Segura
|
|
295
|
+
Se o arquivo original foi alterado no disco após a indexação inicial, a chamada para `read_symbol_body` deve acionar uma re-validação rápida do hash do arquivo e re-parsear a árvore antes de ler a fatia de linhas correspondente, evitando entregar código incorreto ou desalinhado por offset de linhas.
|
|
296
|
+
|
|
297
|
+
#### Definição de Done (Fase 5)
|
|
298
|
+
* O processo MCP inicia e responde adequadamente à mensagem padrão de handshake do protocolo: `{"jsonrpc": "2.0", "method": "initialize", "params": {...}, "id": 1}` enviada via terminal (`stdin`).
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 5. Como Integrar e Testar em Diferentes Clientes
|
|
303
|
+
|
|
304
|
+
As ferramentas de IA locais se comunicam de forma nativa com o executável gerado. Use estes arquivos de configuração de referência para testar o seu servidor MCP local.
|
|
305
|
+
|
|
306
|
+
### 5.1 Testando com Google Antigravity IDE / CLI
|
|
307
|
+
Crie ou adicione a configuração ao arquivo global de agentes do Antigravity (ex: `~/.config/antigravity/mcp_servers.json` ou local no projeto em `.antigravity/mcp.json`):
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"mcpServers": {
|
|
312
|
+
"smart-code-indexer": {
|
|
313
|
+
"command": "/usr/local/bin/mcp-smart-indexer",
|
|
314
|
+
"args": ["start", "--path", "."],
|
|
315
|
+
"env": {
|
|
316
|
+
"RUST_LOG": "info"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 5.2 Testando com Claude Code (CLI)
|
|
324
|
+
Para vincular diretamente o binário compilado no Claude Code global, execute o utilitário interativo:
|
|
325
|
+
```bash
|
|
326
|
+
claude mcp add smart-code-indexer -- /usr/local/bin/mcp-smart-indexer start --path .
|
|
327
|
+
```
|
|
328
|
+
Ou manualmente no seu arquivo de configuração `~/.claude.json`:
|
|
329
|
+
```json
|
|
330
|
+
{
|
|
331
|
+
"mcpServers": {
|
|
332
|
+
"smart-code-indexer": {
|
|
333
|
+
"command": "mcp-smart-indexer",
|
|
334
|
+
"args": ["start", "--path", "."],
|
|
335
|
+
"alwaysOn": true
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 5.3 Testando com Cursor ou Cline (VS Code Extension)
|
|
342
|
+
Adicione nas configurações de desenvolvedor MCP do Cursor ou no arquivo global `clinesettings.json`:
|
|
343
|
+
```json
|
|
344
|
+
{
|
|
345
|
+
"mcpServers": {
|
|
346
|
+
"smart-code-indexer": {
|
|
347
|
+
"command": "mcp-smart-indexer",
|
|
348
|
+
"args": ["start", "--path", "."],
|
|
349
|
+
"disabled": false,
|
|
350
|
+
"autoApprove": []
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## 6. Checklist de Validação Final para a IA Executora
|
|
359
|
+
|
|
360
|
+
Para considerar este projeto 100% implementado de forma automatizada, a ferramenta de IA que escrever o código deve validar os seguintes pontos de qualidade:
|
|
361
|
+
|
|
362
|
+
- [ ] **Desempenho de Inicialização:** O servidor MCP no boot em um projeto de 1M de linhas de código deve responder ao handshake de inicialização em menos de **1 segundo**, realizando a vetorização em segundo plano (background thread pool).
|
|
363
|
+
- [ ] **Consumo de Memória:** O consumo de RAM estático do processo MCP em background não deve exceder **100MB** em repouso.
|
|
364
|
+
- [ ] **Robusteza do Watcher:** Ao criar um novo arquivo `.cs` contendo um método de teste, a busca semântica por `search_symbols` deve conseguir encontrá-lo em até **2 segundos** de forma assíncrona após salvar o arquivo no editor de código.
|
|
365
|
+
- [ ] **Agnóstico de Plataforma:** O binário compila e roda sem quebras no Windows, Linux e macOS (Darwin) com comportamento consistente de leitura do sistema de arquivos.
|
|
366
|
+
- [ ] **Resiliência a Erros Sintáticos:** Se o desenvolvedor salvar um arquivo com erros de compilação ou sintaxe quebrada no meio de uma refatoração, o parser AST (Tree-sitter) deve lidar de forma graciosa retornando os símbolos válidos anteriores em vez de crashar o indexador.
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rpcajr/smart-graph-indexer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Smart Graph Code Indexer MCP server in TypeScript",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"graph-indexer": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && copyfiles -u 0 \"wasm/*.wasm\" dist/",
|
|
11
|
+
"start": "node dist/index.js start",
|
|
12
|
+
"index": "node dist/index.js index",
|
|
13
|
+
"package": "pkg . --targets node18-win-x64,node18-macos-x64,node18-linux-x64 --out-path bin/"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@modelcontextprotocol/sdk": "^1.0.1",
|
|
17
|
+
"@xenova/transformers": "^2.17.2",
|
|
18
|
+
"chokidar": "^3.6.0",
|
|
19
|
+
"commander": "^11.1.0",
|
|
20
|
+
"ignore": "^5.3.1",
|
|
21
|
+
"tree-sitter-wasms": "^0.1.13",
|
|
22
|
+
"web-tree-sitter": "^0.20.8"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.11.24",
|
|
26
|
+
"copyfiles": "^2.4.1",
|
|
27
|
+
"pkg": "^5.8.1",
|
|
28
|
+
"typescript": "^5.3.3"
|
|
29
|
+
},
|
|
30
|
+
"pkg": {
|
|
31
|
+
"assets": [
|
|
32
|
+
"dist/wasm/*.wasm"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/graph.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export class DependencyGraph {
|
|
2
|
+
// Map of file relative path -> set of other files/namespaces this file imports (outgoing)
|
|
3
|
+
private adjacencyList: Map<string, Set<string>> = new Map();
|
|
4
|
+
// Map of file/namespace -> set of files that import it (incoming)
|
|
5
|
+
private reverseAdjacencyList: Map<string, Set<string>> = new Map();
|
|
6
|
+
|
|
7
|
+
constructor() {}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adds or updates a file and its dependencies in the graph.
|
|
11
|
+
*/
|
|
12
|
+
public updateFileDependencies(filePath: string, dependencies: string[]) {
|
|
13
|
+
// Clean old dependencies if file already existed
|
|
14
|
+
this.removeFile(filePath);
|
|
15
|
+
|
|
16
|
+
// Set outgoing dependencies
|
|
17
|
+
const outgoing = new Set(dependencies);
|
|
18
|
+
this.adjacencyList.set(filePath, outgoing);
|
|
19
|
+
|
|
20
|
+
// Set incoming dependencies
|
|
21
|
+
for (const dep of dependencies) {
|
|
22
|
+
if (!this.reverseAdjacencyList.has(dep)) {
|
|
23
|
+
this.reverseAdjacencyList.set(dep, new Set());
|
|
24
|
+
}
|
|
25
|
+
this.reverseAdjacencyList.get(dep)!.add(filePath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Removes a file and its edges from the graph.
|
|
31
|
+
*/
|
|
32
|
+
public removeFile(filePath: string) {
|
|
33
|
+
const oldDeps = this.adjacencyList.get(filePath);
|
|
34
|
+
if (oldDeps) {
|
|
35
|
+
for (const dep of oldDeps) {
|
|
36
|
+
const incoming = this.reverseAdjacencyList.get(dep);
|
|
37
|
+
if (incoming) {
|
|
38
|
+
incoming.delete(filePath);
|
|
39
|
+
if (incoming.size === 0) {
|
|
40
|
+
this.reverseAdjacencyList.delete(dep);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
this.adjacencyList.delete(filePath);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Also remove from reverse list (in case this file was imported by others)
|
|
48
|
+
this.reverseAdjacencyList.delete(filePath);
|
|
49
|
+
for (const [node, deps] of this.adjacencyList.entries()) {
|
|
50
|
+
if (deps.has(filePath)) {
|
|
51
|
+
deps.delete(filePath);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Clears the entire graph.
|
|
58
|
+
*/
|
|
59
|
+
public clear() {
|
|
60
|
+
this.adjacencyList.clear();
|
|
61
|
+
this.reverseAdjacencyList.clear();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets direct dependencies (files/namespaces this file imports).
|
|
66
|
+
*/
|
|
67
|
+
public getOutgoing(filePath: string): string[] {
|
|
68
|
+
return Array.from(this.adjacencyList.get(filePath) || []);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets dependants (files that import this file/namespace).
|
|
73
|
+
*/
|
|
74
|
+
public getIncoming(filePathOrNamespace: string): string[] {
|
|
75
|
+
return Array.from(this.reverseAdjacencyList.get(filePathOrNamespace) || []);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Exports the entire graph for debugging/serialization.
|
|
80
|
+
*/
|
|
81
|
+
public serialize() {
|
|
82
|
+
const serialized: Record<string, { imports: string[]; importedBy: string[] }> = {};
|
|
83
|
+
const allNodes = new Set([...this.adjacencyList.keys(), ...this.reverseAdjacencyList.keys()]);
|
|
84
|
+
|
|
85
|
+
for (const node of allNodes) {
|
|
86
|
+
serialized[node] = {
|
|
87
|
+
imports: this.getOutgoing(node),
|
|
88
|
+
importedBy: this.getIncoming(node),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return serialized;
|
|
92
|
+
}
|
|
93
|
+
}
|