From a50aa307ab524bc5270f974f48650873ed601047 Mon Sep 17 00:00:00 2001 From: yuanzhipeng <2501363769@qq.com> Date: Sat, 7 Feb 2026 20:17:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(schema-converter):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E7=B1=BB=E5=9E=8B=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B9=B6=E4=BC=98=E5=8C=96schema=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 file 和 fileList 类型用于单文件和多文件上传功能 - 添加文件配置信息处理,包括 accept、typeCategories、uploadMode 等参数 - 为文件类型添加 x-file-type、x-accept、x-type-categories 等扩展属性 - 优化默认值处理逻辑,排除文件类型设置默认值的情况 refactor(main): 重构工具配置处理优先级 - 将 schema 获取优先级调整为先从 sqlParams 转换,再使用 inputJsonSchema - 增强错误处理机制,当 sqlParams 转换失败时自动回退到 inputJsonSchema - 当两种方式都失败时提供空 schema 作为兜底方案 - 改进日志记录,增加调试信息和警告提示 chore: 更新项目版本号和测试配置 - 更新 pyproject.toml 中的版本号从 0.1.3 到 0.1.5 - 修改测试用的 workflowId 和 workflowExecuteKey 环境变量 --- .../__pycache__/main.cpython-312.pyc | Bin 14114 -> 0 bytes .../schema_converter.cpython-312.pyc | Bin 6766 -> 0 bytes .../lzwcai_workflow_to_mcp/main.py | 56 ++++++++++++------ .../schema_converter.py | 52 +++++++++++++++- .../__pycache__/__init__.cpython-312.pyc | Bin 1073 -> 1073 bytes lzwcai_workflow_to_mcp/main.py | 4 +- lzwcai_workflow_to_mcp/pyproject.toml | 2 +- 7 files changed, 90 insertions(+), 24 deletions(-) delete mode 100644 lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/__pycache__/main.cpython-312.pyc delete mode 100644 lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/__pycache__/schema_converter.cpython-312.pyc diff --git a/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/__pycache__/main.cpython-312.pyc b/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 22b665687afcb824c426a20157aaa551a2a000ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14114 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 list[types.Tool]: logger.debug(f"处理工具配置: name={name}, description={description[:50] if description else 'None'}...") - # 优先使用 inputJsonSchema,如果不存在则从 sqlParams 转换 - input_json_schema = query.get("inputJsonSchema") - if input_json_schema: + # 优先从 sqlParams 转换,因为它包含更详细的文件配置信息 + sql_params = query.get("sqlParams") + if sql_params: try: - # inputJsonSchema 是 JSON 字符串,需要解析 - if isinstance(input_json_schema, str): - input_schema = json.loads(input_json_schema) - else: - input_schema = input_json_schema - # 清理 schema,确保 enum 只包含字符串 - input_schema = sanitize_json_schema(input_schema) - logger.debug(f"使用 inputJsonSchema (已清理): {json.dumps(input_schema, ensure_ascii=False)}") - except (json.JSONDecodeError, TypeError) as e: - logger.warning(f"解析 inputJsonSchema 失败: {e},回退到 sqlParams") - sql_params = query.get("sqlParams", "[]") input_schema = convert_sql_params_to_input_schema(sql_params) + logger.debug(f"从 sqlParams 转换的 inputSchema: {json.dumps(input_schema, ensure_ascii=False)}") + except Exception as e: + logger.warning(f"从 sqlParams 转换失败: {e},尝试使用 inputJsonSchema") + # 回退到 inputJsonSchema + input_json_schema = query.get("inputJsonSchema") + if input_json_schema: + try: + if isinstance(input_json_schema, str): + input_schema = json.loads(input_json_schema) + else: + input_schema = input_json_schema + input_schema = sanitize_json_schema(input_schema) + logger.debug(f"使用 inputJsonSchema (已清理): {json.dumps(input_schema, ensure_ascii=False)}") + except (json.JSONDecodeError, TypeError) as e2: + logger.error(f"解析 inputJsonSchema 也失败: {e2},使用空 schema") + input_schema = {"type": "object", "properties": {}, "required": []} + else: + logger.warning("sqlParams 和 inputJsonSchema 都不可用,使用空 schema") + input_schema = {"type": "object", "properties": {}, "required": []} else: - # 从 sqlParams 转换 - sql_params = query.get("sqlParams", "[]") - input_schema = convert_sql_params_to_input_schema(sql_params) - logger.debug(f"从 sqlParams 转换的 inputSchema: {json.dumps(input_schema, ensure_ascii=False)}") + # 如果没有 sqlParams,尝试使用 inputJsonSchema + input_json_schema = query.get("inputJsonSchema") + if input_json_schema: + try: + if isinstance(input_json_schema, str): + input_schema = json.loads(input_json_schema) + else: + input_schema = input_json_schema + input_schema = sanitize_json_schema(input_schema) + logger.debug(f"使用 inputJsonSchema (已清理): {json.dumps(input_schema, ensure_ascii=False)}") + except (json.JSONDecodeError, TypeError) as e: + logger.error(f"解析 inputJsonSchema 失败: {e},使用空 schema") + input_schema = {"type": "object", "properties": {}, "required": []} + else: + logger.warning("sqlParams 和 inputJsonSchema 都不存在,使用空 schema") + input_schema = {"type": "object", "properties": {}, "required": []} tools.append( types.Tool( diff --git a/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/schema_converter.py b/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/schema_converter.py index f497d4d..640a4a5 100644 --- a/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/schema_converter.py +++ b/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/schema_converter.py @@ -7,6 +7,8 @@ Schema 转换器 - paragraph: 段落/多行文本 - select: 下拉选项 - number: 数字输入 +- file: 单文件上传 +- fileList: 多文件上传 """ import json from typing import Any @@ -60,7 +62,13 @@ def convert_param_to_schema_property(param: dict) -> tuple[str, dict, bool]: "maxLength": 200, "defaultValue": "", "required": true, - "options": ["选项1", "选项2"] # 仅 select 类型 + "options": ["选项1", "选项2"], # 仅 select 类型 + "fileConfig": { # 仅 file/fileList 类型 + "uploadMode": "both", + "typeCategories": ["image"], + "customAccept": "", + "accept": ".jpg,.jpeg,.png" + } } Returns: @@ -73,6 +81,7 @@ def convert_param_to_schema_property(param: dict) -> tuple[str, dict, bool]: max_length = param.get("maxLength") is_required = param.get("required", False) options = param.get("options", []) + file_config = param.get("fileConfig", {}) property_schema = { "description": display_name @@ -112,12 +121,49 @@ def convert_param_to_schema_property(param: dict) -> tuple[str, dict, bool]: elif param_type == "number": property_schema["type"] = "number" + elif param_type == "file": + # 单文件上传 + property_schema["type"] = "string" + property_schema["format"] = "url" + property_schema["x-file-type"] = "single" + + # 添加文件配置信息 + if file_config: + if file_config.get("accept"): + property_schema["x-accept"] = file_config["accept"] + if file_config.get("typeCategories"): + property_schema["x-type-categories"] = file_config["typeCategories"] + if file_config.get("uploadMode"): + property_schema["x-upload-mode"] = file_config["uploadMode"] + # 保留完整配置 + property_schema["x-file-config"] = file_config + + elif param_type == "fileList": + # 多文件上传 + property_schema["type"] = "array" + property_schema["items"] = { + "type": "string", + "format": "url" + } + property_schema["x-file-type"] = "multiple" + + # 添加文件配置信息 + if file_config: + if file_config.get("accept"): + property_schema["x-accept"] = file_config["accept"] + if file_config.get("typeCategories"): + property_schema["x-type-categories"] = file_config["typeCategories"] + if file_config.get("uploadMode"): + property_schema["x-upload-mode"] = file_config["uploadMode"] + # 保留完整配置 + property_schema["x-file-config"] = file_config + else: # 默认当作 string 处理 property_schema["type"] = "string" - # 添加默认值 - if default_value not in (None, ""): + # 添加默认值(文件类型不需要默认值) + if default_value not in (None, "") and param_type not in ("file", "fileList"): if param_type == "number": try: property_schema["default"] = int(default_value) if str(default_value).isdigit() else float(default_value) diff --git a/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/utils/__pycache__/__init__.cpython-312.pyc b/lzwcai_workflow_to_mcp/lzwcai_workflow_to_mcp/utils/__pycache__/__init__.cpython-312.pyc index 2000b8d1fd8fd7d9112a3c8fb9605d2e3e14cf7c..074d8be96d1f0dbe6d39346739ff7da40c2923e6 100644 GIT binary patch delta 20 acmdnUv5|xOG%qg~0}xbftKG=0#sUC07zF+R delta 20 acmdnUv5|xOG%qg~0}vc3%iqYY#sUC0W(52I diff --git a/lzwcai_workflow_to_mcp/main.py b/lzwcai_workflow_to_mcp/main.py index d1197e0..7e44bdf 100644 --- a/lzwcai_workflow_to_mcp/main.py +++ b/lzwcai_workflow_to_mcp/main.py @@ -7,8 +7,8 @@ import os if __name__ == "__main__": # 设置环境变量 - os.environ["workflowId"] = "2019984063311556609" - os.environ["workflowExecuteKey"] = "wf_45bd630402664485a2ef5cd3ede5aa53" + os.environ["workflowId"] = "2020107946473074690" + os.environ["workflowExecuteKey"] = "wf_20170f33487d41459c180c6a277991a4" os.environ["backendBaseUrl"] = "http://192.168.2.236:8088" # Import and run the actual MCP server diff --git a/lzwcai_workflow_to_mcp/pyproject.toml b/lzwcai_workflow_to_mcp/pyproject.toml index 4fbafb3..d864806 100644 --- a/lzwcai_workflow_to_mcp/pyproject.toml +++ b/lzwcai_workflow_to_mcp/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "lzwcai-workflow-to-mcp" -version = "0.1.3" +version = "0.1.5" description = "MCP server for executing business SQL queries with dynamic tool generation" readme = "README.md" requires-python = ">=3.10"