Skip to content

Commit 9798e9e

Browse files
authored
refactor: move tool registry (#160)
* refactor: move tool registry * chore: license headers
1 parent 95abf30 commit 9798e9e

6 files changed

Lines changed: 299 additions & 266 deletions

File tree

src/deepset_mcp/main.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
from deepset_mcp.api.client import AsyncDeepsetClient
1616
from deepset_mcp.config import DEEPSET_DOCS_DEFAULT_SHARE_URL
17-
from deepset_mcp.tool_factory import WorkspaceMode, register_tools
17+
from deepset_mcp.tool_factory import register_tools
18+
from deepset_mcp.tool_models import WorkspaceMode
1819

1920
# Initialize MCP Server
2021
mcp = FastMCP("Deepset Cloud MCP", settings={"log_level": "ERROR"})
@@ -140,7 +141,7 @@ def main() -> None:
140141

141142
# Handle --list-tools flag early
142143
if args.list_tools:
143-
from deepset_mcp.tool_factory import TOOL_REGISTRY
144+
from deepset_mcp.tool_registry import TOOL_REGISTRY
144145

145146
print("Available tools:")
146147
for tool_name in sorted(TOOL_REGISTRY.keys()):

src/deepset_mcp/tool_factory.py

Lines changed: 2 additions & 261 deletions
Original file line numberDiff line numberDiff line change
@@ -10,63 +10,16 @@
1010
import os
1111
import re
1212
from collections.abc import Awaitable, Callable
13-
from dataclasses import dataclass, field
14-
from enum import StrEnum
1513
from typing import Any
1614

1715
from mcp.server.fastmcp import Context, FastMCP
1816

1917
from deepset_mcp.api.client import AsyncDeepsetClient
2018
from deepset_mcp.config import DEFAULT_CLIENT_HEADER
21-
from deepset_mcp.initialize_embedding_model import get_initialized_model
2219
from deepset_mcp.store import STORE
23-
from deepset_mcp.tools.custom_components import (
24-
get_latest_custom_component_installation_logs as get_latest_custom_component_installation_logs_tool,
25-
list_custom_component_installations as list_custom_component_installations_tool,
26-
)
27-
from deepset_mcp.tools.doc_search import (
28-
search_docs as search_docs_tool,
29-
)
30-
from deepset_mcp.tools.haystack_service import (
31-
get_component_definition as get_component_definition_tool,
32-
get_custom_components as get_custom_components_tool,
33-
list_component_families as list_component_families_tool,
34-
search_component_definition as search_component_definition_tool,
35-
)
36-
from deepset_mcp.tools.indexes import (
37-
create_index as create_index_tool,
38-
deploy_index as deploy_index_tool,
39-
get_index as get_index_tool,
40-
list_indexes as list_indexes_tool,
41-
update_index as update_index_tool,
42-
)
43-
44-
# Import all tool functions
45-
from deepset_mcp.tools.pipeline import (
46-
create_pipeline as create_pipeline_tool,
47-
deploy_pipeline as deploy_pipeline_tool,
48-
get_pipeline as get_pipeline_tool,
49-
get_pipeline_logs as get_pipeline_logs_tool,
50-
list_pipelines as list_pipelines_tool,
51-
search_pipeline as search_pipeline_tool,
52-
update_pipeline as update_pipeline_tool,
53-
validate_pipeline as validate_pipeline_tool,
54-
)
55-
from deepset_mcp.tools.pipeline_template import (
56-
get_template as get_pipeline_template_tool,
57-
list_templates as list_pipeline_templates_tool,
58-
search_templates as search_pipeline_templates_tool,
59-
)
60-
from deepset_mcp.tools.secrets import (
61-
get_secret as get_secret_tool,
62-
list_secrets as list_secrets_tool,
63-
)
20+
from deepset_mcp.tool_models import MemoryType, ToolConfig, WorkspaceMode
21+
from deepset_mcp.tool_registry import TOOL_REGISTRY
6422
from deepset_mcp.tools.tokonomics import RichExplorer, explorable, explorable_and_referenceable, referenceable
65-
from deepset_mcp.tools.workspace import (
66-
create_workspace as create_workspace_tool,
67-
get_workspace as get_workspace_tool,
68-
list_workspaces as list_workspaces_tool,
69-
)
7023

7124

7225
def are_docs_available() -> bool:
@@ -78,89 +31,6 @@ def are_docs_available() -> bool:
7831
)
7932

8033

