datarobot-genai 0.1.68__tar.gz → 0.1.69__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.
Files changed (101) hide show
  1. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/PKG-INFO +1 -1
  2. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/pyproject.toml +1 -1
  3. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/mcp/common.py +82 -48
  4. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/.gitignore +0 -0
  5. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/AUTHORS +0 -0
  6. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/LICENSE +0 -0
  7. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/README.md +0 -0
  8. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/__init__.py +0 -0
  9. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/__init__.py +0 -0
  10. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/agents/__init__.py +0 -0
  11. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/agents/base.py +0 -0
  12. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/chat/__init__.py +0 -0
  13. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/chat/auth.py +0 -0
  14. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/chat/client.py +0 -0
  15. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/chat/responses.py +0 -0
  16. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/cli/__init__.py +0 -0
  17. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/cli/agent_environment.py +0 -0
  18. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/cli/agent_kernel.py +0 -0
  19. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/custom_model.py +0 -0
  20. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/mcp/__init__.py +0 -0
  21. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/telemetry_agent.py +0 -0
  22. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/utils/__init__.py +0 -0
  23. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/utils/auth.py +0 -0
  24. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/core/utils/urls.py +0 -0
  25. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/crewai/__init__.py +0 -0
  26. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/crewai/agent.py +0 -0
  27. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/crewai/base.py +0 -0
  28. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/crewai/events.py +0 -0
  29. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/crewai/mcp.py +0 -0
  30. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/__init__.py +0 -0
  31. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/__init__.py +0 -0
  32. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/auth.py +0 -0
  33. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/clients.py +0 -0
  34. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/config.py +0 -0
  35. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/config_utils.py +0 -0
  36. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/constants.py +0 -0
  37. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/credentials.py +0 -0
  38. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dr_mcp_server.py +0 -0
  39. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dr_mcp_server_logo.py +0 -0
  40. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_prompts/__init__.py +0 -0
  41. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_prompts/controllers.py +0 -0
  42. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_prompts/dr_lib.py +0 -0
  43. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_prompts/register.py +0 -0
  44. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_prompts/utils.py +0 -0
  45. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/__init__.py +0 -0
  46. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/__init__.py +0 -0
  47. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/__init__.py +0 -0
  48. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/base.py +0 -0
  49. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/default.py +0 -0
  50. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/adapters/drum.py +0 -0
  51. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/config.py +0 -0
  52. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/controllers.py +0 -0
  53. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/metadata.py +0 -0
  54. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/register.py +0 -0
  55. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_agentic_fallback_schema.json +0 -0
  56. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/deployment/schemas/drum_prediction_fallback_schema.json +0 -0
  57. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/register.py +0 -0
  58. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/dynamic_tools/schema.py +0 -0
  59. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/exceptions.py +0 -0
  60. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/logging.py +0 -0
  61. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/mcp_instance.py +0 -0
  62. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/mcp_server_tools.py +0 -0
  63. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/memory_management/__init__.py +0 -0
  64. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/memory_management/manager.py +0 -0
  65. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/memory_management/memory_tools.py +0 -0
  66. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/routes.py +0 -0
  67. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/routes_utils.py +0 -0
  68. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/server_life_cycle.py +0 -0
  69. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/telemetry.py +0 -0
  70. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/tool_filter.py +0 -0
  71. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/core/utils.py +0 -0
  72. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/server.py +0 -0
  73. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/__init__.py +0 -0
  74. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/integration_mcp_server.py +0 -0
  75. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/mcp_utils_ete.py +0 -0
  76. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/mcp_utils_integration.py +0 -0
  77. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/openai_llm_mcp_client.py +0 -0
  78. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/tool_base_ete.py +0 -0
  79. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/test_utils/utils.py +0 -0
  80. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/__init__.py +0 -0
  81. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/__init__.py +0 -0
  82. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/data.py +0 -0
  83. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/deployment.py +0 -0
  84. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/deployment_info.py +0 -0
  85. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/model.py +0 -0
  86. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/predict.py +0 -0
  87. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/predict_realtime.py +0 -0
  88. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/project.py +0 -0
  89. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/drmcp/tools/predictive/training.py +0 -0
  90. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/langgraph/__init__.py +0 -0
  91. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/langgraph/agent.py +0 -0
  92. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/langgraph/mcp.py +0 -0
  93. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/llama_index/__init__.py +0 -0
  94. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/llama_index/agent.py +0 -0
  95. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/llama_index/base.py +0 -0
  96. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/llama_index/mcp.py +0 -0
  97. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/nat/__init__.py +0 -0
  98. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/nat/agent.py +0 -0
  99. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/nat/datarobot_llm_clients.py +0 -0
  100. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/nat/datarobot_llm_providers.py +0 -0
  101. {datarobot_genai-0.1.68 → datarobot_genai-0.1.69}/src/datarobot_genai/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datarobot-genai
