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

This commit is contained in:
Novice 2025-10-27 14:54:11 +08:00
commit b5e23b84ce
No known key found for this signature in database
GPG Key ID: EE3F68E3105DAAAB
5 changed files with 44 additions and 16 deletions

View File

@ -1073,7 +1073,8 @@ class ToolMCPListAllApi(Resource):
with Session(db.engine) as session, session.begin(): with Session(db.engine) as session, session.begin():
service = MCPToolManageService(session=session) service = MCPToolManageService(session=session)
tools = service.list_providers(tenant_id=tenant_id) # Skip sensitive data decryption for list view to improve performance
tools = service.list_providers(tenant_id=tenant_id, include_sensitive=False)
return [tool.to_dict() for tool in tools] return [tool.to_dict() for tool in tools]

View File

@ -150,8 +150,13 @@ class MCPProviderEntity(BaseModel):
# If not JSON, assume it's a file path # If not JSON, assume it's a file path
return file_helpers.get_signed_file_url(self.icon) return file_helpers.get_signed_file_url(self.icon)
def to_api_response(self, user_name: str | None = None) -> dict[str, Any]: def to_api_response(self, user_name: str | None = None, include_sensitive: bool = True) -> dict[str, Any]:
"""Convert to API response format""" """Convert to API response format
Args:
user_name: User name to display
include_sensitive: If False, skip expensive decryption operations (for list view optimization)
"""
response = { response = {
"id": self.id, "id": self.id,
"author": user_name or "Anonymous", "author": user_name or "Anonymous",
@ -172,14 +177,20 @@ class MCPProviderEntity(BaseModel):
"sse_read_timeout": str(self.sse_read_timeout), "sse_read_timeout": str(self.sse_read_timeout),
} }
# Add masked headers # Skip expensive operations when sensitive data is not needed (e.g., list view)
response["masked_headers"] = self.masked_headers() if not include_sensitive:
response["masked_headers"] = {}
response["is_dynamic_registration"] = True
else:
# Add masked headers
response["masked_headers"] = self.masked_headers()
# Add authentication info if available
masked_creds = self.masked_credentials()
if masked_creds:
response["authentication"] = masked_creds
response["is_dynamic_registration"] = self.credentials.get("is_dynamic_registration", True)
# Add authentication info if available
masked_creds = self.masked_credentials()
if masked_creds:
response["authentication"] = masked_creds
response["is_dynamic_registration"] = self.credentials.get("is_dynamic_registration", True)
return response return response
def retrieve_client_information(self) -> OAuthClientInformation | None: def retrieve_client_information(self) -> OAuthClientInformation | None:

View File

@ -726,7 +726,9 @@ class ToolManager:
if "mcp" in filters: if "mcp" in filters:
with Session(db.engine) as session: with Session(db.engine) as session:
mcp_service = MCPToolManageService(session=session) mcp_service = MCPToolManageService(session=session)
mcp_providers = mcp_service.list_providers(tenant_id=tenant_id, for_list=True) mcp_providers = mcp_service.list_providers(
tenant_id=tenant_id, for_list=True, include_sensitive=False
)
for mcp_provider in mcp_providers: for mcp_provider in mcp_providers:
result_providers[f"mcp_provider.{mcp_provider.name}"] = mcp_provider result_providers[f"mcp_provider.{mcp_provider.name}"] = mcp_provider

View File

@ -252,8 +252,16 @@ class MCPToolManageService:
mcp_tool = self.get_provider(provider_id=provider_id, tenant_id=tenant_id) mcp_tool = self.get_provider(provider_id=provider_id, tenant_id=tenant_id)
self._session.delete(mcp_tool) self._session.delete(mcp_tool)
def list_providers(self, *, tenant_id: str, for_list: bool = False) -> list[ToolProviderApiEntity]: def list_providers(
"""List all MCP providers for a tenant.""" self, *, tenant_id: str, for_list: bool = False, include_sensitive: bool = True
) -> list[ToolProviderApiEntity]:
"""List all MCP providers for a tenant.
Args:
tenant_id: Tenant ID
for_list: If True, return provider ID; if False, return server identifier
include_sensitive: If False, skip expensive decryption operations (default: True for backward compatibility)
"""
from models.account import Account from models.account import Account
stmt = select(MCPToolProvider).where(MCPToolProvider.tenant_id == tenant_id).order_by(MCPToolProvider.name) stmt = select(MCPToolProvider).where(MCPToolProvider.tenant_id == tenant_id).order_by(MCPToolProvider.name)
@ -269,7 +277,10 @@ class MCPToolManageService:
return [ return [
ToolTransformService.mcp_provider_to_user_provider( ToolTransformService.mcp_provider_to_user_provider(
provider, for_list=for_list, user_name=user_name_map.get(provider.user_id) provider,
for_list=for_list,
user_name=user_name_map.get(provider.user_id),
include_sensitive=include_sensitive,
) )
for provider in mcp_providers for provider in mcp_providers
] ]

View File

@ -234,7 +234,10 @@ class ToolTransformService:
@staticmethod @staticmethod
def mcp_provider_to_user_provider( def mcp_provider_to_user_provider(
db_provider: MCPToolProvider, for_list: bool = False, user_name: str | None = None db_provider: MCPToolProvider,
for_list: bool = False,
user_name: str | None = None,
include_sensitive: bool = True,
) -> ToolProviderApiEntity: ) -> ToolProviderApiEntity:
# Use provided user_name to avoid N+1 query, fallback to load_user() if not provided # Use provided user_name to avoid N+1 query, fallback to load_user() if not provided
if user_name is None: if user_name is None:
@ -244,7 +247,7 @@ class ToolTransformService:
# Convert to entity and use its API response method # Convert to entity and use its API response method
provider_entity = db_provider.to_entity() provider_entity = db_provider.to_entity()
response = provider_entity.to_api_response(user_name=user_name) response = provider_entity.to_api_response(user_name=user_name, include_sensitive=include_sensitive)
# Add additional fields specific to the transform # Add additional fields specific to the transform
response["id"] = db_provider.server_identifier if not for_list else db_provider.id response["id"] = db_provider.server_identifier if not for_list else db_provider.id