Skip to content

[BUG] MCP Server: cross_encoder/reranker not configurable, hardcoded to OpenAI — requires OPENAI_API_KEY even with non-OpenAI providers #1393

Closed

Description

@marians

Bug Description

The MCP server does not pass a cross_encoder argument when constructing the Graphiti client. This causes Graphiti.__init__ to always fall back to OpenAIRerankerClient(), which requires OPENAI_API_KEY. This makes it impossible to run the MCP server without an OpenAI API key, even when using Anthropic/Gemini/Groq for both LLM and embeddings.

Steps to Reproduce

Configure the MCP server to use non-OpenAI providers for both LLM and embeddings:

# config.yaml
llm:
  provider: "anthropic"
  model: "claude-haiku-4-5-20251001"
  temperature: 0.0
  providers:
    anthropic:
      api_key: "${ANTHROPIC_API_KEY}"

embedder:
  provider: "gemini"
  model: "gemini-embedding-001"
  providers:
    gemini:
      api_key: "${GOOGLE_API_KEY}"

database:
  provider: "falkordb"

Start the MCP server. Both LLM and embedder clients are created successfully, but initialization crashes when Graphiti.__init__ tries to create the default OpenAIRerankerClient.

Expected Behavior

The MCP server should allow configuring the cross-encoder/reranker provider, or at minimum select a matching reranker based on the configured LLM provider.

Actual Behavior

The server crashes with:

openai.OpenAIError: The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable

Traceback:

File "/app/mcp/src/graphiti_mcp_server.py", line 225, in initialize
    self.client = Graphiti(
File "/app/mcp/.venv/lib/python3.11/site-packages/graphiti_core/graphiti.py", line 224, in __init__
    self.cross_encoder = OpenAIRerankerClient()
File "/app/mcp/.venv/lib/python3.11/site-packages/graphiti_core/cross_encoder/openai_reranker_client.py", line 55, in __init__
    self.client = AsyncOpenAI(api_key=config.api_key, base_url=config.base_url)
openai.OpenAIError: The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable

Environment

  • Graphiti Version: graphiti-core 0.28.2, MCP server 1.0.2 (Docker image zepai/knowledge-graph-mcp:1.0.2-graphiti-0.28.2)
  • Python Version: 3.11
  • Operating System: Docker (Debian-based)
  • Database Backend: FalkorDB
  • LLM Provider & Model: Anthropic claude-haiku-4-5-20251001

Installation Method

  • Docker (zepai/knowledge-graph-mcp:1.0.2-graphiti-0.28.2)

Root Cause

graphiti_mcp_server.py lines 225-231 and 233-239 construct Graphiti(...) passing llm_client and embedder but not cross_encoder:

self.client = Graphiti(
    graph_driver=falkor_driver,
    llm_client=llm_client,
    embedder=embedder_client,
    max_coroutines=self.semaphore_limit,
    # cross_encoder is missing here
)

Graphiti.__init__ (graphiti.py line 142) accepts an optional cross_encoder parameter, but when it's not provided, it defaults to OpenAIRerankerClient() (line 224), which unconditionally requires OPENAI_API_KEY.

Workaround

Monkey-patch Graphiti.__init__ to inject an alternative reranker before the server starts. For example, for Gemini:

import graphiti_core.graphiti as _graphiti

_orig_init = _graphiti.Graphiti.__init__

def _patched_init(self, *args, cross_encoder=None, **kwargs):
    if cross_encoder is None:
        from graphiti_core.cross_encoder.gemini_reranker_client import GeminiRerankerClient
        cross_encoder = GeminiRerankerClient()
    _orig_init(self, *args, cross_encoder=cross_encoder, **kwargs)

_graphiti.Graphiti.__init__ = _patched_init

Possible Solution

graphiti-core already ships GeminiRerankerClient and BGERerankerClient alongside OpenAIRerankerClient. The MCP server could:

  1. Add a reranker (or cross_encoder) section to the config schema, mirroring the existing llm/embedder pattern.
  2. Or, as a simpler default, infer the reranker from the configured LLM provider (e.g., Anthropic/Gemini LLM → GeminiRerankerClient, OpenAI → OpenAIRerankerClient).
  3. Pass the resulting cross_encoder to the Graphiti() constructor.

Related

Activity

  1. winklemad commented on Jul 8, 2026

    @winklemad
    Contributor

    I'd like to take this — confirmed against main. Both Graphiti() construction sites in mcp_server/src/graphiti_mcp_server.py (the FalkorDB and Neo4j branches) pass llm_client/embedder but no cross_encoder, so Graphiti.init (L224-227 in graphiti_core/graphiti.py) falls back to OpenAIRerankerClient() and needs OPENAI_API_KEY — exactly the traceback here. Since graphiti-core already ships GeminiRerankerClient and BGERerankerClient, this is pure wiring. My plan: default to your option 2 — infer the reranker from the configured LLM provider via the existing factory in services/factories.py (OpenAI→OpenAIReranker, Anthropic/Gemini→GeminiReranker, etc.) — plus an optional explicit reranker config block (option 1) for override, threaded into both Graphiti() calls. Tests: a factory unit test + a boot test asserting the server starts on a non-OpenAI config without OPENAI_API_KEY. Does "infer-by-default + optional explicit config" match what you'd want, or would you rather I ship just the explicit config block first?

  2. added a commit that references this issue on Jul 27, 2026
    3d7b368
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions