MCP Server
RedisVL includes a built-in Model Context Protocol (MCP) server that exposes an existing Redis search index to AI agents and assistants through a small, stable tool contract: search-records and upsert-records.
The Model Context Protocol is an open standard that lets AI applications (Claude Desktop, IDE assistants, agent frameworks) call external tools in a uniform way. The RedisVL MCP server, built on the official MCP Go SDK, connects to one existing Redis index, embeds queries with a configured vectorizer, and lets any MCP client search — and optionally write to — that index.
Running the server
The server runs via the rvl CLI with a YAML configuration file:
rvl mcp --config mcp-config.yaml
By default it serves over stdio, which is what desktop MCP clients spawn. For remote clients, use the Streamable HTTP transport:
rvl mcp --config mcp-config.yaml --transport streamable-http --host 127.0.0.1 --port 8000
Pass --read-only when clients should only be able to search:
rvl mcp --config mcp-config.yaml --read-only
Configuration
A complete example (see examples/mcp-config.yaml in the repository):
server:
redis_url: redis://localhost:6379
index:
# Name of an existing Redis search index to expose
redis_name: movies
# Vectorizer used for query embedding and upsert embedding.
# Classes: openai, azure_openai, cohere, mistral, voyageai, ollama.
# API keys come from the standard environment variables.
vectorizer:
class: openai
model: text-embedding-3-small
runtime:
# Vector field of the index (required when a vectorizer is set)
vector_field_name: embedding
# Record field embedded during upsert
default_embed_text_field: description
# Optional: restrict fields returned by search-records
# return_fields: [title, genre, rating]
default_limit: 10
max_limit: 100
max_upsert_records: 64
skip_embedding_if_present: true
# Disable the upsert tool entirely (can also pass --read-only)
read_only: false
| Field | Description | Default |
|---|---|---|
|
Redis connection URL. Falls back to the |
|
|
Name of the existing index to expose (required). |
— |
|
Embedding provider: |
— |
|
Embedding model name. |
provider default |
|
Skips the dimension probe when set. |
auto-detected |
|
Text field used for full-text search fallback (required when no vectorizer is configured). |
— |
|
Vector field used for semantic search and upsert embedding (required when a vectorizer is configured). |
— |
|
Record field embedded during upsert. |
— |
|
Search result count when the client omits |
|
|
Cap on the client-provided |
|
|
Cap on records per upsert call. |
|
|
Skip embedding records that already carry a vector field value. |
|
|
Restrict the fields returned by search. |
all fields except the vector field |
|
Vector datatype of the index field. |
|
|
Disable the upsert tool (equivalent to |
|
Tools
search-records
Runs a semantic search when a vectorizer is configured, otherwise a full-text search over runtime.text_field_name. Raw vector payloads are stripped from the returned records.
{
"query": "space adventure with a robot sidekick",
"limit": 5,
"offset": 0,
"filter": "@genre:{scifi}"
}
Only query is required. filter accepts a raw Redis query filter expression. The result is JSON with count and records.
upsert-records
Inserts or updates records in the index (disabled in read-only mode). When a vectorizer and default_embed_text_field are configured, text in that field is embedded automatically — unless the record already carries a vector value and skip_embedding_if_present is true.
{
"records": [
{"title": "Alien Robot Friends", "genre": "scifi",
"description": "A space adventure with a robot sidekick"}
],
"id_field": "title"
}
The result is JSON with upserted (count) and keys.
Transports and security
-
stdio (default) — the client spawns the server as a subprocess; nothing is exposed on the network. Never authenticated.
-
sse — the server listens on
--host/--portusing the HTTP+SSE transport (for clients on the older protocol revision). -
streamable-http — the server listens on
--host/--portfor remote MCP clients.
Without configured authentication, binding an HTTP transport to a non-loopback host is refused unless you pass --allow-unauthenticated, and a warning is printed even then: any client that can reach the address has full access.
|
JWT authentication
The HTTP transports support JWT bearer authentication, configured in the
server.auth block (or entirely via REDISVL_MCP_AUTH_* environment
variables, which take precedence — useful for injecting settings without
touching the YAML):
server:
redis_url: redis://localhost:6379
auth:
type: jwt
# exactly one of jwks_uri or public_key (PEM) is required
jwks_uri: https://your-idp.example.com/.well-known/jwks.json
issuer: https://your-idp.example.com/ # required
audience: redisvl-mcp # required
# algorithm: RS256 # optional; restricts accepted alg
required_scopes: [mcp:access] # required on every token
read_scope: search:read # gates search-records
write_scope: search:write # gates upsert-records
# authorization_claim: scp # or e.g. "roles" for Azure AD
Tokens are validated for signature, issuer, audience, and the presence of
required claims (defaults exp and iat, so tokens that would never
expire are rejected). Symmetric algorithms (HS*) are not supported.
Requests without a valid token receive 401 with a WWW-Authenticate
challenge; tokens missing a configured read/write scope have the
corresponding tool call rejected. With auth configured, non-loopback binds
are permitted without --allow-unauthenticated.
Environment overrides: REDISVL_MCP_AUTH_TYPE, _JWKS_URI,
_PUBLIC_KEY, _ISSUER, _AUDIENCE, _ALGORITHM, _REQUIRED_SCOPES
(comma-separated), _REQUIRED_CLAIMS (comma-separated), _READ_SCOPE,
_WRITE_SCOPE, _AUTHORIZATION_CLAIM, _BASE_URL. Setting
REDISVL_MCP_AUTH_TYPE=none disables auth regardless of YAML.
Schema overrides
Older Redis versions omit some field attributes (notably vector dims and
datatype) from FT.INFO. The index.schema_overrides block patches the
inspected schema at startup:
index:
redis_name: movies
schema_overrides:
fields:
- name: embedding
type: vector
attrs:
dims: 1536
datatype: float32
Overrides can only patch attrs of fields that were discovered from
FT.INFO — they cannot add fields or change a discovered field’s type or
path. The configured runtime field mappings are validated against the
effective (patched) schema at startup, so misconfigurations fail fast
rather than at query time.
Using with Claude Desktop
For stdio MCP servers, add an entry to claude_desktop_config.json:
{
"mcpServers": {
"redisvl": {
"command": "/usr/local/bin/rvl",
"args": ["mcp", "--config", "/path/to/mcp-config.yaml", "--read-only"],
"env": {
"REDIS_URL": "redis://localhost:6379",
"OPENAI_API_KEY": "sk-..."
}
}
}
}
Restart Claude Desktop and the search-records tool (and upsert-records, unless read-only) appears in the tools list.
Start with --read-only and only enable upserts once you trust the client and have sized max_upsert_records appropriately.
|
See also
-
The rvl CLI — all
rvl mcpflags -
Vectorizers — the embedding providers behind
index.vectorizer -
Getting Started — creating the index the server exposes