-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand file tree
/
Copy pathtools.py
More file actions
103 lines (90 loc) · 3.52 KB
/
Copy pathtools.py
File metadata and controls
103 lines (90 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import json
import re
import uuid_utils.compat as uuid
from django.db.models import QuerySet
from application.models import ApplicationApiKey, Application, ChatUserType, ChatSourceChoices
from chat.serializers.chat import ChatSerializers
class MCPToolHandler:
def __init__(self, auth_header):
app_key = QuerySet(ApplicationApiKey).filter(secret_key=auth_header, is_active=True).first()
if not app_key:
raise PermissionError("Invalid API Key")
self.application = QuerySet(Application).filter(id=app_key.application_id, is_publish=True).first()
if not self.application:
raise PermissionError("Application is not found or not published")
def initialize(self):
return {
"protocolVersion": "2025-06-18",
"serverInfo": {
"name": "maxkb-mcp",
"version": "1.0.0"
},
"capabilities": {
"tools": {}
}
}
def list_tools(self):
return {
"tools": [
{
"name": f'agent_{str(self.application.id)[:8]}',
"description": f'{self.application.name} {self.application.desc}',
"inputSchema": {
"type": "object",
"properties": {
"message": {"type": "string", "description": "The message to send to the AI."},
},
"required": ["message"]
}
}
]
}
def _get_chat_id(self):
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': self.application.id,
'chat_user_id': str(uuid.uuid7()),
'chat_user_type': ChatUserType.ANONYMOUS_USER,
'ip_address': '-',
'source': {"type": ChatSourceChoices.ONLINE.value},
'debug': False
}).open()
def call_tool(self, params):
args = params.get("arguments", {})
payload = {
'message': args.get('message'),
'stream': True,
're_chat': False
}
resp = ChatSerializers(data={
'chat_id': self._get_chat_id(),
'chat_user_id': str(uuid.uuid7()),
'chat_user_type': ChatUserType.ANONYMOUS_USER,
'application_id': self.application.id,
'ip_address': '-',
'source': {"type": ChatSourceChoices.ONLINE.value},
'debug': False,
}).chat(payload)
chunks = []
for raw_line in resp:
line = raw_line.decode("utf-8", errors="replace").rstrip("\r\n")
if not line.startswith("data:"):
continue
payload = line[5:].strip()
if not payload or payload == "[DONE]":
continue
try:
event = json.loads(payload)
except json.JSONDecodeError:
continue
if event.get("operate") is True:
chunks.append(event.get("content", ""))
if event.get("is_end"):
break
data = ''.join(chunks)
# 排除<tool_calls_render></tool_calls_render>标签
data = re.sub(r'<tool_calls_render>.*?</tool_calls_render>', '', data, flags=re.DOTALL)
return {"content": [{"type": "text", "text": data}]}