From 64935841e010288acdca3d8a1e221e3a1c4e3d51 Mon Sep 17 00:00:00 2001 From: z30057876 Date: Sat, 26 Jul 2025 11:21:47 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=BA=93=E7=89=88?= =?UTF-8?q?=E6=9C=AC=EF=BC=9B=E6=9B=B4=E6=96=B0MCP=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/oidc.py | 4 +- apps/models/mcp.py | 27 +++++++---- apps/models/user.py | 7 ++- apps/models/vectors.py | 59 ++++++++++++++++++++---- apps/routers/conversation.py | 3 +- apps/scheduler/mcp/host.py | 23 +++++----- apps/scheduler/mcp/select.py | 8 ++-- apps/scheduler/pool/loader/app.py | 1 - apps/scheduler/pool/loader/call.py | 5 -- apps/scheduler/pool/loader/mcp.py | 66 +++++++++++++++------------ apps/scheduler/pool/loader/service.py | 5 +- apps/scheduler/pool/mcp/default.py | 9 ++-- apps/scheduler/pool/mcp/pool.py | 4 +- apps/schemas/mcp.py | 42 +---------------- 14 files changed, 135 insertions(+), 128 deletions(-) diff --git a/apps/common/oidc.py b/apps/common/oidc.py index fba8e216..b5e2bb62 100644 --- a/apps/common/oidc.py +++ b/apps/common/oidc.py @@ -34,13 +34,13 @@ class OIDCProvider: async def set_token(user_sub: str, access_token: str, refresh_token: str) -> None: """设置MongoDB中的OIDC Token到sessions集合""" async with postgres.session() as session: - session.add(Session( + await session.merge(Session( userSub=user_sub, sessionType=SessionType.ACCESS_TOKEN, token=access_token, validUntil=datetime.now(UTC) + timedelta(minutes=OIDC_ACCESS_TOKEN_EXPIRE_TIME), )) - session.add(Session( + await session.merge(Session( userSub=user_sub, sessionType=SessionType.REFRESH_TOKEN, token=refresh_token, diff --git a/apps/models/mcp.py b/apps/models/mcp.py index 828cf36d..b3454c87 100644 --- a/apps/models/mcp.py +++ b/apps/models/mcp.py @@ -3,10 +3,11 @@ import uuid from datetime import UTC, datetime from enum import Enum as PyEnum +from hashlib import shake_128 from typing import Any from sqlalchemy import BigInteger, DateTime, Enum, ForeignKey, String -from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column from .base import Base @@ -42,7 +43,7 @@ class MCPInfo(Base): """MCP 创建者""" config: Mapped[dict[str, Any]] = mapped_column(JSONB) """MCP 配置""" - id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default_factory=uuid.uuid4) + id: Mapped[str] = mapped_column(String(255), primary_key=True) """MCP ID""" updatedAt: Mapped[datetime] = mapped_column( # noqa: N815 DateTime(timezone=True), @@ -60,9 +61,9 @@ class MCPActivated(Base): """MCP 激活用户""" __tablename__ = "framework_mcp_activated" - mcp_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_mcp.id"), index=True, unique=True) + mcpId: Mapped[str] = mapped_column(ForeignKey("framework_mcp.id"), index=True, unique=True) # noqa: N815 """MCP ID""" - user_sub: Mapped[str] = mapped_column(ForeignKey("framework_user.userSub")) + userSub: Mapped[str] = mapped_column(ForeignKey("framework_user.userSub")) # noqa: N815 """用户ID""" id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True, init=False) """主键ID""" @@ -72,9 +73,19 @@ class MCPTools(Base): """MCP 工具""" __tablename__ = "framework_mcp_tools" - mcp_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_mcp.id"), index=True) + mcpId: Mapped[str] = mapped_column(ForeignKey("framework_mcp.id"), index=True) # noqa: N815 """MCP ID""" - tools: Mapped[dict[str, Any]] = mapped_column(JSONB) - """MCP 工具""" - id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True, init=False) + toolName: Mapped[str] = mapped_column(String(255)) # noqa: N815 + """MCP 工具名称""" + description: Mapped[str] = mapped_column(String(65535)) + """MCP 工具描述""" + inputSchema: Mapped[dict[str, Any]] = mapped_column(JSONB) # noqa: N815 + """MCP 工具输入参数""" + outputSchema: Mapped[dict[str, Any]] = mapped_column(JSONB) # noqa: N815 + """MCP 工具输出参数""" + id: Mapped[str] = mapped_column( + String(32), + primary_key=True, + default_factory=lambda: shake_128(uuid.uuid4().bytes).hexdigest(8), + ) """主键ID""" diff --git a/apps/models/user.py b/apps/models/user.py index 9eb45114..34695c7c 100644 --- a/apps/models/user.py +++ b/apps/models/user.py @@ -2,10 +2,9 @@ import enum import uuid -from datetime import datetime +from datetime import UTC, datetime from hashlib import sha256 -import pytz from sqlalchemy import ARRAY, BigInteger, Boolean, DateTime, Enum, ForeignKey, Integer, String from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column @@ -22,7 +21,7 @@ class User(Base): userSub: Mapped[str] = mapped_column(String(50), index=True, unique=True) # noqa: N815 """用户名""" lastLogin: Mapped[datetime] = mapped_column( # noqa: N815 - DateTime(timezone=True), default_factory=lambda: datetime.now(tz=pytz.timezone("Asia/Shanghai")), + DateTime(timezone=True), default_factory=lambda: datetime.now(tz=UTC), ) """用户最后一次登录时间""" isActive: Mapped[bool] = mapped_column(Boolean, default=True) # noqa: N815 @@ -75,7 +74,7 @@ class UserAppUsage(Base): usageCount: Mapped[int] = mapped_column(Integer, default=0) # noqa: N815 """应用使用次数""" lastUsed: Mapped[datetime] = mapped_column( # noqa: N815 - DateTime(timezone=True), default_factory=lambda: datetime.now(tz=pytz.timezone("Asia/Shanghai")), + DateTime(timezone=True), default_factory=lambda: datetime.now(tz=UTC), ) """用户最后一次使用时间""" diff --git a/apps/models/vectors.py b/apps/models/vectors.py index 181a7796..1c3214ef 100644 --- a/apps/models/vectors.py +++ b/apps/models/vectors.py @@ -3,7 +3,8 @@ import uuid from pgvector.sqlalchemy import Vector -from sqlalchemy import ForeignKey, Index +from sqlalchemy import ForeignKey, Index, String +from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from .base import Base @@ -13,11 +14,11 @@ class FlowPoolVector(Base): """Flow向量数据""" __tablename__ = "framework_flow_vector" - appId: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_app.id")) # noqa: N815 + appId: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_app.id"), nullable=False) # noqa: N815 """所属App的ID""" - embedding: Mapped[Vector] = mapped_column(Vector(1024)) + embedding: Mapped[Vector] = mapped_column(Vector(1024), nullable=False) """向量数据""" - id: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_flow.id"), primary_key=True) + id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("framework_flow.id"), primary_key=True) """Flow的ID""" __table_args__ = ( Index( @@ -34,9 +35,9 @@ class ServicePoolVector(Base): """Service向量数据""" __tablename__ = "framework_service_vector" - embedding: Mapped[Vector] = mapped_column(Vector(1024)) + embedding: Mapped[Vector] = mapped_column(Vector(1024), nullable=False) """向量数据""" - id: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_service.id"), primary_key=True) + id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("framework_service.id"), primary_key=True) """Service的ID""" __table_args__ = ( Index( @@ -53,11 +54,11 @@ class NodePoolVector(Base): """Node向量数据""" __tablename__ = "framework_node_vector" - embedding: Mapped[Vector] = mapped_column(Vector(1024)) + embedding: Mapped[Vector] = mapped_column(Vector(1024), nullable=False) """向量数据""" - serviceId: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_service.id")) # noqa: N815 + serviceId: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_service.id"), nullable=False) # noqa: N815 """Service的ID""" - id: Mapped[uuid.UUID] = mapped_column(ForeignKey("framework_node.id"), primary_key=True) + id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("framework_node.id"), primary_key=True) """Node的ID""" __table_args__ = ( Index( @@ -68,3 +69,43 @@ class NodePoolVector(Base): postgresql_ops={"embedding": "vector_cosine_ops"}, ), ) + + +class MCPVector(Base): + """MCP向量数据""" + + __tablename__ = "framework_mcp_vector" + embedding: Mapped[Vector] = mapped_column(Vector(1024), nullable=False) + """向量数据""" + id: Mapped[str] = mapped_column(String(255), ForeignKey("framework_mcp.id"), primary_key=True) + """MCP的ID""" + __table_args__ = ( + Index( + "hnsw_index", + "embedding", + postgresql_using="hnsw", + postgresql_with={"m": 16, "ef_construction": 200}, + postgresql_ops={"embedding": "vector_cosine_ops"}, + ), + ) + + +class MCPToolVector(Base): + """MCP工具向量数据""" + + __tablename__ = "framework_mcp_tool_vector" + embedding: Mapped[Vector] = mapped_column(Vector(1024), nullable=False) + """向量数据""" + mcpId: Mapped[str] = mapped_column(String(255), ForeignKey("framework_mcp.id"), nullable=False, index=True) # noqa: N815 + """MCP的ID""" + id: Mapped[str] = mapped_column(String(255), ForeignKey("framework_mcp_tool.id"), primary_key=True) + """MCP工具的ID""" + __table_args__ = ( + Index( + "hnsw_index", + "embedding", + postgresql_using="hnsw", + postgresql_with={"m": 16, "ef_construction": 200}, + postgresql_ops={"embedding": "vector_cosine_ops"}, + ), + ) diff --git a/apps/routers/conversation.py b/apps/routers/conversation.py index df1a3076..5c13e382 100644 --- a/apps/routers/conversation.py +++ b/apps/routers/conversation.py @@ -3,10 +3,9 @@ import logging import uuid -from datetime import datetime +from datetime import UTC, datetime from typing import Annotated -import pytz from fastapi import APIRouter, Body, Depends, Query, Request, status from fastapi.responses import JSONResponse diff --git a/apps/scheduler/mcp/host.py b/apps/scheduler/mcp/host.py index 6299f0f5..c7f1383e 100644 --- a/apps/scheduler/mcp/host.py +++ b/apps/scheduler/mcp/host.py @@ -10,11 +10,12 @@ from jinja2.sandbox import SandboxedEnvironment from mcp.types import TextContent from apps.llm.function import JsonGenerator +from apps.models.mcp import MCPTools from apps.scheduler.mcp.prompt import MEMORY_TEMPLATE from apps.scheduler.pool.mcp.client import MCPClient from apps.scheduler.pool.mcp.pool import MCPPool from apps.schemas.enum_var import StepStatus -from apps.schemas.mcp import MCPPlanItem, MCPTool +from apps.schemas.mcp import MCPPlanItem from apps.schemas.task import FlowStepHistory from apps.services.mcp_service import MCPServiceManager from apps.services.task import TaskManager @@ -76,7 +77,7 @@ class MCPHost: async def _save_memory( self, - tool: MCPTool, + tool: MCPTools, plan_item: MCPPlanItem, input_data: dict[str, Any], result: str, @@ -100,8 +101,8 @@ class MCPHost: task_id=self._task_id, flow_id=self._runtime_id, flow_name=self._runtime_name, - step_id=tool.name, - step_name=tool.name, + step_id=tool.toolId, + step_name=tool.toolName, # description是规划的实际内容 step_description=plan_item.content, status=StepStatus.SUCCESS, @@ -121,7 +122,7 @@ class MCPHost: return output_data - async def _fill_params(self, tool: MCPTool, query: str) -> dict[str, Any]: + async def _fill_params(self, tool: MCPTools, query: str) -> dict[str, Any]: """填充工具参数""" # 更清晰的输入·指令,这样可以调用generate llm_query = rf""" @@ -137,24 +138,24 @@ class MCPHost: {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": await self.assemble_memory()}, ], - tool.input_schema, + tool.inputSchema, ) return await json_generator.generate() - async def call_tool(self, tool: MCPTool, plan_item: MCPPlanItem) -> list[dict[str, Any]]: + async def call_tool(self, tool: MCPTools, plan_item: MCPPlanItem) -> list[dict[str, Any]]: """调用工具""" # 拿到Client - client = await MCPPool().get(tool.mcp_id, self._user_sub) + client = await MCPPool().get(tool.mcpId, self._user_sub) if client is None: - err = f"[MCPHost] MCP Server不合法: {tool.mcp_id}" + err = f"[MCPHost] MCP Server不合法: {tool.mcpId}" logger.error(err) raise ValueError(err) # 填充参数 params = await self._fill_params(tool, plan_item.instruction) # 调用工具 - result = await client.call_tool(tool.name, params) + result = await client.call_tool(tool.toolName, params) # 保存记忆 processed_result = [] for item in result.content: @@ -166,7 +167,7 @@ class MCPHost: return processed_result - async def get_tool_list(self, mcp_id_list: list[str]) -> list[MCPTool]: + async def get_tool_list(self, mcp_id_list: list[str]) -> list[MCPTools]: """获取工具列表""" # 获取工具列表 tool_list = [] diff --git a/apps/scheduler/mcp/select.py b/apps/scheduler/mcp/select.py index ffa45bc9..203ce784 100644 --- a/apps/scheduler/mcp/select.py +++ b/apps/scheduler/mcp/select.py @@ -6,10 +6,8 @@ import logging from apps.llm.embedding import Embedding from apps.llm.function import FunctionLLM from apps.llm.reasoning import ReasoningLLM -from apps.schemas.mcp import ( - MCPSelectResult, - MCPTool, -) +from apps.models.mcp import MCPTools +from apps.schemas.mcp import MCPSelectResult from apps.services.mcp_service import MCPServiceManager logger = logging.getLogger(__name__) @@ -69,7 +67,7 @@ class MCPSelector: @staticmethod - async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTool]: + async def select_top_tool(query: str, mcp_list: list[str], top_n: int = 10) -> list[MCPTools]: """选择最合适的工具""" tool_vector = await LanceDB().get_table("mcp_tool") query_embedding = await Embedding.get_embedding([query]) diff --git a/apps/scheduler/pool/loader/app.py b/apps/scheduler/pool/loader/app.py index f7403b04..bfb539ce 100644 --- a/apps/scheduler/pool/loader/app.py +++ b/apps/scheduler/pool/loader/app.py @@ -8,7 +8,6 @@ from anyio import Path from fastapi.encoders import jsonable_encoder from apps.common.config import config -from apps.common.mongo import MongoDB from apps.models.app import App from apps.scheduler.pool.check import FileChecker from apps.schemas.agent import AgentAppMetadata diff --git a/apps/scheduler/pool/loader/call.py b/apps/scheduler/pool/loader/call.py index 4cc7d71d..07b26e75 100644 --- a/apps/scheduler/pool/loader/call.py +++ b/apps/scheduler/pool/loader/call.py @@ -2,16 +2,11 @@ """Call 加载器""" import asyncio -import importlib import logging -import sys -from hashlib import shake_128 from pathlib import Path import apps.scheduler.call as system_call from apps.common.config import config -from apps.common.lance import LanceDB -from apps.common.mongo import MongoDB from apps.common.singleton import SingletonMeta from apps.llm.embedding import Embedding from apps.models.node import NodeInfo diff --git a/apps/scheduler/pool/loader/mcp.py b/apps/scheduler/pool/loader/mcp.py index ef4a2a41..932d8272 100644 --- a/apps/scheduler/pool/loader/mcp.py +++ b/apps/scheduler/pool/loader/mcp.py @@ -5,13 +5,14 @@ import asyncio import base64 import json import logging -import random import shutil +from hashlib import shake_128 import asyncer from anyio import Path -from sqids.sqids import Sqids +from sqlalchemy import select +from apps.common.postgres import postgres from apps.common.process_handler import ProcessHandler from apps.common.singleton import SingletonMeta from apps.constants import MCP_PATH @@ -20,17 +21,12 @@ from apps.models.mcp import MCPInfo, MCPInstallStatus, MCPTools, MCPType from apps.scheduler.pool.mcp.client import MCPClient from apps.scheduler.pool.mcp.install import install_npx, install_uvx from apps.schemas.mcp import ( - MCPCollection, MCPServerConfig, MCPServerSSEConfig, MCPServerStdioConfig, - MCPTool, - MCPToolVector, - MCPVector, ) logger = logging.getLogger(__name__) -sqids = Sqids(min_length=12) class MCPLoader(metaclass=SingletonMeta): @@ -57,6 +53,7 @@ class MCPLoader(metaclass=SingletonMeta): await (MCP_PATH / "users").unlink(missing_ok=True) await (MCP_PATH / "users").mkdir(parents=True, exist_ok=True) + @staticmethod async def _load_config(config_path: Path) -> MCPServerConfig: """ @@ -77,6 +74,7 @@ class MCPLoader(metaclass=SingletonMeta): return MCPServerConfig.model_validate(f_content) + @staticmethod async def _install_template_task( mcp_id: str, config: MCPServerConfig, @@ -175,12 +173,13 @@ class MCPLoader(metaclass=SingletonMeta): logger.info("[MCPLoader] 初始化MCP模板: %s", mcp_dir.as_posix()) await MCPLoader.init_one_template(mcp_dir.name, config) + @staticmethod async def _get_template_tool( mcp_id: str, config: MCPServerConfig, user_sub: str | None = None, - ) -> list[MCPTool]: + ) -> list[MCPTools]: """ 获取MCP模板的工具列表 @@ -206,12 +205,13 @@ class MCPLoader(metaclass=SingletonMeta): # 获取工具列表 tool_list = [] for item in client.tools: - tool_list += [MCPTool( - id=sqids.encode([random.randint(0, 1000000) for _ in range(5)])[:6], # noqa: S311 - name=item.name, - mcp_id=mcp_id, + tool_list += [MCPTools( + mcpId=mcp_id, + toolId=item., + toolName=item.name, description=item.description or "", - input_schema=item.inputSchema, + inputSchema=item.inputSchema, + outputSchema=item.outputSchema or {}, )] await client.stop() return tool_list @@ -262,6 +262,12 @@ class MCPLoader(metaclass=SingletonMeta): # 服务本身向量化 embedding = await Embedding.get_embedding([config.description]) + async with postgres.session() as session: + await session.merge(MCPVector( + id=mcp_id, + embedding=embedding[0], + )) + while True: try: mcp_table = await LanceDB().get_table("mcp") @@ -358,23 +364,6 @@ class MCPLoader(metaclass=SingletonMeta): await f.aclose() return MCPServerConfig.model_validate(config) - @staticmethod - async def update_template_status(mcp_id: str, status: MCPInstallStatus) -> None: - """ - 更新数据库中MCP模板状态 - - :param str mcp_id: MCP模板ID - :param MCPStatus status: MCP模板status - :return: 无 - """ - # 更新数据库 - mongo = MongoDB() - mcp_collection = mongo.get_collection("mcp") - await mcp_collection.update_one( - {"_id": mcp_id}, - {"$set": {"status": status}}, - upsert=True, - ) @staticmethod async def user_active_template(user_sub: str, mcp_id: str) -> None: @@ -489,6 +478,23 @@ class MCPLoader(metaclass=SingletonMeta): raise logger.info("[MCPLoader] 清除LanceDB中无效的MCP") + + @staticmethod + async def update_template_status(mcp_id: str, status: MCPInstallStatus) -> None: + """ + 更新数据库中MCP模板状态 + + :param str mcp_id: MCP模板ID + :param MCPInstallStatus status: MCP模板状态 + :return: 无 + """ + async with postgres.session() as session: + mcp_data = (await session.scalars(select(MCPInfo).where(MCPInfo.id == mcp_id))).one_or_none() + if mcp_data: + mcp_data.status = status + await session.merge(mcp_data) + + @staticmethod async def delete_mcp(mcp_id: str) -> None: """ diff --git a/apps/scheduler/pool/loader/service.py b/apps/scheduler/pool/loader/service.py index c1dc502e..2e06208b 100644 --- a/apps/scheduler/pool/loader/service.py +++ b/apps/scheduler/pool/loader/service.py @@ -9,7 +9,6 @@ from fastapi.encoders import jsonable_encoder from sqlalchemy import delete, insert from apps.common.config import config -from apps.common.mongo import MongoDB from apps.common.postgres import postgres from apps.llm.embedding import Embedding from apps.models.node import NodeInfo @@ -42,7 +41,7 @@ class ServiceLoader: # 载入OpenAPI文档,获取Node列表 try: - nodes: list[NodePool] = [] + nodes: list[NodeInfo] = [] async for yaml_path in (service_path / "openapi").rglob("*.yaml"): nodes.extend(await OpenAPILoader().load_one(service_id, yaml_path, metadata.api.server)) except Exception: @@ -100,7 +99,7 @@ class ServiceLoader: @staticmethod - async def _update_db(nodes: list[NodePool], metadata: ServiceMetadata) -> None: + async def _update_db(nodes: list[NodeInfo], metadata: ServiceMetadata) -> None: """更新数据库""" if not metadata.hashes: err = f"[ServiceLoader] 服务 {metadata.id} 的哈希值为空" diff --git a/apps/scheduler/pool/mcp/default.py b/apps/scheduler/pool/mcp/default.py index 215e3ce2..4f29ccae 100644 --- a/apps/scheduler/pool/mcp/default.py +++ b/apps/scheduler/pool/mcp/default.py @@ -2,9 +2,7 @@ """MCP 默认配置""" import logging -import random - -from sqids.sqids import Sqids +import uuid from apps.schemas.mcp import ( MCPServerConfig, @@ -14,9 +12,8 @@ from apps.schemas.mcp import ( ) logger = logging.getLogger(__name__) -sqids = Sqids(min_length=6) DEFAULT_STDIO = MCPServerConfig( - name="MCP服务_" + sqids.encode([random.randint(0, 1000000) for _ in range(5)]), # noqa: S311 + name="MCP服务_" + uuid.uuid4().hex[:6], description="MCP服务描述", type=MCPType.STDIO, config=MCPServerStdioConfig( @@ -32,7 +29,7 @@ DEFAULT_STDIO = MCPServerConfig( """默认的Stdio协议MCP Server配置""" DEFAULT_SSE = MCPServerConfig( - name="MCP服务_" + sqids.encode([random.randint(0, 1000000) for _ in range(5)]), # noqa: S311 + name="MCP服务_" + uuid.uuid4().hex[:6], description="MCP服务描述", type=MCPType.SSE, config=MCPServerSSEConfig( diff --git a/apps/scheduler/pool/mcp/pool.py b/apps/scheduler/pool/mcp/pool.py index 91cde4d9..9119b901 100644 --- a/apps/scheduler/pool/mcp/pool.py +++ b/apps/scheduler/pool/mcp/pool.py @@ -3,10 +3,10 @@ import logging -from apps.common.mongo import MongoDB from apps.common.singleton import SingletonMeta from apps.constants import MCP_PATH -from apps.schemas.mcp import MCPServerConfig, MCPType +from apps.models.mcp import MCPType +from apps.schemas.mcp import MCPServerConfig from .client import MCPClient diff --git a/apps/schemas/mcp.py b/apps/schemas/mcp.py index 43be897c..e6b98d25 100644 --- a/apps/schemas/mcp.py +++ b/apps/schemas/mcp.py @@ -2,11 +2,11 @@ """MCP 相关数据结构""" from enum import Enum -from typing import Any -from lancedb.pydantic import LanceModel, Vector from pydantic import BaseModel, Field +from apps.models.mcp import MCPType + class MCPStatus(str, Enum): """MCP 状态""" @@ -49,44 +49,6 @@ class MCPServerConfig(BaseModel): config: MCPServerStdioConfig | MCPServerSSEConfig = Field(description="MCP 服务器配置") -class MCPTool(BaseModel): - """MCP工具""" - - id: str = Field(description="MCP工具ID") - name: str = Field(description="MCP工具名称") - description: str = Field(description="MCP工具描述") - mcp_id: str = Field(description="MCP ID") - input_schema: dict[str, Any] = Field(description="MCP工具输入参数") - - -class MCPCollection(BaseModel): - """MCP相关信息""" - - id: str = Field(description="MCP ID", alias="_id", default="") - name: str = Field(description="MCP 自然语言名称", default="") - description: str = Field(description="MCP 自然语言描述", default="") - type: MCPType = Field(description="MCP 类型", default=MCPType.SSE) - activated: list[str] = Field(description="激活该MCP的用户ID列表", default=[]) - tools: list[MCPTool] = Field(description="MCP工具列表", default=[]) - status: MCPInstallStatus = Field(description="MCP服务状态", default=MCPInstallStatus.INSTALLING) - author: str = Field(description="MCP作者", default="") - - -class MCPVector(LanceModel): - """MCP向量化数据,存储在LanceDB的 ``mcp`` 表中""" - - id: str = Field(description="MCP ID") - embedding: Vector(dim=1024) = Field(description="MCP描述的向量信息") # type: ignore[call-arg] - - -class MCPToolVector(LanceModel): - """MCP工具向量化数据,存储在LanceDB的 ``mcp_tool`` 表中""" - - id: str = Field(description="工具ID") - mcp_id: str = Field(description="MCP ID") - embedding: Vector(dim=1024) = Field(description="MCP工具描述的向量信息") # type: ignore[call-arg] - - class MCPSelectResult(BaseModel): """MCP选择结果""" -- Gitee From 8909fdacac85ec44613460134e3b092ace9bcebb Mon Sep 17 00:00:00 2001 From: z30057876 Date: Sat, 26 Jul 2025 11:21:54 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=BA=93=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ac114cec..ab024be5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,23 +14,19 @@ dependencies = [ "jinja2==3.1.6", "jionlp==1.5.20", "jsonschema==4.23.0", - "lancedb==0.21.2", - "mcp==1.9.4", + "mcp==1.12.2", "minio==7.2.15", "ollama==0.5.1", - "openai==1.91.0", + "openai==1.97.1", "pandas==2.2.3", "pgvector==0.4.1", "pillow==10.3.0", "pydantic==2.11.7", - "pymongo==4.12.1", "python-jsonpath==1.3.0", "python-magic==0.4.27", "python-multipart==0.0.20", - "pytz==2025.2", "pyyaml==6.0.2", - "rich==13.9.4", - "sqids==0.5.1", + "rich==14.1.0", "sqlalchemy==2.0.41", "tiktoken==0.9.0", "toml==0.10.2", @@ -49,7 +45,7 @@ dev = [ "fastapi-profiler-lite>=0.3.2", "pytest==8.3.5", "pytest-mock==3.14.0", - "ruff==0.11.2", + "ruff==0.12.5", "sphinx==8.2.3", "sphinx-rtd-theme==3.0.2", ] -- Gitee