deepset-mcp-server provides an API SDK and MCP (model context protocol) tools to interact with the deepset API.
deepset is an AI platform that allows users to develop and deploy AI applications.
All applications are defined as Haystack pipelines.
Haystack is an Open Source Python framework for AI application building.
All source code is in src/deepset_mcp.
Code for the API SDK is in src/deepset_mcp/api.
Code for tools is in src/deepset_mcp/tools.
The tools are added to an MCP server which is defined in src/deepset_mcp/main.py and configured in src/deepset_mcp/tool_factory.py.
Tests are in the test directory.
All unit tests go into test/unit, integration tests go into test/integration.
We use uv to manage the project.
All project level configurations are defined in pyproject.toml at the root of the repository.
The API SDK is 'async first'.
All API interactions run through a common facade called AsyncDeepsetClient.
The client exposes resources that in turn expose methods to interact with these resources through the deepset API.
As an example, to fetch a specific pipeline a user might do:
from deepset_mcp.api.client import AsyncDeepsetClient
async with AsyncDeepsetClient() as client:
response = await client.pipelines(workspace="some_workspace").get("my_pipeline")Tools are meant to be used by large language models.
Known exceptions should usually be caught and converted to strings.
Typically, we have one tool file per resource.
A tool can make multiple calls to different resources or different methods on the same resource to produce the desired output.
Most tools are imported into src/deepset_mcp/tool_factory.py where they are added to the MCP server.
Let's assume we want to add a PipelineFeedbackResource.
You would need to make the following changes:
- add a package for the resource at
src/deepset_mcp/api/pipeline_feedback - the resource goes into
src/deepset_mcp/api/pipeline_feedback/resource.py - (optional) if you need to define models for API response they would go into
src/deepset_mcp/api/pipeline_feedback/models.py - add a Protocol for the resource in
src/deepset_mcp/api/pipeline_feedback/protocols.py - add the resource to the AsyncClientProtocol in the
src/deepset_mcp/api/protocols.py(depending on the resource you need client and workspace or just client) - add a method for the resource to the
AsyncDeepsetClientinsrc/deepset_mcp/api/client.py
Each resource gets unit and integration tests for all methods.
-
first add a stub for the resource to the
BaseFakeClientintest/unit/conftest.py -
create a directory for the unit tests in
test/unit/api/(i.e.test/unit/api/pipeline_feedback) -
we use pytest for all unit tests
-
import the
BaseFakeClientfromtest/unit/conftest.py -
Overwrite the
pipeline_feedback-method on the client so that it returns your actualPipelineFeedbackResource -
Add fake responses to the client according to what you want to test
-
Create comprehensive unit tests
-
all tests must have complete type hints including return types
-
test/unit/api/haystack_service/test_haystack_service_resource.pyhas a good example of how to structure unit tests for a resource -
integration tests go into
test/integration -
create an integration test file at
test/integration/test_integration_pipeline_feedback_resource.py -
test/integration/test_integration_haystack_service_resource.pyhas a good example for how integration tests may look like -
don't add too many integration tests, they are mostly a sanity check, the bulk of the testing should be written as unit tests
Let's assume we want to add a fetch_pipeline_resource-tool that will use our newly added resource.
You would need to perform the following steps:
- the tool would go into
src/deepset_mcp/tools/pipeline_feedback.py - the client will ALWAYS be passed to the tool as a dependency injection (type:
AsyncClientProtocol) - the tool should call the methods on the resource through the client
- refer to
src/deepset_mcp/tools/pipeline.pyas a good example for tool implementations - extract model or response serialization into reusable helper functions
- once you added a tool, import it in
src/deepset_mcp/tool_factory.pyand add it to the tool registry with the appropriate config - the docstring of the tool will serve as the prompt for the large language model calling the tool, make sure it has good instructions on when to use the tool, how to best use it, and what kind of answer to expect.
We ONLY add unit tests for the tool. The mcp integration will not have tests.
- the tool tests will go into
test/unit/tools(i.e.test/unit/tools/test_pipeline_feedback.py) - use a FakeResource to test the tool
- import the
BaseFakeClientand overwrite the resource method to return your fake resource test/unit/tools/test_pipeline.pyhas a good example for how to test a tool
- Our code is clean and maintainable
- Pay attention to great code structure and optimize for readability
- We use mypy (strict) and ruff for type checking and linting
- Docstrings MUST follow the reStructuredText style (this is a new change and many docstrings follow a different style) Example:
def foo(arg1: Type1, arg2: Type2) -> ReturnType:
"""Returns the result of fooing ``arg1`` with ``arg2``.
:param arg1: A good argument.
:param arg2: Another good argument.
:returns: Some nifty thing or other.
"""- We use Python 3.12
- We use many modern code constructs throughout the code base (Protocols, Generics, Dependency Injection)
- Generally follow the coding style that you are already observing throughout the code base
- keep changes minimal and only implement what was requested in the issue
- all changes need to be tested according to our testing guidelines
- use clear commit messages following the conventional commits style
- we typically make changes in relatively small PRs (e.g. 1 PR for adding a resource and another PR for adding the tools)
- use docstrings, add comments only where needed, follow our code style guidelines
- be kind!