- 2026-10-22
- 6 minuti
tokensave: algoritmi su grafo semantico, MCP server e context builder

Questo è il quarto e ultimo articolo della serie sull’architettura interna di tokensave. Nel primo articolo abbiamo introdotto il concetto di grafo semantico e la pipeline ad alto livello; nel secondo abbiamo analizzato il modello dei dati e la fase di estrazione. Qui vediamo come il grafo viene interrogato: algoritmi di traversata, analisi statiche, server MCP e context builder per gli agenti AI.
Gli algoritmi sul grafo
Il modulo graph/ implementa algoritmi classici di teoria dei grafi applicati al codice.
Traversata BFS/DFS (graph/traversal.rs)
La traversata generica supporta:
- Direzione: forward (seguendo archi uscenti) o backward (archi entranti)
- Filtraggio per tipo di arco
- Profondità massima configurabile
Su questa base vengono costruite tutte le operazioni di navigazione del grafo:
| Operazione | Descrizione |
|---|---|
| Callers | BFS backward su archi Calls — chi chiama questa funzione? |
| Callees | BFS forward su archi Calls — cosa chiama questa funzione? |
| Impact radius | BFS multi-arco — quali simboli sono raggiungibili da questo nodo? |
| Call graph | Espansione bidirezionale da una funzione |
| Type hierarchy | Traversata su archi Implements e Extends |
| Shortest path | BFS tra due nodi qualsiasi |
Analisi statiche (graph/queries.rs)
Oltre alle traversate, il modulo implementa analisi di più alto livello:
- Dead code: nodi senza archi
Calls/Usesentranti (esclusi i file) - Dipendenze circolari: algoritmo di Tarjan (SCC — Strongly Connected Components) sugli archi di import a livello di file
- Dipendenze e dipendenti di un file: quali file usa? da quali è usato?
L’algoritmo di Tarjan lavora sul grafo compresso dei file (non dei singoli simboli), rendendo l’analisi efficiente anche su codebase molto grandi. Identifica le Strongly Connected Components: gruppi di file che si importano reciprocamente in modo circolare, un segnale di accoppiamento eccessivo da tenere sotto controllo.
Il server MCP
Il modulo mcp/ implementa un server Model Context Protocol che gira su stdio con JSON-RPC 2.0. Ogni richiesta di un agente AI viene deserializzata, instradata all’handler corrispondente, e la risposta viene serializzata e restituita.
I tool MCP sono organizzati in categorie:
| Categoria | Esempi |
|---|---|
| Ricerca | tokensave_search, tokensave_context, tokensave_node |
| Navigazione | tokensave_callers, tokensave_callees, tokensave_impact |
| Analisi | tokensave_complexity, tokensave_dead_code, tokensave_circular |
| Metriche | tokensave_rank, tokensave_hotspots, tokensave_gini |
| Qualità | tokensave_doc_coverage, tokensave_recursion |
| Git | tokensave_changelog, tokensave_commit_context |
Ogni chiamata a un tool registra anche la stima dei token risparmiati: la differenza tra i token che sarebbero stati consumati leggendo i file raw e quelli effettivamente usati dalla risposta del tool. Il totale viene accumulato nel database locale e, opzionalmente, in un contatore globale anonimo.
Il context builder per gli agenti AI
Il modulo context/builder.rs è il punto di integrazione più importante per gli agenti: dato un task in linguaggio naturale, costruisce un TaskContext pronto per essere inserito nel prompt dell’agente.
Il processo è:
- Estrazione dei termini chiave dalla query (splitting camelCase, heuristics)
- Ricerca FTS5 su nome, qualified name, firma e docstring dei nodi
- Espansione tramite grafo: i nodi trovati vengono espansi seguendo gli archi per includere caller, callee e tipi correlati
- Lettura del codice sorgente per i nodi più rilevanti
- Assemblaggio e ranking del
TaskContextfinale
Keyword expansion vs embedding vettoriali
Un dettaglio di design interessante: tokensave sceglie deliberatamente keyword expansion (gestita dall’agente LLM) invece di embedding vettoriali.
| Keyword expansion | Embedding locali | |
|---|---|---|
| Costo di indicizzazione | Zero | ~30s per 1.000 nodi |
| Latenza di query | ~1ms (FTS5) | ~200ms (cosine similarity) |
| Impatto sul binario | Nessuno | +15-20 MB (ONNX runtime) |
| Qualità concettuale | Dipende dall’LLM | Migliore per naming opaco |
Se la codebase usa nomi come guardianGateway per l’autenticazione, gli embedding vettoriali la troverebbero per similarità distribuzionale; le keyword la trovano solo se l’agente è abbastanza “furbo” da includere il termine nel suo array keywords. In pratica, un LLM moderno è sufficientemente capace da coprire la grande maggioranza dei casi.
I tier di supporto linguistico
Per controllare dimensione del binario e tempo di compilazione, i linguaggi sono organizzati in tier selezionabili tramite feature flag Cargo:
| Tier | Feature | Dimensione approssimativa | Linguaggi inclusi |
|---|---|---|---|
| Lite | sempre attivo | ~30 MB | Rust, Go, Java, TypeScript/JS, Python, C/C++, Kotlin, C#, Swift, Scala |
| Medium | --features medium | ~80 MB | + Dart, Pascal, PHP, Ruby, Bash, Protobuf, PowerShell, Nix, VB.NET |
| Full | default | ~150 MB | + Lua, Zig, Obj-C, Perl, Fortran, COBOL, BASIC dialetti, e altri |
Conclusioni
tokensave è un esempio di come una scelta architetturale ben precisa — costruire un grafo semantico offline invece di leggere file on-demand — possa cambiare radicalmente l’efficienza di un sistema.
L’implementazione in Rust rispecchia questa filosofia: parser compilati (tree-sitter), storage embedded (libSQL/SQLite), algoritmi efficienti sul grafo (BFS, Tarjan SCC), tutto senza dipendenze di runtime esterne. Il risultato è un binario autonomo che risponde in millisecondi alle domande che un agente AI altrimenti risolverebbe leggendo megabyte di codice.
Se vuoi esplorare il grafo del tuo progetto in prima persona, inizia con:
tokensave init # crea .tokensave/tokensave.db
tokensave status # mostra statistiche sul grafo
tokensave tool # lista tutti i tool MCP disponibili
Riferimenti
- Sorgente tokensave 7.4.0: crates.io/crates/tokensave
- Repository ufficiale: github.com/aovestdipaperino/tokensave
- tree-sitter: tree-sitter.github.io
- Model Context Protocol: modelcontextprotocol.io
- Algoritmo di Tarjan (SCC): wikipedia.org/wiki/Tarjan’s_strongly_connected_components_algorithm













