mcp-query-table 0.3.9__py3-none-any.whl → 0.3.11__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.
@@ -17,9 +17,9 @@ def main():
17
17
  parser.add_argument("--executable_path", type=str, help="浏览器路径",
18
18
  nargs="?", default=r'C:\Program Files\Google\Chrome\Application\chrome.exe')
19
19
  parser.add_argument("--user_data_dir", type=str, help="浏览器用户数据目录",
20
- nargs="?", default=rf'C:\Users\{getpass.getuser()}\AppData\Local\Google\Chrome\User Data\Default')
20
+ nargs="?", default=rf'C:\Users\{getpass.getuser()}\AppData\Local\Google\Chrome\User Data')
21
21
  parser.add_argument("--transport", type=str, help="传输类型",
22
- default='stdio', choices=['stdio', 'sse'])
22
+ default='stdio', choices=['stdio', 'sse', 'streamable-http'])
23
23
  parser.add_argument("--host", type=str, help="MCP服务端绑定地址",
24
24
  default='0.0.0.0')
25
25
  parser.add_argument("--port", type=int, help="MCP服务端绑定端口",
@@ -1 +1 @@
1
- __version__ = "0.3.9"
1
+ __version__ = "0.3.11"
mcp_query_table/server.py CHANGED
@@ -22,9 +22,9 @@ class QueryServer:
22
22
  devtools=False,
23
23
  headless=True)
24
24
 
25
- async def query(self, query_input: str, query_type: QueryType, max_page: int, site: Site):
25
+ async def query(self, query_input: str, query_type: QueryType, max_page: int, rename: bool, site: Site):
26
26
  page = await self.browser.get_page()
27
- df = await qt_query(page, query_input, query_type, max_page, site)
27
+ df = await qt_query(page, query_input, query_type, max_page, rename, site)
28
28
  self.browser.release_page(page)
29
29
 
30
30
  if self.format == 'csv':
@@ -53,9 +53,10 @@ async def query(
53
53
  query_type: Annotated[QueryType, Field(default=QueryType.CNStock,
54
54
  description="查询类型。支持`A股`、`指数`、`基金`、`港股`、`美股`等")],
55
55
  max_page: Annotated[int, Field(default=1, ge=1, le=10, description="最大页数。只查第一页即可")],
56
+ rename: Annotated[bool, Field(default=False, description="是否重命名列名")],
56
57
  site: Annotated[Site, Field(default=Site.THS, description="站点。支持`东方财富`、`通达信`、`同花顺`")]
57
58
  ) -> str:
58
- return await qsv.query(query_input, query_type, max_page, site)
59
+ return await qsv.query(query_input, query_type, max_page, rename, site)
59
60
 
60
61
 
61
62
  # chat功能不通过mcp暴露,因为在Cline等客户端中本就有LLM功能,反而导致返回的数据没有正确提交
@@ -81,7 +81,7 @@ class Pagination:
81
81
  datas.extend(v)
82
82
  return datas
83
83
 
84
- def get_dataframe(self):
84
+ def get_dataframe(self, rename: bool):
85
85
  columns = {x['key']: x['title'] for x in self.columns}
86
86
  dtypes = {x['key']: convert_type(x['dataType']) for x in self.columns}
87
87
 
@@ -98,7 +98,10 @@ class Pagination:
98
98
  except ValueError:
99
99
  logger.info("转换失败 {}:{}", k, v)
100
100
 
101
- return df.rename(columns=columns)
101
+ if rename:
102
+ return df.rename(columns=columns)
103
+ else:
104
+ return df
102
105
 
103
106
 
104
107
  P = Pagination()
@@ -121,7 +124,8 @@ async def on_response(response):
121
124
  async def query(page: Page,
122
125
  q: str = "收盘价>100元",
123
126
  type_: QueryType = 'stock',
124
- max_page: int = 5) -> pd.DataFrame:
127
+ max_page: int = 5,
128
+ rename: bool = True) -> pd.DataFrame:
125
129
  type = _type_.get(type_, None)
126
130
  assert type is not None, f"不支持的类型:{type_}"
127
131
 
