topicforge 0.6.1__tar.gz → 0.6.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. {topicforge-0.6.1 → topicforge-0.6.3}/CHANGELOG.md +63 -1
  2. {topicforge-0.6.1 → topicforge-0.6.3}/PKG-INFO +12 -4
  3. {topicforge-0.6.1 → topicforge-0.6.3}/README.md +10 -3
  4. topicforge-0.6.3/docs/CLIENTS.md +286 -0
  5. {topicforge-0.6.1 → topicforge-0.6.3}/docs/DDS_QUICKSTART.md +1 -1
  6. {topicforge-0.6.1 → topicforge-0.6.3}/docs/TESTING.md +3 -3
  7. {topicforge-0.6.1 → topicforge-0.6.3}/plugin/README.md +1 -1
  8. topicforge-0.6.3/plugin/pyproject.toml +16 -0
  9. {topicforge-0.6.1 → topicforge-0.6.3}/pyproject.toml +15 -2
  10. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/__init__.py +1 -1
  11. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_mock/adapter.py +3 -0
  12. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/factory.py +51 -8
  13. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/health.py +1 -1
  14. topicforge-0.6.3/src/topicforge/tools/annotations.py +32 -0
  15. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/tools/handlers.py +25 -12
  16. {topicforge-0.6.1 → topicforge-0.6.3}/tests/conftest.py +29 -0
  17. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_config.py +39 -9
  18. topicforge-0.6.3/tests/test_dds_inactive_reason.py +188 -0
  19. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_discovery_tracker.py +6 -2
  20. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_factory.py +28 -1
  21. topicforge-0.6.3/tests/test_tool_annotations.py +44 -0
  22. topicforge-0.6.3/tests/test_version_consistency.py +175 -0
  23. topicforge-0.6.1/tests/test_dds_inactive_reason.py +0 -94
  24. {topicforge-0.6.1 → topicforge-0.6.3}/.gitignore +0 -0
  25. {topicforge-0.6.1 → topicforge-0.6.3}/LICENSE +0 -0
  26. {topicforge-0.6.1 → topicforge-0.6.3}/docs/TROUBLESHOOTING.md +0 -0
  27. {topicforge-0.6.1 → topicforge-0.6.3}/docs/TUTORIEL.md +0 -0
  28. {topicforge-0.6.1 → topicforge-0.6.3}/docs/VALIDATION.md +0 -0
  29. {topicforge-0.6.1 → topicforge-0.6.3}/docs/dds-interop-matrix.md +0 -0
  30. {topicforge-0.6.1 → topicforge-0.6.3}/examples/README.md +0 -0
  31. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/00_hello_pub_sub/README.md +0 -0
  32. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/01_who_is_on_the_bus/README.md +0 -0
  33. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/02_why_cant_they_talk/README.md +0 -0
  34. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/03_a_node_crashed/README.md +0 -0
  35. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/04_late_joiner_misses_data/README.md +0 -0
  36. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/05_reliability_in_code/README.md +0 -0
  37. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/06_durability_late_joiner_in_code/README.md +0 -0
  38. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/07_deadline_in_code/README.md +0 -0
  39. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/08_crash_seen_from_inside/README.md +0 -0
  40. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/10_lidar_silent_after_driver_swap/README.md +0 -0
  41. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/11_who_talks_to_whom/README.md +0 -0
  42. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/12_safety_monitor_dropout/README.md +0 -0
  43. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/13_deadline_not_offered/README.md +0 -0
  44. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/14_restart_loop/README.md +0 -0
  45. {topicforge-0.6.1 → topicforge-0.6.3}/examples/dds/README.md +0 -0
  46. {topicforge-0.6.1 → topicforge-0.6.3}/plugin/LICENSE +0 -0
  47. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/agent_eval/README.md +0 -0
  48. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/README.md +0 -0
  49. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/cyclone_c/README.md +0 -0
  50. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/cyclone_cpp/README.md +0 -0
  51. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/cyclone_rust/README.md +0 -0
  52. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/dust_py/README.md +0 -0
  53. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/fast_publisher_cpp/README.md +0 -0
  54. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/fast_py/README.md +0 -0
  55. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/opensplice_publisher/README.md +0 -0
  56. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/rti_c/README.md +0 -0
  57. {topicforge-0.6.1 → topicforge-0.6.3}/scripts/integration/publishers/rti_cpp/README.md +0 -0
  58. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/__main__.py +0 -0
  59. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/__init__.py +0 -0
  60. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/base.py +0 -0
  61. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/__init__.py +0 -0
  62. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/cdr_decoder.py +0 -0
  63. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/dds_helpers.py +0 -0
  64. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/dds_introspection.py +0 -0
  65. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/discovery_tracker.py +0 -0
  66. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/endpoints.py +0 -0
  67. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/lifecycle.py +0 -0
  68. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/metrics_buffer.py +0 -0
  69. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/qos_analyzer.py +0 -0
  70. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/qos_endpoints.py +0 -0
  71. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/qos_normalize.py +0 -0
  72. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/qos_scan.py +0 -0
  73. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/topic_filter.py +0 -0
  74. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/common/xtypes.py +0 -0
  75. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/composite.py +0 -0
  76. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_cyclone/__init__.py +0 -0
  77. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_cyclone/adapter.py +0 -0
  78. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_dust/__init__.py +0 -0
  79. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_dust/adapter.py +0 -0
  80. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_fast/__init__.py +0 -0
  81. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_fast/adapter.py +0 -0
  82. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_opendds/__init__.py +0 -0
  83. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/dds_opendds/adapter.py +0 -0
  84. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/__init__.py +0 -0
  85. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/adapter.py +0 -0
  86. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/echo_parser.py +0 -0
  87. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/echo_stream.py +0 -0
  88. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/parsers.py +0 -0
  89. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_live/process_tree.py +0 -0
  90. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_mock/__init__.py +0 -0
  91. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/adapters/ros2_mock/fixtures.py +0 -0
  92. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/config/__init__.py +0 -0
  93. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/config/settings.py +0 -0
  94. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/constants.py +0 -0
  95. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/models/__init__.py +0 -0
  96. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/models/schemas.py +0 -0
  97. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/server/__init__.py +0 -0
  98. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/server/app.py +0 -0
  99. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/__init__.py +0 -0
  100. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/bag_service.py +0 -0
  101. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/bag_stats.py +0 -0
  102. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/inspector.py +0 -0
  103. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/services/sample_budget.py +0 -0
  104. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/telemetry/__init__.py +0 -0
  105. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/telemetry/client.py +0 -0
  106. {topicforge-0.6.1 → topicforge-0.6.3}/src/topicforge/tools/__init__.py +0 -0
  107. {topicforge-0.6.1 → topicforge-0.6.3}/tests/__init__.py +0 -0
  108. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/image_noarr.yaml +0 -0
  109. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/image_trunc4.yaml +0 -0
  110. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/scan_edge.yaml +0 -0
  111. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/scan_noarr.yaml +0 -0
  112. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/scan_trunc128.yaml +0 -0
  113. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/scan_trunc3.yaml +0 -0
  114. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/string_latched.yaml +0 -0
  115. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_echo/twist.yaml +0 -0
  116. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_topic_info_verbose_cmd_vel.txt +0 -0
  117. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_topic_info_verbose_parameter_events.txt +0 -0
  118. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_topic_info_verbose_scan.txt +0 -0
  119. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_topic_info_verbose_tf.txt +0 -0
  120. {topicforge-0.6.1 → topicforge-0.6.3}/tests/fixtures/ros2_topic_info_verbose_tf_static.txt +0 -0
  121. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/__init__.py +0 -0
  122. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/Dockerfile +0 -0
  123. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/__init__.py +0 -0
  124. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/entrypoint.sh +0 -0
  125. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/publisher.py +0 -0
  126. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/run_bench.py +0 -0
  127. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/ros2/test_live_adapter.py +0 -0
  128. {topicforge-0.6.1 → topicforge-0.6.3}/tests/integration/test_real_bus.py +0 -0
  129. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_analyze_bag_multi_format.py +0 -0
  130. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_bag_omnisim_humble.py +0 -0
  131. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_bag_service.py +0 -0
  132. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_bag_stats.py +0 -0
  133. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_cdr_decoder.py +0 -0
  134. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_composite_adapter.py +0 -0
  135. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_cyclone_adapter.py +0 -0
  136. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dds_cross_vendor.py +0 -0
  137. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dds_helpers.py +0 -0
  138. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dds_introspection.py +0 -0
  139. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dds_qos_normalization.py +0 -0
  140. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dds_schemas.py +0 -0
  141. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_dust_adapter.py +0 -0
  142. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_echo_parser.py +0 -0
  143. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_echo_stream.py +0 -0
  144. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_endpoints.py +0 -0
  145. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_example_node_spec.py +0 -0
  146. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_fast_adapter.py +0 -0
  147. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_health.py +0 -0
  148. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_history_and_hints.py +0 -0
  149. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_honest_outputs.py +0 -0
  150. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_inspector.py +0 -0
  151. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_lifecycle_buffer.py +0 -0
  152. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_live_adapter_graph.py +0 -0
  153. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_live_adapter_parse.py +0 -0
  154. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_live_adapter_subprocess.py +0 -0
  155. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_live_sample_notes.py +0 -0
  156. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_metrics_buffer.py +0 -0
  157. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_mock_adapter.py +0 -0
  158. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_opendds_adapter.py +0 -0
  159. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_peek_bag_samples.py +0 -0
  160. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_process_tree.py +0 -0
  161. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_qos_analyzer.py +0 -0
  162. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_qos_endpoints.py +0 -0
  163. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_qos_scan.py +0 -0
  164. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_sample_options.py +0 -0
  165. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_telemetry.py +0 -0
  166. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_tools_integration.py +0 -0
  167. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_topic_metrics.py +0 -0
  168. {topicforge-0.6.1 → topicforge-0.6.3}/tests/test_xtypes.py +0 -0