3
- Version: 0.1.68
3
+ Version: 0.1.69
4
4
  Summary: Generic helpers for GenAI
5
5
  Project-URL: Homepage, https://github.com/datarobot-oss/datarobot-genai
6
6
  Author: DataRobot, Inc.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "datarobot-genai"
7
- version = "0.1.68"
7
+ version = "0.1.69"
8
8
  description = "Generic helpers for GenAI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10, <3.13"
@@ -13,16 +13,20 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import json
16
+ import logging
16
17
  import re
18
+ from http import HTTPStatus
17
19
  from typing import Any
18
20
  from typing import Literal
19
- from urllib.parse import urlparse
20
21
 
22
+ import requests
21
23
  from datarobot.core.config import DataRobotAppFrameworkBaseSettings
22
24
  from pydantic import field_validator
23
25
 
24
26
  from datarobot_genai.core.utils.auth import AuthContextHeaderHandler
25
27
 
28
+ logger = logging.getLogger(__name__)
29
+
26
30
 
27
31
  class MCPConfig(DataRobotAppFrameworkBaseSettings):
28
32
  """Configuration for MCP server connection.
@@ -39,6 +43,7 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
39
43
  datarobot_api_token: str | None = None
40
44
  authorization_context: dict[str, Any] | None = None
41
45
  forwarded_headers: dict[str, str] | None = None
46
+ mcp_server_port: int | None = None
42
47
 
43
48
  _auth_context_handler: AuthContextHeaderHandler | None = None
44
49
  _server_config: dict[str, Any] | None = None
@@ -49,17 +54,14 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
49
54
  if value is None:
50
55
  return None
51
56
 
52
- if not isinstance(value, str):
53
- msg = "external_mcp_headers must be a JSON string"
54
- raise TypeError(msg)
55
-
56
57
  candidate = value.strip()
57
58
 
58
59
  try:
59
60
  json.loads(candidate)
60
- except json.JSONDecodeError as exc:
61
+ except json.JSONDecodeError:
61
62
  msg = "external_mcp_headers must be valid JSON"
62
- raise ValueError(msg) from exc
63
+ logger.warning(msg)
64
+ return None
63
65
 
64
66
  return candidate
65
67
 
@@ -69,15 +71,12 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
69
71
  if value is None:
70
72
  return None
71
73
 
72
- if not isinstance(value, str):
73
- msg = "mcp_deployment_id must be a string"
74
- raise TypeError(msg)
75
-
76
74
  candidate = value.strip()
77
75
 
78
76
  if not re.fullmatch(r"[0-9a-fA-F]{24}", candidate):
79
77
  msg = "mcp_deployment_id must be a valid 24-character hex ID"
80
- raise ValueError(msg)
78
+ logger.warning(msg)
79
+ return None
81
80
 
82
81
  return candidate
83
82
 
@@ -112,6 +111,45 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
112
111
  # Authorization context not available (e.g., in tests)
113
112
  return {}
114
113
 
114
+ def _build_authenticated_headers(self) -> dict[str, str]:
115
+ """Build headers for authenticated requests.
116
+
117
+ Returns
118
+ -------
119
+ Dictionary containing forwarded headers (if available) and authentication headers.
120
+ """
121
+ headers: dict[str, str] = {}
122
+ if self.forwarded_headers:
123
+ headers.update(self.forwarded_headers)
124
+ headers.update(self._authorization_bearer_header())
125
+ headers.update(self._authorization_context_header())
126
+ return headers
127
+
128
+ def _check_localhost_server(self, url: str, timeout: float = 2.0) -> bool:
129
+ """Check if MCP server is running on localhost.
130
+
131
+ Parameters
132
+ ----------
133
+ url : str
134
+ The URL to check.
135
+ timeout : float, optional
136
+ Request timeout in seconds (default: 2.0).
137
+
138
+ Returns
139
+ -------
140
+ bool
141
+ True if server is running and responding with OK status, False otherwise.
142
+ """
143
+ try:
144
+ response = requests.get(url, timeout=timeout)
145
+ return (
146
+ response.status_code == HTTPStatus.OK
147
+ and response.json().get("message") == "DataRobot MCP Server is running"
148
+ )
149
+ except requests.RequestException as e:
150
+ logger.debug(f"Failed to connect to MCP server at {url}: {e}")
151
+ return False
152
+
115
153
  def _build_server_config(self) -> dict[str, Any] | None:
116
154
  """
