Python: avoid duplicate MCP tools during reload#5962
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Prevents duplicate FunctionTool entries from being appended to MCPTool._functions when load_tools() runs concurrently (e.g., a manual call racing with a tools/list_changed notification-triggered reload). The fix recomputes the existing_names set after each list_tools page returns, so a concurrent reload that has already appended is observed before the second appender runs.
Changes:
- Moved the
existing_namessnapshot inside the pagination loop, afterawait self.session.list_tools(...)returns. - Added a regression test (
test_load_tools_concurrent_reload_does_not_duplicate_tools) that gates two concurrentload_tools()calls behind a sharedasyncio.Eventto force the race.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| python/packages/core/agent_framework/_mcp.py | Recompute existing_names after each list_tools response to observe entries appended by concurrent reloads. |
| python/packages/core/tests/core/test_mcp.py | Adds a regression test for concurrent load_tools() invocations. |
| self._tool_call_meta_by_name.clear() | ||
|
|
||
| params: types.PaginatedRequestParams | None = None |
| assert mock_session.list_tools.call_count == 2 | ||
| assert [f.name for f in tool._functions] == ["tool_1"] | ||
|
|
||
|
|
9dd232c to
38c4250
Compare
|
Updated to address the inline comments. The reload path now serializes function-list reloads and rebuilds tool-call metadata locally before swapping it in, so concurrent reloads cannot clear metadata another reload just populated. I also added coverage for concurrent paginated reloads preserving both tools and metadata. Local validation: targeted/full core MCP test file passed, ruff check/format, py_compile, pyright -P core, mypy -P core, and git diff --check. |
Summary
list_toolsrequest returnsFunctionToolobjectsload_tools()calls concurrentlyFixes #5911
To verify
uv run pytest tests\core\test_mcp.py -q -k "load_tools_concurrent_reload_does_not_duplicate_tools or load_tools_pagination_with_duplicates"uv run ruff check agent_framework\_mcp.py tests\core\test_mcp.pyuv run ruff format --check agent_framework\_mcp.py tests\core\test_mcp.pypython -m py_compile python\packages\core\agent_framework\_mcp.py python\packages\core\tests\core\test_mcp.py