amazon-ads-mcp 0.2.7__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.
- amazon_ads_mcp/__init__.py +11 -0
- amazon_ads_mcp/auth/__init__.py +33 -0
- amazon_ads_mcp/auth/base.py +211 -0
- amazon_ads_mcp/auth/hooks.py +172 -0
- amazon_ads_mcp/auth/manager.py +791 -0
- amazon_ads_mcp/auth/oauth_state_store.py +277 -0
- amazon_ads_mcp/auth/providers/__init__.py +14 -0
- amazon_ads_mcp/auth/providers/direct.py +393 -0
- amazon_ads_mcp/auth/providers/example_auth0.py.example +216 -0
- amazon_ads_mcp/auth/providers/openbridge.py +512 -0
- amazon_ads_mcp/auth/registry.py +146 -0
- amazon_ads_mcp/auth/secure_token_store.py +297 -0
- amazon_ads_mcp/auth/token_store.py +723 -0
- amazon_ads_mcp/config/__init__.py +5 -0
- amazon_ads_mcp/config/sampling.py +111 -0
- amazon_ads_mcp/config/settings.py +366 -0
- amazon_ads_mcp/exceptions.py +314 -0
- amazon_ads_mcp/middleware/__init__.py +11 -0
- amazon_ads_mcp/middleware/authentication.py +1474 -0
- amazon_ads_mcp/middleware/caching.py +177 -0
- amazon_ads_mcp/middleware/oauth.py +175 -0
- amazon_ads_mcp/middleware/sampling.py +112 -0
- amazon_ads_mcp/models/__init__.py +320 -0
- amazon_ads_mcp/models/amc_models.py +837 -0
- amazon_ads_mcp/models/api_responses.py +847 -0
- amazon_ads_mcp/models/base_models.py +215 -0
- amazon_ads_mcp/models/builtin_responses.py +496 -0
- amazon_ads_mcp/models/dsp_models.py +556 -0
- amazon_ads_mcp/models/stores_brands.py +610 -0
- amazon_ads_mcp/server/__init__.py +6 -0
- amazon_ads_mcp/server/__main__.py +6 -0
- amazon_ads_mcp/server/builtin_prompts.py +269 -0
- amazon_ads_mcp/server/builtin_tools.py +962 -0
- amazon_ads_mcp/server/file_routes.py +547 -0
- amazon_ads_mcp/server/html_templates.py +149 -0
- amazon_ads_mcp/server/mcp_server.py +327 -0
- amazon_ads_mcp/server/openapi_utils.py +158 -0
- amazon_ads_mcp/server/sampling_handler.py +251 -0
- amazon_ads_mcp/server/server_builder.py +751 -0
- amazon_ads_mcp/server/sidecar_loader.py +178 -0
- amazon_ads_mcp/server/transform_executor.py +827 -0
- amazon_ads_mcp/tools/__init__.py +22 -0
- amazon_ads_mcp/tools/cache_management.py +105 -0
- amazon_ads_mcp/tools/download_tools.py +267 -0
- amazon_ads_mcp/tools/identity.py +236 -0
- amazon_ads_mcp/tools/oauth.py +598 -0
- amazon_ads_mcp/tools/profile.py +150 -0
- amazon_ads_mcp/tools/profile_listing.py +285 -0
- amazon_ads_mcp/tools/region.py +320 -0
- amazon_ads_mcp/tools/region_identity.py +175 -0
- amazon_ads_mcp/utils/__init__.py +6 -0
- amazon_ads_mcp/utils/async_compat.py +215 -0
- amazon_ads_mcp/utils/errors.py +452 -0
- amazon_ads_mcp/utils/export_content_type_resolver.py +249 -0
- amazon_ads_mcp/utils/export_download_handler.py +579 -0
- amazon_ads_mcp/utils/header_resolver.py +81 -0
- amazon_ads_mcp/utils/http/__init__.py +56 -0
- amazon_ads_mcp/utils/http/circuit_breaker.py +127 -0
- amazon_ads_mcp/utils/http/client_manager.py +329 -0
- amazon_ads_mcp/utils/http/request.py +207 -0
- amazon_ads_mcp/utils/http/resilience.py +512 -0
- amazon_ads_mcp/utils/http/resilient_client.py +195 -0
- amazon_ads_mcp/utils/http/retry.py +76 -0
- amazon_ads_mcp/utils/http_client.py +873 -0
- amazon_ads_mcp/utils/media/__init__.py +21 -0
- amazon_ads_mcp/utils/media/negotiator.py +243 -0
- amazon_ads_mcp/utils/media/types.py +199 -0
- amazon_ads_mcp/utils/openapi/__init__.py +16 -0
- amazon_ads_mcp/utils/openapi/json.py +55 -0
- amazon_ads_mcp/utils/openapi/loader.py +263 -0
- amazon_ads_mcp/utils/openapi/refs.py +46 -0
- amazon_ads_mcp/utils/region_config.py +200 -0
- amazon_ads_mcp/utils/response_wrapper.py +171 -0
- amazon_ads_mcp/utils/sampling_helpers.py +156 -0
- amazon_ads_mcp/utils/sampling_wrapper.py +173 -0
- amazon_ads_mcp/utils/security.py +630 -0
- amazon_ads_mcp/utils/tool_naming.py +137 -0
- amazon_ads_mcp-0.2.7.dist-info/METADATA +664 -0
- amazon_ads_mcp-0.2.7.dist-info/RECORD +82 -0
- amazon_ads_mcp-0.2.7.dist-info/WHEEL +4 -0
- amazon_ads_mcp-0.2.7.dist-info/entry_points.txt +3 -0
- amazon_ads_mcp-0.2.7.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""HTTP request utilities with response handling and retry logic.
|
|
2
|
+
|
|
3
|
+
This module provides a simplified interface for making HTTP requests
|
|
4
|
+
with automatic retry logic and convenient response handling. It
|
|
5
|
+
includes a wrapper class for HTTP responses that provides easy access
|
|
6
|
+
to common response properties and methods.
|
|
7
|
+
|
|
8
|
+
The module integrates with the HTTP client manager and retry decorator
|
|
9
|
+
to provide robust HTTP communication capabilities.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any, Dict, Optional
|
|
13
|
+
|
|
14
|
+
import httpx
|
|
15
|
+
|
|
16
|
+
from .client_manager import get_http_client
|
|
17
|
+
from .retry import async_retry
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class HTTPResponse:
|
|
21
|
+
"""Wrapper for HTTP responses with convenient access methods.
|
|
22
|
+
|
|
23
|
+
This class wraps httpx.Response objects and provides easy access
|
|
24
|
+
to common response properties and methods. It includes caching
|
|
25
|
+
for JSON responses to avoid repeated parsing and provides
|
|
26
|
+
convenient boolean methods for checking response status.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, response: httpx.Response):
|
|
30
|
+
"""Initialize the response wrapper.
|
|
31
|
+
|
|
32
|
+
:param response: The underlying httpx.Response object
|
|
33
|
+
:type response: httpx.Response
|
|
34
|
+
"""
|
|
35
|
+
self.response = response
|
|
36
|
+
self._json_cache = None
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def status_code(self) -> int:
|
|
40
|
+
"""Get the HTTP status code of the response.
|
|
41
|
+
|
|
42
|
+
:return: HTTP status code
|
|
43
|
+
:rtype: int
|
|
44
|
+
"""
|
|
45
|
+
return self.response.status_code
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def headers(self) -> httpx.Headers:
|
|
49
|
+
"""Get the response headers.
|
|
50
|
+
|
|
51
|
+
:return: Response headers
|
|
52
|
+
:rtype: httpx.Headers
|
|
53
|
+
"""
|
|
54
|
+
return self.response.headers
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def text(self) -> str:
|
|
58
|
+
"""Get the response body as text.
|
|
59
|
+
|
|
60
|
+
:return: Response body text
|
|
61
|
+
:rtype: str
|
|
62
|
+
"""
|
|
63
|
+
return self.response.text
|
|
64
|
+
|
|
65
|
+
def json(self) -> Any:
|
|
66
|
+
"""Get the response body as parsed JSON.
|
|
67
|
+
|
|
68
|
+
The result is cached to avoid repeated parsing of the same
|
|
69
|
+
response body.
|
|
70
|
+
|
|
71
|
+
:return: Parsed JSON response
|
|
72
|
+
:rtype: Any
|
|
73
|
+
"""
|
|
74
|
+
if self._json_cache is None:
|
|
75
|
+
self._json_cache = self.response.json()
|
|
76
|
+
return self._json_cache
|
|
77
|
+
|
|
78
|
+
def is_success(self) -> bool:
|
|
79
|
+
"""Check if the response indicates success (2xx status code).
|
|
80
|
+
|
|
81
|
+
:return: True if status code is in 200-299 range
|
|
82
|
+
:rtype: bool
|
|
83
|
+
"""
|
|
84
|
+
return 200 <= self.status_code < 300
|
|
85
|
+
|
|
86
|
+
def is_client_error(self) -> bool:
|
|
87
|
+
"""Check if the response indicates a client error (4xx status code).
|
|
88
|
+
|
|
89
|
+
:return: True if status code is in 400-499 range
|
|
90
|
+
:rtype: bool
|
|
91
|
+
"""
|
|
92
|
+
return 400 <= self.status_code < 500
|
|
93
|
+
|
|
94
|
+
def is_server_error(self) -> bool:
|
|
95
|
+
"""Check if the response indicates a server error (5xx status code).
|
|
96
|
+
|
|
97
|
+
:return: True if status code is in 500-599 range
|
|
98
|
+
:rtype: bool
|
|
99
|
+
"""
|
|
100
|
+
return 500 <= self.status_code < 600
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@async_retry(max_attempts=3, delay=1.0, backoff=2.0)
|
|
104
|
+
async def make_request(
|
|
105
|
+
method: str,
|
|
106
|
+
url: str,
|
|
107
|
+
headers: Optional[Dict[str, str]] = None,
|
|
108
|
+
json_data: Optional[Dict[str, Any]] = None,
|
|
109
|
+
params: Optional[Dict[str, Any]] = None,
|
|
110
|
+
timeout: Optional[float] = None,
|
|
111
|
+
**kwargs,
|
|
112
|
+
) -> HTTPResponse:
|
|
113
|
+
"""Make an HTTP request with automatic retry logic.
|
|
114
|
+
|
|
115
|
+
This function makes HTTP requests with configurable parameters
|
|
116
|
+
and automatic retry on failure. It uses the HTTP client manager
|
|
117
|
+
to get an appropriate client and applies retry logic for
|
|
118
|
+
transient failures.
|
|
119
|
+
|
|
120
|
+
:param method: HTTP method (e.g., 'GET', 'POST', 'PUT')
|
|
121
|
+
:type method: str
|
|
122
|
+
:param url: URL to make the request to
|
|
123
|
+
:type url: str
|
|
124
|
+
:param headers: Optional request headers
|
|
125
|
+
:type headers: Optional[Dict[str, str]]
|
|
126
|
+
:param json_data: Optional JSON data to send in request body
|
|
127
|
+
:type json_data: Optional[Dict[str, Any]]
|
|
128
|
+
:param params: Optional query parameters
|
|
129
|
+
:type params: Optional[Dict[str, Any]]
|
|
130
|
+
:param timeout: Optional request timeout in seconds
|
|
131
|
+
:type timeout: Optional[float]
|
|
132
|
+
:param **kwargs: Additional request parameters
|
|
133
|
+
:return: HTTPResponse wrapper containing the response
|
|
134
|
+
:rtype: HTTPResponse
|
|
135
|
+
:raises httpx.HTTPStatusError: If the response status indicates an error
|
|
136
|
+
"""
|
|
137
|
+
client = await get_http_client()
|
|
138
|
+
|
|
139
|
+
request_kwargs = {"headers": headers, "params": params, **kwargs}
|
|
140
|
+
if json_data is not None:
|
|
141
|
+
request_kwargs["json"] = json_data
|
|
142
|
+
if timeout is not None:
|
|
143
|
+
request_kwargs["timeout"] = timeout
|
|
144
|
+
|
|
145
|
+
response = await client.request(method, url, **request_kwargs)
|
|
146
|
+
response.raise_for_status()
|
|
147
|
+
return HTTPResponse(response)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
async def get(url: str, **kwargs) -> HTTPResponse:
|
|
151
|
+
"""Make a GET request.
|
|
152
|
+
|
|
153
|
+
:param url: URL to make the GET request to
|
|
154
|
+
:type url: str
|
|
155
|
+
:param **kwargs: Additional request parameters
|
|
156
|
+
:return: HTTPResponse wrapper containing the response
|
|
157
|
+
:rtype: HTTPResponse
|
|
158
|
+
"""
|
|
159
|
+
return await make_request("GET", url, **kwargs)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
async def post(url: str, **kwargs) -> HTTPResponse:
|
|
163
|
+
"""Make a POST request.
|
|
164
|
+
|
|
165
|
+
:param url: URL to make the POST request to
|
|
166
|
+
:type url: str
|
|
167
|
+
:param **kwargs: Additional request parameters
|
|
168
|
+
:return: HTTPResponse wrapper containing the response
|
|
169
|
+
:rtype: HTTPResponse
|
|
170
|
+
"""
|
|
171
|
+
return await make_request("POST", url, **kwargs)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
async def put(url: str, **kwargs) -> HTTPResponse:
|
|
175
|
+
"""Make a PUT request.
|
|
176
|
+
|
|
177
|
+
:param url: URL to make the PUT request to
|
|
178
|
+
:type url: str
|
|
179
|
+
:param **kwargs: Additional request parameters
|
|
180
|
+
:return: HTTPResponse wrapper containing the response
|
|
181
|
+
:rtype: HTTPResponse
|
|
182
|
+
"""
|
|
183
|
+
return await make_request("PUT", url, **kwargs)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def delete(url: str, **kwargs) -> HTTPResponse:
|
|
187
|
+
"""Make a DELETE request.
|
|
188
|
+
|
|
189
|
+
:param url: URL to make the DELETE request to
|
|
190
|
+
:type url: str
|
|
191
|
+
:param **kwargs: Additional request parameters
|
|
192
|
+
:return: HTTPResponse wrapper containing the response
|
|
193
|
+
:rtype: HTTPResponse
|
|
194
|
+
"""
|
|
195
|
+
return await make_request("DELETE", url, **kwargs)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
async def patch(url: str, **kwargs) -> HTTPResponse:
|
|
199
|
+
"""Make a PATCH request.
|
|
200
|
+
|
|
201
|
+
:param url: URL to make the PATCH request to
|
|
202
|
+
:type url: str
|
|
203
|
+
:param **kwargs: Additional request parameters
|
|
204
|
+
:return: HTTPResponse wrapper containing the response
|
|
205
|
+
:rtype: HTTPResponse
|
|
206
|
+
"""
|
|
207
|
+
return await make_request("PATCH", url, **kwargs)
|