feat: add MCP server for artifact cleanup - #17
NotYash1066 wants to merge 1 commit into
Conversation
Expose irona over stdio MCP while reusing the existing scanner and deleter paths. Document PATH-based configuration so MCP clients can call irona portably instead of hardcoding a user-local binary. Constraint: MCP clients launch servers by command and args, so the binary must support a non-TUI stdio mode. Rejected: Separate irona-mcp crate | unnecessary split for two tools that reuse existing core behavior. Confidence: high Scope-risk: moderate Directive: Keep MCP cleanup destructive only through explicit clean_artifacts path arguments; do not make scan_artifacts delete anything. Tested: cargo test; pre-commit fmt and clippy hook; installed binary smoke-tested with initialize and tools/list; Codex MCP command verified after local config wiring. Not-tested: End-to-end startup from a freshly restarted Codex process.
kunjee17
left a comment
There was a problem hiding this comment.
Thanks for this — the MCP layer is well built. The JSON-RPC framing is correct, notifications properly get no response (message.get("id")? returning None is the right shape), the tool definitions carry real outputSchema and annotations rather than the bare minimum, and you kept it to a single new dependency with hand-rolled JSON, which fits how the rest of this codebase is written. 54 tests passing and clippy clean on my machine too.
Two things came up in review that I wanted to explain rather than just point at.
clean_artifacts will delete any path it is given
Caller-supplied strings go straight to remove_dir_all with nothing in between:
let path = PathBuf::from(path);
sizes.push(scanner::dir_size(&path));
original_paths.push(path.clone());
delete_inputs.push((index, path)); // no validationI tested it against the built binary rather than assuming. A plain directory with a text file in it and no marker file:
$ echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"clean_artifacts",
"arguments":{"paths":["/tmp/irona-notartifact/my-documents"]}}}' | irona --mcp
{"result":{"structuredContent":{"deleted_count":1,"total_freed_bytes":10, ...
Gone.
I read your note that cleanup is "destructive only through explicit clean_artifacts path arguments", and in a normal CLI that reasoning would hold — the caller typed the path. What makes this different is that the caller is a model. The argument is generated, not typed, so it can be wrong from a hallucination or from something the model read earlier in the session. destructiveHint: true helps, but it is advisory and clients are not obliged to confirm on it, so there is no backstop when they don't.
The fix is small: canonicalize each path and check it against the scanner's own detection before deleting.
The scanner refactor cost the TUI its streaming
Turning par_iter().for_each(|..| tx.send(..)) into par_iter().map(..).collect() means nothing is sent until the whole parallel phase finishes. dir_size is the slow part — it walks every file under each candidate — and the TUI used to fill in progressively while that ran. Now the list stays empty until the entire scan completes, which is very visible on a large workspace.
Both callers can be served by pulling phase 1 into a shared helper: scan keeps streaming, scan_artifacts collects.
Where this landed
I could not push to your fork branch from my environment, so rather than leave this waiting I opened #19, which carries your commit forward unchanged with one fix commit on top addressing both points, plus tests. Your authorship is preserved in the history. I'm closing this one in favour of that.
Genuinely nice work — the issues above are about the trust boundary an MCP tool sits on, not about the implementation. Two smaller things I left alone and noted on #19 as follow-ups: initialize echoes back whatever protocolVersion the client sends including unsupported ones, and scan_artifacts has no cap on result count, so scanning a large tree could return a lot of entries into a model's context.
…ard) (#19) * Enable AI clients to manage artifacts through MCP Expose irona over stdio MCP while reusing the existing scanner and deleter paths. Document PATH-based configuration so MCP clients can call irona portably instead of hardcoding a user-local binary. Constraint: MCP clients launch servers by command and args, so the binary must support a non-TUI stdio mode. Rejected: Separate irona-mcp crate | unnecessary split for two tools that reuse existing core behavior. Confidence: high Scope-risk: moderate Directive: Keep MCP cleanup destructive only through explicit clean_artifacts path arguments; do not make scan_artifacts delete anything. Tested: cargo test; pre-commit fmt and clippy hook; installed binary smoke-tested with initialize and tools/list; Codex MCP command verified after local config wiring. Not-tested: End-to-end startup from a freshly restarted Codex process. * fix: gate clean_artifacts on artifact detection, restore scan streaming clean_artifacts passed caller-supplied paths straight to remove_dir_all with no validation. Since the caller is a model, a hallucinated or injected path meant silent recursive deletion of arbitrary directories — verified against the built binary on a plain directory holding a text file. Every path is now canonicalized and checked with scanner::is_artifact, which accepts a directory only when a marker file sits beside it or a .gitignore rule matches it. One bad path fails the whole call. Splitting scan into scan_artifacts also cost the TUI its streaming: the parallel dir_size phase collected into a Vec before sending anything, so the list stayed empty until the whole scan finished. Phase 1 is now a shared collect_candidates helper, letting scan keep sending each entry as its size lands while scan_artifacts collects for MCP. Also reports isError when some deletions fail rather than always false. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Karthiya Yash Kiranbhai <160919026+NotYash1066@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Landed via #19 — your commit carried forward with a delete guard on |
Summary
irona --mcpstdio Model Context Protocol serverscan_artifactsandclean_artifactstools backed by the existing scanner/deleter logicPATHso configs can usecommand = "irona"instead of a local absolute binary pathCloses #16
Verification
cargo testpassed: 54 testsfmt,clippy,buildinitializeandtools/listscan_artifacts/clean_artifactswork end to endNotes
This intentionally keeps cleanup destructive only through explicit
clean_artifactspath arguments;scan_artifactsis read-only.