get_symbol
Raw source bytes for one indexed symbol with exact line bounds, cheaper and safer than reading the whole file and counting offsets. The only MCP tool that returns actual source code.
Every other tool returns context about code. get_symbol returns the
code itself: the raw source bytes of a single indexed symbol with
its exact start/end lines. It's the precise, bounded alternative to a
full-file Read followed by offset arithmetic. It also serves live
range reads and resolves omission refs (repowise#<12-hex>) from
truncated responses.
When to call
- You need one function or class body, not the whole file.
- After
get_context: pipe thesymbol_idfrom its symbol list straight in. - To confirm a signature or implementation before editing, without pulling 800 unrelated lines into the context window.
- For anything between symbols: imports, module docstrings, or a
decorator, with a
path.py:140-180range read. - To restore truncated content: when a response's
_meta.omittedlists refs and you have no shell forrepowise expand(e.g. Claude Desktop).
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
symbol_idrequired | string | — | One of three forms: "path/to/file.py::SymbolName" (canonical, from get_context's symbol list, separator normalised across languages: ::, ., /), "path/to/file.py:140-180" (a live range read, 200 lines max), or an omission ref "repowise#<12-hex>" / a pasted whole [repowise#…] marker. |
id | string | — | Accepted alias for symbol_id. symbol_id wins when both are given. |
query | string | — | Omission refs only: return just the stored lines matching this regex (or substring). Ignored for symbol ids and range reads. |
context_lines | number | 0 | Extra source lines to include before and after the symbol (0 to 50). |
depth | number | 1 | Follow the call graph outward from this symbol and include what it calls, with bodies, in callee_bodies (1 to 3). 1 is this symbol alone. Out-of-range values clamp rather than error. |
repo | string | — | Repository alias. Usually omitted. "all" is not supported. get_symbol resolves one symbol in one repo. |
Returns
For a symbol id or a range read:
| Field | Meaning |
|---|---|
symbol_id | The resolved canonical id |
source | The symbol's source bytes (bounded at ~600 lines), each line prefixed with its file line number in the same format as a Read result |
start_line, end_line | Exact 1-based line bounds in the file |
kind | function, class, method, … (range reads: "range") |
language | Detected language tag (symbol ids only) |
truncated | true if the body exceeded the line bound and was cut |
verified | Bounds were checked (or corrected) against the live file. Always true for a range read |
On a miss, returns { error: "Symbol not found …" } with the closest
candidate ids (suggestions) so the agent can retry without another
get_context call, or fallback_lines from a live grep when the name
matches a live line that isn't an indexed symbol (a constant, import,
or alias).
For an omission ref, returns the stored content plus provenance
(source, created_at, original_tokens) instead.
With depth above 1, the response also carries callee_bodies: the
symbols this one calls, transitively, each with its depth (hops from
the root), source, and a verified flag. Every symbol appears once, at
the shallowest depth it was reached from. Callees past the response
budget are listed in not_rendered with a fetch_with range that
retrieves them, so a bounded walk never reads as a complete one.
Example
get_symbol("src/auth/service.py::AuthService")
get_symbol(
symbol_id="src/auth/service.py::login",
context_lines=10,
)
# Follow the call graph one hop out, bodies included
get_symbol(symbol_id="src/auth/service.py::login", depth=2)
# Anything that falls between indexed symbols
get_symbol("src/auth/service.py:140-180")
# Restore content a truncated response stashed behind a marker
get_symbol("repowise#a1b2c3d4e5f6")
get_symbol("repowise#a1b2c3d4e5f6", query="FAILED")Things worth knowing
- Ambiguous, not silently resolved. When a name resolves to more
than one definition (overloads, re-exports, conditional definitions),
the response has
ambiguous: trueand acandidateslist carrying every matching body, none picked for you. Candidates past the response budget appear innot_renderedwith afetch_withrange read. - Separator-agnostic.
file.py::Name,file.py.Name, andfile.py/Nameall resolve; use whateverget_contexthanded you. - Bounded by design. The ~600-line cap keeps a single call from
blowing the context window on a giant generated file;
truncatedtells you when that happened, with acontinuationrange to fetch the remainder in one more call. - Range reads are always live.
path.py:140-180slices the current file on disk (200 lines max), soverifiedis alwaystrue.
Pair it with get_context: get_context
returns the symbol_ids and signatures, get_symbol fetches the one
body you actually need. Two calls, zero file reads.
get_context
The workhorse tool. Compact, batched context for any set of files, modules, or symbols: docs, ownership, freshness, and optional callers/callees/metrics/community in one call.
search_codebase
Hybrid code search over repowise's indexes: symbols, file paths, or the wiki, depending on the shape of the query. One tool instead of a fallback to Grep for identifiers.