Skip to content

v5.7.5 - MongoDB 9, Voyage Contextual Embeddings & Reranker, MCP 2025-11-25

Choose a tag to compare

@AdrianCurtin AdrianCurtin released this 06 Oct 14:29
· 9 commits to main since this release
6851fb2

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 as results_direct, and Parse::AtlasSearch searches) re-run a query the server killed with QueryPlanKilled. 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 a parse.mongodb.query_killed_retry notification. Other driver errors are not retried.
  • CHANGED: The integration test stack runs mongo:9 by default; set MONGO_VERSION=8 for the previous major. MongoDB 9 will not start on a data volume written by 8, so switch with docker-compose down -v or a separate PSNEXT_PREFIX. Atlas Local stays on 8.0 until a 9.x image is published.
  • CHANGED: Applications using Parse::MongoDB, Parse::AtlasSearch, or the *_direct query methods against a 9.0 server should use the mongo driver 2.26 or newer, which handles 9.0's overload (Intelligent Workload Management) errors.

Contextualized chunk embeddings and a Voyage reranker

  • NEW: Parse::Embeddings::Voyage accepts voyage-code-4 (1024 native, Matryoshka 256/512/1024/2048) and the contextualized voyage-context-4 and voyage-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 to embed_batch_size: 32.
  • NEW: Parse::Retrieval::Reranker::Voyage wraps Voyage's /v1/rerank and plugs into Parse::Retrieval.retrieve(rerank:). It defaults to rerank-3, accepts rerank-3-lite and 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::Cache keyed 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-hosted LocalHTTP servers serving different weights under one model name, or a provider behind a proxy) could be served each other's vectors. The key now includes Provider#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/discover is exempt from the MCP-Protocol-Version check. Newer clients send it before initialize with 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 to initialize.
  • NEW: The server negotiates 2025-11-25 and still accepts 2025-06-18, 2025-03-26, and 2024-11-05. serverInfo carries title and description.
  • NEW: completion/complete completes class names for prompt arguments (class_name, parent_class, child_class, classes) and the {className} resource-template variable, and field names for group_by and pointer_field. Candidates come from the same scoped tools that back resources/list and get_schema, so hidden classes and fields are never offered. Completions count against the agent's rate limiter.
  • NEW: logging/setLevel sends notifications/message at or above the session's level on streaming requests. Tools log with agent.log(level, data, logger:), and failed tool calls are logged at warning. The capability is advertised only by MCPRackApp with streaming on.
  • FIXED: initialize with an Mcp-Session-Id already 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-25 client that declares only url mode 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/call whose arguments is not a JSON object returns a tool result with isError: true instead of an internal error, and malformed completion/complete or logging/setLevel params return -32602.

Dependencies and tooling

  • CHANGED: Bumped locked dependencies to their latest compatible releases: mongo 2.25.0 → 2.26.0, faraday 2.14.3 → 2.14.4, graphql 2.6.10 → 2.6.11, activesupport 8.1.3.1 → 8.1.4, and activemodel 8.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.5 lane 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 $lookup equality) treat a dotted path that traverses an array and resolves to no non-null value as null. For { a: [] } or { a: [1] }, a query for "a.b" equal to nil now matches, and not equal to nil no longer does.
    • $group rejects an accumulator with an empty field name.
    • $where, $function, and $accumulator are no longer deprecated in 9.0. The SDK continues to block them in every pipeline and constraint it validates.
  • The embed macro sends each record's source text as its own document, so a contextualized model registered as an embed provider stores vectors without surrounding-document context. Use embed_chunks for chunk-level context, and store the vectors on a chunk class that does not declare embed, which would recompute and overwrite them on save.
  • logging/setLevel targets MCP 2025-11-25 and earlier; MCP 2026-07-28 replaces it with a per-request level. agent.log is 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