81-
EXPLORER = RichExplorer(store=STORE)
82-
83-
84-
def get_from_object_store(object_id: str, path: str = "") -> str:
85-
"""Use this tool to fetch an object from the object store.
86-
87-
You can fetch a specific object by using the object's id (e.g. `@obj_001`).
88-
You can also fetch any nested path by using the path-parameter
89-
(e.g. `{"object_id": "@obj_001", "path": "user_info.given_name"}`
90-
-> returns the content at obj.user_info.given_name).
91-
92-
:param object_id: The id of the object to fetch in the format `@obj_001`.
93-
:param path: The path of the object to fetch in the format of `access.to.attr` or `["access"]["to"]["attr"]`.
94-
"""
95-
return EXPLORER.explore(obj_id=object_id, path=path)
96-
97-
98-
def get_slice_from_object_store(
99-
object_id: str,
100-
start: int = 0,
101-
end: int | None = None,
102-
path: str = "",
103-
) -> str:
104-
"""Extract a slice from a string or list object that is stored in the object store.
105-
106-
:param object_id: Identifier of the object.
107-
:param start: Start index for slicing.
108-
:param end: End index for slicing (optional - leave empty to get slice from start to end of sequence).
109-
:param path: Navigation path to object to slice (optional).
110-
:return: String representation of the slice.
111-
"""
112-
return EXPLORER.slice(obj_id=object_id, start=start, end=end, path=path)
113-
114-
115-
async def search_docs(query: str) -> str:
116-
"""Search the deepset platform documentation.
117-
118-
This tool allows you to search through deepset's official documentation to find
119-
information about features, API usage, best practices, and troubleshooting guides.
120-
Use this when you need to look up specific deepset functionality or help users
121-
understand how to use deepset features.
122-
123-
:param query: The search query to execute against the documentation.
124-
:returns: The formatted search results from the documentation.
125-
"""
126-
async with AsyncDeepsetClient(
127-
api_key=os.environ["DEEPSET_DOCS_API_KEY"], transport_config=DEFAULT_CLIENT_HEADER
128-
) as client:
129-
response = await search_docs_tool(
130-
client=client,
131-
workspace=os.environ["DEEPSET_DOCS_WORKSPACE"],
132-
pipeline_name=os.environ["DEEPSET_DOCS_PIPELINE_NAME"],
133-
query=query,
134-
)
135-
return response
136-
137-
138-
class WorkspaceMode(StrEnum):
139-
"""Configuration for how workspace is provided to tools."""
140-
141-
STATIC = "static" # workspace from env, no parameter in tool signature
142-
DYNAMIC = "dynamic" # workspace as required parameter in tool signature
143-
144-
145-
class MemoryType(StrEnum):
146-
"""Configuration for how memory is provided to tools."""
147-
148-
EXPLORABLE = "explorable"
149-
REFERENCEABLE = "referenceable"
150-
BOTH = "both"
151-
NO_MEMORY = "no_memory"
152-
153-
154-
@dataclass
155-
class ToolConfig:
156-
"""Configuration for tool registration."""
157-
158-
needs_client: bool = False
159-
needs_workspace: bool = False
160-
memory_type: MemoryType = MemoryType.NO_MEMORY
161-
custom_args: dict[str, Any] = field(default_factory=dict)
162-
163-
16434
def get_workspace_from_env() -> str:
16535
"""Gets the workspace configured from environment variable."""
16636
workspace = os.environ.get("DEEPSET_WORKSPACE")
@@ -169,135 +39,6 @@ def get_workspace_from_env() -> str:
16939
return workspace
17040

17141

