feat(file_tools): 添加解析JSON或文本文件的新工具
新增 parse_json 工具,用于读取 txt 或 json 文件内容并智能解析。 工具优先尝试将内容解析为JSON,返回结构化数据;若解析失败则作为纯文本返回。 同时更新项目版本号至 0.1.3。
This commit is contained in:
@@ -120,6 +120,24 @@ tools: List[Tool] = [
|
||||
},
|
||||
"required": ["file_path"]
|
||||
}
|
||||
),
|
||||
Tool(
|
||||
name="parse_json",
|
||||
description="读取txt或json文件内容,优先按JSON解析并返回结构化数据",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"content_base64": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"file_path": {"type": "string"}
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
@@ -430,6 +448,49 @@ def _build_path_data_uri(arguments: Dict[str, Any]) -> str:
|
||||
return _build_data_uri(data, mime_type)
|
||||
|
||||
|
||||
def _build_txt_or_json_result(data: bytes, name: Optional[str]) -> str:
|
||||
text = data.decode("utf-8-sig")
|
||||
try:
|
||||
parsed = json.loads(text)
|
||||
return json.dumps(
|
||||
{
|
||||
"type": "json",
|
||||
"name": name,
|
||||
"data": parsed
|
||||
},
|
||||
ensure_ascii=False
|
||||
)
|
||||
except json.JSONDecodeError:
|
||||
return json.dumps(
|
||||
{
|
||||
"type": "text",
|
||||
"name": name,
|
||||
"data": text
|
||||
},
|
||||
ensure_ascii=False
|
||||
)
|
||||
|
||||
|
||||
async def _parse_json(arguments: Dict[str, Any]) -> str:
|
||||
raw_file_path = str(arguments.get("file_path", ""))
|
||||
file_path = raw_file_path.strip().strip("`").strip()
|
||||
if _is_url(file_path):
|
||||
async with httpx.AsyncClient(follow_redirects=True, timeout=20) as client:
|
||||
response = await client.get(file_path)
|
||||
response.raise_for_status()
|
||||
name = Path(urlparse(file_path).path).name or None
|
||||
return _build_txt_or_json_result(response.content, name)
|
||||
|
||||
if file_path and file_path != arguments.get("file_path"):
|
||||
arguments = dict(arguments)
|
||||
arguments["file_path"] = file_path
|
||||
|
||||
file_info, data, _ = _extract_file_payload(arguments)
|
||||
if data is None:
|
||||
raise ValueError("missing file content")
|
||||
return _build_txt_or_json_result(data, file_info.get("name"))
|
||||
|
||||
|
||||
async def _build_url_data_uri(arguments: Dict[str, Any]) -> str:
|
||||
url = arguments.get("url")
|
||||
if not url:
|
||||
@@ -519,6 +580,8 @@ async def handle_call_tool(name: str, arguments: Dict[str, Any]) -> List[TextCon
|
||||
if not file_path:
|
||||
raise ValueError("missing file_path")
|
||||
result = await asyncio.to_thread(_upload_file_to_minio_sync, file_path)
|
||||
elif name == "parse_json":
|
||||
result = await _parse_json(arguments)
|
||||
else:
|
||||
raise ValueError(f"unknown tool name: {name}")
|
||||
return [TextContent(type="text", text=result)]
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "lzwcai-file-tools-mcp"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
description = "File tools MCP server"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
|
||||
Reference in New Issue
Block a user