Adapt to the gateway 0.7.0 client surface - #30
Merged
Conversation
bburda
force-pushed
the
fix/gateway-070-client-surface
branch
2 times, most recently
from
September 2, 2026 09:49
cfd0a33 to
75da163
Compare
bburda
marked this pull request as ready for review
September 2, 2026 09:57
mfaferek93
approved these changes
Sep 2, 2026
Lifecycle operation ids lost their plural form, so the generated modules are get_app_status, put_app_status_restart and the rest. The dispatch map named the old ones, and because client.py imports the API groups at module level this was not only a lifecycle failure - nothing that imports ros2_medkit_mcp.client started at all. Two request bodies the gateway used to leave open are now described, and both revealed calls the gateway had been rejecting: - Script execution sends ScriptExecutionRequest. The caller's params went out as the whole body, so the gateway answered 400 'Missing required field: execution_type' for every execution this server has ever started. They now travel under 'parameters'. execution_type is an argument that defaults to 'now': that is the only value the built-in backend accepts, but the schema leaves it an open string and says a provider plugin defines its own vocabulary, so hardcoding it put a value the API treats as the caller's choice out of reach. The presence check on params is 'is not None', because parameters reaches the provider untouched and an explicitly empty object is a different request from an absent one. - Update registration requires 'id'. The tool's example omitted it, so an agent following the description built a request the gateway refused. Data categories and data groups answer 501 on every entity type; the ROS 2 data provider neither groups nor categorises its topics. Their tests mocked a 200 no gateway returns, so they passed while the tools could not work. They now assert what the gateway sends, and a pinning test keeps the undocumented-200 path visible if the schema ever gains one. The client pin moves to the 0.7.0 wheel, and the package version follows it.
bburda
force-pushed
the
fix/gateway-070-client-surface
branch
from
September 2, 2026 11:23
75da163 to
3e94f44
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Summary
The gateway 0.7.0 spec renames and tightens parts of the surface this server calls. Adapting to it also fixed two calls the gateway had been rejecting all along.
Lifecycle. The operation ids lost their plural form, so the generated modules are now
get_app_status,put_app_status_restartand the rest. The dispatch map named the old ones. Becauseclient.pyimports the API groups at module level, this was not only a lifecycle failure - nothing that importsros2_medkit_mcp.clientstarted at all.Script execution. The body is
ScriptExecutionRequest, whereexecution_typeis required and the script inputs belong underparameters. The caller params went out as the whole body, so every execution this server started got:They now travel under
parameters, withexecution_typeset tonow. That is the only value the shipped backend accepts, and the tool exposes no scheduling, so it is not something a caller has to supply.Update registration.
idis required and validated by the gateway, and becomes the path segment of theLocationheader on 201. The tool description showed an example without it, so an agent following the description built a request the gateway refused. The description now saysidis required and the example uses it.Data categories and data groups. These answer
501 not-implementedon every entity type, because the ROS 2 data provider neither groups nor categorises its topics. The 0.7.0 spec documents that; the 0.6.0 spec advertised a200the gateway never returned. Their tests mocked that200, so they passed while the tools could not work. The tools stay in the set, since a provider plugin may implement the resources, and the error mapping already carries the gateway reason out intact:The tests now assert that. One more test pins the undocumented-200 path, so adding a
200to the gateway schema shows up here instead of silently changing what the tool returns.Execution type. The body's
execution_typewas going out as a hardcodednow. That is the only value the built-in script backend accepts, but the schema leaves it an open string and says a provider plugin defines its own vocabulary, so hardcoding it put a value the API treats as the caller's choice out of reach. It is an argument now, still defaulting tonow, and the tool schema says what it means. The presence check onparamswas a truth test, so an explicitly empty object and an absent one produced the same request;parametersreaches the provider untouched, so those are two different requests.This is a draft on purpose. The package version moves to 0.7.0 alongside the client pin, which is not published yet, so
poetry.lockis stale andpoetry check --lockfails. Runpoetry lockonceros2_medkit_client0.7.0 is released, then this is ready.Issue
Type
Testing
Verified against a gateway built from the 0.7.0 release branch, with the client regenerated from that gateway's exported spec and installed locally.
poetry run python run_tests.pypasses 221 tests. The three new ones assert the request body rather than the response status, since a 202 comes back either way: the script inputs travel underparameters, a caller-supplied execution type is forwarded, and an explicitly empty parameters object survives. Before the change the suite did not run at all: 6 test modules failed to import withImportError: cannot import name 'get_apps_status'.poetry run ruff check .,poetry run ruff format --check src/ tests/andpoetry run mypy src/are clean.get_statuson an app and on a component both return{"status": "notReady"}, so the renamed modules resolve and the request reaches the gateway.set_statusreaches the gateway and gets its real answer for these entities ([not-implemented] Lifecycle control not available for this entity).execute_script("talker", "hello", {"iterations": 3})runs the script and the script reads backhello {"iterations":3}on stdin, so the parameters arrive where the provider looks for them.400 Missing required field: execution_type, and the new shape answers202.list_data_categoriesandlist_data_groupsreturn[not-implemented] Data categories are not implemented for ROS 2and the matching message for groups.Checklist
poetry run ruff check src/ tests/)poetry run ruff format --check src/ tests/)poetry run mypy src/)poetry run python run_tests.py)