Last week a friend sent me a screenshot. His AI assistant had just spent eleven tool calls and most of a context window hunting for a function he could have pointed it to in two seconds. "Is it always this dumb?" he asked.

It isn't. It's just navigating blind.

Out of the box, most AI coding tools navigate your project with text search — grep, ripgrep, glob patterns. That works fine on a toy repo and falls apart on a real one — not because grep can't find things, but because it finds too many. Two thousand unranked matches, and the agent burns its context reading the wrong twelve files. The fix is to let it narrow structurally before it reads anything, through a real retrieval tool over MCP — and the fastest one I know to set up is Octocode. We wrote about why semantic code search beats grep already — this post is the part where you actually plug it in.

Five minutes, start to finish. These are the steps.

What You're Building

Octocode is an open-source (Apache 2.0) MCP server written in Rust. It parses your code with tree-sitter into real symbols — functions, classes, imports — builds a knowledge graph of how those pieces relate, and exposes four tools to any MCP-compatible client:

ToolWhat your agent gets
semantic_searchFind code by meaning — "where do we validate tokens?" returns the function, not 300 keyword hits
view_signaturesThe structure of a file — signatures, classes, imports — without reading the whole thing
graphragRelationship queries — "what calls this?", "what does this import?"
structural_searchAST pattern matching — every .unwrap(), every new instantiation, specific shapes

