12
12
from types import FrameType
13
13
from typing import TYPE_CHECKING , Any , Callable , ClassVar , Generic , cast , final , overload
14
14
15
+ from mcp import types as mcp_types
15
16
from opentelemetry .trace import NoOpTracer , use_span
16
17
from pydantic .json_schema import GenerateJsonSchema
17
18
from typing_extensions import Literal , Never , Self , TypeIs , TypeVar , deprecated
70
71
from fasta2a .broker import Broker
71
72
from fasta2a .schema import AgentProvider , Skill
72
73
from fasta2a .storage import Storage
73
- from mcp import types as mcp_types
74
74
from starlette .middleware import Middleware
75
75
from starlette .routing import BaseRoute , Route
76
76
from starlette .types import ExceptionHandler , Lifespan
@@ -1849,23 +1849,36 @@ async def elicitation_callback(context: Any, params: Any) -> Any:
1849
1849
1850
1850
return mcp_types .ElicitResult (action = 'accept' , content = {'result' : str (result )})
1851
1851
1852
- # Try MCP tools with name mapping
1853
- actual_tool_name = tool_name .replace ('_' , '-' )
1854
-
1852
+ # Find the MCP server that has this tool
1853
+ target_server = None
1855
1854
for toolset in self ._user_toolsets :
1856
1855
if not isinstance (toolset , MCPServer ):
1857
1856
continue
1858
- mcp_server = toolset
1859
- if 'mcp-run-python' in str (mcp_server ):
1857
+ if 'mcp-run-python' in str (toolset ):
1860
1858
continue
1861
1859
1860
+ # Check if this server has the tool
1862
1861
try :
1863
- result = await mcp_server .direct_call_tool (actual_tool_name , tool_arguments )
1864
- return mcp_types .ElicitResult (action = 'accept' , content = {'result' : str (result )})
1862
+ server_tools = await toolset .list_tools ()
1863
+ for tool_def in server_tools :
1864
+ if tool_def .name == tool_name :
1865
+ target_server = toolset
1866
+ break
1867
+ if target_server :
1868
+ break
1865
1869
except Exception :
1866
1870
continue
1867
1871
1868
- return mcp_types .ErrorData (code = mcp_types .INVALID_PARAMS , message = f'Tool { tool_name } not found' )
1872
+ if target_server :
1873
+ try :
1874
+ result = await target_server .direct_call_tool (tool_name , tool_arguments )
1875
+ return mcp_types .ElicitResult (action = 'accept' , content = {'result' : str (result )})
1876
+ except Exception as e :
1877
+ return mcp_types .ErrorData (
1878
+ code = mcp_types .INTERNAL_ERROR , message = f'Tool execution failed: { str (e )} '
1879
+ )
1880
+ else :
1881
+ return mcp_types .ErrorData (code = mcp_types .INVALID_PARAMS , message = f'Tool { tool_name } not found' )
1869
1882
1870
1883
except Exception as e :
1871
1884
return mcp_types .ErrorData (code = mcp_types .INTERNAL_ERROR , message = f'Tool execution failed: { str (e )} ' )
@@ -1883,30 +1896,37 @@ async def auto_inject_tools_callback(
1883
1896
) -> Any :
1884
1897
"""Auto-inject available tools into run_python_code calls."""
1885
1898
if tool_name == 'run_python_code' :
1886
- # Auto-inject available tools if not already provided
1887
- if 'tools' not in arguments or not arguments ['tools' ]:
1888
- available_tools : list [str ] = []
1889
-
1890
- # Add function tools
1891
- available_tools .extend (list (self ._function_toolset .tools .keys ()))
1892
-
1893
- for toolset in self ._user_toolsets :
1894
- if not isinstance (toolset , MCPServer ):
1895
- continue
1896
- mcp_server = toolset
1897
- if 'mcp-run-python' in str (mcp_server ):
1898
- continue
1899
-
1900
- try :
1901
- server_tools = await mcp_server .list_tools ()
1902
- for tool_def in server_tools :
1903
- python_name = tool_def .name .replace ('-' , '_' )
1904
- available_tools .append (python_name )
1905
- except Exception :
1906
- # Silently continue if we can't get tools from a server
1907
- pass
1908
-
1909
- arguments ['tools' ] = available_tools
1899
+ # Always auto-inject all available tools for Python code execution
1900
+ available_tools : list [str ] = []
1901
+ tool_name_mapping : dict [str , str ] = {}
1902
+
1903
+ # Add function tools
1904
+ function_tools = list (self ._function_toolset .tools .keys ())
1905
+ available_tools .extend (function_tools )
1906
+ for func_tool_name in function_tools :
1907
+ tool_name_mapping [func_tool_name ] = func_tool_name
1908
+
1909
+ # Add MCP server tools with proper name conversion
1910
+ for toolset in self ._user_toolsets :
1911
+ if not isinstance (toolset , MCPServer ):
1912
+ continue
1913
+ if 'mcp-run-python' in str (toolset ):
1914
+ continue
1915
+
1916
+ try :
1917
+ server_tools = await toolset .list_tools ()
1918
+ for tool_def in server_tools :
1919
+ original_name = tool_def .name
1920
+ python_name = original_name .replace ('-' , '_' )
1921
+ available_tools .append (python_name )
1922
+ tool_name_mapping [python_name ] = original_name
1923
+ except Exception :
1924
+ # Silently continue if we can't get tools from a server
1925
+ pass
1926
+
1927
+ # Always provide all available tools and mapping
1928
+ arguments ['tools' ] = available_tools
1929
+ arguments ['tool_name_mapping' ] = tool_name_mapping
1910
1930
1911
1931
# Continue with normal processing
1912
1932
return await call_tool_func (tool_name , arguments , None )
@@ -1937,17 +1957,16 @@ async def run_mcp_servers(
1937
1957
1938
1958
for toolset in self ._user_toolsets :
1939
1959
if isinstance (toolset , MCPServer ):
1940
- mcp_server = toolset
1941
1960
if (
1942
- hasattr (mcp_server , 'allow_elicitation' )
1943
- and mcp_server .allow_elicitation
1944
- and mcp_server .elicitation_callback is None
1961
+ hasattr (toolset , 'allow_elicitation' )
1962
+ and toolset .allow_elicitation
1963
+ and toolset .elicitation_callback is None
1945
1964
):
1946
- mcp_server .elicitation_callback = self ._create_elicitation_callback ()
1965
+ toolset .elicitation_callback = self ._create_elicitation_callback ()
1947
1966
1948
1967
# Also setup auto-tool-injection for run_python_code if not already set
1949
- if mcp_server .process_tool_call is None :
1950
- mcp_server .process_tool_call = self ._create_auto_tool_injection_callback ()
1968
+ if toolset .process_tool_call is None :
1969
+ toolset .process_tool_call = self ._create_auto_tool_injection_callback ()
1951
1970
1952
1971
async with self :
1953
1972
yield
0 commit comments