@@ -5,6 +5,66 @@ All notable changes to TopicForge are documented in this file.
5
5
  The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [0.6.3] - 2026-10-07
11
+
12
+ ### Added
13
+
14
+ - Platform-aware DDS message: when the Cyclone backend is requested but the binding is
15
+ missing, `dds_inactive_reason` (and the server log) now says why in plain words, for
16
+ example "`cyclonedds` has no prebuilt wheel for linux-aarch64 / Python 3.14", and what
17
+ to do (build it against the Cyclone C library, or use mock). A server that falls back
18
+ to the mock fixtures because of this reports the reason in `health_check` too. Field
19
+ names are unchanged.
20
+ - CI: a `ubuntu-24.04-arm` job that installs the package without a Cyclone wheel and
21
+ checks that the server starts and `health_check` explains, and Python 3.14 in the test
22
+ matrix (the suite runs there with the binding absent).
23
+
24
+ - MCP `ToolAnnotations` on all twelve tools (`title`, `readOnlyHint=true`,
25
+ `destructiveHint=false`, `idempotentHint=true`, per-tool `openWorldHint`),
26
+ built by one shared helper in `tools/annotations.py`, and
27
+ `tests/test_tool_annotations.py`, which fails if any tool lacks them.
28
+
29
+ ### Changed
30
+
31
+ - `cyclonedds` is now a core dependency, restricted by an environment marker to the
32
+ platforms where it ships prebuilt wheels (Python 3.10-3.13 on Linux x86_64, Windows
33
+ AMD64 and macOS), so `uvx topicforge` and `pip install topicforge` bring the DDS
34
+ binding with no extra. Other platforms (Linux aarch64, Python 3.14, Windows ARM64)
35
+ install cleanly without it. `topicforge[dds]` and `topicforge[dds-cyclone]` stay as
36
+ aliases. The default `TOPICFORGE_DDS_BACKEND` is still `mock`.
37
+ - The Claude plugin launches `uvx --python 3.12 --from topicforge==0.6.3 topicforge`
38
+ without an extra; its dependencies are declared in the new `plugin/pyproject.toml`
39
+ (a lock, `plugin/uv.lock`, is generated once the release is on PyPI). The version
40
+ consistency test covers both files.
41
+ - Documented launch commands, the Cursor and VS Code install links and the MCP Bundle
42
+ now use `topicforge==X` instead of `topicforge[dds]==X`.
43
+ - `SECURITY.md`: new section "Read-only guarantee: architecture, declaration,
44
+ proof" (including the limits of passivity on a DDS domain and the ros2 CLI),
45
+ Popen streaming with process-tree kill documented, any MCP client named, and
46
+ a remote-access paragraph.
47
+
48
+ ## [0.6.2] - 2026-10-06
49
+
50
+ ### Added
51
+
52
+ - [docs/CLIENTS.md](docs/CLIENTS.md): ready-to-paste local stdio configs for Claude
53
+ Code, Claude Desktop, Cursor, VS Code / Copilot, Windsurf / Devin, Cline, Roo Code,
54
+ Continue, Zed, JetBrains, Codex CLI, Gemini CLI, Goose, LM Studio, Amazon Q / Kiro
55
+ and Warp, with one-click install links for Cursor and VS Code, and a note on why
56
+ ChatGPT web and a hosted endpoint are out of scope. Linked from the README.
57
+ - `gemini-extension.json` and `GEMINI.md`: install in Gemini CLI with
58
+ `gemini extensions install https://github.com/yaniswav/TopicForge`.
59
+ - `mcpb/`: an MCP Bundle (`uv` server type, no vendored dependencies) for one-click
60
+ Claude Desktop install. The release workflow packs it and attaches it to the GitHub
61
+ release.
62
+ - `publish.yml` publishes `server.json` to the official MCP Registry after the PyPI
63
+ publish succeeds (pinned, checksum-verified `mcp-publisher`, GitHub OIDC), so the
64
+ registry no longer lags behind PyPI.
65
+ - `tests/test_version_consistency.py`: fails when the package, `server.json`, plugin,
66
+ Gemini extension, MCP Bundle and the pins in `docs/CLIENTS.md` disagree.
67
+
8
68
  ## [0.6.1] - 2026-10-06
