ref(mcp): Separate tool, prompt and resource patches#6726
ref(mcp): Separate tool, prompt and resource patches#6726alexander-alderman-webb wants to merge 11 commits into
Conversation
Codecov Results 📊✅ 90045 passed | ⏭️ 6302 skipped | Total: 96347 | Pass Rate: 93.46% | Execution Time: 316m 18s 📊 Comparison with Base Branch
✨ No test changes detected All tests are passing successfully. ❌ Patch coverage is 68.29%. Project has 2478 uncovered lines. Files with missing lines (1)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 89.74% 89.64% -0.1%
==========================================
Files 192 192 —
Lines 23823 23911 +88
Branches 8226 8244 +18
==========================================
+ Hits 21378 21433 +55
- Misses 2445 2478 +33
- Partials 1349 1354 +5Generated by Codecov Action |
There was a problem hiding this comment.
handler_name may be unbound in _extract_handler_data_from_args for tool and prompt types
In _extract_handler_data_from_args (mcp.py ~line 423), if original_args is empty and original_kwargs.get("name") is falsy, handler_name is never assigned for handler_type == "tool" or "prompt", causing an UnboundLocalError when it is referenced at return handler_name, arguments (tool) or arguments = {"name": handler_name, ...} (prompt). Add an else: handler_name = "unknown" fallback in both branches.
Evidence
_extract_handler_data_from_argslines 422-446: bothtoolandpromptbranches assignhandler_nameonly underif original_args:orelif original_kwargs.get("name"):, with noelseclause.- For the prompt branch,
handler_nameis immediately used on the very next line:arguments = {"name": handler_name, **(arguments or {})}, so anUnboundLocalErroris raised beforereturn. - For the tool branch,
handler_nameis used in the sharedreturn handler_name, argumentsat line ~455. _prepare_handler_datareaches_extract_handler_data_from_argswhen bothparams is Noneand_is_v2_context(original_args)is False (e.g., emptyoriginal_argsin a v2 kwargs-only call).- The resource branch correctly initialises
handler_name = "unknown"before any conditional, confirming the fix pattern is known.
Identified by Warden find-bugs
There was a problem hiding this comment.
UnboundLocalError when tool/prompt handler called with no args and no kwargs name
In _extract_handler_data_from_args, handler_name is only assigned inside if original_args: / elif original_kwargs.get("name"): branches for the "tool" and "prompt" types; if both conditions are false, handler_name is never set. The prompt branch then immediately dereferences it at arguments = {"name": handler_name, ...}, raising UnboundLocalError at runtime.
Evidence
_extract_handler_data_from_args(mcp.py ~line 407) handles"tool"and"prompt"withif original_args: handler_name = .../elif original_kwargs.get("name"): handler_name = ...— noelseclause and no default value.- For
"prompt", line 446 unconditionally readshandler_nameinarguments = {"name": handler_name, **(arguments or {})}before the function returns. - For
"tool", the unbound name would surface atreturn handler_name, arguments. - The
"resource"branch correctly defaults tohandler_name = "unknown"first, so only tool and prompt are affected. _prepare_handler_datacalls this function on the non-v2 code path (line 486) without any guard against empty args.
Identified by Warden code-review
There was a problem hiding this comment.
UnboundLocalError when original_args is empty and original_kwargs has no 'name' key in _extract_handler_data_from_args
For handler_type == 'tool' and handler_type == 'prompt', handler_name is assigned only inside if/elif branches with no else fallback; if both conditions are falsy the variable is unbound and will raise UnboundLocalError — for 'prompt' the crash occurs immediately at arguments = {'name': handler_name, ...} inside the function.
Evidence
_extract_handler_data_from_args(mcp.py ~line 421):if original_args: handler_name = .../elif original_kwargs.get('name'): handler_name = ...— noelseclause for either the 'tool' or 'prompt' branch.- The 'resource' branch correctly initialises
handler_name = 'unknown'before the conditionals, showing the pattern is inconsistent. - For 'prompt',
handler_nameis dereferenced immediately within the same function atarguments = {'name': handler_name, ...}(line ~445), so an empty call with no positional args and no kwargs 'name' crashes before returning. _prepare_handler_datacalls this function via theelsebranch whenparams is Noneand_is_v2_contextis False, so v1 stdio callers with missing arguments hit this path.
Identified by Warden find-bugs
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 93ea189. Configure here.
| [options] | ||
| prerelease-mode = "allow" | ||
|
|
There was a problem hiding this comment.
this keeps changing when I commit, I think it's the pre-commit.

Description
Separate patches for tool, prompt and resource handlers.
This reduces conditionals and removes inappropriate generalization. Each handler type has different input and output types, and require different span attributes.
Issues
Reminders
uv run ruff.feat:,fix:,ref:,meta:)