alita-sdk 0.3.442__py3-none-any.whl → 0.3.444__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.
@@ -22,6 +22,7 @@ from ..utils.mcp_oauth import (
22
22
  canonical_resource,
23
23
  extract_resource_metadata_url,
24
24
  fetch_resource_metadata,
25
+ infer_authorization_servers_from_realm,
25
26
  )
26
27
 
27
28
  logger = logging.getLogger(__name__)
@@ -547,6 +548,25 @@ class McpToolkit(BaseToolkit):
547
548
  if response.status_code == 401:
548
549
  resource_metadata_url = extract_resource_metadata_url(auth_header, connection_config.url)
549
550
  metadata = fetch_resource_metadata(resource_metadata_url, timeout=timeout) if resource_metadata_url else None
551
+
552
+ # If we couldn't get metadata from the resource_metadata endpoint,
553
+ # infer authorization servers from the WWW-Authenticate header and server URL
554
+ if not metadata or not metadata.get('authorization_servers'):
555
+ inferred_servers = infer_authorization_servers_from_realm(auth_header, connection_config.url)
556
+ if inferred_servers:
557
+ if not metadata:
558
+ metadata = {}
559
+ metadata['authorization_servers'] = inferred_servers
560
+ logger.info(f"Inferred authorization servers for {connection_config.url}: {inferred_servers}")
561
+
562
+ # Fetch OAuth authorization server metadata from the inferred server
563
+ # This avoids CORS issues in the frontend
564
+ from alita_sdk.runtime.utils.mcp_oauth import fetch_oauth_authorization_server_metadata
565
+ auth_server_metadata = fetch_oauth_authorization_server_metadata(inferred_servers[0], timeout=timeout)
566
+ if auth_server_metadata:
567
+ metadata['oauth_authorization_server'] = auth_server_metadata
568
+ logger.info(f"Fetched OAuth metadata for {inferred_servers[0]}")
569
+
550
570
  raise McpAuthorizationRequired(
551
571
  message=f"MCP server {connection_config.url} requires OAuth authorization",
552
572
  server_url=canonical_resource(connection_config.url),
@@ -18,6 +18,7 @@ from ..utils.mcp_oauth import (
18
18
  canonical_resource,
19
19
  extract_resource_metadata_url,
20
20
  fetch_resource_metadata_async,
21
+ infer_authorization_servers_from_realm,
21
22
  )
22
23
 
23
24
  logger = logging.getLogger(__name__)
@@ -129,6 +130,25 @@ class McpRemoteTool(McpServerTool):
129
130
  session=session,
130
131
  timeout=self.tool_timeout_sec,
131
132
  )
