mcp-query-table 0.3.2__py3-none-any.whl → 0.3.3__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.
@@ -1 +1 @@
1
- __version__ = "0.3.2"
1
+ __version__ = "0.3.3"
mcp_query_table/enums.py CHANGED
@@ -26,3 +26,4 @@ class Provider(Enum):
26
26
  Nami = '纳米搜索' # 360 纳米搜索
27
27
  YuanBao = '腾讯元宝' # 腾讯元宝
28
28
  BaiDu = '百度AI搜索' # 百度AI搜索
29
+ # YiYan = '文心一言' # 百度文心一言
@@ -5,6 +5,7 @@
5
5
  """
6
6
  import json
7
7
 
8
+ from loguru import logger
8
9
  from playwright.async_api import Page
9
10
 
10
11
  import mcp_query_table
@@ -66,6 +67,7 @@ async def on_route(route):
66
67
  async def chat(page: Page,
67
68
  prompt: str,
68
69
  create: bool,
70
+ files: list[str],
69
71
  ) -> str:
70
72
  if not page.url.startswith(_PAGE0_):
71
73
  create = True
@@ -73,6 +75,10 @@ async def chat(page: Page,
73
75
  if create:
74
76
  await page.goto(_PAGE0_)
75
77
 
78
+ if len(files) > 0:
79
+ # TODO
80
+ logger.warning("抱歉,百度AI搜索的上传文件功能未突破")
81
+
76
82
  await page.route(_PAGE1_, on_route)
77
83
  async with page.expect_response(_PAGE1_, timeout=mcp_query_table.TIMEOUT) as response_info:
78
84
  await page.locator("#chat-input-box").fill(prompt)
@@ -6,11 +6,12 @@ import json
6
6
  from playwright.async_api import Page
7
7
 
8
8
  import mcp_query_table
9
- from mcp_query_table.tool import GlobalVars
9
+ from mcp_query_table.tool import GlobalVars, is_image
10
10
 
11
11
  _PAGE0_ = "https://www.n.cn"
12
12
  _PAGE1_ = "https://www.n.cn/search"
13
- _PAGE2_ = "https://www.n.cn/api/common/chat/v2"
13
+ _PAGE2_ = "https://www.n.cn/api/common/chat/v2" # 对话
14
+ _PAGE3_ = "https://www.n.cn/api/image/upload" # 上传图片
14
15
 
15
16
  G = GlobalVars()
16
17
 
@@ -48,7 +49,7 @@ def read_event_stream(text):
48
49
 
49
50
 
50
51
  async def on_response(response):
51
- if response == _PAGE2_:
52
+ if response.url == _PAGE2_:
52
53
  # print("on_response", response.url)
53
54
  text = await response.text()
54
55
  G.set_text(read_event_stream(text))
@@ -57,14 +58,43 @@ async def on_response(response):
57
58
  async def chat(page: Page,
58
59
  prompt: str,
59
60
  create: bool,
61
+ files: list[str],
60
62
  ) -> str:
63
+ """
64
+
65
+ Parameters
66
+ ----------
67
+ page : playwright.async_api.Page
68
+ 页面
69
+ prompt : str
70
+ 问题
71
+ create : bool
72
+ 是否创建新的对话
73
+ files : list[str] | None
74
+ 上传的文件列表。目前仅支持上传图片
75
+
76
+ Returns
77
+ -------
78
+ str
79
+ 回答
80
+ """
61
81
  if not create:
62
82
  if not page.url.startswith(_PAGE1_):
63
83
  create = True
84
+ if len(files) > 0:
85
+ create = True
86
+
87
+ for file in files:
88
+ assert is_image(file), f"仅支持上传图片,{file}不是图片"
64
89
 
65
90
  if create:
66
- await page.goto(_PAGE0_)
67
91
  name = "输入任何问题"
92
+
93
+ await page.goto(_PAGE0_)
94
+ if len(files) > 0:
95
+ # 只能在新会话中上传文件
96
+ async with page.expect_response(_PAGE3_, timeout=mcp_query_table.TIMEOUT) as response_info:
97
+ await page.locator("input[type=\"file\"]").set_input_files(files)
68
98
  else:
69
99
  name = "提出后续问题,Enter发送,Shift+Enter 换行"
70
100
 
@@ -2,14 +2,16 @@
2
2
  腾讯元宝
3
3
  """
4
4
  import json
5
+ import re
5
6
 
6
7
  from playwright.async_api import Page
7
8
 
8
9
  import mcp_query_table
