kl-mcp-client 2.0.4__tar.gz → 2.1.2__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kl-mcp-client
3
- Version: 2.0.4
3
+ Version: 2.1.2
4
4
  Summary: MCP Client for Python
5
5
  Author-email: Kyle <hngan.it@gmail.com>
6
6
  License: MIT
@@ -146,3 +146,4 @@ class MCPClient:
146
146
  async def aclose(self):
147
147
  """Close the httpx async client"""
148
148
  await self._client.aclose()
149
+
@@ -46,7 +46,7 @@ class MCPTools:
46
46
 
47
47
  async def screenshot(self, sessionId: str) -> Dict[str, Any]:
48
48
  """
49
- ADK Web expects this structure:
49
+ ADK Web expects:
50
50
  {
51
51
  "type": "image",
52
52
  "mimeType": "image/png",
@@ -121,7 +121,7 @@ class MCPTools:
121
121
  ) -> Dict[str, Any]:
122
122
  args = {"sessionId": sessionId, "selector": selector}
123
123
  if timeoutMs is not None:
124
- args["timeoutMs"] = timeoutMs
124
+ args["timeoutMs"] = int(timeoutMs)
125
125
 
126
126
  res = await self.client.call_tool("waitForSelector", args)
127
127
  return res.get("structuredContent", {})
@@ -145,10 +145,10 @@ class MCPTools:
145
145
  return res.get("structuredContent", {})
146
146
 
147
147
  # ======================================================
148
- # ADVANCED
148
+ # ADVANCED ACTIONS
149
149
  # ======================================================
150
150
 
151
- async def click_to_text(self, sessionId: str, text: str) -> dict:
151
+ async def click_to_text(self, sessionId: str, text: str) -> Dict[str, Any]:
152
152
  res = await self.client.call_tool(
153
153
  "clickToText", {"sessionId": sessionId, "text": text}
154
154
  )
@@ -178,25 +178,144 @@ class MCPTools:
178
178
  )
179
179
  return res.get("structuredContent", {})
180
180
 
181
+ async def get_dom_tree(self, sessionId: str, args: Optional[dict] = None):
182
+ return await self.client.call_tool(
183
+ "getDomTree", {"sessionId": sessionId, "args": args or {}}
184
+ )
185
+
186
+ async def get_clickable(self, sessionId: str, args: Optional[dict] = None):
187
+ return await self.client.call_tool(
188
+ "getClickable", {"sessionId": sessionId, "args": args or {}}
189
+ )
190
+
191
+ async def selector_map(
192
+ self, sessionId: str, selector: str, args: Optional[dict] = None
193
+ ):
194
+ return await self.client.call_tool(
195
+ "selectorMap",
196
+ {"sessionId": sessionId, "selector": selector, "args": args or {}},
197
+ )
198
+
199
+ # ======================================================
200
+ # AI / CONTENT PARSING
201
+ # ======================================================
202
+
181
203
  async def parse_html_by_prompt(self, html: str, prompt: str) -> Dict[str, Any]:
204
+ res = await self.client.call_tool(
205
+ "parseHTMLByPrompt",
206
+ {"html": html, "prompt": prompt},
207
+ )
208
+ return res.get("structuredContent", {})
209
+
210
+ # ======================================================
211
+ # MOUSE / PERFORM ACTIONS
212
+ # ======================================================
213
+
214
+ async def perform_click_xy(
215
+ self,
216
+ sessionId: str,
217
+ x: float,
218
+ y: float,
219
+ ) -> Dict[str, Any]:
182
220
  """
