Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
alias(libs.plugins.spring.dependency.management)
jacoco
alias(libs.plugins.errorprone)
alias(libs.plugins.spotless)
}

group = "org.apache.solr"
Expand Down Expand Up @@ -77,4 +78,24 @@ tasks.withType<JavaCompile>().configureEach {
option("NullAway:OnlyNullMarked", "true") // Enable nullness checks only in null-marked code
error("NullAway") // bump checks from warnings (default) to errors
}
}
}

tasks.build {
dependsOn(tasks.spotlessApply)
}

spotless {
java {
target("src/**/*.java")
googleJavaFormat().aosp().reflowLongStrings()
removeUnusedImports()
trimTrailingWhitespace()
endWithNewline()
importOrder()
formatAnnotations()
}
kotlinGradle {
target("*.gradle.kts")
ktlint()
}
}
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
spring-boot = "3.5.6"
spring-dependency-management = "1.1.7"
errorprone-plugin = "4.2.0"
spotless = "7.0.2"

# Main dependencies
spring-ai = "1.1.0-M3"
Expand Down Expand Up @@ -79,4 +80,5 @@ errorprone = [
[plugins]
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }
spring-dependency-management = { id = "io.spring.dependency-management", version.ref = "spring-dependency-management" }
errorprone = { id = "net.ltgt.errorprone", version.ref = "errorprone-plugin" }
errorprone = { id = "net.ltgt.errorprone", version.ref = "errorprone-plugin" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
123 changes: 66 additions & 57 deletions src/main/java/org/apache/solr/mcp/server/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,57 +25,65 @@

/**
* Main Spring Boot application class for the Apache Solr Model Context Protocol (MCP) Server.
*
* <p>This class serves as the entry point for the Solr MCP Server application, which provides
* a bridge between AI clients (such as Claude Desktop) and Apache Solr search and indexing
* capabilities through the Model Context Protocol specification.</p>
*
* <p><strong>Application Architecture:</strong></p>
*
* <p>This class serves as the entry point for the Solr MCP Server application, which provides a
* bridge between AI clients (such as Claude Desktop) and Apache Solr search and indexing
* capabilities through the Model Context Protocol specification.
*
* <p><strong>Application Architecture:</strong>
*
* <p>The application follows a service-oriented architecture where each major Solr operation
* category is encapsulated in its own service class:</p>
* category is encapsulated in its own service class:
*
* <ul>
* <li><strong>SearchService</strong>: Search operations, faceting, sorting, pagination</li>
* <li><strong>IndexingService</strong>: Document indexing, schema-less ingestion, batch processing</li>
* <li><strong>CollectionService</strong>: Collection management, metrics, health monitoring</li>
* <li><strong>SchemaService</strong>: Schema introspection and field management</li>
* <li><strong>SearchService</strong>: Search operations, faceting, sorting, pagination
* <li><strong>IndexingService</strong>: Document indexing, schema-less ingestion, batch
* processing
* <li><strong>CollectionService</strong>: Collection management, metrics, health monitoring
* <li><strong>SchemaService</strong>: Schema introspection and field management
* </ul>
*
* <p><strong>Spring Boot Features:</strong></p>
*
* <p><strong>Spring Boot Features:</strong>
*
* <ul>
* <li><strong>Auto-Configuration</strong>: Automatic setup of Solr client and service beans</li>
* <li><strong>Property Management</strong>: Externalized configuration through application.properties</li>
* <li><strong>Dependency Injection</strong>: Automatic wiring of service dependencies</li>
* <li><strong>Component Scanning</strong>: Automatic discovery of service classes</li>
* <li><strong>Auto-Configuration</strong>: Automatic setup of Solr client and service beans
* <li><strong>Property Management</strong>: Externalized configuration through
* application.properties
* <li><strong>Dependency Injection</strong>: Automatic wiring of service dependencies
* <li><strong>Component Scanning</strong>: Automatic discovery of service classes
* </ul>
*
* <p><strong>Communication Flow:</strong></p>
*
* <p><strong>Communication Flow:</strong>
*
* <ol>
* <li>AI client connects to MCP server via stdio</li>
* <li>Client discovers available tools through MCP protocol</li>
* <li>Client invokes tools with natural language parameters</li>
* <li>Server routes requests to appropriate service methods</li>
* <li>Services interact with Solr via SolrJ client library</li>
* <li>Results are serialized and returned to AI client</li>
* <li>AI client connects to MCP server via stdio
* <li>Client discovers available tools through MCP protocol
* <li>Client invokes tools with natural language parameters
* <li>Server routes requests to appropriate service methods
* <li>Services interact with Solr via SolrJ client library
* <li>Results are serialized and returned to AI client
* </ol>
*
* <p><strong>Configuration Requirements:</strong></p>
* <p>The application requires the following configuration properties:</p>
*
* <p><strong>Configuration Requirements:</strong>
*
* <p>The application requires the following configuration properties:
*
* <pre>{@code
* # application.properties
* solr.url=http://localhost:8983
* }</pre>
*
* <p><strong>Deployment Considerations:</strong></p>
*
* <p><strong>Deployment Considerations:</strong>
*
* <ul>
* <li>Ensure Solr server is running and accessible at configured URL</li>
* <li>Verify network connectivity between MCP server and Solr</li>
* <li>Configure appropriate timeouts for production workloads</li>
* <li>Monitor application logs for connection and performance issues</li>
* <li>Ensure Solr server is running and accessible at configured URL
* <li>Verify network connectivity between MCP server and Solr
* <li>Configure appropriate timeouts for production workloads
* <li>Monitor application logs for connection and performance issues
* </ul>
*
* @version 0.0.1
* @since 0.0.1
*
* @see SearchService
* @see IndexingService
* @see CollectionService
Expand All @@ -87,35 +95,36 @@ public class Main {

/**
* Main application entry point that starts the Spring Boot application.
*
* <p>This method initializes the Spring application context, configures all
* service beans, establishes Solr connectivity, and begins listening for
* MCP client connections via standard input/output.</p>
*
* <p><strong>Startup Process:</strong></p>
*
* <p>This method initializes the Spring application context, configures all service beans,
* establishes Solr connectivity, and begins listening for MCP client connections via standard
* input/output.
*
* <p><strong>Startup Process:</strong>
*
* <ol>
* <li>Initialize Spring Boot application context</li>
* <li>Load configuration properties from various sources</li>
* <li>Create and configure SolrClient bean</li>
* <li>Initialize all service beans with dependency injection</li>
* <li>Register MCP tools from service methods</li>
* <li>Start MCP server listening on stdio</li>
* <li>Initialize Spring Boot application context
* <li>Load configuration properties from various sources
* <li>Create and configure SolrClient bean
* <li>Initialize all service beans with dependency injection
* <li>Register MCP tools from service methods
* <li>Start MCP server listening on stdio
* </ol>
*
* <p><strong>Error Handling:</strong></p>
* <p>Startup failures typically indicate configuration issues such as:</p>
*
* <p><strong>Error Handling:</strong>
*
* <p>Startup failures typically indicate configuration issues such as:
*
* <ul>
* <li>Missing or invalid Solr URL configuration</li>
* <li>Network connectivity issues to Solr server</li>
* <li>Missing required dependencies or classpath issues</li>
* <li>Missing or invalid Solr URL configuration
* <li>Network connectivity issues to Solr server
* <li>Missing required dependencies or classpath issues
* </ul>
*
*
* @param args command-line arguments passed to the application
*
* @see SpringApplication#run(Class, String...)
*/
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}

}
}
136 changes: 72 additions & 64 deletions src/main/java/org/apache/solr/mcp/server/config/SolrConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,63 +16,67 @@
*/
package org.apache.solr.mcp.server.config;

