refactor(tools-mcp): structured JSON results + shell consolidation #91
No reviewers
Labels
No labels
bug
commercial
documentation
duplicate
enhancement
feature
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jasoncouture/llama-shears!91
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "tool-rework"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Convert every MCP tool to return a typed record (serialized to JSON by the SDK) instead of a free-form string. Each result implements
IToolResponse(string? Errorchannel) so callers can distinguish success/failure without parsing prose.IToolResponsecontract inLlamaShears.Core.Tools.ModelContextProtocol.file_read/file_list/file_write/file_append/file_delete/file_move/file_regex_replace/file_grepall return record results.file_read: dropped the 512 KiB hard-size check (response budget is the only gate now), raisedResponseBudgetlimits, addedcreatedAt/modifiedAt(DateTimeOffset, local time), removedNextStartLine(agent reported it as token-noise —endLine + 1is the resume cursor).memory_index/memory_search/memory_storereturn structured payloads.cron_cancel/list/trigger/edit/schedulereturn sharedCronJobSummary-bearing records.TodoListResult(state, itemCount, items[]).shell_sh+shell_bashinto a singleshell_run(bash-only); dual entry points added MCP surface for nothing on Fedora/Mac/Arch and were a footgun on Debian-family/bin/sh = dash.Test plan
dotnet buildcleandotnet test— 519 / 519 passing at every commit🤖 Generated with Claude Code
Pull request overview
This PR refactors the Model Context Protocol (MCP) tool surface so tools return structured, typed result records (serialized to JSON) implementing a shared
IToolResponseerror channel, and consolidates the shell tools into a single bash-based entry point.Changes:
IToolResponseand updates MCP tools to return typed record payloads with a sharedErrorfield instead of free-form strings.file_read’s previous hard file-size refusal.Reviewed changes
Copilot reviewed 48 out of 48 changed files in this pull request and generated 3 comments.
Show a summary per file
file_writeresult fields (Error,Written,BytesWritten,Overwritten).file_regex_replaceresults.file_readtests to assert on range fields, EOF behavior, and timestamps; updates truncation/resume testing.file_grepmatch objects and counts.file_deleteresult fields.file_appendresult fields.string? Error).TodoListResult(structured JSON) and centralizes state-to-error mapping.IToolResponse.shell_run(bash) and returnsShellRunResultstructured output.IToolResponse.MemoryStoreResultwithStored,RelativePath, andError.MemorySearchResultPayloadwith query echoing and hit list.IToolResponse.IToolResponse.IToolResponse.MemoryIndexResultinstead of formatted strings.file_writeto returnFileWriteResultand standardizes failure handling viaError.file_regex_replaceto returnFileRegexReplaceResultwith edited/replacement counts.file_readto returnFileReadResultwith range/timestamps/EOF flag and removes hard file-size cap.file_moveto returnFileMoveResultwith moved/overwritten flags and structured errors.file_listto returnFileListResultcontaining structured entries and truncation metadata.file_grepto returnGrepResultwith match objects and counts.IToolResponse.IToolResponse.IToolResponse.IToolResponse.IToolResponse.IToolResponse.IToolResponse.IToolResponse.cron_triggerto returnCronTriggerResultstructured output.cron_scheduleto returnCronScheduleResultincluding aCronJobSummary.cron_listto returnCronListResultwith structured job summaries.cron_editto returnCronEditResultwith edited flag and updated job summary.IToolResponse.IToolResponse.IToolResponse.IToolResponse.IToolResponse.cron_cancelto returnCronCancelResultstructured output.💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
@ -196,7 +204,6 @@ public sealed partial class GrepToolmatch = match.NextMatch();}This empty
catch (RegexMatchTimeoutException)silently swallows timeouts without any written justification or signal to the caller. ADR-0010 forbids swallowing exceptions unless the reasoning is explicitly documented in the catch block, and a grep timeout also changes observable results. Consider either returning a structured warning/error (e.g., anErrors/SkippedFilesfield) or at least adding anIgnored — …comment and logging so operators/users can tell matches may be incomplete.This catch block discards IO/authorization failures (
_ = ex;) without any written justification or reporting. Per ADR-0010, swallowing is forbidden unless the reasoning is articulated in the catch block, and silently skipping unreadable files can materially change grep results. Consider returning a structured warning/error (per-file or aggregated), logging at least at Debug/Information with the file path, or rethrowing and letting the caller handle failure.When a single line exceeds the response budget,
ReadRangeAsyncreturnsTruncated=truewithLinesReturned=0. In that case this response setsEndLine = requestedStartLine - 1, so the documented resume cursor (endLine + 1) does not advance and callers can get stuck in an infinite retry loop. Consider surfacing an explicit error for this condition and/or returning a resume cursor that guarantees forward progress (e.g., a dedicatedNextStartLine/ResumeStartLinefield, or a differentEndLinesentinel when truncated-with-zero-lines occurs).