Skip to main content
Glama

search_bodies

Search the compiled text inside C/C++ definition bodies to find code patterns such as calls, ISR registrations, enum constants, or table data. Matches code behavior, not symbol names.

Instructions

Find patterns in the TEXT OF A DEFINITION — the code inside its extent.

Searches ifdef-filtered text — only the code that compiles for the build of the query. A line of an inactive #if branch holds nothing, thus a pattern that lives only in a dead branch gives no result here. That empty answer is the correct one: the code does not compile.

Searches the stored text of every definition (is_definition=1), and a definition is not only a callable. Measured on one project of 60,877 symbols, the text covers:

  • Callables — function, method, constructor, destructor. Call patterns (.attach(, .rise(, callback(&), ISR registration, one case label of a long switch.

  • Types — class, struct, union, enum, namespace. An enum constant, a bit field, a member declaration such as InterruptIn _pin; — all inside the body of the type that holds them.

  • Definitions of data — varglobal, varlocal, typedef. A table with a multi-line initializer is found by its content.

A match on a type reports the type as the result, thus a query for one enum constant answers with the enum, and match_lines gives the line of the constant itself.

Only the text matches. The query is bound to the stored body: a hit in the NAME, the signature, the docstring or the llm_analysis of a symbol is not a hit here. Measured on one project, sensor used to give 36 results of which 22 matched only through a summary that a model wrote — untrusted text that cannot be cited, and a _match_snippet with no match in it. Use search_code to reach a name or a concept. A column filter you write yourself (summary : sensor) overrides the binding.

When to use search_bodies and when search_code:

  • search_bodies — patterns in the code (what the code DOES or DECLARES): self test, attach, SELF_TEST.

  • search_code — symbols by NAME (what the code IS): modem init, interrupt handler.

The query goes to FTS5 as you wrote it. This tool alone adds no wildcard, and that is what keeps a pattern precise:

  • A space is an AND of two exact tokens, NOT an OR. CommandType NUM answers with the definitions that hold both.

  • No prefix is implied. SELF_TEST matches the tokens self test and misses Self tester; write SELF_TEST* to reach the second. Measured on one project, the wildcard added the one caller that the bare query missed.

  • Punctuation is not searchable. FTS5 cannot parse .attach( at all, thus the query is repaired into the phrase ".attach(" — and the tokenizer inside a phrase drops the punctuation too, so what runs is the word attach. Such a result carries _fallback: "sanitized" and _query_used. The hits whose body really holds .attach( are the ones with match_lines.

  • search_code and search_content behave the OTHER way: each of their terms gets a trailing * and the terms are OR-joined.

Limitation — the extent of a definition is the boundary. Text that belongs to no definition is out of reach:

  • #include, #define, #ifdef — preprocessor directives. search_code covers a macro name and value. search_content covers the directive as text.

  • extern "C" — a linkage specifier is no symbol.

  • A comment or a declaration at file scope, outside every definition.

For those, use search_content, which indexes the full file text.

Set project_only=True for a question about YOUR code ("where do we register interrupt handlers?"). Leave it False (default) when the vendor SDK code — the framework or OS code that your team did not write — is also relevant.

Results include _match_snippet — a highlighted excerpt that shows each match in context (e.g. _timeout.<b>attach</b>(callback(...))) — and match_lines, the line numbers of the matches inside the definition. line is where the definition starts, which for a large function is far from the match. Cite from match_lines instead. Project code sorts before vendor code in the output.

Read-only: yes. Requires the FTS5 index. May auto-reindex stale files (non-blocking) — see search_code.

Args: query: FTS5 search terms, 1-3 words. A bare multi-word query is an AND of exact tokens, and no wildcard is added — see the query rules above. A single word is the broadest form: 'attach' reaches every .attach(...) pattern. Add * for a prefix ('attach*'), and double quotes for a phrase ('"attach callback"'). project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. kind: Optional filter to return only symbols of this kind. limit: Maximum results of one page (default 20, max 100). offset: Skip this many results. Reads the next page of a pattern with many hits; the page notice names the offset to use. project_only: When True, exclude vendor SDK directories and return only application code. Default False. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as the application or the bootloader. Give it when the build has an image name.

Returns: list of dicts. The page notice leads the answer — total, offset, shown, more — and each that follows holds: name, qualified_name, kind, file, line (first line of the definition), is_definition, signature, _match_snippet (excerpt around the match), source (the text of the definition).

Also, when they carry an answer:

* ``match_lines`` (list[int]) — absolute line numbers of the
  matches, up to 20.  Computed from the full text, thus a match
  after the cut below still has a number.  Use these to cite
  ``file:line``, and not the ``line`` of the definition.  The name
  carries no leading underscore for a reason: a field the caller
  must cite is an answer, while ``_``-prefixed fields
  (``_match_snippet``, ``_fallback``, ``_source_truncated``) tell
  where the answer came from.
* ``_source_truncated`` (True) — ``source`` is cut.  A callable
  keeps 2000 characters, any other kind 500, because the body of a
  type is mostly members that the match has nothing to do with.
  ``get_source`` gives the whole text.
* ``_fallback`` (``"sanitized"``) with ``_query_used`` — FTS5 could
  not parse the query as written, thus a repaired one ran.  The
  repair drops punctuation, so the answer is wider than the text
  that was asked for.  Every query FTS5 accepts runs untouched and
  carries neither field.

``source`` here is bare text with no line-number prefix.  Only
``get_source`` numbers its lines.

No match gives ``[]``.  A dict with ``error`` means the query
failed.  A query that FTS5 refuses to parse, also after the
repair, gives one dict with ``warning`` + ``hint`` — an empty list
always means "no such code", never "bad query".  When a file that
the answer names changed on disk, a dict with ``warning`` comes
first; an empty answer gets it too when indexed files changed.

Input Schema

NameRequiredDescriptionDefault
kindNoOptional kind filter: function, method, class, etc.
imageNoImage of the build: a separate program, such as the application or the bootloader. On a project of more than one build, give it when that build has an image name, as the refusal lists it.
limitNoMaximum results of one page (default 20, max 100).
queryYesFTS5 search terms for the body of a definition. 1-3 words. E.g. 'attach', 'callback', 'rise'.
offsetNoSkip this many results. Reads the next page of a pattern with many hits.
projectNoProject name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both.
variantNoVariant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build for you. One query answers for ONE build.
project_onlyNoExclude vendor SDK code. When True, only application code. Default False.
project_rootNoProject root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those.

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv0.32.1
    • changedInput schema / properties / image / description
      Previous value: -"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program."New value: +"Image of the build: a separate program, such as the application or the bootloader. On a project of more than one build, give it when that build has an image name, as the refusal lists it."
    • changedInput schema / properties / variant / description
      Previous value: -"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."New value: +"Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build for you. One query answers for ONE build."
  2. Changed6 schema fields changedv0.32.0
    • changedInput schema / properties / image / description
      Previous value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program."
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum results (default 20, max 100)."New value: +"Maximum results of one page (default 20, max 100)."
    • addedInput schema / properties / limit / minimum
      Added value: +1
    • addedInput schema / properties / offset
      Added value: +{
      +  "default": 0,
      +  "description": "Skip this many results. Reads the next page of a pattern with many hits.",
      +  "minimum": 0,
      +  "title": "Offset",
      +  "type": "integer"
      +}
    • addedInput schema / properties / query / minLength
      Added value: +1
    • changedInput schema / properties / variant / description
      Previous value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
  3. Changed4 schema fields changedv0.30.0
    • addedInput schema / additionalProperties
      Added value: +false
    • addedInput schema / properties / project
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both.",
      +  "title": "Project"
      +}
    • changedInput schema / properties / project_root / description
      Previous value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
    • changedInput schema / properties / query / description
      Previous value: -"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'callback', 'rise'."New value: +"FTS5 search terms for the body of a definition. 1-3 words. E.g. 'attach', 'callback', 'rise'."
  4. Changed2 schema fields changedv0.25.3
    • addedInput schema / properties / image
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.",
      +  "title": "Image"
      +}
    • addedInput schema / properties / variant
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.",
      +  "title": "Variant"
      +}
  5. Changed2 schema fields changedv0.18.2
    • changedInput schema / properties / project_only / description
      Previous value: -"Exclude vendor SDK code (mbed-os/, .pio/, zephyr/, build/). When True, only your application code (src/, lib/). Default False."New value: +"Exclude vendor SDK code. When True, only application code. Default False."
    • changedInput schema / properties / query / description
      Previous value: -"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'NVIC_SetVector', 'rise'."New value: +"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'callback', 'rise'."
  6. Addedv0.13.1

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and does so richly: read-only, requires FTS5 index, may auto-reindex stale files, ifdef-filtered semantics, punctuation sanitization producing _fallback/_query_used, source truncation limits (2000/500 chars), warning-first dicts on file change, and the [] = no-match vs warning = bad-query distinction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Content-dense and every section earns its place, but it is a very long wall of prose with some repetition (e.g. the search_code contrast is restated in several places). The key routing rule is front-loaded, but the size is well beyond what is needed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists yet the description still pins down the non-obvious return contract (page notice fields, match_lines vs line, underscore-prefix convention, error/warning dicts). For a 9-parameter tool with build-selection complexity, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (baseline 3), but the description materially exceeds it: the query FTS5 grammar (space = AND not OR, no implied prefix, wildcard needed, phrase quoting), the project/project_root mutual exclusivity, and variant/image build-selection rules that the terse schema lines do not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource: find patterns in the stored TEXT of a definition, i.e. the code inside its extent. It immediately bounds scope (only text, not name/signature/docstring/summary) and explicitly contrasts with search_code, search_content, and get_source, so an agent can place it among its 37 siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use routing: 'search_bodies — patterns in the code; search_code — symbols by NAME; search_content — full file text'. It also names the boundary cases (preprocessor directives, extern "C", file-scope declarations) and redirects to search_content for them, plus when to set project_only=True vs default.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.