feat(mcp): self-healing tool execution with LLM argument correction#40
Merged
Conversation
New module mcp/retry.py with ToolRetryExecutor that wraps tool dispatch with a single retry on retryable errors (ValueError, LLMError, TimeoutError, ConnectionError). On failure, asks the LLM to diagnose and suggest corrected arguments via structured JSON. Security and auth errors (ProfileError, PathTraversalError) are never retried. Add MCPRetryConfig with enabled, max_retries, use_llm_correction, correction_model, timeout_seconds, and retryable_errors fields.
Accept optional retry_executor parameter in create_mcp_server(). When provided, tool dispatch routes through ToolRetryExecutor.execute() with a closure over all dependencies. When absent, dispatch is direct — preserving existing behavior for callers that don't configure retry.
19 tests across 4 classes: basic execution (3), retry logic (6), LLM correction (6), and should_retry classification (4). Covers success passthrough, retryable vs non-retryable error routing, LLM JSON parsing (valid/invalid/declined), exhausted error preservation, and disabled/missing client edge cases.
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.
Summary
Add self-healing tool execution to the MCP server, inspired by SivaRamSV/paaw's self-healing tool pattern. When an MCP tool fails with a retryable error, the system asks the LLM to diagnose the failure and suggest corrected arguments, then retries once. Security and auth errors are never retried.
How It Works
Error Classification
ProfileError,PathTraversalError,TypeError,KeyError,AttributeErrorValueError,LLMError,TimeoutError,ConnectionErrorLLM Correction
When a retryable error occurs, the executor sends a structured prompt to the fast model:
{"arguments": {...corrected...}}or{"corrected": false, "reason": "..."}Changes
New Files
src/vaultmind/mcp/retry.py(168 lines) —ToolRetryExecutorclass withexecute(),_should_retry(), and_correct_args()methods.ToolRetryExhaustedErrorexception preserving bothoriginal_errorandretry_error. Module-level_NON_RETRYABLE_TYPESfrozenset for hard-blocked error typestests/test_mcp_retry.py(313 lines) — 19 tests across 4 classesModified Files
src/vaultmind/config.py— AddedMCPRetryConfigclass withenabled,max_retries,use_llm_correction,correction_model,timeout_seconds,retryable_errorsfields. Addedmcp_retryfield toSettingsconfig/default.toml— Added[mcp_retry]section with all config entriessrc/vaultmind/mcp/server.py— Addedretry_executoroptional parameter tocreate_mcp_server(). When provided, tool dispatch routes throughToolRetryExecutor.execute()with a closure over all dependencies. When absent, dispatch is direct — preserving existing behaviorBackward Compatibility
retry_executordefaults toNoneincreate_mcp_server()— existing callers unaffectedMCPRetryConfig.enabledisFalse, executor is a passthrough (direct dispatch)use_llm_correctionisFalseor no LLM client provided, retryable errors still raise (no silent swallowing)ToolRetryExhaustedErrorinherits fromException, preserving standard error handling chainsTest plan
test_mcp_retry.pyacross 4 classes:ruff check— cleanmypy --ignore-missing-imports— clean