133
+
134
+ # If we couldn't get metadata from the resource_metadata endpoint,
135
+ # infer authorization servers from the WWW-Authenticate header and server URL
136
+ if not metadata or not metadata.get('authorization_servers'):
137
+ inferred_servers = infer_authorization_servers_from_realm(auth_header, self.server_url)
138
+ if inferred_servers:
139
+ if not metadata:
140
+ metadata = {}
141
+ metadata['authorization_servers'] = inferred_servers
142
+ logger.info(f"Inferred authorization servers for {self.server_url}: {inferred_servers}")
143
+
144
+ # Fetch OAuth authorization server metadata from the inferred server
145
+ # This avoids CORS issues in the frontend
146
+ from alita_sdk.runtime.utils.mcp_oauth import fetch_oauth_authorization_server_metadata
147
+ auth_server_metadata = fetch_oauth_authorization_server_metadata(inferred_servers[0], timeout=self.tool_timeout_sec)
148
+ if auth_server_metadata:
149
+ metadata['oauth_authorization_server'] = auth_server_metadata
150
+ logger.info(f"Fetched OAuth metadata for {inferred_servers[0]}")
151
+
132
152
  raise McpAuthorizationRequired(
133
153
  message=f"MCP server {self.server_url} requires OAuth authorization",
134
154
  server_url=canonical_resource(self.server_url),
@@ -46,7 +46,7 @@ class McpAuthorizationRequired(ToolException):
46
46
  def extract_resource_metadata_url(www_authenticate: Optional[str], server_url: Optional[str] = None) -> Optional[str]:
47
47
  """
48
48
  Pull the resource_metadata URL from a WWW-Authenticate header if present.
49
- If not found and server_url is provided, construct the standard .well-known URL.
49
+ If not found and server_url is provided, try to construct resource metadata URLs.
50
50
  """
51
51
  if not www_authenticate and not server_url:
52
52
  return None
@@ -57,16 +57,62 @@ def extract_resource_metadata_url(www_authenticate: Optional[str], server_url: O
57
57
  if match:
58
58
  return match.group(1)
59
59
 
60
- # Fallback: construct standard .well-known URL if server_url provided
61
- if server_url:
62
- parsed = urlparse(server_url)
63
- # Build the standard resource metadata URL
64
- base_url = f"{parsed.scheme}://{parsed.netloc}"
65
- return f"{base_url}/.well-known/resource-metadata"
60
+ # For servers that don't provide resource_metadata in WWW-Authenticate,
61
+ # we'll return None and rely on inferring authorization servers from the realm
62
+ # or using well-known OAuth discovery endpoints directly
63
+ return None
64
+
65
+
66
+ def fetch_oauth_authorization_server_metadata(base_url: str, timeout: int = 10) -> Optional[Dict[str, Any]]:
67
+ """
68
+ Fetch OAuth authorization server metadata from well-known endpoints.
69
+ Tries both oauth-authorization-server and openid-configuration discovery endpoints.
70
+ """
71
+ discovery_endpoints = [
72
+ f"{base_url}/.well-known/oauth-authorization-server",
73
+ f"{base_url}/.well-known/openid-configuration",
74
+ ]
75
+
76
+ for endpoint in discovery_endpoints:
77
+ try:
78
+ resp = requests.get(endpoint, timeout=timeout)
79
+ if resp.status_code == 200:
80
+ return resp.json()
81
+ except Exception as exc:
82
+ logger.debug(f"Failed to fetch OAuth metadata from {endpoint}: {exc}")
83
+ continue
66
84
 
67
85
  return None
68
86
 
69
87
 
88
+ def infer_authorization_servers_from_realm(www_authenticate: Optional[str], server_url: str) -> Optional[list]:
89
+ """
90
+ Infer authorization server URLs from WWW-Authenticate realm or server URL.
91
+ This is used when the server doesn't provide resource_metadata endpoint.
92
+ """
93
+ if not www_authenticate and not server_url:
94
+ return None
95
+
96
+ authorization_servers = []
97
+
98
+ # Try to extract realm from WWW-Authenticate header
99
+ realm = None
100
+ if www_authenticate:
101
+ realm_match = re.search(r'realm\s*=\s*\"([^\"]+)\"', www_authenticate)
102
+ if realm_match:
103
+ realm = realm_match.group(1)
104
+
105
+ # Parse the server URL to get base domain
106
+ parsed = urlparse(server_url)
107
+ base_url = f"{parsed.scheme}://{parsed.netloc}"
108
+
109
+ # Return the base authorization server URL (not the discovery endpoint)
110
+ # The client will append .well-known paths when fetching metadata
111
+ authorization_servers.append(base_url)
112
+
113
+ return authorization_servers if authorization_servers else None
114
+
115
+
70
116
  def fetch_resource_metadata(resource_metadata_url: str, timeout: int = 10) -> Optional[Dict[str, Any]]:
71
117
  """Fetch and parse the protected resource metadata document."""
72
118
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.442
3
+ Version: 0.3.444
4
4
  Summary: SDK for building langchain agents using resources from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedj27@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -103,7 +103,7 @@ alita_sdk/runtime/toolkits/application.py,sha256=HHAKgwKOckxc7EQG-AV7rz4POOzQJKF
103
103
  alita_sdk/runtime/toolkits/artifact.py,sha256=YChNCX4QhVpaQG7Jk4TS-Wl0Aruc4slQ2K21zh9nNO0,3176
104
104
  alita_sdk/runtime/toolkits/configurations.py,sha256=kIDAlnryPQfbZyFxV-9SzN2-Vefzx06TX1BBdIIpN90,141
105
105
  alita_sdk/runtime/toolkits/datasource.py,sha256=qk78OdPoReYPCWwahfkKLbKc4pfsu-061oXRryFLP6I,2498
106
- alita_sdk/runtime/toolkits/mcp.py,sha256=yaEpIYSGGd9W_dlru0s3T-naICdzO1M6OrSfkjtnI7I,39030
106
+ alita_sdk/runtime/toolkits/mcp.py,sha256=4AHZoTb6J3_plIwxK8nQAK5tSTi_zhC3gTOzl0vdYBw,40452
107
107
  alita_sdk/runtime/toolkits/prompt.py,sha256=WIpTkkVYWqIqOWR_LlSWz3ug8uO9tm5jJ7aZYdiGRn0,1192
108
108
  alita_sdk/runtime/toolkits/subgraph.py,sha256=wwUK8JjPXkGzyVZ3tAukmvST6eGbqx_U11rpnmbrvtg,2105
109
109
  alita_sdk/runtime/toolkits/tools.py,sha256=F93TOPQWmULpslyJh-lCEdkQ3OD4RbEvfe84g8wBzb0,11639
@@ -122,7 +122,7 @@ alita_sdk/runtime/tools/llm.py,sha256=iRG_wU4T01LRsjEMPZe5Uah7LiMqDc-vspwkMuQtlt
122
122
  alita_sdk/runtime/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
123
123
  alita_sdk/runtime/tools/loop_output.py,sha256=U4hO9PCQgWlXwOq6jdmCGbegtAxGAPXObSxZQ3z38uk,8069
124
124
  alita_sdk/runtime/tools/mcp_inspect_tool.py,sha256=38X8euaxDbEGjcfp6ElvExZalpZun6QEr6ZEW4nU5pQ,11496
125
- alita_sdk/runtime/tools/mcp_remote_tool.py,sha256=C05S9UC0OB31idIvZ1CE0qwKrUbCL9nATwZ3RhAovbg,9553
125
+ alita_sdk/runtime/tools/mcp_remote_tool.py,sha256=Rbzkp-uOZ8dXnOgkk0LU4p0Tyo_KmGbeDRfTB-FdEP4,11129
126
126
  alita_sdk/runtime/tools/mcp_server_tool.py,sha256=-xO3H6BM63KaIV1CdcQKPVE0WPigiqOgFZDX7m2_yGs,4419
127
127
  alita_sdk/runtime/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8QwB0UwpsWCYruXU,11692
128
128
  alita_sdk/runtime/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
@@ -136,7 +136,7 @@ alita_sdk/runtime/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
136
136
  alita_sdk/runtime/utils/constants.py,sha256=Xntx1b_uxUzT4clwqHA_U6K8y5bBqf_4lSQwXdcWrp4,13586
137
137
  alita_sdk/runtime/utils/evaluate.py,sha256=iM1P8gzBLHTuSCe85_Ng_h30m52hFuGuhNXJ7kB1tgI,1872
138
138
  alita_sdk/runtime/utils/logging.py,sha256=svPyiW8ztDfhqHFITv5FBCj8UhLxz6hWcqGIY6wpJJE,3331
139
- alita_sdk/runtime/utils/mcp_oauth.py,sha256=NDyRVfkLxVGh8lFo0fWjCZeHf_slZjXJ6Eyf9w-PROU,4400
139
+ alita_sdk/runtime/utils/mcp_oauth.py,sha256=Ynoa_C_G5WXL_tlcdol2wBLgQauyvIPX0isCJKsvWMs,6151
140
140
  alita_sdk/runtime/utils/save_dataframe.py,sha256=i-E1wp-t4wb17Zq3nA3xYwgSILjoXNizaQAA9opWvxY,1576
141
141
  alita_sdk/runtime/utils/streamlit.py,sha256=yIb4YIGH8HRAXZtZlywjxI07Xdcb5eUt7rMA-elFTdc,107261
142
142
  alita_sdk/runtime/utils/toolkit_runtime.py,sha256=MU63Fpxj0b5_r1IUUc0Q3-PN9VwL7rUxp2MRR4tmYR8,5136
@@ -360,8 +360,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
360
360
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
361
361
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
362
362
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
363
- alita_sdk-0.3.442.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
364
- alita_sdk-0.3.442.dist-info/METADATA,sha256=n14d1M_12NDy-RGtDKFesrDUl40DJpFZfLEYmihW72A,19071
365
- alita_sdk-0.3.442.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
366
- alita_sdk-0.3.442.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
367
- alita_sdk-0.3.442.dist-info/RECORD,,
363
+ alita_sdk-0.3.444.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
364
+ alita_sdk-0.3.444.dist-info/METADATA,sha256=umIbGNVs1zB3QuPT3WTWNI31mdOJHTPQR6trqqNmCJY,19071
365
+ alita_sdk-0.3.444.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
366
+ alita_sdk-0.3.444.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
367
+ alita_sdk-0.3.444.dist-info/RECORD,,