Skip to content

Commit a838885

Browse files
authored
Merge pull request #1272 from BudEcosystem/fix/tool_name_prefix
fix(budprompt): resolve RenamedToolset error in response formatters
2 parents 5fb1dec + a3539b0 commit a838885

File tree

3 files changed

+56
-27
lines changed

3 files changed

+56
-27
lines changed

services/budprompt/budprompt/executors/v4/openai_response_formatter.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ def _format_tools(self, tools: Optional[List[MCPToolConfig]]) -> List[Tool]:
579579
formatted_tools.append(
580580
Mcp(
581581
type="mcp",
582-
server_label=tool_config.server_label,
582+
server_label=tool_config.server_label or "unknown",
583583
server_url=tool_config.server_url,
584584
allowed_tools=list(tool_config.allowed_tools) if tool_config.allowed_tools else None,
585585
headers=None,
@@ -607,15 +607,12 @@ async def _fetch_mcp_tool_lists(self, tools: Optional[List[MCPToolConfig]]) -> L
607607

608608
for tool_config in tools:
609609
if tool_config.type == "mcp":
610-
# Load the MCP server
611-
mcp_server = await loader.load_tools(tool_config)
612-
if not mcp_server:
610+
# Fetch tool list directly from server (get_tool_list is self-contained)
611+
tool_list_data = await loader.get_tool_list(tool_config)
612+
if not tool_list_data:
613613
continue
614614

615-
# Fetch tool list from server
616-
tool_list_data = await loader.get_tool_list(mcp_server, tool_config.server_label or "unknown")
617-
618-
if tool_list_data:
615+
if tool_list_data.get("tools"):
619616
# Parse tools from MCP response
620617
tools_list: List[McpListToolsTool] = []
621618
for tool_info in tool_list_data.get("tools", []):

services/budprompt/budprompt/executors/v4/openai_streaming_formatter.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,14 +289,8 @@ async def emit_mcp_tool_list_events(self) -> List[ResponseStreamEvent]:
289289
continue
290290

291291
try:
292-
# Load MCP server
293-
mcp_server = await loader.load_tools(tool_config)
294-
if not mcp_server:
295-
logger.warning(f"Failed to load MCP server: {tool_config.server_label}")
296-
continue
297-
298-
# Fetch tool list
299-
tool_list_data = await loader.get_tool_list(mcp_server, tool_config.server_label or "unknown")
292+
# Fetch tool list directly (get_tool_list is self-contained)
293+
tool_list_data = await loader.get_tool_list(tool_config)
300294
if not tool_list_data:
301295
logger.warning(f"No tool list data from MCP server: {tool_config.server_label}")
302296
continue

services/budprompt/budprompt/executors/v4/tool_loaders.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ async def load_tools(self, tool_config: MCPToolConfig) -> Optional[Any]:
8989
gateway_slugs = self._get_gateway_slugs(tool_config)
9090

9191
if gateway_slugs:
92-
# Fetch tool list to get original names
93-
tool_list = await self.get_tool_list(mcp_server, tool_config.server_label or "unknown")
94-
if tool_list and tool_list.get("tools"):
95-
original_names = [tool.name for tool in tool_list["tools"]]
92+
# Fetch tool list to get original names directly from mcp_server
93+
# (not via get_tool_list() which strips prefixes)
94+
tools_list = await mcp_server.list_tools()
95+
if tools_list:
96+
original_names = [tool.name for tool in tools_list]
9697

9798
# Generate mapping: short_name -> original_name
9899
# Try each slug to find matching prefix
@@ -109,7 +110,7 @@ async def load_tools(self, tool_config: MCPToolConfig) -> Optional[Any]:
109110
# Update allowed_tool_names with SHORT names
110111
tool_config.allowed_tool_names = list(name_map.keys())
111112

112-
logger.info(
113+
logger.debug(
113114
f"Stripped gateway prefixes from {len(name_map)} tools "
114115
f"for server '{tool_config.server_label}' using {len(gateway_slugs)} slug(s)"
115116
)
@@ -145,23 +146,60 @@ def _get_gateway_slugs(self, tool_config: MCPToolConfig) -> List[str]:
145146
return list(tool_config.gateway_slugs.values())
146147
return []
147148

148-
async def get_tool_list(self, mcp_server: MCPServerStreamableHTTP, server_label: str) -> Optional[Dict]:
149+
async def get_tool_list(self, tool_config: MCPToolConfig) -> Optional[Dict]:
149150
"""Fetch the list of available tools from an MCP server.
150151
152+
Creates its own MCP connection and strips gateway slugs from tool names.
153+
This is a self-contained method that can be called independently of load_tools().
154+
151155
Args:
152-
mcp_server: The MCP server instance
153-
server_label: Label for the server (for logging)
156+
tool_config: MCP tool configuration
154157
155158
Returns:
156-
Dictionary with tools list or None on error
159+
Dictionary with tools list (renamed if gateway_slugs present) or None on error
157160
"""
161+
server_label = tool_config.server_label or "unknown"
162+
163+
if not tool_config.server_url:
164+
logger.warning(f"Skipping MCP tool list '{server_label}': server_url is missing")
165+
return {"server_label": server_label, "tools": [], "error": "server_url is missing"}
166+
158167
try:
159-
# Use the MCP server's list_tools method
160-
# This is provided by pydantic-ai's MCPServerStreamableHTTP
168+
# Create fresh MCP server connection
169+
mcp_url = f"{self.base_url}servers/{tool_config.server_url}/mcp"
170+
headers = {}
171+
if self.api_key:
172+
headers["Authorization"] = f"Bearer {self.api_key}"
173+
174+
mcp_server = MCPServerStreamableHTTP(url=mcp_url, headers=headers if headers else None)
175+
176+
# Fetch tool list
161177
tools_list = await mcp_server.list_tools()
162178

163179
logger.debug(f"Retrieved {len(tools_list)} tools from MCP server '{server_label}'")
164180

181+
# Get gateway slugs for name stripping
182+
gateway_slugs = self._get_gateway_slugs(tool_config)
183+
184+
if gateway_slugs:
185+
# Strip gateway slugs from tool names
186+
# Create new Tool objects with renamed names
187+
renamed_tools = []
188+
for tool in tools_list:
189+
short_name = tool.name
190+
for slug in gateway_slugs:
191+
prefix = f"{slug}-"
192+
if tool.name.startswith(prefix):
193+
short_name = tool.name[len(prefix) :]
194+
break
195+
196+
# Create a modified copy with the short name
197+
renamed_tool = tool.model_copy(update={"name": short_name})
198+
renamed_tools.append(renamed_tool)
199+
200+
logger.debug(f"Stripped gateway prefixes from {len(renamed_tools)} tools for '{server_label}'")
201+
return {"server_label": server_label, "tools": renamed_tools, "error": None}
202+
165203
return {"server_label": server_label, "tools": tools_list, "error": None}
166204

167205
except Exception as e:

0 commit comments

Comments
 (0)