9
69
 
10
70
  ### Added
@@ -1294,7 +1354,9 @@ Initial MVP release of TopicForge: ROS Topic Inspector & Bag Analyzer MCP server
1294
1354
  - The write path (publishing, commanding robots) is intentionally out of scope for the MVP.
1295
1355
  - `analyze_bag` in live mode parses `ros2 bag info` text output; deeper anomaly detection remains mock-only for now.
1296
1356
 
1297
- [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.6.1...HEAD
1357
+ [Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.6.3...HEAD
1358
+ [0.6.3]: https://github.com/yaniswav/TopicForge/compare/v0.6.2...v0.6.3
1359
+ [0.6.2]: https://github.com/yaniswav/TopicForge/compare/v0.6.1...v0.6.2
1298
1360
  [0.6.1]: https://github.com/yaniswav/TopicForge/compare/v0.6.0...v0.6.1
1299
1361
  [0.6.0]: https://github.com/yaniswav/TopicForge/compare/v0.5.6...v0.6.0
1300
1362
  [0.5.6]: https://github.com/yaniswav/TopicForge/compare/v0.5.5...v0.5.6
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: topicforge
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: ROS Topic Inspector & Bag Analyzer MCP server for AI agents
5
5
  Project-URL: Homepage, https://github.com/yaniswav/TopicForge
6
6
  Project-URL: Repository, https://github.com/yaniswav/TopicForge
@@ -40,6 +40,7 @@ Classifier: Programming Language :: Python :: 3.11
40
40
  Classifier: Programming Language :: Python :: 3.12
41
41
  Classifier: Programming Language :: Python :: 3.13
42
42
  Requires-Python: >=3.10
43
+ Requires-Dist: cyclonedds>=0.10; python_version < '3.14' and ((platform_system == 'Linux' and platform_machine == 'x86_64') or (platform_system == 'Windows' and platform_machine == 'AMD64') or platform_system == 'Darwin')
43
44
  Requires-Dist: mcp<2,>=1.0.0
44
45
  Requires-Dist: pydantic>=2.6
45
46
  Requires-Dist: pyyaml>=6
@@ -70,6 +71,8 @@ Description-Content-Type: text/markdown
70
71
 
71
72
  A read-only MCP (Model Context Protocol) server that lets an AI agent inspect a ROS2 graph, recorded bag files and the DDS layer underneath ROS. The code has no write path: it cannot publish to the bus or command a robot, and there is no permission system to configure.
72
73
 
74
+ Every tool also declares itself read-only in the MCP protocol (`readOnlyHint`, `destructiveHint=false`, `idempotentHint`, with an honest `openWorldHint`), and a test fails if any tool lacks it. See [`SECURITY.md`](SECURITY.md#read-only-guarantee-architecture-declaration-proof) for the guarantee and its limits.
75
+
73
76
  It gives the agent twelve typed tools that return frozen Pydantic schemas, identical whether the server talks to a real robot or to its built-in mock fixtures. Ask why `nav_planner` gets no scan, and the agent reads the bus, finds the BEST_EFFORT writer facing a RELIABLE reader and names the incompatible policy (see [`examples/02-debug-qos-mismatch.md`](examples/02-debug-qos-mismatch.md)). It is meant for ROS2 developers, robotics ML/CV engineers and teams that cannot accept a write path into a production stack.
74
77
 
75
78
  For DDS, TopicForge joins a domain as a read-only participant through one open-source binding (Eclipse CycloneDDS from PyPI) and reads the builtin discovery topics that the OMG DDS-RTPS protocol standardizes. So far the author has observed Cyclone DDS and Dust DDS participants on a live bus. RTI Connext, OpenDDS, CoreDX and Fast DDS announce themselves through the same standard discovery, but none of them has been observed yet. This covers discovery only: participants, readers, writers and their QoS. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md).
@@ -98,7 +101,11 @@ The server speaks MCP over stdio and waits for a client, so wire it into one. Fo
98
101
  }
99
102
  ```
100
103
 
101
- Then ask it to list the topics or to analyze `/tmp/demo.mcap`. For Claude Code: `claude mcp add topicforge -- topicforge`. Setup for a real ROS2 environment (WSL2, Linux, Docker, native Windows) is in [`docs/TESTING.md`](docs/TESTING.md); recurring monitoring prompts and the privacy contract are in [`docs/TUTORIEL.md`](docs/TUTORIEL.md).
104
+ Then ask it to list the topics or to analyze `/tmp/demo.mcap`. For Claude Code: `claude mcp add topicforge -- topicforge`.
105
+
106
+ **Other MCP clients.** Ready-to-paste configs for Claude Desktop, Cursor, VS Code, Windsurf, Cline, Roo Code, Continue, Zed, JetBrains, Codex, Gemini CLI, Goose and more are in [`docs/CLIENTS.md`](docs/CLIENTS.md). One-click: [Add to Cursor](https://cursor.com/install-mcp?name=topicforge&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJ0b3BpY2ZvcmdlPT0wLjYuMyIsInRvcGljZm9yZ2UiXSwiZW52Ijp7IlRPUElDRk9SR0VfTU9ERSI6ImF1dG8iLCJUT1BJQ0ZPUkdFX0REU19CQUNLRU5EIjoiY3ljbG9uZSIsIlRPUElDRk9SR0VfRERTX0RPTUFJTl9JRCI6IjAifX0%3D) | [Install in VS Code](https://vscode.dev/redirect/mcp/install?name=topicforge&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22topicforge%3D%3D0.6.3%22%2C%22topicforge%22%5D%2C%22env%22%3A%7B%22TOPICFORGE_MODE%22%3A%22auto%22%2C%22TOPICFORGE_DDS_BACKEND%22%3A%22cyclone%22%2C%22TOPICFORGE_DDS_DOMAIN_ID%22%3A%220%22%7D%7D).
107
+
108
+ Setup for a real ROS2 environment (WSL2, Linux, Docker, native Windows) is in [`docs/TESTING.md`](docs/TESTING.md); recurring monitoring prompts and the privacy contract are in [`docs/TUTORIEL.md`](docs/TUTORIEL.md).
102
109
 
103
110
  ## Tools
104
111
 
@@ -134,7 +141,8 @@ Walkthroughs against the mock, each with the exact tool calls and payloads, are
134
141
  ## DDS backends
135
142
 
136
143
  ```bash
137
- pip install topicforge[dds] # Eclipse CycloneDDS ([dds-cyclone] is the same thing)
144
+ pip install topicforge # includes Eclipse CycloneDDS where wheels exist (Python 3.10-3.13; Linux x86_64, Windows x64, macOS)
145
+ pip install "topicforge[dds]" # alias, kept so older commands work; forces a source build elsewhere (needs the Cyclone C library)
138
146
  TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
139
147
  ```
140
148
 
@@ -191,7 +199,7 @@ When on, each tool call emits one event with exactly six fields:
191
199
  | `tool_name` | `"list_topics"` | One of the twelve tools, never argument values |
192
200
  | `latency_ms` | `12.34` | Handler wall-clock duration, 2 decimals |
193
201
  | `mode` | `"mock"` | Mode of the adapter actually serving: `mock` or `live` |
194
- | `version` | `"0.6.1"` | TopicForge server version |
202
+ | `version` | `"0.6.3"` | TopicForge server version |
195
203
  | `session_id` | `"a1b2c3..."` | Random UUID per process, never persisted |
196
204
  | `success` | `true` | Whether the handler returned or raised |
197
205
 
@@ -10,6 +10,8 @@
10
10
 
11
11
  A read-only MCP (Model Context Protocol) server that lets an AI agent inspect a ROS2 graph, recorded bag files and the DDS layer underneath ROS. The code has no write path: it cannot publish to the bus or command a robot, and there is no permission system to configure.
12
12
 
13
+ Every tool also declares itself read-only in the MCP protocol (`readOnlyHint`, `destructiveHint=false`, `idempotentHint`, with an honest `openWorldHint`), and a test fails if any tool lacks it. See [`SECURITY.md`](SECURITY.md#read-only-guarantee-architecture-declaration-proof) for the guarantee and its limits.
14
+
13
15
  It gives the agent twelve typed tools that return frozen Pydantic schemas, identical whether the server talks to a real robot or to its built-in mock fixtures. Ask why `nav_planner` gets no scan, and the agent reads the bus, finds the BEST_EFFORT writer facing a RELIABLE reader and names the incompatible policy (see [`examples/02-debug-qos-mismatch.md`](examples/02-debug-qos-mismatch.md)). It is meant for ROS2 developers, robotics ML/CV engineers and teams that cannot accept a write path into a production stack.
14
16
 
15
17
  For DDS, TopicForge joins a domain as a read-only participant through one open-source binding (Eclipse CycloneDDS from PyPI) and reads the builtin discovery topics that the OMG DDS-RTPS protocol standardizes. So far the author has observed Cyclone DDS and Dust DDS participants on a live bus. RTI Connext, OpenDDS, CoreDX and Fast DDS announce themselves through the same standard discovery, but none of them has been observed yet. This covers discovery only: participants, readers, writers and their QoS. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md).
@@ -38,7 +40,11 @@ The server speaks MCP over stdio and waits for a client, so wire it into one. Fo
38
40
  }
39
41
  ```
40
42
 
41
- Then ask it to list the topics or to analyze `/tmp/demo.mcap`. For Claude Code: `claude mcp add topicforge -- topicforge`. Setup for a real ROS2 environment (WSL2, Linux, Docker, native Windows) is in [`docs/TESTING.md`](docs/TESTING.md); recurring monitoring prompts and the privacy contract are in [`docs/TUTORIEL.md`](docs/TUTORIEL.md).
43
+ Then ask it to list the topics or to analyze `/tmp/demo.mcap`. For Claude Code: `claude mcp add topicforge -- topicforge`.
44
+
45
+ **Other MCP clients.** Ready-to-paste configs for Claude Desktop, Cursor, VS Code, Windsurf, Cline, Roo Code, Continue, Zed, JetBrains, Codex, Gemini CLI, Goose and more are in [`docs/CLIENTS.md`](docs/CLIENTS.md). One-click: [Add to Cursor](https://cursor.com/install-mcp?name=topicforge&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJ0b3BpY2ZvcmdlPT0wLjYuMyIsInRvcGljZm9yZ2UiXSwiZW52Ijp7IlRPUElDRk9SR0VfTU9ERSI6ImF1dG8iLCJUT1BJQ0ZPUkdFX0REU19CQUNLRU5EIjoiY3ljbG9uZSIsIlRPUElDRk9SR0VfRERTX0RPTUFJTl9JRCI6IjAifX0%3D) | [Install in VS Code](https://vscode.dev/redirect/mcp/install?name=topicforge&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22topicforge%3D%3D0.6.3%22%2C%22topicforge%22%5D%2C%22env%22%3A%7B%22TOPICFORGE_MODE%22%3A%22auto%22%2C%22TOPICFORGE_DDS_BACKEND%22%3A%22cyclone%22%2C%22TOPICFORGE_DDS_DOMAIN_ID%22%3A%220%22%7D%7D).
46
+
47
+ Setup for a real ROS2 environment (WSL2, Linux, Docker, native Windows) is in [`docs/TESTING.md`](docs/TESTING.md); recurring monitoring prompts and the privacy contract are in [`docs/TUTORIEL.md`](docs/TUTORIEL.md).
42
48
 
43
49
  ## Tools
44
50
 
@@ -74,7 +80,8 @@ Walkthroughs against the mock, each with the exact tool calls and payloads, are
74
80
  ## DDS backends
75
81
 
76
82
  ```bash
77
- pip install topicforge[dds] # Eclipse CycloneDDS ([dds-cyclone] is the same thing)
83
+ pip install topicforge # includes Eclipse CycloneDDS where wheels exist (Python 3.10-3.13; Linux x86_64, Windows x64, macOS)
84
+ pip install "topicforge[dds]" # alias, kept so older commands work; forces a source build elsewhere (needs the Cyclone C library)
78
85
  TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
79
86
  ```
80
87
 
@@ -131,7 +138,7 @@ When on, each tool call emits one event with exactly six fields:
131
138
  | `tool_name` | `"list_topics"` | One of the twelve tools, never argument values |
132
139
  | `latency_ms` | `12.34` | Handler wall-clock duration, 2 decimals |
133
140
  | `mode` | `"mock"` | Mode of the adapter actually serving: `mock` or `live` |
134
- | `version` | `"0.6.1"` | TopicForge server version |
141
+ | `version` | `"0.6.3"` | TopicForge server version |
135
142
  | `session_id` | `"a1b2c3..."` | Random UUID per process, never persisted |
136
143
  | `success` | `true` | Whether the handler returned or raised |
137
144
 
@@ -0,0 +1,286 @@
1
+ # Using TopicForge from your MCP client
2
+
3
+ Last checked 2026-10-07.
4
+
5
+ TopicForge (ROS 2 / DDS) is a local, read-only MCP server that speaks stdio.
6
+ Every client below launches it as a child process with the same command:
7
+
8
+ ```
9
+ uvx --from "topicforge==0.6.3" topicforge
10
+ ```
11
+
12
+ and the same three environment variables:
13
+
14
+ | Variable | Value | Meaning |
15
+ | --- | --- | --- |
16
+ | `TOPICFORGE_MODE` | `auto` | Use ROS 2 if it is on PATH, else fixtures. |
17
+ | `TOPICFORGE_DDS_BACKEND` | `cyclone` | Join the DDS bus as a read-only participant (the `cyclonedds` binding is installed with TopicForge on supported platforms). Use `mock` for a demo with no robot. |
18
+ | `TOPICFORGE_DDS_DOMAIN_ID` | `0` | The one DDS domain to observe (0-232). Fixed at startup: restart the server to change it. |
19
+
20
+ The registry name is `io.github.yaniswav/topicforge`. Where a client asks for a
21
+ display name, use **TopicForge (ROS 2 / DDS)**: an unrelated SEO product is also
22
+ called TopicForge in the MCP registries.
23
+
24
+ The version pin (`==0.6.3`) is moved on every release together with the other
25
+ version strings; a test keeps them in sync.
26
+
27
+ ## Before you start
28
+
29
+ - **uv.** `uvx` ships with [uv](https://docs.astral.sh/uv/getting-started/installation/).
30
+ Install it once, then check `uvx --version` in a new terminal.
31
+ - **Desktop apps do not inherit your shell PATH.** On Windows especially, an app
32
+ started from the Start menu may not see `uvx`. If a client reports "command not
33
+ found", put the absolute path in `command` (find it with `where uvx` on Windows
34
+ or `which uvx` elsewhere, for example `C:/Users/you/.local/bin/uvx.exe`;
35
+ forward slashes are fine in JSON).
36
+ - **First start is slow.** `uvx` downloads the package and the Cyclone DDS binding
37
+ the first time. Clients with a short startup timeout may need a retry or a
38
+ larger timeout (noted per client below).
39
+ - **Platforms without a Cyclone wheel.** Since 0.6.3 `cyclonedds` is a normal dependency
40
+ of `topicforge`, installed only where it ships prebuilt wheels: Python 3.10 to 3.13 on
41
+ Linux x86_64, Windows x64 and macOS. On Linux ARM (Jetson, Raspberry Pi), Windows ARM64
42
+ or Python 3.14 the server still starts and `health_check` says why the DDS backend is
43
+ off (`dds_inactive_reason`); with a pinned Python, add `"--python", "3.12"` before
44
+ `"--from"` in the args. To build the binding yourself, install the Cyclone C library and
45
+ run `pip install "topicforge[dds]"`. The `[dds]` and `[dds-cyclone]` extras still work
46
+ as aliases, so older commands keep installing.
47
+ - **pip alternative.** `pip install "topicforge==0.6.3"`, then use
48
+ `"command": "topicforge"` (or `"command": "python", "args": ["-m", "topicforge"]`)
49
+ with no `args` for uvx. Use the absolute path of the binary if the client does
50
+ not see your venv.
51
+ - **No robot at hand?** Set `TOPICFORGE_DDS_BACKEND` to `mock` to try the tools
52
+ against deterministic fixtures.
53
+
54
+ ## What cannot work: ChatGPT and hosted endpoints
55
+
56
+ ChatGPT on the web and in the desktop app cannot run local stdio MCP servers; it
57
+ only talks to remote MCP endpoints. Use Codex (below), which runs local stdio
58
+ servers, or any other client on this page.
59
+
60
+ A hosted TopicForge endpoint is out of scope on purpose. TopicForge has to sit on
61
+ the same network as the DDS participants it observes, and exposing a robot bus to
62
+ the internet would contradict the read-only safety promise the product is built
63
+ on.
64
+
65
+ ## The common JSON shape
66
+
67
+ Most clients read an `mcpServers` object like this one. The per-client sections
68
+ say where the file lives and what differs.
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "topicforge": {
74
+ "command": "uvx",
75
+ "args": ["--from", "topicforge==0.6.3", "topicforge"],
76
+ "env": {
77
+ "TOPICFORGE_MODE": "auto",
78
+ "TOPICFORGE_DDS_BACKEND": "cyclone",
79
+ "TOPICFORGE_DDS_DOMAIN_ID": "0"
80
+ }
81
+ }
82
+ }
83
+ }
84
+ ```
85
+
86
+ ## Claude Code
87
+
88
+ Plugin (server plus two skills, asks for backend and domain at install):
89
+
90
+ ```
91
+ claude plugin marketplace add yaniswav/TopicForge
92
+ claude plugin install topicforge@topicforge
93
+ ```
94
+
95
+ Or just the server:
96
+
97
+ ```
98
+ claude mcp add topicforge --env TOPICFORGE_MODE=auto --env TOPICFORGE_DDS_BACKEND=cyclone --env TOPICFORGE_DDS_DOMAIN_ID=0 -- uvx --from "topicforge==0.6.3" topicforge
99
+ ```
100
+
101
+ ## Claude Desktop
102
+
103
+ From 0.6.3: download `topicforge-<version>.mcpb` from the latest GitHub release and double-click it. Claude Desktop asks for the DDS backend and domain id and manages Python and dependencies itself through uv.
104
+
105
+ Or edit the config file by hand: `claude_desktop_config.json` (Settings > Developer > Edit Config):
106
+ `%APPDATA%\Claude\claude_desktop_config.json` on Windows,
107
+ `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS. Paste
108
+ the common JSON shape above and restart the app completely. On Windows, if
109
+ `uvx` is not found, use its absolute path as `command`.
110
+
111
+ ## Cursor
112
+
113
+ The one-click links in this page and in the README are https redirects, because GitHub and PyPI strip `cursor://` and `vscode:` links. Only the raw schemes are documented by Cursor and VS Code; the https forms (`cursor.com/install-mcp`, `vscode.dev/redirect/mcp/install`) were observed to redirect correctly on 2026-10-06 but are not in the vendors' docs (unverified, last checked 2026-10-06). The raw links are given as a fallback.
114
+
115
+ One click: [Add TopicForge to Cursor](https://cursor.com/install-mcp?name=topicforge&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJ0b3BpY2ZvcmdlPT0wLjYuMyIsInRvcGljZm9yZ2UiXSwiZW52Ijp7IlRPUElDRk9SR0VfTU9ERSI6ImF1dG8iLCJUT1BJQ0ZPUkdFX0REU19CQUNLRU5EIjoiY3ljbG9uZSIsIlRPUElDRk9SR0VfRERTX0RPTUFJTl9JRCI6IjAifX0%3D)
116
+
117
+ If that page does not open Cursor, use the raw deeplink: `cursor://anysphere.cursor-deeplink/mcp/install?name=topicforge&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJ0b3BpY2ZvcmdlPT0wLjYuMyIsInRvcGljZm9yZ2UiXSwiZW52Ijp7IlRPUElDRk9SR0VfTU9ERSI6ImF1dG8iLCJUT1BJQ0ZPUkdFX0REU19CQUNLRU5EIjoiY3ljbG9uZSIsIlRPUElDRk9SR0VfRERTX0RPTUFJTl9JRCI6IjAifX0=`
118
+
119
+ Or paste the common JSON shape into `~/.cursor/mcp.json` (all projects) or
120
+ `.cursor/mcp.json` (one project).
121
+
122
+ ## VS Code / GitHub Copilot
123
+
124
+ One click: [Install in VS Code](https://vscode.dev/redirect/mcp/install?name=topicforge&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22topicforge%3D%3D0.6.3%22%2C%22topicforge%22%5D%2C%22env%22%3A%7B%22TOPICFORGE_MODE%22%3A%22auto%22%2C%22TOPICFORGE_DDS_BACKEND%22%3A%22cyclone%22%2C%22TOPICFORGE_DDS_DOMAIN_ID%22%3A%220%22%7D%7D)
125
+
126
+ Fallback, the raw URL handler: `vscode:mcp/install?%7B%22name%22%3A%22topicforge%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22topicforge%3D%3D0.6.3%22%2C%22topicforge%22%5D%2C%22env%22%3A%7B%22TOPICFORGE_MODE%22%3A%22auto%22%2C%22TOPICFORGE_DDS_BACKEND%22%3A%22cyclone%22%2C%22TOPICFORGE_DDS_DOMAIN_ID%22%3A%220%22%7D%7D`
127
+
128
+ Or put this in `.vscode/mcp.json` (the key is `servers`, not `mcpServers`), or run
129
+ "MCP: Add Server" from the Command Palette:
130
+
131
+ ```json
132
+ {
133
+ "servers": {
134
+ "topicforge": {
135
+ "type": "stdio",
136
+ "command": "uvx",
137
+ "args": ["--from", "topicforge==0.6.3", "topicforge"],
138
+ "env": {
139
+ "TOPICFORGE_MODE": "auto",
140
+ "TOPICFORGE_DDS_BACKEND": "cyclone",
141
+ "TOPICFORGE_DDS_DOMAIN_ID": "0"
142
+ }
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## Windsurf / Devin (Cascade)
149
+
150
+ Windsurf's docs now redirect to Devin's (unverified, last checked 2026-10-06). Edit `%APPDATA%\devin\mcp_config.json`
151
+ (Windows) or `~/.config/devin/mcp_config.json` (macOS, Linux) and paste the common
152
+ JSON shape. Older installs may still use `~/.codeium/windsurf/mcp_config.json` (unverified, last checked 2026-10-06).
153
+
154
+ ## Cline
155
+
156
+ Open the MCP Servers icon in the Cline panel, then Configure, then "Configure MCP
157
+ Servers", and paste the common JSON shape (the file is
158
+ `~/.cline/data/settings/cline_mcp_settings.json` per docs.cline.bot on 2026-10-06; older VS Code installs kept it elsewhere, unverified). Optional fields such as
159
+ `"disabled": false` and `"autoApprove": []` are accepted.
160
+
161
+ ## Roo Code
162
+
163
+ Project file `.roo/mcp.json` (takes precedence) or the global `mcp_settings.json`
164
+ opened from the MCP view. Paste the common JSON shape. Roo's docs say Windows
165
+ needs a `cmd /c` wrapper for `npx`; for `uvx`, try it directly first and fall back
166
+ to `"command": "cmd", "args": ["/c", "uvx", "--from", "topicforge==0.6.3",
167
+ "topicforge"]` if it fails to start.
168
+
169
+ ## Continue
170
+
171
+ Create `.continue/mcpServers/topicforge.yaml` (MCP works in agent mode only):
172
+
173
+ ```yaml
174
+ name: TopicForge (ROS 2 / DDS)
175
+ version: 0.0.1
176
+ schema: v1
177
+ mcpServers:
178
+ - name: topicforge
179
+ type: stdio
180
+ command: uvx
181
+ args:
182
+ - "--from"
183
+ - "topicforge==0.6.3"
184
+ - "topicforge"
185
+ env:
186
+ TOPICFORGE_MODE: auto
187
+ TOPICFORGE_DDS_BACKEND: cyclone
188
+ TOPICFORGE_DDS_DOMAIN_ID: "0"
189
+ ```
190
+
191
+ ## Zed
192
+
193
+ In `settings.json`, under `context_servers`:
194
+
195
+ ```json
196
+ {
197
+ "context_servers": {
198
+ "topicforge": {
199
+ "command": "uvx",
200
+ "args": ["--from", "topicforge==0.6.3", "topicforge"],
201
+ "env": {
202
+ "TOPICFORGE_MODE": "auto",
203
+ "TOPICFORGE_DDS_BACKEND": "cyclone",
204
+ "TOPICFORGE_DDS_DOMAIN_ID": "0"
205
+ }
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## JetBrains AI Assistant
212
+
213
+ Settings > Tools > AI Assistant > Model Context Protocol (MCP) > Add, then paste the
214
+ common JSON shape. You can also use "Import from Claude" if you already set it up
215
+ there.
216
+
217
+ ## OpenAI Codex CLI
218
+
219
+ Codex runs local stdio servers (CLI, IDE extension and desktop app share
220
+ `~/.codex/config.toml`). The default startup timeout is 10 s, which a first `uvx`
221
+ run with the dds extra can exceed, so set it to 60 s:
222
+
223
+ ```toml
224
+ [mcp_servers.topicforge]
225
+ command = "uvx"
226
+ args = ["--from", "topicforge==0.6.3", "topicforge"]
227
+ startup_timeout_sec = 60
228
+
229
+ [mcp_servers.topicforge.env]
230
+ TOPICFORGE_MODE = "auto"
231
+ TOPICFORGE_DDS_BACKEND = "cyclone"
232
+ TOPICFORGE_DDS_DOMAIN_ID = "0"
233
+ ```
234
+
235
+ ## Gemini CLI
236
+
237
+ As an extension (reads `gemini-extension.json` from this repository):
238
+
239
+ ```
240
+ gemini extensions install https://github.com/yaniswav/TopicForge
241
+ ```
242
+
243
+ Or paste the common JSON shape into `~/.gemini/settings.json` (or
244
+ `.gemini/settings.json` in a project). Add `"timeout": 60000` (milliseconds) for
245
+ the slow first start, and do not set `"trust": true`.
246
+
247
+ ## Goose
248
+
249
+ In `~/.config/goose/config.yaml` (macOS, Linux; the Windows location is unverified, last checked 2026-10-06), or via the extensions screen:
250
+
251
+ ```yaml
252
+ extensions:
253
+ topicforge:
254
+ name: TopicForge (ROS 2 / DDS)
255
+ type: stdio
256
+ cmd: uvx
257
+ args: [--from, "topicforge==0.6.3", topicforge]
258
+ enabled: true
259
+ envs: { "TOPICFORGE_MODE": "auto", "TOPICFORGE_DDS_BACKEND": "cyclone", "TOPICFORGE_DDS_DOMAIN_ID": "0" }
260
+ timeout: 300
261
+ ```
262
+
263
+ ## LM Studio
264
+
265
+ Program tab > Install > Edit `mcp.json` (same notation as Cursor), then paste the
266
+ common JSON shape. LM Studio's docs only show remote examples; local command
267
+ servers follow the Cursor notation but are not documented explicitly. Small
268
+ local models may struggle with twelve tools.
269
+
270
+ ## Amazon Q Developer / Kiro
271
+
272
+ Kiro: `~/.kiro/settings/mcp.json` (user) or `.kiro/settings/mcp.json` (workspace,
273
+ takes precedence); paste the common JSON shape. Amazon Q Developer CLI uses the
274
+ same shape in `~/.aws/amazonq/mcp.json` (the Amazon Q path and the move to Kiro CLI are unverified, last checked 2026-10-06).
275
+
276
+ ## Warp
277
+
278
+ Settings > MCP > "+ Add", then paste the common JSON shape (unverified, last checked 2026-10-06: the Warp docs page could not be fetched).
279
+
280
+ ## Troubleshooting
281
+
282
+ - Run the command by hand first: `uvx --from "topicforge==0.6.3" topicforge --version`.
283
+ - Server starts but sees no DDS participants: check the domain id, and that the
284
+ client machine is on the same network as the robot (DDS discovery uses
285
+ multicast UDP). Ask the assistant to call `health_check`.
286
+ - More in [TROUBLESHOOTING.md](TROUBLESHOOTING.md) and [TESTING.md](TESTING.md).
@@ -30,7 +30,7 @@ pip install topicforge[dds] # same as [dds-cyclone]
30
30
  TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
31
31
  ```
32
32
 
33
- `cyclonedds` publishes wheels for CPython 3.10 to 3.13 on Windows, Linux and macOS (as of 11.0.1). A background thread reads the builtin DCPS topics through `BuiltinDataReader`. On a real bus `list_participants` reports each participant's `name` (EntityName QoS) and `hostname` (the `__Hostname` discovery property) when the remote participant sets them, and the vendor from the first two bytes of the GUID prefix; implementations that do not follow that convention (Dust DDS, RTI by default) show vendor `unknown`.
33
+ `cyclonedds` publishes wheels for CPython 3.10 to 3.13 on Windows, Linux and macOS (as of 11.0.1), and `topicforge` depends on it only there. Elsewhere (Linux aarch64, Python 3.14, Windows ARM64) `health_check` reports why in `dds_inactive_reason`. A background thread reads the builtin DCPS topics through `BuiltinDataReader`. On a real bus `list_participants` reports each participant's `name` (EntityName QoS) and `hostname` (the `__Hostname` discovery property) when the remote participant sets them, and the vendor from the first two bytes of the GUID prefix; implementations that do not follow that convention (Dust DDS, RTI by default) show vendor `unknown`.
34
34
 
35
35
  Fast DDS has no PyPI install path. The `fastdds` binding is not published, so TopicForge declares no extra for it. Build eProsima's [Fast-DDS-python](https://github.com/eProsima/Fast-DDS-python) from source (it needs the Fast DDS C++ libraries and SWIG), install it into the same environment, then `TOPICFORGE_DDS_BACKEND=fast`. The adapter was written against the 2.6.x API and has never run against a bus.
36
36
 
@@ -15,7 +15,7 @@ How to get a working ROS2 environment to point TopicForge at, and how to wire it
15
15
  ```bash
16
16
  python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
17
17
  pip install topicforge
18
- python -m topicforge --version # -> topicforge 0.6.1
18
+ python -m topicforge --version # -> topicforge 0.6.3
19
19
  TOPICFORGE_MODE=mock python -m topicforge # blocks on stdio; MCP clients spawn it
20
20
  ```
21
21
 
@@ -41,7 +41,7 @@ python3 -m venv ~/topicforge-venv && source ~/topicforge-venv/bin/activate
41
41
  pip install topicforge # Ubuntu 22.04 ships Python 3.10, which is enough
42
42
  ```
43
43
 
44
- Then run live mode with three terminals. In the first, `ros2 run demo_nodes_cpp talker` publishes `/chatter` at about 1 Hz. In the second, `ros2 topic list` should show `/chatter`. In the third, source ROS2, activate the venv and run `TOPICFORGE_MODE=live python -m topicforge`. The startup line reads `topicforge 0.6.1 ready (mode=live, requested_mode=live, adapter=ros2_cli, telemetry=off)`; `mode=mock` means `ros2` was not found and the server fell back to fixtures.
44
+ Then run live mode with three terminals. In the first, `ros2 run demo_nodes_cpp talker` publishes `/chatter` at about 1 Hz. In the second, `ros2 topic list` should show `/chatter`. In the third, source ROS2, activate the venv and run `TOPICFORGE_MODE=live python -m topicforge`. The startup line reads `topicforge 0.6.3 ready (mode=live, requested_mode=live, adapter=ros2_cli, telemetry=off)`; `mode=mock` means `ros2` was not found and the server fell back to fixtures.
45
45
 
46
46
  ## Linux native
47
47
 
@@ -102,4 +102,4 @@ TopicForge speaks MCP over stdio; any compliant client can spawn it with a comma
102
102
  }
103
103
  ```
104
104
 
105
- That is the Claude Desktop shape (`claude_desktop_config.json`); restart the app and the twelve tools appear under the hammer icon. For Claude Code run `claude mcp add topicforge -- topicforge`. Cursor, Continue and Cline accept the same stdio config. If the `topicforge` script is not on PATH, use `"command": "python", "args": ["-m", "topicforge"]`, or the absolute path of the binary inside your venv: desktop clients do not inherit your shell's PATH or venv activation.
105
+ That is the Claude Desktop shape (`claude_desktop_config.json`); restart the app and the twelve tools appear under the hammer icon. For Claude Code run `claude mcp add topicforge -- topicforge`. Cursor, Continue and Cline accept the same stdio config; ready-to-paste configs for every major client are in [`CLIENTS.md`](CLIENTS.md). If the `topicforge` script is not on PATH, use `"command": "python", "args": ["-m", "topicforge"]`, or the absolute path of the binary inside your venv: desktop clients do not inherit your shell's PATH or venv activation.
@@ -4,7 +4,7 @@ TopicForge is a read-only MCP server for ROS 2 and DDS. This plugin bundles the
4
4
 
5
5
  ## What is included
6
6
 
7
- - MCP server `topicforge`, started with `uvx` from the `topicforge` package on PyPI (version pinned to 0.6.1). It exposes twelve read-only tools: `health_check`, `list_topics`, `get_topic_info`, `sample_messages`, `analyze_bag`, `peek_bag_samples`, `list_participants`, `list_endpoints`, `detect_qos_mismatches`, `participant_events`, `peek_dds_samples`, `topic_metrics`.
7
+ - MCP server `topicforge`, started with `uvx` from the `topicforge` package on PyPI (version pinned to 0.6.3). It exposes twelve read-only tools: `health_check`, `list_topics`, `get_topic_info`, `sample_messages`, `analyze_bag`, `peek_bag_samples`, `list_participants`, `list_endpoints`, `detect_qos_mismatches`, `participant_events`, `peek_dds_samples`, `topic_metrics`.
8
8
  - Skill `diagnose-dds-bus`: what to call, and in which order, when nodes do not talk, a topic gets no data, or a node crashed or restarts.
9
9
  - Skill `inspect-ros2-robot`: listing topics, sampling messages and reading bags, including large arrays and simulation time.
10
10
 
@@ -0,0 +1,16 @@
1
+ # Dependency manifest for the Claude plugin directory. It is not a package: it only declares
2
+ # what `plugin/.mcp.json` launches, so that `uv.lock` next to it pins every dependency with
3
+ # hashes. Keep the topicforge pin equal to the version in `.mcp.json`; a test checks it.
4
+ # After a release reaches PyPI, regenerate the lock: `cd plugin && uv lock`.
5
+ [project]
6
+ name = "topicforge-claude-plugin"
7
+ version = "0.6.3"
8
+ description = "Locked launch manifest for the TopicForge Claude plugin."
9
+ # cyclonedds ships wheels for CPython 3.10 to 3.13 only (checked on PyPI 2026-10-07).
10
+ requires-python = ">=3.10,<3.14"
11
+ dependencies = [
12
+ "topicforge==0.6.3",
13
+ ]
14
+
15
+ [tool.uv]
16
+ package = false
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "topicforge"
7
- version = "0.6.1"
7
+ version = "0.6.3"
8
8
  description = "ROS Topic Inspector & Bag Analyzer MCP server for AI agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -26,6 +26,13 @@ dependencies = [
26
26
  "mcp>=1.0.0,<2",
27
27
  "pydantic>=2.6",
28
28
  "pyyaml>=6",
29
+ # Cyclone DDS binding, core since 0.6.3 so that `uvx topicforge` (no extra) can join a
30
+ # DDS bus. The marker lists exactly the platforms where cyclonedds 11.0.1 ships wheels
31
+ # (checked on PyPI 2026-10-07): CPython 3.10-3.13 on Linux x86_64, Windows AMD64 and
32
+ # macOS (x86_64 and arm64). Anywhere else (Linux aarch64, Python 3.14, Windows ARM64)
33
+ # pip would try to build the sdist, which needs the Cyclone C library and fails, so the
34
+ # dependency is skipped there and the server reports why in `dds_inactive_reason`.
35
+ 'cyclonedds>=0.10; python_version < "3.14" and ((platform_system == "Linux" and platform_machine == "x86_64") or (platform_system == "Windows" and platform_machine == "AMD64") or platform_system == "Darwin")',
29
36
  ]
30
37
 
31
38
  [project.optional-dependencies]
@@ -50,6 +57,12 @@ dev = [
50
57
  # Fast DDS still works if its Python binding is built from eProsima's sources;
51
58
  # see docs/DDS_QUICKSTART.md. Do not add a name here without checking it
52
59
  # resolves on PyPI and belongs to the upstream project.
60
+ #
61
+ # `[dds]` and `[dds-cyclone]` are kept as aliases since 0.6.3 (cyclonedds became a core
62
+ # dependency on supported platforms) so existing `topicforge[dds]` commands keep working.
63
+ # They deliberately list cyclonedds WITHOUT the platform marker: a user on an unsupported
64
+ # platform (Linux aarch64, Python 3.14) who has the Cyclone C library installed can still opt
65
+ # in with `pip install "topicforge[dds]"` and build the binding from source.
53
66
  dds-cyclone = [
54
67
  "cyclonedds>=0.10",
55
68
  ]
@@ -81,7 +94,7 @@ packages = ["src/topicforge"]
81
94
 
82
95
  [tool.hatch.build.targets.sdist]
83
96
  include = ["src/topicforge", "tests", "docs", "README.md", "CHANGELOG.md", "LICENSE", "pyproject.toml"]
84
- exclude = [".claude", "docs/projet-file/**", "docs/projet-file", "tests/fixtures/bags/**", "CLAUDE.md", "*.pdf", ".pytest_cache", "pytest-cache-files-*", "pro"]
97
+ exclude = [".claude", "docs/projet-file/**", "docs/projet-file", "tests/fixtures/bags/**", "CLAUDE.md", "*.pdf", ".pytest_cache", "pytest-cache-files-*", "pro", "mcpb"]
85
98
 
86
99
  [tool.pytest.ini_options]
87
100
  testpaths = ["tests"]
@@ -1,5 +1,5 @@
1
1
  """TopicForge: ROS Topic Inspector & Bag Analyzer MCP server."""
2
2
 
3
- __version__ = "0.6.1"
3
+ __version__ = "0.6.3"
4
4
 
5
5
  __all__ = ["__version__"]
@@ -29,6 +29,9 @@ _BAG_EXTENSIONS: frozenset[str] = frozenset({".mcap", ".db3", ".bag"})
29
29
 
30
30
  class MockAdapter:
31
31
  name: AdapterName = "mock"
32
+ # Set by the factory when a DDS backend was requested but the server fell back to
33
+ # these fixtures, so `health_check` can say why. `None` for a deliberate mock.
34
+ dds_inactive_reason: str | None = None
32
35
 
33
36
  @property
34
37
  def effective_mode(self) -> EffectiveMode: