This project implements a Model Context Protocol (MCP) server that provides document search capabilities through Apache Solr. It allows Large Language Models to search and retrieve documents from Solr collections using the MCP standard.
- MCP Resources for searching Solr documents
- MCP Tools for advanced search and document retrieval
- Asynchronous communication with Solr using httpx
- Type-safe interfaces with Pydantic models
- Authentication support (JWT)
- Comprehensive test suite
- Docker-based Solr development environment
Version 1.0.0 - See CHANGELOG.md for details on all changes.
The Model Context Protocol (MCP) is a standardized way for applications to provide context to Large Language Models (LLMs). This project implements an MCP server that exposes Apache Solr's search capabilities to LLMs, allowing them to:
- Search for documents using simple or complex queries
- Retrieve specific documents by ID
- Filter, sort, and paginate search results
- Python 3.11+
- Docker and Docker Compose (for the integrated Solr environment)
uv
package manager (recommended)- MCP 1.6.0+ (see compatibility notes below)
-
Install
uv
(if not already installed):pip install uv
-
Install the project dependencies:
uv install
Or with pip:
pip install -e .
-
Copy the environment template and configure it:
cp .env.example .env # Edit .env with your Solr connection details
-
Create and activate a virtual environment (important):
python -m venv .venv source .venv/bin/activate # On Linux/macOS # OR .\.venv\Scripts\activate # On Windows
Note: Always ensure the virtual environment is activated before running the server or client tools. Many connection issues are caused by running commands outside the virtual environment.
This project is currently developed and tested with MCP 1.6.0, which has some API differences from earlier versions:
- MCP 1.6.0 doesn't support the
app.state
attribute for storing shared state - The
lifespan
context manager pattern causes TaskGroup errors in MCP 1.6.0 - Instead, the project uses global variables for shared resources (such as the Solr client)
- MCP 1.6.0 doesn't support direct HTTP access - The FastMCP.run() method only supports 'stdio' or 'sse' transport
If you're using a different MCP version, you may need to adjust the code accordingly. See the TASK.md file under "Discovered During Work" for more details on compatibility issues.
Since MCP 1.6.0 doesn't support direct HTTP access through its standard API, this project includes a FastAPI-based alternative server that mimics the MCP interface but ensures HTTP accessibility:
# Run the FastAPI-based server for direct HTTP access
python run_server.py --mode http
This server provides:
- Direct HTTP access on port 8765
- MCP-compatible tool endpoints (e.g.,
/tool/search
) - MCP-compatible resource endpoints (e.g.,
/resource/solr://search/{query}
) - Interactive API documentation at http://localhost:8765/docs
Example of direct HTTP access with curl:
# Tool endpoint example
curl -X POST http://localhost:8765/tool/search \
-H "Content-Type: application/json" \
-d '{"query": "*:*", "rows": 5}'
# Resource endpoint example
curl -G http://localhost:8765/resource/solr%3A%2F%2Fsearch%2F%2A%3A%2A
The project includes a Docker Compose setup with Apache Solr and sample documents for development and testing:
# Start the Solr container with sample data
./start_solr.sh
# Access the Solr Admin UI
open http://localhost:8983/solr/
This will:
- Start an Apache Solr 9.4 container
- Create a "documents" collection
- Load 10 sample documents with various fields
- Configure everything for immediate use with the MCP server
You can run the MCP server using the provided wrapper script which supports different modes:
# Show help and available options
python run_server.py --mode help
# Run the MCP protocol server (for LLM integration)
python run_server.py --mode mcp
# Run the HTTP API server (for direct HTTP access)
python run_server.py --mode http
# Specify a custom port
python run_server.py --mode http --port 9000
For development with MCP Inspector GUI:
# MCP development environment with inspector GUI
mcp dev src/server/mcp_server.py
For Claude Desktop integration:
# Install the MCP server for Claude Desktop
mcp install src/server/mcp_server.py --name "Solr Search"
The server exposes the following MCP endpoints:
- Resource:
solr://search/{query}
- Basic search functionality - Tool:
search
- Advanced search with filtering, sorting, and pagination - Tool:
get_document
- Retrieve specific documents by ID
# Example of using the search tool from an MCP client
result = await session.call_tool(
"search",
arguments={
"query": "machine learning",
"filter_query": "category:technology",
"sort": "date desc",
"rows": 5,
"start": 0
}
)
# Example of retrieving a document by ID
document = await session.call_tool(
"get_document",
arguments={
"id": "doc123",
"fields": ["title", "content", "author"]
}
)
The following environment variables can be configured in your .env
file:
# MCP Server Configuration
MCP_SERVER_NAME=Solr Search
MCP_SERVER_PORT=8765
# Apache Solr Configuration
SOLR_BASE_URL=http://localhost:8983/solr
SOLR_COLLECTION=documents
SOLR_USERNAME=
SOLR_PASSWORD=
# Authentication (for future use)
JWT_SECRET_KEY=your_jwt_secret_key
JWT_ALGORITHM=HS256
JWT_EXPIRATION_MINUTES=1440 # 24 hours
# Logging
LOG_LEVEL=INFO
There are several ways to test and interact with the MCP Solr server:
This is the most convenient method for testing and debugging:
# Start the server with the inspector
mcp dev src/server/mcp_server.py
Then open http://127.0.0.1:6274 in your browser to access the MCP Inspector.
-
Using the Resource:
- Find the resource
solr://search/{query}
in the sidebar - Replace
{query}
with your search term (e.g.,*:*
for all documents) - Click "Execute"
- Find the resource
-
Using the Search Tool:
- Go to the "Tools" section and select the "search" tool
- Enter parameters in JSON format:
{ "query": "*:*", "filter_query": "category:technology", "sort": "id asc", "rows": 5, "start": 0 }
- Click "Execute"
- Go to the "Tools" section and select the "get_document" tool
- Enter parameters in JSON format:
{ "id": "doc1", "fields": ["title", "content", "author"] }
- Click "Execute"
You can create a simple Python client to test the server:
import asyncio
from mcp.client import MCPClient
async def test_solr_search():
# Connect to the MCP server
async with MCPClient(url="http://localhost:8765") as client:
# Get server info to verify connection
server_info = await client.get_server_info()
print("Connected to MCP server:", server_info.name)
# Execute a search
search_result = await client.call_tool(
"search",
arguments={
"query": "*:*",
"filter_query": None,
"sort": "id asc",
"rows": 5,
"start": 0
}
)
print("Search results:", search_result)
# If documents were found, retrieve the first one
if "response" in search_result and search_result["response"]["numFound"] > 0:
doc_id = search_result["response"]["docs"][0]["id"]
document = await client.call_tool(
"get_document",
arguments={
"id": doc_id,
"fields": ["title", "content"]
}
)
print(f"Document with ID {doc_id}:", document)
if __name__ == "__main__":
asyncio.run(test_solr_search())
Save this as test_solr_client.py
and run:
python test_solr_client.py
You can also test with curl or any HTTP client. Note that the MCP server expects specific request formats:
# Testing search tool with curl
curl -X POST http://localhost:8765/tool/search \
-H "Content-Type: application/json" \
-d '{"query": "*:*", "rows": 5}'
# Retrieving a document with curl
curl -X POST http://localhost:8765/tool/get_document \
-H "Content-Type: application/json" \
-d '{"id": "doc1"}'
# Using the resource endpoint
curl -G http://localhost:8765/resource/solr%3A%2F%2Fsearch%2F%2A%3A%2A \
--data-urlencode "query=*:*"
If you can access the MCP Inspector but not connect with other clients:
-
Check CORS settings:
- If using a web client from a different origin, CORS might be blocking requests
-
Verify network access:
- Ensure port 8765 is accessible from the client
-
Check for authentication requirements:
- If authentication is enabled, ensure clients are including the required credentials
-
Inspect request format:
- MCP expects specific endpoint formats and JSON structures
-
Use the debug server mode:
MCP_DEBUG=1 python run_server.py --mode mcp
# Run all tests (unit and integration)
pytest
# Run only unit tests
pytest tests/test_server.py
# Run only integration tests (requires running Solr)
pytest tests/test_integration_server.py -m integration
# Run with coverage
pytest --cov=src
Integration tests will automatically skip if the Solr server is not available, so they're safe to run even without a running Docker environment.
/src
server.py # Main MCP server implementation
/tests
test_server.py # Unit tests with mocked Solr responses
test_integration_server.py # Integration tests with real Solr
/docker
/solr
load_sample_data.py # Script to load sample documents
/configsets
/documents
/conf
schema.xml # Solr schema definition
solrconfig.xml # Solr configuration
stopwords.txt # Stopwords for text analysis
docker-compose.yml # Docker Compose configuration for Solr
start_solr.sh # Script to start Solr and load data
.env.example # Environment variables template
pyproject.toml # Project configuration
PLANNING.md # Project planning document
TASK.md # Project tasks and progress tracking
CHANGELOG.md # Documentation of project changes
README.md # This file
This project follows Semantic Versioning. For the versions available, see the CHANGELOG.md file for details on what has changed in each version.
- MCP Python SDK Documentation
- Apache Solr Documentation
- Claude Desktop - For direct integration with the MCP server
- Fork the repository
- Create a feature branch:
git checkout -b feature-name
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin feature-name
- Submit a pull request
This project is licensed under the MIT License.