Chroma

Lightweight, dependency-free, in-memory Chroma (v1) API fake for testing code that uses the real chromadb client. Stores embeddings in memory and performs a real L2 nearest-neighbor query.

Default port: 4860

Quick start

import { ChromaServer } from "./services/chroma/src/server.js";

const server = new ChromaServer(4860);
await server.start();
// ... run your app/tests ...
await server.stop();

REST usage:

// Create a collection
const col = await (await fetch("http://127.0.0.1:4860/api/v1/collections", {
  method: "POST", headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "docs" }),
})).json();

// Add embeddings
await fetch(`http://127.0.0.1:4860/api/v1/collections/${col.id}/add`, {
  method: "POST", headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ ids: ["a"], embeddings: [[1, 0, 0]], documents: ["doc a"] }),
});

// Query nearest neighbors
const res = await fetch(`http://127.0.0.1:4860/api/v1/collections/${col.id}/query`, {
  method: "POST", headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query_embeddings: [[0.9, 0.1, 0]], n_results: 3 }),
});
// => { ids, distances, documents, metadatas }

Access via MCP / preview URL

Implemented operations

Service & inspection operations (parlel extensions)

Surface coverage

This emulator faithfully replicates the API surface most application code and agents exercise. Anything below the supported lines is either an intentional design choice for a fast, zero-cost local emulator (✓ By design) or a candidate for a future release (⟳ Roadmap) — never a silent inaccuracy.

Legend: ✅ fully supported · ◐ accepted (stored, not strictly enforced) · ✓ by design · ⟳ on the roadmap.

FeatureStatus
Collection create/list/get/delete✅ Supported
add / upsert with explicit embeddings✅ Supported
query nearest-neighbor (L2)✅ Supported (real squared L2)
get / count / delete records✅ Supported
Server-side embedding functions⟳ Roadmap — supply embeddings
where metadata filters ($eq/$ne/$gt/$gte/$lt/$lte/$in/$nin/$and/$or)✅ Supported
where_document filters ($contains / $not_contains / $and / $or)✅ Supported
limit / offset on get✅ Supported
Cosine/IP space selection◐ Default squared-L2 ordering (metadata accepted)
Auth tokens◐ Not required

Error codes & shapes

Errors use { "error": "..." }.

StatusWhen
400missing name / embeddings / query_embeddings
404unknown collection or endpoint
409collection already exists (without get_or_create)

Manifest

See services/chroma/manifest.json:

<!-- parlel:testenv:start -->

Configuration — test.env

Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.

CHROMA_BASE_URL=http://parlel-bridge:4860
CHROMA_SERVER_HOST=parlel-bridge:4860
CHROMA_SERVER_HTTP_PORT=4860
<!-- parlel:testenv:end -->