> ## Documentation Index
> Fetch the complete documentation index at: https://recipe.uselettuce.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tools

> Reference for the lettuce MCP tools.

<Note>
  On **cloud**, every tool takes a `repo` argument naming one of your repos,
  and the full surface below is available. On a **local** stdio server
  ([Run locally](/local)) `repo` is a path (or omit it and set `LETTUCE_DB`),
  and the default surface is just `understand` + `read_snippet` — set
  `CODEWAZE_MCP_FULL=1` to expose everything else.
</Note>

Every tool takes a `repo` argument naming one of your repos. Each call
returns compact rows with `id`, `kind`, `qualified_name`, `path`,
`line_start` / `line_end`, `signature`, and `summary` fields. The
relationship tools (`neighbors`, `callers`, …) also tag rows with the
`edge_kind` (`calls`, `imports`, `contains`, `inherits`, `references`)
and `direction` that led there.

## High-level tools (start here)

Most agents only need these three.

<ResponseField name="understand(repo, task)">
  Returns candidate symbols, code, callers, callees, related docs, and a
  `confidence` score (0..1) for `task` in `repo`. Answers most questions
  in one call.
</ResponseField>

<ResponseField name="route(repo, task)">
  Returns ranked candidate symbols (with code) for `task` in `repo`, plus
  a `confidence` level (`high` / `medium` / `low` / `none`).
</ResponseField>

<ResponseField name="locate(repo, query, candidates?)">
  Returns the top candidates in `repo` for `query`. Each carries
  `file:line`, signature, code, callers, and callees.
</ResponseField>

## Finding code

<ResponseField name="search(repo, query, kind?, limit?)">
  Search symbols in `repo` matching `query`. Matches across names,
  signatures, summaries, and paths — `button` also matches `IconButton`.
</ResponseField>

<ResponseField name="find_symbol(repo, name, kind?, fuzzy?)">
  Find symbols by exact name in `repo` (or `LIKE` pattern when
  `fuzzy=true`).
</ResponseField>

<ResponseField name="entry_points(repo, limit?)">
  Return the nodes with the highest incoming-edge count in `repo`.
</ResponseField>

## Following relationships

<ResponseField name="callers(repo, node_id) / callees(repo, node_id)">
  Nodes that call this node, and nodes called by it.
</ResponseField>

<ResponseField name="imports_of(repo, node_id) / imported_by(repo, node_id)">
  Modules imported by this node, and nodes that import it.
</ResponseField>

<ResponseField name="neighbors(repo, node_id, direction?, edge_kinds?)">
  1-hop neighbors of a node. Each row carries the `edge_kind` and
  `direction` that led there.
</ResponseField>

<ResponseField name="find_path(repo, src_id, dst_id, edge_kinds?)">
  Shortest path between two nodes, or `{"path": null}`.
</ResponseField>

<ResponseField name="transitive(repo, node_id, direction, edge_kinds?, max_depth?)">
  Nodes transitively reachable from a node along the given edge kinds.
  Each row carries its `depth`.
</ResponseField>

<ResponseField name="subgraph(repo, node_id, depth?, max_nodes?)">
  Bounded subgraph around a node.
</ResponseField>

## Reading source

<ResponseField name="summary(repo, node_id)">
  A single node row: `file:line`, signature, docstring first line.
</ResponseField>

<ResponseField name="read_snippet(repo, node_id?, path?, name?, line_start?, line_end?, around?, context_lines?, max_lines?)">
  Read source. Pass a `path` (optionally with `line_start`/`line_end` or
  `around` a line), a `name`, or a `node_id` from an earlier result.
  Lines are line-numbered; ranges longer than `max_lines` are truncated.
</ResponseField>

## A typical flow

For a request like *"add rate limiting to the `/login` endpoint"*:

1. `understand(repo, "add rate limiting to the /login endpoint")` →
   candidate symbols with code, callers, callees, and related docs. Often
   enough to answer.
2. If you need to see more of the file: `read_snippet(repo, node_id, …)`.

To drive the navigation by hand:

1. `search(repo, "login")` → the endpoint, with `file:line`.
2. `callers(repo, id)` → who routes and tests it.
3. `callees(repo, id)` → what it already depends on.
4. `search(repo, "rate limit", fuzzy=true)` → locate the helper.
5. `find_path(repo, ...)` → confirm it isn't already wired in.
6. `read_snippet(repo, node_id=id)` → read just those lines, then edit.
