发布

  • Release v3.1.0 (#342)

    frostbyte_neo 发布于 2026-06-17 22:49:22 +00:00

    • Refactor ping_robot to ping_robots with support for multiple targets
    • Change ping_robot() to ping_robots() accepting list of targets
    • Add parallel execution using ThreadPoolExecutor for performance
    • Pre-resolve DNS before ping/port checks to fail fast on invalid hostnames
    • Update test files to use new ping_robots API
    • Fix: Handle missing service types in metadata resource (#236)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Fix: Handle missing service types in metadata resource
    • Changed service type format from rosapi/Services to rosapi_msgs/srv/Services
    • Added fallback handling when types array is empty or mismatched
    • Prevents empty service list when ROS 2 returns services without types
    • Services without types are now marked as 'unknown' instead of being dropped
    • ruff

    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • chore: sync main back to develop (#234)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com


    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • Add default value for ping_robots targets parameter

    Set default targets to localhost (127.0.0.1) on port 9090 when not provided.
    Follows codebase pattern using = None with type ignore comment instead of Optional.

    • fix: prevent crash on non-dict rosbridge responses in service tools (#256)

    Add _check_response() and _extract_error() helpers to safely handle
    rosbridge responses where 'values' is a string instead of a dict,
    which happens when calling non-existent services.

    Fixes #257

    • feat: add rate_hz to publish_for_durations for continuous streaming (#250)

    • feat: add rate_hz parameter to publish_for_durations for continuous streaming

    • fix: compensate for send overhead in rate_hz timing

    • docs: add 30-second explainer and prerequisites to README (#263)

    New users unfamiliar with MCP or rosbridge need a quick plain-language
    explanation before diving into installation. Added:

    • "What is this?" section with ASCII architecture diagram
    • "What you need" 3-point prerequisites list
    • Clearer formatting for key benefits section

    Co-authored-by: Claude Opus 4.6 noreply@anthropic.com

    • Revert "docs: add 30-second explainer and prerequisites to README (#263)" (#266)

    This reverts commit b864ce854f.

    • chore: remove commented-out inspect_all_parameters dead code

    • fix: add fallback for empty types array in topics metadata (#237)

    • fix: prevent crashes on non-dict rosbridge responses (#251) (#265)

    • fix: safe response handling in services.py (#257)

    • fix: safe response handling in topics.py (#258)

    • fix: safe response handling in nodes.py (#259)

    • fix: safe response handling in parameters.py (#260)

    • fix: safe response handling in actions.py (#261)

    • fix: safe response handling in ros_metadata.py (#251)

    • fix: restore ros_mcp/utils/response.py from orphan commit (#282)

    • feat: return images directly from subscribe tools (#241) (#262)

    • feat: return images directly from subscribe tools

    Images from subscribe_once and subscribe_for_duration are now
    returned as ImageContent directly, displaying in the AI client
    window without requiring a separate tool call.

    Rename analyze_previously_received_image to view_saved_image.

    Return ToolResult with TextContent/ImageContent instead of mixed
    dicts and content objects. This fixes serialization errors when
    subscribe_for_duration returns both image and non-image messages.

    Changes:

    • Wrap non-image messages in TextContent for consistent typing
    • Use ToolResult for image returns in subscribe_once (ImageContent + text)
    • Build subscribe_for_duration results as flat Content block list
    • Remove -> dict return type annotations (functions now return ToolResult)

    Co-authored-by: mok mok@contoro.com

    • refactor(detection): ROS version detection with RosVersion enum, add tool tests (step0) (#276)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • refactor(connection): detect rosapi types on connect, connectivity tests, add tool tests (step1) (#278)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • ci: add detect step to CI output, opt into Node.js 24

    • fix: use default rosapi node name — prefix is /rosapi/ for all distros

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • chore: gitignore superpowers plans and untrack committed files

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • style: align test docstrings across modules

    • feat(connection): detect rosapi types on successful connect

    • test: integration test for rosbridge connectivity

    • fix: correct port_check key access and add negative connectivity tests

    • ci: run all integration tests and rename run-detect-test.sh to run-tests.sh

    • ci: rename scripts for consistency, remove run-all-cross-tests.sh

    • test: call actual MCP tools in connection integration tests

    • fix: restore ws_manager port after wrong-port test

    • Merge PR#297 back to develop (#313)

    • ci: add auto-sync workflow from main to develop (#312)

    Automatically creates a sync PR and merges main into develop
    when main is updated. Uses merge-tree to skip no-op syncs
    (including cherry-picks). If conflicts exist, a draft PR is
    left open with resolution instructions.

    Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: restructure installation pages (#297)

    • Refactor ping_robot to ping_robots with support for multiple targets

    • Change ping_robot() to ping_robots() accepting list of targets
    • Add parallel execution using ThreadPoolExecutor for performance
    • Pre-resolve DNS before ping/port checks to fail fast on invalid hostnames
    • Update test files to use new ping_robots API
    • Fix: Handle missing service types in metadata resource (#236)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Fix: Handle missing service types in metadata resource
    • Changed service type format from rosapi/Services to rosapi_msgs/srv/Services
    • Added fallback handling when types array is empty or mismatched
    • Prevents empty service list when ROS 2 returns services without types
    • Services without types are now marked as 'unknown' instead of being dropped
    • ruff

    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • chore: sync main back to develop (#234)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com


    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • Add default value for ping_robots targets parameter

    Set default targets to localhost (127.0.0.1) on port 9090 when not provided.
    Follows codebase pattern using = None with type ignore comment instead of Optional.

    • fix: prevent crash on non-dict rosbridge responses in service tools (#256)

    Add _check_response() and _extract_error() helpers to safely handle
    rosbridge responses where 'values' is a string instead of a dict,
    which happens when calling non-existent services.

    Fixes #257

    • feat: add rate_hz to publish_for_durations for continuous streaming (#250)

    • feat: add rate_hz parameter to publish_for_durations for continuous streaming

    • fix: compensate for send overhead in rate_hz timing

    • docs: add 30-second explainer and prerequisites to README (#263)

    New users unfamiliar with MCP or rosbridge need a quick plain-language
    explanation before diving into installation. Added:

    • "What is this?" section with ASCII architecture diagram
    • "What you need" 3-point prerequisites list
    • Clearer formatting for key benefits section

    Co-authored-by: Claude Opus 4.6 noreply@anthropic.com

    • Revert "docs: add 30-second explainer and prerequisites to README (#263)" (#266)

    This reverts commit b864ce854f.

    • chore: remove commented-out inspect_all_parameters dead code

    • fix: add fallback for empty types array in topics metadata (#237)

    • fix: prevent crashes on non-dict rosbridge responses (#251) (#265)

    • fix: safe response handling in services.py (#257)

    • fix: safe response handling in topics.py (#258)

    • fix: safe response handling in nodes.py (#259)

    • fix: safe response handling in parameters.py (#260)

    • fix: safe response handling in actions.py (#261)

    • fix: safe response handling in ros_metadata.py (#251)

    • fix: restore ros_mcp/utils/response.py from orphan commit (#282)

    • docs: add restructured installation pages (Phase 1)

    New docs/install/ directory with separated concerns:

    • installation.md: landing page with two-machine topology and quickstart
    • clients/claude-code.md: Claude Code as recommended client
    • rosbridge.md: robot-side setup (ROS 2 primary, ROS 1 in dropdown)
    • connect.md: connecting to robot and exploring
    • troubleshooting.md: consolidated troubleshooting
    • http-transport.md: advanced HTTP transport setup
    • from-source.md: developer installation from source

    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: add navigation links and fix layout across install pages
    • Add "Back to Installation Guide | Troubleshooting" footer to all step pages
    • Move troubleshooting link from inline to footer bar on rosbridge page
    • Fix duplicate Advanced section on rosbridge page

    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: add remaining client pages and complete Phase 2

    New client pages: Claude Desktop, Codex CLI, Gemini CLI, Cursor,
    ChatGPT (with ngrok setup), Robot MCP Client, Custom/Programmatic.
    New pip.md for alternative pip installation methods.

    Updated landing page with all client links, reordered CLI tools first.
    Updated from-source.md with test step and client configuration.
    Added restart tips, config file help tips, and explicit verify prompts
    across all client pages.

    • docs: Phase 3 cutover - delete old install docs, update all links

    Delete docs/installation.md, docs/installation-alternatives.md,
    and docs/installation-from-source.md. All content has been migrated
    to docs/install/.

    Update all references across README.md, example READMEs,
    architecture.md, contributing.md, and testing.md to point to
    the new docs/install/installation.md.

    • docs: proofread and tighten installation landing page

    • docs: proofread and tighten README and installation landing page

    • docs: reorder Why ROS-MCP bullets, capitalize Robot

    • docs: split Getting Started intro, fix typos

    • docs: fix broken links and stale references found in review

    • Fix broken links to LIMO and Unitree Go2 examples in connect.md
    • Remove empty Troubleshooting heading in connect.md
    • Fix stale step references in contributing.md
    • Add cross-reference links in ChatGPT and Cursor example READMEs
    • Update stale comment in tests/installation/__init__.py
    • feat: return images directly from subscribe tools (#241) (#262)

    • feat: return images directly from subscribe tools

    Images from subscribe_once and subscribe_for_duration are now
    returned as ImageContent directly, displaying in the AI client
    window without requiring a separate tool call.

    Rename analyze_previously_received_image to view_saved_image.

    Return ToolResult with TextContent/ImageContent instead of mixed
    dicts and content objects. This fixes serialization errors when
    subscribe_for_duration returns both image and non-image messages.

    Changes:

    • Wrap non-image messages in TextContent for consistent typing
    • Use ToolResult for image returns in subscribe_once (ImageContent + text)
    • Build subscribe_for_duration results as flat Content block list
    • Remove -> dict return type annotations (functions now return ToolResult)

    Co-authored-by: mok mok@contoro.com

    • refactor(detection): ROS version detection with RosVersion enum, add tool tests (step0) (#276)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • refactor(connection): detect rosapi types on connect, connectivity tests, add tool tests (step1) (#278)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • ci: add detect step to CI output, opt into Node.js 24

    • fix: use default rosapi node name — prefix is /rosapi/ for all distros

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • chore: gitignore superpowers plans and untrack committed files

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • style: align test docstrings across modules

    • feat(connection): detect rosapi types on successful connect

    • test: integration test for rosbridge connectivity

    • fix: correct port_check key access and add negative connectivity tests

    • ci: run all integration tests and rename run-detect-test.sh to run-tests.sh

    • ci: rename scripts for consistency, remove run-all-cross-tests.sh

    • test: call actual MCP tools in connection integration tests

    • fix: restore ws_manager port after wrong-port test


    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com
    Co-authored-by: Wouter 151727235+woutervhaaften@users.noreply.github.com
    Co-authored-by: mok mok@contoro.com


    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com
    Co-authored-by: Wouter 151727235+woutervhaaften@users.noreply.github.com
    Co-authored-by: mok mok@contoro.com

    • docs: fix typos in Docker Turtlesim and Gemini READMEs (#284)

    • docs: fix macOS Claude Desktop config for uvx PATH resolution (#311)

    Prepend PATH=$HOME/.local/bin:$PATH to the macOS zsh args so uvx is
    found even though zsh -lc does not source ~/.zshrc.

    Closes #310

    • fix: make devcontainer compatible with macOS (#303)

    fix: make devcontainer compatible with macOS by removing --gpus=all

    Co-authored-by: Rohit John Varghese 93564012+r-johnv@users.noreply.github.com

    • docs: clarify WSL2 Docker limitations and add Windows(native) + ROS(WSL) setup guide (#305)

    docs: clarify WSL limitation and add native Windows setup guide (fixes #289)

    Co-authored-by: hoh78 hoh78@wisc.edu

    • refactor(nodes): migrate node tools to rosapi_service()/rosapi_type(), add tool tests (step2) (#280)

    • test: add integration tests for node tools (red)

    • refactor(nodes): use rosapi_service()/rosapi_type() instead of hardcoded paths

    • test: add negative tests and run node_details on all distros

    • test: call actual MCP tools in node integration tests

    • style: ruff format long assert lines in test_nodes

    • fix: surface detection failure warning, fall back to ROS 2 types when unknown

    • Sync main into develop: README examples refresh + image cleanup + macOS docs (#331)

    • ci: add auto-sync workflow from main to develop (#312)

    Automatically creates a sync PR and merges main into develop
    when main is updated. Uses merge-tree to skip no-op syncs
    (including cherry-picks). If conflicts exist, a draft PR is
    left open with resolution instructions.

    Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: restructure installation pages (#297)

    • Refactor ping_robot to ping_robots with support for multiple targets

    • Change ping_robot() to ping_robots() accepting list of targets
    • Add parallel execution using ThreadPoolExecutor for performance
    • Pre-resolve DNS before ping/port checks to fail fast on invalid hostnames
    • Update test files to use new ping_robots API
    • Fix: Handle missing service types in metadata resource (#236)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Fix: Handle missing service types in metadata resource
    • Changed service type format from rosapi/Services to rosapi_msgs/srv/Services
    • Added fallback handling when types array is empty or mismatched
    • Prevents empty service list when ROS 2 returns services without types
    • Services without types are now marked as 'unknown' instead of being dropped
    • ruff

    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • chore: sync main back to develop (#234)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Bump version to 3.0.0

    • Release v3.0.0 (#229)

    • fix: Add cross-platform X11 forwarding support for Docker turtlesim

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors

    Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    • Fixed the error in building uv venv

    • feat: Enhance turtlesim launch scripts for cross-platform compatibility and X11 support

    • Added CI test

    • Added CI test

    • launch scripts

    • Removed ci

    • Delete mcp_json.txt

    • updated README

    • *launch.py for turtlesim docker

    • chore: bump version to v2.2.1

    • Add turtlebot3 example (#193)

    • add images of examples using turtlebot3

    • add example tutorial of turtlebot3

    • change turtlebot3 image and add gif to show example3 image

    • fix image file path

    • compress gif file

    • add specification i used for the demo

    • add launch file for turtlebot3 and mcp server


    Co-authored-by: Rohit John Varghese rohit@contoro.com

    • Reorganize docker turtlesim example scripts

    • Cross platform docker launch system and fix for GUI display issues on macOS with XQuartz for example 5 (#186)

    • Fix macOS XQuartz display issues with dynamic DOCKER_DISPLAY variable
    • Add platform-specific setup instructions for macOS, Linux, Windows
    • Remove hard-coded IP addresses and display numbers
    • Add comprehensive troubleshooting for common X11 connection errors
    • Resolves Docker GUI display issues on macOS and improves cross-platform compatibility.

    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu

    • Fixed the scripts path

    • Fixed the scripts path in example 5 (#195)

    • Update example image for ROS2 system query (#198)

    • Update image under installation guide for tutrtesim ROS2 system query example

    • Updated docs with Custom MCP Client (#197)

    Updated docs with custom MCP client integration

    • Fix mutable defaults in publish_once and publish_for_durations (#202)

    Replace mutable default arguments (dict={}, lists=[]) with None and
    initialize inside the functions to prevent cross-call state bleed.

    • Add MCP Resources for ROS Metadata etc (#205)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • ruff format and check

    • Added functionality and tested the Unitree GO2

    The following commit address the the issue that due to control heirarchy in Unitree Go2, the previously implemented archietcture of publishing values to the /wirellesscontroller topic may not always result in the robot movement, even after successful publication to the the respective topic. This commit adds a ROS workspace - go2_ws which exposes all the sports sdk commands as ROS2 services which can be used the ROS-MCP server. The following implementaion uses a variety of movements, acctions available at high level for the unitree go2. The given code has been tested on a real robot. In addition, for the setup in the README I have added instructioons o how to connect to the robot without the access to the WiFi router, it assumes that not everyone may have admin access.

    • ruff format

    • Major refactoring and modularization of the ros-mcp server (#213)

    • chore: bump version to v2.2.1

    • fix: use consistent image path for compressed and raw images

    Previously, compressed images were saved to ./camera/received_image_compressed.jpeg
    while raw images were saved to ./camera/received_image.jpeg. This caused the
    analyze_previously_received_image tool to fail when trying to analyze compressed
    images, as it only looks for ./camera/received_image.jpeg.

    This commit standardizes the path for both compressed and raw images to use
    ./camera/received_image.jpeg, ensuring that the analysis tool can find images
    regardless of their original format.

    • Add comprehensive restructuring and migration plans
    • Add plans.md: Index document for all planning documents
    • Add restructuring_plan.md: Complete implementation guide with split-by-feature structure
    • Update merge_plan.md: High-level overview with structure options
    • Update move_all_tools.md: Quick reference guide for tool migration
    • Move planning documents to docs/ directory
    • Move merge_plan.md, move_all_tools.md, restructuring_plan.md to docs/
    • Add plans.md index document in docs/
    • Update references to simple-mcp-ai in merge_plan.md
    • Organized subplans to docs folder

    • Update restructuring plan to use __init__.py in tools/ and utils/

    • Updated restructuring_plan.md to reflect package structure using __init__.py
    • Changed tools.py references to tools/__init__.py
    • Documented utils/__init__.py structure
    • Updated pyproject.toml: removed py-modules, added proper packages configuration
    • Restructured codebase to use package structure with __init__.py files
    • Merge back develop (with resources feature) to dev/ros_mcp (#212)

    • Add MCP resources for ROS metadata and robot specs

    • Add resources/ros_metadata.py: Resource for getting all ROS metadata (topics, services, nodes, parameters)
    • Add resources/robot_specs.py: Resource for listing all available robot specifications
    • Fix rosapi parameters service: Use /rosapi/get_param_names instead of /rosapi/parameters
    • Add resources/__init__.py: Register all resources with MCP server
    • Update server.py: Register MCP resources on startup
    • Refactor: Move services and nodes tools to separate modules
    • Create ros_mcp/tools/services.py with service-related tools
    • Create ros_mcp/tools/nodes.py with node-related tools
    • Update restructuring plan documentation with progress
    • Update tools_plan.md with migration status
    • Update tool registration in __init__.py
    • Refactoring entrypoints for the repo

    • Moved node-related tools to tools folder

    • Moved topic-related tools to tools folder

    • Moved service-related tools to tools folder

    • Clean up topics.py: remove redundant None checks, improve validation logic, and format code

    • ruff format across all files

    • Migrate parameter tools to modular tools structure

    • Tools migrated: get_parameter, set_parameter, has_parameter, delete_parameter, get_parameters, inspect_all_parameters, get_parameter_details
    • Migrate image tools to modular structure and consolidate helpers

    • Migrate service tools: clean up services.py and remove from monolithic

    • Migrate action tools to modular structure

    • Migrate from server_monolithic.py to ros_mcp/main.py

    • Update server.py to use ros_mcp.main instead of ros_mcp.server
    • Remove server_monolithic.py (functionality fully migrated to modular structure)
    • All functionality now consolidated in ros_mcp/main.py + server.py
    • Restore missing topic tools
    • Fix tool count from 38 to 39 by restoring get_topic_publishers and get_topic_subscribers
    • Add get_topic_publishers_impl and get_topic_subscribers_impl functions
    • Remove get_topic_details tool registration (was not in original 39 tools)
    • Update resource imports to use ros_mcp.utils.websocket_manager
    • Fix robot_specs.py path calculation for new location
    • refactor: rename websocket_manager.py to websocket.py and remove base utils folder
    • Rename ros_mcp/utils/websocket_manager.py to websocket.py
    • Update all imports across codebase to use new module name
    • Remove base utils/ folder (all functions migrated to ros_mcp/utils/)
    • Consolidate utils structure to single location
    • removed root utils folder

    • ruff format

    • Updated plans

    • Fix robot_specifications path in config_utils.py

    Fixed incorrect path resolution for robot_specifications directory.
    Changed from parent.parent to parent.parent.parent to correctly
    point to project root where robot_specifications/ is located.

    • Commented out prompts implementation

    • Minor changes to resources

    • Bugfix: MCP tool parsing by replacing Any with dict and copying default arguments

    • Added server_monolithic for reference

    • ruff format

    • Bugfix: modified rosapi services types in mcp tool implementation

    • Fix parameter tools: merge implementations, use node-specific list_parameters service, fix service types

    • Fix parameter tools to handle non-existing parameters safely

    • Add existence check before get/set/delete operations to prevent rosapi_node crashes
    • Fix has_parameter to correctly detect non-existent parameters (handles '""' value case)
    • Add _safe_check_parameter_exists helper that uses get_param instead of has_param service
    • Remove redundant existence checks and error handling code
    • Simplify has_parameter to use helper directly instead of calling get_parameter
    • Add proper empty value detection for parameters with '""' string values
    • All parameter tools now return structured responses instead of crashing
    • Added prompts for testing server tools

    • Add test_connection_tools prompt and rename test_server_capabilities to test_server_tools

    • Add test_connection_tools.py prompt with comprehensive guide for connection tools
    • Guide covers ping_robot, connect_to_robot, and detect_ros_version
    • Include troubleshooting, examples, and best practices
    • Rename test_server_capabilities to test_server_tools for consistency
    • Update all imports and function names accordingly
    • Register test_connection_tools in prompts __init__.py
    • Refactor nodes tools: inline implementations and move inspect_all_nodes to resources

    • Update test-nodes-tools prompts to use resource instead of inspect_all_nodes tool

    • Replace inspect_all_nodes() tool references with ros-mcp://ros-metadata/nodes/all resource
    • Update testing checklist and tips to reference the resource
    • Complete migration of inspect_all_nodes from tool to resource
    • Added prompts to test parameters tools + registration

    • ruff format

    • Move inspect_all_services from tools to resources and add test_services_tools prompts

    • Refactor services tools: inline implementations and merge get_service_providers into get_service_details

    • Refactor topics tools: migrate inspect_all to resources, inline implementations, and add default values

    • Clean up and fix action tools + added prompt for test_actions_tools

    • Added resource to get actions details + minor ruff formt changes

    • Remove verbose sections from test prompts to keep prompts concise and focused on essential testing information.

    • Add comprehensive testing guide with complete instructions

    • Include prerequisites and setup instructions
    • Document how to use test prompts
    • Document how to access and use resources
    • Include complete testing workflow examples
    • Add troubleshooting section
    • Remove resource validation, focus on gathering resources
    • Fix documentation consistency and add architecture guide

    • Minor changes to documentation

    • Removed *_impl patter for connection tools module

    • Removed *_impl patter for images tools module

    • Removed *_impl patter for robot_config tools module

    • Added docstrings for each tool following Args/Results pattern

    • Added tool implementation template including decorator/docstrings/implementation details.

    • Remove Optional/union types from tool parameters, use None defaults and apply at runtime defaults.

    • Update actions.py, services.py, and topics.py to use dynamic defaults
    • Fixes MCP tool parameter validation issues for LLM clients (issue #140)
    • Minor typo

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch

    • feat: add MCP tool annotations for improved LLM understanding

    Add ToolAnnotations to all 31 tools across 8 modular tool files:

    • topics.py: 8 tools (6 readOnlyHint, 2 destructiveHint)
    • services.py: 4 tools (3 readOnlyHint, 1 destructiveHint)
    • nodes.py: 2 tools (2 readOnlyHint)
    • connection.py: 2 tools (1 readOnlyHint, 1 destructiveHint)
    • actions.py: 5 tools (3 readOnlyHint, 2 destructiveHint)
    • parameters.py: 6 tools (4 readOnlyHint, 2 destructiveHint)
    • images.py: 1 tool (1 readOnlyHint)
    • robot_config.py: 3 tools (3 readOnlyHint)

    Tool annotations help LLMs understand tool behavior before execution,
    enabling better tool selection and safety warnings for destructive operations.

    🤖 Generated with Claude Code

    • Fix packaging configuration: add missing modules and correct entry point
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • fix: update type annotations to use union syntax for optional parameters
    • Replace 'float = None' with 'float | None = None' in topics.py, actions.py, and services.py
    • Replace 'int = None' with 'int | None = None' in topics.py
    • Replace 'Context = None' with 'Context | None = None' in actions.py
    • Fixes 8 linter errors related to type annotations
    • fix: resolve remaining linter errors in images, actions, and parameters
    • images.py: Update return type to dict | Any to allow ImageContent return
    • actions.py: Initialize action_interfaces before if/else block to fix scoping issue
    • parameters.py: Move fallback return out of else block for clearer control flow
    • Fix packaging configuration: add missing modules and correct entry point (#221)
    • Add ros_mcp.prompts and ros_mcp.resources to packages list
    • Fix entry point from ros_mcp.server:main to ros_mcp.main:main
    • feat: add integration.py for parent server registration (#223)

    • feat: add integration.py for parent server registration

    Adds ros_mcp/integration.py that owns ROS configuration (rosbridge IP/port)
    and provides register() function for submodule_integration.py to call.
    This allows the parent server to be submodule-agnostic.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • ruff errors

    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com

    • fix: remove union types from tool signatures for MCP client compatibility

    Remove union types (float | None, int | None, Context | None) from tool
    function signatures and replace with simple types plus type ignore flags.
    This ensures FastMCP generates simpler JSON schemas without anyOf unions,
    which are incompatible with many MCP clients (Cursor, Home Assistant, etc.).

    Changes:

    • services.py: call_service() timeout parameter
    • actions.py: send_action_goal() timeout and ctx parameters
    • topics.py: subscribe_once() and subscribe_for_duration() timeout,
      queue_length, and throttle_rate_ms parameters

    Runtime behavior unchanged - functions already handle None values correctly.

    • style: format call_service function parameters on separate lines

    • fix: improve type annotations in images.py

    • Replace dict | Any with dict | ImageContent for accurate return type
    • Add ImageContent import from mcp.types
    • Add return type annotation to _encode_image_to_imagecontent()
    • Remove unused Any import from typing

    This provides better type safety and matches the actual return types.

    • docs: add issue #140 references to all type ignore flags

    Add '# See issue #140' comments to all type ignore flags to document
    why they are needed. This provides context linking the type suppressions
    to the MCP client compatibility issue discussed in issue #140.

    Updated files:

    • actions.py: timeout and ctx parameters
    • images.py: return type and return statement
    • services.py: timeout parameter
    • topics.py: timeout, queue_length, and throttle_rate_ms parameters
    • feat: add Docker-based installation tests

    Add installation tests that validate package installation across different
    methods (pip, uvx, uv) and Python versions (3.10, 3.11, 3.12).

    Tests use Docker to create clean environments and install from git to catch
    installation issues before PyPI release.

    Test files:

    • test_pip_install.py: pip install from git and source
    • test_uvx_install.py: uvx --from git+repo installation
    • test_source_install.py: uv sync development workflow

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: Change connect_to_robot to destructiveHint=False

    Address review feedback from @r-johnv. The connect_to_robot tool:

    • Sets internal IP/port configuration in the WebSocket manager
    • Tests connectivity (ping and port check)
    • Does NOT send commands to the robot
    • Does NOT modify robot state or behavior

    This is a configuration/connectivity check, not a destructive action.
    Per MCP spec, destructiveHint should only be true for tools that
    perform destructive updates to external systems.

    • fix: Sort imports in images.py to fix ruff linting

    • Fix type annotations and improve test configuration

    • Fix type annotations in conftest.py (str|None, dict|None) to resolve linter errors
    • Remove incorrect tests/ entry from .gitignore (test files should be tracked)
    • Add 'slow' marker documentation to pyproject.toml
    • Format code with ruff

    • refactor: simplify installation tests per review feedback

    Address review feedback from @r-johnv:

    1. Remove redundant SUCCESS echo from Dockerfiles

      • returncode == 0 already confirms all steps passed
      • Hardcoded echo doesn't verify anything meaningful
    2. Remove redundant SUCCESS assertion from tests

      • The assertion just checked for hardcoded echo output
      • returncode check is sufficient
    3. Remove test_uvx_install_with_transport_flag

      • Testing --transport=stdio is redundant (it's the default)
      • Transport flag testing belongs in E2E tests, not installation tests

    Installation tests now focus purely on verifying:

    • Package installs successfully (pip/uvx/uv)
    • CLI entry point works (ros-mcp --help)
    • Package is importable (import ros_mcp)

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • Add test for uvx install from local repository
    • Add test_uvx_install_from_local to test uvx . installation method
    • Create Dockerfile.uvx-local for local uvx installation testing
    • Minor formatting fix in test_source_install.py
    • chore: remove outdated files
    • Remove server_monolithic.py (functionality migrated to modular structure)
    • Remove docs/merge_plan_mok.md (completed planning document)
    • Update docs/restructuring_plan.md to remove broken references

    All functionality has been successfully migrated to ros_mcp/main.py and
    ros_mcp/tools/ structure. The monolithic file is no longer needed.

    • Bump version to 3.0.0

    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • fix: CI publish workflow and bump to v3.0.1
    • Install dev dependencies (uv sync --extra dev) to make pytest available
    • Skip slow tests in CI (-m "not slow")
    • Bump version to 3.0.1

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: allow pytest exit code 5 (no tests collected)

    All current tests are marked as slow, so -m "not slow" selects none.
    Exit code 5 means no tests were collected, which is acceptable.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

    • fix: update MCP registry schema to 2025-12-11

    The 2025-10-17 schema is deprecated. Updated to latest schema version.

    Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com


    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com

    • Add default value for ping_robots targets parameter

    Set default targets to localhost (127.0.0.1) on port 9090 when not provided.
    Follows codebase pattern using = None with type ignore comment instead of Optional.

    • fix: prevent crash on non-dict rosbridge responses in service tools (#256)

    Add _check_response() and _extract_error() helpers to safely handle
    rosbridge responses where 'values' is a string instead of a dict,
    which happens when calling non-existent services.

    Fixes #257

    • feat: add rate_hz to publish_for_durations for continuous streaming (#250)

    • feat: add rate_hz parameter to publish_for_durations for continuous streaming

    • fix: compensate for send overhead in rate_hz timing

    • docs: add 30-second explainer and prerequisites to README (#263)

    New users unfamiliar with MCP or rosbridge need a quick plain-language
    explanation before diving into installation. Added:

    • "What is this?" section with ASCII architecture diagram
    • "What you need" 3-point prerequisites list
    • Clearer formatting for key benefits section

    Co-authored-by: Claude Opus 4.6 noreply@anthropic.com

    • Revert "docs: add 30-second explainer and prerequisites to README (#263)" (#266)

    This reverts commit b864ce854f.

    • chore: remove commented-out inspect_all_parameters dead code

    • fix: add fallback for empty types array in topics metadata (#237)

    • fix: prevent crashes on non-dict rosbridge responses (#251) (#265)

    • fix: safe response handling in services.py (#257)

    • fix: safe response handling in topics.py (#258)

    • fix: safe response handling in nodes.py (#259)

    • fix: safe response handling in parameters.py (#260)

    • fix: safe response handling in actions.py (#261)

    • fix: safe response handling in ros_metadata.py (#251)

    • fix: restore ros_mcp/utils/response.py from orphan commit (#282)

    • docs: add restructured installation pages (Phase 1)

    New docs/install/ directory with separated concerns:

    • installation.md: landing page with two-machine topology and quickstart
    • clients/claude-code.md: Claude Code as recommended client
    • rosbridge.md: robot-side setup (ROS 2 primary, ROS 1 in dropdown)
    • connect.md: connecting to robot and exploring
    • troubleshooting.md: consolidated troubleshooting
    • http-transport.md: advanced HTTP transport setup
    • from-source.md: developer installation from source

    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: add navigation links and fix layout across install pages
    • Add "Back to Installation Guide | Troubleshooting" footer to all step pages
    • Move troubleshooting link from inline to footer bar on rosbridge page
    • Fix duplicate Advanced section on rosbridge page

    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

    • docs: add remaining client pages and complete Phase 2

    New client pages: Claude Desktop, Codex CLI, Gemini CLI, Cursor,
    ChatGPT (with ngrok setup), Robot MCP Client, Custom/Programmatic.
    New pip.md for alternative pip installation methods.

    Updated landing page with all client links, reordered CLI tools first.
    Updated from-source.md with test step and client configuration.
    Added restart tips, config file help tips, and explicit verify prompts
    across all client pages.

    • docs: Phase 3 cutover - delete old install docs, update all links

    Delete docs/installation.md, docs/installation-alternatives.md,
    and docs/installation-from-source.md. All content has been migrated
    to docs/install/.

    Update all references across README.md, example READMEs,
    architecture.md, contributing.md, and testing.md to point to
    the new docs/install/installation.md.

    • docs: proofread and tighten installation landing page

    • docs: proofread and tighten README and installation landing page

    • docs: reorder Why ROS-MCP bullets, capitalize Robot

    • docs: split Getting Started intro, fix typos

    • docs: fix broken links and stale references found in review

    • Fix broken links to LIMO and Unitree Go2 examples in connect.md
    • Remove empty Troubleshooting heading in connect.md
    • Fix stale step references in contributing.md
    • Add cross-reference links in ChatGPT and Cursor example READMEs
    • Update stale comment in tests/installation/__init__.py
    • feat: return images directly from subscribe tools (#241) (#262)

    • feat: return images directly from subscribe tools

    Images from subscribe_once and subscribe_for_duration are now
    returned as ImageContent directly, displaying in the AI client
    window without requiring a separate tool call.

    Rename analyze_previously_received_image to view_saved_image.

    Return ToolResult with TextContent/ImageContent instead of mixed
    dicts and content objects. This fixes serialization errors when
    subscribe_for_duration returns both image and non-image messages.

    Changes:

    • Wrap non-image messages in TextContent for consistent typing
    • Use ToolResult for image returns in subscribe_once (ImageContent + text)
    • Build subscribe_for_duration results as flat Content block list
    • Remove -> dict return type annotations (functions now return ToolResult)

    Co-authored-by: mok mok@contoro.com

    • refactor(detection): ROS version detection with RosVersion enum, add tool tests (step0) (#276)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • refactor(connection): detect rosapi types on connect, connectivity tests, add tool tests (step1) (#278)

    • chore: add Docker infrastructure for integration tests (Noetic + Humble)

    • feat: add integration test fixtures with Docker lifecycle and --ros-distro option

    • feat: add rosapi_types module with RosVersion enum for ROS 1/2 detection

    • test: add integration tests for ROS version detection (Noetic + Humble)

    • feat: robust ROS version detection with cross-test validation

    • ci: add integration test workflow for 4 ROS distros (melodic, noetic, humble, jazzy)

    • ci: add detect step to CI output, opt into Node.js 24

    • fix: use default rosapi node name — prefix is /rosapi/ for all distros

    • docs: clarify detection strategy — get_ros_version vs get_param as discriminants

    • chore: gitignore superpowers plans and untrack committed files

    • refactor: detect_ros_version tool uses rosapi_types, add tools fixture

    • test: use get_nodes tool instead of raw ws.request in test_resolved_service_works

    • style: align test docstrings across modules

    • feat(connection): detect rosapi types on successful connect

    • test: integration test for rosbridge connectivity

    • fix: correct port_check key access and add negative connectivity tests

    • ci: run all integration tests and rename run-detect-test.sh to run-tests.sh

    • ci: rename scripts for consistency, remove run-all-cross-tests.sh

    • test: call actual MCP tools in connection integration tests

    • fix: restore ws_manager port after wrong-port test


    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com
    Co-authored-by: Wouter 151727235+woutervhaaften@users.noreply.github.com
    Co-authored-by: mok mok@contoro.com

    • docs: add macOS/Docker setup instructions for 8_images tutorial (#295)

    • docs: add macOS setup instructions for 6_chatgpt tutorial (#293)

    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com

    • docs: clarify ROS Noetic demo environment for 2_gemini (#300)

    Add a compatibility note for ROS2 Jazzy / WSL users in the 2_gemini README.

    • docs: add example images for README refresh (#329)

    Adds the image assets referenced by the README examples refresh so they
    resolve on main ahead of that PR:

    • MCP Demos Slide - With text - 640p.gif
    • ROS MCP Gripper vacuum test.jpg
    • Wilson thumbnail.jpg
    • docs: refresh Examples in Action section in README (#330)

    • docs: refresh Examples in Action section in README

    • Add demos slide GIF at top of examples, linked to YouTube
    • Update industrial robot example image to gripper vacuum test
    • Replace MOCA example with Wilson (Gemini, ROS 2 + Nav2)
    • Replace real Go2 example with Unitree Go2 in NVIDIA Isaac Sim
    • Remove unused Contoro_robot.png
    • docs: condense industrial robot example description

    • docs: add section separators in README examples

    • docs: add example images for README refresh

    Adds the image assets referenced by the README examples refresh so they
    resolve on main ahead of that PR:

    • MCP Demos Slide - With text - 640p.gif
    • ROS MCP Gripper vacuum test.jpg
    • Wilson thumbnail.jpg
    • docs: swap demos GIF for shorter 7to12s clip, drop unused result.gif
    • Replace 19MB 'With text - 640p' demos GIF with 6.7MB '7to12s' clip
    • Point README at the new GIF
    • Remove unused result.gif
    • docs: remove unused images from docs/images

    Drop connected_mcp.png and how_to_use_{1,2,3}.png — no longer referenced
    after the installation docs restructure.

    • docs: remove 19MB 640p demos GIF reintroduced by main merge

    The merge from main re-added the old 640p demos GIF (added on main via
    #329). Remove it again so only the 6.7MB 7to12s clip remains.


    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com
    Co-authored-by: Claude Opus 4.6 (1M context) noreply@anthropic.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Stefano Dalla Gasperina stefano.dallagasperina@austin.utexas.edu
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com
    Co-authored-by: Wouter 151727235+woutervhaaften@users.noreply.github.com
    Co-authored-by: mok mok@contoro.com
    Co-authored-by: Sunghwan Cho 89915211+sunnycho100@users.noreply.github.com
    Co-authored-by: sbae56-art sbae56@wisc.edu

    • docs: add warning and termination commands to prevent Claude config reset (#306)

    Editing claude_desktop_config.json while Claude Desktop is running in the
    background can silently wipe the change the moment a chat is opened
    (reproduced on Windows 11, Claude Desktop 1.1.9493.0). Add an Important
    callout at the top of "Add the MCP Server" with platform-specific
    termination commands.

    The existing Verify-the-Setup section already documents per-OS restart
    commands, so the original PR's caching-troubleshooting note is omitted
    here as redundant.

    Resolves #291

    Co-authored-by: hoh78 hoh78@wisc.edu
    Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • refactor(topics): migrate to rosapi_service()/rosapi_type(), add tool tests (step3) (#281)

    • refactor(topics): migrate to rosapi_service()/rosapi_type()

    Replace 6 hardcoded /rosapi/ service paths and 6 hardcoded rosapi/* type
    strings in topics.py with the rosapi_service() / rosapi_type() helpers
    introduced by step1. Same pattern as the nodes refactor in step2 (#280).

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • test(topics): integration tests for topic tools via MCP tool functions

    Add tests/integration/test_topics.py — 20 tests across 9 classes covering
    get_topics, get_topic_type, get_topic_details, get_message_details,
    subscribe_once, subscribe_for_duration, publish_once, publish_for_durations,
    and an end-to-end TestPublishAndSubscribe::test_turtle_moves_after_publish
    that publishes a velocity and verifies the turtle's pose changes.

    Tests call MCP tool functions directly via the tools fixture (no mocks)
    against the live rosbridge container managed by conftest.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • ci(run-tests): add module filter and helpful default usage
    • Accept an optional second positional argument selecting a single test
      module (e.g. ./run-tests.sh humble topics).
    • When called with no args, print a usage line that enumerates available
      distros AND auto-discovers the available modules from tests/integration.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • test(topics): tighten test_pose_details and make rate_hz explicit

    Addresses MAY items from PR #281 review:

    • test_pose_details now asserts turtlesim is among the publishers, not
      just that publisher_count > 0. A regression that returned someone
      else's node would otherwise pass silently. Matches the pattern used
      in tests/integration/test_nodes.py.
    • test_publish_sequence now passes rate_hz=0 explicitly so the comment
      about non-streaming-mode timing is self-contained at the call site.
      rate_hz=0 is the documented default of publish_for_durations.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • test(topics): bound published_count and assert forward motion

    Address PR #281 review nits:

    • test_publish_sequence: assert 1 <= published_count <= len(messages)
      instead of only >= 1, catching over-publish regressions while keeping
      the documented lower-bound tolerance for rate_hz=0 timing.
    • test_turtle_moves_after_publish: assert x_after > x_before (forward
      velocity at spawn theta=0 must increase x) instead of x_after != x_before.

    Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • refactor(services): migrate to rosapi_service()/rosapi_type(), add tool tests (step4) (#322)

    • refactor(services): use rosapi_service()/rosapi_type() instead of hardcoded paths

    • test: integration tests for service tools via MCP tool functions

    • ci: add per-module test runner for services

    • test: add call_service tests for clear and nonexistent service

    • test(services): drop per-module wrapper, clean up spawned turtle

    Address PR #322 review:

    • Remove run-services-tests.sh — reintroduced the per-module wrapper
      pattern removed in #281; ./run-tests.sh services covers it.
    • test_call_spawn_turtle: kill the spawned turtle in a finally block so
      state doesn't leak across tests in a reused session.
    • test: add unit tests for utility modules (#309)

    • test: add unit tests for utils modules (response, config, network)

    • test: reduce unit test scope per review feedback

    Remove test_network_utils.py since ping_ip_and_port is already
    covered by tests/integration/test_connection.py with real sockets.

    Remove test_response.py since _check_response and _safe_get_values
    are small utility functions that integration tests exercise
    implicitly on every service call.

    Trim conftest.py to drop the now-unused response fixtures.

    Add a note on _patch_specs_dir about the coupling to config_utils
    internal path resolution.

    Addresses review feedback from @stex2005 on PR #309.


    Co-authored-by: Stefano Dalla Gasperina stefano.dallag@gmail.com

    • refactor(actions): standardize action tools, add integration tests (step5) (#321)

    • refactor(actions): use rosapi_service()/rosapi_type(), remove blocking asyncio.sleep

    • feat(actions): clean up action tools, add action tests for all distros

    • refactor(actions): align typedef parsing with topics/services; fix detail tests

    • _parse_typedef now returns the canonical {fields, field_count} shape used
      by get_message_details (topics) and get_service_details (services), dropping
      the divergent field_details/examples/constants keys.
    • Rename test_nonexistent_action_returns_error -> test_missing_action_type_returns_error
      (it omitted action_type, so it only exercised the 'action_type required' path).
    • Add test_nonexistent_action_type_returns_error to cover the no-definition branch.
    • fix(actions): validate action_type before querying details to avoid rosapi crash

    • test(actions): negative test asserts rosapi survives bogus action_type

    • refactor(actions): clarify get_action_details API, harden status/cancel, cover send/cancel

    • get_action_details: tool description/docstring now state action_type is
      required and point to the right discovery path; distinguish 'interfaces
      unavailable' from 'type not found'
    • get_action_status: report an idle action as 0 goals instead of an error
    • cancel_action_goal: note that success means the request was sent, not acked
    • send_action_goal/cancel: normalize action_name to a leading slash
    • tests: add send_action_goal and cancel_action_goal coverage (ROS 2 goal
      completion + error paths), scope the action_type regression test to ROS 2
    • refactor(parameters): migrate to rosapi_service()/rosapi_type(), add tool tests (step6) (#332)

    • refactor(parameters): use rosapi_service()/rosapi_type() for rosapi calls

    Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

    • test(parameters): integration tests for parameter tools across all distros

    Covers get_parameter, set_parameter, has_parameter, delete_parameter,
    get_parameters, and get_parameter_details against live rosbridge containers
    on melodic, noetic, humble, and jazzy. Three ROS 1 behaviors are skipped
    with documented reasons: has_parameter false-positive for non-existent params,
    delete_param successful=False response format mismatch, and get_parameters
    relying on ROS 2-only per-node list_parameters service.

    Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

    • test(parameters): make test_delete_round_trip skips explicitly version-conditional

    Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

    • test(parameters): DRY existing-param lookup, tighten successful check, restore mutated param

    Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

    • fix(parameters): handle ROS 1 rosapi response shapes, unskip lazy tests

    Two real ROS 1 bugs were surfaced by writing the integration tests, and
    the prior commit took the lazy path of skipping them. Fix the bugs and
    remove the skips.

    1. _safe_check_parameter_exists (used by has_parameter, set_parameter,
      delete_parameter, get_parameter_details): on ROS 1, rosbridge returns
      {"values": {"value": "null"}, "result": true} for a missing param.
      _is_empty_value treated only "" and bare quotes as empty, so any
      nonexistent param was misclassified as existing. Treat the literal
      string "null" as the missing sentinel.

    2. delete_parameter response parsing: rosapi delete_param returns
      {"values": {}, "result": true} on success. The handler read
      "successful" out of values with a default of False, so every
      successful ROS 1 delete reported successful=False. Fall back to the
      top-level "result" field when "successful" is absent from values.

    Also restructure test_parameters.py to:

    • drop the ROS 1 skip in test_nonexistent_parameter (now passes)
    • drop the ROS 1 skip in test_delete_round_trip (now passes; ROS 2 still
      skips, since per-node turtlesim params can't be round-tripped via
      rosbridge)
    • assert the documented ROS-2-only error path in test_returns_list_for_known_node
      instead of skipping
    • drop both ROS 1 skips in TestGetParameterDetails (the tool already had
      a value-based type inference fallback for when describe_parameters is
      unavailable, so it works on ROS 1)

    Test counts before -> after:

    • melodic: 77 passed, 7 skipped -> 82 passed, 2 skipped
    • noetic: 77 passed, 7 skipped -> 82 passed, 2 skipped
    • humble: 83 passed, 1 skipped -> 83 passed, 1 skipped
    • jazzy: 83 passed, 1 skipped -> 83 passed, 1 skipped

    The 2 remaining ROS 1 skips are pre-existing action tests; the 1
    remaining ROS 2 skip is the documented per-node deletion limitation.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • test(parameters): make ROS 2 delete-round-trip skip reason evidence-based

    Verified against a live humble container: turtlesim silently drops undeclared
    params (set 'succeeds' but nothing persists), and deleting a declared param
    crashes the rosapi node. So ROS 2 delete-success genuinely can't be exercised
    here; the skip protects the suite. The testable ROS 2 delete paths (nonexistent,
    empty name) remain covered by the other tests.

    • refactor(parameters): drop unused _PARAMS key, document has_parameter limitation
    • Remove the unused 'read_name' entry from the _PARAMS test fixture
    • Document in has_parameter that empty-string / literal 'null' values are
      reported as nonexistent (rosbridge ROS 1 get_param has no exists signal)
    • Coerce delete_parameter's success value to bool for symmetry with the
      result-fallback branch

    Co-authored-by: Claude Sonnet 4.6 noreply@anthropic.com

    • refactor(metadata): migrate ros_metadata to rosapi helpers + tests (step7) (#339)

    Migrate ros_mcp/resources/ros_metadata.py to rosapi_service()/rosapi_type()
    and the centralized version resolver, completing the rosapi migration series
    (step3-6). Adds integration tests for all five ros-mcp://ros-metadata/*
    resources, including graceful-degradation coverage.

    Verified green on melodic / noetic / humble / jazzy.

    • docs(install): explain macOS zsh -lc / uvx PATH pitfall (#340)

    zsh -lc starts a login, non-interactive shell that sources
    ~/.zprofile but not ~/.zshrc, where the uv installer adds
    ~/.local/bin to PATH. Claude Desktop's subprocess therefore can't
    find uvx and fails to attach, even though uvx ros-mcp --help works
    in a normal terminal.

    Add a Troubleshooting section with the reproduce command and two
    fixes (add ~/.local/bin to ~/.zprofile, or use the absolute uvx
    path), and cross-link it from the macOS config block.

    Closes #310

    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • docs(install): document rosapi as a required dependency (#341)

    ros-mcp-server needs both rosbridge_server (WebSocket) and rosapi
    (introspection services). Starting rosbridge with ros2 run /
    rosrun brings up the WebSocket without rosapi, so every
    introspection tool fails with "Service does not exist".

    Explain the requirement on the rosbridge setup page, point users at
    the launch file (which starts both) rather than run, mention the
    rosbridge-suite metapackage, and add a rosapi presence check to the
    verification step.

    Closes #277

    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • chore(release): bump version to 3.1.0

    Co-authored-by: Rohit John Varghese rohit@contoro.com
    Co-authored-by: Rohit John Varghese 93564012+r-johnv@users.noreply.github.com
    Co-authored-by: Rohit John Varghese 93564012+rjohn-v@users.noreply.github.com
    Co-authored-by: Giovanni Toffetti toff@zhaw.ch
    Co-authored-by: Bharat Jain bharat.jain@plaksha.edu.in
    Co-authored-by: Bharat Jain 152432505+itsbharatj@users.noreply.github.com
    Co-authored-by: Yuta 120556494+Yutarop@users.noreply.github.com
    Co-authored-by: Luis Luna 158509707+luisluna01@users.noreply.github.com
    Co-authored-by: Jungsoo Lee 69760395+lpigeon@users.noreply.github.com
    Co-authored-by: triepod-ai 199543909+triepod-ai@users.noreply.github.com
    Co-authored-by: Claude Opus 4.5 noreply@anthropic.com
    Co-authored-by: mokcontoro mokcontoro@users.noreply.github.com
    Co-authored-by: Wouter 151727235+woutervhaaften@users.noreply.github.com
    Co-authored-by: mok mok@contoro.com
    Co-authored-by: Changyong Kwak samisme2005@gmail.com
    Co-authored-by: Leo Jeong 77630442+Tyrrnien81@users.noreply.github.com
    Co-authored-by: Raphael(Hyuntaek) Oh raphy0316@naver.com
    Co-authored-by: hoh78 hoh78@wisc.edu
    Co-authored-by: Sunghwan Cho 89915211+sunnycho100@users.noreply.github.com
    Co-authored-by: sbae56-art sbae56@wisc.edu
    Co-authored-by: RobotMCP Bot admin@robotmcp.ai

    下载附件