Labsco
spuentesp logo

LAIN-mcp

β˜… 7

from spuentesp

Rust MCP server that gives AI coding agents architectural awareness β€” persistent knowledge graph, blast radius analysis, co-change detection via git, and local semantic search. No API keys, runs entirely on-premise.

πŸ”₯πŸ”₯πŸ”₯πŸ”₯βœ“ VerifiedFreeAdvanced setup

LAIN-mcp

LAIN builds a map of how all the code in your project connects β€” what calls what, what depends on what, which files tend to change together. Then it lets your AI coding assistant ask questions about that map. So instead of the AI just looking at one file and guessing, it can ask "if I change this function, what else breaks?" and get a real answer. It plugs into any AI agent that supports MCP and runs in the background while you work.

TL,DR:

Copy & paste β€” that's it
# One-line install (interactive - will ask you to configure and add to PATH)
curl -fsSL https://raw.githubusercontent.com/spuentesp/lain/main/install.sh | bash

# After install: reload your shell (or open a new terminal)
source ~/.zshrc # or ~/.bashrc

# Or non-interactive (skips prompts, auto-adds to PATH)
curl -fsSL https://raw.githubusercontent.com/spuentesp/lain/main/install.sh | \
 bash /dev/stdin --workspace . --transport both --yes

What is Lain?

Lain is a persistent code-intelligence MCP server. It builds a queryable knowledge graph of your codebase β€” symbols and their relationships extracted via LSP and tree-sitter, augmented with git co-change history and optional semantic embeddings β€” and exposes that graph through MCP tools. The value over LSP-only or RAG-based approaches is cross-file structural reasoning: blast radius for proposed changes, transitive dependency traces, anchor identification, co-change correlation, and contextual build failure decoration so agents can reason about callers rather than just the failing line. Written in Rust, persists across sessions, stays fresh during editing via a file watcher that updates a volatile overlay layered on top of the static graph.

Key Features

Query Language (query_graph)

JSON-based ops array for flexible graph traversals:

Copy & paste β€” that's it
{
 "ops": [
 { "op": "find", "type": "Function" },
 { "op": "connect", "edge": "Calls", "depth": { "min": 1, "max": 3 } },
 { "op": "filter", "label": "test" },
 { "op": "semantic_filter", "like": "error handling", "threshold": 0.35 },
 { "op": "limit", "count": 10 }
 ]
}

Available ops: find, connect, filter, semantic_filter, group, sort, limit

Dependency Intelligence

  • get_call_chain β€” Shortest path between two functions

  • get_blast_radius β€” Everything affected by a change

  • trace_dependency β€” What a symbol depends on

  • get_coupling_radar β€” Files that change together

Architectural Analysis

  • find_anchors β€” Most-called, most-stable symbols (architectural pillars)

  • list_entry_points β€” Find main(), route handlers, app initialization

  • get_context_depth β€” How far from an entry point (abstraction layers)

  • explore_architecture β€” High-level tree of modules and files

Search

  • semantic_search β€” Find code by meaning, not just names (uses local ONNX embeddings)

Code Health

  • find_dead_code β€” Potentially unreachable code (filters trait defaults, common names)

  • suggest_refactor_targets β€” High-coupling, low-stability nodes

Build Integration

Lain enriches build failures with architectural context:

  • run_build β€” Build with Rust/Go/JS/Python toolchain error parsing

  • run_tests β€” Tests with error enrichment

  • run_clippy β€” cargo clippy with context

MCP Transport Modes

Mode Command Use Case stdio --transport stdio Claude Code, MCP clients http --transport http --port 9999 Web diagnostics dashboard both --transport both --port 9999 Both stdio + diagnostics

A/B Testing Results

A simple A/B test was run on the asciinema_fix_pty_bug (a small fork i made from https://github.com/asciinema/asciinema.git ) across 5 passes, 4 times using a script. Median numbers are reported.

Metric with_lain without_lain Pass rate 5/5 (100%) 5/5 (100%) Median duration 39.3s 54.1s Median tokens in 35,488 41,731

Key observations:

  • Both conditions passed 100% β€” the bug fix worked in both conditions, with variation per run.

  • with_lain used fewer input tokens (~35k vs ~42k median), a difference of ~7k tokens per run.

About the bug: The failing test (pty::tests::spawn_extra_env on macOS) stems from handle_child() setting env vars via env::set_var() before execvp(). The shell's interpretation of echo -n $VAR varies across platforms β€” sometimes -n is treated as a literal argument. The fix: use printf "%s" "$ASCIINEMA_TEST_FOO" instead, portable across all Unix-like systems.

This was a test I did for A/B comparison β€” not a rigorous evaluation.

License

MIT β€” Copyright (c) 2026 spuentesp