import java.util.concurrent.TimeUnit;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.Http2SolrClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

/**
* Spring Configuration class for Apache Solr client setup and connection management.
*
* <p>This configuration class is responsible for creating and configuring the SolrJ client
* that serves as the primary interface for communication with Apache Solr servers. It handles
* URL normalization, connection parameters, and timeout configurations to ensure reliable
* connectivity for the MCP server operations.</p>
*
* <p><strong>Configuration Features:</strong></p>
*
* <p>This configuration class is responsible for creating and configuring the SolrJ client that
* serves as the primary interface for communication with Apache Solr servers. It handles URL
* normalization, connection parameters, and timeout configurations to ensure reliable connectivity
* for the MCP server operations.
*
* <p><strong>Configuration Features:</strong>
*
* <ul>
* <li><strong>Automatic URL Normalization</strong>: Ensures proper Solr URL formatting</li>
* <li><strong>Connection Timeout Management</strong>: Configurable timeouts for reliability</li>
* <li><strong>Property Integration</strong>: Uses externalized configuration through properties</li>
* <li><strong>Production-Ready Defaults</strong>: Optimized timeout values for production use</li>
* <li><strong>Automatic URL Normalization</strong>: Ensures proper Solr URL formatting
* <li><strong>Connection Timeout Management</strong>: Configurable timeouts for reliability
* <li><strong>Property Integration</strong>: Uses externalized configuration through properties
* <li><strong>Production-Ready Defaults</strong>: Optimized timeout values for production use
* </ul>
*
* <p><strong>URL Processing:</strong></p>
* <p>The configuration automatically normalizes Solr URLs to ensure proper communication:</p>
*
* <p><strong>URL Processing:</strong>
*
* <p>The configuration automatically normalizes Solr URLs to ensure proper communication:
*
* <ul>
* <li>Adds trailing slashes if missing</li>
* <li>Appends "/solr/" path if not present in the URL</li>
* <li>Handles various URL formats (with/without protocols, paths, etc.)</li>
* <li>Adds trailing slashes if missing
* <li>Appends "/solr/" path if not present in the URL
* <li>Handles various URL formats (with/without protocols, paths, etc.)
* </ul>
*
* <p><strong>Connection Parameters:</strong></p>
*
* <p><strong>Connection Parameters:</strong>
*
* <ul>
* <li><strong>Connection Timeout</strong>: 10 seconds (10,000ms) for establishing connections</li>
* <li><strong>Socket Timeout</strong>: 60 seconds (60,000ms) for read operations</li>
* <li><strong>Connection Timeout</strong>: 10 seconds (10,000ms) for establishing connections
* <li><strong>Socket Timeout</strong>: 60 seconds (60,000ms) for read operations
* </ul>
*
* <p><strong>Configuration Example:</strong></p>
*
* <p><strong>Configuration Example:</strong>
*
* <pre>{@code
* # application.properties
* solr.url=http://localhost:8983
*
*
* # Results in normalized URL: http://localhost:8983/solr/
* }</pre>
*
* <p><strong>Supported URL Formats:</strong></p>
*
* <p><strong>Supported URL Formats:</strong>
*
* <ul>
* <li>{@code http://localhost:8983} → {@code http://localhost:8983/solr/}</li>
* <li>{@code http://localhost:8983/} → {@code http://localhost:8983/solr/}</li>
* <li>{@code http://localhost:8983/solr} → {@code http://localhost:8983/solr/}</li>
* <li>{@code http://localhost:8983/solr/} → {@code http://localhost:8983/solr/} (unchanged)</li>
* <li>{@code http://localhost:8983} → {@code http://localhost:8983/solr/}
* <li>{@code http://localhost:8983/} → {@code http://localhost:8983/solr/}
* <li>{@code http://localhost:8983/solr} → {@code http://localhost:8983/solr/}
* <li>{@code http://localhost:8983/solr/} → {@code http://localhost:8983/solr/} (unchanged)
* </ul>
*
* @version 0.0.1
* @since 0.0.1
*
* @see SolrConfigurationProperties
* @see Http2SolrClient
* @see org.springframework.boot.context.properties.EnableConfigurationProperties
Expand All @@ -87,44 +91,48 @@ public class SolrConfig {

/**
* Creates and configures a SolrClient bean for Apache Solr communication.
*
* <p>This method serves as the primary factory for creating SolrJ client instances
* that are used throughout the application for all Solr operations. It performs
* automatic URL normalization and applies production-ready timeout configurations.</p>
*
* <p><strong>URL Normalization Process:</strong></p>
*
* <p>This method serves as the primary factory for creating SolrJ client instances that are
* used throughout the application for all Solr operations. It performs automatic URL
* normalization and applies production-ready timeout configurations.
*
* <p><strong>URL Normalization Process:</strong>
*
* <ol>
* <li><strong>Trailing Slash</strong>: Ensures URL ends with "/"</li>
* <li><strong>Solr Path</strong>: Appends "/solr/" if not already present</li>
* <li><strong>Validation</strong>: Checks for proper Solr endpoint format</li>
* <li><strong>Trailing Slash</strong>: Ensures URL ends with "/"
* <li><strong>Solr Path</strong>: Appends "/solr/" if not already present
* <li><strong>Validation</strong>: Checks for proper Solr endpoint format
* </ol>
*
* <p><strong>Connection Configuration:</strong></p>
*
* <p><strong>Connection Configuration:</strong>
*
* <ul>
* <li><strong>Connection Timeout</strong>: 10,000ms - Time to establish initial connection</li>
* <li><strong>Socket Timeout</strong>: 60,000ms - Time to wait for data/response</li>
* <li><strong>Connection Timeout</strong>: 10,000ms - Time to establish initial connection
* <li><strong>Socket Timeout</strong>: 60,000ms - Time to wait for data/response
* </ul>
*
* <p><strong>Client Type:</strong></p>
* <p>Creates an {@code HttpSolrClient} configured for standard HTTP-based communication
* with Solr servers. This client type is suitable for both standalone Solr instances
* and SolrCloud deployments when used with load balancers.</p>
*
* <p><strong>Error Handling:</strong></p>
* <p>URL normalization is defensive and handles various input formats gracefully.
* Invalid URLs or connection failures will be caught during application startup
* or first usage, providing clear error messages for troubleshooting.</p>
*
* <p><strong>Production Considerations:</strong></p>
*
* <p><strong>Client Type:</strong>
*
* <p>Creates an {@code HttpSolrClient} configured for standard HTTP-based communication with
* Solr servers. This client type is suitable for both standalone Solr instances and SolrCloud
* deployments when used with load balancers.
*
* <p><strong>Error Handling:</strong>
*
* <p>URL normalization is defensive and handles various input formats gracefully. Invalid URLs
* or connection failures will be caught during application startup or first usage, providing
* clear error messages for troubleshooting.
*
* <p><strong>Production Considerations:</strong>
*
* <ul>
* <li>Timeout values are optimized for production workloads</li>
* <li>Connection pooling is handled by the HttpSolrClient internally</li>
* <li>Client is thread-safe and suitable for concurrent operations</li>
* <li>Timeout values are optimized for production workloads
* <li>Connection pooling is handled by the HttpSolrClient internally
* <li>Client is thread-safe and suitable for concurrent operations
* </ul>
*
*
* @param properties the injected Solr configuration properties containing connection URL
* @return configured SolrClient instance ready for use in application services
*
* @see Http2SolrClient.Builder
* @see SolrConfigurationProperties#url()
*/
Expand Down Expand Up @@ -153,4 +161,4 @@ SolrClient solrClient(SolrConfigurationProperties properties) {
.withIdleTimeout(SOCKET_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.build();
}
}
}
Loading