kl-mcp-client 1.0.0__tar.gz → 1.0.1__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.
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.4
2
+ Name: kl-mcp-client
3
+ Version: 1.0.1
4
+ Summary: MCP Client
5
+ Author-email: Kyle <hngan.it@gmail.com>
6
+ License: MIT
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.32.5
10
+ Requires-Dist: httpx>=0.28.1
11
+
12
+ # 📦 kl-mcp-client
13
+
14
+ **kl-mcp-client** là SDK Python giúp giao tiếp với **MCP (Model Context Protocol) Browser Server** — một server trung gian điều khiển Chrome/Chromium qua CDP.
15
+
16
+ Thư viện này được thiết kế để:
17
+
18
+ - Điều khiển Chrome tự động: click, nhập liệu, screenshot, đọc DOM…
19
+ - Kết nối trình duyệt Chrome Remote qua CDP (Chrome DevTools Protocol)
20
+ - Tích hợp làm Web Automation Agent trong **Google ADK**
21
+ - Hoạt động độc lập như một browser automation SDK
22
+
23
+ ---
24
+
25
+ # 🚀 Cài đặt
26
+
27
+ ```bash
28
+ pip install kl-mcp-client
29
+ ```
30
+
31
+ ---
32
+
33
+ # 🧩 Thành phần của thư viện
34
+
35
+ Package gồm 2 module chính:
36
+
37
+ | File | Vai trò |
38
+ |------|---------|
39
+ | `client.py` | JSON-RPC HTTP Client giao tiếp với MCP Server |
40
+ | `tools.py` | Wrapper cấp cao, cung cấp API tiện dụng cho các Agent & automation |
41
+
42
+ ---
43
+
44
+ # ✨ Tính năng chính
45
+
46
+ ### ✔ Điều khiển trình duyệt
47
+ - Mở tab, load URL
48
+ - Click CSS selector, click bằng text, click bằng nodeId
49
+ - Nhập text vào input
50
+ - Screenshot (chuẩn ADK hiển thị được)
51
+
52
+ ### ✔ DOM Tools nâng cao
53
+ - Find element by selector / text / XPath
54
+ - Lấy bounding box
55
+ - Lấy toàn bộ DOM Tree
56
+ - Lấy danh sách clickable elements
57
+ - Highlight elements (nếu server hỗ trợ)
58
+
59
+ ### ✔ Tương tác hệ thống
60
+ - Upload file bằng base64
61
+ - Import cookies
62
+ - Evaluate JavaScript
63
+
64
+ ### ✔ Chrome Remote Debugging
65
+ - Tạo session từ địa chỉ:
66
+ `http://localhost:9222/json/version`
67
+
68
+ ---
69
+
70
+ # 🧭 Cách sử dụng
71
+
72
+ ## 1. Import client & tools
73
+
74
+ ```python
75
+ from kl_mcp_client.client import MCPClient
76
+ from kl_mcp_client.tools import MCPTools
77
+ ```
78
+
79
+ ---
80
+
81
+ ## 2. Tạo kết nối tới MCP Server
82
+
83
+ ```python
84
+ mcp = MCPClient(
85
+ base_url="http://localhost:3000/mcp",
86
+ timeout=30,
87
+ retries=2
88
+ )
89
+ tools = MCPTools(mcp)
90
+ ```
91
+
92
+ ---
93
+
94
+ ## 3. Tạo session (Chrome Remote)
95
+
96
+ ```python
97
+ session = tools.create_session("http://localhost:9222/json/version")
98
+ sid = session["sessionId"]
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 4. Mở URL
104
+
105
+ ```python
106
+ tools.open_page(sid, "https://google.com")
107
+ ```
108
+
109
+ ---
110
+
111
+ ## 5. Screenshot (hiển thị được trong ADK Web)
112
+
113
+ ```python
114
+ img = tools.screenshot(sid)
115
+ print(img)
116
+ ```
117
+
118
+ Trả về:
119
+
120
+ ```json
121
+ {
122
+ "type": "image",
123
+ "mimeType": "image/png",
124
+ "data": "<base64>"
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 6. Click & Type
131
+
132
+ ```python
133
+ tools.click(sid, "#login")
134
+ tools.type(sid, "input[name=q]", "Hello world")
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 7. Find Elements
140
+
141
+ ```python
142
+ tools.find_element(sid, "#content")
143
+ tools.find_element_by_text(sid, "Đăng nhập")
144
+ tools.find_element_xpath(sid, "//input[@type='email']")
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 8. Upload File
150
+
151
+ ```python
152
+ import base64
153
+ data = base64.b64encode(open("test.pdf", "rb").read()).decode()
154
+
155
+ tools.upload_file(
156
+ sid,
157
+ selector="input[type=file]",
158
+ filename="test.pdf",
159
+ base64Data=data
160
+ )
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 9. Import Cookies
166
+
167
+ ```python
168
+ tools.import_cookies(sid, [
169
+ {"name": "token", "value": "abc", "domain": "example.com", "path": "/"}
170
+ ])
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 10. Đóng session
176
+
177
+ ```python
178
+ tools.close_session(sid)
179
+ ```
180
+
181
+ ---
182
+
183
+ # 🧪 Ví dụ đầy đủ
184
+
185
+ ```python
186
+ from kl_mcp_client.client import MCPClient
187
+ from kl_mcp_client.tools import MCPTools
188
+ import base64
189
+
190
+ mcp = MCPClient("http://localhost:3000/mcp")
191
+ tools = MCPTools(mcp)
192
+
193
+ # Create session
194
+ sid = tools.create_session("http://localhost:9222/json/version")["sessionId"]
195
+
196
+ # Navigate
197
+ tools.open_page(sid, "https://google.com")
198
+
199
+ # Screenshot
200
+ img = tools.screenshot(sid)
201
+ print("Screenshot returned:", img["mimeType"])
202
+
203
+ # Search
204
+ tools.type(sid, "input[name=q]", "Hello MCP")
205
+ tools.click_to_text(sid, "Google Search")
206
+
207
+ # Close
208
+ tools.close_session(sid)
209
+ ```
210
+
211
+ ---
212
+
213
+ # 🏗 Kiến trúc
214
+
215
+ ```
216
+ Python App / ADK Agent
217
+
218
+ kl-mcp-client
219
+
220
+ MCP Browser Server
221
+
222
+ Chrome / CDP
223
+ ```
224
+
225
+ ---
226
+
227
+ # 📘 Yêu cầu
228
+
229
+ - Python ≥ 3.8
230
+ - MCP Server chạy sẵn (Chromedp backend)
231
+ - Chrome/Chromium với cờ:
232
+
233
+ ```
234
+ chrome.exe --remote-debugging-port=9222
235
+ ```
236
+
237
+ ---
238
+
239
+ # 📝 License
240
+
241
+ MIT License.
242
+
243
+ ---
244
+
245
+ # 📚 Liên hệ
246
+
247
+ Nếu bạn cần:
248
+
249
+ - MCP Server đầy đủ
250
+ - Hỗ trợ tích hợp ADK Web Agent
251
+ - Thêm tool: DOM Tree, highlight, selector map…
@@ -0,0 +1,240 @@
1
+ # 📦 kl-mcp-client
2
+
3
+ **kl-mcp-client** là SDK Python giúp giao tiếp với **MCP (Model Context Protocol) Browser Server** — một server trung gian điều khiển Chrome/Chromium qua CDP.
4
+
5
+ Thư viện này được thiết kế để:
6
+
7
+ - Điều khiển Chrome tự động: click, nhập liệu, screenshot, đọc DOM…
8
+ - Kết nối trình duyệt Chrome Remote qua CDP (Chrome DevTools Protocol)
9
+ - Tích hợp làm Web Automation Agent trong **Google ADK**
10
+ - Hoạt động độc lập như một browser automation SDK
11
+
12
+ ---
13
+
14
+ # 🚀 Cài đặt
15
+
16
+ ```bash
17
+ pip install kl-mcp-client
18
+ ```
19
+
20
+ ---
21
+
22
+ # 🧩 Thành phần của thư viện
23
+
24
+ Package gồm 2 module chính:
25
+
26
+ | File | Vai trò |
27
+ |------|---------|
28
+ | `client.py` | JSON-RPC HTTP Client giao tiếp với MCP Server |
29
+ | `tools.py` | Wrapper cấp cao, cung cấp API tiện dụng cho các Agent & automation |
30
+
31
+ ---
32
+
33
+ # ✨ Tính năng chính
34
+
35
+ ### ✔ Điều khiển trình duyệt
36
+ - Mở tab, load URL
37
+ - Click CSS selector, click bằng text, click bằng nodeId
38
+ - Nhập text vào input
39
+ - Screenshot (chuẩn ADK hiển thị được)
40
+
41
+ ### ✔ DOM Tools nâng cao
42
+ - Find element by selector / text / XPath
43
+ - Lấy bounding box
44
+ - Lấy toàn bộ DOM Tree
45
+ - Lấy danh sách clickable elements
46
+ - Highlight elements (nếu server hỗ trợ)
47
+
48
+ ### ✔ Tương tác hệ thống
49
+ - Upload file bằng base64
50
+ - Import cookies
51
+ - Evaluate JavaScript
52
+
53
+ ### ✔ Chrome Remote Debugging
54
+ - Tạo session từ địa chỉ:
55
+ `http://localhost:9222/json/version`
56
+
57
+ ---
58
+
59
+ # 🧭 Cách sử dụng
60
+
61
+ ## 1. Import client & tools
62
+
63
+ ```python
64
+ from kl_mcp_client.client import MCPClient
65
+ from kl_mcp_client.tools import MCPTools
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 2. Tạo kết nối tới MCP Server
71
+
72
+ ```python
73
+ mcp = MCPClient(
74
+ base_url="http://localhost:3000/mcp",
75
+ timeout=30,
76
+ retries=2
77
+ )
78
+ tools = MCPTools(mcp)
79
+ ```
80
+
81
+ ---
82
+
83
+ ## 3. Tạo session (Chrome Remote)
84
+
85
+ ```python
86
+ session = tools.create_session("http://localhost:9222/json/version")
87
+ sid = session["sessionId"]
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 4. Mở URL
93
+
94
+ ```python
95
+ tools.open_page(sid, "https://google.com")
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 5. Screenshot (hiển thị được trong ADK Web)
101
+
102
+ ```python
103
+ img = tools.screenshot(sid)
104
+ print(img)
105
+ ```
106
+
107
+ Trả về:
108
+
109
+ ```json
110
+ {
111
+ "type": "image",
112
+ "mimeType": "image/png",
113
+ "data": "<base64>"
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## 6. Click & Type
120
+
121
+ ```python
122
+ tools.click(sid, "#login")
123
+ tools.type(sid, "input[name=q]", "Hello world")
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 7. Find Elements
129
+
130
+ ```python
131
+ tools.find_element(sid, "#content")
132
+ tools.find_element_by_text(sid, "Đăng nhập")
133
+ tools.find_element_xpath(sid, "//input[@type='email']")
134
+ ```
135
+
136
+ ---
137
+
138
+ ## 8. Upload File
139
+
140
+ ```python
141
+ import base64
142
+ data = base64.b64encode(open("test.pdf", "rb").read()).decode()
143
+
144
+ tools.upload_file(
145
+ sid,
146
+ selector="input[type=file]",
147
+ filename="test.pdf",
148
+ base64Data=data
149
+ )
150
+ ```
151
+
152
+ ---
153
+
154
+ ## 9. Import Cookies
155
+
156
+ ```python
157
+ tools.import_cookies(sid, [
158
+ {"name": "token", "value": "abc", "domain": "example.com", "path": "/"}
159
+ ])
160
+ ```
161
+
162
+ ---
163
+
164
+ ## 10. Đóng session
165
+
166
+ ```python
167
+ tools.close_session(sid)
168
+ ```
169
+
170
+ ---
171
+
172
+ # 🧪 Ví dụ đầy đủ
173
+
174
+ ```python
175
+ from kl_mcp_client.client import MCPClient
176
+ from kl_mcp_client.tools import MCPTools
177
+ import base64
178
+
179
+ mcp = MCPClient("http://localhost:3000/mcp")
180
+ tools = MCPTools(mcp)
181
+
182
+ # Create session
183
+ sid = tools.create_session("http://localhost:9222/json/version")["sessionId"]
184
+
185
+ # Navigate
186
+ tools.open_page(sid, "https://google.com")
187
+
188
+ # Screenshot
189
+ img = tools.screenshot(sid)
190
+ print("Screenshot returned:", img["mimeType"])
191
+
192
+ # Search
193
+ tools.type(sid, "input[name=q]", "Hello MCP")
194
+ tools.click_to_text(sid, "Google Search")
195
+
196
+ # Close
197
+ tools.close_session(sid)
198
+ ```
199
+
200
+ ---
201
+
202
+ # 🏗 Kiến trúc
203
+
204
+ ```
205
+ Python App / ADK Agent
206
+
207
+ kl-mcp-client
208
+
209
+ MCP Browser Server
210
+
211
+ Chrome / CDP
212
+ ```
213
+
214
+ ---
215
+
216
+ # 📘 Yêu cầu
217
+
218
+ - Python ≥ 3.8
219
+ - MCP Server chạy sẵn (Chromedp backend)
220
+ - Chrome/Chromium với cờ:
221
+
222
+ ```
223
+ chrome.exe --remote-debugging-port=9222
224
+ ```
225
+
226
+ ---
227
+
228
+ # 📝 License
229
+
230
+ MIT License.
231
+
232
+ ---
233
+
234
+ # 📚 Liên hệ
235
+
236
+ Nếu bạn cần:
237
+
238
+ - MCP Server đầy đủ
239
+ - Hỗ trợ tích hợp ADK Web Agent
240
+ - Thêm tool: DOM Tree, highlight, selector map…
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.4
2
+ Name: kl-mcp-client
3
+ Version: 1.0.1
4
+ Summary: MCP Client
5
+ Author-email: Kyle <hngan.it@gmail.com>
6
+ License: MIT
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.32.5
10
+ Requires-Dist: httpx>=0.28.1
11
+
12
+ # 📦 kl-mcp-client
13
+
14
+ **kl-mcp-client** là SDK Python giúp giao tiếp với **MCP (Model Context Protocol) Browser Server** — một server trung gian điều khiển Chrome/Chromium qua CDP.
15
+
16
+ Thư viện này được thiết kế để:
17
+
18
+ - Điều khiển Chrome tự động: click, nhập liệu, screenshot, đọc DOM…
19
+ - Kết nối trình duyệt Chrome Remote qua CDP (Chrome DevTools Protocol)
20
+ - Tích hợp làm Web Automation Agent trong **Google ADK**
21
+ - Hoạt động độc lập như một browser automation SDK
22
+
23
+ ---
24
+
25
+ # 🚀 Cài đặt
26
+
27
+ ```bash
28
+ pip install kl-mcp-client
29
+ ```
30
+
31
+ ---
32
+
33
+ # 🧩 Thành phần của thư viện
34
+
35
+ Package gồm 2 module chính:
36
+
37
+ | File | Vai trò |
38
+ |------|---------|
39
+ | `client.py` | JSON-RPC HTTP Client giao tiếp với MCP Server |
40
+ | `tools.py` | Wrapper cấp cao, cung cấp API tiện dụng cho các Agent & automation |
41
+
42
+ ---
43
+
44
+ # ✨ Tính năng chính
45
+
46
+ ### ✔ Điều khiển trình duyệt
47
+ - Mở tab, load URL
48
+ - Click CSS selector, click bằng text, click bằng nodeId
49
+ - Nhập text vào input
50
+ - Screenshot (chuẩn ADK hiển thị được)
51
+
52
+ ### ✔ DOM Tools nâng cao
53
+ - Find element by selector / text / XPath
54
+ - Lấy bounding box
55
+ - Lấy toàn bộ DOM Tree
56
+ - Lấy danh sách clickable elements
57
+ - Highlight elements (nếu server hỗ trợ)
58
+
59
+ ### ✔ Tương tác hệ thống
60
+ - Upload file bằng base64
61
+ - Import cookies
62
+ - Evaluate JavaScript
63
+
64
+ ### ✔ Chrome Remote Debugging
65
+ - Tạo session từ địa chỉ:
66
+ `http://localhost:9222/json/version`
67
+
68
+ ---
69
+
70
+ # 🧭 Cách sử dụng
71
+
72
+ ## 1. Import client & tools
73
+
74
+ ```python
75
+ from kl_mcp_client.client import MCPClient
76
+ from kl_mcp_client.tools import MCPTools
77
+ ```
78
+
79
+ ---
80
+
81
+ ## 2. Tạo kết nối tới MCP Server
82
+
83
+ ```python
84
+ mcp = MCPClient(
85
+ base_url="http://localhost:3000/mcp",
86
+ timeout=30,
87
+ retries=2
88
+ )
89
+ tools = MCPTools(mcp)
90
+ ```
91
+
92
+ ---
93
+
94
+ ## 3. Tạo session (Chrome Remote)
95
+
96
+ ```python
97
+ session = tools.create_session("http://localhost:9222/json/version")
98
+ sid = session["sessionId"]
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 4. Mở URL
104
+
105
+ ```python
106
+ tools.open_page(sid, "https://google.com")
107
+ ```
108
+
109
+ ---
110
+
111
+ ## 5. Screenshot (hiển thị được trong ADK Web)
112
+
113
+ ```python
114
+ img = tools.screenshot(sid)
115
+ print(img)
116
+ ```
117
+
118
+ Trả về:
119
+
120
+ ```json
121
+ {
122
+ "type": "image",
123
+ "mimeType": "image/png",
124
+ "data": "<base64>"
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## 6. Click & Type
131
+
132
+ ```python
133
+ tools.click(sid, "#login")
134
+ tools.type(sid, "input[name=q]", "Hello world")
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 7. Find Elements
140
+
141
+ ```python
142
+ tools.find_element(sid, "#content")
143
+ tools.find_element_by_text(sid, "Đăng nhập")
144
+ tools.find_element_xpath(sid, "//input[@type='email']")
145
+ ```
146
+
147
+ ---
148
+
149
+ ## 8. Upload File
150
+
151
+ ```python
152
+ import base64
153
+ data = base64.b64encode(open("test.pdf", "rb").read()).decode()
154
+
155
+ tools.upload_file(
156
+ sid,
157
+ selector="input[type=file]",
158
+ filename="test.pdf",
159
+ base64Data=data
160
+ )
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 9. Import Cookies
166
+
167
+ ```python
168
+ tools.import_cookies(sid, [
169
+ {"name": "token", "value": "abc", "domain": "example.com", "path": "/"}
170
+ ])
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 10. Đóng session
176
+
177
+ ```python
178
+ tools.close_session(sid)
179
+ ```
180
+
181
+ ---
182
+
183
+ # 🧪 Ví dụ đầy đủ
184
+
185
+ ```python
186
+ from kl_mcp_client.client import MCPClient
187
+ from kl_mcp_client.tools import MCPTools
188
+ import base64
189
+
190
+ mcp = MCPClient("http://localhost:3000/mcp")
191
+ tools = MCPTools(mcp)
192
+
193
+ # Create session
194
+ sid = tools.create_session("http://localhost:9222/json/version")["sessionId"]
195
+
196
+ # Navigate
197
+ tools.open_page(sid, "https://google.com")
198
+
199
+ # Screenshot
200
+ img = tools.screenshot(sid)
201
+ print("Screenshot returned:", img["mimeType"])
202
+
203
+ # Search
204
+ tools.type(sid, "input[name=q]", "Hello MCP")
205
+ tools.click_to_text(sid, "Google Search")
206
+
207
+ # Close
208
+ tools.close_session(sid)
209
+ ```
210
+
211
+ ---
212
+
213
+ # 🏗 Kiến trúc
214
+
215
+ ```
216
+ Python App / ADK Agent
217
+
218
+ kl-mcp-client
219
+
220
+ MCP Browser Server
221
+
222
+ Chrome / CDP
223
+ ```
224
+
225
+ ---
226
+
227
+ # 📘 Yêu cầu
228
+
229
+ - Python ≥ 3.8
230
+ - MCP Server chạy sẵn (Chromedp backend)
231
+ - Chrome/Chromium với cờ:
232
+
233
+ ```
234
+ chrome.exe --remote-debugging-port=9222
235
+ ```
236
+
237
+ ---
238
+
239
+ # 📝 License
240
+
241
+ MIT License.
242
+
243
+ ---
244
+
245
+ # 📚 Liên hệ
246
+
247
+ Nếu bạn cần:
248
+
249
+ - MCP Server đầy đủ
250
+ - Hỗ trợ tích hợp ADK Web Agent
251
+ - Thêm tool: DOM Tree, highlight, selector map…
@@ -3,7 +3,5 @@ pyproject.toml
3
3
  kl_mcp_client.egg-info/PKG-INFO
4
4
  kl_mcp_client.egg-info/SOURCES.txt
5
5
  kl_mcp_client.egg-info/dependency_links.txt
6
- kl_mcp_client.egg-info/top_level.txt
7
- mcp_client/__init__.py
8
- mcp_client/client.py
9
- mcp_client/tools.py
6
+ kl_mcp_client.egg-info/requires.txt
7
+ kl_mcp_client.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ requests>=2.32.5
2
+ httpx>=0.28.1
@@ -4,11 +4,15 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kl-mcp-client"
7
- version = "1.0.0"
7
+ version = "1.0.1"
8
8
  description = "MCP Client"
9
9
  authors = [
10
10
  { name="Kyle", email="hngan.it@gmail.com" }
11
11
  ]
12
+ dependencies = [
13
+ "requests>=2.32.5",
14
+ "httpx>=0.28.1"
15
+ ]
12
16
  readme = "README.md"
13
17
  license = { text = "MIT" }
14
- requires-python = ">=3.7"
18
+ requires-python = ">=3.8"
@@ -1,8 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: kl-mcp-client
3
- Version: 1.0.0
4
- Summary: MCP Client
5
- Author-email: Kyle <hngan.it@gmail.com>
6
- License: MIT
7
- Requires-Python: >=3.7
8
- Description-Content-Type: text/markdown
File without changes
@@ -1,8 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: kl-mcp-client
3
- Version: 1.0.0
4
- Summary: MCP Client
5
- Author-email: Kyle <hngan.it@gmail.com>
6
- License: MIT
7
- Requires-Python: >=3.7
8
- Description-Content-Type: text/markdown
@@ -1 +0,0 @@
1
- mcp_client
File without changes
@@ -1,136 +0,0 @@
1
- # mcp_client.py
2
- import time
3
- import uuid
4
- from typing import Any, Dict, List, Optional
5
-
6
- import requests
7
-
8
- DEFAULT_HEADERS = {
9
- "Content-Type": "application/json",
10
- "Accept": "application/json, text/event-stream",
11
- }
12
-
13
-
14
- class MCPError(Exception):
15
- pass
16
-
17
-
18
- class MCPClient:
19
- def __init__(
20
- self,
21
- base_url: str,
22
- headers: Optional[Dict[str, str]] = None,
23
- timeout: int = 30,
24
- retries: int = 1,
25
- ):
26
- """
27
- base_url: full MCP HTTP endpoint e.g. http://localhost:3000/mcp
28
- headers: extra headers (e.g. {"Authorization": "Bearer ..."})
29
- timeout: request timeout seconds
30
- retries: number of attempts for network errors
31
- """
32
- self.base_url = base_url.rstrip("/")
33
- self.headers = DEFAULT_HEADERS.copy()
34
- if headers:
35
- self.headers.update(headers)
36
- self.timeout = timeout
37
- self.retries = max(1, int(retries))
38
- # local cache of sessions -> can be used to reuse session ids
39
- self._sessions: Dict[str, Dict[str, Any]] = {}
40
-
41
- def _rpc(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
42
- payload = {
43
- "jsonrpc": "2.0",
44
- "id": str(uuid.uuid4()),
45
- "method": method,
46
- "params": params,
47
- }
48
- last_exc = None
49
- for attempt in range(self.retries):
50
- try:
51
- r = requests.post(
52
- self.base_url,
53
- json=payload,
54
- headers=self.headers,
55
- timeout=self.timeout,
56
- )
57
- r.raise_for_status()
58
- except requests.RequestException as e:
59
- last_exc = e
60
- time.sleep(0.2 * (attempt + 1))
61
- continue
62
-
63
- try:
64
- data = r.json()
65
- except ValueError:
66
- raise MCPError(
67
- f"Invalid JSON response (status {r.status_code}): {r.text}"
68
- )
69
-
70
- if "error" in data and data["error"] is not None:
71
- err = data["error"]
72
- raise MCPError(
73
- {
74
- "code": err.get("code"),
75
- "message": err.get("message"),
76
- "data": err.get("data"),
77
- }
78
- )
79
- return data.get("result", {})
80
-
81
- # all retries failed
82
- raise MCPError(f"Request failed after {self.retries} attempts: {last_exc}")
83
-
84
- # ----- Generic callTool wrapper -----
85
- def call_tool_structured(
86
- self, tool: str, arguments: Optional[Dict[str, Any]] = None
87
- ) -> Dict[str, Any]:
88
- args = {"tool": tool, "arguments": arguments or {}}
89
- res = self._rpc("callTool", args)
90
- # return structuredContent when possible
91
- if isinstance(res, dict) and "structuredContent" in res:
92
- return res["structuredContent"]
93
- # fallback: maybe top-level result
94
- return res
95
-
96
- # ----- Generic callTool wrapper -----
97
- def call_tool(
98
- self, tool: str, arguments: Optional[Dict[str, Any]] = None
99
- ) -> Dict[str, Any]:
100
- args = {"tool": tool, "arguments": arguments or {}}
101
- res = self._rpc("callTool", args)
102
- # # return structuredContent when possible
103
- # if isinstance(res, dict) and "structuredContent" in res:
104
- # return res["structuredContent"]
105
- # # fallback: maybe top-level result
106
- return res
107
-
108
- # ----- Session helpers -----
109
- def create_session(self, cdpUrl: str) -> str:
110
- result = self.call_tool_structured("createSession", {"cdpUrl": cdpUrl})
111
- # Many MCP servers put sessionId in structuredContent.sessionId or result.sessionId
112
- session_id = None
113
- if isinstance(result, dict):
114
- session_id = (
115
- result.get("sessionId") or result.get("session_id") or result.get("id")
116
- )
117
- if not session_id:
118
- # fallback: try raw result text or content
119
- raise MCPError("createSession did not return sessionId")
120
- # store meta
121
- self._sessions[session_id] = {"created_at": time.time()}
122
- return session_id
123
-
124
- def close_session(self, session_id: str) -> bool:
125
- try:
126
- self.call_tool_structured("closeSession", {"sessionId": session_id})
127
- if session_id in self._sessions:
128
- del self._sessions[session_id]
129
- return True
130
- except MCPError:
131
- # still remove local record if present
132
- self._sessions.pop(session_id, None)
133
- raise
134
-
135
- def list_local_sessions(self) -> List[str]:
136
- return list(self._sessions.keys())
@@ -1,173 +0,0 @@
1
- from typing import Any, Dict, Optional
2
-
3
- from .client import MCPClient
4
-
5
-
6
- class MCPTools:
7
- """
8
- Wrapper chuẩn cho Google ADK + MCP Server.
9
- - Tool nào trả text/html/... → dùng structuredContent
10
- - Tool screenshot → trả đúng content để ADK Web hiển thị image
11
- """
12
-
13
- def __init__(self, client: MCPClient):
14
- self.client = client
15
-
16
- # ======================================================
17
- # SESSION MANAGEMENT
18
- # ======================================================
19
-
20
- def create_session(self, cdpUrl: str) -> Dict[str, Any]:
21
- sid = self.client.create_session(cdpUrl)
22
- return {"sessionId": sid}
23
-
24
- def close_session(self, sessionId: str) -> Dict[str, Any]:
25
- ok = self.client.close_session(sessionId)
26
- return {"ok": bool(ok)}
27
-
28
- def list_sessions(self) -> Dict[str, Any]:
29
- return {"sessions": self.client.list_local_sessions()}
30
-
31
- # ======================================================
32
- # NAVIGATION & DOM
33
- # ======================================================
34
-
35
- def open_page(self, sessionId: str, url: str) -> Dict[str, Any]:
36
- return self.client.call_tool(
37
- "openPage", {"sessionId": sessionId, "url": url}
38
- ).get("structuredContent", {})
39
-
40
- def get_html(self, sessionId: str) -> Dict[str, Any]:
41
- return self.client.call_tool("getHTML", {"sessionId": sessionId}).get(
42
- "structuredContent", {}
43
- )
44
-
45
- def screenshot(self, sessionId: str) -> Dict[str, Any]:
46
- """
47
- Trả về đúng phần IMAGE content:
48
- {
49
- "type": "image",
50
- "mimeType": "image/png",
51
- "data": "<base64>"
52
- }
53
- """
54
- full = self.client.call_tool("screenshot", {"sessionId": sessionId})
55
- return full["content"][0]
56
-
57
- def click(self, sessionId: str, selector: str) -> Dict[str, Any]:
58
- return self.client.call_tool(
59
- "click", {"sessionId": sessionId, "selector": selector}
60
- ).get("structuredContent", {})
61
-
62
- def type(self, sessionId: str, selector: str, text: str) -> Dict[str, Any]:
63
- return self.client.call_tool(
64
- "type", {"sessionId": sessionId, "selector": selector, "text": text}
65
- ).get("structuredContent", {})
66
-
67
- def evaluate(self, sessionId: str, expression: str) -> Dict[str, Any]:
68
- return self.client.call_tool(
69
- "evaluate", {"sessionId": sessionId, "expression": expression}
70
- ).get("structuredContent", {})
71
-
72
- # ======================================================
73
- # ELEMENT UTILITIES
74
- # ======================================================
75
-
76
- def find_element(self, sessionId: str, selector: str) -> Dict[str, Any]:
77
- return self.client.call_tool(
78
- "findElement", {"sessionId": sessionId, "selector": selector}
79
- ).get("structuredContent", {})
80
-
81
- def find_all(self, sessionId: str, selector: str) -> Dict[str, Any]:
82
- return self.client.call_tool(
83
- "findAll", {"sessionId": sessionId, "selector": selector}
84
- ).get("structuredContent", {})
85
-
86
- def get_bounding_box(self, sessionId: str, selector: str) -> Dict[str, Any]:
87
- return self.client.call_tool(
88
- "getBoundingBox", {"sessionId": sessionId, "selector": selector}
89
- ).get("structuredContent", {})
90
-
91
- def click_bounding_box(self, sessionId: str, selector: str) -> Dict[str, Any]:
92
- return self.client.call_tool(
93
- "clickBoundingBox", {"sessionId": sessionId, "selector": selector}
94
- ).get("structuredContent", {})
95
-
96
- def upload_file(
97
- self, sessionId: str, selector: str, filename: str, base64data: str
98
- ) -> Dict[str, Any]:
99
- """
100
- Upload file vào input[type=file]
101
- Args:
102
- sessionId: MCP browser session
103
- selector: CSS selector, ví dụ 'input[type=file]'
104
- filename: tên file trên browser side
105
- base64data: dữ liệu base64 (không kèm header)
106
- Returns:
107
- structured result từ server
108
- """
109
- return self.client.call_tool(
110
- "uploadFile",
111
- {
112
- "sessionId": sessionId,
113
- "selector": selector,
114
- "filename": filename,
115
- "data": base64data,
116
- },
117
- ).get("structuredContent", {})
118
-
119
- def wait_for_selector(
120
- self, sessionId: str, selector: str, timeoutMs: Optional[int] = None
121
- ) -> Dict[str, Any]:
122
- args = {"sessionId": sessionId, "selector": selector}
123
- if timeoutMs is not None:
124
- args["timeoutMs"] = int(timeoutMs)
125
-
126
- return self.client.call_tool("waitForSelector", args).get(
127
- "structuredContent", {}
128
- )
129
-
130
- # ======================================================
131
- # TAB MANAGEMENT
132
- # ======================================================
133
-
134
- def new_tab(
135
- self, sessionId: str, url: Optional[str] = "about:blank"
136
- ) -> Dict[str, Any]:
137
- return self.client.call_tool(
138
- "newTab", {"sessionId": sessionId, "url": url}
139
- ).get("structuredContent", {})
140
-
141
- def switch_tab(self, sessionId: str, targetId: str) -> Dict[str, Any]:
142
- return self.client.call_tool(
143
- "switchTab", {"sessionId": sessionId, "targetId": targetId}
144
- ).get("structuredContent", {})
145
-
146
- # ======================================================
147
- # ADVANCED ACTIONS
148
- # ======================================================
149
-
150
- def click_to_text(self, sessionId: str, text: str) -> dict:
151
- return self.client.call_tool(
152
- "clickToText", {"sessionId": sessionId, "text": text}
153
- ).get("structuredContent", {})
154
-
155
- def find_element_xpath(self, sessionId: str, xpath: str) -> Dict[str, Any]:
156
- return self.client.call_tool(
157
- "findElementByXPath", {"sessionId": sessionId, "xpath": xpath}
158
- ).get("structuredContent", {})
159
-
160
- def find_element_by_text(self, sessionId: str, text: str) -> Dict[str, Any]:
161
- return self.client.call_tool(
162
- "findElementByText", {"sessionId": sessionId, "text": text}
163
- ).get("structuredContent", {})
164
-
165
- def click_by_node_id(self, sessionId: str, nodeId: int) -> Dict[str, Any]:
166
- return self.client.call_tool(
167
- "clickByNodeId", {"sessionId": sessionId, "nodeId": nodeId}
168
- ).get("structuredContent", {})
169
-
170
- def import_cookies(self, sessionId: str, cookies: dict) -> Dict[str, Any]:
171
- return self.client.call_tool(
172
- "importCookies", {"sessionId": sessionId, "cookies": cookies}
173
- ).get("structuredContent", {})
File without changes