ros2_medkit_mcp
Provides MCP tools to interact with ROS 2 systems via the SOVD HTTP API, enabling discovery of entities, reading and publishing topic data, calling services and actions, and managing parameters.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ros2_medkit_mcplist all components"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ros2_medkit_mcp
A thin MCP (Model Context Protocol) adapter that connects an LLM to an existing SOVD HTTP API exposed by ros2_medkit.
Overview
This server does not implement SOVD itself. It provides MCP tools that call the existing HTTP endpoints of a running ros2_medkit gateway.
Related MCP server: Agentforce MCP Integration Server
Features
Full ros2_medkit gateway coverage: Discovery, component data, operations (services/actions), configurations (ROS 2 parameters), and entity lifecycle status (apps/components)
Dual transport support: stdio and streamable-http
Async HTTP client using httpx
Pydantic validation for configuration and models
Bearer token authentication support
Quick Start
Prerequisites
Installation
# Clone the repository
git clone https://github.com/selfpatch/ros2_medkit_mcp.git
cd ros2_medkit_mcp
# Install dependencies with Poetry
poetry installOr with uv:
uv venv
uv pip install -e . # add '.[dev]' for the test and lint toolsThe project uses the Poetry build backend, so install it with
uv pip install(notuv sync, which only reads PEP 621[project]dependencies). The entry points then live in.venv/bin/.
Don't want a checkout at all? Run it straight from the repository with uvx:
uvx --from git+https://github.com/selfpatch/ros2_medkit_mcp ros2-medkit-mcp-stdioConfiguration
The server is configured via environment variables:
Variable | Default | Description |
|
| Base URL of the ros2_medkit SOVD API |
| (none) | Optional Bearer token for authentication |
|
| HTTP request timeout in seconds |
Running the Server
stdio Transport (for Claude Desktop, etc.)
poetry run ros2-medkit-mcp-stdio
# uv: uv run --no-sync ros2-medkit-mcp-stdio (or: .venv/bin/ros2-medkit-mcp-stdio)
# uvx: uvx --from git+https://github.com/selfpatch/ros2_medkit_mcp ros2-medkit-mcp-stdioFor Claude Desktop, add to your claude_desktop_config.json:
{
"mcpServers": {
"ros2_medkit": {
"command": "poetry",
"args": ["run", "ros2-medkit-mcp-stdio"],
"cwd": "/path/to/ros2_medkit_mcp",
"env": {
"ROS2_MEDKIT_BASE_URL": "http://localhost:8080/api/v1"
}
}
}
}Or with uvx, which needs no local checkout (drop the cwd):
{
"mcpServers": {
"ros2_medkit": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/selfpatch/ros2_medkit_mcp",
"ros2-medkit-mcp-stdio"
],
"env": {
"ROS2_MEDKIT_BASE_URL": "http://localhost:8080/api/v1"
}
}
}
}Streamable HTTP Transport
poetry run ros2-medkit-mcp-http --host 0.0.0.0 --port 8765
# uv: uv run --no-sync ros2-medkit-mcp-http --host 0.0.0.0 --port 8765
# uvx: uvx --from git+https://github.com/selfpatch/ros2_medkit_mcp ros2-medkit-mcp-http --host 0.0.0.0 --port 8765The server will be available at http://0.0.0.0:8765/mcp.
VS Code MCP Configuration
See the examples/ directory for ready-to-use MCP configuration files:
mcp-stdio.json- Local stdio transportmcp-http.json- HTTP transport for remote server
Docker
# Build image
docker build -t ros2-medkit-mcp .
# Run HTTP server (default)
docker run -p 8765:8765 ros2-medkit-mcp
# Run with stdio transport
docker run -i ros2-medkit-mcp stdio
# With custom gateway URL
docker run -p 8765:8765 -e ROS2_MEDKIT_BASE_URL=http://host.docker.internal:8080/api/v1 ros2-medkit-mcpUsing docker-compose:
docker-compose upUsing Docker Image as MCP Server in VS Code
To use the Docker image as an MCP server in VS Code with the GitHub Copilot extension:
Start the MCP server container:
docker run -d --name ros2-medkit-mcp -p 8765:8765 \ -e ROS2_MEDKIT_BASE_URL=http://host.docker.internal:8080/api/v1 \ ghcr.io/selfpatch/ros2_medkit_mcp:latestConfigure VS Code MCP settings (
.vscode/mcp.jsonor user settings):{ "servers": { "ros2_medkit": { "type": "sse", "url": "http://localhost:8765/mcp", "headers": {} } } }Verify the connection by checking the health endpoint:
curl http://localhost:8765/healthExpected response:
{"status": "healthy", "service": "ros2_medkit_mcp", "sovd_url": "http://host.docker.internal:8080/api/v1"}Use with Copilot Chat - the MCP tools will be available for querying ROS 2 system state via SOVD API.
Note: Use
host.docker.internalto connect from the container to services running on your host machine (like ros2_medkit gateway).
MCP Tools
Discovery Tools
sovd_version
Get the SOVD API version information.
Arguments: None
Returns: JSON version object from GET /version-info
sovd_entities_list
List all SOVD entities (areas, components, apps, and functions) with optional filtering.
Arguments:
filter(optional, string): Substring filter applied to entityidandnamefields
Returns: Combined array of areas from GET /areas, components from GET /components, apps from GET /apps, and functions from GET /functions (when those endpoints are available)
sovd_entities_get
Get a specific entity by ID with live data if available.
Arguments:
entity_id(required, string): The entity identifier
Returns: Entity object with optional data field for components
sovd_faults_list
List faults for a specific component.
Arguments:
component_id(required, string): The component identifier
Returns: Array of fault objects from GET /components/{component_id}/faults
sovd_faults_get
Get a specific fault by ID.
Arguments:
component_id(required, string): The component identifierfault_id(required, string): The fault identifier
Returns: Fault object from GET /components/{component_id}/faults/{fault_id}
sovd_faults_clear
Clear (acknowledge/dismiss) a fault.
Arguments:
component_id(required, string): The component identifierfault_id(required, string): The fault identifier to clear
Returns: Response from DELETE /components/{component_id}/faults/{fault_id}
sovd_area_components
List all components within a specific area.
Arguments:
area_id(required, string): The area identifier (e.g., 'powertrain', 'chassis', 'body')
Returns: Array of component objects from GET /areas/{area_id}/components
Entity Data Tools
sovd_entity_data
Read all topic data from an entity (component or app).
Arguments:
entity_id(required, string): The entity identifierentity_type(optional, string): Entity type - 'components' or 'apps' (default: 'components')
Returns: Array of topic data from GET /{entity_type}/{entity_id}/data
sovd_entity_topic_data
Read data from a specific topic within an entity.
Arguments:
entity_id(required, string): The entity identifiertopic_name(required, string): The topic name (e.g., 'temperature', 'rpm')entity_type(optional, string): Entity type - 'components' or 'apps' (default: 'components')
Returns: Topic data from GET /{entity_type}/{entity_id}/data/{topic_name}
sovd_publish_topic
Publish data to a component's topic.
Arguments:
component_id(required, string): The component identifiertopic_name(required, string): The topic name to publish todata(required, object): The message data to publish as JSON object
Returns: Response from PUT /components/{component_id}/data/{topic_name}
Operations Tools (Services & Actions)
sovd_list_operations
List all operations (services and actions) available for a component.
Arguments:
component_id(required, string): The component identifier
Returns: Array of operations from GET /components/{component_id}/operations
sovd_create_execution
Call a ROS 2 service or send an action goal.
Arguments:
entity_id(required, string): The entity identifieroperation_name(required, string): The operation name (service or action)request_data(optional, object): Request data (parameters for actions/services)entity_type(optional, string): Entity type - 'components', 'apps', 'areas', or 'functions' (default: 'components')
Returns: Response from POST /{entity_type}/{entity_id}/operations/{operation_name}/executions
sovd_get_execution
Get the current status of a running action execution.
Arguments:
entity_id(required, string): The entity identifieroperation_name(required, string): The action nameexecution_id(required, string): The execution ID (goal_id)entity_type(optional, string): Entity type (default: 'components')
Returns: Status from GET /{entity_type}/{entity_id}/operations/{operation_name}/executions/{execution_id}
sovd_list_executions
List all executions for an operation.
Arguments:
entity_id(required, string): The entity identifieroperation_name(required, string): The action nameentity_type(optional, string): Entity type (default: 'components')
Returns: List from GET /{entity_type}/{entity_id}/operations/{operation_name}/executions
sovd_cancel_execution
Cancel a running action execution.
Arguments:
entity_id(required, string): The entity identifieroperation_name(required, string): The action nameexecution_id(required, string): The execution ID (goal_id)entity_type(optional, string): Entity type (default: 'components')
Returns: Response from DELETE /{entity_type}/{entity_id}/operations/{operation_name}/executions/{execution_id}
Configuration Tools (ROS 2 Parameters)
sovd_list_configurations
List all configurations (ROS 2 parameters) for a component.
Arguments:
component_id(required, string): The component identifier
Returns: Array of parameters from GET /components/{component_id}/configurations
sovd_get_configuration
Get a specific configuration (parameter) value.
Arguments:
component_id(required, string): The component identifierparam_name(required, string): The parameter name
Returns: Parameter value from GET /components/{component_id}/configurations/{param_name}
sovd_set_configuration
Set a configuration (parameter) value.
Arguments:
component_id(required, string): The component identifierparam_name(required, string): The parameter namevalue(required, any): The new parameter value (string, number, boolean, or array)
Returns: Response from PUT /components/{component_id}/configurations/{param_name}
sovd_delete_configuration
Reset a configuration (parameter) to its default value.
Arguments:
component_id(required, string): The component identifierparam_name(required, string): The parameter name
Returns: Response from DELETE /components/{component_id}/configurations/{param_name}
sovd_delete_all_configurations
Reset all configurations (parameters) to their default values.
Arguments:
component_id(required, string): The component identifier
Returns: Response from DELETE /components/{component_id}/configurations
Lifecycle Tools
Lifecycle status is only available for apps and components (not areas or functions).
Reading the status needs no plugin - the gateway derives it from the ROS 2 graph and,
for managed lifecycle nodes, from their reported state. Triggering a transition does need
one: the gateway routes it to a LifecycleProvider plugin registered for that entity, and
no provider ships with the gateway. A transition on a local app or component of a gateway
with no provider therefore gets HTTP 501 from the gateway, which this server surfaces as
[not-implemented] Lifecycle control not available for this entity. An aggregating
gateway forwards requests for remote entities to the peer that owns them, so a peer that
does have a provider answers normally.
ros2_medkit_status_get
Get the lifecycle status of an app or component (e.g. ready / notReady).
Arguments:
entity_type(required, string):appsorcomponentsentity_id(required, string): The entity identifier
Returns: Response from GET /{entity_type}/{entity_id}/status
ros2_medkit_status_set
Trigger a lifecycle transition on an app or component via PUT /{entity_type}/{entity_id}/status/{action}. Requires a gateway-side LifecycleProvider plugin for the entity. Warning: shutdown, force-shutdown, restart, and force-restart affect the running node or host process.
Arguments:
entity_type(required, string):appsorcomponentsentity_id(required, string): The entity identifieraction(required, string): one ofstart,restart,force-restart,shutdown,force-shutdown
Returns: {} - the gateway accepts the transition with a body-less 202, which the tool renders as an empty JSON object. With no provider registered for the entity the call returns the gateway error instead: [not-implemented] Lifecycle control not available for this entity.
MCP Resources
sovd://openapi
Returns information about the OpenAPI specification location.
Development
Setup
# Install dependencies including dev tools
poetry install
# Install pre-commit hooks
poetry run pre-commit installRunning Tests
# Use the test runner script (recommended, avoids ROS 2 plugin conflicts)
poetry run python run_tests.py -v
# Or directly if not in a ROS 2 environment
poetry run pytest -vCode Quality
# Run all pre-commit hooks
poetry run pre-commit run --all-files
# Or run individually:
poetry run ruff check src/ tests/ # Linting
poetry run ruff format src/ tests/ # Formatting
poetry run mypy src/ # Type checkingLicense
This server cannot be deployed
Maintenance
Related MCP Connectors
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
MCP-Native LLM Orchestration Agent
LLM Orchestration Agent (Mcp)
LLM Orchestration MCP Agent
Related MCP Servers
- AlicenseAqualityDmaintenanceA generic MCP server that dynamically exposes any OpenAPI-documented REST API to LLMs by auto-discovering endpoints. It provides tools for exploring API capabilities and making authenticated requests directly through natural language interfaces.27 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to connect to LLM/API services using the Model Context Protocol, providing real-time interaction and tool access. Also offers RESTful API endpoints via FastAPI for programmatic integration with existing systems.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceBridges LLM clients with existing RESTful microservices by converting MCP tool calls into REST requests, enabling any REST API to be used as an MCP tool without modifying the microservices.486,710 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables LLMs to interact with any REST API that has an OpenAPI specification by providing a lightweight MCP server that translates between natural language and API calls.MIT