183
- Parse HTML content using AI with dynamic prompt-defined structure.
221
+ Move mouse smoothly to (x, y) and left click.
222
+ """
223
+ res = await self.client.call_tool(
224
+ "perform",
225
+ {
226
+ "sessionId": sessionId,
227
+ "action": "click",
228
+ "x": float(x),
229
+ "y": float(y),
230
+ },
231
+ )
232
+ return res.get("structuredContent", {})
184
233
 
185
- Args:
186
- html: Raw HTML string (client-provided)
187
- prompt: Instruction that defines what to extract and output structure
188
- Example:
189
- - "Hãy lấy nội dung bài viết, struct trả về { content }"
190
- - "Hãy lấy số lượng like, share, comment, trả JSON { like, share, comment }"
234
+ async def perform_drag(
235
+ self,
236
+ sessionId: str,
237
+ from_x: float,
238
+ from_y: float,
239
+ to_x: float,
240
+ to_y: float,
241
+ ) -> Dict[str, Any]:
242
+ """
243
+ Drag mouse from (from_x, from_y) to (to_x, to_y).
244
+ """
245
+ res = await self.client.call_tool(
246
+ "perform",
247
+ {
248
+ "sessionId": sessionId,
249
+ "action": "drag",
250
+ "from": {"x": float(from_x), "y": float(from_y)},
251
+ "to": {"x": float(to_x), "y": float(to_y)},
252
+ },
253
+ )
254
+ return res.get("structuredContent", {})
191
255
 
192
- Returns:
193
- structuredContent (dynamic JSON defined by prompt)
256
+ async def perform_hover(
257
+ self,
258
+ sessionId: str,
259
+ x: float,
260
+ y: float,
261
+ ) -> Dict[str, Any]:
262
+ """
263
+ Move mouse smoothly to (x, y) without clicking.
194
264
  """
195
265
  res = await self.client.call_tool(
196
- "parseHTMLByPrompt",
266
+ "perform",
197
267
  {
198
- "html": html,
199
- "prompt": prompt,
268
+ "sessionId": sessionId,
269
+ "action": "hover",
270
+ "x": float(x),
271
+ "y": float(y),
200
272
  },
201
273
  )
202
274
  return res.get("structuredContent", {})
275
+
276
+ # CLEAN TEXT / READ MODE
277
+ # ======================================================
278
+ async def get_clean_text(self, sessionId: str) -> Dict[str, Any]:
279
+ """
280
+ Lấy toàn bộ visible text đã được clean trên trang hiện tại.
281
+ - Bỏ script/style/iframe/svg/canvas
282
+ - Chỉ text nhìn thấy (display/visibility/opacity)
283
+
284
+ Returns:
285
+ {
286
+ "text": "...",
287
+ "length": 12345
288
+ }
289
+ """
290
+ res = await self.client.call_tool(
291
+ "getCleanText",
292
+ {"sessionId": sessionId},
293
+ )
294
+ return res.get("structuredContent", {})
295
+
296
+ # ======================================================
297
+ # KEYBOARD (ASYNC)
298
+ # ======================================================
299
+ async def send_key(
300
+ self,
301
+ sessionId: str,
302
+ key: str,
303
+ ) -> Dict[str, Any]:
304
+ """
305
+ Send a keyboard key to the active page (async).
306
+
307
+ Args:
308
+ sessionId: MCP browser session
309
+ key: Keyboard key (e.g. "Enter", "Tab", "Escape", "ArrowDown",
310
+ "Ctrl+a", "Ctrl+Enter")
311
+
312
+ Returns:
313
+ structuredContent from MCP server
314
+ """
315
+ return await self.call_tool_structured(
316
+ "sendKey",
317
+ {
318
+ "sessionId": sessionId,
319
+ "key": key,
320
+ },
321
+ )
@@ -300,3 +300,24 @@ class MCPTools:
300
300
  "prompt": prompt,
301
301
  },
302
302
  ).get("structuredContent", {})
303
+
304
+ # ======================================================
305
+ # CLEAN TEXT / READ MODE
306
+ # ======================================================
307
+ @_ensure_client
308
+ def get_clean_text(self, sessionId: str) -> Dict[str, Any]:
309
+ """
310
+ Lấy toàn bộ visible text đã được clean trên trang hiện tại.
311
+ - Bỏ script/style/iframe/svg/canvas
312
+ - Chỉ text nhìn thấy (display/visibility/opacity)
313
+
314
+ Returns:
315
+ {
316
+ "text": "...",
317
+ "length": 12345
318
+ }
319
+ """
320
+ return self.client.call_tool(
321
+ "getCleanText",
322
+ {"sessionId": sessionId},
323
+ ).get("structuredContent", {})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kl-mcp-client
3
- Version: 2.0.4
3
+ Version: 2.1.2
4
4
  Summary: MCP Client for Python
5
5
  Author-email: Kyle <hngan.it@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kl-mcp-client"
7
- version = "2.0.4"
7
+ version = "2.1.2"
8
8
  description = "MCP Client for Python"
9
9
  dependencies = [ "requests>=2.32.5", "httpx>=0.28.1",]
10
10
  readme = "README.md"
File without changes
File without changes