Skip to content

feat(MCP): Implement the base framework for a RediVL MCP server#532

Open
vishal-bala wants to merge 5 commits intofeat/RAAE-1395-redisvl-mcpfrom
feat/RAAE-1396/mcp-framework
Open

feat(MCP): Implement the base framework for a RediVL MCP server#532
vishal-bala wants to merge 5 commits intofeat/RAAE-1395-redisvl-mcpfrom
feat/RAAE-1396/mcp-framework

Conversation

@vishal-bala
Copy link
Collaborator

@vishal-bala vishal-bala commented Mar 12, 2026

This PR implements the base framework for a RedisVL MCP server. In this iteration, the goal is to introduce the scaffolding for the MCP server to the extent that the server is runnable but does not have any meaningful functionality.


Note

Medium Risk
Adds a new MCP server surface that manages Redis index creation/validation, vectorizer instantiation, and request concurrency/timeouts; misconfiguration could affect startup behavior and Redis resources. Changes are mostly additive and gated behind an optional mcp extra, reducing impact on existing users.

Overview
Introduces a new optional redisvl.mcp package (enabled via the mcp extra) that provides a runnable MCP server scaffold (RedisVLMCPServer) with lifecycle management for an AsyncSearchIndex, lazy vectorizer construction, and guarded execution with concurrency + timeout limits.

Adds YAML-based MCP configuration loading (load_mcp_config) with ${VAR}/${VAR:-default} env substitution and Pydantic validation for runtime limits and schema field mappings, plus a small error contract (MCPErrorCode, RedisVLMCPError, map_exception) for consistent failure reporting.

Expands test coverage with unit tests for config/env substitution, settings, and error mapping, plus integration tests validating server startup/shutdown behavior (index creation modes, dims mismatch fail-fast, and cleanup on failures). Updates import-sanity to skip redisvl.mcp when optional extras aren’t installed.

Written by Cursor Bugbot for commit 8f98c5c. This will update automatically on new commits. Configure here.

@vishal-bala vishal-bala changed the base branch from main to feat/RAAE-1395-redisvl-mcp March 12, 2026 10:15
@jit-ci
Copy link

jit-ci bot commented Mar 12, 2026

🛡️ Jit Security Scan Results

CRITICAL HIGH MEDIUM

✅ No security findings were detected in this PR


Security scan by Jit

@vishal-bala vishal-bala changed the title Ensure MCP server always disconnects index during shutdown feat(MCP): Implement the base framework for a RediVL MCP server Mar 12, 2026
@vishal-bala vishal-bala self-assigned this Mar 12, 2026
@vishal-bala vishal-bala added the auto:minor Increment the minor version when merged label Mar 12, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf0f0895a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +68 to +72
self._vectorizer = await asyncio.wait_for(
asyncio.to_thread(self._build_vectorizer),
timeout=timeout,
)
self._validate_vectorizer_dims()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disconnect index on startup exceptions

If vectorizer construction or dimension validation fails in this block (for example, a provider init error or a dims mismatch), startup() exits with an exception after AsyncSearchIndex has already opened a Redis client via exists()/create(), but there is no cleanup path that calls disconnect(). In retrying processes this leaks Redis connections across failed startups and can eventually exhaust connection limits; wrap startup initialization in failure cleanup (or call shutdown() in an exception handler) so the index client is always released.

Useful? React with 👍 / 👎.

@vishal-bala vishal-bala requested review from nkanu17 and rbs333 March 12, 2026 12:01
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

await aclose()
elif callable(close):
close()
self._vectorizer = None
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vectorizer reference leaks when close fails during shutdown

Medium Severity

In shutdown(), self._vectorizer = None is placed after the await aclose() / close() calls. If the close operation raises, that line is never reached and self._vectorizer retains its reference. This contrasts with the index cleanup in the finally block, which correctly sets self._index = None before calling disconnect(). The inconsistency means a failed vectorizer close leaves the reference dangling — subsequent shutdown() retries will re-attempt the failing close, and get_vectorizer() could return a broken instance.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto:minor Increment the minor version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant