Skip to main content
Glama

inspect_tf

Read-onlyIdempotent

Rebuild the ROS 2 TF tree from /tf and /tf_static to detect lookup breaks, stale frames, cycles, disconnected roots, and URDF frame issues.

Instructions

ROS 2 graph only. Rebuild the TF tree from the transforms on /tf_static (latched) and /tf (listened to for window_s) and flag what breaks lookups. Returns a TfReport: frames (parent, kind static/dynamic/both, age_s, stale, observed_frequency_hz on wall time, sim_frequency_hz on stamps), roots, counts and findings {kind, frames, text}: stale (a frame trails the newest /tf stamp by more than stale_after_s), two_parents, disconnected (several roots), static_and_dynamic, cycle, no_path. Ages and rates use header stamps, so they hold on sim time (real_time_factor far from 1 means sim). A slow or intermittent publisher needs a longer window_s (diagnose uses 8 s). Give source_frame and target_frame for the path between them. It also reads /robot_description and flags URDF links with no frame (declared_not_published) and joints on the wrong stream (fixed_joint_on_tf, movable_joint_on_tf_static). Empty frames when nothing is published (read note). The listening is capped (3000 messages): echo can drop messages at high rates, so the tree is exact but frequencies are approximate (truncated). Raises an MCP error without a ros2 CLI. Mock mode: a fixed 5 s capture of the demo robot with one stale frame. Duration: ROS lock, one call at a time, ends within 45 s; busy if held.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "inspect_tf"
  }
}

Input Schema

NameRequiredDescriptionDefault
window_sNoSeconds to listen to `/tf`, 1..20, default 5.
urdf_pathNoServer path of a `.urdf` (no xacro, 1 MiB max) used instead of /robot_description.
source_frameNoFrame name, e.g. `base_link`. Give `source_frame` and `target_frame` together to get the chain between them in `path`.
target_frameNoSee `source_frame`.
stale_after_sNoA frame is stale past this many seconds of stamp time, default 2.

Output Schema

NameRequiredDescriptionDefault
noteNoOne sentence of context, or `None`.
pathNoFrames from `source_frame` to `target_frame`.
hintsYes
rootsYesFrames with no parent; one in a sound tree.
framesYesSorted by name.
findingsYesEmpty when the tree is sound.
window_sYes
path_noteNoWhy `path` is `None`, or context.
truncatedYesMessages were dropped or the cap was hit.
urdf_noteNo
frame_countYes
stale_countYes
urdf_sourceNo
reference_nsYesNewest `/tf` stamp: the clock for `age_s`.
stamp_span_sYes
static_countYesFrames with a static transform.
dynamic_countYesFrames with a dynamic transform.
message_countYesTransforms captured, repeats included.
mode_effectiveYes`live` or `mock` (fixtures).
transform_countYesDistinct parent-child pairs.
urdf_link_countNo
window_actual_sYes
real_time_factorYesStamp time over wall time: about 1 on a real robot, other on sim.
frames_not_in_urdfNoTF frames not in the URDF (`map`, `odom` are normal).
declared_frames_missingNoURDF links with no TF frame.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv0.10.0
    • addedInput schema / properties / urdf_path
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Server path of a `.urdf` (no xacro, 1 MiB max) used instead of /robot_description."
      +}
    • changedOutput schema / $defs / TfFrame / properties / age_s / description
      Previous value: -"Seconds its stamp trails the newest `/tf` stamp; `None` if static or root."New value: +"Seconds its stamp trails the newest `/tf` stamp of this capture (grows between calls); `None`: static or root."
    • addedOutput schema / $defs / TfFrame / properties / last_stamp_ns / description
      Added value: +"Newest transform stamp; 0 is normal for a static transform, `None` for a root."
  2. Changed1 schema field changedv0.8.1
    • changedOutput schema / $defs / TfFrame / properties / stale / description
      Previous value: -"`age_s` above `stale_after_s`."New value: +"`age_s` above `stale_after_s`, or above 10 periods (min 1 s) of a steady edge."
  3. Addedv0.8.0

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already establish read-only, idempotent, non-destructive behavior, and the description adds substantial operational detail: latched /tf_static, listened /tf, capped message listening, approximate frequencies, empty frames, MCP error without ros2 CLI, mock mode, lock duration, and busy behavior. This is well beyond what the annotations provide.

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?

The description is long but information-dense and front-loads the core purpose before details. Most parentheticals and warnings earn their place, though the density makes it harder to scan than ideal.

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?

Covers the high-complexity tool thoroughly: inputs, report shape, finding kinds, real-versus-sim timing, empty results, error conditions, mock mode, and duration limits. Even with an output schema, the extra behavioral context makes the definition complete for correct invocation.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds useful meaning: window_s must be longer for slow publishers, stale_after_s is measured against the newest /tf stamp, and source_frame plus target_frame produce the path between them. It does not add much for urdf_path, but overall it goes beyond 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 and resource: rebuild the TF tree from /tf_static and /tf, then flag lookup breakages. The ROS 2 graph-only scope and the TfReport return make it clearly distinguishable from general graph or diagnosis siblings.

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

Usage Guidelines4/5

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

Explicitly limits the tool to the ROS 2 graph and explains that a slow or intermittent publisher needs a longer window_s, noting that diagnose uses 8 s. It does not fully spell out when to choose diagnose or other alternatives instead, so it falls short of a 5.

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