Repository navigation
v5.7.5 - MongoDB 9, Voyage Contextual Embeddings & Reranker, MCP 2025-11-25
Feature Release
A compatibility and retrieval release: MongoDB 9.0 support with automatic re-runs of queries 9.0 kills mid-flight, Voyage voyage-code-4, contextualized chunk embeddings and a Voyage reranker, an embedding cache that no longer mixes deployments, and an MCP server that speaks protocol 2025-11-25 with argument completion, logging, and stricter session ownership.
Changes
MongoDB 9.0 is supported
- NEW: Mongo-direct reads (
Parse::MongoDB.aggregate,Parse::MongoDB.find, everything routed through them such asresults_direct, andParse::AtlasSearchsearches) re-run a query the server killed withQueryPlanKilled. MongoDB 9.0 kills a running query this way when a concurrent write turns an indexed field it references into an array (multikey). The read is retried up to twice before the error propagates, and each retry emits aparse.mongodb.query_killed_retrynotification. Other driver errors are not retried. - CHANGED: The integration test stack runs
mongo:9by default; setMONGO_VERSION=8for the previous major. MongoDB 9 will not start on a data volume written by 8, so switch withdocker-compose down -vor a separatePSNEXT_PREFIX. Atlas Local stays on 8.0 until a 9.x image is published. - CHANGED: Applications using
Parse::MongoDB,Parse::AtlasSearch, or the*_directquery methods against a 9.0 server should use themongodriver 2.26 or newer, which handles 9.0's overload (Intelligent Workload Management) errors.
Contextualized chunk embeddings and a Voyage reranker
- NEW:
Parse::Embeddings::Voyageacceptsvoyage-code-4(1024 native, Matryoshka 256/512/1024/2048) and the contextualizedvoyage-context-4andvoyage-context-3, which embed each chunk together with the document it came from through Voyage's/v1/contextualizedembeddings. - NEW:
Voyage#embed_chunks(documents)takes one Array of chunk Strings per document and returns one Array of chunk vectors per document. It enforces Voyage's document and chunk caps before sending, and splits large inputs across requests by whole document so each response stays within the response-size cap. That split is sized by the vectors returned, so it does not by itself keep a request under Voyage's 120k input-token cap. Context models default toembed_batch_size: 32. - NEW:
Parse::Retrieval::Reranker::Voyagewraps Voyage's/v1/rerankand plugs intoParse::Retrieval.retrieve(rerank:). It defaults torerank-3, acceptsrerank-3-liteand the 2.5 and 2 series, and routes an Atlas model API key (al-prefix) to the Atlas Embedding and Reranking API automatically.
Embedding cache entries no longer cross deployments
- FIXED:
Parse::Embeddings::Cachekeyed entries by provider class, model, dimensions, and input type, but not endpoint, so two providers of the same class and model at different deployments (two self-hostedLocalHTTPservers serving different weights under one model name, or a provider behind a proxy) could be served each other's vectors. The key now includesProvider#cache_identity: the endpoint's scheme, host, non-default port, and path, never credentials or a query string. Providers without an endpoint keep their existing keys; built-in providers' existing entries miss once and refill.
MCP server speaks protocol 2025-11-25
- FIXED:
server/discoveris exempt from theMCP-Protocol-Versioncheck. Newer clients send it beforeinitializewith a version this server does not support; the transport rejected it with a 400, so those clients treated the server as broken instead of falling back toinitialize. - NEW: The server negotiates
2025-11-25and still accepts2025-06-18,2025-03-26, and2024-11-05.serverInfocarriestitleanddescription. - NEW:
completion/completecompletes class names for prompt arguments (class_name,parent_class,child_class,classes) and the{className}resource-template variable, and field names forgroup_byandpointer_field. Candidates come from the same scoped tools that backresources/listandget_schema, so hidden classes and fields are never offered. Completions count against the agent's rate limiter. - NEW:
logging/setLevelsendsnotifications/messageat or above the session's level on streaming requests. Tools log withagent.log(level, data, logger:), and failed tool calls are logged atwarning. The capability is advertised only byMCPRackAppwith streaming on. - FIXED:
initializewith anMcp-Session-Idalready bound to a different principal is refused with 403 instead of rebinding the session. Previously a known session id was enough to take over its listening stream, recorded elicitation capability, and log level. The owning principal can still re-initialize. - FIXED: Approval prompts are sent only to clients that accept form-mode elicitation. A
2025-11-25client that declares onlyurlmode was sent a form, rejected it, and the approval was reported as a user cancellation; it is now refused up front with the correct reason. - CHANGED: A
tools/callwhoseargumentsis not a JSON object returns a tool result withisError: trueinstead of an internal error, and malformedcompletion/completeorlogging/setLevelparams return -32602.
Dependencies and tooling
- CHANGED: Bumped locked dependencies to their latest compatible releases:
mongo2.25.0 → 2.26.0,faraday2.14.3 → 2.14.4,graphql2.6.10 → 2.6.11,activesupport8.1.3.1 → 8.1.4, andactivemodel8.1.3.1 → 8.1.4. The lockfile moves to Bundler 4.0.22 and records gem checksums. - CHANGED: CI tests Ruby 3.2, 3.3, 3.4, and 4.0; the former
3.5lane resolved to a 2025 preview build.
Behavior Notes
- These MongoDB 9.0 server changes apply to REST queries (Parse Server passes them to MongoDB) and mongo-direct queries alike:
- Comparisons against
null($eq,$ne,$in,$nin,$gte,$lte, and$lookupequality) treat a dotted path that traverses an array and resolves to no non-null value asnull. For{ a: [] }or{ a: [1] }, a query for"a.b"equal tonilnow matches, and not equal tonilno longer does. $grouprejects an accumulator with an empty field name.$where,$function, and$accumulatorare no longer deprecated in 9.0. The SDK continues to block them in every pipeline and constraint it validates.
- Comparisons against
- The
embedmacro sends each record's source text as its own document, so a contextualized model registered as anembedprovider stores vectors without surrounding-document context. Useembed_chunksfor chunk-level context, and store the vectors on a chunk class that does not declareembed, which would recompute and overwrite them on save. logging/setLeveltargets MCP2025-11-25and earlier; MCP2026-07-28replaces it with a per-request level.agent.logis the stable API either way.
Code Example
voyage = Parse::Embeddings::Voyage.new(api_key: ENV.fetch("VOYAGE_API_KEY"), model: "voyage-context-4")
# One Array of chunks per document; each chunk is embedded with its document as context.
vectors = voyage.embed_chunks([["The release slipped a week.", "It ships Friday."]])
# => [[vec_a1, vec_a2]]
# Rerank retrieved documents with Voyage (an "al-..." Atlas key routes to Atlas automatically).
reranker = Parse::Retrieval::Reranker::Voyage.new(api_key: ENV.fetch("VOYAGE_API_KEY"), model: "rerank-3-lite")
Parse::Retrieval.retrieve(query: "reset my password", klass: Article, k: 30, rerank: reranker, rerank_top_n: 5)Commit: 6851fb2
Author: Adrian Curtin
Date: October 6, 2026