117
155
  Get MCP server configuration.
@@ -121,34 +159,6 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
121
159
  Server configuration dict with url, transport, and optional headers,
122
160
  or None if not configured.
123
161
  """
124
- if self.external_mcp_url:
125
- # External MCP URL - no authentication needed
126
- headers: dict[str, str] = {}
127
-
128
- # Forward headers for localhost connections
129
- if self.forwarded_headers:
130
- try:
131
- parsed_url = urlparse(self.external_mcp_url)
132
- hostname = parsed_url.hostname or ""
133
- # Check if hostname is localhost or 127.0.0.1
134
- if hostname in ("localhost", "127.0.0.1", "::1"):
135
- headers.update(self.forwarded_headers)
136
- except Exception:
137
- # If URL parsing fails, fall back to simple string check
138
- if "localhost" in self.external_mcp_url or "127.0.0.1" in self.external_mcp_url:
139
- headers.update(self.forwarded_headers)
140
-
141
- # Merge external headers if provided
142
- if self.external_mcp_headers:
143
- external_headers = json.loads(self.external_mcp_headers)
144
- headers.update(external_headers)
145
-
146
- return {
147
- "url": self.external_mcp_url.rstrip("/"),
148
- "transport": self.external_mcp_transport,
149
- "headers": headers,
150
- }
151
-
152
162
  if self.mcp_deployment_id:
153
163
  # DataRobot deployment ID - requires authentication
154
164
  if self.datarobot_endpoint is None:
@@ -165,15 +175,9 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
165
175
  base_url = f"{base_url}/api/v2"
166
176
 
167
177
  url = f"{base_url}/deployments/{self.mcp_deployment_id}/directAccess/mcp"
178
+ headers = self._build_authenticated_headers()
168
179
 
169
- # Start with forwarded headers if available
170
- headers = {}
171
- if self.forwarded_headers:
172
- headers.update(self.forwarded_headers)
173
-
174
- # Add authentication headers
175
- headers.update(self._authorization_bearer_header())
176
- headers.update(self._authorization_context_header())
180
+ logger.info(f"Using DataRobot hosted MCP deployment: {url}")
177
181
 
178
182
  return {
179
183
  "url": url,
@@ -181,4 +185,34 @@ class MCPConfig(DataRobotAppFrameworkBaseSettings):
181
185
  "headers": headers,
182
186
  }
183
187
 
188
+ if self.external_mcp_url:
189
+ # External MCP URL - no authentication needed
190
+ headers = {}
191
+
192
+ # Merge external headers if provided
193
+ if self.external_mcp_headers:
194
+ external_headers = json.loads(self.external_mcp_headers)
195
+ headers.update(external_headers)
196
+
197
+ logger.info(f"Using external MCP URL: {self.external_mcp_url}")
198
+
199
+ return {
200
+ "url": self.external_mcp_url.rstrip("/"),
201
+ "transport": self.external_mcp_transport,
202
+ "headers": headers,
203
+ }
204
+
205
+ # No MCP configuration found, setup localhost if running locally
206
+ if self.mcp_server_port:
207
+ url = f"http://localhost:{self.mcp_server_port}"
208
+ if self._check_localhost_server(url):
209
+ headers = self._build_authenticated_headers()
210
+ logger.info(f"Using localhost MCP server: {url}")
211
+ return {
212
+ "url": f"{url}/mcp",
213
+ "transport": "streamable-http",
214
+ "headers": headers,
215
+ }
216
+ logger.warning(f"MCP server is not running or not responding at {url}")
217
+
184
218
  return None