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.
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/PKG-INFO +1 -1
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/asyncio/client.py +1 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/asyncio/tools.py +135 -16
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/tools.py +21 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client.egg-info/PKG-INFO +1 -1
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/pyproject.toml +1 -1
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/README.md +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/__init__.py +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/__version__.py +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/asyncio/__init__.py +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client/client.py +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client.egg-info/SOURCES.txt +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client.egg-info/dependency_links.txt +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client.egg-info/requires.txt +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/kl_mcp_client.egg-info/top_level.txt +0 -0
- {kl_mcp_client-2.0.4 → kl_mcp_client-2.1.2}/setup.cfg +0 -0
|
@@ -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
|
|
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) ->
|
|
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
|
-
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
193
|
-
|
|
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
|
-
"
|
|
266
|
+
"perform",
|
|
197
267
|
{
|
|
198
|
-
"
|
|
199
|
-
"
|
|
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", {})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|