Merge branch 'feat/mcp-06-18' into deploy/dev

This commit is contained in:
Novice 2025-10-27 14:36:01 +08:00
commit b407cf0189
No known key found for this signature in database
GPG Key ID: EE3F68E3105DAAAB
2 changed files with 32 additions and 8 deletions

View File

@ -254,11 +254,23 @@ class MCPToolManageService:
def list_providers(self, *, tenant_id: str, for_list: bool = False) -> list[ToolProviderApiEntity]:
"""List all MCP providers for a tenant."""
from models.account import Account
stmt = select(MCPToolProvider).where(MCPToolProvider.tenant_id == tenant_id).order_by(MCPToolProvider.name)
mcp_providers = self._session.scalars(stmt).all()
if not mcp_providers:
return []
# Batch query all users to avoid N+1 problem
user_ids = {provider.user_id for provider in mcp_providers}
users = self._session.query(Account).where(Account.id.in_(user_ids)).all()
user_name_map = {user.id: user.name for user in users}
return [
ToolTransformService.mcp_provider_to_user_provider(provider, for_list=for_list)
ToolTransformService.mcp_provider_to_user_provider(
provider, for_list=for_list, user_name=user_name_map.get(provider.user_id)
)
for provider in mcp_providers
]

View File

@ -233,17 +233,23 @@ class ToolTransformService:
)
@staticmethod
def mcp_provider_to_user_provider(db_provider: MCPToolProvider, for_list: bool = False) -> ToolProviderApiEntity:
def mcp_provider_to_user_provider(
db_provider: MCPToolProvider, for_list: bool = False, user_name: str | None = None
) -> ToolProviderApiEntity:
# Use provided user_name to avoid N+1 query, fallback to load_user() if not provided
if user_name is None:
user = db_provider.load_user()
user_name = user.name if user else None
# Convert to entity and use its API response method
provider_entity = db_provider.to_entity()
user = db_provider.load_user()
response = provider_entity.to_api_response(user_name=user.name if user else None)
response = provider_entity.to_api_response(user_name=user_name)
# Add additional fields specific to the transform
response["id"] = db_provider.server_identifier if not for_list else db_provider.id
response["tools"] = ToolTransformService.mcp_tool_to_user_tool(
db_provider, [MCPTool(**tool) for tool in json.loads(db_provider.tools)]
db_provider, [MCPTool(**tool) for tool in json.loads(db_provider.tools)], user_name=user_name
)
response["server_identifier"] = db_provider.server_identifier
@ -257,11 +263,17 @@ class ToolTransformService:
return ToolProviderApiEntity(**response)
@staticmethod
def mcp_tool_to_user_tool(mcp_provider: MCPToolProvider, tools: list[MCPTool]) -> list[ToolApiEntity]:
user = mcp_provider.load_user()
def mcp_tool_to_user_tool(
mcp_provider: MCPToolProvider, tools: list[MCPTool], user_name: str | None = None
) -> list[ToolApiEntity]:
# Use provided user_name to avoid N+1 query, fallback to load_user() if not provided
if user_name is None:
user = mcp_provider.load_user()
user_name = user.name if user else "Anonymous"
return [
ToolApiEntity(
author=user.name if user else "Anonymous",
author=user_name or "Anonymous",
name=tool.name,
label=I18nObject(en_US=tool.name, zh_Hans=tool.name),
description=I18nObject(en_US=tool.description or "", zh_Hans=tool.description or ""),