Skip to content

Add entity lifecycle status MCP tools (apps + components) - #23

Open
bburda wants to merge 3 commits into
mainfrom
feat/lifecycle-status
Open

Add entity lifecycle status MCP tools (apps + components)#23
bburda wants to merge 3 commits into
mainfrom
feat/lifecycle-status

Conversation

@bburda

@bburda bburda commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Add ros2_medkit_status_get and ros2_medkit_status_set MCP tools (with sovd_status_get / sovd_status_set back-compat aliases), wrapping the gateway 0.6.0 entity lifecycle API. status_get reads the readiness status; status_set triggers a transition (start / restart / force-restart / shutdown / force-shutdown). Restricted to apps and components; other entity types and unknown actions are rejected with a clear error.


Issue


Type

  • Bug fix
  • New feature
  • Breaking change
  • Documentation only

Testing

In a worktree branched from origin/main (post-0.6.0-migration):

  • run_tests.py - 184 passed (168 baseline + 16 new lifecycle/tool/arg-model tests)
  • ruff check src/ tests/ - clean
  • ruff format --check src/ tests/ - clean
  • mypy src/ - clean

Checklist

  • Breaking changes are clearly described (none - additive feature)
  • Linting passes (poetry run ruff check src/ tests/)
  • Formatting passes (poetry run ruff format --check src/ tests/)
  • Type checking passes (poetry run mypy src/)
  • Tests pass (poetry run python run_tests.py)
  • Docs were updated if behavior or public API changed (README lifecycle tools section)

Expose ros2_medkit_status_get/set for apps and components (start,
restart, force-restart, shutdown, force-shutdown), with sovd_*
back-compat aliases. Wraps the gateway 0.6.0 lifecycle API; rejects
other entity types and unknown actions.
Copilot AI lite review requested due to automatic review settings June 25, 2026 08:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class MCP tool support for the ros2_medkit gateway (v0.6.0) entity lifecycle status API, allowing clients to query readiness state and trigger lifecycle transitions for apps and components (with sovd_* aliases preserved for backward compatibility).

Changes:

  • Added lifecycle argument models (LifecycleEntityType, LifecycleAction, StatusGetArgs, StatusSetArgs) to validate entity-type and action inputs.
  • Added two new MCP tools (ros2_medkit_status_get, ros2_medkit_status_set) plus sovd_status_get / sovd_status_set aliases, wiring dispatch through to the client.
  • Implemented lifecycle API support in SovdClient (get_status, set_status) and added corresponding unit tests and README documentation.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/ros2_medkit_mcp/client.py Adds lifecycle endpoint routing, validation, and get_status/set_status client methods backed by generated lifecycle API functions.
src/ros2_medkit_mcp/models.py Introduces Pydantic argument models/enums for lifecycle status tools with strict validation (apps/components + allowed actions).
src/ros2_medkit_mcp/mcp_app.py Registers the new MCP tools, adds aliases, and dispatches tool calls to the new client lifecycle methods.
tests/test_new_tools.py Adds integration-style client tests for lifecycle GET/PUT behavior and input rejection cases.
tests/test_mcp_app.py Adds unit tests for tool alias resolution and Pydantic validation of lifecycle argument models.
README.md Documents the new lifecycle tools and their arguments/return behavior.

@bburda bburda self-assigned this Aug 20, 2026
Comment thread README.md Outdated
- `entity_id` (required, string): The entity identifier
- `action` (required, string): one of `start`, `restart`, `force-restart`, `shutdown`, `force-shutdown`

**Returns:** `202 Accepted` from `PUT /{entity_type}/{entity_id}/status/{action}` (no body)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 202 here is the happy path only when a LifecycleProvider plugin handles the entity. I ran ghcr.io/selfpatch/ros2_medkit-jazzy:latest and every transition PUT returns 501 [not-implemented] Lifecycle control not available for this entity - the gateway's handle_transition requires a plugin provider and there is no default one, so on a stock gateway status_set always fails while status_get works. Worth one sentence here (and in the status_set tool description, so the model can relay it) - otherwise a first-time user concludes the tool is broken. Also, the MCP tool itself returns {} rendered as JSON, not a raw 202.

A transition PUT is answered by a gateway-side LifecycleProvider plugin and
no provider ships with the gateway, so on a stock gateway every status_set
call comes back as 501 not-implemented while status_get works. Say so in the
README and in the tool description, and describe what the tool actually
returns on success: an empty JSON object, not a raw 202.

Cover the paths that carried the claim: the missing-provider 501 for all five
actions, both entity types against every action so a wrong _ENTITY_FUNC_MAP
entry shows as a request to the wrong URL, and the registered MCP handlers -
tool registry, schema enums, dispatch and the sovd_* alias - which no test
reached before.
Copilot AI review requested due to automatic review settings August 22, 2026 20:58
models.py switched to StrEnum for FaultStatus; the lifecycle enums are
declared the same way so the import stays a single name.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (3)

README.md:390

  • The lifecycle API is introduced specifically with the gateway 0.6.0 contract, so older gateways that do not expose /{entity_type}/{entity_id}/status will return an error for reads as well. Please qualify this statement (for example, “Reading the status works on gateways that expose the 0.6.0 lifecycle API”) so users do not assume compatibility with every gateway version.
Reading the status works on any gateway. Triggering a transition requires the gateway
to have a `LifecycleProvider` plugin registered for the entity; there is no built-in

README.md:392

  • The MCP tool does not return the documented 501 prefix here: _call_void stores the status in SovdClientError.status_code, but its message for this error envelope is only [not-implemented] ..., and call_tool does not append status_code. This also conflicts with the exact output documented below on line 411; please describe the actual tool error (or change the formatter if the HTTP status must be exposed).
`501 [not-implemented] Lifecycle control not available for this entity`.

src/ros2_medkit_mcp/mcp_app.py:2643

  • This tool description also presents status_get as working on a stock gateway without stating the required gateway version. Since this client is pinned to and the feature is defined for gateway 0.6.0, older gateways can reject the GET endpoint; qualify the claim here so the tool metadata does not overstate compatibility.
                    " LifecycleProvider plugin for the entity; there is no"
                    " built-in provider, so a stock gateway answers every"
                    " transition with 'not-implemented' while status_get still"
                    " works. On success the gateway returns a body-less 202 and"

Copilot AI review requested due to automatic review settings August 22, 2026 21:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

README.md:392

  • SovdClientError keeps the HTTP status in status_code, but call_tool formats only str(e), so the tool output contains [not-implemented] Lifecycle control not available for this entity without the 501 prefix. This example disagrees with the actual response (and with the wording below); please update the documented error text or include status codes in the formatter.
`501 [not-implemented] Lifecycle control not available for this entity`.

src/ros2_medkit_mcp/mcp_app.py:3265

  • At this branch, an unsupported entity_type or action raises ValidationError, but the broad handler below converts it into Internal error: .... That mislabels invalid user input as a server failure and does not provide the clear rejection promised for lifecycle arguments. Handle validation errors as input errors (or validate these arguments before dispatch) so the response is not labeled internal.
                status_get_args = StatusGetArgs(**arguments)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add entity lifecycle status MCP tools (apps + components)

3 participants