Merge remote-tracking branch 'origin/feature/knowledge_lxc' into develop

This commit is contained in:
lixiangcheng1
2026-02-25 10:31:34 +08:00
15 changed files with 1106 additions and 0 deletions

View File

@@ -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)

View 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

View 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

View File

@@ -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",

View 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)

View 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)

View 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

View 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

View File

@@ -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",

View 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

View 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

View 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

View 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

View File

@@ -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]

View File

@@ -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