您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

mcp_server_app.py 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. from flask import Response, request
  2. from flask_login import current_user, login_required
  3. from api.db import VALID_MCP_SERVER_TYPES
  4. from api.db.db_models import MCPServer
  5. from api.db.services.mcp_server_service import MCPServerService
  6. from api.db.services.user_service import TenantService
  7. from api.settings import RetCode
  8. from api.utils import get_uuid
  9. from api.utils.api_utils import get_data_error_result, get_json_result, server_error_response, validate_request
  10. from api.utils.web_utils import safe_json_parse
  11. @manager.route("/list", methods=["POST"]) # noqa: F821
  12. @login_required
  13. def list_mcp() -> Response:
  14. keywords = request.args.get("keywords", "")
  15. page_number = int(request.args.get("page", 0))
  16. items_per_page = int(request.args.get("page_size", 0))
  17. orderby = request.args.get("orderby", "create_time")
  18. if request.args.get("desc", "true").lower() == "false":
  19. desc = False
  20. else:
  21. desc = True
  22. req = request.get_json()
  23. mcp_ids = req.get("mcp_ids", [])
  24. try:
  25. servers = MCPServerService.get_servers(current_user.id, mcp_ids, page_number, items_per_page, orderby, desc, keywords) or []
  26. return get_json_result(data={"mcp_servers": servers, "total": len(servers)})
  27. except Exception as e:
  28. return server_error_response(e)
  29. @manager.route("/detail", methods=["GET"]) # noqa: F821
  30. @login_required
  31. def detail() -> Response:
  32. mcp_id = request.args["mcp_id"]
  33. try:
  34. mcp_server = MCPServerService.get_or_none(id=mcp_id, tenant_id=current_user.id)
  35. if mcp_server is None:
  36. return get_json_result(code=RetCode.NOT_FOUND, data=None)
  37. return get_json_result(data=mcp_server.to_dict())
  38. except Exception as e:
  39. return server_error_response(e)
  40. @manager.route("/create", methods=["POST"]) # noqa: F821
  41. @login_required
  42. @validate_request("name", "url", "server_type")
  43. def create() -> Response:
  44. req = request.get_json()
  45. server_type = req.get("server_type", "")
  46. if server_type not in VALID_MCP_SERVER_TYPES:
  47. return get_data_error_result(message="Unsupported MCP server type.")
  48. server_name = req.get("name", "")
  49. if not server_name or len(server_name.encode("utf-8")) > 255:
  50. return get_data_error_result(message=f"Invaild MCP name or length is {len(server_name)} which is large than 255.")
  51. req["headers"] = safe_json_parse(req.get("headers", {}))
  52. req["variables"] = safe_json_parse(req.get("variables", {}))
  53. try:
  54. req["id"] = get_uuid()
  55. req["tenant_id"] = current_user.id
  56. e, _ = TenantService.get_by_id(current_user.id)
  57. if not e:
  58. return get_data_error_result(message="Tenant not found.")
  59. if not MCPServerService.insert(**req):
  60. return get_data_error_result()
  61. return get_json_result(data={"id": req["id"]})
  62. except Exception as e:
  63. return server_error_response(e)
  64. @manager.route("/update", methods=["POST"]) # noqa: F821
  65. @login_required
  66. @validate_request("id")
  67. def update() -> Response:
  68. req = request.get_json()
  69. server_type = req.get("server_type", "")
  70. if server_type and server_type not in VALID_MCP_SERVER_TYPES:
  71. return get_data_error_result(message="Unsupported MCP server type.")
  72. server_name = req.get("name", "")
  73. if server_name and len(server_name.encode("utf-8")) > 255:
  74. return get_data_error_result(message=f"Invaild MCP name or length is {len(server_name)} which is large than 255.")
  75. req["headers"] = safe_json_parse(req.get("headers", {}))
  76. req["variables"] = safe_json_parse(req.get("variables", {}))
  77. try:
  78. req["tenant_id"] = current_user.id
  79. if not MCPServerService.filter_update([MCPServer.id == req["id"], MCPServer.tenant_id == req["tenant_id"]], req):
  80. return get_data_error_result(message="Failed to updated MCP server.")
  81. e, updated_mcp = MCPServerService.get_by_id(req["id"])
  82. if not e:
  83. return get_data_error_result(message="Failed to fetch updated MCP server.")
  84. return get_json_result(data=updated_mcp.to_dict())
  85. except Exception as e:
  86. return server_error_response(e)
  87. @manager.route("/rm", methods=["POST"]) # noqa: F821
  88. @login_required
  89. @validate_request("mcp_ids")
  90. def rm() -> Response:
  91. req = request.get_json()
  92. mcp_ids = req.get("mcp_ids", [])
  93. try:
  94. req["tenant_id"] = current_user.id
  95. if not MCPServerService.delete_by_ids(mcp_ids):
  96. return get_data_error_result(message=f"Failed to delete MCP servers {mcp_ids}")
  97. return get_json_result(data=True)
  98. except Exception as e:
  99. return server_error_response(e)
  100. @manager.route("/import", methods=["POST"]) # noqa: F821
  101. @login_required
  102. @validate_request("mcpServers")
  103. def import_multiple() -> Response:
  104. req = request.get_json()
  105. servers = req.get("mcpServers", {})
  106. if not servers:
  107. return get_data_error_result(message="No MCP servers provided.")
  108. results = []
  109. try:
  110. for server_name, config in servers.items():
  111. if not all(key in config for key in ["type", "url"]):
  112. results.append({"server": server_name, "success": False, "message": "Missing required fields (type or url)"})
  113. continue
  114. base_name = server_name
  115. new_name = base_name
  116. counter = 0
  117. while True:
  118. e, _ = MCPServerService.get_by_name_and_tenant(name=new_name, tenant_id=current_user.id)
  119. if not e:
  120. break
  121. new_name = f"{base_name}_{counter}"
  122. counter += 1
  123. create_data = {
  124. "id": get_uuid(),
  125. "tenant_id": current_user.id,
  126. "name": new_name,
  127. "url": config["url"],
  128. "server_type": config["type"],
  129. "variables": {"authorization_token": config.get("authorization_token", ""), "tool_configuration": config.get("tool_configuration", {})},
  130. }
  131. if MCPServerService.insert(**create_data):
  132. result = {"server": server_name, "success": True, "action": "created", "id": create_data["id"], "new_name": new_name}
  133. if new_name != base_name:
  134. result["message"] = f"Renamed from '{base_name}' to avoid duplication"
  135. results.append(result)
  136. else:
  137. results.append({"server": server_name, "success": False, "message": "Failed to create MCP server."})
  138. return get_json_result(data={"results": results})
  139. except Exception as e:
  140. return server_error_response(e)
  141. @manager.route("/export", methods=["POST"]) # noqa: F821
  142. @login_required
  143. @validate_request("mcp_ids")
  144. def export_multiple() -> Response:
  145. req = request.get_json()
  146. mcp_ids = req.get("mcp_ids", [])
  147. if not mcp_ids:
  148. return get_data_error_result(message="No MCP server IDs provided.")
  149. try:
  150. exported_servers = {}
  151. for mcp_id in mcp_ids:
  152. e, mcp_server = MCPServerService.get_by_id(mcp_id)
  153. if e and mcp_server.tenant_id == current_user.id:
  154. server_key = mcp_server.name
  155. exported_servers[server_key] = {
  156. "type": mcp_server.server_type,
  157. "url": mcp_server.url,
  158. "name": mcp_server.name,
  159. "authorization_token": mcp_server.variables.get("authorization_token", ""),
  160. "tool_configuration": mcp_server.variables.get("tool_configuration", {}),
  161. }
  162. return get_json_result(data={"mcpServers": exported_servers})
  163. except Exception as e:
  164. return server_error_response(e)