Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.5] - 06/18/2025

- Update chromadb to 1.0.13
- Simplify configuration instantiation
- Clarify list_collection success with no collections
- Remove Optional parameters, replace with | None

## [0.2.4] - 05/21/2025

### Changed
Expand Down
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "chroma-mcp"
version = "0.2.4"
version = "0.2.5"
description = "Chroma MCP Server - Vector Database Integration for LLM Applications"
readme = "README.md"
requires-python = ">=3.10"
Expand All @@ -16,7 +16,7 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules"
]
dependencies = [
"chromadb>=1.0.10",
"chromadb>=1.0.13",
"cohere>=5.14.2",
"httpx>=0.28.1",
"mcp[cli]>=1.2.1",
Expand All @@ -41,6 +41,9 @@ build-backend = "hatchling.build"
[project.scripts]
chroma-mcp = "chroma_mcp:main"

[project.optional-dependencies]
sentence-transformers = ["sentence-transformers>=4.1.0"]

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
Expand Down
95 changes: 2 additions & 93 deletions src/chroma_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


from chromadb.api.collection_configuration import (
CreateCollectionConfiguration, CreateHNSWConfiguration, UpdateHNSWConfiguration, UpdateCollectionConfiguration
CreateCollectionConfiguration
)
from chromadb.api import EmbeddingFunction
from chromadb.utils.embedding_functions import (
Expand Down Expand Up @@ -80,7 +80,6 @@ def get_chroma_client(args=None):

# Load environment variables from .env file if it exists
load_dotenv(dotenv_path=args.dotenv_path)
print(args.dotenv_path)
if args.client_type == 'http':
if not args.host:
raise ValueError("Host must be provided via --host flag or CHROMA_HOST environment variable when using HTTP client")
Expand Down Expand Up @@ -182,57 +181,19 @@ async def chroma_create_collection(
collection_name: str,
embedding_function_name: str = "default",
metadata: Dict | None = None,
space: str | None = None,
ef_construction: int | None = None,
ef_search: int | None = None,
max_neighbors: int | None = None,
num_threads: int | None = None,
batch_size: int | None = None,
sync_threshold: int | None = None,
resize_factor: float | None = None,
) -> str:
"""Create a new Chroma collection with configurable HNSW parameters.

Args:
collection_name: Name of the collection to create
space: Distance function used in HNSW index. Options: 'l2', 'ip', 'cosine'
ef_construction: Size of the dynamic candidate list for constructing the HNSW graph
ef_search: Size of the dynamic candidate list for searching the HNSW graph
max_neighbors: Maximum number of neighbors to consider during HNSW graph construction
num_threads: Number of threads to use during HNSW construction
batch_size: Number of elements to batch together during index construction
sync_threshold: Number of elements to process before syncing index to disk
resize_factor: Factor to resize the index by when it's full
embedding_function_name: Name of the embedding function to use. Options: 'default', 'cohere', 'openai', 'jina', 'voyageai', 'ollama', 'roboflow'
metadata: Optional metadata dict to add to the collection
"""
client = get_chroma_client()


embedding_function = mcp_known_embedding_functions[embedding_function_name]

hnsw_config = CreateHNSWConfiguration()
if space:
hnsw_config["space"] = space
if ef_construction:
hnsw_config["ef_construction"] = ef_construction
if ef_search:
hnsw_config["ef_search"] = ef_search
if max_neighbors:
hnsw_config["max_neighbors"] = max_neighbors
if num_threads:
hnsw_config["num_threads"] = num_threads
if batch_size:
hnsw_config["batch_size"] = batch_size
if sync_threshold:
hnsw_config["sync_threshold"] = sync_threshold
if resize_factor:
hnsw_config["resize_factor"] = resize_factor



configuration=CreateCollectionConfiguration(
hnsw=hnsw_config,
embedding_function=embedding_function()
)

Expand Down Expand Up @@ -310,52 +271,24 @@ async def chroma_modify_collection(
collection_name: str,
new_name: str | None = None,
new_metadata: Dict | None = None,
ef_search: int | None = None,
num_threads: int | None = None,
batch_size: int | None = None,
sync_threshold: int | None = None,
resize_factor: float | None = None,
) -> str:
"""Modify a Chroma collection's name or metadata.

Args:
collection_name: Name of the collection to modify
new_name: Optional new name for the collection
new_metadata: Optional new metadata for the collection
ef_search: Size of the dynamic candidate list for searching the HNSW graph
num_threads: Number of threads to use during HNSW construction
batch_size: Number of elements to batch together during index construction
sync_threshold: Number of elements to process before syncing index to disk
resize_factor: Factor to resize the index by when it's full
"""
client = get_chroma_client()
try:
collection = client.get_collection(collection_name)

hnsw_config = UpdateHNSWConfiguration()
if ef_search:
hnsw_config["ef_search"] = ef_search
if num_threads:
hnsw_config["num_threads"] = num_threads
if batch_size:
hnsw_config["batch_size"] = batch_size
if sync_threshold:
hnsw_config["sync_threshold"] = sync_threshold
if resize_factor:
hnsw_config["resize_factor"] = resize_factor

configuration = UpdateCollectionConfiguration(
hnsw=hnsw_config
)
collection.modify(name=new_name, configuration=configuration, metadata=new_metadata)
collection.modify(name=new_name, metadata=new_metadata)

modified_aspects = []
if new_name:
modified_aspects.append("name")
if new_metadata:
modified_aspects.append("metadata")
if ef_search or num_threads or batch_size or sync_threshold or resize_factor:
modified_aspects.append("hnsw")

return f"Successfully modified collection {collection_name}: updated {' and '.join(modified_aspects)}"
except Exception as e:
Expand Down Expand Up @@ -662,30 +595,6 @@ def validate_thought_data(input_data: Dict) -> Dict:
"branchId": input_data.get("branchId"),
"needsMoreThoughts": input_data.get("needsMoreThoughts"),
}

def process_thought(input_data: Dict) -> Dict:
"""Process a new thought."""
try:
# Validate input data
validated_input = validate_thought_data(input_data)

# Adjust total thoughts if needed
if validated_input["thoughtNumber"] > validated_input["totalThoughts"]:
validated_input["totalThoughts"] = validated_input["thoughtNumber"]

# Return response
return {
"sessionId": validated_input["sessionId"],
"thoughtNumber": validated_input["thoughtNumber"],
"totalThoughts": validated_input["totalThoughts"],
"nextThoughtNeeded": validated_input["nextThoughtNeeded"],
}

except Exception as e:
return {
"error": str(e),
"status": "failed"
}

def main():
"""Entry point for the Chroma MCP server."""
Expand Down
9 changes: 0 additions & 9 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,18 +564,9 @@ async def test_create_collection_success():
hnsw_collection = "test_hnsw_collection"
hnsw_params = {
"collection_name": hnsw_collection,
"space": "cosine",
"ef_construction": 100,
"ef_search": 50,
"max_neighbors": 16 # Assuming M corresponds to max_neighbors
}
hnsw_result = await mcp.call_tool("chroma_create_collection", hnsw_params)
assert "Successfully created collection" in hnsw_result[0].text
# Check if the specific config values are in the output string
assert "'space': 'cosine'" in hnsw_result[0].text
assert "'ef_construction': 100" in hnsw_result[0].text
assert "'ef_search': 50" in hnsw_result[0].text
assert "'max_neighbors': 16" in hnsw_result[0].text

finally:
# Cleanup: delete the collections if they exist
Expand Down
Loading