172-
TOOL_REGISTRY: dict[str, tuple[Callable[..., Any], ToolConfig]] = {
173-
# Workspace tools
174-
"list_pipelines": (
175-
list_pipelines_tool,
176-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
177-
),
178-
"create_pipeline": (
179-
create_pipeline_tool,
180-
ToolConfig(
181-
needs_client=True,
182-
needs_workspace=True,
183-
memory_type=MemoryType.BOTH,
184-
custom_args={"skip_validation_errors": True},
185-
),
186-
),
187-
"update_pipeline": (
188-
update_pipeline_tool,
189-
ToolConfig(
190-
needs_client=True,
191-
needs_workspace=True,
192-
memory_type=MemoryType.BOTH,
193-
custom_args={"skip_validation_errors": True},
194-
),
195-
),
196-
"get_pipeline": (
197-
get_pipeline_tool,
198-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
199-
),
200-
"deploy_pipeline": (
201-
deploy_pipeline_tool,
202-
ToolConfig(
203-
needs_client=True,
204-
needs_workspace=True,
205-
memory_type=MemoryType.EXPLORABLE,
206-
custom_args={"wait_for_deployment": True, "timeout_seconds": 600, "poll_interval": 5},
207-
),
208-
),
209-
"validate_pipeline": (
210-
validate_pipeline_tool,
211-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.BOTH),
212-
),
213-
"get_pipeline_logs": (
214-
get_pipeline_logs_tool,
215-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
216-
),
217-
"search_pipeline": (
218-
search_pipeline_tool,
219-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
220-
),
221-
"list_indexes": (
222-
list_indexes_tool,
223-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
224-
),
225-
"get_index": (
226-
get_index_tool,
227-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
228-
),
229-
"create_index": (
230-
create_index_tool,
231-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.BOTH),
232-
),
233-
"update_index": (
234-
update_index_tool,
235-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.BOTH),
236-
),
237-
"deploy_index": (
238-
deploy_index_tool,
239-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
240-
),
241-
"list_templates": (
242-
list_pipeline_templates_tool,
243-
ToolConfig(
244-
needs_client=True,
245-
needs_workspace=True,
246-
memory_type=MemoryType.EXPLORABLE,
247-
custom_args={"field": "created_at", "order": "DESC", "limit": 100},
248-
),
249-
),
250-
"get_template": (
251-
get_pipeline_template_tool,
252-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
253-
),
254-
"search_templates": (
255-
search_pipeline_templates_tool,
256-
ToolConfig(
257-
needs_client=True,
258-
needs_workspace=True,
259-
memory_type=MemoryType.EXPLORABLE,
260-
custom_args={"model": get_initialized_model()},
261-
),
262-
),
263-
"list_custom_component_installations": (
264-
list_custom_component_installations_tool,
265-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
266-
),
267-
"get_latest_custom_component_installation_logs": (
268-
get_latest_custom_component_installation_logs_tool,
269-
ToolConfig(needs_client=True, needs_workspace=True, memory_type=MemoryType.EXPLORABLE),
270-
),
271-
# Non-workspace tools
272-
"list_component_families": (
273-
list_component_families_tool,
274-
ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE),
275-
),
276-
"get_component_definition": (
277-
get_component_definition_tool,
278-
ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE),
279-
),
280-
"search_component_definitions": (
281-
search_component_definition_tool,
282-
ToolConfig(
283-
needs_client=True, memory_type=MemoryType.EXPLORABLE, custom_args={"model": get_initialized_model()}
284-
),
285-
),
286-
"get_custom_components": (
287-
get_custom_components_tool,
288-
ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE),
289-
),
290-
"list_secrets": (list_secrets_tool, ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE)),
291-
"get_secret": (get_secret_tool, ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE)),
292-
"list_workspaces": (list_workspaces_tool, ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE)),
293-
"get_workspace": (get_workspace_tool, ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE)),
294-
"create_workspace": (create_workspace_tool, ToolConfig(needs_client=True, memory_type=MemoryType.EXPLORABLE)),
295-
"get_from_object_store": (get_from_object_store, ToolConfig(memory_type=MemoryType.NO_MEMORY)),
296-
"get_slice_from_object_store": (get_slice_from_object_store, ToolConfig(memory_type=MemoryType.NO_MEMORY)),
297-
"search_docs": (search_docs, ToolConfig(memory_type=MemoryType.NO_MEMORY)),
298-
}
299-
300-
30142
def apply_custom_args(base_func: Callable[..., Any], config: ToolConfig) -> Callable[..., Any]:
30243
"""
30344
Applies custom keyword arguments defined in the ToolConfig to a function.

src/deepset_mcp/tool_models.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SPDX-FileCopyrightText: 2025-present deepset GmbH <info@deepset.ai>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
from dataclasses import dataclass, field
6+
from enum import StrEnum
7+
from typing import Any
8+
9+
10+
class MemoryType(StrEnum):
11+
"""Configuration for how memory is provided to tools."""
12+
13+
EXPLORABLE = "explorable"
14+
REFERENCEABLE = "referenceable"
15+
BOTH = "both"
16+
NO_MEMORY = "no_memory"
17+
18+
19+
@dataclass
20+
class ToolConfig:
21+
"""Configuration for tool registration."""
22+
23+
needs_client: bool = False
24+
needs_workspace: bool = False
25+
memory_type: MemoryType = MemoryType.NO_MEMORY
26+
custom_args: dict[str, Any] = field(default_factory=dict)
27+
28+
29+
class WorkspaceMode(StrEnum):
30+
"""Configuration for how workspace is provided to tools."""
31+
32+
STATIC = "static" # workspace from env, no parameter in tool signature
33+
DYNAMIC = "dynamic" # workspace as required parameter in tool signature

0 commit comments

Comments
 (0)