chore: refactor app MCP configuration and implement AI chat functionality

This commit is contained in:
CaptainB 2025-12-23 10:50:48 +08:00
parent 6aa3999e05
commit bf9ae948d5
3 changed files with 79 additions and 56 deletions

View File

@ -269,14 +269,8 @@ 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(api_key, app.name, app.desc)
app_config = executor.get_app_mcp_config(app.id, app.name, app.desc)
mcp_servers_config[str(app.id)] = app_config
if len(mcp_servers_config) > 0:

View File

@ -0,0 +1,70 @@
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])

View File

@ -233,59 +233,18 @@ exec({dedent(code)!a})
}
return tool_config
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()
def get_app_mcp_config(self, application_id, name, description):
cwd = os.path.dirname(os.path.abspath(__file__))
app_config = {
'command': sys.executable,
'args': [
'-c',
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
f'{cwd}/app_mcp.py',
BASE_DIR,
str(application_id),
name,
description,
],
'cwd': _sandbox_path,
'cwd': BASE_DIR,
'env': {
'LD_PRELOAD': f'{_sandbox_path}/lib/sandbox.so',
},