Skip to main content
Glama

list_topics

Read-onlyIdempotent

List ROS 2 graph topics with message types and publisher/subscriber counts to inspect live or mock systems; use endpoint tools for DDS-only setups.

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. counts_unknown: true = counts 0/0 are unknown, not an orphan. Empty topics when the graph has none or live discovery times out. Raises an MCP error without a ros2 CLI. 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": "list_topics"
  }
}

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. Changed1 schema field changedv0.10.0
    • addedOutput schema / $defs / TopicListItem / properties / counts_unknown
      Added value: +{
      +  "description": "True when the counts could not be read (shown as 0).",
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
  2. 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"
      +]
  3. 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"
  4. First observedv0.5.6

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare the read-only/idempotent/non-destructive profile; the description adds materially new behavior: empty `topics` on an empty graph or live-discovery timeout, an MCP error when no `ros2` CLI exists, a 45 s bound under a ROS lock with one call at a time, and `busy` status when the lock is held. It also warns that `counts_unknown: true` means counts of 0/0 are unknown rather than an orphan topic, which prevents a likely misreading.

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 scope and the sibling routing rule, then edge cases, errors, and timing, with no filler sentences. The telegraphic, bold-heavy fragment style is dense and slightly costs readability, but essentially every clause carries operational 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?

For a zero-parameter, read-only listing tool with full annotation coverage and an output schema, the description covers the remaining gaps an agent needs: environment scope, sibling routing, empty-result meaning, failure mode, and latency/lock behavior. Nothing required 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.

Parameters4/5

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

The tool takes zero parameters, so there is nothing for the description to disambiguate at the schema level; baseline applies. The listed fields (`name`, `message_type`, `publisher_count`, `subscriber_count`, `mode_effective`) are return-shape explanations, useful but not 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?

Uses a specific verb and resource ("List the topics on the ROS 2 graph") and immediately names the sibling it is not ("on a DDS-only setup use `list_endpoints`"). The agent can distinguish it from list_endpoints and get_topic_info without opening any 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?

Explicit when-to-use (ROS 2 graph, including the mock graph) and when-not-to-use (DDS-only setups go to `list_endpoints`), plus a second routing rule for the excluded data: "QoS is not listed: use `get_topic_info`". Both alternatives and their selecting conditions are stated.

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