feat: 实现完整的 MCP 工具调用管道 - 让 Claude AI 真正调用 MCP 工具 核心功能: - MCP 工具发现: 从 MCP 服务器获取可用工具列表 (SSE 响应解析) - 工具转换器: 将 MCP 工具定义转换为 Claude API tools 格式 - tool_use 处理器: 处理 Claude 返回的工具调用请求 - MCP 调用器: 实际调用 MCP 工具并返回结果 - 多轮对话管理: 自动处理工具调用后的后续对话 测试验证: - ✅ 成功发现 11 个 Novel Translator MCP 工具 - ✅ Claude 智能选择工具并执行翻译任务 - ✅ 自动添加术语表并优化翻译结果 新增文件: - backend/mcp_client.py: MCP 客户端 + SSE 响应解析 - backend/tool_converter.py: MCP → Claude 工具格式转换 - backend/tool_handler.py: tool_use 响应处理器 - backend/conversation_manager.py: 多轮对话管理器 - backend/app.py: Flask 后端集成完整管道 - frontend/index.html: Web 聊天界面 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> EOF )
94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
"""
|
|
AI MCP Web UI - 简化后端服务器
|
|
使用 Python 内置 http.server 模块
|
|
"""
|
|
import os
|
|
import json
|
|
import http.server
|
|
import socketserver
|
|
from pathlib import Path
|
|
|
|
# 配置
|
|
PORT = int(os.getenv('PORT', 5000))
|
|
FRONTEND_DIR = str(Path(__file__).parent.parent / 'frontend')
|
|
|
|
class MCPHandler(http.server.SimpleHTTPRequestHandler):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, directory=FRONTEND_DIR, **kwargs)
|
|
|
|
def log_message(self, format, *args):
|
|
print(f"[{self.log_date_time_string()}] {format % args}")
|
|
|
|
def end_headers(self):
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
|
self.send_header('Access-Control-Allow-Headers', 'Content-Type, X-Session-ID')
|
|
super().end_headers()
|
|
|
|
def do_OPTIONS(self):
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
|
|
def do_GET(self):
|
|
if self.path == '/api/health':
|
|
self.send_json_response(200, {
|
|
"status": "ok",
|
|
"message": "MCP Web UI Server (Simplified)",
|
|
"frontend_dir": FRONTEND_DIR
|
|
})
|
|
elif self.path == '/api/mcp/servers':
|
|
self.send_json_response(200, {
|
|
"servers": [
|
|
{"id": "novel-translator", "name": "Novel Translator MCP", "enabled": True},
|
|
{"id": "novel-platform-user", "name": "Novel Platform User MCP", "enabled": False},
|
|
{"id": "novel-platform-admin", "name": "Novel Platform Admin MCP", "enabled": False}
|
|
]
|
|
})
|
|
else:
|
|
super().do_GET()
|
|
|
|
def do_POST(self):
|
|
content_length = int(self.headers.get('Content-Length', 0))
|
|
data = {}
|
|
if content_length > 0:
|
|
try:
|
|
post_data = self.rfile.read(content_length)
|
|
data = json.loads(post_data.decode('utf-8'))
|
|
except:
|
|
pass
|
|
|
|
if self.path == '/api/chat':
|
|
message = data.get('message', '')
|
|
self.send_json_response(200, {
|
|
"response": f"[简化服务器] 收到: {message}\n\n注意: 完整 AI 功能需要安装 Flask、Anthropic SDK 等依赖。",
|
|
"model": "simplified-server"
|
|
})
|
|
elif self.path == '/api/auth/login':
|
|
self.send_json_response(200, {
|
|
"success": False,
|
|
"message": "完整认证功能需要 Flask 支持"
|
|
})
|
|
else:
|
|
self.send_json_response(404, {"error": "Not found"})
|
|
|
|
def send_json_response(self, code, data):
|
|
self.send_response(code)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
self.wfile.write(json.dumps(data, ensure_ascii=False).encode('utf-8'))
|
|
|
|
def main():
|
|
print("=" * 50)
|
|
print(" MCP Web UI - 简化服务器")
|
|
print("=" * 50)
|
|
print(f" 端口: {PORT}")
|
|
print(f" 前端: {FRONTEND_DIR}")
|
|
print(f" 访问: http://localhost:{PORT}")
|
|
print("=" * 50)
|
|
|
|
with socketserver.TCPServer(("0.0.0.0", PORT), MCPHandler) as httpd:
|
|
httpd.serve_forever()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|