Code Intelligence (MCI)
A queryable semantic map of your codebase — every function, class, and route is a symbol; every call, import, and test relationship is an edge. Shared across every agent in your workspace.
What MCI is, in plain English
Your codebase is a graph — every function connects to every function that calls it, every file it imports, every test that covers it. MCI builds and maintains that graph so AI agents (and humans) can answer two questions that normally take an hour:
- Where is the thing that does X? — by meaning, not text. Search
"user signup flow" and find the right function even when it's named
createInitialAccountand never uses the word "signup." - What breaks if I change this? — every caller, every test, every file that historically changes alongside it. Before the edit, not after the bug.
Everything else MCI does (architectural tours, cluster maps, multi-agent coordination) is downstream of that graph. Finding and impact are why it earns its keep.
https://mcp.momentalos.com/mcp/v3. Legacy momental_code_* tool names from v1 still work as translating stubs — see the v1 → v3 mapping for the full table.
The four tools
| Tool | Actions | What it answers |
|---|---|---|
code_search | find, search, file | "Where is X?" — exact lookup, hybrid semantic + BM25, all-symbols-in-file with callers/callees inline |
code_inspect | symbol, blast, deps, diff_impact, rename_impact, tests, traces | "What breaks if I change X?" — 360° symbol view, blast radius, dependency tree, change-impact, rename-impact, test coverage, runtime traces |
code_map | clusters, map, tour, graph | "How is this codebase organised?" — Louvain clusters, Mermaid diagram, persona-tuned tour, raw graph queries |
code_manage | register, list, clear, delete, check_pending, submit_index, update_files, embed, cochange, references, claim, active, review | Repo registration, indexer ingest endpoints, multi-agent file-claim coordination, Vega review hand-off |
Full schemas in the MCP Tool Reference (items 27–30).
Graph model
| Element | Detail |
|---|---|
| Symbol | id, qualifiedName, name, filePath, startLine, endLine, kind (FUNCTION, CLASS, INTERFACE, TYPE, METHOD, CONSTANT, VARIABLE, EXPORT), signature, docstring, isExported, isEntryPoint |
| Edge | fromQualifiedName, toQualifiedName, edgeType (CALLS, IMPORTS, EXTENDS, IMPLEMENTS, REFERENCES, RE_EXPORTS, TESTS), optional confidence, filePath, callLine |
| Reference | LSP-sourced (TS auto-detected). Enables type refs, generics, decorators, JSX usage in code_inspect blast. Submitted via code_manage action:references. |
| Co-change pair | fileA, fileB, coChangeCount, frequency from git log. Submitted via code_manage action:cochange. |
| Cluster | Louvain community of related symbols, named by an LLM (claude-haiku) on first compute. |
| Embedding | Per-symbol semantic vector. Without embeddings, code_search action:search falls back to BM25 with degraded: true. |
Languages with full AST extraction: TypeScript, JavaScript, Python, Go. Swift uses regex-based same-file CALLS only.
The npm package: @momentalos/cli
The indexer and agent listener ship as one published package: @momentalos/cli. Requires Node.js 20+.
npm install -g @momentalos/cli Or run without installing:
npx -p @momentalos/cli momental-indexer --help
npx -p @momentalos/cli momental-agent --help Three bins
| Bin | Purpose |
|---|---|
momental | CLI router — momental index …, momental agent, momental completion |
momental-indexer | The MCI indexer — parses your codebase and submits the symbol graph. This is what populates the graph the four code_* tools query. |
momental-agent | The agent listener daemon — outbound WSS to the Momental relay; spawns Claude Code when tasks are assigned to your agent. No inbound ports required. |
Environment variables
| Variable | Default | Purpose |
|---|---|---|
MOMENTAL_API_KEY | — | API key (mmt_*); alternative to --api-key |
MOMENTAL_MCP_URL | https://mcp.momentalos.com/mcp/v3 | MCP endpoint override |
MOMENTAL_AGENT_ID | — | Agent ID for coding-tool keys (find in .mcp.json) |
API key auto-discovery (first hit wins): --api-key flag → $MOMENTAL_API_KEY → .mcp.json walked up to home → ~/.claude.json → ~/.momental/config.json.
Indexing — full vs. incremental
Indexing populates the graph for one repo. There are two paths:
- Full index wraps
code_manage action:submit_index, which is an atomic full replacement of all symbols + edges for thatrepoId. - Incremental reindex wraps
code_manage action:update_files, which deletes stale symbols for the listed files and inserts the new ones. Co-change pairs, embeddings, and references for unchanged files are preserved.
First-time full index
momental-indexer \
--dir . \
--api-key mmt_YOUR_KEY \
--name my-repo \
--ts-calls \
--ts-tests \
--git-cochange \
--git-sha "$(git rev-parse HEAD)" Pipeline:
- Calls
code_manage action:register(or reuses--repo-id) → returnsrepoId. - Walks the source tree, respecting
.gitignoreand--exclude. - Extracts symbols via AST (TypeScript Compiler API, python3 AST, go compiler, Swift parser); falls back to enhanced regex if a runtime is missing.
- Builds edges: IMPORTS, EXTENDS, IMPLEMENTS, plus type-aware CALLS when
--ts-calls. - Optional: TESTS edges (
--ts-tests), DI edges (--ts-di), git co-change pairs (--git-cochange), LSP references (auto-detected for TS). - Submits via
code_manage action:submit_index— atomic full replacement. - Follow-ups:
submit_referencesif LSP refs were extracted;cochangeif--git-cochangeran.
After the full index lands, kick off semantic embeddings asynchronously:
# via MCP — generates embeddings for all symbols missing them
code_manage({ action: "embed", repoId }) Embedding takes ~1 minute per ~1k symbols. Until embeddings exist, code_search action:search returns degraded: true and ranks via BM25 alone.
Incremental reindex on top of an existing index
Use this after editing files — much faster than a full re-index, and preserves co-change pairs and embeddings for files you did not touch.
Stdin file list (typical CI / git-hook):
git diff --name-only HEAD~1 HEAD | \
momental-indexer \
--dir . \
--repo-id <existing-repo-id> \
--incremental-files - \
--git-sha "$(git rev-parse HEAD)" Explicit file list:
momental-indexer \
--dir . \
--repo-id <existing-repo-id> \
--incremental-files src/auth.ts,src/billing.ts Behind the scenes the indexer:
- Parses only the listed files.
- Calls
code_manage action:update_fileswith{ repoId, filePaths, symbols, edges }. - The handler deletes stale symbols for those files, then inserts the new ones.
- Co-change pairs, embeddings, and references for unchanged files are untouched.
update_files is the canonical "incremental on top of existing index" entry point. submit_index, by contrast, is always a full wipe-and-replace for the repo.
Pending-reindex signal (UI-triggered reindex)
When a user clicks "Reindex" in the Momental UI (or another process wants the indexer to re-run), the request is recorded as a pending reindex on the repo row. An indexer running in --watch mode polls for those requests and runs a full index when one appears:
momental-indexer \
--dir . \
--repo-id <existing-repo-id> \
--watch 30 # poll interval in seconds Programmatic check:
code_manage({ action: "check_pending" })
# → repos where reindexRequestedAt > lastIndexedAt --watch requires --repo-id (the watched repo). Use this on a long-running developer machine or a CI box to keep one repo continuously up to date with UI-triggered requests.
CI integration (GitHub Actions)
Full index on main:
- name: Index codebase
run: |
npm install -g @momentalos/cli
momental-indexer \
--dir . \
--api-key "${{ secrets.MOMENTAL_API_KEY }}" \
--name my-repo \
--ts-calls --ts-tests --git-cochange \
--git-sha "$(git rev-parse HEAD)" Incremental on PR (only changed files):
- name: Incremental MCI update
run: |
git diff --name-only origin/main...HEAD | \
momental-indexer \
--dir . \
--repo-id "${{ secrets.MOMENTAL_REPO_ID }}" \
--incremental-files - \
--git-sha "$(git rev-parse HEAD)" \
--quiet Most-used indexer flags
| Flag | Meaning |
|---|---|
--dir <path> | Root directory to index (default: cwd) |
--api-key <key> | API key (mmt_*); or set MOMENTAL_API_KEY |
--name <name> | Repo display name in Momental (default: directory name) |
--repo-id <id> | Existing repo ID — skips registration; required for incremental and --watch |
--lang <lang> | typescript (default), javascript, python, go, swift |
--ts-calls | Type-aware CALLS via TS compiler API (recommended; auto-detected with tsconfig.json) |
--ts-tests | TESTS edges from test files → source files (auto-enabled) |
--ts-di | NestJS / Angular constructor injection CALLS (auto-detected) |
--git-cochange | Parse git log for files-that-change-together pairs |
--cochange-limit N | Max commits scanned for co-change (default 500) |
--git-sha <sha> | Record current commit SHA in repo metadata |
--incremental-files -|<list> | Reindex only listed files (stdin or comma-separated list) |
--watch <seconds> | Poll for UI-triggered reindex requests; runs full index when one appears |
--exclude <paths> | Comma-separated dirs to skip relative to --dir |
--dry-run | Parse only — no submission |
--quiet / -q | Suppress non-error output |
--version | Print indexer version and exit |
Daily usage — the agent playbook
For agents and humans both, MCI replaces grep / glob / cold reads. The mandate inside Momental's own agents:
Before touching any file — search MCI first.
Before modifying any function — check its blast radius first.
Before writing any code — claim your files first.
Recommended startup sequence (every session)
1. code_manage({ action: "list" }) # what repos are indexed
2. code_map({ action: "tour", repoId, persona: "agent" }) # for new codebases — dependency-ordered learning path
3. code_manage({ action: "claim", repoId, filePaths, taskId }) # before edits
4. code_inspect({ action: "diff_impact", repoId, filePaths }) # blast + testsToRun[] before writing
5. ... do the work ...
6. code_inspect({ action: "tests", repoId, filePath }) # exactly the right tests, not all tests Don't do these without MCI first
| Banned shortcut | MCI alternative |
|---|---|
grep -r "functionName" | code_search({ action: "find", name: "functionName" }) |
grep -r "concept" | code_search({ action: "search", query: "concept" }) |
cat src/service.ts (cold) | code_search({ action: "file", repoId, filePath }) — callers/callees inline |
| Editing without context | code_inspect({ action: "blast", symbolIds }) first |
| Starting any edit | code_manage({ action: "claim", repoId, filePaths, taskId }) first |
grep misses callers in other files. A change that looks local often has 10 upstream callers you'll never find without MCI.
Multi-agent coordination
code_manage action:claim is advisory, not a hard lock. TTL is 600 s by default; refresh with another claim call every ~480 s on long sessions. Conflicts are returned as warnings (with the colliding agent's id), not hard errors. Pass force: true to proceed despite a conflict (after coordinating via the Agent Room or task comments).
See live claims:
code_manage({ action: "active", repoId })
# → { activeAgents: 3, claims: [{ agentId, filePaths, ttlRemainingSeconds, isExpired }] }
Architecture notes & non-obvious behavior
Aspect Behavior Search ranking code_search action:search is hybrid: BM25 + cosine over embeddings, normalised to [0, 1]. Relevance labels: HIGH ≥ 0.7, MEDIUM ≥ 0.4, LOW < 0.4. Degraded mode If a repo has no embeddings, the result includes degraded: true and BM25-only results are served. Run code_manage action:embed to enable semantic ranking. Blast radius depth Default maxDepth: 5, max 8. isPartialResult: true indicates at least one node was reached at maxDepth — paths beyond that are truncated. Risk levels code_inspect blast returns riskLevel: P0…P5 | UNKNOWN. UNKNOWN means the graph has no CALLS edges to walk (typical of repos indexed without --ts-calls). Cluster naming Louvain community detection; cluster names are LLM-generated (claude-haiku) on recompute: true. Cost ≈ $0.001 per cluster. Falls back to directory-derived names if the LLM is unavailable. Path normalisation code_inspect diff_impact accepts package-relative, src-relative, or git-root-relative paths and normalises to the indexer's storage form. Module-import edges code_inspect symbol flags file-level imports with isModuleImport: true — render as "imported by" rather than "called by". Test detection code_inspect tests requires the indexer ran with --ts-tests (auto-enabled in current versions). Returns runCommand like pnpm test <first-test-file>. Idempotent register code_manage register upserts on (teamId, lower(trim(repoUrl ?? name))) — no duplicate rows on re-run. Privacy The indexer transmits only symbol names, signatures truncated at the first {, docstrings, and line numbers. No source code is sent.
Troubleshooting
Symptom Likely cause / fix code_search action:search returns degraded: true No embeddings yet — call code_manage action:embed, wait ~1 min per 1k symbols. code_inspect action:blast returns riskLevel: UNKNOWN Repo was indexed without --ts-calls. Re-run the indexer with --ts-calls. code_inspect action:tests returns no tests Indexer didn't emit TESTS edges. Re-index with --ts-tests (auto-enabled in v3.x indexer). Python / Go / Swift symbols present, edges very sparse Install python3 / go for AST-based extraction. Swift cross-file CALLS are not supported. momental-indexer: No Momental API key found Pass --api-key mmt_…, set $MOMENTAL_API_KEY, or place the key in .mcp.json / ~/.claude.json / ~/.momental/config.json. Cluster names look like file paths LLM was unavailable when clusters were last computed — re-run with code_map({ action: "clusters", repoId, recompute: true }). Claim conflicts on long-running edit Refresh the claim every ~480 s with another code_manage action:claim call (TTL is 600 s). Reindex never picks up new commits Either run momental-indexer (incremental or full), or run it with --watch <seconds> so UI-triggered check_pending requests fire automatically.
Install the indexer npm install -g @momentalos/cli
First full index momental-indexer \
--dir . \
--api-key mmt_YOUR_KEY \
--name my-repo \
--ts-calls --ts-tests \
--git-cochange
Incremental reindex git diff --name-only HEAD~1 | \
momental-indexer \
--repo-id <id> \
--incremental-files -
Find webhook auth code_search({
action: "search",
query: "webhook authentication"
})
Blast radius of a PR code_inspect({
action: "diff_impact",
repoId,
filePaths: [
"src/routes/payments.ts",
"src/services/billing.ts"
]
})
Claim before editing code_manage({
action: "claim",
repoId,
filePaths: ["src/auth.ts"],
taskId
})