@@ -141,4 +145,4 @@ async def query(page: Page,
141
145
  await page.get_by_role("button", name="下一页").click()
142
146
  await on_response(await response_info.value)
143
147
 
144
- return P.get_dataframe()
148
+ return P.get_dataframe(rename)
@@ -80,7 +80,7 @@ class Pagination:
80
80
  datas.extend(v)
81
81
  return datas
82
82
 
83
- def get_dataframe(self):
83
+ def get_dataframe(self, rename: bool):
84
84
  columns = {x['key']: x['index_name'] for x in self.columns}
85
85
  dtypes = {x['key']: convert_type(x['type']) for x in self.columns}
86
86
 
@@ -94,7 +94,10 @@ class Pagination:
94
94
  except ValueError:
95
95
  logger.info("转换失败 {}:{}", k, v)
96
96
 
97
- return df.rename(columns=columns)
97
+ if rename:
98
+ return df.rename(columns=columns)
99
+ else:
100
+ return df
98
101
 
99
102
 
100
103
  P = Pagination()
@@ -148,7 +151,8 @@ async def on_response(response):
148
151
  async def query(page: Page,
149
152
  w: str = "收盘价>1000元",
150
153
  type_: QueryType = 'stock',
151
- max_page: int = 5) -> pd.DataFrame:
154
+ max_page: int = 5,
155
+ rename: bool = False) -> pd.DataFrame:
152
156
  querytype = _querytype_.get(type_, None)
153
157
  assert querytype is not None, f"不支持的类型:{type_}"
154
158
 
@@ -168,4 +172,4 @@ async def query(page: Page,
168
172
  await page.get_by_text("下页").click()
169
173
  await on_response(await response_info.value)
170
174
 
171
- return P.get_dataframe()
175
+ return P.get_dataframe(rename)
@@ -78,7 +78,7 @@ class Pagination:
78
78
  datas.extend(v)
79
79
  return datas
80
80
 
81
- def get_dataframe(self):
81
+ def get_dataframe(self, rename: bool):
82
82
  dtypes = [convert_type(x) for x in self.dtypes]
83
83
  df = pd.DataFrame(self.get_list(), columns=self.columns)
84
84
  for i, v in enumerate(dtypes):
@@ -128,7 +128,8 @@ async def on_response2(response):
128
128
  async def query(page: Page,
129
129
  message: str = "收盘价>100元",
130
130
  type_: QueryType = 'AG',
131
- max_page: int = 5) -> pd.DataFrame:
131
+ max_page: int = 5,
132
+ rename: bool = False) -> pd.DataFrame:
132
133
  queryType = _queryType_.get(type_, None)
133
134
  assert queryType is not None, f"不支持的类型:{type_}"
134
135
 
@@ -147,4 +148,4 @@ async def query(page: Page,
147
148
  await page.get_by_role("button", name="下一页").click()
148
149
  await on_response1(await response_info.value)
149
150
 
150
- return P.get_dataframe()
151
+ return P.get_dataframe(rename)
mcp_query_table/tool.py CHANGED
@@ -66,8 +66,8 @@ def get_user_data_dir(user_data_dir) -> Optional[str]:
66
66
  """获取浏览器可用户目录"""
67
67
  browsers = {
68
68
  "default": user_data_dir,
69
- "chrome.exe": rf'C:\Users\{getpass.getuser()}\AppData\Local\Google\Chrome\User Data\Default',
70
- "msedge.exe": rf"C:\Users\{getpass.getuser()}\AppData\Local\Microsoft\Edge\User Data\Default",
69
+ "chrome.exe": rf'C:\Users\{getpass.getuser()}\AppData\Local\Google\Chrome\User Data', # 使用默认配置文件时无法创建CDP
70
+ "msedge.exe": rf"C:\Users\{getpass.getuser()}\AppData\Local\Microsoft\Edge\User Data",
71
71
  }
72
72
  for k, v in browsers.items():
73
73
  if v is None:
@@ -136,6 +136,10 @@ class BrowserManager:
136
136
  command = [executable_path, f'--remote-debugging-port={port}', '--start-maximized']
137
137
  if self.devtools:
138
138
  command.append('--auto-open-devtools-for-tabs')
139
+ if self.user_data_dir:
140
+ command.append(f'--user-data-dir={self.user_data_dir}')
141
+ else:
142
+ logger.warning('Chrome必须另行指定`--user-data-dir`才能创建CDP连接')
139
143
 
140
144
  for i in range(2):
141
145
  try:
@@ -249,7 +253,9 @@ async def query(
249
253
  query_input: str = "收盘价>100元",
250
254
  query_type: QueryType = QueryType.CNStock,
251
255
  max_page: int = 5,
252
- site: Site = Site.THS) -> pd.DataFrame:
256
+ rename: bool = False,
257
+ site: Site = Site.THS,
258
+ ) -> pd.DataFrame:
253
259
  """查询表格
254
260
 
255
261
  Parameters
@@ -262,6 +268,8 @@ async def query(
262
268
  查询类型, by default QueryType.astock
263
269
  max_page : int, optional
264
270
  最大页数, by default 5
271
+ rename: bool
272
+ 是否重命名列名, by default False
265
273
  site : Site, optional
266
274
  站点, by default Site.iwencai
267
275
 
@@ -275,13 +283,13 @@ async def query(
275
283
 
276
284
  if site == Site.EastMoney:
277
285
  from mcp_query_table.sites.eastmoney import query
278
- return await query(page, query_input, query_type, max_page)
286
+ return await query(page, query_input, query_type, max_page, rename)
279
287
  if site == Site.THS:
280
288
  from mcp_query_table.sites.iwencai import query
281
- return await query(page, query_input, query_type, max_page)
289
+ return await query(page, query_input, query_type, max_page, rename)
282
290
  if site == Site.TDX:
283
291
  from mcp_query_table.sites.tdx import query
284
- return await query(page, query_input, query_type, max_page)
292
+ return await query(page, query_input, query_type, max_page, rename)
285
293
 
286
294
  raise ValueError(f"未支持的站点:{site}")
287
295
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp_query_table
3
- Version: 0.3.9
3
+ Version: 0.3.11
4
4
  Summary: query table from website, support MCP
5
5
  Author-email: wukan <wu-kan@163.com>
6
6
  License: MIT License
@@ -137,6 +137,8 @@ if __name__ == '__main__':
137
137
  - `endpoint`以`ws://`开头,连接远程`Playwright Server`。也是无头模式,但无法指定`user_data_dir`,所以使用受限
138
138
  - 参考:https://playwright.dev/python/docs/docker#running-the-playwright-server
139
139
 
140
+ `Chrome`新版的安全策略使用默认`user_data_dir`时将无法创建`CDP`服务,建议重新复制配置目录到其他地方
141
+
140
142
  ## MCP支持
141
143
 
142
144
  确保可以在控制台中执行`python -m mcp_query_table -h`。如果不能,可能要先`pip install mcp_query_table`
@@ -172,7 +174,7 @@ if __name__ == '__main__':
172
174
  先在控制台中执行如下命令,启动`MCP`服务
173
175
 
174
176
  ```commandline
175
- python -m mcp_query_table --format markdown --transport sse --port 8000 --endpoint http://127.0.0.1:9222
177
+ python -m mcp_query_table --format markdown --transport sse --port 8000 --endpoint http://127.0.0.1:9222 --user_data_dir "D:\user-data-dir"
176
178
  ```
177
179
 
178
180
  然后就可以连接到`MCP`服务了
@@ -188,6 +190,14 @@ python -m mcp_query_table --format markdown --transport sse --port 8000 --endpoi
188
190
  }
189
191
  ```
190
192
 
193
+ ### Streamable HTTP方式
194
+
195
+ ```commandline
196
+ python -m mcp_query_table --format markdown --transport streamable-http --port 8000 --endpoint http://127.0.0.1:9222 --user_data_dir "D:\user-data-dir"
197
+ ```
198
+
199
+ 连接的地址是`http://127.0.0.1:8000/mcp`
200
+
191
201
  ## 使用`MCP Inspector`进行调试
192
202
 
193
203
  ```commandline
@@ -221,5 +231,7 @@ npx @modelcontextprotocol/inspector python -m mcp_query_table --format markdown
221
231
  ![streamlit](docs/img/streamlit.png)
222
232
 
223
233
  ## 参考
234
+
224
235
  - [Selenium webdriver无法附加到edge实例,edge的--remote-debugging-port选项无效](https://blog.csdn.net/qq_30576521/article/details/142370538)
225
- - https://github.com/AtuboDad/playwright_stealth/issues/31
236
+ - https://github.com/AtuboDad/playwright_stealth/issues/31
237
+ - https://github.com/browser-use/browser-use/issues/1520
@@ -0,0 +1,19 @@
1
+ mcp_query_table/__init__.py,sha256=K-0DU2hpeRvM9ZAuky0aWZtJLuOgKg7ZRd-pL9noc0o,330
2
+ mcp_query_table/__main__.py,sha256=Hl70DkzAY1wJNnrirjiMRXHhemptXXy_1Q3sASMTWSk,1472
3
+ mcp_query_table/_version.py,sha256=TESjMH0a_iUkwdfWT4nyzKizSFmmCY2omxnS2XyT97Y,23
4
+ mcp_query_table/enums.py,sha256=7bu0m0zJBIfiS-eHGURw1ZHWNXgsq6gH1SztUhCgF-Y,678
5
+ mcp_query_table/server.py,sha256=re3UnNAe75IJAH8oyJZAzYAzp_rg3uH1vIroKJ7k69w,3871
6
+ mcp_query_table/tool.py,sha256=3wUZfvfA_4fNmc5sWi60gdGuqT5y7ZPKt-Nibw9NzY4,11737
7
+ mcp_query_table/utils.py,sha256=MUKcklPF9TkABhM8wN0-kW0iy9AlmjL6oycZyxB_Qk8,722
8
+ mcp_query_table/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ mcp_query_table/providers/baidu.py,sha256=S75D2zbpqG1r4Rxz7pJf5u2ZHNLO8nqV-LPEjlACtHg,3390
10
+ mcp_query_table/providers/n.py,sha256=SLalpwHSdkXNoMCLQEx1TEFlo50dS7I9JNli5jz8w6k,3202
11
+ mcp_query_table/providers/yuanbao.py,sha256=1wRMy7Z2JraM3MrgLDSdyg-EqX-D26ysx7CW1GFtVho,3292
12
+ mcp_query_table/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ mcp_query_table/sites/eastmoney.py,sha256=wuM1rJkuQKrtL0a6ZyslMohPtucSgrs_jjaZWdkxhZo,4593
14
+ mcp_query_table/sites/iwencai.py,sha256=oCxNuGxiYcaMREHGpNoqspmCLlXSkvTFw2_EsmJSzlw,5174
15
+ mcp_query_table/sites/tdx.py,sha256=-u-rzhmYPW1m3zUFQsd-RUztafC43gQPhtmB6OuqA4M,4184
16
+ mcp_query_table-0.3.11.dist-info/METADATA,sha256=s7yPOuqh4HbNpdz5CjRo5INmcSGwxm0neIr0XrM2quA,9830
17
+ mcp_query_table-0.3.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ mcp_query_table-0.3.11.dist-info/licenses/LICENSE,sha256=rbvv_CTd7biGwT21tvhgQ2zkbPFXOoON7WFQWEdElBA,1063
19
+ mcp_query_table-0.3.11.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- mcp_query_table/__init__.py,sha256=K-0DU2hpeRvM9ZAuky0aWZtJLuOgKg7ZRd-pL9noc0o,330
2
- mcp_query_table/__main__.py,sha256=K0r7y8PD9y9pFg3bAQxNo21KlQpGz1jqGg_zptPfenM,1461
3
- mcp_query_table/_version.py,sha256=xmkmdvq15kb61xdtCoa1YARnvHBnUgI-0GWIJYvHNeA,22
4
- mcp_query_table/enums.py,sha256=7bu0m0zJBIfiS-eHGURw1ZHWNXgsq6gH1SztUhCgF-Y,678
5
- mcp_query_table/server.py,sha256=D2-7ZmutijphasbLMosg9P5EOhJTB4RvC9-zmvCvc5k,3749
6
- mcp_query_table/tool.py,sha256=dW6Hcv7aB-hBotd7OBzCWQrpRck1h5812y6sRCUENVA,11380
7
- mcp_query_table/utils.py,sha256=MUKcklPF9TkABhM8wN0-kW0iy9AlmjL6oycZyxB_Qk8,722
8
- mcp_query_table/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- mcp_query_table/providers/baidu.py,sha256=S75D2zbpqG1r4Rxz7pJf5u2ZHNLO8nqV-LPEjlACtHg,3390
10
- mcp_query_table/providers/n.py,sha256=SLalpwHSdkXNoMCLQEx1TEFlo50dS7I9JNli5jz8w6k,3202
11
- mcp_query_table/providers/yuanbao.py,sha256=1wRMy7Z2JraM3MrgLDSdyg-EqX-D26ysx7CW1GFtVho,3292
12
- mcp_query_table/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- mcp_query_table/sites/eastmoney.py,sha256=LImjpYVuM5YnXwnNzB2hkKfHofocZZScetGqMOCHZpk,4477
14
- mcp_query_table/sites/iwencai.py,sha256=FlIQOAN6wPz0B8w5DFX-EHekPO5HPIYdLMhiX1dYV7s,5057
15
- mcp_query_table/sites/tdx.py,sha256=P-GNFUsS5_INy3sicaZbUBdudgQBZuhu_QyVvyw4yDg,4126
16
- mcp_query_table-0.3.9.dist-info/METADATA,sha256=w6Kk_cokNDdnTgr7APF6IhlSVOHJTrDAO0uGdhTaNvA,9353
17
- mcp_query_table-0.3.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- mcp_query_table-0.3.9.dist-info/licenses/LICENSE,sha256=rbvv_CTd7biGwT21tvhgQ2zkbPFXOoON7WFQWEdElBA,1063
19
- mcp_query_table-0.3.9.dist-info/RECORD,,