Skip to main content
Glama

list_topics

Read-onlyIdempotent

List ROS 2 graph topics with name, message type, publisher and subscriber counts to inspect live or mock graphs; returns empty if none found or discovery times out.

Instructions

ROS 2 graph only; on a DDS-only setup use list_endpoints. List the topics on the ROS 2 graph (or the mock graph) as a TopicListing: each has name, message_type, publisher_count and subscriber_count; mode_effective tells a real graph from fixtures. QoS is not listed: use get_topic_info. Empty topics when the graph has none or live discovery times out. Raises an MCP error without a ros2 CLI. Read-only; no side effects. Duration: ros2 CLI behind the ROS lock, one call at a time; ends within 45 s; busy error if the lock is held (retry).

Input Schema

NameRequiredDescriptionDefault

No arguments

Output Schema

NameRequiredDescriptionDefault
noteNoOne sentence of context, or `None`.
totalYes
topicsYes
returnedYes
truncatedYes
mode_effectiveYes`live` or `mock` (fixtures).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.8.0
    • removedOutput schema / description
      Removed value: -"Envelope returned by `list_topics`."
    • removedOutput schema / properties / note / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / note / default
      Removed value: -null
    • addedOutput schema / properties / note / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. Changed15 schema fields changedv0.7.1
    • removedInput schema / title
      Removed value: -"list_topicsArguments"
    • removedOutput schema / $defs / QosProfile
      Removed value: -{
      -  "additionalProperties": false,
      -  "description": "QoS profile of one DDS endpoint (reader or writer).\n\nCovers the policies behind most \"subscriber receives nothing\" cases.\nVendor-specific extensions are ignored.",
      -  "properties": {
      -    "data_representation": {
      -      "anyOf": [
      -        {
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Data representations the endpoint accepts or offers, from `XCDR1` and `XCDR2`. `None` when not announced.",
      -      "title": "Data Representation"
      -    },
      -    "deadline_ns": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Deadline QoS in nanoseconds. `None` means no deadline (infinite, the DDS default). A reader deadline tighter (smaller) than a writer deadline is incompatible: the writer cannot guarantee the reader's promise.",
      -      "title": "Deadline Ns"
      -    },
      -    "destination_order": {
      -      "anyOf": [
      -        {
      -          "enum": [
      -            "BY_RECEPTION_TIMESTAMP",
      -            "BY_SOURCE_TIMESTAMP"
      -          ],
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "DestinationOrder QoS. `None` when not announced.",
      -      "title": "Destination Order"
      -    },
      -    "durability": {
      -      "description": "DDS Durability QoS. `VOLATILE` writers do not retain samples for late joiners; `TRANSIENT_LOCAL` writers do. A `TRANSIENT_LOCAL` reader cannot match a `VOLATILE` writer.",
      -      "enum": [
      -        "VOLATILE",
      -        "TRANSIENT_LOCAL",
      -        "TRANSIENT",
      -        "PERSISTENT"
      -      ],
      -      "title": "Durability",
      -      "type": "string"
      -    },
      -    "history": {
      -      "anyOf": [
      -        {
      -          "enum": [
      -            "KEEP_LAST",
      -            "KEEP_ALL"
      -          ],
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "DDS History QoS. `KEEP_LAST` keeps a bounded ring buffer of size `history_depth`; `KEEP_ALL` keeps every sample (memory permitting). Mixed `KEEP_ALL` reader with `KEEP_LAST` writer is risky but not strictly incompatible. `None` when it is not known: DDS discovery does not carry History, so it is reported only for TopicForge's own endpoints and for Cyclone DDS peers that set something other than the default (see `history_note`).",
      -      "title": "History"
      -    },
      -    "history_depth": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Depth for `KEEP_LAST`. `None` for `KEEP_ALL` or when `history` is `None`.",
      -      "title": "History Depth"
      -    },
      -    "history_note": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Set when `history` was left out because discovery did not announce it.",
      -      "title": "History Note"
      -    },
      -    "latency_budget_ns": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "LatencyBudget QoS in nanoseconds (a delivery-delay hint). `0` is the DDS default. `None` means infinite or not announced.",
      -      "title": "Latency Budget Ns"
      -    },
      -    "liveliness_kind": {
      -      "anyOf": [
      -        {
      -          "enum": [
      -            "AUTOMATIC",
      -            "MANUAL_BY_PARTICIPANT",
      -            "MANUAL_BY_TOPIC"
      -          ],
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Liveliness QoS kind. `AUTOMATIC` is asserted by the middleware; the two `MANUAL_*` kinds need the application to write or assert liveliness, and the endpoint is declared not alive when it does not within `liveliness_lease_ns`. `None` when not announced.",
      -      "title": "Liveliness Kind"
      -    },
      -    "liveliness_lease_ns": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Liveliness lease duration in nanoseconds. `None` means infinite (the DDS default) or not announced.",
      -      "title": "Liveliness Lease Ns"
      -    },
      -    "ownership_kind": {
      -      "anyOf": [
      -        {
      -          "enum": [
      -            "SHARED",
      -            "EXCLUSIVE"
      -          ],
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Ownership QoS kind. With `EXCLUSIVE`, only the writer with the highest `ownership_strength` delivers samples to a reader. `None` when not announced.",
      -      "title": "Ownership Kind"
      -    },
      -    "ownership_strength": {
      -      "anyOf": [
      -        {
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Ownership strength of a writer (`EXCLUSIVE` ownership). `None` when not announced.",
      -      "title": "Ownership Strength"
      -    },
      -    "partitions": {
      -      "anyOf": [
      -        {
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Partition names the endpoint's Publisher or Subscriber belongs to. No Partition policy is the default partition, reported as `[\"\"]` (never an empty list). Endpoints only match when their partitions intersect. `None` only when the backend cannot read partitions at all (unknown, not the default).",
      -      "title": "Partitions"
      -    },
      -    "reliability": {
      -      "description": "DDS Reliability QoS. `RELIABLE` retries lost samples; `BEST_EFFORT` does not. A `RELIABLE` reader cannot match a `BEST_EFFORT` writer.",
      -      "enum": [
      -        "RELIABLE",
      -        "BEST_EFFORT"
      -      ],
      -      "title": "Reliability",
      -      "type": "string"
      -    },
      -    "unknown_policies": {
      -      "anyOf": [
      -        {
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Policies the endpoint announced but whose value could not be read (for example `Deadline`). Their duration fields are `None` here, which does NOT mean infinite for these: the scan does not compare them.",
      -      "title": "Unknown Policies"
      -    }
      -  },
      -  "required": [
      -    "reliability",
      -    "durability"
      -  ],
      -  "title": "QosProfile",
      -  "type": "object"
      -}
    • removedOutput schema / $defs / TopicInfo
      Removed value: -{
      -  "additionalProperties": false,
      -  "description": "Description of a single ROS2 topic.\n\nCarries optional DDS-side enrichment fields when the active middleware\nbackend can resolve them (CycloneDDS / Fast DDS). The ROS2 CLI adapter and\nthe mock ROS2 path leave them `None`.",
      -  "properties": {
      -    "message_type": {
      -      "description": "ROS2 message type, e.g. `geometry_msgs/msg/Twist`.",
      -      "title": "Message Type",
      -      "type": "string"
      -    },
      -    "mode_effective": {
      -      "description": "Runtime mode the adapter served this response in: `live` (real ROS2 introspection) or `mock` (deterministic fixtures). Lets a caller tell a real graph from a demo one without calling `health_check`.",
      -      "enum": [
      -        "mock",
      -        "live"
      -      ],
      -      "title": "Mode Effective",
      -      "type": "string"
      -    },
      -    "name": {
      -      "description": "Fully qualified topic name, e.g. `/cmd_vel`.",
      -      "title": "Name",
      -      "type": "string"
      -    },
      -    "publisher_count": {
      -      "description": "Publishers known to the graph.",
      -      "minimum": 0,
      -      "title": "Publisher Count",
      -      "type": "integer"
      -    },
      -    "qos_durability": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Durability announced by the topic's publishers: `volatile`, `transient_local` (late subscribers receive the last samples; typical of latched topics such as `/tf_static`), or `mixed` when publishers disagree. `null` when unknown, with the same rules as `qos_reliability`.",
      -      "title": "Qos Durability"
      -    },
      -    "qos_profile": {
      -      "anyOf": [
      -        {
      -          "$ref": "#/$defs/QosProfile"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Effective DDS QoS profile for this topic when resolvable. `None` from the ROS2 CLI adapter or when the DDS module is inactive. The DDS module populates this on a best-effort basis (picks one representative endpoint if reader/writer QoS differ)."
      -    },
      -    "qos_reliability": {
      -      "anyOf": [
      -        {
      -          "type": "string"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "Reliability announced by the topic's publishers: `reliable`, `best_effort`, or `mixed` when publishers disagree. `null` when unknown: the topic has no publisher, or the value was not read (`list_topics` does not read QoS; `get_topic_info` does).",
      -      "title": "Qos Reliability"
      -    },
      -    "reader_count": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "DDS reader-endpoint count when the active backend can resolve endpoint-level info (Cyclone / Fast DDS). `None` from the ROS2 CLI adapter or when the DDS module is inactive.",
      -      "title": "Reader Count"
      -    },
      -    "subscriber_count": {
      -      "description": "Subscribers known to the graph.",
      -      "minimum": 0,
      -      "title": "Subscriber Count",
      -      "type": "integer"
      -    },
      -    "writer_count": {
      -      "anyOf": [
      -        {
      -          "minimum": 0,
      -          "type": "integer"
      -        },
      -        {
      -          "type": "null"
      -        }
      -      ],
      -      "default": null,
      -      "description": "DDS writer-endpoint count when the active backend can resolve endpoint-level info. `None` from the ROS2 CLI adapter or when the DDS module is inactive.",
      -      "title": "Writer Count"
      -    }
      -  },
      -  "required": [
      -    "name",
      -    "message_type",
      -    "publisher_count",
      -    "subscriber_count",
      -    "mode_effective"
      -  ],
      -  "title": "TopicInfo",
      -  "type": "object"
      -}
    • addedOutput schema / $defs / TopicListItem
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "message_type": {
      +      "type": "string"
      +    },
      +    "name": {
      +      "type": "string"
      +    },
      +    "publisher_count": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "subscriber_count": {
      +      "minimum": 0,
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "name",
      +    "message_type",
      +    "publisher_count",
      +    "subscriber_count"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / additionalProperties
      Added value: +false
    • addedOutput schema / description
      Added value: +"Envelope returned by `list_topics`."
    • addedOutput schema / properties / mode_effective
      Added value: +{
      +  "description": "`live` or `mock` (fixtures).",
      +  "enum": [
      +    "mock",
      +    "live"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / note
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "One sentence of context, or `None`."
      +}
    • removedOutput schema / properties / result
      Removed value: -{
      -  "items": {
      -    "$ref": "#/$defs/TopicInfo"
      -  },
      -  "title": "Result",
      -  "type": "array"
      -}
    • addedOutput schema / properties / returned
      Added value: +{
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / topics
      Added value: +{
      +  "items": {
      +    "$ref": "#/$defs/TopicListItem"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / total
      Added value: +{
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "type": "boolean"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "result"
      -]New value: +[
      +  "topics",
      +  "returned",
      +  "total",
      +  "truncated",
      +  "mode_effective"
      +]
    • changedOutput schema / title
      Previous value: -"list_topicsOutput"New value: +"TopicListing"
  3. First observedv0.5.6

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the readOnly/idempotent annotations: discloses empty-result semantics, MCP error behavior without the `ros2` CLI, a 45 s duration bound, and lock contention with a `busy` error requiring retry. That is exactly the operational context an agent needs before calling a discovery tool that can block on a lock.

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?

Front-loads the scope constraint and then uses bolded fragments for empty results, errors, and duration, so it scans well. Slightly dense and includes one redundant phrase ('Read-only; no side effects') already covered by annotations, but nearly every sentence carries distinct information.

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?

Even though an output schema exists, the description adds result-field meaning (`mode_effective`, publisher/subscriber counts) and the critical edge cases: empty topics, discovery timeout, missing CLI, and lock contention. Nothing an agent needs to decide whether to call it or interpret its failure modes is missing.

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?

With zero parameters the baseline is 4, and the description correctly avoids inventing parameter details. It instead explains the shape of what comes back, which is useful but belongs more to the output schema than to parameter semantics.

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 ('List the topics on the ROS 2 graph') and immediately scopes it against the DDS-only alternative by naming `list_endpoints`. An agent can distinguish it from siblings like `get_topic_info` and `list_endpoints` without opening a schema.

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 routes usage: ROS 2 graph only, use `list_endpoints` for DDS-only setups, and use `get_topic_info` because QoS is not included here. It also names the error condition (missing `ros2` CLI) and the retry case (busy lock), which is when-to-use guidance no sibling name alone would provide.

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