9
- from mcp_query_table.tool import GlobalVars
10
+ from mcp_query_table.tool import GlobalVars, is_image
10
11
 
11
12
  _PAGE0_ = "https://yuanbao.tencent.com/"
12
13
  _PAGE1_ = "https://yuanbao.tencent.com/api/chat"
14
+ _PAGE2_ = "https://yuanbao.tencent.com/api/resource/genUploadInfo"
13
15
 
14
16
  G = GlobalVars()
15
17
 
@@ -65,6 +67,7 @@ async def on_route(route):
65
67
  async def chat(page: Page,
66
68
  prompt: str,
67
69
  create: bool,
70
+ files: list[str]
68
71
  ) -> str:
69
72
  if not page.url.startswith(_PAGE0_):
70
73
  create = True
@@ -72,6 +75,26 @@ async def chat(page: Page,
72
75
  if create:
73
76
  await page.goto(_PAGE0_)
74
77
 
78
+ if len(files) > 0:
79
+ is_img, is_doc = False, False
80
+ for f in files:
81
+ if is_image(f):
82
+ is_img = True
83
+ else:
84
+ is_doc = True
85
+ assert is_img ^ is_doc, "不能同时包含图片和文档"
86
+
87
+ # 点击上传文件按钮,才会出现上传文件的input
88
+ await page.get_by_role("button").filter(has_text=re.compile(r"^$")).last.click()
89
+
90
+ # 上传文件
91
+ async with page.expect_response(_PAGE2_, timeout=mcp_query_table.TIMEOUT) as response_info:
92
+ if is_img:
93
+ await page.locator("input[type=\"file\"]").nth(-2).set_input_files(files)
94
+ else:
95
+ await page.locator("input[type=\"file\"]").last.set_input_files(files)
96
+
97
+ # 提问
75
98
  await page.route(f"{_PAGE1_}/*", on_route)
76
99
  async with page.expect_response(f"{_PAGE1_}/*", timeout=mcp_query_table.TIMEOUT) as response_info:
77
100
  textbox = page.locator(".ql-editor")
mcp_query_table/server.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Annotated, Optional
1
+ from typing import Annotated, Optional, List
2
2
 
3
3
  from loguru import logger
4
4
  from mcp.server.fastmcp import FastMCP
@@ -29,9 +29,9 @@ class QueryServer:
29
29
  if self.format == 'json':
30
30
  return df.to_json(force_ascii=False, indent=2)
31
31
 
32
- async def chat(self, prompt: str, create: bool, provider: Provider):
32
+ async def chat(self, prompt: str, create: bool, files: List[str], provider: Provider):
33
33
  page = await self.browser.get_page()
34
- txt = await qt_chat(page, prompt, create, provider)
34
+ txt = await qt_chat(page, prompt, create, files, provider)
35
35
  self.browser.release_page(page)
36
36
  return txt
37
37
 
@@ -57,10 +57,11 @@ async def query(
57
57
  async def chat(
58
58
  prompt: Annotated[str, Field(description="提示词。如:`9.9大还是9.11大?`")],
59
59
  create: Annotated[bool, Field(default=False, description="是否创建新对话")],
60
+ files: Annotated[List[str], Field(default=None, description="上传的文件列表。不同网站支持程度不同")],
60
61
  provider: Annotated[
61
62
  Provider, Field(default=Provider.Nami, description="提供商。支持`纳米搜索`、`腾讯元宝`、`百度AI搜索`")]
62
63
  ) -> str:
63
- return await qsv.chat(prompt, create, provider)
64
+ return await qsv.chat(prompt, create, files, provider)
64
65
 
65
66
 
66
67
  def serve(format, cdp_endpoint, executable_path, transport, host, port):
mcp_query_table/tool.py CHANGED
@@ -230,6 +230,7 @@ async def chat(
230
230
  page: Page,
231
231
  prompt: str = "9.9大还是9.11大?",
232
232
  create: bool = False,
233
+ files: list[str] | None = None,
233
234
  provider: Provider = Provider.Nami) -> str:
234
235
  """大语言对话
235
236
 
@@ -241,6 +242,8 @@ async def chat(
241
242
  对话内容, by default "9.9大还是9.11大?"
242
243
  create : bool, optional
243
244
  是否创建新对话, by default False
245
+ files : list[str] | None, optional
246
+ 上传的文件列表。不同网站支持程度不同
244
247
  provider : Provider, optional
245
248
  提供商, by default Provider.N
246
249
 
@@ -250,14 +253,25 @@ async def chat(
250
253
  对话结果
251
254
 
252
255
  """
256
+ # 空列表转None
257
+ if files is None:
258
+ files = []
259
+
253
260
  if provider == Provider.Nami:
254
261
  from mcp_query_table.providers.n import chat
255
- return await chat(page, prompt, create)
262
+ return await chat(page, prompt, create, files)
256
263
  if provider == Provider.YuanBao:
257
264
  from mcp_query_table.providers.yuanbao import chat
258
- return await chat(page, prompt, create)
265
+ return await chat(page, prompt, create, files)
259
266
  if provider == Provider.BaiDu:
260
267
  from mcp_query_table.providers.baidu import chat
261
- return await chat(page, prompt, create)
268
+ return await chat(page, prompt, create, files)
262
269
 
263
270
  raise ValueError(f"未支持的提供商:{provider}")
271
+
272
+
273
+ def is_image(path: str) -> bool:
274
+ """判断是否是图片文件"""
275
+ img_ext = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
276
+ ext = Path(path).suffix.lower()
277
+ return ext in img_ext
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp_query_table
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: query table from website, support MCP
5
5
  Author-email: wukan <wu-kan@163.com>
6
6
  License: MIT License
@@ -132,7 +132,8 @@ if __name__ == '__main__':
132
132
 
133
133
  确保可以在控制台中执行`python -m mcp_query_table -h`。如果不能,可能要先`pip install mcp_query_table`
134
134
 
135
- 在`Cline`中可以配置如下。其中`command`是`python`的绝对路径,`executable_path`是`Chrome`的绝对路径。
135
+ 在`Cline`中可以配置如下。其中`command`是`python`的绝对路径,`executable_path`是`Chrome`的绝对路径,`timeout`是超时时间,单位为秒。
136
+ 在各`AI`平台中由于返回时间常需1分钟以上,所以需要设置大的超时时间。
136
137
 
137
138
  ### STDIO方式
138
139
 
@@ -140,6 +141,7 @@ if __name__ == '__main__':
140
141
  {
141
142
  "mcpServers": {
142
143
  "mcp_query_table": {
144
+ "timeout": 300,
143
145
  "command": "D:\\Users\\Kan\\miniconda3\\envs\\py312\\python.exe",
144
146
  "args": [
145
147
  "-m",
@@ -170,6 +172,7 @@ python -m mcp_query_table --format markdown --transport sse --port 8000
170
172
  {
171
173
  "mcpServers": {
172
174
  "mcp_query_table": {
175
+ "timeout": 300,
173
176
  "url": "http://127.0.0.1:8000/sse"
174
177
  }
175
178
  }
@@ -182,8 +185,8 @@ python -m mcp_query_table --format markdown --transport sse --port 8000
182
185
  npx @modelcontextprotocol/inspector python -m mcp_query_table --format markdown
183
186
  ```
184
187
 
185
- 打开浏览器并翻页是一个比较耗时的操作,会导致`MCP Inspector`页面超时,可以`http://localhost:5173/?timeout=600000`
186
- 表示超时时间为600
188
+ 打开浏览器并翻页是一个比较耗时的操作,会导致`MCP Inspector`页面超时,可以`http://localhost:5173/?timeout=300000`
189
+ 表示超时时间为300
187
190
 
188
191
  第一次尝试编写`MCP`项目,可能会有各种问题,欢迎大家交流。
189
192
 
@@ -0,0 +1,19 @@
1
+ mcp_query_table/__init__.py,sha256=gNXLL6MtH667HEdsUbJ4OAbGqwYO1dLdkqorV3-RtLM,238
2
+ mcp_query_table/__main__.py,sha256=W3tMnZZTvkhjlLHmSYHng3CTvYX6-LjyaBDhf-ypH7w,1186
3
+ mcp_query_table/_version.py,sha256=8KcCYTXH99C2-gCLuPILJvtT9YftRWJsartIx6TQ2ZY,22
4
+ mcp_query_table/enums.py,sha256=Hen0X1f2of69f08epun6HvYIgbpw_rf8BvoRQ184kS4,679
5
+ mcp_query_table/server.py,sha256=oV8CSi-EW5-xlPn38R1wLu7U-pCHgAJci1W8rJFsXSk,3430
6
+ mcp_query_table/tool.py,sha256=uKqqrUrnUnvwlOipX0YODUg9WMq_Us994X8sysxe1cM,8571
7
+ mcp_query_table/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ mcp_query_table/providers/baidu.py,sha256=VkjAN6mSD4xa9kfDvbCb_Xj9Su5F2dakzYNgjoLGsR4,2738
9
+ mcp_query_table/providers/n.py,sha256=GcqNMra1pc_DTw3QB3a2SUNzZCOrGjiuvuVDS-hTz5o,3006
10
+ mcp_query_table/providers/yuanbao.py,sha256=BfHg3A6RGOT-GxfxkrAoiOQFFo6qydtI5tZSoRGtPiY,3244
11
+ mcp_query_table/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ mcp_query_table/sites/eastmoney.py,sha256=LImjpYVuM5YnXwnNzB2hkKfHofocZZScetGqMOCHZpk,4477
13
+ mcp_query_table/sites/iwencai.py,sha256=g56pj3pbxu4mXLNnaaS3Hdx-DvEy_9OBrQJe26z4z08,5059
14
+ mcp_query_table/sites/tdx.py,sha256=RIUQaB7Tn4AVyWaevk9SzTKIDwVO2f9erIlI-adXPLY,4126
15
+ mcp_query_table-0.3.3.dist-info/licenses/LICENSE,sha256=rbvv_CTd7biGwT21tvhgQ2zkbPFXOoON7WFQWEdElBA,1063
16
+ mcp_query_table-0.3.3.dist-info/METADATA,sha256=cRXUETyJhkJ12POY1fMsZv2YHvFdBor8c_BqNOZhy5g,8372
17
+ mcp_query_table-0.3.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
18
+ mcp_query_table-0.3.3.dist-info/top_level.txt,sha256=5M_8dkO1USOX7_EWbWS6O_TEsZ5yo-AodFNKeUEgvEQ,16
19
+ mcp_query_table-0.3.3.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- mcp_query_table/__init__.py,sha256=gNXLL6MtH667HEdsUbJ4OAbGqwYO1dLdkqorV3-RtLM,238
2
- mcp_query_table/__main__.py,sha256=W3tMnZZTvkhjlLHmSYHng3CTvYX6-LjyaBDhf-ypH7w,1186
3
- mcp_query_table/_version.py,sha256=vNiWJ14r_cw5t_7UDqDQIVZvladKFGyHH2avsLpN7Vg,22
4
- mcp_query_table/enums.py,sha256=l-6uuGyniMVJGNh4tx9ZtktIjKSqyoHBHCJAdaOvczY,628
5
- mcp_query_table/server.py,sha256=l8tt-1UNjTc5A8r3jGPt5REyCzU7N1t9_ndNJmThJ9k,3264
6
- mcp_query_table/tool.py,sha256=X-mopuv0QRiQ2J_VLDcVWkH8ynXVTPgl6vlaYnDKnWA,8143
7
- mcp_query_table/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- mcp_query_table/providers/baidu.py,sha256=N7D2mWzVfNJ2dbAMbdHisoBdac17-joyeF7BkFhLKPQ,2560
9
- mcp_query_table/providers/n.py,sha256=H8hXgai8GDj3KizS2du4ix28PZlDaD6BkoyaheJnYd4,2152
10
- mcp_query_table/providers/yuanbao.py,sha256=eTcOeV1ERFq7x5EgThBe9zsSodriGy7-eIWJRqcgwYU,2350
11
- mcp_query_table/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- mcp_query_table/sites/eastmoney.py,sha256=LImjpYVuM5YnXwnNzB2hkKfHofocZZScetGqMOCHZpk,4477
13
- mcp_query_table/sites/iwencai.py,sha256=g56pj3pbxu4mXLNnaaS3Hdx-DvEy_9OBrQJe26z4z08,5059
14
- mcp_query_table/sites/tdx.py,sha256=RIUQaB7Tn4AVyWaevk9SzTKIDwVO2f9erIlI-adXPLY,4126
15
- mcp_query_table-0.3.2.dist-info/licenses/LICENSE,sha256=rbvv_CTd7biGwT21tvhgQ2zkbPFXOoON7WFQWEdElBA,1063
16
- mcp_query_table-0.3.2.dist-info/METADATA,sha256=D9kCuwRBvBsn1RRc0ysYwSPia_94ferz8UVlye68GwM,8187
17
- mcp_query_table-0.3.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
18
- mcp_query_table-0.3.2.dist-info/top_level.txt,sha256=5M_8dkO1USOX7_EWbWS6O_TEsZ5yo-AodFNKeUEgvEQ,16
19
- mcp_query_table-0.3.2.dist-info/RECORD,,