lightpdf-aipdf-mcp 0.1.139__py3-none-any.whl → 0.1.141__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.
- lightpdf_aipdf_mcp/common.py +3 -1
- lightpdf_aipdf_mcp/converter.py +10 -2
- lightpdf_aipdf_mcp/server.py +51 -3
- {lightpdf_aipdf_mcp-0.1.139.dist-info → lightpdf_aipdf_mcp-0.1.141.dist-info}/METADATA +1 -1
- {lightpdf_aipdf_mcp-0.1.139.dist-info → lightpdf_aipdf_mcp-0.1.141.dist-info}/RECORD +7 -7
- {lightpdf_aipdf_mcp-0.1.139.dist-info → lightpdf_aipdf_mcp-0.1.141.dist-info}/WHEEL +0 -0
- {lightpdf_aipdf_mcp-0.1.139.dist-info → lightpdf_aipdf_mcp-0.1.141.dist-info}/entry_points.txt +0 -0
lightpdf_aipdf_mcp/common.py
CHANGED
@@ -25,6 +25,7 @@ class Logger:
|
|
25
25
|
self.context = context
|
26
26
|
self.collect_info = collect_info
|
27
27
|
self._info_log = []
|
28
|
+
self._debug = os.getenv("DEBUG")
|
28
29
|
|
29
30
|
async def log(self, level: str, message: str, add_to_result: bool = True):
|
30
31
|
"""记录日志消息"""
|
@@ -40,7 +41,8 @@ class Logger:
|
|
40
41
|
|
41
42
|
mcp_level = level_map.get(level.lower(), "info")
|
42
43
|
|
43
|
-
|
44
|
+
if self._debug:
|
45
|
+
print(f"mcp_level: {mcp_level}, message: {message}", file=sys.stderr)
|
44
46
|
# 直接调用session的send_log_message方法
|
45
47
|
await self.context.session.send_log_message(mcp_level, message)
|
46
48
|
|
lightpdf_aipdf_mcp/converter.py
CHANGED
@@ -173,8 +173,8 @@ class Converter(BaseApiClient):
|
|
173
173
|
await self.logger.error("未找到API_KEY。请在客户端配置API_KEY环境变量。")
|
174
174
|
return ConversionResult(success=False, file_path=file_path, error_message="未找到API_KEY", original_name=original_name)
|
175
175
|
|
176
|
-
# 特殊格式:doc-repair用于去除水印,number-pdf
|
177
|
-
is_special_operation = format in ["doc-repair", "number-pdf", "flatten-pdf", "resize-pdf"]
|
176
|
+
# 特殊格式:doc-repair用于去除水印,number-pdf用于添加页码,pdf-replace-text用于替换文本,输出均为PDF
|
177
|
+
is_special_operation = format in ["doc-repair", "number-pdf", "flatten-pdf", "resize-pdf", "pdf-replace-text"]
|
178
178
|
actual_output_format = "pdf" if is_special_operation else format
|
179
179
|
|
180
180
|
# 检查是否为URL或OSS路径,如果是则跳过文件格式检查
|
@@ -214,6 +214,12 @@ class Converter(BaseApiClient):
|
|
214
214
|
await self.logger.error(error_msg)
|
215
215
|
return ConversionResult(success=False, file_path=file_path, error_message=error_msg, original_name=original_name)
|
216
216
|
|
217
|
+
# 如果是替换文本操作,检查是否PDF文件
|
218
|
+
if format == "pdf-replace-text" and input_format != InputFormat.PDF:
|
219
|
+
error_msg = "替换文本功能仅支持PDF文件"
|
220
|
+
await self.logger.error(error_msg)
|
221
|
+
return ConversionResult(success=False, file_path=file_path, error_message=error_msg, original_name=original_name)
|
222
|
+
|
217
223
|
# 验证输出格式(除去特殊操作外)
|
218
224
|
if not is_special_operation:
|
219
225
|
try:
|
@@ -252,6 +258,8 @@ class Converter(BaseApiClient):
|
|
252
258
|
operation_desc = "展平PDF"
|
253
259
|
elif format == "resize-pdf":
|
254
260
|
operation_desc = "调整PDF大小"
|
261
|
+
elif format == "pdf-replace-text":
|
262
|
+
operation_desc = "替换文本"
|
255
263
|
else:
|
256
264
|
if is_remote_path:
|
257
265
|
operation_desc = f"转换为 {output_format.value.upper()} 格式"
|
lightpdf_aipdf_mcp/server.py
CHANGED
@@ -11,6 +11,9 @@ from urllib.request import url2pathname
|
|
11
11
|
# 第三方库导入
|
12
12
|
from dotenv import load_dotenv
|
13
13
|
|
14
|
+
# 加载环境变量
|
15
|
+
load_dotenv()
|
16
|
+
|
14
17
|
# MCP相关导入
|
15
18
|
from mcp.server.lowlevel import Server, NotificationOptions
|
16
19
|
from mcp.server.models import InitializationOptions
|
@@ -24,9 +27,6 @@ from .translator import Translator, TranslateResult
|
|
24
27
|
from .summarizer import Summarizer
|
25
28
|
from .ocr import OcrClient
|
26
29
|
|
27
|
-
# 加载环境变量
|
28
|
-
load_dotenv()
|
29
|
-
|
30
30
|
# 类型定义
|
31
31
|
T = TypeVar('T', bound=BaseResult)
|
32
32
|
ProcessFunc = Callable[[str], Any]
|
@@ -66,6 +66,7 @@ def generate_result_report(
|
|
66
66
|
}
|
67
67
|
if hasattr(result, "summary") and result.summary is not None:
|
68
68
|
file_info["summary"] = result.summary
|
69
|
+
file_info["instruction"] = "Return the 'summary' field content directly without any modification or additional processing."
|
69
70
|
else:
|
70
71
|
file_info["download_url"] = result.download_url
|
71
72
|
report_obj["success_files"].append(file_info)
|
@@ -444,6 +445,8 @@ async def process_tool_call(
|
|
444
445
|
operation_desc = "添加页码"
|
445
446
|
elif format == "flatten-pdf":
|
446
447
|
operation_desc = "展平PDF"
|
448
|
+
elif format == "pdf-replace-text":
|
449
|
+
operation_desc = "替换文本"
|
447
450
|
else:
|
448
451
|
operation_desc = f"转换为 {format} 格式"
|
449
452
|
|
@@ -1159,6 +1162,46 @@ async def handle_list_tools() -> list[types.Tool]:
|
|
1159
1162
|
"required": ["files"]
|
1160
1163
|
}
|
1161
1164
|
),
|
1165
|
+
types.Tool(
|
1166
|
+
name="replace_text",
|
1167
|
+
description="Replace or delete text in PDF files. When new_text is empty, the old_text will be deleted from the PDF.",
|
1168
|
+
inputSchema={
|
1169
|
+
"type": "object",
|
1170
|
+
"properties": {
|
1171
|
+
"files": {
|
1172
|
+
"type": "array",
|
1173
|
+
"items": {
|
1174
|
+
"type": "object",
|
1175
|
+
"properties": {
|
1176
|
+
"path": {
|
1177
|
+
"type": "string",
|
1178
|
+
"description": "PDF file URL to replace text in, must include protocol, supports http/https/oss"
|
1179
|
+
},
|
1180
|
+
"password": {
|
1181
|
+
"type": "string",
|
1182
|
+
"description": "PDF document password, required if the document is password-protected"
|
1183
|
+
},
|
1184
|
+
"name": {
|
1185
|
+
"type": "string",
|
1186
|
+
"description": "Original filename of the document"
|
1187
|
+
}
|
1188
|
+
},
|
1189
|
+
"required": ["path"]
|
1190
|
+
},
|
1191
|
+
"description": "List of PDF files to replace text in, each containing path and optional password"
|
1192
|
+
},
|
1193
|
+
"old_text": {
|
1194
|
+
"type": "string",
|
1195
|
+
"description": "The text to be replaced or deleted"
|
1196
|
+
},
|
1197
|
+
"new_text": {
|
1198
|
+
"type": "string",
|
1199
|
+
"description": "The replacement text. If empty, the old_text will be deleted"
|
1200
|
+
}
|
1201
|
+
},
|
1202
|
+
"required": ["files", "old_text", "new_text"]
|
1203
|
+
}
|
1204
|
+
),
|
1162
1205
|
types.Tool(
|
1163
1206
|
name="create_pdf",
|
1164
1207
|
description="Create a PDF file from LaTeX source code string only. File upload is NOT supported. If you want to convert a TEX file to PDF, please use the convert_document tool instead. This tool only accepts pure LaTeX code as input.",
|
@@ -1344,6 +1387,11 @@ async def handle_call_tool(name: str, arguments: dict | None) -> list[types.Text
|
|
1344
1387
|
"is_edit_operation": False,
|
1345
1388
|
"param_keys": ["page_size", "resolution"]
|
1346
1389
|
},
|
1390
|
+
"replace_text": {
|
1391
|
+
"format": "pdf-replace-text",
|
1392
|
+
"is_edit_operation": False,
|
1393
|
+
"param_keys": ["old_text", "new_text"]
|
1394
|
+
},
|
1347
1395
|
"unlock_pdf": {
|
1348
1396
|
"edit_type": "decrypt", # 编辑类型
|
1349
1397
|
"is_edit_operation": True, # 标记为编辑操作
|
@@ -1,13 +1,13 @@
|
|
1
1
|
lightpdf_aipdf_mcp/__init__.py,sha256=PPnAgpvJLYLVOTxnHDmJAulFnHJD6wuTwS6tRGjqq6s,141
|
2
|
-
lightpdf_aipdf_mcp/common.py,sha256=
|
3
|
-
lightpdf_aipdf_mcp/converter.py,sha256=
|
2
|
+
lightpdf_aipdf_mcp/common.py,sha256=T4WKhtoWvDEosoU36ryZ-7IS62iNm_TL8H_jo6nFf7c,9214
|
3
|
+
lightpdf_aipdf_mcp/converter.py,sha256=r8iO5R5vLNNKWdb6WSnwzTwwmp2TvgLXSIvvA4y___o,15336
|
4
4
|
lightpdf_aipdf_mcp/create_pdf.py,sha256=oALIhOBo60D3Gu_li7d7FF0COhFfSTM-BJpc63r9iAs,2465
|
5
5
|
lightpdf_aipdf_mcp/editor.py,sha256=BR-sWW9L7tybEPOhdc8W-uwdBoom19EPTmGDvy_2gMc,27941
|
6
6
|
lightpdf_aipdf_mcp/ocr.py,sha256=IyzxisA6qtXcGTHZofpUYXYDdcIjUaaHcVUKpM7DH9A,2832
|
7
|
-
lightpdf_aipdf_mcp/server.py,sha256=
|
7
|
+
lightpdf_aipdf_mcp/server.py,sha256=gLzV_td5TVkt2bzTvJAFyDiEgJSiAWh4RtJJ-2G4m5c,77622
|
8
8
|
lightpdf_aipdf_mcp/summarizer.py,sha256=2QMMgo_xxlEDSd_STPh7-1lBc4VRsL4SPSTijJPyb3I,5456
|
9
9
|
lightpdf_aipdf_mcp/translator.py,sha256=nuZa4FpsA0xeRWAEGqSPIM55aJuazJX1m32uajowo7I,2778
|
10
|
-
lightpdf_aipdf_mcp-0.1.
|
11
|
-
lightpdf_aipdf_mcp-0.1.
|
12
|
-
lightpdf_aipdf_mcp-0.1.
|
13
|
-
lightpdf_aipdf_mcp-0.1.
|
10
|
+
lightpdf_aipdf_mcp-0.1.141.dist-info/METADATA,sha256=kYlwLqSPgIdI5O4-IE3y14MOdUlbGcHSUAJBXjpgxFE,8120
|
11
|
+
lightpdf_aipdf_mcp-0.1.141.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
12
|
+
lightpdf_aipdf_mcp-0.1.141.dist-info/entry_points.txt,sha256=X7TGUe52N4sYH-tYt0YUGApeJgw-efQlZA6uAZmlmr4,63
|
13
|
+
lightpdf_aipdf_mcp-0.1.141.dist-info/RECORD,,
|
File without changes
|
{lightpdf_aipdf_mcp-0.1.139.dist-info → lightpdf_aipdf_mcp-0.1.141.dist-info}/entry_points.txt
RENAMED
File without changes
|