agbcloud-sdk 0.1.0__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.
- agb/__init__.py +7 -0
- agb/agb.py +215 -0
- agb/api/__init__.py +11 -0
- agb/api/base_service.py +122 -0
- agb/api/client.py +257 -0
- agb/api/http_client.py +660 -0
- agb/api/models/__init__.py +36 -0
- agb/api/models/call_mcp_tool_request.py +51 -0
- agb/api/models/call_mcp_tool_response.py +149 -0
- agb/api/models/create_session_request.py +32 -0
- agb/api/models/create_session_response.py +165 -0
- agb/api/models/get_link_request.py +78 -0
- agb/api/models/get_link_response.py +128 -0
- agb/api/models/get_mcp_resource_request.py +27 -0
- agb/api/models/get_mcp_resource_response.py +193 -0
- agb/api/models/init_browser_request.py +76 -0
- agb/api/models/init_browser_response.py +133 -0
- agb/api/models/list_mcp_tools_request.py +27 -0
- agb/api/models/list_mcp_tools_response.py +113 -0
- agb/api/models/release_session_request.py +27 -0
- agb/api/models/release_session_response.py +102 -0
- agb/config.py +54 -0
- agb/exceptions.py +65 -0
- agb/model/__init__.py +15 -0
- agb/model/response.py +137 -0
- agb/modules/__init__.py +35 -0
- agb/modules/browser/__init__.py +21 -0
- agb/modules/browser/browser.py +419 -0
- agb/modules/browser/browser_agent.py +470 -0
- agb/modules/browser/eval/local_page_agent.py +203 -0
- agb/modules/browser/eval/page_agent.py +351 -0
- agb/modules/browser/eval/page_tasks/allrecipes.py +85 -0
- agb/modules/browser/eval/page_tasks/apple.py +40 -0
- agb/modules/browser/eval/page_tasks/arxiv.py +107 -0
- agb/modules/browser/eval/page_tasks/combination_sauce.py +62 -0
- agb/modules/browser/eval/page_tasks/extract_aigrant_companies.py +73 -0
- agb/modules/browser/eval/page_tasks/extract_apartments.py +60 -0
- agb/modules/browser/eval/page_tasks/extract_area_codes.py +205 -0
- agb/modules/browser/eval/page_tasks/imdb_movie_details.py +78 -0
- agb/modules/browser/eval/page_tasks/nonsense_action.py +28 -0
- agb/modules/browser/eval/page_tasks/observe_amazon_add_to_cart.py +44 -0
- agb/modules/browser/eval/page_tasks/observe_iframes1.py +74 -0
- agb/modules/browser/eval/page_tasks/simple_google_search.py +16 -0
- agb/modules/browser/eval/page_tasks/tegner_shop.py +129 -0
- agb/modules/browser/eval/page_tasks/vanta_h.py +23 -0
- agb/modules/browser/eval/run_page_evals.py +192 -0
- agb/modules/browser/eval/service.py +1879 -0
- agb/modules/code.py +90 -0
- agb/modules/command.py +70 -0
- agb/modules/file_system.py +788 -0
- agb/modules/oss.py +331 -0
- agb/session.py +205 -0
- agb/session_params.py +23 -0
- agbcloud_sdk-0.1.0.dist-info/METADATA +131 -0
- agbcloud_sdk-0.1.0.dist-info/RECORD +58 -0
- agbcloud_sdk-0.1.0.dist-info/WHEEL +5 -0
- agbcloud_sdk-0.1.0.dist-info/licenses/LICENSE +201 -0
- agbcloud_sdk-0.1.0.dist-info/top_level.txt +1 -0
agb/__init__.py
ADDED
agb/agb.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AGB represents the main client for interacting with the AGB cloud runtime
|
|
4
|
+
environment.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
from typing import Dict, List, Optional, Union
|
|
10
|
+
from threading import Lock
|
|
11
|
+
|
|
12
|
+
from agb.api.client import Client as mcp_client
|
|
13
|
+
from agb.api.models import (
|
|
14
|
+
CreateSessionRequest,
|
|
15
|
+
ReleaseSessionRequest,
|
|
16
|
+
CreateSessionResponse,
|
|
17
|
+
)
|
|
18
|
+
from agb.config import load_config, Config
|
|
19
|
+
from agb.session import Session, BaseSession
|
|
20
|
+
from agb.session_params import CreateSessionParams
|
|
21
|
+
from agb.model.response import SessionResult, DeleteResult
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AGB:
|
|
25
|
+
"""
|
|
26
|
+
AGB represents the main client for interacting with the AGB cloud runtime
|
|
27
|
+
environment.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, api_key: str = "", cfg: Optional[Config] = None):
|
|
31
|
+
"""
|
|
32
|
+
Initialize the AGB client.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
api_key (str): API key for authentication. If not provided, it will be
|
|
36
|
+
loaded from the AGB_API_KEY environment variable.
|
|
37
|
+
cfg (Optional[Config]): Configuration object. If not provided, default
|
|
38
|
+
configuration will be used.
|
|
39
|
+
"""
|
|
40
|
+
if not api_key:
|
|
41
|
+
api_key = os.getenv("AGB_API_KEY")
|
|
42
|
+
if not api_key:
|
|
43
|
+
raise ValueError(
|
|
44
|
+
"API key is required. Provide it as a parameter or set the "
|
|
45
|
+
"AGB_API_KEY environment variable"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Load configuration
|
|
49
|
+
self.config = load_config(cfg)
|
|
50
|
+
|
|
51
|
+
self.api_key = api_key
|
|
52
|
+
self.endpoint = self.config.endpoint
|
|
53
|
+
self.timeout_ms = self.config.timeout_ms
|
|
54
|
+
|
|
55
|
+
# Initialize the HTTP API client with the complete config
|
|
56
|
+
self.client = mcp_client(self.config)
|
|
57
|
+
self._sessions = {}
|
|
58
|
+
self._lock = Lock()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def create(self, params: Optional[CreateSessionParams] = None) -> SessionResult:
|
|
62
|
+
"""
|
|
63
|
+
Create a new session in the AGB cloud environment.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
params (Optional[CreateSessionParams], optional): Parameters for
|
|
67
|
+
creating the session.Defaults to None.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
SessionResult: Result containing the created session and request ID.
|
|
71
|
+
"""
|
|
72
|
+
try:
|
|
73
|
+
if params is None:
|
|
74
|
+
params = CreateSessionParams()
|
|
75
|
+
|
|
76
|
+
request = CreateSessionRequest(authorization=f"Bearer {self.api_key}")
|
|
77
|
+
|
|
78
|
+
if params.image_id:
|
|
79
|
+
request.image_id = params.image_id
|
|
80
|
+
|
|
81
|
+
response : CreateSessionResponse = self.client.create_mcp_session(request)
|
|
82
|
+
|
|
83
|
+
# Check if response is empty
|
|
84
|
+
if response is None:
|
|
85
|
+
return SessionResult(
|
|
86
|
+
request_id="",
|
|
87
|
+
success=False,
|
|
88
|
+
error_message="OpenAPI client returned None response",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
print("Response body:")
|
|
93
|
+
print(response.to_dict())
|
|
94
|
+
except Exception:
|
|
95
|
+
print(f"Response: {response}")
|
|
96
|
+
|
|
97
|
+
# Extract request ID
|
|
98
|
+
request_id = getattr(response, 'request_id', '') or ''
|
|
99
|
+
|
|
100
|
+
# Check if the session creation was successful
|
|
101
|
+
if response.data and response.data.success is False:
|
|
102
|
+
error_msg = response.data.err_msg
|
|
103
|
+
if error_msg is None:
|
|
104
|
+
error_msg = "Unknown error"
|
|
105
|
+
return SessionResult(
|
|
106
|
+
request_id=request_id,
|
|
107
|
+
success=False,
|
|
108
|
+
error_message=error_msg,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
session_id = response.get_session_id()
|
|
112
|
+
if not session_id:
|
|
113
|
+
return SessionResult(
|
|
114
|
+
request_id=request_id,
|
|
115
|
+
success=False,
|
|
116
|
+
error_message=response.get_error_message(),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# ResourceUrl is optional in CreateMcpSession response
|
|
120
|
+
resource_url = response.get_resource_url()
|
|
121
|
+
|
|
122
|
+
print("session_id =", session_id)
|
|
123
|
+
print("resource_url =", resource_url)
|
|
124
|
+
|
|
125
|
+
# Create Session object
|
|
126
|
+
session = Session(self, session_id)
|
|
127
|
+
if resource_url is not None:
|
|
128
|
+
session.resource_url = resource_url
|
|
129
|
+
|
|
130
|
+
# Store image_id used for this session
|
|
131
|
+
session.image_id = params.image_id
|
|
132
|
+
|
|
133
|
+
with self._lock:
|
|
134
|
+
self._sessions[session_id] = session
|
|
135
|
+
|
|
136
|
+
# Return SessionResult with request ID
|
|
137
|
+
return SessionResult(request_id=request_id, success=True, session=session)
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
print("Error calling create_mcp_session:", e)
|
|
141
|
+
return SessionResult(
|
|
142
|
+
request_id="",
|
|
143
|
+
success=False,
|
|
144
|
+
error_message=f"Failed to create session: {e}",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def list(self) -> List[BaseSession]:
|
|
148
|
+
"""
|
|
149
|
+
List all available sessions.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List[BaseSession]: A list of all available sessions.
|
|
153
|
+
"""
|
|
154
|
+
with self._lock:
|
|
155
|
+
return list(self._sessions.values())
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def delete(self, session: Session) -> DeleteResult:
|
|
159
|
+
"""
|
|
160
|
+
Delete a session by session object.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
session (Session): The session to delete.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
DeleteResult: Result indicating success or failure and request ID.
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
# Create request to release the session
|
|
170
|
+
request = ReleaseSessionRequest(
|
|
171
|
+
authorization=f"Bearer {self.api_key}",
|
|
172
|
+
session_id=session.session_id,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Make the API call
|
|
176
|
+
response = self.client.release_mcp_session(request)
|
|
177
|
+
|
|
178
|
+
# Check if response is empty
|
|
179
|
+
if response is None:
|
|
180
|
+
return DeleteResult(
|
|
181
|
+
request_id="",
|
|
182
|
+
success=False,
|
|
183
|
+
error_message="OpenAPI client returned None response",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Check response type, if it's ReleaseSessionResponse, use new parsing method
|
|
187
|
+
if hasattr(response, 'is_successful'):
|
|
188
|
+
# This is a ReleaseSessionResponse object
|
|
189
|
+
if response.is_successful():
|
|
190
|
+
# Remove from local cache
|
|
191
|
+
with self._lock:
|
|
192
|
+
self._sessions.pop(session.session_id, None)
|
|
193
|
+
|
|
194
|
+
return DeleteResult(request_id=response.request_id or "", success=True)
|
|
195
|
+
else:
|
|
196
|
+
error_msg = response.get_error_message() or "Failed to delete session"
|
|
197
|
+
return DeleteResult(
|
|
198
|
+
request_id=response.request_id or "",
|
|
199
|
+
success=False,
|
|
200
|
+
error_message=error_msg,
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
return DeleteResult(
|
|
204
|
+
request_id=response.request_id or "",
|
|
205
|
+
success=False,
|
|
206
|
+
error_message="Failed to delete session",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
except Exception as e:
|
|
210
|
+
print("Error calling release_mcp_session:", e)
|
|
211
|
+
# In case of error, return failure result with error message
|
|
212
|
+
return DeleteResult(
|
|
213
|
+
success=False,
|
|
214
|
+
error_message=f"Failed to delete session {session.session_id}: {e}",
|
|
215
|
+
)
|
agb/api/__init__.py
ADDED
agb/api/base_service.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import requests
|
|
3
|
+
import time
|
|
4
|
+
import random
|
|
5
|
+
import string
|
|
6
|
+
from typing import Any, Dict
|
|
7
|
+
|
|
8
|
+
from agb.api.models import CallMcpToolRequest
|
|
9
|
+
from agb.exceptions import AGBError
|
|
10
|
+
from agb.model import OperationResult
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseService:
|
|
14
|
+
"""
|
|
15
|
+
Base service class that provides common functionality for all service classes.
|
|
16
|
+
This class implements the common methods for calling MCP tools and parsing
|
|
17
|
+
responses.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, session):
|
|
21
|
+
"""
|
|
22
|
+
Initialize a BaseService object.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
session: The Session instance that this service belongs to.
|
|
26
|
+
"""
|
|
27
|
+
self.session = session
|
|
28
|
+
|
|
29
|
+
def _handle_error(self, e):
|
|
30
|
+
"""
|
|
31
|
+
Handle and convert exceptions. This method should be overridden by subclasses
|
|
32
|
+
to provide specific error handling.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
e (Exception): The exception to handle.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Exception: The handled exception.
|
|
39
|
+
"""
|
|
40
|
+
return e
|
|
41
|
+
|
|
42
|
+
def _call_mcp_tool(self, name: str, args: Dict[str, Any], read_timeout: int = None, connect_timeout: int = None) -> OperationResult:
|
|
43
|
+
"""
|
|
44
|
+
Internal helper to call MCP tool and handle errors.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
name (str): The name of the tool to call.
|
|
48
|
+
args (Dict[str, Any]): The arguments to pass to the tool.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
OperationResult: The response from the tool with request ID.
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
args_json = json.dumps(args, ensure_ascii=False)
|
|
55
|
+
|
|
56
|
+
# use traditional API call
|
|
57
|
+
request = CallMcpToolRequest(
|
|
58
|
+
authorization=f"Bearer {self.session.get_api_key()}",
|
|
59
|
+
session_id=self.session.get_session_id(),
|
|
60
|
+
name=name,
|
|
61
|
+
args=args_json,
|
|
62
|
+
)
|
|
63
|
+
response = self.session.get_client().call_mcp_tool(request, read_timeout=read_timeout, connect_timeout=connect_timeout)
|
|
64
|
+
|
|
65
|
+
# Check if response is empty
|
|
66
|
+
if response is None:
|
|
67
|
+
return OperationResult(
|
|
68
|
+
request_id="",
|
|
69
|
+
success=False,
|
|
70
|
+
error_message="OpenAPI client returned None response",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
request_id = response.request_id or ""
|
|
74
|
+
|
|
75
|
+
# Check response type, if it's CallMcpToolResponse, use new parsing method
|
|
76
|
+
if hasattr(response, 'is_tool_successful'):
|
|
77
|
+
# This is a CallMcpToolResponse object
|
|
78
|
+
try:
|
|
79
|
+
print("Response body:")
|
|
80
|
+
print(json.dumps(response.json_data, ensure_ascii=False, indent=2))
|
|
81
|
+
except Exception:
|
|
82
|
+
print(f"Response: {response}")
|
|
83
|
+
|
|
84
|
+
if response.is_tool_successful():
|
|
85
|
+
# Tool execution successful
|
|
86
|
+
result = response.get_tool_result()
|
|
87
|
+
return OperationResult(request_id=request_id, success=True, data=result)
|
|
88
|
+
else:
|
|
89
|
+
# Tool execution failed
|
|
90
|
+
error_msg = response.get_error_message() or "Tool execution failed"
|
|
91
|
+
return OperationResult(
|
|
92
|
+
request_id=request_id,
|
|
93
|
+
success=False,
|
|
94
|
+
error_message=error_msg,
|
|
95
|
+
)
|
|
96
|
+
else:
|
|
97
|
+
# This is the original OpenAPI response object, use existing parsing method
|
|
98
|
+
# Here you can add existing parsing logic if needed
|
|
99
|
+
error_msg = "Unsupported response type"
|
|
100
|
+
return OperationResult(
|
|
101
|
+
request_id=request_id,
|
|
102
|
+
success=False,
|
|
103
|
+
error_message=error_msg,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
except AGBError as e:
|
|
108
|
+
handled_error = self._handle_error(e)
|
|
109
|
+
request_id = "" if "request_id" not in locals() else request_id
|
|
110
|
+
return OperationResult(
|
|
111
|
+
request_id=request_id,
|
|
112
|
+
success=False,
|
|
113
|
+
error_message=str(handled_error),
|
|
114
|
+
)
|
|
115
|
+
except Exception as e:
|
|
116
|
+
handled_error = self._handle_error(e)
|
|
117
|
+
request_id = "" if "request_id" not in locals() else request_id
|
|
118
|
+
return OperationResult(
|
|
119
|
+
request_id=request_id,
|
|
120
|
+
success=False,
|
|
121
|
+
error_message=f"Failed to call MCP tool {name}: {handled_error}",
|
|
122
|
+
)
|
agb/api/client.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AGB API client implementation using HTTP client
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Dict, Optional, Union, List, Any
|
|
7
|
+
from agb.api.models import (
|
|
8
|
+
CreateSessionResponse,
|
|
9
|
+
CallMcpToolResponse,
|
|
10
|
+
ListMcpToolsResponse,
|
|
11
|
+
GetMcpResourceResponse,
|
|
12
|
+
ReleaseSessionResponse,
|
|
13
|
+
CreateSessionRequest,
|
|
14
|
+
ReleaseSessionRequest,
|
|
15
|
+
CallMcpToolRequest,
|
|
16
|
+
ListMcpToolsRequest,
|
|
17
|
+
GetMcpResourceRequest,
|
|
18
|
+
InitBrowserRequest,
|
|
19
|
+
InitBrowserResponse,
|
|
20
|
+
GetLinkRequest,
|
|
21
|
+
GetLinkResponse,
|
|
22
|
+
)
|
|
23
|
+
from .http_client import HTTPClient
|
|
24
|
+
import aiohttp
|
|
25
|
+
|
|
26
|
+
class Client:
|
|
27
|
+
"""
|
|
28
|
+
AGB API client that uses HTTP client
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, config=None):
|
|
32
|
+
"""
|
|
33
|
+
Initialize the client
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
config: Configuration object for HTTP client
|
|
37
|
+
"""
|
|
38
|
+
self.config = config
|
|
39
|
+
self._http_client = None
|
|
40
|
+
|
|
41
|
+
def _get_http_client(self, api_key: str) -> HTTPClient:
|
|
42
|
+
"""
|
|
43
|
+
Get HTTP client instance, creating a new one for each request
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
api_key: API key for authentication
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
HTTPClient: HTTP client instance
|
|
50
|
+
"""
|
|
51
|
+
# Always create a new HTTP client for each request
|
|
52
|
+
return HTTPClient(api_key=api_key, cfg=self.config)
|
|
53
|
+
|
|
54
|
+
def create_mcp_session(self, request: CreateSessionRequest) -> CreateSessionResponse:
|
|
55
|
+
"""
|
|
56
|
+
Create MCP session using HTTP client
|
|
57
|
+
"""
|
|
58
|
+
# Extract API key from authorization header
|
|
59
|
+
if not request.authorization:
|
|
60
|
+
raise ValueError("authorization is required")
|
|
61
|
+
|
|
62
|
+
# Get HTTP client and make request directly with the input request
|
|
63
|
+
http_client = self._get_http_client(request.authorization)
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
response = http_client.create_session(request)
|
|
67
|
+
return response
|
|
68
|
+
finally:
|
|
69
|
+
# Always close the HTTP client to release resources
|
|
70
|
+
http_client.close()
|
|
71
|
+
|
|
72
|
+
def release_mcp_session(self, request: ReleaseSessionRequest) -> ReleaseSessionResponse:
|
|
73
|
+
"""
|
|
74
|
+
Release MCP session using HTTP client
|
|
75
|
+
"""
|
|
76
|
+
if not request.session_id:
|
|
77
|
+
raise ValueError("session_id is required")
|
|
78
|
+
|
|
79
|
+
if not request.authorization:
|
|
80
|
+
raise ValueError("authorization is required")
|
|
81
|
+
|
|
82
|
+
# Get HTTP client and make request directly with the input request
|
|
83
|
+
http_client = self._get_http_client(request.authorization)
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
response = http_client.release_session(request)
|
|
87
|
+
return response
|
|
88
|
+
finally:
|
|
89
|
+
# Always close the HTTP client to release resources
|
|
90
|
+
http_client.close()
|
|
91
|
+
|
|
92
|
+
def call_mcp_tool(self, request: CallMcpToolRequest, read_timeout: int = None, connect_timeout: int = None) -> CallMcpToolResponse:
|
|
93
|
+
"""
|
|
94
|
+
Call MCP tool using HTTP client
|
|
95
|
+
"""
|
|
96
|
+
if not request.authorization:
|
|
97
|
+
raise ValueError("authorization is required")
|
|
98
|
+
|
|
99
|
+
# Get HTTP client and make request directly with the input request
|
|
100
|
+
http_client = self._get_http_client(request.authorization)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
response = http_client.call_mcp_tool(request, read_timeout=read_timeout, connect_timeout=connect_timeout)
|
|
104
|
+
return response
|
|
105
|
+
finally:
|
|
106
|
+
# Always close the HTTP client to release resources
|
|
107
|
+
http_client.close()
|
|
108
|
+
|
|
109
|
+
def list_mcp_tools(self, request: ListMcpToolsRequest) -> ListMcpToolsResponse:
|
|
110
|
+
"""
|
|
111
|
+
List MCP tools using HTTP client
|
|
112
|
+
"""
|
|
113
|
+
if not request.authorization:
|
|
114
|
+
raise ValueError("authorization is required")
|
|
115
|
+
|
|
116
|
+
# Get HTTP client and make request directly with the input request
|
|
117
|
+
http_client = self._get_http_client(request.authorization)
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
response = http_client.list_mcp_tools(request)
|
|
121
|
+
return response
|
|
122
|
+
finally:
|
|
123
|
+
# Always close the HTTP client to release resources
|
|
124
|
+
http_client.close()
|
|
125
|
+
|
|
126
|
+
def get_mcp_resource(self, request: GetMcpResourceRequest) -> GetMcpResourceResponse:
|
|
127
|
+
"""
|
|
128
|
+
Get MCP resource using HTTP client
|
|
129
|
+
"""
|
|
130
|
+
if not request.session_id:
|
|
131
|
+
raise ValueError("session_id is required")
|
|
132
|
+
|
|
133
|
+
if not request.authorization:
|
|
134
|
+
raise ValueError("authorization is required")
|
|
135
|
+
|
|
136
|
+
# Get HTTP client and make request directly with the input request
|
|
137
|
+
http_client = self._get_http_client(request.authorization)
|
|
138
|
+
|
|
139
|
+
try:
|
|
140
|
+
response = http_client.get_mcp_resource(request)
|
|
141
|
+
return response
|
|
142
|
+
finally:
|
|
143
|
+
# Always close the HTTP client to release resources
|
|
144
|
+
http_client.close()
|
|
145
|
+
|
|
146
|
+
def init_browser(self, request: InitBrowserRequest) -> InitBrowserResponse:
|
|
147
|
+
"""
|
|
148
|
+
Initialize browser using HTTP client
|
|
149
|
+
"""
|
|
150
|
+
if not request.authorization:
|
|
151
|
+
raise ValueError("authorization is required")
|
|
152
|
+
|
|
153
|
+
# Get HTTP client and make request directly with the input request
|
|
154
|
+
http_client = self._get_http_client(request.authorization)
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
response = http_client.init_browser(request)
|
|
158
|
+
return response
|
|
159
|
+
finally:
|
|
160
|
+
# Always close the HTTP client to release resources
|
|
161
|
+
http_client.close()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
async def init_browser_async(
|
|
165
|
+
self,
|
|
166
|
+
request: InitBrowserRequest,
|
|
167
|
+
) -> InitBrowserResponse:
|
|
168
|
+
"""
|
|
169
|
+
Async version of init_browser using HTTP client
|
|
170
|
+
"""
|
|
171
|
+
if not request.authorization:
|
|
172
|
+
raise ValueError("authorization is required")
|
|
173
|
+
|
|
174
|
+
# Get HTTP client and make async request
|
|
175
|
+
http_client = self._get_http_client(request.authorization)
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
response = await http_client.init_browser_async(request)
|
|
179
|
+
return response
|
|
180
|
+
finally:
|
|
181
|
+
# Always close the HTTP client to release resources
|
|
182
|
+
http_client.close()
|
|
183
|
+
|
|
184
|
+
def close(self):
|
|
185
|
+
"""Close HTTP client and clean up resources"""
|
|
186
|
+
# No need to manage long-lived HTTP client anymore
|
|
187
|
+
# Each request creates a new client that gets cleaned up automatically
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
async def call_api_async_with_requests(url, method="GET", headers=None, params=None, data=None, json=None, timeout=30):
|
|
191
|
+
"""
|
|
192
|
+
使用 aiohttp 实现异步 HTTP 请求,模拟 requests 的用法。
|
|
193
|
+
"""
|
|
194
|
+
async with aiohttp.ClientSession() as session:
|
|
195
|
+
req_method = getattr(session, method.lower())
|
|
196
|
+
async with req_method(
|
|
197
|
+
url,
|
|
198
|
+
headers=headers,
|
|
199
|
+
params=params,
|
|
200
|
+
data=data,
|
|
201
|
+
json=json,
|
|
202
|
+
timeout=timeout
|
|
203
|
+
) as resp:
|
|
204
|
+
resp_data = await resp.text()
|
|
205
|
+
# 你可以根据需要返回 resp.json() 或 resp.read()
|
|
206
|
+
return {
|
|
207
|
+
"status_code": resp.status,
|
|
208
|
+
"headers": dict(resp.headers),
|
|
209
|
+
"body": resp_data
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def get_link(
|
|
214
|
+
self,
|
|
215
|
+
request: GetLinkRequest,
|
|
216
|
+
) -> GetLinkResponse:
|
|
217
|
+
"""
|
|
218
|
+
Get session link using HTTP client
|
|
219
|
+
"""
|
|
220
|
+
if not request.authorization:
|
|
221
|
+
raise ValueError("authorization is required")
|
|
222
|
+
|
|
223
|
+
if not request.session_id:
|
|
224
|
+
raise ValueError("session_id is required")
|
|
225
|
+
|
|
226
|
+
# Get HTTP client and make request directly with the input request
|
|
227
|
+
http_client = self._get_http_client(request.authorization)
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
response = http_client.get_link(request)
|
|
231
|
+
return response
|
|
232
|
+
finally:
|
|
233
|
+
# Always close the HTTP client to release resources
|
|
234
|
+
http_client.close()
|
|
235
|
+
|
|
236
|
+
async def get_link_async(
|
|
237
|
+
self,
|
|
238
|
+
request: GetLinkRequest,
|
|
239
|
+
) -> GetLinkResponse:
|
|
240
|
+
"""
|
|
241
|
+
Async version of get_link using HTTP client
|
|
242
|
+
"""
|
|
243
|
+
if not request.authorization:
|
|
244
|
+
raise ValueError("authorization is required")
|
|
245
|
+
|
|
246
|
+
if not request.session_id:
|
|
247
|
+
raise ValueError("session_id is required")
|
|
248
|
+
|
|
249
|
+
# Get HTTP client and make async request
|
|
250
|
+
http_client = self._get_http_client(request.authorization)
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
response = await http_client.get_link_async(request)
|
|
254
|
+
return response
|
|
255
|
+
finally:
|
|
256
|
+
# Always close the HTTP client to release resources
|
|
257
|
+
http_client.close()
|