diff --git a/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py b/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py index 9e64060be..e1df2b8c6 100644 --- a/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py +++ b/apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py @@ -269,8 +269,14 @@ class BaseChatStep(IChatStep): self.context['application_ids'] = application_ids for application_id in application_ids: app = QuerySet(Application).filter(id=application_id).first() + app_key = QuerySet(ApplicationApiKey).filter(application_id=application_id, is_active=True).first() + # TODO 处理api + if app_key is not None: + api_key = app_key.secret_key + else: + continue executor = ToolExecutor() - app_config = executor.get_app_mcp_config(app.id, app.name, app.desc) + app_config = executor.get_app_mcp_config(api_key, app.name, app.desc) mcp_servers_config[str(app.id)] = app_config if len(mcp_servers_config) > 0: diff --git a/apps/common/utils/app_mcp.py b/apps/common/utils/app_mcp.py deleted file mode 100644 index 806e0bbd4..000000000 --- a/apps/common/utils/app_mcp.py +++ /dev/null @@ -1,70 +0,0 @@ -import json -import logging -import os -import sys - -import uuid_utils.compat as uuid -from asgiref.sync import sync_to_async -from mcp.server.fastmcp import FastMCP - -logging.basicConfig(level=logging.WARNING) -logging.getLogger("mcp").setLevel(logging.ERROR) -logging.getLogger("mcp.server").setLevel(logging.ERROR) - - -def app_mcp_init(base_dir: str, application_id: str, name: str, description: str): - import django - - sys.path.insert(0, base_dir) - - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "maxkb.settings") - - django.setup() - mcp = FastMCP() - - @sync_to_async - def _get_chat_id(): - from application.models import ChatUserType - from chat.serializers.chat import OpenChatSerializers - from common.init import init_template - - init_template.run() - - return OpenChatSerializers(data={ - 'application_id': application_id, - 'chat_user_id': str(uuid.uuid7()), - 'chat_user_type': ChatUserType.ANONYMOUS_USER, - 'debug': False - }).open() - - @sync_to_async - def _chat_with_ai(chat_id: str, message: str) -> str: - from application.models import ChatUserType - from chat.serializers.chat import ChatSerializers - - payload = { - 'message': message, - 'stream': False, - 're_chat': False - } - resp = ChatSerializers(data={ - 'chat_id': chat_id, - 'chat_user_id': str(uuid.uuid7()), - 'chat_user_type': ChatUserType.ANONYMOUS_USER, - 'application_id': application_id, - 'debug': False, - }).chat(payload) - data = json.loads(str(resp.text)) - return str(data.get("data", {}).get("content") or data.get("response")) - - @mcp.tool(description=f'{name} {description}') - async def ai_chat(message: str) -> str: - chat_id = await _get_chat_id() - reply = await _chat_with_ai(chat_id, message) - - return reply or "AI 未能生成回复" - - mcp.run(transport='stdio') - - -app_mcp_init(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) diff --git a/apps/common/utils/tool_code.py b/apps/common/utils/tool_code.py index 03b3e49c2..cd0e21226 100644 --- a/apps/common/utils/tool_code.py +++ b/apps/common/utils/tool_code.py @@ -233,18 +233,59 @@ exec({dedent(code)!a}) } return tool_config - def get_app_mcp_config(self, application_id, name, description): - cwd = os.path.dirname(os.path.abspath(__file__)) + def get_app_mcp_config(self, api_key, name, description): + chat_path = CONFIG.get_chat_path() + _code = f''' +import requests +from typing import Optional + +def _get_chat_id() -> Optional[str]: + url = f"http://127.0.0.1:8080{chat_path}/api/open" + headers = {{ + 'accept': '*/*', + 'Authorization': f'Bearer {api_key}' + }} + try: + resp = requests.get(url, headers=headers, timeout=10) + resp.raise_for_status() + return resp.json().get("data") + except Exception as e: + raise e + + +def _chat_with_ai(chat_id: str, message: str) -> Optional[str]: + url = f"http://127.0.0.1:8080{chat_path}/api/chat_message/{{chat_id}}" + headers = {{"Content-Type": "application/json", "Authorization": f'Bearer {api_key}'}} + payload = {{ + "message": message, + "re_chat": False, + "stream": False + }} + try: + resp = requests.post(url, json=payload, headers=headers, timeout=600) + resp.raise_for_status() + data = resp.json() + return str(data.get("data", {{}}).get("content") or data.get("response")) + except Exception as e: + raise e + +def ai_chat(message: str) -> str: + chat_id = _get_chat_id() + reply = _chat_with_ai(chat_id, message) + return reply or "AI 未能生成回复" + + ''' + _code = self.generate_mcp_server_code(_code, {}, name, description) + # print(_code) + maxkb_logger.debug(f"Python code of mcp app: {_code}") + compressed_and_base64_encoded_code_str = base64.b64encode(gzip.compress(_code.encode())).decode() app_config = { 'command': sys.executable, 'args': [ - f'{cwd}/app_mcp.py', - BASE_DIR, - str(application_id), - name, - description, + '-c', + f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())', ], - 'cwd': BASE_DIR, + 'cwd': _sandbox_path, 'env': { 'LD_PRELOAD': f'{_sandbox_path}/lib/sandbox.so', },