Skip to main content
Glama

find_variables

Locate C/C++ variables by full or partial name and trace which functions read or write them through the call graph, covering global, local, and field definitions.

Instructions

Find C/C++ variables by name or part of it and trace who reads or writes them through the call graph. libclang-powered: splits variables into global (varglobal — file/namespace/class-scope) and local (varlocal — inside a function body).

Each result includes a type signature (bool timeSet, const IPAddress modbus_ip), the enclosing function for locals ("<file scope>" for globals), and a references list of the functions that read or write the variable — the same ref_kind values as find_references ("call", "ref", "member"). The list is capped at 30 per variable, and holds only references of the selected build; references_total gives the whole count. Only definitions are returned, globals first, then by name.

Use when you need to understand shared state, find who modifies a global variable, trace side effects, or distinguish important globals from loop counters. For general symbol search use search_code or lookup_symbol. For all references to a specific variable (including reads in expressions), use find_references.

This tool is the way to a LOCAL variable: search_code drops the varlocal kind, because a local matches every topic query aimed at the function around it. search_code(..., kind="varlocal") reaches them as well.

Legacy indexes with kind="variable" (pre-split) are detected and included in results — reindex to fully benefit from the split.

Read-only. No side effects.

Args: name: Variable name or part of it. Substring match on name and qualified name (e.g. g_ finds g_debug_level, g_state). project_root: Project root directory. 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 kind filter — "varglobal", "varlocal", "field", or None (all). Default None. The legacy "variable" is also accepted, for an index made before the kind was split. limit: Maximum results (default 20, max 100). offset: Skip this many variables. Reads the next page; the page notice names the offset to use. 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, each with: name (str), qualified_name (str), kind (str — "varglobal", "varlocal", "field", or "variable" on an index made before the kind was split), file (str), line (int), signature (str — e.g. "const IPAddress modbus_ip"), enclosing_function (str — function name for varlocal, "<file scope>" for varglobal), enclosing_class (str — class or struct name for fields and static members, empty otherwise), references (list[dict] — function, file, line, ref_kind; at most 30), references_total (int — every reference of the variable). When the list is cut, references_hint names the find_references call that lists them all.

The page notice ``{total, offset, shown, more, hint}`` comes
before the rows of the answer.  ``total`` counts every variable that matches.  When
``more`` is true, the ``hint`` names the call that reads the next
page.  A page after the last variable gives one ``info`` dict that
names the total.

No match gives ``[]``.  One dict with ``error`` means the query
failed — check that key first.
A ``warning`` dict that comes first means that indexed files
changed after the last index run: the results can be out of date.

Input Schema

NameRequiredDescriptionDefault
kindNoFilter by kind: 'varglobal', 'varlocal', 'field', legacy 'variable', or None for all.
nameYesVariable name or part of it. Substring match on name and qualified name (e.g. 'g_' finds g_debug_level, g_state).
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 (default 20, max 100).
offsetNoSkip this many variables. Reads the next page of a name that many variables share.
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_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. Changed5 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 / kind / description
      Previous value: -"Filter by kind: 'varglobal', 'varlocal', 'field', or None for all."New value: +"Filter by kind: 'varglobal', 'varlocal', 'field', legacy 'variable', or None for all."
    • changedInput schema / properties / name / description
      Previous value: -"Variable name or prefix to search. Uses LIKE match (e.g. 'g_' finds g_debug_level, g_state)."New value: +"Variable name or part of it. Substring match on name and qualified name (e.g. 'g_' finds g_debug_level, g_state)."
    • addedInput schema / properties / offset
      Added value: +{
      +  "default": 0,
      +  "description": "Skip this many variables. Reads the next page of a name that many variables share.",
      +  "minimum": 0,
      +  "title": "Offset",
      +  "type": "integer"
      +}
    • 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. Changed4 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."
    • addedInput schema / properties / limit / minimum
      Added value: +1
    • addedInput schema / properties / name / 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. Changed3 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."
  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. Addedv0.25.2

TDQS

A4.5/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden, and it delivers: read-only/no side effects, a 30-reference cap with references_total and a hint to find_references, result ordering (definitions only, globals first), build-scoped results ('one query answers for ONE build'), legacy-index handling, plus explicit error/warning/empty response shapes. This is unusually complete behavioral disclosure for a tool with zero annotation coverage.

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

Conciseness3/5

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

Well organized and front-loaded with purpose and routing, but the trailing Args and Returns blocks substantially duplicate the input schema and the output schema, and the Returns section runs long for a tool that already publishes a structured return. Several sentences repeat points made earlier (the varlocal/search_code caveat).

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?

For an 8-parameter tool spanning build selection (variant/image), pagination, index states, and partial-failure responses, the description covers everything an agent needs to call it correctly and interpret the result, and it correctly defers return-value detail where an output schema exists while still explaining the cap and page notice.

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

Parameters3/5

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

Schema description coverage is 100% and each parameter already carries a description, so the schema does the heavy lifting and a 3 is the baseline. The prose largely restates schema text (substring matching, limit/offset, project vs project_root), adding little beyond the mutual-exclusion note already present in the schema.

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 specific verb+resource ('Find C/C++ variables by name or part of it and trace who reads or writes them through the call graph') and immediately distinguishes itself from search_code, lookup_symbol, and find_references by naming the conditions that select each. The global/local split adds precision about what is actually searched.

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?

Explicitly enumerates the situations this tool serves ('understand shared state, find who modifies a global variable, trace side effects') and routes the agent to alternatives for the adjacent cases ('For general symbol search use search_code or lookup_symbol', 'For all references to a specific variable ... use find_references'). It also flags the local-variable gap in search_code, which is a routing rule, not just a fact.

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