deepset-mcp 0.0.6__py3-none-any.whl → 0.0.8__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.
- deepset_mcp/__init__.py +3 -4
- deepset_mcp/api/__init__.py +3 -0
- deepset_mcp/api/client.py +126 -107
- deepset_mcp/api/custom_components/__init__.py +3 -0
- deepset_mcp/api/custom_components/models.py +7 -8
- deepset_mcp/api/custom_components/protocols.py +4 -3
- deepset_mcp/api/custom_components/resource.py +39 -13
- deepset_mcp/api/haystack_service/__init__.py +3 -0
- deepset_mcp/api/haystack_service/protocols.py +21 -0
- deepset_mcp/api/haystack_service/resource.py +46 -0
- deepset_mcp/api/indexes/__init__.py +3 -0
- deepset_mcp/api/indexes/models.py +23 -11
- deepset_mcp/api/indexes/protocols.py +13 -4
- deepset_mcp/api/indexes/resource.py +86 -22
- deepset_mcp/api/integrations/__init__.py +4 -0
- deepset_mcp/api/integrations/models.py +4 -13
- deepset_mcp/api/integrations/protocols.py +3 -3
- deepset_mcp/api/integrations/resource.py +5 -5
- deepset_mcp/api/pipeline/__init__.py +1 -15
- deepset_mcp/api/pipeline/models.py +66 -28
- deepset_mcp/api/pipeline/protocols.py +6 -10
- deepset_mcp/api/pipeline/resource.py +101 -58
- deepset_mcp/api/pipeline_template/__init__.py +3 -0
- deepset_mcp/api/pipeline_template/models.py +12 -23
- deepset_mcp/api/pipeline_template/protocols.py +11 -5
- deepset_mcp/api/pipeline_template/resource.py +51 -39
- deepset_mcp/api/protocols.py +13 -11
- deepset_mcp/api/secrets/__init__.py +3 -0
- deepset_mcp/api/secrets/models.py +2 -8
- deepset_mcp/api/secrets/protocols.py +4 -3
- deepset_mcp/api/secrets/resource.py +32 -7
- deepset_mcp/api/shared_models.py +111 -1
- deepset_mcp/api/transport.py +30 -58
- deepset_mcp/api/user/__init__.py +3 -0
- deepset_mcp/api/workspace/__init__.py +1 -3
- deepset_mcp/api/workspace/models.py +4 -8
- deepset_mcp/api/workspace/protocols.py +3 -3
- deepset_mcp/api/workspace/resource.py +5 -9
- deepset_mcp/config.py +1 -1
- deepset_mcp/main.py +5 -20
- deepset_mcp/mcp/__init__.py +10 -0
- deepset_mcp/{server.py → mcp/server.py} +8 -18
- deepset_mcp/{store.py → mcp/store.py} +3 -3
- deepset_mcp/{tool_factory.py → mcp/tool_factory.py} +20 -37
- deepset_mcp/mcp/tool_models.py +57 -0
- deepset_mcp/{tool_registry.py → mcp/tool_registry.py} +16 -6
- deepset_mcp/{tools/tokonomics → tokonomics}/__init__.py +3 -1
- deepset_mcp/{tools/tokonomics → tokonomics}/decorators.py +2 -2
- deepset_mcp/{tools/tokonomics → tokonomics}/explorer.py +1 -1
- deepset_mcp/tools/__init__.py +58 -0
- deepset_mcp/tools/custom_components.py +7 -4
- deepset_mcp/tools/haystack_service.py +64 -22
- deepset_mcp/tools/haystack_service_models.py +40 -0
- deepset_mcp/tools/indexes.py +131 -32
- deepset_mcp/tools/object_store.py +1 -1
- deepset_mcp/tools/pipeline.py +40 -10
- deepset_mcp/tools/pipeline_template.py +35 -18
- deepset_mcp/tools/secrets.py +29 -13
- deepset_mcp/tools/workspace.py +2 -2
- deepset_mcp-0.0.8.dist-info/METADATA +100 -0
- deepset_mcp-0.0.8.dist-info/RECORD +74 -0
- deepset_mcp/api/README.md +0 -536
- deepset_mcp/api/pipeline/log_level.py +0 -13
- deepset_mcp/tool_models.py +0 -42
- deepset_mcp-0.0.6.dist-info/METADATA +0 -807
- deepset_mcp-0.0.6.dist-info/RECORD +0 -75
- /deepset_mcp/{tools/tokonomics → tokonomics}/object_store.py +0 -0
- {deepset_mcp-0.0.6.dist-info → deepset_mcp-0.0.8.dist-info}/WHEEL +0 -0
- {deepset_mcp-0.0.6.dist-info → deepset_mcp-0.0.8.dist-info}/entry_points.txt +0 -0
- {deepset_mcp-0.0.6.dist-info → deepset_mcp-0.0.8.dist-info}/licenses/LICENSE +0 -0
deepset_mcp/__init__.py
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
5
|
from deepset_mcp.config import DEEPSET_DOCS_DEFAULT_SHARE_URL
|
|
6
|
-
from deepset_mcp.server import configure_mcp_server
|
|
7
|
-
from deepset_mcp.
|
|
8
|
-
from deepset_mcp.tool_registry import ALL_DEEPSET_TOOLS
|
|
6
|
+
from deepset_mcp.mcp.server import configure_mcp_server
|
|
7
|
+
from deepset_mcp.mcp.tool_registry import ALL_DEEPSET_TOOLS
|
|
9
8
|
|
|
10
|
-
__all__ = ["configure_mcp_server", "
|
|
9
|
+
__all__ = ["configure_mcp_server", "ALL_DEEPSET_TOOLS", "DEEPSET_DOCS_DEFAULT_SHARE_URL"]
|
deepset_mcp/api/__init__.py
CHANGED
deepset_mcp/api/client.py
CHANGED
|
@@ -29,7 +29,27 @@ T = TypeVar("T")
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class AsyncDeepsetClient(AsyncClientProtocol):
|
|
32
|
-
"""Async Client for interacting with the deepset API.
|
|
32
|
+
"""Async Client for interacting with the deepset API.
|
|
33
|
+
|
|
34
|
+
This client provides asynchronous access to most deepset API endpoints
|
|
35
|
+
and resources through a convenient interface.
|
|
36
|
+
|
|
37
|
+
**Example usage:**
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from deepset_mcp.api import AsyncDeepsetClient
|
|
41
|
+
|
|
42
|
+
async with AsyncDeepsetClient() as client:
|
|
43
|
+
pipes = await client.pipelines(workspace="example-workspace")
|
|
44
|
+
all_pipelines = await pipes.list()
|
|
45
|
+
example_pipeline = await pipes.get(pipeline_name="example-pipeline")
|
|
46
|
+
await pipes.create(pipeline_name="example-pipeline-v2", yaml_config="...")
|
|
47
|
+
|
|
48
|
+
indexes = await client.indexes(workspace="example-workspace")
|
|
49
|
+
all_indexes = await indexes.list()
|
|
50
|
+
example_index = await indexes.get(index_name="example-index")
|
|
51
|
+
```
|
|
52
|
+
"""
|
|
33
53
|
|
|
34
54
|
def __init__(
|
|
35
55
|
self,
|
|
@@ -38,19 +58,13 @@ class AsyncDeepsetClient(AsyncClientProtocol):
|
|
|
38
58
|
transport: TransportProtocol | None = None,
|
|
39
59
|
transport_config: dict[str, Any] | None = None,
|
|
40
60
|
) -> None:
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
base_url : str, optional
|
|
49
|
-
Base URL for the deepset API.
|
|
50
|
-
transport : TransportProtocol, optional
|
|
51
|
-
Custom transport implementation.
|
|
52
|
-
transport_config : dict, optional
|
|
53
|
-
Configuration for default transport (e.g. timeout).
|
|
61
|
+
"""Initialize an instance of the AsyncDeepsetClient.
|
|
62
|
+
|
|
63
|
+
:param api_key: API key or token. Falls back to DEEPSET_API_KEY env var
|
|
64
|
+
:param base_url: Base URL for the deepset API
|
|
65
|
+
:param transport: Custom transport implementation
|
|
66
|
+
:param transport_config: Configuration for default transport (e.g. timeout). All configuration parameters are
|
|
67
|
+
forwarded to httpx.AsyncClient.
|
|
54
68
|
"""
|
|
55
69
|
self.api_key = api_key or os.environ.get("DEEPSET_API_KEY")
|
|
56
70
|
if not self.api_key:
|
|
@@ -65,6 +79,73 @@ class AsyncDeepsetClient(AsyncClientProtocol):
|
|
|
65
79
|
config=transport_config,
|
|
66
80
|
)
|
|
67
81
|
|
|
82
|
+
def pipelines(self, workspace: str) -> PipelineResource:
|
|
83
|
+
"""Resource to interact with pipelines in the specified workspace.
|
|
84
|
+
|
|
85
|
+
:param workspace: Workspace identifier
|
|
86
|
+
:returns: Pipeline resource instance
|
|
87
|
+
"""
|
|
88
|
+
return PipelineResource(client=self, workspace=workspace)
|
|
89
|
+
|
|
90
|
+
def indexes(self, workspace: str) -> IndexResource:
|
|
91
|
+
"""Resource to interact with indexes in the specified workspace.
|
|
92
|
+
|
|
93
|
+
:param workspace: Workspace identifier
|
|
94
|
+
:returns: Index resource instance
|
|
95
|
+
"""
|
|
96
|
+
return IndexResource(client=self, workspace=workspace)
|
|
97
|
+
|
|
98
|
+
def pipeline_templates(self, workspace: str) -> PipelineTemplateResource:
|
|
99
|
+
"""Resource to interact with pipeline templates in the specified workspace.
|
|
100
|
+
|
|
101
|
+
:param workspace: Workspace identifier
|
|
102
|
+
:returns: Pipeline template resource instance
|
|
103
|
+
"""
|
|
104
|
+
return PipelineTemplateResource(client=self, workspace=workspace)
|
|
105
|
+
|
|
106
|
+
def haystack_service(self) -> HaystackServiceResource:
|
|
107
|
+
"""Resource to interact with the Haystack service API.
|
|
108
|
+
|
|
109
|
+
:returns: Haystack service resource instance
|
|
110
|
+
"""
|
|
111
|
+
return HaystackServiceResource(client=self)
|
|
112
|
+
|
|
113
|
+
def integrations(self) -> IntegrationResource:
|
|
114
|
+
"""Resource to interact with integrations.
|
|
115
|
+
|
|
116
|
+
:returns: Integration resource instance
|
|
117
|
+
"""
|
|
118
|
+
return IntegrationResource(client=self)
|
|
119
|
+
|
|
120
|
+
def custom_components(self, workspace: str) -> CustomComponentsResource:
|
|
121
|
+
"""Resource to interact with custom components in the specified workspace.
|
|
122
|
+
|
|
123
|
+
:param workspace: Workspace identifier
|
|
124
|
+
:returns: Custom components resource instance
|
|
125
|
+
"""
|
|
126
|
+
return CustomComponentsResource(client=self)
|
|
127
|
+
|
|
128
|
+
def secrets(self) -> SecretResource:
|
|
129
|
+
"""Resource to interact with secrets.
|
|
130
|
+
|
|
131
|
+
:returns: Secret resource instance
|
|
132
|
+
"""
|
|
133
|
+
return SecretResource(client=self)
|
|
134
|
+
|
|
135
|
+
def workspaces(self) -> WorkspaceResource:
|
|
136
|
+
"""Resource to interact with workspaces.
|
|
137
|
+
|
|
138
|
+
:returns: Workspace resource instance
|
|
139
|
+
"""
|
|
140
|
+
return WorkspaceResource(client=self)
|
|
141
|
+
|
|
142
|
+
def users(self) -> UserResource:
|
|
143
|
+
"""Resource to interact with users.
|
|
144
|
+
|
|
145
|
+
:returns: User resource instance
|
|
146
|
+
"""
|
|
147
|
+
return UserResource(client=self)
|
|
148
|
+
|
|
68
149
|
@overload
|
|
69
150
|
async def request(
|
|
70
151
|
self,
|
|
@@ -102,31 +183,17 @@ class AsyncDeepsetClient(AsyncClientProtocol):
|
|
|
102
183
|
timeout: float | None | Literal["config"] = "config",
|
|
103
184
|
**kwargs: Any,
|
|
104
185
|
) -> TransportResponse[Any]:
|
|
105
|
-
"""
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
headers : dict, optional
|
|
117
|
-
Additional headers to include
|
|
118
|
-
response_type : type[T], optional
|
|
119
|
-
Expected response type for type checking
|
|
120
|
-
timeout : float | None | Literal["config"], optional
|
|
121
|
-
Request timeout in seconds. If "config", uses transport config timeout.
|
|
122
|
-
If None, disables timeout. If float, uses specific timeout.
|
|
123
|
-
**kwargs : Any
|
|
124
|
-
Additional arguments to pass to transport
|
|
125
|
-
|
|
126
|
-
Returns
|
|
127
|
-
-------
|
|
128
|
-
TransportResponse[T]
|
|
129
|
-
Response with parsed JSON if available
|
|
186
|
+
"""Make a regular (non-streaming) request to the deepset API.
|
|
187
|
+
|
|
188
|
+
:param endpoint: API endpoint path
|
|
189
|
+
:param method: HTTP method
|
|
190
|
+
:param data: JSON data to send in request body
|
|
191
|
+
:param headers: Additional headers to include
|
|
192
|
+
:param response_type: Expected response type for type checking
|
|
193
|
+
:param timeout: Request timeout in seconds. If "config", uses transport config timeout.
|
|
194
|
+
If None, disables timeout. If float, uses specific timeout
|
|
195
|
+
:param kwargs: Additional arguments to pass to transport
|
|
196
|
+
:returns: Response with parsed JSON if available
|
|
130
197
|
"""
|
|
131
198
|
if not endpoint.startswith("/"):
|
|
132
199
|
endpoint = f"/{endpoint}"
|
|
@@ -163,41 +230,29 @@ class AsyncDeepsetClient(AsyncClientProtocol):
|
|
|
163
230
|
headers: dict[str, str] | None = None,
|
|
164
231
|
**kwargs: Any,
|
|
165
232
|
) -> AbstractAsyncContextManager[StreamingResponse]:
|
|
166
|
-
"""
|
|
167
|
-
Make a streaming request to the deepset API.
|
|
233
|
+
"""Make a streaming request to the deepset API.
|
|
168
234
|
|
|
169
235
|
Must be used as an async context manager to ensure proper cleanup.
|
|
170
236
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
--------
|
|
191
|
-
async with client.stream_request("/pipelines/search-stream", data={"query": "AI"}) as response:
|
|
192
|
-
if response.success:
|
|
193
|
-
async for line in response.iter_lines():
|
|
194
|
-
# Process each line of the stream
|
|
195
|
-
data = json.loads(line)
|
|
196
|
-
print(data)
|
|
197
|
-
else:
|
|
198
|
-
# Handle error
|
|
199
|
-
error_body = await response.read_body()
|
|
200
|
-
print(f"Error {response.status_code}: {error_body}")
|
|
237
|
+
Example::
|
|
238
|
+
|
|
239
|
+
async with client.stream_request("/pipelines/search-stream", data={"query": "AI"}) as response:
|
|
240
|
+
if response.success:
|
|
241
|
+
async for line in response.iter_lines():
|
|
242
|
+
# Process each line of the stream
|
|
243
|
+
data = json.loads(line)
|
|
244
|
+
print(data)
|
|
245
|
+
else:
|
|
246
|
+
# Handle error
|
|
247
|
+
error_body = await response.read_body()
|
|
248
|
+
print(f"Error {response.status_code}: {error_body}")
|
|
249
|
+
|
|
250
|
+
:param endpoint: API endpoint path
|
|
251
|
+
:param method: HTTP method (usually POST for streaming)
|
|
252
|
+
:param data: JSON data to send in request body
|
|
253
|
+
:param headers: Additional headers to include
|
|
254
|
+
:param kwargs: Additional arguments to pass to transport
|
|
255
|
+
:returns: Response object with streaming capabilities
|
|
201
256
|
"""
|
|
202
257
|
|
|
203
258
|
@asynccontextmanager
|
|
@@ -243,39 +298,3 @@ class AsyncDeepsetClient(AsyncClientProtocol):
|
|
|
243
298
|
"""Exit the AsyncContextmanager and clean up resources."""
|
|
244
299
|
await self.close()
|
|
245
300
|
return False
|
|
246
|
-
|
|
247
|
-
def pipelines(self, workspace: str) -> PipelineResource:
|
|
248
|
-
"""Resource to interact with pipelines in the specified workspace."""
|
|
249
|
-
return PipelineResource(client=self, workspace=workspace)
|
|
250
|
-
|
|
251
|
-
def haystack_service(self) -> HaystackServiceResource:
|
|
252
|
-
"""Resource to interact with the Haystack service API."""
|
|
253
|
-
return HaystackServiceResource(client=self)
|
|
254
|
-
|
|
255
|
-
def pipeline_templates(self, workspace: str) -> PipelineTemplateResource:
|
|
256
|
-
"""Resource to interact with pipeline templates in the specified workspace."""
|
|
257
|
-
return PipelineTemplateResource(client=self, workspace=workspace)
|
|
258
|
-
|
|
259
|
-
def indexes(self, workspace: str) -> IndexResource:
|
|
260
|
-
"""Resource to interact with indexes in the specified workspace."""
|
|
261
|
-
return IndexResource(client=self, workspace=workspace)
|
|
262
|
-
|
|
263
|
-
def custom_components(self, workspace: str) -> CustomComponentsResource:
|
|
264
|
-
"""Resource to interact with custom components in the specified workspace."""
|
|
265
|
-
return CustomComponentsResource(client=self)
|
|
266
|
-
|
|
267
|
-
def users(self) -> UserResource:
|
|
268
|
-
"""Resource to interact with users."""
|
|
269
|
-
return UserResource(client=self)
|
|
270
|
-
|
|
271
|
-
def secrets(self) -> SecretResource:
|
|
272
|
-
"""Resource to interact with secrets."""
|
|
273
|
-
return SecretResource(client=self)
|
|
274
|
-
|
|
275
|
-
def workspaces(self) -> WorkspaceResource:
|
|
276
|
-
"""Resource to interact with workspaces."""
|
|
277
|
-
return WorkspaceResource(client=self)
|
|
278
|
-
|
|
279
|
-
def integrations(self) -> IntegrationResource:
|
|
280
|
-
"""Resource to interact with integrations."""
|
|
281
|
-
return IntegrationResource(client=self)
|
|
@@ -13,17 +13,16 @@ class CustomComponentInstallation(BaseModel):
|
|
|
13
13
|
"""Model representing a custom component installation."""
|
|
14
14
|
|
|
15
15
|
custom_component_id: str
|
|
16
|
+
"Unique identifier for the custom component"
|
|
16
17
|
status: str
|
|
18
|
+
"Current installation status of the component"
|
|
17
19
|
version: str
|
|
20
|
+
"Version number of the installed component"
|
|
18
21
|
created_by_user_id: str
|
|
22
|
+
"ID of the user who initiated the installation"
|
|
19
23
|
logs: list[dict[str, Any]]
|
|
24
|
+
"Installation log entries with timestamps and messages"
|
|
20
25
|
organization_id: str
|
|
26
|
+
"ID of the organization where the component is installed"
|
|
21
27
|
user_info: DeepsetUser | None = None
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class CustomComponentInstallationList(BaseModel):
|
|
25
|
-
"""Model representing a list of custom component installations."""
|
|
26
|
-
|
|
27
|
-
data: list[CustomComponentInstallation]
|
|
28
|
-
total: int
|
|
29
|
-
has_more: bool
|
|
28
|
+
"Detailed information about the user who created the installation"
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
from typing import Protocol
|
|
6
6
|
|
|
7
|
-
from deepset_mcp.api.custom_components.models import
|
|
7
|
+
from deepset_mcp.api.custom_components.models import CustomComponentInstallation
|
|
8
|
+
from deepset_mcp.api.shared_models import PaginatedResponse
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class CustomComponentsProtocol(Protocol):
|
|
11
12
|
"""Protocol defining the implementation for CustomComponentsResource."""
|
|
12
13
|
|
|
13
14
|
async def list_installations(
|
|
14
|
-
self, limit: int = 20,
|
|
15
|
-
) ->
|
|
15
|
+
self, limit: int = 20, after: str | None = None, field: str = "created_at", order: str = "DESC"
|
|
16
|
+
) -> PaginatedResponse[CustomComponentInstallation]:
|
|
16
17
|
"""List custom component installations."""
|
|
17
18
|
...
|
|
18
19
|
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
5
|
from typing import Any
|
|
6
|
+
from urllib.parse import quote
|
|
6
7
|
|
|
7
|
-
from deepset_mcp.api.custom_components.models import
|
|
8
|
+
from deepset_mcp.api.custom_components.models import CustomComponentInstallation
|
|
8
9
|
from deepset_mcp.api.custom_components.protocols import CustomComponentsProtocol
|
|
10
|
+
from deepset_mcp.api.exceptions import UnexpectedAPIError
|
|
9
11
|
from deepset_mcp.api.protocols import AsyncClientProtocol
|
|
12
|
+
from deepset_mcp.api.shared_models import PaginatedResponse
|
|
10
13
|
from deepset_mcp.api.transport import raise_for_status
|
|
11
14
|
|
|
12
15
|
|
|
@@ -21,29 +24,52 @@ class CustomComponentsResource(CustomComponentsProtocol):
|
|
|
21
24
|
self._client = client
|
|
22
25
|
|
|
23
26
|
async def list_installations(
|
|
24
|
-
self, limit: int = 20,
|
|
25
|
-
) ->
|
|
26
|
-
"""
|
|
27
|
+
self, limit: int = 20, after: str | None = None, field: str = "created_at", order: str = "DESC"
|
|
28
|
+
) -> PaginatedResponse[CustomComponentInstallation]:
|
|
29
|
+
"""Lists custom component installations and returns the first page of results.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
The returned object can be iterated over to fetch subsequent pages.
|
|
32
|
+
|
|
33
|
+
:param limit: Maximum number of installations to return per page.
|
|
34
|
+
:param after: The cursor to fetch the next page of results.
|
|
30
35
|
:param field: Field to sort by.
|
|
31
36
|
:param order: Sort order (ASC or DESC).
|
|
32
|
-
|
|
33
|
-
:returns: List of custom component installations.
|
|
37
|
+
:returns: A `PaginatedResponse` object containing the first page of installations.
|
|
34
38
|
"""
|
|
39
|
+
# 1. Prepare arguments for the initial API call
|
|
40
|
+
# TODO: Pagination in the deepset API is currently implemented in an unintuitive way.
|
|
41
|
+
# TODO: The cursor is always time based (created_at) and after signifies installations older than the
|
|
42
|
+
# TODO: current cursor
|
|
43
|
+
# TODO: while 'before' signals installations younger than the current cursor.
|
|
44
|
+
# TODO: This is applied irrespective of any sort (e.g. name) that would conflict with this approach.
|
|
45
|
+
# TODO: Change this to 'after' once the behaviour is fixed on the deepset API
|
|
46
|
+
request_params = {"limit": limit, "field": field, "order": order, "before": after}
|
|
47
|
+
request_params = {k: v for k, v in request_params.items() if v is not None}
|
|
48
|
+
|
|
49
|
+
# 2. Make the first API call using a private, stateless method
|
|
50
|
+
page = await self._list_api_call(**request_params)
|
|
51
|
+
|
|
52
|
+
# 3. Inject the logic needed for subsequent fetches into the response object
|
|
53
|
+
page._inject_paginator(
|
|
54
|
+
fetch_func=self._list_api_call,
|
|
55
|
+
# Base args for the *next* fetch don't include initial cursors
|
|
56
|
+
base_args={"limit": limit, "field": field, "order": order},
|
|
57
|
+
)
|
|
58
|
+
return page
|
|
59
|
+
|
|
60
|
+
async def _list_api_call(self, **kwargs: Any) -> PaginatedResponse[CustomComponentInstallation]:
|
|
61
|
+
"""A private, stateless method that performs the raw API call."""
|
|
62
|
+
params = "&".join([f"{key}={quote(str(value), safe='')}" for key, value in kwargs.items()])
|
|
35
63
|
resp = await self._client.request(
|
|
36
|
-
endpoint=f"v2/custom_components?
|
|
64
|
+
endpoint=f"v2/custom_components?{params}",
|
|
37
65
|
method="GET",
|
|
38
66
|
response_type=dict[str, Any],
|
|
39
67
|
)
|
|
40
|
-
|
|
41
68
|
raise_for_status(resp)
|
|
42
|
-
|
|
43
69
|
if resp.json is None:
|
|
44
|
-
|
|
70
|
+
raise UnexpectedAPIError(status_code=resp.status_code, message="Empty response", detail=None)
|
|
45
71
|
|
|
46
|
-
return
|
|
72
|
+
return PaginatedResponse[CustomComponentInstallation].create_with_cursor_field(resp.json, "custom_component_id")
|
|
47
73
|
|
|
48
74
|
async def get_latest_installation_logs(self) -> str | None:
|
|
49
75
|
"""Get the logs from the latest custom component installation.
|
|
@@ -15,3 +15,24 @@ class HaystackServiceProtocol(Protocol):
|
|
|
15
15
|
async def get_component_input_output(self, component_name: str) -> dict[str, Any]:
|
|
16
16
|
"""Fetch input and output schema for a component from the API."""
|
|
17
17
|
...
|
|
18
|
+
|
|
19
|
+
async def run_component(
|
|
20
|
+
self,
|
|
21
|
+
component_type: str,
|
|
22
|
+
init_params: dict[str, Any] | None = None,
|
|
23
|
+
input_data: dict[str, Any] | None = None,
|
|
24
|
+
input_types: dict[str, str] | None = None,
|
|
25
|
+
workspace: str | None = None,
|
|
26
|
+
) -> dict[str, Any]:
|
|
27
|
+
"""Run a Haystack component with the given parameters.
|
|
28
|
+
|
|
29
|
+
:param component_type: The type of component to run
|
|
30
|
+
(e.g., "haystack.components.builders.prompt_builder.PromptBuilder")
|
|
31
|
+
:param init_params: Initialization parameters for the component
|
|
32
|
+
:param input_data: Input data for the component
|
|
33
|
+
:param input_types: Optional type information for inputs (inferred if not provided)
|
|
34
|
+
:param workspace: Optional workspace name to run the component in
|
|
35
|
+
|
|
36
|
+
:returns: Dictionary containing the component's output sockets
|
|
37
|
+
"""
|
|
38
|
+
...
|
|
@@ -57,3 +57,49 @@ class HaystackServiceResource(HaystackServiceProtocol):
|
|
|
57
57
|
raise ResourceNotFoundError(f"Component '{component_name}' not found.")
|
|
58
58
|
|
|
59
59
|
return resp.json[0] if resp.json is not None else {}
|
|
60
|
+
|
|
61
|
+
async def run_component(
|
|
62
|
+
self,
|
|
63
|
+
component_type: str,
|
|
64
|
+
init_params: dict[str, Any] | None = None,
|
|
65
|
+
input_data: dict[str, Any] | None = None,
|
|
66
|
+
input_types: dict[str, str] | None = None,
|
|
67
|
+
workspace: str | None = None,
|
|
68
|
+
) -> dict[str, Any]:
|
|
69
|
+
"""Run a Haystack component with the given parameters.
|
|
70
|
+
|
|
71
|
+
:param component_type: The type of component to run (e.g., "haystack.components.builders.PromptBuilder")
|
|
72
|
+
:param init_params: Initialization parameters for the component
|
|
73
|
+
:param input_data: Input data for the component
|
|
74
|
+
:param input_types: Optional type information for inputs (inferred if not provided)
|
|
75
|
+
:param workspace: Optional workspace name to run the component in
|
|
76
|
+
|
|
77
|
+
:returns: Dictionary containing the component's output sockets
|
|
78
|
+
"""
|
|
79
|
+
payload: dict[str, Any] = {
|
|
80
|
+
"component_type": component_type,
|
|
81
|
+
"init_params": init_params or {},
|
|
82
|
+
"input": input_data or {},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if input_types is not None:
|
|
86
|
+
payload["input_types"] = input_types
|
|
87
|
+
|
|
88
|
+
endpoint = "v1/haystack/components/run"
|
|
89
|
+
if workspace is not None:
|
|
90
|
+
endpoint = f"v1/workspaces/{workspace}/haystack/components/run"
|
|
91
|
+
|
|
92
|
+
resp = await self._client.request(
|
|
93
|
+
endpoint=endpoint,
|
|
94
|
+
method="POST",
|
|
95
|
+
headers={
|
|
96
|
+
"accept": "application/json",
|
|
97
|
+
"content-type": "application/json",
|
|
98
|
+
},
|
|
99
|
+
data=payload,
|
|
100
|
+
response_type=dict[str, Any],
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
raise_for_status(resp)
|
|
104
|
+
|
|
105
|
+
return resp.json if resp.json is not None else {}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from pydantic import BaseModel
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
9
|
from rich.repr import Result
|
|
10
10
|
|
|
11
11
|
from deepset_mcp.api.shared_models import DeepsetUser
|
|
@@ -15,30 +15,50 @@ class IndexStatus(BaseModel):
|
|
|
15
15
|
"""Status information about documents in an index."""
|
|
16
16
|
|
|
17
17
|
pending_file_count: int
|
|
18
|
+
"Number of files waiting to be processed"
|
|
18
19
|
failed_file_count: int
|
|
20
|
+
"Number of files that failed during indexing"
|
|
19
21
|
indexed_no_documents_file_count: int
|
|
22
|
+
"Number of files indexed but containing no documents"
|
|
20
23
|
indexed_file_count: int
|
|
24
|
+
"Number of successfully indexed files"
|
|
21
25
|
total_file_count: int
|
|
26
|
+
"Total number of files in the index"
|
|
22
27
|
|
|
23
28
|
|
|
24
29
|
class Index(BaseModel):
|
|
25
30
|
"""A deepset index."""
|
|
26
31
|
|
|
27
32
|
pipeline_index_id: str
|
|
33
|
+
"Unique identifier for the pipeline index"
|
|
28
34
|
name: str
|
|
35
|
+
"Human-readable name of the index"
|
|
29
36
|
description: str | None = None
|
|
30
|
-
|
|
37
|
+
"Optional description of the index purpose and contents"
|
|
38
|
+
yaml_config: str = Field(alias="config_yaml")
|
|
39
|
+
"YAML configuration defining the index structure and settings"
|
|
31
40
|
workspace_id: str
|
|
41
|
+
"ID of the workspace containing this index"
|
|
32
42
|
settings: dict[str, Any]
|
|
43
|
+
"Index configuration settings and parameters"
|
|
33
44
|
desired_status: str
|
|
45
|
+
"Target operational status for the index"
|
|
34
46
|
deployed_at: datetime | None = None
|
|
47
|
+
"Timestamp when the index was deployed"
|
|
35
48
|
last_edited_at: datetime | None = None
|
|
49
|
+
"Timestamp when the index was last modified"
|
|
36
50
|
max_index_replica_count: int
|
|
51
|
+
"Maximum number of replicas allowed for this index"
|
|
37
52
|
created_at: datetime
|
|
53
|
+
"Timestamp when the index was created"
|
|
38
54
|
updated_at: datetime | None = None
|
|
55
|
+
"Timestamp when the index was last updated"
|
|
39
56
|
created_by: DeepsetUser
|
|
57
|
+
"User who created the index"
|
|
40
58
|
last_edited_by: DeepsetUser | None = None
|
|
59
|
+
"User who last modified the index"
|
|
41
60
|
status: IndexStatus
|
|
61
|
+
"Current status information about documents in the index"
|
|
42
62
|
|
|
43
63
|
def __rich_repr__(self) -> Result:
|
|
44
64
|
"""Used to display the model in an LLM friendly way."""
|
|
@@ -56,12 +76,4 @@ class Index(BaseModel):
|
|
|
56
76
|
else None,
|
|
57
77
|
)
|
|
58
78
|
yield "last_edited_at", self.last_edited_at.strftime("%m/%d/%Y %I:%M:%S %p") if self.last_edited_at else None
|
|
59
|
-
yield "
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class IndexList(BaseModel):
|
|
63
|
-
"""Response model for listing indexes."""
|
|
64
|
-
|
|
65
|
-
data: list[Index]
|
|
66
|
-
has_more: bool
|
|
67
|
-
total: int
|
|
79
|
+
yield "yaml_config", self.yaml_config if self.yaml_config is not None else "Get full index to see config."
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
from typing import Protocol
|
|
6
6
|
|
|
7
|
-
from deepset_mcp.api.indexes.models import Index
|
|
7
|
+
from deepset_mcp.api.indexes.models import Index
|
|
8
8
|
from deepset_mcp.api.pipeline.models import PipelineValidationResult
|
|
9
|
+
from deepset_mcp.api.shared_models import PaginatedResponse
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class IndexResourceProtocol(Protocol):
|
|
12
13
|
"""Protocol defining the implementation for IndexResource."""
|
|
13
14
|
|
|
14
|
-
async def list(self, limit: int = 10,
|
|
15
|
+
async def list(self, limit: int = 10, after: str | None = None) -> PaginatedResponse[Index]:
|
|
15
16
|
"""List indexes in the configured workspace."""
|
|
16
17
|
...
|
|
17
18
|
|
|
@@ -19,10 +20,10 @@ class IndexResourceProtocol(Protocol):
|
|
|
19
20
|
"""Fetch a single index by its name."""
|
|
20
21
|
...
|
|
21
22
|
|
|
22
|
-
async def create(self,
|
|
23
|
+
async def create(self, index_name: str, yaml_config: str, description: str | None = None) -> Index:
|
|
23
24
|
"""Create a new index with the given name and configuration.
|
|
24
25
|
|
|
25
|
-
:param
|
|
26
|
+
:param index_name: Name of the index
|
|
26
27
|
:param yaml_config: YAML configuration for the index
|
|
27
28
|
:param description: Optional description for the index
|
|
28
29
|
:returns: Created index details
|
|
@@ -49,6 +50,14 @@ class IndexResourceProtocol(Protocol):
|
|
|
49
50
|
"""
|
|
50
51
|
...
|
|
51
52
|
|
|
53
|
+
async def validate(self, yaml_config: str) -> PipelineValidationResult:
|
|
54
|
+
"""Validate an index's YAML configuration against the API.
|
|
55
|
+
|
|
56
|
+
:param yaml_config: The YAML configuration string to validate.
|
|
57
|
+
:returns: PipelineValidationResult containing validation status and any errors.
|
|
58
|
+
"""
|
|
59
|
+
...
|
|
60
|
+
|
|
52
61
|
async def delete(self, index_name: str) -> None:
|
|
53
62
|
"""Delete an index.
|
|
54
63
|
|