| """ |
| JSON内容提取插件 MCP工具定义 |
| """ |
|
|
| from app.mcp.decorators import mcp_tool |
| from pydantic import BaseModel, Field |
| from typing import Any, List, Optional |
|
|
|
|
| class ExtractFromJsonInput(BaseModel): |
| """从JSON数据提取content的输入参数""" |
| json_data: Any = Field(description="JSON数据对象") |
| output_file: Optional[str] = Field( |
| default=None, |
| description="输出文件路径(可选,不提供则返回格式化文本)" |
| ) |
|
|
|
|
| class ExtractFromJsonOutput(BaseModel): |
| """从JSON数据提取content的输出结果""" |
| success: bool = Field(description="操作是否成功") |
| contents: List[str] = Field(default=[], description="提取的content列表") |
| formatted_output: str = Field(default="", description="格式化后的输出") |
| count: int = Field(default=0, description="提取的content数量") |
| error: Optional[str] = Field(default=None, description="错误信息") |
|
|
|
|
| class ExtractFromFileInput(BaseModel): |
| """从JSON文件提取content的输入参数""" |
| file_path: str = Field(description="JSON文件路径") |
| output_file: Optional[str] = Field( |
| default=None, |
| description="输出文件路径(可选)" |
| ) |
|
|
|
|
| class ExtractFromFileOutput(BaseModel): |
| """从JSON文件提取content的输出结果""" |
| success: bool = Field(description="操作是否成功") |
| file_path: str = Field(description="源文件路径") |
| contents: List[str] = Field(default=[], description="提取的content列表") |
| formatted_output: str = Field(default="", description="格式化后的输出") |
| count: int = Field(default=0, description="提取的content数量") |
| error: Optional[str] = Field(default=None, description="错误信息") |
|
|
|
|
| class ExtractFromDirectoryInput(BaseModel): |
| """从目录批量提取content的输入参数""" |
| dir_path: str = Field(description="包含JSON文件的目录路径") |
| output_file: Optional[str] = Field( |
| default=None, |
| description="输出文件路径(可选)" |
| ) |
|
|
|
|
| class ExtractFromDirectoryOutput(BaseModel): |
| """从目录批量提取content的输出结果""" |
| success: bool = Field(description="操作是否成功") |
| dir_path: str = Field(description="源目录路径") |
| file_count: int = Field(default=0, description="处理的文件数量") |
| result: str = Field(default="", description="提取结果") |
| error: Optional[str] = Field(default=None, description="错误信息") |
|
|
|
|
| class ConversationMessage(BaseModel): |
| """对话消息结构""" |
| role: str = Field(description="消息角色(system/user/assistant)") |
| content: str = Field(description="消息内容") |
|
|
|
|
| class ExtractConversationFromJsonInput(BaseModel): |
| """从JSON数据提取对话的输入参数""" |
| json_data: Any = Field(description="JSON数据对象") |
|
|
|
|
| class ExtractConversationFromJsonOutput(BaseModel): |
| """从JSON数据提取对话的输出结果""" |
| success: bool = Field(description="操作是否成功") |
| is_conversation: bool = Field(description="是否为对话格式") |
| messages: List[ConversationMessage] = Field(default=[], description="对话消息列表") |
| formatted_output: str = Field(default="", description="格式化后的对话记录") |
| count: int = Field(default=0, description="消息数量") |
| error: Optional[str] = Field(default=None, description="错误信息") |
|
|
|
|
| class ExtractConversationFromFileInput(BaseModel): |
| """从JSON文件提取对话的输入参数""" |
| file_path: str = Field(description="JSON文件路径") |
|
|
|
|
| class ExtractConversationFromFileOutput(BaseModel): |
| """从JSON文件提取对话的输出结果""" |
| success: bool = Field(description="操作是否成功") |
| file_path: str = Field(description="源文件路径") |
| is_conversation: bool = Field(description="是否为对话格式") |
| messages: List[ConversationMessage] = Field(default=[], description="对话消息列表") |
| formatted_output: str = Field(default="", description="格式化后的对话记录") |
| count: int = Field(default=0, description="消息数量") |
| error: Optional[str] = Field(default=None, description="错误信息") |
|
|
|
|
| |
| _core = None |
|
|
|
|
| def _get_core(): |
| """获取核心逻辑实例""" |
| global _core |
| if _core is None: |
| from .core import JsonContentExtractorCore |
| _core = JsonContentExtractorCore() |
| return _core |
|
|
|
|
| @mcp_tool( |
| name="json-content", |
| title="从JSON数据提取content", |
| description="从JSON数据对象中递归提取所有content字段的内容。如果是OpenAI对话格式,会自动识别并按对话格式输出。", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def extract_from_json(params: ExtractFromJsonInput) -> ExtractFromJsonOutput: |
| """ |
| 从JSON数据中提取content字段 |
| |
| 支持递归提取嵌套的content字段,包括处理OpenAI API格式的content数组。 |
| 如果是OpenAI对话格式(包含messages数组),会自动识别并按对话格式输出。 |
| |
| Args: |
| params: 包含JSON数据 |
| |
| Returns: |
| ExtractFromJsonOutput: 提取的内容 |
| """ |
| core = _get_core() |
|
|
| try: |
| |
| if core._is_conversation_format(params.json_data): |
| formatted_output = core._format_conversation(params.json_data) |
| messages = core._extract_conversation(params.json_data) |
| contents = [msg["content"] for msg in messages] |
| else: |
| contents = core.extract_content_from_json(params.json_data) |
|
|
| formatted_contents = [] |
| for i, content in enumerate(contents, 1): |
| formatted = core.format_content(content) |
| formatted_contents.append(f"=== Content {i} ===\n{formatted}") |
|
|
| formatted_output = "\n\n".join(formatted_contents) if formatted_contents else "未找到content内容" |
|
|
| |
| if params.output_file and contents: |
| try: |
| with open(params.output_file, 'w', encoding='utf-8') as f: |
| f.write(formatted_output) |
| except Exception as e: |
| return ExtractFromJsonOutput( |
| success=False, |
| contents=contents, |
| formatted_output=formatted_output, |
| count=len(contents), |
| error=f"保存文件失败: {str(e)}" |
| ) |
|
|
| return ExtractFromJsonOutput( |
| success=True, |
| contents=contents, |
| formatted_output=formatted_output, |
| count=len(contents) |
| ) |
|
|
| except Exception as e: |
| return ExtractFromJsonOutput( |
| success=False, |
| error=str(e) |
| ) |
|
|
|
|
| @mcp_tool( |
| name="json-file", |
| title="从JSON文件提取content", |
| description="从JSON文件中递归提取所有content字段的内容。如果是OpenAI对话格式,会自动识别并按对话格式输出。", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def extract_from_file(params: ExtractFromFileInput) -> ExtractFromFileOutput: |
| """ |
| 从JSON文件中提取content字段 |
| |
| 如果是OpenAI对话格式,会自动识别并按对话格式输出。 |
| |
| Args: |
| params: 包含文件路径 |
| |
| Returns: |
| ExtractFromFileOutput: 提取的内容 |
| """ |
| core = _get_core() |
|
|
| try: |
| import os |
| if not os.path.exists(params.file_path): |
| return ExtractFromFileOutput( |
| success=False, |
| file_path=params.file_path, |
| error=f"文件不存在: {params.file_path}" |
| ) |
|
|
| contents = core.extract_content_from_file(params.file_path) |
| result = core.process_single_file(params.file_path, output_file=params.output_file) |
|
|
| return ExtractFromFileOutput( |
| success=True, |
| file_path=params.file_path, |
| contents=contents, |
| formatted_output=result, |
| count=len(contents) |
| ) |
|
|
| except Exception as e: |
| return ExtractFromFileOutput( |
| success=False, |
| file_path=params.file_path, |
| error=str(e) |
| ) |
|
|
|
|
| @mcp_tool( |
| name="json-dir", |
| title="从目录批量提取content", |
| description="从目录中所有JSON文件递归提取content字段的内容", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def extract_from_directory(params: ExtractFromDirectoryInput) -> ExtractFromDirectoryOutput: |
| """ |
| 从目录中批量提取content字段 |
| |
| Args: |
| params: 包含目录路径 |
| |
| Returns: |
| ExtractFromDirectoryOutput: 提取的结果 |
| """ |
| core = _get_core() |
|
|
| try: |
| import os |
| import glob |
|
|
| if not os.path.exists(params.dir_path): |
| return ExtractFromDirectoryOutput( |
| success=False, |
| dir_path=params.dir_path, |
| error=f"目录不存在: {params.dir_path}" |
| ) |
|
|
| json_files = glob.glob(os.path.join(params.dir_path, "*.json")) |
| result = core.process_directory(params.dir_path, output_file=params.output_file) |
|
|
| return ExtractFromDirectoryOutput( |
| success=True, |
| dir_path=params.dir_path, |
| file_count=len(json_files), |
| result=result |
| ) |
|
|
| except Exception as e: |
| return ExtractFromDirectoryOutput( |
| success=False, |
| dir_path=params.dir_path, |
| error=str(e) |
| ) |
|
|
|
|
| @mcp_tool( |
| name="json-chat", |
| title="从JSON数据提取对话", |
| description="从JSON数据中提取OpenAI格式的对话消息,返回结构化的对话记录", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def extract_conversation_from_json(params: ExtractConversationFromJsonInput) -> ExtractConversationFromJsonOutput: |
| """ |
| 从JSON数据中提取对话消息 |
| |
| 专门用于处理OpenAI格式的对话JSON,返回结构化的消息列表。 |
| 如果不是对话格式,is_conversation会返回false。 |
| |
| Args: |
| params: 包含JSON数据 |
| |
| Returns: |
| ExtractConversationFromJsonOutput: 结构化的对话消息 |
| """ |
| core = _get_core() |
|
|
| try: |
| messages = core.extract_conversation_from_json(params.json_data) |
| is_conversation = len(messages) > 0 |
|
|
| if is_conversation: |
| formatted_output = core._format_conversation(params.json_data) |
| else: |
| formatted_output = "该数据不是对话格式" |
|
|
| return ExtractConversationFromJsonOutput( |
| success=True, |
| is_conversation=is_conversation, |
| messages=[ConversationMessage(**msg) for msg in messages], |
| formatted_output=formatted_output, |
| count=len(messages) |
| ) |
|
|
| except Exception as e: |
| return ExtractConversationFromJsonOutput( |
| success=False, |
| error=str(e) |
| ) |
|
|
|
|
| @mcp_tool( |
| name="json-chatfile", |
| title="从JSON文件提取对话", |
| description="从JSON文件中提取OpenAI格式的对话消息,返回结构化的对话记录", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def extract_conversation_from_file(params: ExtractConversationFromFileInput) -> ExtractConversationFromFileOutput: |
| """ |
| 从JSON文件中提取对话消息 |
| |
| 专门用于处理OpenAI格式的对话JSON,返回结构化的消息列表。 |
| 如果不是对话格式,is_conversation会返回false。 |
| |
| Args: |
| params: 包含文件路径 |
| |
| Returns: |
| ExtractConversationFromFileOutput: 结构化的对话消息 |
| """ |
| core = _get_core() |
|
|
| try: |
| import os |
| if not os.path.exists(params.file_path): |
| return ExtractConversationFromFileOutput( |
| success=False, |
| file_path=params.file_path, |
| error=f"文件不存在: {params.file_path}" |
| ) |
|
|
| messages = core.extract_conversation_from_file(params.file_path) |
| is_conversation = len(messages) > 0 |
|
|
| if is_conversation: |
| import json |
| with open(params.file_path, 'r', encoding='utf-8') as f: |
| json_data = json.load(f) |
| formatted_output = core._format_conversation(json_data) |
| else: |
| formatted_output = "该文件不是对话格式" |
|
|
| return ExtractConversationFromFileOutput( |
| success=True, |
| file_path=params.file_path, |
| is_conversation=is_conversation, |
| messages=[ConversationMessage(**msg) for msg in messages], |
| formatted_output=formatted_output, |
| count=len(messages) |
| ) |
|
|
| except Exception as e: |
| return ExtractConversationFromFileOutput( |
| success=False, |
| file_path=params.file_path, |
| error=str(e) |
| ) |
|
|