lightpdf-aipdf-mcp 0.1.86__py3-none-any.whl → 0.1.88__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -320,6 +320,13 @@ class Converter(BaseApiClient):
320
320
  )
321
321
  # 检查是否为URL路径
322
322
  elif self.file_handler.is_url(file_path):
323
+ # arxiv.org/pdf/特殊处理
324
+ if isinstance(file_path, str) and "arxiv.org/pdf/" in file_path:
325
+ from urllib.parse import urlparse, urlunparse
326
+ url_obj = urlparse(file_path)
327
+ if not url_obj.path.endswith(".pdf"):
328
+ new_path = url_obj.path + ".pdf"
329
+ file_path = urlunparse(url_obj._replace(path=new_path))
323
330
  data["url"] = file_path
324
331
  # 使用JSON方式时添加Content-Type
325
332
  headers["Content-Type"] = "application/json"
@@ -293,7 +293,7 @@ class Editor(BaseApiClient):
293
293
  # 调用edit_pdf方法处理API请求
294
294
  return await self.edit_pdf(file_path, EditType.DECRYPT, {}, password, original_name)
295
295
 
296
- async def add_watermark(
296
+ async def add_text_watermark(
297
297
  self,
298
298
  file_path: str,
299
299
  text: str,
@@ -359,6 +359,53 @@ class Editor(BaseApiClient):
359
359
  # 调用edit_pdf方法处理API请求
360
360
  return await self.edit_pdf(file_path, EditType.ADD_WATERMARK, extra_params, password, original_name)
361
361
 
362
+ async def add_image_watermark(
363
+ self,
364
+ file_path: str,
365
+ image_url: str,
366
+ position: str = "center",
367
+ opacity: float = 0.7,
368
+ range: str = "",
369
+ layout: Optional[str] = None,
370
+ password: Optional[str] = None,
371
+ original_name: Optional[str] = None
372
+ ) -> EditResult:
373
+ """为PDF文件添加图片水印
374
+
375
+ Args:
376
+ file_path: 要添加水印的PDF文件路径
377
+ image_url: 水印图片的URL,必须包含协议(http/https/oss)
378
+ position: 水印位置,如"top", "center", "diagonal"等,默认"center"
379
+ opacity: 透明度,0.0-1.0,默认0.7
380
+ range: 页面范围,例如 "1,3,5-7" 或空字符串表示所有页面
381
+ layout: 布局方式:"on"=在内容上,"under"=在内容下,默认"on"
382
+ password: 文档密码,如果文档受密码保护,则需要提供(可选)
383
+ original_name: 原始文件名(可选)
384
+
385
+ Returns:
386
+ EditResult: 添加图片水印结果
387
+ """
388
+ # 验证输入文件是否为PDF
389
+ if not await self._validate_pdf_file(file_path):
390
+ return EditResult(success=False, file_path=file_path, error_message="非PDF文件", original_name=original_name)
391
+ if not image_url:
392
+ await self.logger.error("水印图片URL不能为空")
393
+ return EditResult(success=False, file_path=file_path, error_message="水印图片URL不能为空", original_name=original_name)
394
+ # 构建API参数
395
+ extra_params = {
396
+ "edit_type": "image",
397
+ "image_url": image_url,
398
+ "position": position,
399
+ "opacity": opacity,
400
+ "range": range
401
+ }
402
+ if layout:
403
+ extra_params["layout"] = layout
404
+ # 记录操作描述
405
+ await self._log_operation("为PDF添加图片水印", f"图片: {image_url}, 位置: {position}, 透明度: {opacity}")
406
+ # 调用edit_pdf方法处理API请求
407
+ return await self.edit_pdf(file_path, EditType.ADD_WATERMARK, extra_params, password, original_name)
408
+
362
409
  async def remove_margin(self, file_path: str, password: Optional[str] = None, original_name: Optional[str] = None) -> EditResult:
363
410
  """去除PDF文件的白边
364
411
 
@@ -523,6 +570,13 @@ class Editor(BaseApiClient):
523
570
  )
524
571
  # 检查是否为URL路径
525
572
  elif self.file_handler.is_url(file_path):
573
+ # arxiv.org/pdf/特殊处理
574
+ if isinstance(file_path, str) and "arxiv.org/pdf/" in file_path:
575
+ from urllib.parse import urlparse, urlunparse
576
+ url_obj = urlparse(file_path)
577
+ if not url_obj.path.endswith(".pdf"):
578
+ new_path = url_obj.path + ".pdf"
579
+ file_path = urlunparse(url_obj._replace(path=new_path))
526
580
  # 使用JSON方式时添加Content-Type
527
581
  headers["Content-Type"] = "application/json"
528
582
  data["url"] = file_path
@@ -580,6 +634,13 @@ class Editor(BaseApiClient):
580
634
  input_item["password"] = password
581
635
  url_inputs.append(input_item)
582
636
  elif self.file_handler.is_url(file_path):
637
+ # arxiv.org/pdf/特殊处理
638
+ if isinstance(file_path, str) and "arxiv.org/pdf/" in file_path:
639
+ from urllib.parse import urlparse, urlunparse
640
+ url_obj = urlparse(file_path)
641
+ if not url_obj.path.endswith(".pdf"):
642
+ new_path = url_obj.path + ".pdf"
643
+ file_path = urlunparse(url_obj._replace(path=new_path))
583
644
  # 对于URL或OSS路径,添加到inputs数组
584
645
  input_item = {"url": file_path}
585
646
  if password:
@@ -19,6 +19,7 @@ import mcp.types as types
19
19
  from .common import BaseResult, Logger, FileHandler
20
20
  from .converter import Converter, ConversionResult
21
21
  from .editor import Editor, EditResult
22
+ from .translator import Translator, TranslateResult
22
23
 
23
24
  # 加载环境变量
24
25
  load_dotenv()
@@ -154,10 +155,10 @@ async def process_edit_file(
154
155
  """处理单个文件编辑"""
155
156
  if edit_type == "decrypt":
156
157
  return await editor.decrypt_pdf(file_path, password, original_name)
157
- elif edit_type == "add_watermark":
158
- return await editor.add_watermark(
158
+ elif edit_type == "add_text_watermark":
159
+ return await editor.add_text_watermark(
159
160
  file_path=file_path,
160
- text=extra_params.get("text", "水印"),
161
+ text=extra_params.get("text", "文本水印"),
161
162
  position=extra_params.get("position", "center"),
162
163
  opacity=extra_params.get("opacity", 1.0),
163
164
  range=extra_params.get("range", ""),
@@ -168,6 +169,17 @@ async def process_edit_file(
168
169
  password=password,
169
170
  original_name=original_name
170
171
  )
172
+ elif edit_type == "add_image_watermark":
173
+ return await editor.add_image_watermark(
174
+ file_path=file_path,
175
+ image_url=extra_params.get("image_url"),
176
+ position=extra_params.get("position", "center"),
177
+ opacity=extra_params.get("opacity", 0.7),
178
+ range=extra_params.get("range", ""),
179
+ layout=extra_params.get("layout", "on"),
180
+ password=password,
181
+ original_name=original_name
182
+ )
171
183
  elif edit_type == "encrypt":
172
184
  return await editor.encrypt_pdf(
173
185
  file_path=file_path,
@@ -266,9 +278,29 @@ async def process_tool_call(
266
278
  """
267
279
  file_handler = FileHandler(logger)
268
280
  editor = Editor(logger, file_handler)
269
-
281
+ # 新增:翻译操作分支
282
+ if operation_config.get("is_translate_operation"):
283
+ translator = Translator(logger, file_handler)
284
+ extra_params = operation_config.get("extra_params", {})
285
+
286
+ results = await process_batch_files(
287
+ file_objects,
288
+ logger,
289
+ lambda file_path, password, original_name: translator.translate_pdf(
290
+ file_path=file_path,
291
+ source=extra_params.get("source", "auto"),
292
+ target=extra_params.get("target"),
293
+ output_type=extra_params.get("output_type", "mono"),
294
+ password=password,
295
+ original_name=original_name
296
+ ),
297
+ "PDF翻译"
298
+ )
299
+
300
+ report_msg = generate_result_report(results)
301
+
270
302
  # 根据操作类型选择不同的处理逻辑
271
- if operation_config.get("is_edit_operation"):
303
+ elif operation_config.get("is_edit_operation"):
272
304
  # 编辑操作
273
305
  edit_type = operation_config.get("edit_type", "")
274
306
  extra_params = operation_config.get("extra_params")
@@ -276,7 +308,8 @@ async def process_tool_call(
276
308
  # 获取操作描述
277
309
  edit_map = {
278
310
  "decrypt": "解密",
279
- "add_watermark": "添加水印",
311
+ "add_text_watermark": "添加文本水印",
312
+ "add_image_watermark": "添加图片水印",
280
313
  "encrypt": "加密",
281
314
  "compress": "压缩",
282
315
  "split": "拆分",
@@ -385,7 +418,7 @@ async def handle_list_tools() -> list[types.Tool]:
385
418
  return [
386
419
  types.Tool(
387
420
  name="convert_document",
388
- description="Document format conversion tool.\n\nPDF can be converted to: DOCX/XLSX/PPTX/Images (including long images)/HTML/TXT (for text extraction)/CSV;\nOther formats can be converted to PDF: DOCX/XLSX/PPTX/Images/CAD/CAJ/OFD.\n\nDoes not support creating files from content",
421
+ description="Document format conversion tool.\n\nPDF can be converted to: DOCX/XLSX/PPTX/Images (including long images)/HTML/TXT (for text extraction)/CSV;\nOther formats can be converted to PDF: DOCX/XLSX/PPTX/Images/CAD/CAJ/OFD.\n\nDoes not support creating files from content.",
389
422
  inputSchema={
390
423
  "type": "object",
391
424
  "properties": {
@@ -396,20 +429,20 @@ async def handle_list_tools() -> list[types.Tool]:
396
429
  "properties": {
397
430
  "path": {
398
431
  "type": "string",
399
- "description": "File URL, must include protocol, supports http/https/oss"
432
+ "description": "File URL, must include protocol, supports http/https/oss."
400
433
  },
401
434
  "password": {
402
435
  "type": "string",
403
- "description": "Document password, required if the document is password-protected"
436
+ "description": "Document password, required if the document is password-protected."
404
437
  },
405
438
  "name": {
406
439
  "type": "string",
407
- "description": "Original filename of the document"
440
+ "description": "Original filename of the document."
408
441
  }
409
442
  },
410
443
  "required": ["path"]
411
444
  },
412
- "description": "List of files to convert, each containing path and optional password"
445
+ "description": "List of files to convert, each containing path and optional password."
413
446
  },
414
447
  "format": {
415
448
  "type": "string",
@@ -420,7 +453,7 @@ async def handle_list_tools() -> list[types.Tool]:
420
453
  "type": "integer",
421
454
  "enum": [0, 1],
422
455
  "default": 0,
423
- "description": "Whether to merge results: 1 = merge all, 0 = separate. Only valid for: PDF to Excel (1: all pages to one sheet, 0: each page to a sheet), PDF to Image (1: merge to long image, 0: each page to an image), Image to PDF (1: all images to one PDF, 0: each image to a PDF)"
456
+ "description": "Whether to merge results: 1 = merge all, 0 = separate. Only valid for: PDF to Excel (1: all pages to one sheet, 0: each page to a sheet), PDF to Image (1: merge to long image, 0: each page to an image), Image to PDF (1: all images to one PDF, 0: each image to a PDF)."
424
457
  }
425
458
  },
426
459
  "required": ["files", "format"]
@@ -509,7 +542,7 @@ async def handle_list_tools() -> list[types.Tool]:
509
542
  }
510
543
  ),
511
544
  types.Tool(
512
- name="add_watermark",
545
+ name="add_text_watermark",
513
546
  description="Add text watermarks to PDF files.",
514
547
  inputSchema={
515
548
  "type": "object",
@@ -521,7 +554,7 @@ async def handle_list_tools() -> list[types.Tool]:
521
554
  "properties": {
522
555
  "path": {
523
556
  "type": "string",
524
- "description": "PDF file URL to add watermark to, must include protocol, supports http/https/oss"
557
+ "description": "PDF file URL to add text watermark to, must include protocol, supports http/https/oss"
525
558
  },
526
559
  "password": {
527
560
  "type": "string",
@@ -534,7 +567,7 @@ async def handle_list_tools() -> list[types.Tool]:
534
567
  },
535
568
  "required": ["path"]
536
569
  },
537
- "description": "List of PDF files to add watermarks to, each containing path and optional password"
570
+ "description": "List of PDF files to add text watermarks to, each containing path and optional password"
538
571
  },
539
572
  "text": {
540
573
  "type": "string",
@@ -542,7 +575,7 @@ async def handle_list_tools() -> list[types.Tool]:
542
575
  },
543
576
  "position": {
544
577
  "type": "string",
545
- "description": "Watermark position: top-left(topleft), top-center(top), top-right(topright), left(left), center(center), right(right), bottom-left(bottomleft), bottom(bottom), bottom-right(bottomright), diagonal(diagonal, -45 degrees), reverse-diagonal(reverse-diagonal, 45 degrees)",
578
+ "description": "Text watermark position: top-left(topleft), top-center(top), top-right(topright), left(left), center(center), right(right), bottom-left(bottomleft), bottom(bottom), bottom-right(bottomright), diagonal(diagonal, -45 degrees), reverse-diagonal(reverse-diagonal, 45 degrees)",
546
579
  "enum": ["topleft", "top", "topright", "left", "center", "right",
547
580
  "bottomleft", "bottom", "bottomright", "diagonal", "reverse-diagonal"],
548
581
  "default": "center"
@@ -580,6 +613,66 @@ async def handle_list_tools() -> list[types.Tool]:
580
613
  "required": ["files", "text", "position"]
581
614
  }
582
615
  ),
616
+ types.Tool(
617
+ name="add_image_watermark",
618
+ description="Add image watermarks to PDF files.",
619
+ inputSchema={
620
+ "type": "object",
621
+ "properties": {
622
+ "files": {
623
+ "type": "array",
624
+ "items": {
625
+ "type": "object",
626
+ "properties": {
627
+ "path": {
628
+ "type": "string",
629
+ "description": "PDF file URL to add image watermark to, must include protocol, supports http/https/oss"
630
+ },
631
+ "password": {
632
+ "type": "string",
633
+ "description": "PDF document password, required if the document is password-protected"
634
+ },
635
+ "name": {
636
+ "type": "string",
637
+ "description": "Original filename of the document"
638
+ }
639
+ },
640
+ "required": ["path"]
641
+ },
642
+ "description": "List of PDF files to add image watermarks to, each containing path and optional password"
643
+ },
644
+ "image_url": {
645
+ "type": "string",
646
+ "description": "Image URL for the watermark, must include protocol, supports http/https/oss"
647
+ },
648
+ "position": {
649
+ "type": "string",
650
+ "description": "Image watermark position: top-left(topleft), top-center(top), top-right(topright), left(left), center(center), right(right), bottom-left(bottomleft), bottom(bottom), bottom-right(bottomright), diagonal(diagonal, -45 degrees), reverse-diagonal(reverse-diagonal, 45 degrees)",
651
+ "enum": ["topleft", "top", "topright", "left", "center", "right",
652
+ "bottomleft", "bottom", "bottomright", "diagonal", "reverse-diagonal"],
653
+ "default": "center"
654
+ },
655
+ "opacity": {
656
+ "type": "number",
657
+ "description": "Opacity, 0.0-1.0",
658
+ "default": 0.7,
659
+ "minimum": 0.0,
660
+ "maximum": 1.0
661
+ },
662
+ "range": {
663
+ "type": "string",
664
+ "description": "Page range, e.g. '1,3,5-7' or '' (empty string or not set) for all pages"
665
+ },
666
+ "layout": {
667
+ "type": "string",
668
+ "description": "Layout position: on top of content(on) or under content(under)",
669
+ "enum": ["on", "under"],
670
+ "default": "on"
671
+ }
672
+ },
673
+ "required": ["files", "image_url", "position"]
674
+ }
675
+ ),
583
676
  types.Tool(
584
677
  name="unlock_pdf",
585
678
  description="Remove password protection from PDF files.",
@@ -892,7 +985,7 @@ async def handle_list_tools() -> list[types.Tool]:
892
985
  ),
893
986
  types.Tool(
894
987
  name="flatten_pdf",
895
- description="Flatten PDF files (convert editable elements such as text, form fields, annotations, and layers into non-editable static content or fixed content)",
988
+ description="Flatten PDF files (convert editable elements such as text, form fields, annotations, and layers into non-editable static content or fixed content).",
896
989
  inputSchema={
897
990
  "type": "object",
898
991
  "properties": {
@@ -953,7 +1046,56 @@ async def handle_list_tools() -> list[types.Tool]:
953
1046
  },
954
1047
  "required": ["files"]
955
1048
  }
956
- )
1049
+ ),
1050
+ types.Tool(
1051
+ name="translate_pdf",
1052
+ description="Translate PDF documents from a source language to a target language. Supports mono (target only) or dual (source/target bilingual) output.",
1053
+ inputSchema={
1054
+ "type": "object",
1055
+ "properties": {
1056
+ "files": {
1057
+ "type": "array",
1058
+ "items": {
1059
+ "type": "object",
1060
+ "properties": {
1061
+ "path": {
1062
+ "type": "string",
1063
+ "description": "PDF file URL, must include protocol, supports http/https/oss."
1064
+ },
1065
+ "password": {
1066
+ "type": "string",
1067
+ "description": "PDF document password, required if the document is password-protected."
1068
+ },
1069
+ "name": {
1070
+ "type": "string",
1071
+ "description": "Original filename of the document."
1072
+ }
1073
+ },
1074
+ "required": ["path"]
1075
+ },
1076
+ "description": "List of PDF files to translate, each containing path and optional password."
1077
+ },
1078
+ "source": {
1079
+ "type": "string",
1080
+ "description": "Source language. Supports 'auto' for automatic detection.",
1081
+ "enum": ["auto", "ar", "bg", "cz", "da", "de", "el", "en", "es", "fi", "fr", "hbs", "hi", "hu", "id", "it", "ja", "ko", "ms", "nl", "no", "pl", "pt", "ru", "sl", "sv", "th", "tr", "vi", "zh", "zh-tw"],
1082
+ "default": "auto"
1083
+ },
1084
+ "target": {
1085
+ "type": "string",
1086
+ "description": "Target language. Must be specified.",
1087
+ "enum": ["ar", "bg", "cz", "da", "de", "el", "en", "es", "fi", "fr", "hbs", "hi", "hu", "id", "it", "ja", "ko", "ms", "nl", "no", "pl", "pt", "ru", "sl", "sv", "th", "tr", "vi", "zh", "zh-tw"]
1088
+ },
1089
+ "output_type": {
1090
+ "type": "string",
1091
+ "description": "Output type: 'mono' for target language only, 'dual' for source/target bilingual output.",
1092
+ "enum": ["mono", "dual"],
1093
+ "default": "mono"
1094
+ }
1095
+ },
1096
+ "required": ["files", "target"]
1097
+ }
1098
+ ),
957
1099
  ]
958
1100
 
959
1101
  @app.call_tool()
@@ -984,11 +1126,16 @@ async def handle_call_tool(name: str, arguments: dict | None) -> list[types.Text
984
1126
  "edit_type": "decrypt", # 编辑类型
985
1127
  "is_edit_operation": True, # 标记为编辑操作
986
1128
  },
987
- "add_watermark": {
988
- "edit_type": "add_watermark", # 编辑类型
1129
+ "add_text_watermark": {
1130
+ "edit_type": "add_text_watermark", # 编辑类型,文本水印
989
1131
  "is_edit_operation": True, # 标记为编辑操作
990
1132
  "param_keys": ["text", "position", "opacity", "range", "layout",
991
- "font_family", "font_size", "font_color"] # 需要从arguments获取的参数
1133
+ "font_family", "font_size", "font_color"] # 需要从arguments获取的参数(文本水印)
1134
+ },
1135
+ "add_image_watermark": {
1136
+ "edit_type": "add_image_watermark",
1137
+ "is_edit_operation": True,
1138
+ "param_keys": ["image_url", "position", "opacity", "range", "layout"]
992
1139
  },
993
1140
  "protect_pdf": {
994
1141
  "edit_type": "encrypt", # 编辑类型
@@ -1028,6 +1175,10 @@ async def handle_call_tool(name: str, arguments: dict | None) -> list[types.Text
1028
1175
  "is_edit_operation": True,
1029
1176
  "param_keys": [] # 不暴露provider
1030
1177
  },
1178
+ "translate_pdf": {
1179
+ "is_translate_operation": True,
1180
+ "param_keys": ["source", "target", "output_type"]
1181
+ },
1031
1182
  }
1032
1183
 
1033
1184
  DEFAULTS = {
@@ -1075,8 +1226,8 @@ async def handle_call_tool(name: str, arguments: dict | None) -> list[types.Text
1075
1226
  if name == "add_page_numbers":
1076
1227
  # 添加页码工具使用"5"作为position默认值
1077
1228
  operation_config["extra_params"][key] = arguments.get(key, DEFAULTS.get("position_page_numbers"))
1078
- elif name == "add_watermark":
1079
- # 添加水印工具使用"center"作为position默认值
1229
+ elif name == "add_text_watermark":
1230
+ # 添加文本水印工具使用"center"作为position默认值
1080
1231
  operation_config["extra_params"][key] = arguments.get(key, DEFAULTS.get("position_watermark"))
1081
1232
  else:
1082
1233
  # 其他工具使用通用默认值
@@ -0,0 +1,94 @@
1
+ from dataclasses import dataclass
2
+ import os
3
+ import httpx
4
+ from typing import Optional, Dict, Any
5
+ from .common import Logger, BaseResult, FileHandler, BaseApiClient
6
+
7
+ @dataclass
8
+ class TranslateResult(BaseResult):
9
+ """翻译结果数据类"""
10
+ pass
11
+
12
+ class Translator(BaseApiClient):
13
+ """PDF文档翻译器"""
14
+ def __init__(self, logger: Logger, file_handler: FileHandler):
15
+ super().__init__(logger, file_handler)
16
+ api_endpoint = os.getenv("API_ENDPOINT", "techsz.aoscdn.com/api")
17
+ self.api_base_url = f"https://{api_endpoint}/tasks/document/transdocument-local"
18
+
19
+ async def translate_pdf(self, file_path: str, source: str, target: str, output_type: str = "mono", password: Optional[str] = None, original_name: Optional[str] = None) -> TranslateResult:
20
+ if not self.api_key:
21
+ await self.logger.error("未找到API_KEY。请在客户端配置API_KEY环境变量。")
22
+ return TranslateResult(success=False, file_path=file_path, error_message="未找到API_KEY", original_name=original_name)
23
+
24
+ # 构建API参数
25
+ extra_params = {
26
+ "source": source or "auto",
27
+ "target": target,
28
+ "output_type": output_type or "mono"
29
+ }
30
+ if password:
31
+ extra_params["password"] = password
32
+ if original_name:
33
+ extra_params["filename"] = os.path.splitext(original_name)[0]
34
+
35
+ async with httpx.AsyncClient(timeout=3600.0) as client:
36
+ task_id = None
37
+ try:
38
+ # 创建翻译任务
39
+ task_id = await self._create_task(client, file_path, extra_params)
40
+ # 等待任务完成
41
+ download_url = await self._wait_for_task(client, task_id, "翻译")
42
+
43
+ await self.logger.log("info", "翻译完成。可通过下载链接获取结果文件。")
44
+ return TranslateResult(
45
+ success=True,
46
+ file_path=file_path,
47
+ error_message=None,
48
+ download_url=download_url,
49
+ original_name=original_name,
50
+ task_id=task_id
51
+ )
52
+ except Exception as e:
53
+ return TranslateResult(
54
+ success=False,
55
+ file_path=file_path,
56
+ error_message=str(e),
57
+ download_url=None,
58
+ original_name=original_name,
59
+ task_id=task_id
60
+ )
61
+
62
+ async def _create_task(self, client: httpx.AsyncClient, file_path: str, extra_params: dict = None) -> str:
63
+ await self.logger.log("info", "正在提交翻译任务...")
64
+ headers = {"X-API-KEY": self.api_key}
65
+ data = {}
66
+ if extra_params:
67
+ data.update(extra_params)
68
+ # 检查是否为OSS路径
69
+ if self.file_handler.is_oss_id(file_path):
70
+ data["resource_id"] = file_path.split("oss_id://")[1]
71
+ headers["Content-Type"] = "application/json"
72
+ response = await client.post(
73
+ self.api_base_url,
74
+ json=data,
75
+ headers=headers
76
+ )
77
+ elif self.file_handler.is_url(file_path):
78
+ data["url"] = file_path
79
+ headers["Content-Type"] = "application/json"
80
+ response = await client.post(
81
+ self.api_base_url,
82
+ json=data,
83
+ headers=headers
84
+ )
85
+ else:
86
+ with open(file_path, "rb") as f:
87
+ files = {"file": f}
88
+ response = await client.post(
89
+ self.api_base_url,
90
+ files=files,
91
+ data=data,
92
+ headers=headers
93
+ )
94
+ return await self._handle_api_response(response, "创建翻译任务")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lightpdf-aipdf-mcp
3
- Version: 0.1.86
3
+ Version: 0.1.88
4
4
  Summary: MCP Server for LightPDF AI-PDF
5
5
  Author: LightPDF Team
6
6
  License: Proprietary
@@ -0,0 +1,10 @@
1
+ lightpdf_aipdf_mcp/__init__.py,sha256=PPnAgpvJLYLVOTxnHDmJAulFnHJD6wuTwS6tRGjqq6s,141
2
+ lightpdf_aipdf_mcp/common.py,sha256=_UO1f6S9Qr_3k6u5iBpdVDpvTK5U-tHEpu9KsDGqV8Y,6635
3
+ lightpdf_aipdf_mcp/converter.py,sha256=f0gS8tAQlJ8uwJUVUmd9nAA4O9m558e9lAT2B_MxmIo,15135
4
+ lightpdf_aipdf_mcp/editor.py,sha256=9teOqi2y2JbjcCI-kUhYpSXL-F75i7Mfr9E20KKyZP0,29909
5
+ lightpdf_aipdf_mcp/server.py,sha256=khv6gJNWx8nhH6gpOu4jdeeL8p7xMPONEv7mAf8oWXQ,59952
6
+ lightpdf_aipdf_mcp/translator.py,sha256=FACnFcnz1zNDdndR3tAgTfDDkfk1rJRRgWorFbiiEUk,3834
7
+ lightpdf_aipdf_mcp-0.1.88.dist-info/METADATA,sha256=AOlJAa2HvSrrcN2I264tvQ5FR3-Gl4Nz7jqo1Ai4Wjs,8119
8
+ lightpdf_aipdf_mcp-0.1.88.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ lightpdf_aipdf_mcp-0.1.88.dist-info/entry_points.txt,sha256=X7TGUe52N4sYH-tYt0YUGApeJgw-efQlZA6uAZmlmr4,63
10
+ lightpdf_aipdf_mcp-0.1.88.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- lightpdf_aipdf_mcp/__init__.py,sha256=PPnAgpvJLYLVOTxnHDmJAulFnHJD6wuTwS6tRGjqq6s,141
2
- lightpdf_aipdf_mcp/common.py,sha256=_UO1f6S9Qr_3k6u5iBpdVDpvTK5U-tHEpu9KsDGqV8Y,6635
3
- lightpdf_aipdf_mcp/converter.py,sha256=f9YuDtOmXBGlMmS3O4Xn3rdWljY9XcNxu0CjftH4s0o,14726
4
- lightpdf_aipdf_mcp/editor.py,sha256=O7wF_HWs5l-IiXLbZYLNYjj1ygo2v4yGJEYMJtn7jpo,26916
5
- lightpdf_aipdf_mcp/server.py,sha256=sHFc2c7gLM6qh5sqbZREynoT53QZDvoXKCNEzWfnC6o,52200
6
- lightpdf_aipdf_mcp-0.1.86.dist-info/METADATA,sha256=jQKNGcg_UD18y2zd1SC4Mms3iGuE0bPW1lPp31tVw5Y,8119
7
- lightpdf_aipdf_mcp-0.1.86.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- lightpdf_aipdf_mcp-0.1.86.dist-info/entry_points.txt,sha256=X7TGUe52N4sYH-tYt0YUGApeJgw-efQlZA6uAZmlmr4,63
9
- lightpdf_aipdf_mcp-0.1.86.dist-info/RECORD,,