(One optional extra: start the server with --with-lsp="rust-analyzer" — or your language's server — and it also exposes LSP tools: go-to-definition, find-references, hover docs — compiler-grade precision alongside the search tools.)

Once it's connected, your assistant stops grepping and starts navigating. That's the whole pitch.

One honest caveat before we start: if your repo is small enough that ripgrep already finds everything in one hop, this is overkill — keep using ripgrep. The setup below pays off when searches come back with hundreds of matches and your agent starts reading the wrong ones.

Step 1: Install Octocode

One line on macOS, Linux, or Windows:

bash
curl -fsSL https://raw.githubusercontent.com/Muvon/octocode/master/install.sh | sh

On a Mac, Homebrew works too:

bash
brew install muvon/tap/octocode

Prefer to build it yourself? It's Rust, so:

bash
cargo install --git https://github.com/Muvon/octocode

Confirm it landed:

bash
octocode --version

Step 2: Give It an Embedding Provider

Semantic search needs an embedding model to turn code into vectors. Octocode supports several providers, and the default recommendation is Voyage AI — partly because their free tier is genuinely generous (200M free tokens a month, which is more than enough for most projects):

bash
export VOYAGE_API_KEY="your-voyage-api-key"

Grab a key at voyageai.com. Prefer a provider you already pay for? Point Octocode at it:

bash
# OpenAI
export OPENAI_API_KEY="your-key"
octocode config --code-embedding-model "openai:text-embedding-3-small"

# Jina AI
export JINA_API_KEY="your-key"
octocode config --code-embedding-model "jina:jina-embeddings-v3"

# Google
export GOOGLE_API_KEY="your-key"
octocode config --code-embedding-model "google:text-embedding-005"

On default macOS ARM builds, local embedding models are available too — useful if you'd rather no metadata ever leaves the machine. (More on the privacy model below.)

One optional extra: if you want Octocode's commit-message and review features later, set an LLM key as well — export OPENROUTER_API_KEY="your-key". Not needed for search.

Step 3: Index Your Project

Move into your repository and index it once:

bash
cd /your/project
octocode index
# → Indexed 12,847 blocks across 342 files

This is the step people skip before wondering why search returns nothing. To be precise about which tools need it: semantic_search queries the index — no index, empty results. The other three read your source live — graphrag builds its graph lazily with tree-sitter, and view_signatures and structural_search parse files on demand — so they work either way. But semantic search is the tool your agent will reach for most, so index first. Octocode respects your .gitignore, so it won't crawl node_modules, build artifacts, or secrets.

Sanity-check it from the CLI before you wire anything up:

bash
octocode search "authentication middleware"
# → src/middleware/auth.rs | Similarity 0.923

If that returns sensible files, the index is healthy and the MCP server will be too.

Step 4: Connect Your AI Assistant

This is where it pays off. The MCP server is one command — octocode mcp --path /your/project — and every client wires it slightly differently.

Claude Code

A single command registers it:

bash
claude mcp add octocode -- octocode mcp --path /path/to/your/project

Restart your session and the four tools are available. Ask "where is rate limiting handled?" and watch it call semantic_search instead of spraying grep.

Codex

Codex has the same one-command registration:

bash
codex mcp add octocode -- octocode mcp --path /path/to/your/project

Or edit ~/.codex/config.toml directly:

toml
[mcp_servers.octocode]
command = "octocode"
args = ["mcp", "--path", "/path/to/your/project"]

Two traps specific to Codex. First, its config is TOML, not JSON — the table is mcp_servers with an underscore, and writing [mcpServers.octocode] out of JSON habit parses fine but is silently ignored. Second, if your embedding key lives in a shell profile Codex doesn't source, pass it explicitly: codex mcp add octocode --env VOYAGE_API_KEY=your-key -- octocode mcp --path /path/to/your/project.

Cursor

Edit ~/.cursor/mcp.json (or use Settings → MCP Servers):

json
{
	"mcpServers": {
		"octocode": {
			"command": "octocode",
			"args": ["mcp", "--path", "/path/to/your/project"]
		}
	}
}

Claude Desktop and Windsurf

Same JSON shape, different file:

json
{
	"mcpServers": {
		"octocode": {
			"command": "octocode",
			"args": ["mcp", "--path", "/path/to/your/project"]
		}
	}
}
  • Claude Desktop (macOS): ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windsurf: Settings → MCP

Octocode's docs cover 15+ clients — VS Code via Cline or Continue, Zed, Replit, and more — but the pattern never changes: it's always command: "octocode", args: ["mcp", "--path", "..."].

Working across several repos? One server can cover them all: octocode mcp --multi --path /parent/dir serves every git repository one level under that path, and each tool call picks its repo with a project argument.

Octomind (the zero-setup path)

If you're using Octomind as your agent runtime, you don't do any of this. Octocode ships as a capability in the tap system and auto-activates when your message looks like a code-search task — semantic search becomes one of several capabilities the runtime turns on only when needed, so you're not paying for the tool surface when you don't use it. Just run a developer agent:

bash
octomind run developer:general

What It Looks Like When It Works

Same question, before and after:

Before — grep path: "find the API error handling" → 891 matches → the agent reads eight files → greps again → reads four more → finally answers, ~20,000 tokens spent on navigation.

After — MCP path:

text
You: "Where is user authentication implemented?"
AI: (uses semantic_search) "Found in src/auth/login.rs. authenticate()
    validates credentials, generates a JWT, and stores the session in Redis."

You: "What files depend on the payment module?"
AI: (uses graphrag) "src/api/handlers/payment.rs imports payment/mod.rs,
    which is also used by src/workers/refund.rs and src/cron/billing.rs."

The difference isn't that grep couldn't have found the answer — it's that grep hands back an unranked pile and makes the agent do the ranking with its context window. Octocode narrows structurally first: signatures to see a file's shape without reading it, the graph to follow real edges instead of guessing, semantic search to rank by meaning. The agent spends its context budget reasoning about your code instead of finding it. (And the ranking holds up: on Octocode's own retrieval benchmark — 254 hand-annotated queries — code search puts the right file in the top 10 results 99.2% of the time.)

A Note on Privacy

The question I get most: does my code get uploaded? Let me answer it precisely, because the honest answer is better than the vague one. The index lives on your machine, and search never touches the network — the MCP server answers every query locally. The one step that does is indexing: computing a vector for a chunk of code means sending that chunk to your embedding provider, the same way any embedding API works. It's used to compute the vector and nothing is stored or searchable remotely. If even that is more than your threat model allows, run the local embedding model (included in default macOS ARM builds) and nothing leaves the machine at all. Octocode also respects .gitignore, so the files you'd never want indexed are never indexed.

Keep the Index Fresh

The one gotcha worth knowing: the index is a snapshot. If you've just merged a big branch and search feels stale, re-run octocode index — it's incremental, so it only processes what changed. Make it a habit, or wire it into a post-merge git hook and forget about it. (If results are still off after reindexing, I wrote a whole Octocode MCP troubleshooting guide for exactly that.)

That's It

Install, set one API key, octocode index, register one MCP server in your client. Your AI assistant goes from grepping in the dark to navigating your architecture by meaning — across files, through the dependency graph, in milliseconds.

If you want the deeper "why this matters" version — token economics, embeddings, the lost-in-the-middle problem — read Your AI Agent Wastes Most of Its Time Just Finding Code. And if you want to understand how MCP tools plug into an agent in the first place, the MCP Tools Deep Dive covers the protocol end to end.

Get Octocode — give your agent eyes.