Merge remote-tracking branch 'origin/feature/knowledge_lxc' into develop
This commit is contained in:
@@ -19,6 +19,8 @@ from . import (
|
|||||||
implicit_memory_controller,
|
implicit_memory_controller,
|
||||||
knowledge_controller,
|
knowledge_controller,
|
||||||
knowledgeshare_controller,
|
knowledgeshare_controller,
|
||||||
|
mcp_market_controller,
|
||||||
|
mcp_market_config_controller,
|
||||||
memory_agent_controller,
|
memory_agent_controller,
|
||||||
memory_dashboard_controller,
|
memory_dashboard_controller,
|
||||||
memory_episodic_controller,
|
memory_episodic_controller,
|
||||||
@@ -60,6 +62,8 @@ manager_router.include_router(model_controller.router)
|
|||||||
manager_router.include_router(file_controller.router)
|
manager_router.include_router(file_controller.router)
|
||||||
manager_router.include_router(document_controller.router)
|
manager_router.include_router(document_controller.router)
|
||||||
manager_router.include_router(knowledge_controller.router)
|
manager_router.include_router(knowledge_controller.router)
|
||||||
|
manager_router.include_router(mcp_market_controller.router)
|
||||||
|
manager_router.include_router(mcp_market_config_controller.router)
|
||||||
manager_router.include_router(chunk_controller.router)
|
manager_router.include_router(chunk_controller.router)
|
||||||
manager_router.include_router(test_controller.router)
|
manager_router.include_router(test_controller.router)
|
||||||
manager_router.include_router(knowledgeshare_controller.router)
|
manager_router.include_router(knowledgeshare_controller.router)
|
||||||
|
|||||||
336
api/app/controllers/mcp_market_config_controller.py
Normal file
336
api/app/controllers/mcp_market_config_controller.py
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
import requests
|
||||||
|
from sqlalchemy import or_
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from modelscope.hub.errors import raise_for_http_status
|
||||||
|
from modelscope.hub.mcp_api import MCPApi
|
||||||
|
|
||||||
|
from app.core.logging_config import get_api_logger
|
||||||
|
from app.core.response_utils import success, fail
|
||||||
|
from app.db import get_db
|
||||||
|
from app.dependencies import get_current_user
|
||||||
|
from app.models import mcp_market_config_model
|
||||||
|
from app.models.user_model import User
|
||||||
|
from app.schemas import mcp_market_config_schema
|
||||||
|
from app.schemas.response_schema import ApiResponse
|
||||||
|
from app.services import mcp_market_config_service
|
||||||
|
|
||||||
|
# Obtain a dedicated API logger
|
||||||
|
api_logger = get_api_logger()
|
||||||
|
|
||||||
|
router = APIRouter(
|
||||||
|
prefix="/mcp_market_configs",
|
||||||
|
tags=["mcp_market_configs"],
|
||||||
|
dependencies=[Depends(get_current_user)] # Apply auth to all routes in this controller
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/mcp_servers", response_model=ApiResponse)
|
||||||
|
async def get_mcp_servers(
|
||||||
|
mcp_market_config_id: uuid.UUID,
|
||||||
|
page: int = Query(1, gt=0), # Default: 1, which must be greater than 0
|
||||||
|
pagesize: int = Query(20, gt=0, le=100), # Default: 20 items per page, maximum: 100 items
|
||||||
|
keywords: Optional[str] = Query(None, description="Search keywords (Optional search query string,e.g. Chinese service name, English service name, author/owner username)"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Query the mcp servers list in pages
|
||||||
|
- Support keyword search for name,author,owner
|
||||||
|
- Return paging metadata + mcp server list
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Query mcp server list: tenant_id={current_user.tenant_id}, page={page}, pagesize={pagesize}, keywords={keywords}, username: {current_user.username}")
|
||||||
|
|
||||||
|
# 1. parameter validation
|
||||||
|
if page < 1 or pagesize < 1:
|
||||||
|
api_logger.warning(f"Error in paging parameters: page={page}, pagesize={pagesize}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="The paging parameter must be greater than 0"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Query mcp market config information from the database
|
||||||
|
api_logger.debug(f"Query mcp market config: {mcp_market_config_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_id(db,
|
||||||
|
mcp_market_config_id=mcp_market_config_id,
|
||||||
|
current_user=current_user)
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market config does not exist or access is denied: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or access is denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. Execute paged query
|
||||||
|
api = MCPApi()
|
||||||
|
token = db_mcp_market_config.token
|
||||||
|
api.login(token)
|
||||||
|
|
||||||
|
body = {
|
||||||
|
'filter': {},
|
||||||
|
'page_number': page,
|
||||||
|
'page_size': pagesize,
|
||||||
|
'search': keywords
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
cookies = api.get_cookies(token)
|
||||||
|
r = api.session.put(
|
||||||
|
url=api.mcp_base_url,
|
||||||
|
headers=api.builder_headers(api.headers),
|
||||||
|
json=body,
|
||||||
|
cookies=cookies)
|
||||||
|
raise_for_http_status(r)
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
api_logger.error(f"mFailed to get MCP servers: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Failed to get MCP servers: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
data = api._handle_response(r)
|
||||||
|
total = data.get('total_count', 0)
|
||||||
|
mcp_server_list = data.get('mcp_server_list', [])
|
||||||
|
# items = [{
|
||||||
|
# 'name': item.get('name', ''),
|
||||||
|
# 'id': item.get('id', ''),
|
||||||
|
# 'description': item.get('description', '')
|
||||||
|
# } for item in mcp_server_list]
|
||||||
|
|
||||||
|
# 4. Return structured response
|
||||||
|
result = {
|
||||||
|
"items": mcp_server_list,
|
||||||
|
"page": {
|
||||||
|
"page": page,
|
||||||
|
"pagesize": pagesize,
|
||||||
|
"total": total,
|
||||||
|
"has_next": True if page * pagesize < total else False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success(data=result, msg="Query of mcp servers list successful")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/mcp_server", response_model=ApiResponse)
|
||||||
|
async def get_mcp_server(
|
||||||
|
mcp_market_config_id: uuid.UUID,
|
||||||
|
server_id: str,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Get detailed information for a specific MCP Server
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Query mcp server: tenant_id={current_user.tenant_id}, mcp_market_config_id={mcp_market_config_id}, server_id={server_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
# 1. Query mcp market config information from the database
|
||||||
|
api_logger.debug(f"Query mcp market config: {mcp_market_config_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_id(db,
|
||||||
|
mcp_market_config_id=mcp_market_config_id,
|
||||||
|
current_user=current_user)
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market config does not exist or access is denied: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or access is denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Get detailed information for a specific MCP Server
|
||||||
|
api = MCPApi()
|
||||||
|
token = db_mcp_market_config.token
|
||||||
|
api.login(token)
|
||||||
|
|
||||||
|
result = api.get_mcp_server(server_id=server_id)
|
||||||
|
return success(data=result, msg="Query of mcp servers list successful")
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/mcp_market_config", response_model=ApiResponse)
|
||||||
|
async def create_mcp_market_config(
|
||||||
|
create_data: mcp_market_config_schema.McpMarketConfigCreate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
create mcp market config
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Request to create a mcp market config: mcp_market_id={create_data.mcp_market_id}, tenant_id={current_user.tenant_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
api_logger.debug(f"Start creating the mcp market config: {create_data.mcp_market_id}")
|
||||||
|
# 1. Check if the mcp market name already exists
|
||||||
|
db_mcp_market_config_exist = mcp_market_config_service.get_mcp_market_config_by_mcp_market_id(db, mcp_market_id=create_data.mcp_market_id, current_user=current_user)
|
||||||
|
if db_mcp_market_config_exist:
|
||||||
|
api_logger.warning(f"The mcp market id already exists: {create_data.mcp_market_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=f"The mcp market id already exists: {create_data.mcp_market_id}"
|
||||||
|
)
|
||||||
|
db_mcp_market_config = mcp_market_config_service.create_mcp_market_config(db=db, mcp_market_config=create_data, current_user=current_user)
|
||||||
|
api_logger.info(
|
||||||
|
f"The mcp market config has been successfully created: (ID: {db_mcp_market_config.id})")
|
||||||
|
return success(data=jsonable_encoder(mcp_market_config_schema.McpMarketConfig.model_validate(db_mcp_market_config)),
|
||||||
|
msg="The mcp market config has been successfully created")
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"The creation of the mcp market config failed: {create_data.mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{mcp_market_config_id}", response_model=ApiResponse)
|
||||||
|
async def get_mcp_market_config(
|
||||||
|
mcp_market_config_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Retrieve mcp market config information based on mcp_market_config_id
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Obtain details of the mcp market config: mcp_market_config_id={mcp_market_config_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Query mcp market config information from the database
|
||||||
|
api_logger.debug(f"Query mcp market config: {mcp_market_config_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_id(db, mcp_market_config_id=mcp_market_config_id, current_user=current_user)
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(f"The mcp market config does not exist or access is denied: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or access is denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
api_logger.info(f"mcp market config query successful: (ID: {db_mcp_market_config.id})")
|
||||||
|
return success(data=jsonable_encoder(mcp_market_config_schema.McpMarketConfig.model_validate(db_mcp_market_config)),
|
||||||
|
msg="Successfully obtained mcp market config information")
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"mcp market config query failed: mcp_market_config_id={mcp_market_config_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/mcp_market_id/{mcp_market_id}", response_model=ApiResponse)
|
||||||
|
async def get_mcp_market_config_by_mcp_market_id(
|
||||||
|
mcp_market_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Retrieve mcp market config information based on mcp_market_id
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Request to create a mcp market config: mcp_market_id={mcp_market_id}, tenant_id={current_user.tenant_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Query mcp market config information from the database
|
||||||
|
api_logger.debug(f"Query mcp market config: mcp_market_id={mcp_market_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_mcp_market_id(db, mcp_market_id=mcp_market_id, current_user=current_user)
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(f"The mcp market config does not exist or access is denied: mcp_market_id={mcp_market_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or access is denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
api_logger.info(f"mcp market config query successful: (ID: {db_mcp_market_config.id})")
|
||||||
|
return success(data=jsonable_encoder(mcp_market_config_schema.McpMarketConfig.model_validate(db_mcp_market_config)),
|
||||||
|
msg="Successfully obtained mcp market config information")
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"mcp market config query failed: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{mcp_market_config_id}", response_model=ApiResponse)
|
||||||
|
async def update_mcp_market_config(
|
||||||
|
mcp_market_config_id: uuid.UUID,
|
||||||
|
update_data: mcp_market_config_schema.McpMarketConfigUpdate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
# 1. Check if the mcp market config exists
|
||||||
|
api_logger.debug(f"Query the mcp market config to be updated: {mcp_market_config_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_id(db, mcp_market_config_id=mcp_market_config_id, current_user=current_user)
|
||||||
|
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market config does not exist or you do not have permission to access it: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or you do not have permission to access it"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Update fields (only update non-null fields)
|
||||||
|
api_logger.debug(f"Start updating the mcp market config fields: {mcp_market_config_id}")
|
||||||
|
update_dict = update_data.dict(exclude_unset=True)
|
||||||
|
updated_fields = []
|
||||||
|
for field, value in update_dict.items():
|
||||||
|
if hasattr(db_mcp_market_config, field):
|
||||||
|
old_value = getattr(db_mcp_market_config, field)
|
||||||
|
if old_value != value:
|
||||||
|
# update value
|
||||||
|
setattr(db_mcp_market_config, field, value)
|
||||||
|
updated_fields.append(f"{field}: {old_value} -> {value}")
|
||||||
|
|
||||||
|
if updated_fields:
|
||||||
|
api_logger.debug(f"updated fields: {', '.join(updated_fields)}")
|
||||||
|
|
||||||
|
# 3. Save to database
|
||||||
|
try:
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_mcp_market_config)
|
||||||
|
api_logger.info(f"The mcp market config has been successfully updated: (ID: {db_mcp_market_config.id})")
|
||||||
|
except Exception as e:
|
||||||
|
db.rollback()
|
||||||
|
api_logger.error(f"The mcp market config update failed: mcp_market_config_id={mcp_market_config_id} - {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"The mcp market config update failed: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. Return the updated mcp market config
|
||||||
|
return success(data=jsonable_encoder(mcp_market_config_schema.McpMarketConfig.model_validate(db_mcp_market_config)),
|
||||||
|
msg="The mcp market config information updated successfully")
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{mcp_market_config_id}", response_model=ApiResponse)
|
||||||
|
async def delete_mcp_market_config(
|
||||||
|
mcp_market_config_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
delete mcp market config
|
||||||
|
"""
|
||||||
|
api_logger.info(f"Request to delete mcp market config: mcp_market_config_id={mcp_market_config_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Check whether the mcp market config exists
|
||||||
|
api_logger.debug(f"Check whether the mcp market config exists: {mcp_market_config_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_service.get_mcp_market_config_by_id(db, mcp_market_config_id=mcp_market_config_id, current_user=current_user)
|
||||||
|
|
||||||
|
if not db_mcp_market_config:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market config does not exist or you do not have permission to access it: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market config does not exist or you do not have permission to access it"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Deleting mcp market config
|
||||||
|
mcp_market_config_service.delete_mcp_market_config_by_id(db, mcp_market_config_id=mcp_market_config_id, current_user=current_user)
|
||||||
|
api_logger.info(f"The mcp market config has been successfully deleted: (ID: {mcp_market_config_id})")
|
||||||
|
return success(msg="The mcp market config has been successfully deleted")
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"Failed to delete from the mcp market config: mcp_market_config_id={mcp_market_config_id} - {str(e)}")
|
||||||
|
raise
|
||||||
262
api/app/controllers/mcp_market_controller.py
Normal file
262
api/app/controllers/mcp_market_controller.py
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from sqlalchemy import or_
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.core.logging_config import get_api_logger
|
||||||
|
from app.core.response_utils import success, fail
|
||||||
|
from app.db import get_db
|
||||||
|
from app.dependencies import get_current_user
|
||||||
|
from app.models import mcp_market_model
|
||||||
|
from app.models.user_model import User
|
||||||
|
from app.schemas import mcp_market_schema
|
||||||
|
from app.schemas.response_schema import ApiResponse
|
||||||
|
from app.services import mcp_market_service
|
||||||
|
|
||||||
|
# Obtain a dedicated API logger
|
||||||
|
api_logger = get_api_logger()
|
||||||
|
|
||||||
|
router = APIRouter(
|
||||||
|
prefix="/mcp_markets",
|
||||||
|
tags=["mcp_markets"],
|
||||||
|
dependencies=[Depends(get_current_user)] # Apply auth to all routes in this controller
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/mcp_markets", response_model=ApiResponse)
|
||||||
|
async def get_mcp_markets(
|
||||||
|
page: int = Query(1, gt=0), # Default: 1, which must be greater than 0
|
||||||
|
pagesize: int = Query(20, gt=0, le=100), # Default: 20 items per page, maximum: 100 items
|
||||||
|
orderby: Optional[str] = Query(None, description="Sort fields, such as: category, created_at"),
|
||||||
|
desc: Optional[bool] = Query(False, description="Is it descending order"),
|
||||||
|
keywords: Optional[str] = Query(None, description="Search keywords (mcp_market base name)"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Query the mcp markets list in pages
|
||||||
|
- Support keyword search for name,description
|
||||||
|
- Support dynamic sorting
|
||||||
|
- Return paging metadata + mcp_market list
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Query mcp market list: tenant_id={current_user.tenant_id}, page={page}, pagesize={pagesize}, keywords={keywords}, username: {current_user.username}")
|
||||||
|
|
||||||
|
# 1. parameter validation
|
||||||
|
if page < 1 or pagesize < 1:
|
||||||
|
api_logger.warning(f"Error in paging parameters: page={page}, pagesize={pagesize}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="The paging parameter must be greater than 0"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Construct query conditions
|
||||||
|
filters = []
|
||||||
|
|
||||||
|
# Keyword search (fuzzy matching of mcp market name,description)
|
||||||
|
if keywords:
|
||||||
|
api_logger.debug(f"Add keyword search criteria: {keywords}")
|
||||||
|
filters.append(
|
||||||
|
or_(
|
||||||
|
mcp_market_model.McpMarket.name.ilike(f"%{keywords}%"),
|
||||||
|
mcp_market_model.McpMarket.description.ilike(f"%{keywords}%")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# 3. Execute paged query
|
||||||
|
try:
|
||||||
|
api_logger.debug("Start executing mcp market paging query")
|
||||||
|
total, items = mcp_market_service.get_mcp_markets_paginated(
|
||||||
|
db=db,
|
||||||
|
filters=filters,
|
||||||
|
page=page,
|
||||||
|
pagesize=pagesize,
|
||||||
|
orderby=orderby,
|
||||||
|
desc=desc,
|
||||||
|
current_user=current_user
|
||||||
|
)
|
||||||
|
api_logger.info(f"mcp market query successful: total={total}, returned={len(items)} records")
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"mcp market query failed: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Query failed: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. Return structured response
|
||||||
|
result = {
|
||||||
|
"items": items,
|
||||||
|
"page": {
|
||||||
|
"page": page,
|
||||||
|
"pagesize": pagesize,
|
||||||
|
"total": total,
|
||||||
|
"has_next": True if page * pagesize < total else False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success(data=jsonable_encoder(result), msg="Query of mcp market list successful")
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/mcp_market", response_model=ApiResponse)
|
||||||
|
async def create_mcp_market(
|
||||||
|
create_data: mcp_market_schema.McpMarketCreate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
create mcp market
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Request to create a mcp market: name={create_data.name}, tenant_id={current_user.tenant_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
api_logger.debug(f"Start creating the mcp market: {create_data.name}")
|
||||||
|
# 1. Check if the mcp market name already exists
|
||||||
|
db_mcp_market_exist = mcp_market_service.get_mcp_market_by_name(db, name=create_data.name, current_user=current_user)
|
||||||
|
if db_mcp_market_exist:
|
||||||
|
api_logger.warning(f"The mcp market name already exists: {create_data.name}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=f"The mcp market name already exists: {create_data.name}"
|
||||||
|
)
|
||||||
|
db_mcp_market = mcp_market_service.create_mcp_market(db=db, mcp_market=create_data, current_user=current_user)
|
||||||
|
api_logger.info(
|
||||||
|
f"The mcp market has been successfully created: {db_mcp_market.name} (ID: {db_mcp_market.id})")
|
||||||
|
return success(data=jsonable_encoder(mcp_market_schema.McpMarket.model_validate(db_mcp_market)),
|
||||||
|
msg="The mcp market has been successfully created")
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"The creation of the mcp market failed: {create_data.name} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/{mcp_market_id}", response_model=ApiResponse)
|
||||||
|
async def get_mcp_market(
|
||||||
|
mcp_market_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Retrieve mcp market information based on mcp_market_id
|
||||||
|
"""
|
||||||
|
api_logger.info(
|
||||||
|
f"Obtain details of the mcp market: mcp_market_id={mcp_market_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Query mcp market information from the database
|
||||||
|
api_logger.debug(f"Query mcp market: {mcp_market_id}")
|
||||||
|
db_mcp_market = mcp_market_service.get_mcp_market_by_id(db, mcp_market_id=mcp_market_id, current_user=current_user)
|
||||||
|
if not db_mcp_market:
|
||||||
|
api_logger.warning(f"The mcp market does not exist or access is denied: mcp_market_id={mcp_market_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market does not exist or access is denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
api_logger.info(f"mcp market query successful: {db_mcp_market.name} (ID: {db_mcp_market.id})")
|
||||||
|
return success(data=jsonable_encoder(mcp_market_schema.McpMarket.model_validate(db_mcp_market)),
|
||||||
|
msg="Successfully obtained mcp market information")
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"mcp market query failed: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{mcp_market_id}", response_model=ApiResponse)
|
||||||
|
async def update_mcp_market(
|
||||||
|
mcp_market_id: uuid.UUID,
|
||||||
|
update_data: mcp_market_schema.McpMarketUpdate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
# 1. Check if the mcp market exists
|
||||||
|
api_logger.debug(f"Query the mcp market to be updated: {mcp_market_id}")
|
||||||
|
db_mcp_market = mcp_market_service.get_mcp_market_by_id(db, mcp_market_id=mcp_market_id, current_user=current_user)
|
||||||
|
|
||||||
|
if not db_mcp_market:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market does not exist or you do not have permission to access it: mcp_market_id={mcp_market_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market does not exist or you do not have permission to access it"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. not updating the name (name already exists)
|
||||||
|
update_dict = update_data.dict(exclude_unset=True)
|
||||||
|
if "name" in update_dict:
|
||||||
|
name = update_dict["name"]
|
||||||
|
if name != db_mcp_market.name:
|
||||||
|
# Check if the mcp market name already exists
|
||||||
|
db_mcp_market_exist = mcp_market_service.get_mcp_market_by_name(db, name=name, current_user=current_user)
|
||||||
|
if db_mcp_market_exist:
|
||||||
|
api_logger.warning(f"The mcp market name already exists: {name}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=f"The mcp market name already exists: {name}"
|
||||||
|
)
|
||||||
|
# 3. Update fields (only update non-null fields)
|
||||||
|
api_logger.debug(f"Start updating the mcp market fields: {mcp_market_id}")
|
||||||
|
updated_fields = []
|
||||||
|
for field, value in update_dict.items():
|
||||||
|
if hasattr(db_mcp_market, field):
|
||||||
|
old_value = getattr(db_mcp_market, field)
|
||||||
|
if old_value != value:
|
||||||
|
# update value
|
||||||
|
setattr(db_mcp_market, field, value)
|
||||||
|
updated_fields.append(f"{field}: {old_value} -> {value}")
|
||||||
|
|
||||||
|
if updated_fields:
|
||||||
|
api_logger.debug(f"updated fields: {', '.join(updated_fields)}")
|
||||||
|
|
||||||
|
# 4. Save to database
|
||||||
|
try:
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_mcp_market)
|
||||||
|
api_logger.info(f"The mcp market has been successfully updated: {db_mcp_market.name} (ID: {db_mcp_market.id})")
|
||||||
|
except Exception as e:
|
||||||
|
db.rollback()
|
||||||
|
api_logger.error(f"The mcp market update failed: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"The mcp market update failed: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 5. Return the updated mcp market
|
||||||
|
return success(data=jsonable_encoder(mcp_market_schema.McpMarket.model_validate(db_mcp_market)),
|
||||||
|
msg="The mcp market information updated successfully")
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{mcp_market_id}", response_model=ApiResponse)
|
||||||
|
async def delete_mcp_market(
|
||||||
|
mcp_market_id: uuid.UUID,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
current_user: User = Depends(get_current_user)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
delete mcp market
|
||||||
|
"""
|
||||||
|
api_logger.info(f"Request to delete mcp market: mcp_market_id={mcp_market_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. Check whether the mcp market exists
|
||||||
|
api_logger.debug(f"Check whether the mcp market exists: {mcp_market_id}")
|
||||||
|
db_mcp_market = mcp_market_service.get_mcp_market_by_id(db, mcp_market_id=mcp_market_id, current_user=current_user)
|
||||||
|
|
||||||
|
if not db_mcp_market:
|
||||||
|
api_logger.warning(
|
||||||
|
f"The mcp market does not exist or you do not have permission to access it: mcp_market_id={mcp_market_id}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="The mcp market does not exist or you do not have permission to access it"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Deleting mcp market
|
||||||
|
mcp_market_service.delete_mcp_market_by_id(db, mcp_market_id=mcp_market_id, current_user=current_user)
|
||||||
|
api_logger.info(f"The mcp market has been successfully deleted: (ID: {mcp_market_id})")
|
||||||
|
return success(msg="The mcp market has been successfully deleted")
|
||||||
|
except Exception as e:
|
||||||
|
api_logger.error(f"Failed to delete from the mcp market: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
@@ -9,6 +9,8 @@ from .generic_file_model import GenericFile
|
|||||||
from .models_model import ModelConfig, ModelProvider, ModelType, ModelApiKey, ModelBase, LoadBalanceStrategy
|
from .models_model import ModelConfig, ModelProvider, ModelType, ModelApiKey, ModelBase, LoadBalanceStrategy
|
||||||
from .memory_short_model import ShortTermMemory, LongTermMemory
|
from .memory_short_model import ShortTermMemory, LongTermMemory
|
||||||
from .knowledgeshare_model import KnowledgeShare
|
from .knowledgeshare_model import KnowledgeShare
|
||||||
|
from .mcp_market_model import McpMarket
|
||||||
|
from .mcp_market_config_model import McpMarketConfig
|
||||||
from .app_model import App
|
from .app_model import App
|
||||||
from .agent_app_config_model import AgentConfig
|
from .agent_app_config_model import AgentConfig
|
||||||
from .app_release_model import AppRelease
|
from .app_release_model import AppRelease
|
||||||
@@ -50,6 +52,8 @@ __all__ = [
|
|||||||
"ModelType",
|
"ModelType",
|
||||||
"ModelApiKey",
|
"ModelApiKey",
|
||||||
"KnowledgeShare",
|
"KnowledgeShare",
|
||||||
|
"McpMarket",
|
||||||
|
"McpMarketConfig",
|
||||||
"App",
|
"App",
|
||||||
"AgentConfig",
|
"AgentConfig",
|
||||||
"AppRelease",
|
"AppRelease",
|
||||||
|
|||||||
16
api/app/models/mcp_market_config_model.py
Normal file
16
api/app/models/mcp_market_config_model.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import datetime
|
||||||
|
import uuid
|
||||||
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||||
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
from app.db import Base
|
||||||
|
|
||||||
|
class McpMarketConfig(Base):
|
||||||
|
__tablename__ = "mcp_market_configs"
|
||||||
|
|
||||||
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||||
|
mcp_market_id = Column(UUID(as_uuid=True), nullable=False, comment="mcp_markets.id")
|
||||||
|
token = Column(String, nullable=True, comment="mcp market token")
|
||||||
|
status = Column(Integer, default=0, comment="connect status(0: Not connected, 1: connected)")
|
||||||
|
tenant_id = Column(UUID(as_uuid=True), nullable=False, comment="tenant.id")
|
||||||
|
created_by = Column(UUID(as_uuid=True), nullable=False, comment="users.id")
|
||||||
|
created_at = Column(DateTime, default=datetime.datetime.now)
|
||||||
18
api/app/models/mcp_market_model.py
Normal file
18
api/app/models/mcp_market_model.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import datetime
|
||||||
|
import uuid
|
||||||
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||||
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
from app.db import Base
|
||||||
|
|
||||||
|
class McpMarket(Base):
|
||||||
|
__tablename__ = "mcp_markets"
|
||||||
|
|
||||||
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||||
|
name = Column(String, index=True, nullable=False, comment="mcp market name")
|
||||||
|
description = Column(String, index=True, nullable=True, comment="mcp market description")
|
||||||
|
logo_url = Column(String, index=True, nullable=True, comment="logo url")
|
||||||
|
mcp_count = Column(Integer, default=1, comment="mcp count")
|
||||||
|
url = Column(String, index=True, nullable=False, comment="mcp market url")
|
||||||
|
category = Column(String, index=True, nullable=False, comment="category")
|
||||||
|
created_by = Column(UUID(as_uuid=True), nullable=False, comment="users.id")
|
||||||
|
created_at = Column(DateTime, default=datetime.datetime.now)
|
||||||
72
api/app/repositories/mcp_market_config_repository.py
Normal file
72
api/app/repositories/mcp_market_config_repository.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import uuid
|
||||||
|
import datetime
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from app.models.mcp_market_config_model import McpMarketConfig
|
||||||
|
from app.schemas import mcp_market_config_schema
|
||||||
|
from app.core.logging_config import get_db_logger
|
||||||
|
|
||||||
|
# Obtain a dedicated logger for the database
|
||||||
|
db_logger = get_db_logger()
|
||||||
|
|
||||||
|
|
||||||
|
def create_mcp_market_config(db: Session, mcp_market_config: mcp_market_config_schema.McpMarketConfigCreate) -> McpMarketConfig:
|
||||||
|
db_logger.debug(f"Create a mcp market config record: mcp_market_id={mcp_market_config.mcp_market_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market_config = McpMarketConfig(**mcp_market_config.model_dump())
|
||||||
|
db.add(db_mcp_market_config)
|
||||||
|
db.commit()
|
||||||
|
db_logger.info(f"McpMarketConfig record created successfully: {mcp_market_config.mcp_market_id} (ID: {db_mcp_market_config.id})")
|
||||||
|
return db_mcp_market_config
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to create a mcp market config record: mcp_market_id={mcp_market_config.mcp_market_id} - {str(e)}")
|
||||||
|
db.rollback()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_config_by_id(db: Session, mcp_market_config_id: uuid.UUID) -> McpMarketConfig | None:
|
||||||
|
db_logger.debug(f"Query mcp market config based on ID: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market_config = db.query(McpMarketConfig).filter(McpMarketConfig.id == mcp_market_config_id).first()
|
||||||
|
if db_mcp_market_config:
|
||||||
|
db_logger.debug(f"McpMarketConfig query successful: (ID: {mcp_market_config_id})")
|
||||||
|
else:
|
||||||
|
db_logger.debug(f"McpMarketConfig does not exist: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
return db_mcp_market_config
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to query the mcp market config based on the ID: {mcp_market_config_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_config_by_mcp_market_id(db: Session, mcp_market_id: uuid.UUID, tenant_id: uuid.UUID) -> McpMarketConfig | None:
|
||||||
|
db_logger.debug(f"Query mcp market config based on mcp_market_id: {mcp_market_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market_config = db.query(McpMarketConfig).filter(McpMarketConfig.mcp_market_id == mcp_market_id, McpMarketConfig.tenant_id == tenant_id).first()
|
||||||
|
if db_mcp_market_config:
|
||||||
|
db_logger.debug(f"McpMarketConfig query successful: (mcp_market_id: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
db_logger.debug(f"McpMarketConfig does not exist: mcp_market_id={mcp_market_id}")
|
||||||
|
return db_mcp_market_config
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to query the mcp market config based on the mcp_market_id: {mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def delete_mcp_market_config_by_id(db: Session, mcp_market_config_id: uuid.UUID):
|
||||||
|
db_logger.debug(f"Delete McpMarketConfig record: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# First, query the mcp market config information for logging purposes
|
||||||
|
result = db.query(McpMarketConfig).filter(McpMarketConfig.id == mcp_market_config_id).delete()
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
if result > 0:
|
||||||
|
db_logger.info(f"McpMarketConfig record deleted successfully: (ID: {mcp_market_config_id})")
|
||||||
|
else:
|
||||||
|
db_logger.warning(f"The mcp market config record does not exist, and cannot be deleted: id={mcp_market_config_id}")
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to delete mcp market config record: id={mcp_market_config_id} - {str(e)}")
|
||||||
|
db.rollback()
|
||||||
|
raise
|
||||||
124
api/app/repositories/mcp_market_repository.py
Normal file
124
api/app/repositories/mcp_market_repository.py
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import uuid
|
||||||
|
import datetime
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from app.models.mcp_market_model import McpMarket
|
||||||
|
from app.schemas import mcp_market_schema
|
||||||
|
from app.core.logging_config import get_db_logger
|
||||||
|
|
||||||
|
# Obtain a dedicated logger for the database
|
||||||
|
db_logger = get_db_logger()
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_markets_paginated(
|
||||||
|
db: Session,
|
||||||
|
filters: list,
|
||||||
|
page: int,
|
||||||
|
pagesize: int,
|
||||||
|
orderby: str = None,
|
||||||
|
desc: bool = False
|
||||||
|
) -> tuple[int, list]:
|
||||||
|
"""
|
||||||
|
Paged query mcp market (with filtering and sorting)
|
||||||
|
"""
|
||||||
|
db_logger.debug(
|
||||||
|
f"Query mcp market in pages: page={page}, pagesize={pagesize}, orderby={orderby}, desc={desc}, filters_count={len(filters)}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
query = db.query(McpMarket)
|
||||||
|
|
||||||
|
# Apply filter conditions
|
||||||
|
for filter_cond in filters:
|
||||||
|
query = query.filter(filter_cond)
|
||||||
|
|
||||||
|
# Calculate the total count (for pagination)
|
||||||
|
total = query.count()
|
||||||
|
db_logger.debug(f"Total number of mcp_market queries: {total}")
|
||||||
|
|
||||||
|
# sort
|
||||||
|
if orderby:
|
||||||
|
order_attr = getattr(McpMarket, orderby, None)
|
||||||
|
if order_attr is not None:
|
||||||
|
if desc:
|
||||||
|
query = query.order_by(order_attr.desc())
|
||||||
|
else:
|
||||||
|
query = query.order_by(order_attr.asc())
|
||||||
|
db_logger.debug(f"sort: {orderby}, desc={desc}")
|
||||||
|
|
||||||
|
# pagination
|
||||||
|
items = query.offset((page - 1) * pagesize).limit(pagesize).all()
|
||||||
|
db_logger.info(
|
||||||
|
f"The mcp market paging query has been successful: total={total}, Number of current page={len(items)}")
|
||||||
|
|
||||||
|
return total, [mcp_market_schema.McpMarket.model_validate(item) for item in items]
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Querying mcp_market pagination failed: page={page}, pagesize={pagesize} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def create_mcp_market(db: Session, mcp_market: mcp_market_schema.McpMarketCreate) -> McpMarket:
|
||||||
|
db_logger.debug(f"Create a mcp market record: name={mcp_market.name}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market = McpMarket(**mcp_market.model_dump())
|
||||||
|
db.add(db_mcp_market)
|
||||||
|
db.commit()
|
||||||
|
db_logger.info(f"McpMarket record created successfully: {mcp_market.name} (ID: {db_mcp_market.id})")
|
||||||
|
return db_mcp_market
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to create a mcp market record: title={mcp_market.name} - {str(e)}")
|
||||||
|
db.rollback()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_by_id(db: Session, mcp_market_id: uuid.UUID) -> McpMarket | None:
|
||||||
|
db_logger.debug(f"Query mcp market based on ID: mcp_market_id={mcp_market_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market = db.query(McpMarket).filter(McpMarket.id == mcp_market_id).first()
|
||||||
|
if db_mcp_market:
|
||||||
|
db_logger.debug(f"McpMarket query successful: {db_mcp_market.name} (ID: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
db_logger.debug(f"McpMarket does not exist: mcp_market_id={mcp_market_id}")
|
||||||
|
return db_mcp_market
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to query the mcp market based on the ID: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_by_name(db: Session, name: str) -> McpMarket | None:
|
||||||
|
db_logger.debug(f"Query mcp market based on name: name={name}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market = db.query(McpMarket).filter(McpMarket.name == name).first()
|
||||||
|
if db_mcp_market:
|
||||||
|
db_logger.debug(f"mcp market query successful: {name} (ID: {db_mcp_market.id})")
|
||||||
|
else:
|
||||||
|
db_logger.debug(f"mcp market does not exist: name={name}")
|
||||||
|
return db_mcp_market
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to query the mcp market based on the name: {name} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def delete_mcp_market_by_id(db: Session, mcp_market_id: uuid.UUID):
|
||||||
|
db_logger.debug(f"Delete McpMarket record: mcp_market_id={mcp_market_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# First, query the mcp market information for logging purposes
|
||||||
|
db_mcp_market = db.query(McpMarket).filter(McpMarket.id == mcp_market_id).first()
|
||||||
|
if db_mcp_market:
|
||||||
|
name = db_mcp_market.name
|
||||||
|
else:
|
||||||
|
name = "unknown"
|
||||||
|
|
||||||
|
result = db.query(McpMarket).filter(McpMarket.id == mcp_market_id).delete()
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
if result > 0:
|
||||||
|
db_logger.info(f"McpMarket record deleted successfully: {name} (ID: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
db_logger.warning(f"The mcp market record does not exist, and cannot be deleted: mcp_market_id={mcp_market_id}")
|
||||||
|
except Exception as e:
|
||||||
|
db_logger.error(f"Failed to delete mcp market record: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
db.rollback()
|
||||||
|
raise
|
||||||
@@ -8,6 +8,8 @@ from .file_schema import File, FileCreate, FileUpdate
|
|||||||
from .tenant_schema import Tenant, TenantCreate, TenantUpdate
|
from .tenant_schema import Tenant, TenantCreate, TenantUpdate
|
||||||
from .chunk_schema import ChunkCreate, ChunkUpdate, ChunkRetrieve
|
from .chunk_schema import ChunkCreate, ChunkUpdate, ChunkRetrieve
|
||||||
from .knowledgeshare_schema import KnowledgeShare, KnowledgeShareCreate
|
from .knowledgeshare_schema import KnowledgeShare, KnowledgeShareCreate
|
||||||
|
from .mcp_market_schema import McpMarketCreate, McpMarketUpdate, McpMarket
|
||||||
|
from .mcp_market_config_schema import McpMarketConfigCreate, McpMarketConfigUpdate, McpMarketConfig
|
||||||
from .order_schema import CreateOrderRequest, OrderResponse, ExternalOrderResponse
|
from .order_schema import CreateOrderRequest, OrderResponse, ExternalOrderResponse
|
||||||
from .app_schema import (
|
from .app_schema import (
|
||||||
AppChatRequest,
|
AppChatRequest,
|
||||||
@@ -78,6 +80,12 @@ __all__ = [
|
|||||||
"ChunkRetrieve",
|
"ChunkRetrieve",
|
||||||
"KnowledgeShare",
|
"KnowledgeShare",
|
||||||
"KnowledgeShareCreate",
|
"KnowledgeShareCreate",
|
||||||
|
"McpMarketCreate",
|
||||||
|
"McpMarketUpdate",
|
||||||
|
"McpMarket",
|
||||||
|
"McpMarketConfigCreate",
|
||||||
|
"McpMarketConfigUpdate",
|
||||||
|
"McpMarketConfig",
|
||||||
"CreateOrderRequest",
|
"CreateOrderRequest",
|
||||||
"OrderResponse",
|
"OrderResponse",
|
||||||
"ExternalOrderResponse",
|
"ExternalOrderResponse",
|
||||||
|
|||||||
31
api/app/schemas/mcp_market_config_schema.py
Normal file
31
api/app/schemas/mcp_market_config_schema.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from pydantic import BaseModel, Field, field_serializer, ConfigDict
|
||||||
|
import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketConfigBase(BaseModel):
|
||||||
|
mcp_market_id: uuid.UUID
|
||||||
|
token: str | None = None
|
||||||
|
status: int | None = None
|
||||||
|
tenant_id: uuid.UUID | None = None
|
||||||
|
created_by: uuid.UUID | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketConfigCreate(McpMarketConfigBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketConfigUpdate(BaseModel):
|
||||||
|
token: str | None = None
|
||||||
|
status: int | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketConfig(McpMarketConfigBase):
|
||||||
|
id: uuid.UUID
|
||||||
|
created_at: datetime.datetime
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
@field_serializer("created_at", when_used="json")
|
||||||
|
def _serialize_created_at(self, dt: datetime.datetime):
|
||||||
|
return int(dt.timestamp() * 1000) if dt else None
|
||||||
37
api/app/schemas/mcp_market_schema.py
Normal file
37
api/app/schemas/mcp_market_schema.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from pydantic import BaseModel, Field, field_serializer, ConfigDict
|
||||||
|
import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketBase(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: str | None = None
|
||||||
|
logo_url: str | None = None
|
||||||
|
mcp_count: int
|
||||||
|
url: str
|
||||||
|
category: str
|
||||||
|
created_by: uuid.UUID | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketCreate(McpMarketBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarketUpdate(BaseModel):
|
||||||
|
name: str | None = Field(None)
|
||||||
|
description: str | None = Field(None)
|
||||||
|
logo_url: str | None = Field(None)
|
||||||
|
mcp_count: int | None = Field(None)
|
||||||
|
url: str | None = Field(None)
|
||||||
|
category: str | None = Field(None)
|
||||||
|
|
||||||
|
|
||||||
|
class McpMarket(McpMarketBase):
|
||||||
|
id: uuid.UUID
|
||||||
|
created_at: datetime.datetime
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
|
@field_serializer("created_at", when_used="json")
|
||||||
|
def _serialize_created_at(self, dt: datetime.datetime):
|
||||||
|
return int(dt.timestamp() * 1000) if dt else None
|
||||||
83
api/app/services/mcp_market_config_service.py
Normal file
83
api/app/services/mcp_market_config_service.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import uuid
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from app.models.user_model import User
|
||||||
|
from app.models.mcp_market_config_model import McpMarketConfig
|
||||||
|
from app.schemas.mcp_market_config_schema import McpMarketConfigCreate, McpMarketConfigUpdate
|
||||||
|
from app.repositories import mcp_market_config_repository
|
||||||
|
from app.core.logging_config import get_business_logger
|
||||||
|
|
||||||
|
# Obtain a dedicated logger for business logic
|
||||||
|
business_logger = get_business_logger()
|
||||||
|
|
||||||
|
|
||||||
|
def create_mcp_market_config(
|
||||||
|
db: Session, mcp_market_config: McpMarketConfigCreate, current_user: User
|
||||||
|
) -> McpMarketConfig:
|
||||||
|
business_logger.info(f"Create a mcp market config base: {mcp_market_config.mcp_market_id}, creator: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
mcp_market_config.tenant_id = current_user.tenant_id
|
||||||
|
mcp_market_config.created_by = current_user.id
|
||||||
|
business_logger.debug(f"Start creating the mcp market config on mcp_market_id: {mcp_market_config.mcp_market_id}")
|
||||||
|
db_mcp_market_config = mcp_market_config_repository.create_mcp_market_config(
|
||||||
|
db=db, mcp_market_config=mcp_market_config
|
||||||
|
)
|
||||||
|
business_logger.info(
|
||||||
|
f"The mcp market config has been successfully created: {mcp_market_config.mcp_market_id} (ID: {db_mcp_market_config.id}), creator: {current_user.username}")
|
||||||
|
return db_mcp_market_config
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Failed to create a mcp marke config: {mcp_market_config.mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_config_by_id(db: Session, mcp_market_config_id: uuid.UUID, current_user: User) -> McpMarketConfig | None:
|
||||||
|
business_logger.debug(
|
||||||
|
f"Query mcp market config based on ID: mcp_market_config_id={mcp_market_config_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
mcpMarketConfig = mcp_market_config_repository.get_mcp_market_config_by_id(db=db, mcp_market_config_id=mcp_market_config_id)
|
||||||
|
if mcpMarketConfig:
|
||||||
|
business_logger.info(f"mcp market config query successful: (ID: {mcp_market_config_id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"mcp market config does not exist: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
return mcpMarketConfig
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(
|
||||||
|
f"Failed to query the mcp market config based on the ID: {mcp_market_config_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_config_by_mcp_market_id(db: Session, mcp_market_id: uuid.UUID, current_user: User) -> McpMarketConfig | None:
|
||||||
|
business_logger.debug(
|
||||||
|
f"Query mcp market config based on mcp_market_id: {mcp_market_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
mcpMarketConfig = mcp_market_config_repository.get_mcp_market_config_by_mcp_market_id(db=db, mcp_market_id=mcp_market_id, tenant_id=current_user.tenant_id)
|
||||||
|
if mcpMarketConfig:
|
||||||
|
business_logger.info(f"mcp market config query successful: (mcp_market_id: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"mcp market config does not exist: mcp_market_id={mcp_market_id}")
|
||||||
|
return mcpMarketConfig
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(
|
||||||
|
f"Failed to query the mcp market config based on the mcp_market_id: {mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def delete_mcp_market_config_by_id(db: Session, mcp_market_config_id: uuid.UUID, current_user: User) -> None:
|
||||||
|
business_logger.info(f"Delete mcp market config: mcp_market_config_id={mcp_market_config_id}, operator: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# First, query the mcp market config information for logging purposes
|
||||||
|
mcpMarketConfig = mcp_market_config_repository.get_mcp_market_config_by_id(db=db, mcp_market_config_id=mcp_market_config_id)
|
||||||
|
if mcpMarketConfig:
|
||||||
|
business_logger.debug(f"Execute mcp market config deletion: (ID: {mcp_market_config_id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"The mcp market config to be deleted does not exist: mcp_market_config_id={mcp_market_config_id}")
|
||||||
|
|
||||||
|
mcp_market_config_repository.delete_mcp_market_config_by_id(db=db, mcp_market_config_id=mcp_market_config_id)
|
||||||
|
business_logger.info(
|
||||||
|
f"mcp market config record deleted successfully: mcp_market_config_id={mcp_market_config_id}, operator: {current_user.username}")
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Failed to delete mcp market config: mcp_market_config_id={mcp_market_config_id} - {str(e)}")
|
||||||
|
raise
|
||||||
109
api/app/services/mcp_market_service.py
Normal file
109
api/app/services/mcp_market_service.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import uuid
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from app.models.user_model import User
|
||||||
|
from app.models.mcp_market_model import McpMarket
|
||||||
|
from app.schemas.mcp_market_schema import McpMarketCreate, McpMarketUpdate
|
||||||
|
from app.repositories import mcp_market_repository
|
||||||
|
from app.core.logging_config import get_business_logger
|
||||||
|
|
||||||
|
# Obtain a dedicated logger for business logic
|
||||||
|
business_logger = get_business_logger()
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_markets_paginated(
|
||||||
|
db: Session,
|
||||||
|
current_user: User,
|
||||||
|
filters: list,
|
||||||
|
page: int,
|
||||||
|
pagesize: int,
|
||||||
|
orderby: str = None,
|
||||||
|
desc: bool = False
|
||||||
|
) -> tuple[int, list]:
|
||||||
|
business_logger.debug(
|
||||||
|
f"Query mcp market in pages: username={current_user.username}, page={page}, pagesize={pagesize}, orderby={orderby}, desc={desc}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
total, items = mcp_market_repository.get_mcp_markets_paginated(
|
||||||
|
db=db,
|
||||||
|
filters=filters,
|
||||||
|
page=page,
|
||||||
|
pagesize=pagesize,
|
||||||
|
orderby=orderby,
|
||||||
|
desc=desc
|
||||||
|
)
|
||||||
|
business_logger.info(
|
||||||
|
f"The mcp market paging query has been successful: username={current_user.username}, total={total}, Number of current page={len(items)}")
|
||||||
|
return total, items
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Querying mcp market pagination failed: username={current_user.username} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def create_mcp_market(
|
||||||
|
db: Session, mcp_market: McpMarketCreate, current_user: User
|
||||||
|
) -> McpMarket:
|
||||||
|
business_logger.info(f"Create a mcp market base: {mcp_market.name}, creator: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
mcp_market.created_by = current_user.id
|
||||||
|
business_logger.debug(f"Start creating the mcp market: {mcp_market.name}")
|
||||||
|
db_mcp_market = mcp_market_repository.create_mcp_market(
|
||||||
|
db=db, mcp_market=mcp_market
|
||||||
|
)
|
||||||
|
business_logger.info(
|
||||||
|
f"The mcp market has been successfully created: {mcp_market.name} (ID: {db_mcp_market.id}), creator: {current_user.username}")
|
||||||
|
return db_mcp_market
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Failed to create a mcp market: {mcp_market.name} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_by_id(db: Session, mcp_market_id: uuid.UUID, current_user: User) -> McpMarket | None:
|
||||||
|
business_logger.debug(
|
||||||
|
f"Query mcp market based on ID: mcp_market_id={mcp_market_id}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
mcpMarket = mcp_market_repository.get_mcp_market_by_id(db=db, mcp_market_id=mcp_market_id)
|
||||||
|
if mcpMarket:
|
||||||
|
business_logger.info(f"mcp market query successful: {mcpMarket.name} (ID: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"mcp market does not exist: mcp_market_id={mcp_market_id}")
|
||||||
|
return mcpMarket
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(
|
||||||
|
f"Failed to query the mcp market based on the ID: {mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_mcp_market_by_name(db: Session, name: str, current_user: User) -> McpMarket | None:
|
||||||
|
business_logger.debug(f"Query mcp market based on name: name={name}, username: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_mcp_market = mcp_market_repository.get_mcp_market_by_name(db=db, name=name)
|
||||||
|
if db_mcp_market:
|
||||||
|
business_logger.info(f"mcp market query successful: {name} (ID: {db_mcp_market.id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"mcp market does not exist: name={name}")
|
||||||
|
return db_mcp_market
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Failed to query the mcp market based on the name: name={name} - {str(e)}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def delete_mcp_market_by_id(db: Session, mcp_market_id: uuid.UUID, current_user: User) -> None:
|
||||||
|
business_logger.info(f"Delete mcp market: mcp_market_id={mcp_market_id}, operator: {current_user.username}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# First, query the mcp market information for logging purposes
|
||||||
|
mcpMarket = mcp_market_repository.get_mcp_market_by_id(db=db, mcp_market_id=mcp_market_id)
|
||||||
|
if mcpMarket:
|
||||||
|
business_logger.debug(f"Execute mcp market deletion: {mcpMarket.name} (ID: {mcp_market_id})")
|
||||||
|
else:
|
||||||
|
business_logger.warning(f"The mcp market to be deleted does not exist: mcp_market_id={mcp_market_id}")
|
||||||
|
|
||||||
|
mcp_market_repository.delete_mcp_market_by_id(db=db, mcp_market_id=mcp_market_id)
|
||||||
|
business_logger.info(
|
||||||
|
f"mcp market record deleted successfully: mcp_market_id={mcp_market_id}, operator: {current_user.username}")
|
||||||
|
except Exception as e:
|
||||||
|
business_logger.error(f"Failed to delete mcp market: mcp_market_id={mcp_market_id} - {str(e)}")
|
||||||
|
raise
|
||||||
@@ -144,6 +144,7 @@ dependencies = [
|
|||||||
"rdflib>=7.0.0",
|
"rdflib>=7.0.0",
|
||||||
"lxml>=4.9.0",
|
"lxml>=4.9.0",
|
||||||
"httpx>=0.28.0",
|
"httpx>=0.28.0",
|
||||||
|
"modelscope>=1.34.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
|
|||||||
@@ -137,3 +137,4 @@ boto3>=1.28.0
|
|||||||
aiofiles>=23.0.0
|
aiofiles>=23.0.0
|
||||||
lxml>=4.9.0
|
lxml>=4.9.0
|
||||||
httpx>=0.28.0
|
httpx>=0.28.0
|
||||||
|
modelscope>=1.34.0
|
||||||
|
|||||||
Reference in New Issue
Block a user