Repository navigation
refactor(rocmd): move the MCP argv builders and read-only allowlist out of mcp.rs into mcp_argv.rs - #905
Conversation
…ut of mcp.rs into mcp_argv.rs mcp.rs mixed the MCP server and tool dispatch with the pure argument handling behind the tools that spawn rocm. Move that handling into its own module: - normalized_rocm_command_args and ensure_rocm_command_is_read_only, the read-only allowlist behind the rocm_command tool - build_install_sdk_args, build_install_engine_args, build_launch_server_args and build_watcher_enable_args, with their private helpers is_loopback_host and system_prefix_requires_ack The 12 tests that exercise these functions move with them into mcp_argv.rs's own test module, keeping their names and the cfg(unix) gate on the home-escape test. None of them uses test_support. The tool list, the direct-approval classification and their tests stay in mcp.rs, since they read the tool table. This is a pure move. The only edits besides the relocation are widening the six functions mcp.rs calls from private to pub(crate), the import lines, the mod declaration in lib.rs, the docs/architecture.md entries, and a stale path in a comment in apps/rocm/src/remote/mod.rs that named lib.rs for ensure_rocm_command_is_read_only. mcp_argv.rs imports nothing from the rest of the crate, so mcp.rs depends on it and not the other way round. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
There was a problem hiding this comment.
🟢 Approval recommended
There are no active review issues blocking the argument-handling refactor.
No open issues 🎉
What changed in this PR
This refactor separates MCP argument handling from rocmd’s server and dispatch code, reducing mcp.rs without changing user-visible behavior.
Changes:
- Moves argument normalization, the read-only allowlist, four argument builders, and their 12 tests into
mcp_argv.rs. - Registers the new module and imports its six crate-visible functions, leaving dispatch and approval checks in
mcp.rs. - Updates architecture documentation and corrects a source-path comment.
| File | Description |
|---|---|
docs/architecture.md |
Documents the new module and revised MCP responsibilities. |
apps/rocmd/src/mcp.rs |
Imports extracted helpers and removes relocated code and tests. |
apps/rocmd/src/mcp_argv.rs |
Contains argument handling, validation helpers, and 12 relocated tests. |
apps/rocmd/src/lib.rs |
Registers the private mcp_argv module. |
apps/rocm/src/remote/mod.rs |
Corrects the allowlist’s location in a comment; no functional change. |
Review effort: Balanced
juhovainio
left a comment
There was a problem hiding this comment.
Reviewed the move of the MCP argv builders and read-only allowlist from mcp.rs into mcp_argv.rs. The moved bodies are identical to the originals; the only differences are the six fns widened from private to pub(crate) (stated in the PR body), the new module header/use lines, the tests wrapper, and a trimmed rocm_core import list in mcp.rs. All 12 tests moved with their cfg(unix) gate, mod mcp_argv; is declared in lib.rs, the architecture.md links resolve, and the stale comment in remote/mod.rs is corrected. No blocking or non-blocking findings.
CI note: the Strix Halo E2E lane failed with 'llama-server failed to start', which looks like infra rather than this change; the MI300X and W7900 lanes were still pending when I checked.
Summary
apps/rocmd/src/mcp.rsheld the MCP stdio server, the tool table and dispatch, and the argument handling behind the tools that spawnrocm, all in one file of about 1,650 lines. This moves the argument handling into its own module,apps/rocmd/src/mcp_argv.rs, together with the tests that exercise it. It is a pure, behaviour-preserving move and part of the Phase 8.2-D follow-up work to finish splitting the oversizedrocmdmodules. After the movemcp.rshas about 860 production lines (was about 1,140) andmcp_argv.rsabout 305.What moved
normalized_rocm_command_argsmcp.rsmcp_argv.rspub(crate)ensure_rocm_command_is_read_only(the read-only allowlist behind therocm_commandtool)mcp.rsmcp_argv.rspub(crate)build_install_sdk_argsmcp.rsmcp_argv.rspub(crate)build_install_engine_argsmcp.rsmcp_argv.rspub(crate)build_launch_server_argsmcp.rsmcp_argv.rspub(crate)build_watcher_enable_argsmcp.rsmcp_argv.rspub(crate)is_loopback_host,system_prefix_requires_ack(helpers of the builders)mcp.rsmcp_argv.rsTwelve tests moved with them into
mcp_argv.rs's ownmod tests, keeping their names and thecfg(unix)gate oninstall_sdk_rejects_system_prefix_reached_by_escaping_home:remote_read_only_verbs_are_allowed_and_mutating_ones_are_not,rocm_command_helper_allows_only_read_only_rocm_commands,rocm_command_helper_treats_setup_status_as_read_only_and_reset_as_mutating,rocm_command_helper_treats_runtimes_uninstall_dry_run_as_read_only,storage_report_is_read_only_but_removal_is_not,launch_server_rejects_public_bind_without_ack,launch_server_forwards_public_bind_ack,install_sdk_rejects_system_prefix_without_ack,install_sdk_rejects_system_prefix_reached_by_escaping_home,install_sdk_real_install_args_approve_only_the_runtime_replacement,install_sdk_forwards_requested_build_date_and_rejects_conflictandwatcher_enable_builds_mode_args. The count of 12 matches the plan, and none of them usestest_support.What stays in
mcp.rs: the server loop,rocm_mcp_toolsandrocm_mcp_tool, the direct-approval classification (mcp_tool_requires_direct_approval,ensure_direct_mcp_call_allowed) and its two tests (they read the tool table, so moving them would makemcp_argv.rsimportmcp.rsback), the result shapers,read_tail_lines, and the six remaining tests.The only non-move edits are: the six visibility widenings above; the
uselines (mcp.rsgainsuse crate::mcp_argv::{...}and drops the now-unusedDEFAULT_LOCAL_HOSTimport);mod mcp_argv;inlib.rs; thedocs/architecture.mdentry formcp_argv.rsand the updatedmcp.rsentry; and one comment inapps/rocm/src/remote/mod.rsthat namedapps/rocmd/src/lib.rsas the home ofensure_rocm_command_is_read_only(it never lived there) and now namesmcp_argv.rs. rustfmt re-wrapped the signatures of four functions after thepub(crate)prefix lengthened them.Verification
Ran locally:
cargo fmt --all --checkpasses.cargo clippy -p rocmd --all-targets -- -D warningspasses.cargo test -p rocmd --no-fail-fast: 168 passed, 0 failed, 1 ignored.cargo test -p rocmd -- --listand the same with--list --ignored,origin/mainagainst this branch (the baseline built in a separate clean worktree): both empty, 169 and 1 entries on each side. The new list has 12 tests undermcp_argv::testsand 6 undermcp::tests, whereorigin/mainhad 18 undermcp::tests.mcp.rsagainstmcp_argv.rs: every removed line is present in the new file apart from the six signature lines that gainedpub(crate)or were re-wrapped, and the removeduse rocm_core::{...}line.cargo xtask manifest --checkandcargo xtask check-crate-edgespass;cargo xtask lycheepasses (the commit hooks, including lychee and the license-header check, also passed).git diff origin/main...HEADwith the AGENTS.md pattern: no hits. NoPhasewording in the added lines ofdocs/architecture.md.Not run:
cargo clippy -p rocmd --all-targets --target x86_64-pc-windows-msvc: the moved code has nocfg(windows)part (only the onecfg(unix)test, which moved with its gate), but the cross-check could not be completed here because a dependency's build script needslib.exe(cc-rsfails with "failed to find tool lib.exe"). The Windows CI lane covers it.cargo clippy -p rocm: the only change inapps/rocmis a comment.cargo xtask e2eandscripts/smoke_local.py: left to CI.User-visible behaviour
None. This is a pure internal move with no change to any command output, exit code, file the CLI creates or engine selection, so no Gherkin scenario is added; the allowlist and argv-builder behaviour stays covered by the same unit tests, now in
mcp_argv.rs.Notes for reviewers
One commit. A good reading order is
docs/architecture.md,mcp_argv.rs, then the removal inmcp.rs. Agit diff --color-movedof the commit shows the bodies as moved blocks.Module edges:
mcp_argv.rshas nouse crate::imports at all (it uses onlyanyhow,rocm_core::DEFAULT_LOCAL_HOST,serde_json::Value, and callsrocm_coreandrocm_engine_protocolby path), so there is no cycle.mcp.rsgains the single edgecrate::mcp_argv; its existing edges (common,host_snapshot,persistence, andserviceby path) are unchanged.rocmdstill has no dependency onrocm.Open pull requests that touch the same files, read-only check:
build_launch_server_argsand adds tests inapps/rocmd/src/mcp.rs, so it will conflict with this move and needs its hunks re-applied inmcp_argv.rs(the test hunk goes inmcp_argv.rs'smod testsif it targets the argv builder).modline near the top ofapps/rocmd/src/lib.rs; the conflict is mechanical.docs/architecture.mdis touched by a large number of open pull requests; therocmdsection conflicts only with the ones that also edit themcp.rsor neighbouring entries (for example ROCMAI-859: split rocmd watchers.rs into a watchers/ directory #885, which splitswatchers.rs).apps/rocm/src/remote/mod.rsbut not the comment changed here.