feat(mcp): add list-indexes discovery tool (RAAE-1605)#630
Merged
vishal-bala merged 4 commits intoJul 1, 2026
Merged
Conversation
🛡️ Jit Security Scan Results✅ No security findings were detected in this PR
Security scan by Jit
|
Collaborator
Author
|
CI tests are failing due to flaky issues being fixed by redis-developer/sql-redis#39 |
nkanu17
requested changes
Jun 26, 2026
nkanu17
left a comment
Collaborator
There was a problem hiding this comment.
This generally looks great! I ran into one thing that specified in the comments, it is worth checking the auth access pattern across the tools.
118b01d to
bd2a28a
Compare
e8d750c to
14bbdbf
Compare
Base automatically changed from
feature/raae-1604-config-runtime-model
to
feature/raae-1603-mcp-multi-index
June 30, 2026 20:12
Add an always-registered, read-only `list-indexes` MCP tool so clients can enumerate the logical indexes a multi-index server exposes and choose the right one before calling search-records or upsert-records. For each configured binding the tool returns the logical id, an optional description, whether upsert is available (reflecting both the global --read-only flag and the per-index read_only policy), the shared filterable fields, and any explicitly configured runtime limits. Fields are derived from the binding's already-inspected effective schema rather than user-declared metadata; the vector field and the configured default embed-source text field are omitted because they are implementation inputs, not things a client filters on. The Redis index name (redis_name) is never exposed. Limits are surfaced only when explicitly set in config (detected via the runtime model's model_fields_set), so the output reflects deliberate overrides rather than defaults. - New redisvl/mcp/tools/list_indexes.py with list_indexes() + register_list_indexes_tool(). - Registered unconditionally in the server's tool registration, alongside search/upsert. - Output is deterministic and ordered by configured binding. - TDD: unit coverage for field omission, description/limits inclusion rules, redis_name secrecy, read-only reflection, and registration; integration test verifying fields are derived from the inspected schema across a vector and a fulltext binding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the opaque `rt: Any` parameters in list_indexes.py with the concrete `BindingRuntime` type and the clearer name `binding_runtime`, and type the `server` parameters as `RedisVLMCPServer` (via a TYPE_CHECKING import to avoid the server<->tools import cycle). No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ead (RAAE-1605) Address review on list_indexes.py: - Remove the `tool_list_indexes_description` override: that setting does not exist on MCPSettings (only tool_search/upsert_description do), so the getattr branch was always None and never fired. Pass the default description constant directly. - Read the read scope as `auth_config.read_scope` (a typed field on MCPAuthConfig) instead of a silent `getattr(..., "read_scope", None)`. The old form would fail open — silently yielding None and skipping auth enforcement — if the field were ever renamed; direct access fails loud. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
14bbdbf to
2276985
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort 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.
Reviewed by Cursor Bugbot for commit 2276985. Configure here.
…605)
list_indexes registered the tool instance-level, so it can still be called
before startup or after shutdown when _bindings is empty. Returning
{"indexes": []} there is misleading — a client reads it as "no indexes
configured" rather than "server not ready". Guard with the same
"MCP server has not been started" RuntimeError that resolve_binding raises.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Failing tests are because of the Redis 8.8 flakiness issue - proceeding with the merge |
6bd9d30
into
feature/raae-1603-mcp-multi-index
53 of 54 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Motivation
Once a single MCP server can expose multiple logical indexes (RAAE-1604), clients need a lightweight way to discover what's available so they can pick the right index instead of guessing. This PR (RAAE-1605) adds an always-registered, read-only
list-indexestool for exactly that, and it grounds discovery in the schema the server already inspected at startup rather than asking users to re-declare field metadata in config.Implementation
The new tool (
redisvl/mcp/tools/list_indexes.py) returns one entry per configured binding, in configured order: the logicalid, an optionaldescription, anupsert_availableflag, the shared filterablefields, and — only when explicitly configured — alimitsobject.upsert_availableis simplynot effective_read_only, so it already reflects both the global--read-onlyflag and the per-indexread_onlypolicy resolved at startup. Thefieldslist is built from the binding's effective (inspected + overridden) schema that already lives on itsBindingRuntime, so the output stays consistent with what the index actually contains; the vector field and the configured default embed-source text field are omitted because they are implementation inputs rather than fields a client would filter on. The Redis index name (redis_name) is deliberately never exposed. Limits are included only when the operator set them explicitly — detected via the runtime model'smodel_fields_set— so defaults don't masquerade as deliberate overrides; per the contract this coversmax_limitandmax_upsert_records.The tool is registered unconditionally during the server's tool registration (alongside
search-recordsand the conditionally-registeredupsert-records) and is gated by the same read scope as search when auth is enabled, since it is read-only.Verification
mypyclean;black/isortformatted.redis_namesecrecy, read-only reflection, single- and multi-binding output, and tool registration.🤖 Generated with Claude Code
Note
Low Risk
Read-only discovery metadata with no new config; behavior is additive and gated like existing search tools when auth is enabled.
Overview
Adds a read-only
list-indexesMCP tool so clients can discover logical indexes on multi-binding servers before callingsearch-recordsorupsert-records.The tool is always registered during
_register_tools(alongside search; upsert remains conditional). Each binding is returned in config order withid, optionaldescription,upsert_available(not effective_read_only), filterablefieldsfrom the startup-inspected schema (vector and default embed-source text omitted), andlimitsonly whenmax_limit/max_upsert_recordswere explicitly set.redis_nameis never exposed; empty bindings raiseRuntimeErrorlike other pre-startup paths. When auth is on, the tool uses the same read scope as search.Unit and integration tests cover payload rules, registration, and a two-binding startup scenario.
Reviewed by Cursor Bugbot for commit 45ce686. Bugbot is set up for automated code reviews on this repo. Configure here.