lightpdf-aipdf-mcp 0.1.41__py3-none-any.whl → 0.1.43__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.
@@ -57,12 +57,12 @@ class FileHandler:
57
57
  @staticmethod
58
58
  def is_url(path: str) -> bool:
59
59
  """检查路径是否为URL"""
60
- return path.startswith(("http://", "https://"))
60
+ return path.startswith(("http://", "https://", "oss://"))
61
61
 
62
62
  @staticmethod
63
- def is_oss_path(path: str) -> bool:
64
- """检查路径是否为OSS路径"""
65
- return path.startswith("oss://")
63
+ def is_oss_id(path: str) -> bool:
64
+ """检查路径是否为OSS ID"""
65
+ return path.startswith("oss_id://")
66
66
 
67
67
  @staticmethod
68
68
  def get_file_extension(file_path: str) -> str:
@@ -101,7 +101,7 @@ class FileHandler:
101
101
  bool: 文件是否存在
102
102
  """
103
103
  is_url = self.is_url(file_path)
104
- is_oss = self.is_oss_path(file_path)
104
+ is_oss = self.is_oss_id(file_path)
105
105
 
106
106
  # 对于URL或OSS路径,假设它们是有效的
107
107
  if is_url or is_oss:
@@ -172,7 +172,7 @@ class Converter(BaseApiClient):
172
172
  actual_output_format = "pdf" if is_special_operation else format
173
173
 
174
174
  # 检查是否为URL或OSS路径,如果是则跳过文件格式检查
175
- is_remote_path = self.file_handler.is_url(file_path) or self.file_handler.is_oss_path(file_path)
175
+ is_remote_path = self.file_handler.is_url(file_path) or self.file_handler.is_oss_id(file_path)
176
176
 
177
177
  if not is_remote_path:
178
178
  # 只对本地文件进行格式验证
@@ -295,9 +295,9 @@ class Converter(BaseApiClient):
295
295
  data.update(extra_params)
296
296
 
297
297
  # 检查是否为OSS路径
298
- if self.file_handler.is_oss_path(file_path):
298
+ if self.file_handler.is_oss_id(file_path):
299
299
  # OSS路径处理方式,与URL类似,但提取resource_id
300
- data["resource_id"] = file_path.split("oss://")[1]
300
+ data["resource_id"] = file_path.split("oss_id://")[1]
301
301
  # 使用JSON方式时添加Content-Type
302
302
  headers["Content-Type"] = "application/json"
303
303
  response = await client.post(
@@ -41,7 +41,7 @@ class Editor(BaseApiClient):
41
41
  bool: 如果是PDF文件则返回True,否则返回False
42
42
  """
43
43
  # 对于URL或OSS路径,跳过文件格式检查
44
- if self.file_handler.is_url(file_path) or self.file_handler.is_oss_path(file_path):
44
+ if self.file_handler.is_url(file_path) or self.file_handler.is_oss_id(file_path):
45
45
  return True
46
46
 
47
47
  input_format = self.file_handler.get_input_format(file_path)
@@ -433,11 +433,11 @@ class Editor(BaseApiClient):
433
433
  data.update(extra_params)
434
434
 
435
435
  # 检查是否为OSS路径
436
- if self.file_handler.is_oss_path(file_path):
437
- # OSS路径处理方式,与URL类似,但提取resource_id
438
- data["resource_id"] = file_path.split("oss://")[1]
436
+ if self.file_handler.is_oss_id(file_path):
439
437
  # 使用JSON方式时添加Content-Type
440
438
  headers["Content-Type"] = "application/json"
439
+ # OSS路径处理方式,与URL类似,但提取resource_id
440
+ data["resource_id"] = file_path.split("oss_id://")[1]
441
441
  response = await client.post(
442
442
  self.api_base_url,
443
443
  json=data,
@@ -445,9 +445,9 @@ class Editor(BaseApiClient):
445
445
  )
446
446
  # 检查是否为URL路径
447
447
  elif self.file_handler.is_url(file_path):
448
- data["url"] = file_path
449
448
  # 使用JSON方式时添加Content-Type
450
449
  headers["Content-Type"] = "application/json"
450
+ data["url"] = file_path
451
451
  response = await client.post(
452
452
  self.api_base_url,
453
453
  json=data,
@@ -492,15 +492,15 @@ class Editor(BaseApiClient):
492
492
 
493
493
  for i, file_path in enumerate(file_paths):
494
494
  # 检查是否为URL或OSS路径
495
- if self.file_handler.is_url(file_path):
496
- # 对于URL或OSS路径,添加到inputs数组
497
- input_item = {"url": file_path}
495
+ if self.file_handler.is_oss_id(file_path):
496
+ # 对于OSS路径,添加到inputs数组
497
+ input_item = {"resource_id": file_path.split("oss_id://")[1]}
498
498
  if password:
499
499
  input_item["password"] = password
500
500
  url_inputs.append(input_item)
501
- elif self.file_handler.is_oss_path(file_path):
502
- # 对于OSS路径,添加到inputs数组
503
- input_item = {"resource_id": file_path.split("oss://")[1]}
501
+ elif self.file_handler.is_url(file_path):
502
+ # 对于URL或OSS路径,添加到inputs数组
503
+ input_item = {"url": file_path}
504
504
  if password:
505
505
  input_item["password"] = password
506
506
  url_inputs.append(input_item)
@@ -3,6 +3,7 @@
3
3
  import asyncio
4
4
  import os
5
5
  import sys
6
+ import argparse
6
7
  from typing import List, Dict, Any, Callable, TypeVar, Optional, Union
7
8
 
8
9
  # 第三方库导入
@@ -875,19 +876,71 @@ async def main():
875
876
  except Exception as e:
876
877
  print("LightPDF AI-PDF MCP Server (版本信息获取失败)", file=sys.stderr)
877
878
 
878
- import mcp.server.stdio as stdio
879
+ # 解析命令行参数
880
+ parser = argparse.ArgumentParser(description="LightPDF AI-PDF MCP Server")
881
+ parser.add_argument("-p", "--port", type=int, default=0, help="指定SSE服务器的端口号,如果提供则使用SSE模式,否则使用stdio模式")
882
+ args = parser.parse_args()
879
883
 
880
- async with stdio.stdio_server() as (read_stream, write_stream):
881
- await app.run(
882
- read_stream,
883
- write_stream,
884
- app.create_initialization_options(
885
- notification_options=NotificationOptions()
884
+ initialization_options = app.create_initialization_options(
885
+ notification_options=NotificationOptions()
886
+ )
887
+
888
+ if args.port:
889
+ from mcp.server.sse import SseServerTransport
890
+ from starlette.applications import Starlette
891
+ from starlette.routing import Mount, Route
892
+ import uvicorn
893
+
894
+ # 使用SSE服务器
895
+ print(f"启动SSE服务器,端口号:{args.port}", file=sys.stderr)
896
+
897
+ # 创建SSE传输
898
+ transport = SseServerTransport("/messages/")
899
+
900
+ # 定义SSE连接处理函数
901
+ async def handle_sse(request):
902
+ async with transport.connect_sse(
903
+ request.scope, request.receive, request._send
904
+ ) as streams:
905
+ await app.run(
906
+ streams[0], streams[1], initialization_options
907
+ )
908
+
909
+ # 创建Starlette应用
910
+ sse_app = Starlette(routes=[
911
+ Route("/sse/", endpoint=handle_sse),
912
+ Mount("/messages/", app=transport.handle_post_message),
913
+ ])
914
+
915
+ # 使用异步方式启动服务器
916
+ server = uvicorn.Server(uvicorn.Config(
917
+ app=sse_app,
918
+ host="0.0.0.0",
919
+ port=args.port,
920
+ log_level="warning"
921
+ ))
922
+ await server.serve()
923
+ else:
924
+ import mcp.server.stdio as stdio
925
+
926
+ # 使用stdio服务器
927
+ print("启动stdio服务器", file=sys.stderr)
928
+ async with stdio.stdio_server() as (read_stream, write_stream):
929
+ await app.run(
930
+ read_stream,
931
+ write_stream,
932
+ initialization_options
886
933
  )
887
- )
888
934
 
889
935
  def cli_main():
890
- asyncio.run(main())
936
+ try:
937
+ asyncio.run(main())
938
+ except KeyboardInterrupt:
939
+ print("服务器被用户中断", file=sys.stderr)
940
+ sys.exit(0)
941
+ except Exception as e:
942
+ print(f"服务器发生错误: {e}", file=sys.stderr)
943
+ sys.exit(1)
891
944
 
892
945
  if __name__ == "__main__":
893
946
  cli_main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lightpdf-aipdf-mcp
3
- Version: 0.1.41
3
+ Version: 0.1.43
4
4
  Summary: MCP Server for LightPDF AI-PDF
5
5
  Author: LightPDF Team
6
6
  License: Proprietary
@@ -8,9 +8,11 @@ Requires-Python: >=3.8
8
8
  Requires-Dist: httpx
9
9
  Requires-Dist: httpx-sse
10
10
  Requires-Dist: mcp
11
+ Requires-Dist: mcp[cli]
11
12
  Requires-Dist: pydantic
12
13
  Requires-Dist: pydantic-settings
13
14
  Requires-Dist: python-dotenv
15
+ Requires-Dist: starlette
14
16
  Requires-Dist: uvicorn
15
17
  Description-Content-Type: text/markdown
16
18
 
@@ -0,0 +1,9 @@
1
+ lightpdf_aipdf_mcp/__init__.py,sha256=PPnAgpvJLYLVOTxnHDmJAulFnHJD6wuTwS6tRGjqq6s,141
2
+ lightpdf_aipdf_mcp/common.py,sha256=k0oNIKLzqo15UUJAkKJjYZBByLdBGpUPCV59FiqEgcY,6574
3
+ lightpdf_aipdf_mcp/converter.py,sha256=MxjO1yqMqfOQ9B696IyjRbtB3oZpemtD7x8arz52zoc,13312
4
+ lightpdf_aipdf_mcp/editor.py,sha256=CkL5mCM7CSUGD4ZAMoRdgBr3xBpJ-7bEC8InCip5q9A,22802
5
+ lightpdf_aipdf_mcp/server.py,sha256=xErltv5YkV8j3Ja5cm_KgJsc9qqnyCC7RTYs1Id9tWI,37652
6
+ lightpdf_aipdf_mcp-0.1.43.dist-info/METADATA,sha256=0SKzho1zsef_Ar44QCr2aREq7s9R49kfl1FPQRgYZTg,7928
7
+ lightpdf_aipdf_mcp-0.1.43.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ lightpdf_aipdf_mcp-0.1.43.dist-info/entry_points.txt,sha256=X7TGUe52N4sYH-tYt0YUGApeJgw-efQlZA6uAZmlmr4,63
9
+ lightpdf_aipdf_mcp-0.1.43.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- lightpdf_aipdf_mcp/__init__.py,sha256=PPnAgpvJLYLVOTxnHDmJAulFnHJD6wuTwS6tRGjqq6s,141
2
- lightpdf_aipdf_mcp/common.py,sha256=zhd_XxO7cBiQ7A6fc1JJjcpJfRWCQBi3pfBSsrBRusg,6568
3
- lightpdf_aipdf_mcp/converter.py,sha256=SbP5CpDn1suoq9QSApw6kgqJXEc4gwF7Po3oLo5namg,13313
4
- lightpdf_aipdf_mcp/editor.py,sha256=6ELqub8uOW6kwkVz52YdFUyDmkMsN1BkTApSw6Bi-lg,22802
5
- lightpdf_aipdf_mcp/server.py,sha256=jXAcfLWhef5E3cle28bytDTTuMiwTMYAglbAFVF6Wlw,35737
6
- lightpdf_aipdf_mcp-0.1.41.dist-info/METADATA,sha256=EsB0LkJG393OYqZbfO-DzcOC0JGBujmuAx2C6sWbxGk,7879
7
- lightpdf_aipdf_mcp-0.1.41.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- lightpdf_aipdf_mcp-0.1.41.dist-info/entry_points.txt,sha256=X7TGUe52N4sYH-tYt0YUGApeJgw-efQlZA6uAZmlmr4,63
9
- lightpdf_aipdf_mcp-0.1.41.dist-info/RECORD,,