Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Apache Solr MCP

Apache Solr MCP

Presented at Community over Code 2026 Glasgow.

Avatar for Aditya Parikh

Aditya Parikh

October 15, 2026

Other Decks in Programming

Transcript

  1. Talk to Solr Natural-Language Search with MCP Aditya Parikh &

    Eric Pugh Creator, Apache Solr MCP · SOLR-17944 · Solr committer, OpenSource Connectors github.com/apache/solr-mcp linkedin.com/in/adityamparikh · linkedin.com/in/epugh · github.com/adityamparikh
  2. AGENDA The arc of this talk 1 WHAT 2 WHY

    3 HOW 4 DEMO 5 INTERNALS 6 TRANSPORT & SECURITY 7 SHIP & CONTRIBUTE October 11-14, 2026 Glasgow, Scotland
  3. WHAT img/solr-logo.png What is Apache Solr? solr.apache.org Open-source, multi-modal search

    platform on Apache Lucene. 20+ years production-hardened. solr.apache.org SEARCH QUERY Full-text (BM25) • dense vectors (HNSW/ANN) • hybrid • geospatial • MLT Faceting • filter queries (fq) • highlighting • grouping • streaming expressions INDEX ANALYZE JSON / CSV / XML / PDF (Tika) • NRT • atomic updates • nested docs Tokenizers • stemmers • synonyms • 40+ languages • custom analyzer chains SCALE RELEVANCE SolrCloud • sharding + replication • ZooKeeper • rolling upgrades Learning-to-Rank • function queries • boosts • A/B-friendly configs October 11-14, 2026 Glasgow, Scotland
  4. img/mcp-logo.png WHAT modelcontextprotocol.io What is MCP? modelcontextprotocol.io Model Context Protocol

    — open standard for AI assistants to call external systems. USB-C for AI Without MCP With MCP AI App 1 Database AI App 1 AI App 2 Document Repo AI App 2 AI App 3 External API AI App 3 M × N integrations October 11-14, 2026 Database MCP Document Repo External API M + N integrations Glasgow, Scotland
  5. WHAT What is Solr MCP? 2025 was the year of

    building MCPs. 2026 is the year of putting them in production. apache/solr-mcp Apache 2.0 • first-party ASF sub-project • SOLR-17944 Drop-in Claude Desktop, Claude Code, Cursor, MCP Inspector, any MCP client Two transports STDIO (local desktop) & Streamable HTTP (shared, OAuth 2.1-secured) Packaged JAR • Docker • Java 25+ Built on Spring AI MCP Server • SolrJ • Spring Security • Testcontainers • JSpecify October 11-14, 2026 Glasgow, Scotland
  6. WHY Same question. Two interfaces. BEFORE — Solr query syntax

    q=genre_s:"Science Fiction" &fq=initial_release_date:[ 1990-01-01T00:00:00Z TO 2000-01-01T00:00:00Z} &sort=initial_release_date desc &rows=5&facet=true &facet.field=directed_by AFTER — natural language “Show me the 5 most recent sci-fi films from the 90s, with counts by director.” The LLM calls get-schema, picks the right fields, builds the query, runs it, and summarizes. No Solr syntax required. Requires: field names, date format, query DSL. October 11-14, 2026 Glasgow, Scotland
  7. WHY Locked out of Solr — not just non-developers Solr

    indexes the data. The people who need answers can't write the query — and neither can engineers who don't know Solr syntax, Java or SolrJ. Even experts context-switch between Admin UI, curl and the reference guide. ! Business analysts File tickets with engineering for one-off queries ! Support reps Can't explore knowledge bases without a custom UI ! Product managers Wait days for data — “how many tickets mention X?” ! Engineers new to Solr Write code daily — just not Solr query syntax, Java or SolrJ ! Every new question = new dashboard, new endpoint, new JIRA ticket October 11-14, 2026 Glasgow, Scotland
  8. WHY Why first-party matters A separate repo, released independently —

    works with multiple Solr versions, Apache-governed. ASF GOVERNANCE WORKS WITH YOUR SOLR Apache 2.0, CLAs, public mailing lists, no vendor lock-in Supports multiple Solr versions — adopt without waiting for a cluster upgrade SECURITY & TRUSTED RELEASES LONGEVITY Apache Security Team, CVE process, coordinated disclosure — plus signed, SBOM-tracked source releases via ATR’s Compose → Vote → Finish. Official ASF Docker image: contributors wanted. Outlasts individual maintainers, companies, hype cycles October 11-14, 2026 Glasgow, Scotland
  9. HOW / ARCHITECTURE How it fits together The LLM client

    talks MCP to the server. The server speaks SolrJ to Solr. MCP protocol Java HTTP / Solr API LLM CLIENT SOLR MCP SERVER SolrJ APACHE SOLR Claude Desktop Spring AI MCP Official Java client Collections Claude Code Spring Security for Apache Solr Schemas Cursor STDIO or HTTP Index MCP Inspector October 11-14, 2026 Glasgow, Scotland
  10. HOW / MCP vs API Why not just hand the

    model Solr’s API? Solr’s API is everything Solr can do. Solr MCP is the part we chose to let a model do — declared in code. SOLR’S HTTP API everything Solr can do Query /select /export SOLR MCP tools/list · 15 tools /stream /sql Update <add> <delete> by id <delete> by query Collections CREATE LIST RELOAD Schema read add-field Admin ping Luke · metrics DELETE add-field-type reached by a Solr MCP tool SAME ASK, TWO CLIENTS “delete the books collection” Config API READ-ONLY debugQuery <commit> SPLITSHARD search get-schema list-collections get-collection-stats check-health list-aliases create-collection add-fields add-field-types index-json-documents index-csv-documents index-xml-documents index-markdown-documents create-alias optimize BACKUP delete-field replace-field Core Admin Security API not exposed to the model Claude Desktop MCP tools only Checks list-aliases, finds no delete tool, stops and hands you the curl command. books survives. WRITES delete-alias Claude Code MCP + shell, auto mode Same checks, then ran curl …action=DELETE itself. books deleted. Not in tools/list → not callable via MCP; isolate Solr so MCP is the only path. Enforced in code, not in a prompt: <add>-only XML, additive schema, @PreAuthorize on every tool. October 11-14, 2026 Glasgow, Scotland
  11. HOW / MCP vs API The tool list limited the

    MCP server, not the agent Three things lined up so curl could reach Solr. Each has a fix; only the first is enforced by Solr itself. WHY CLAUDE CODE COULD DELETE IT HOW TO PREVENT IT Solr had no authentication 1 Turn on Solr security enforced by Solr localhost:8983 accepted admin calls from any client. They work as plain GETs, so any tool that fetches a URL can delete. BasicAuth + rules. solr-mcp’s account gets read, update, schema-edit and CREATE; a custom rule keeps action=DELETE admin-only. The agent had another way in 2 Deny the bypass in Claude Code safety net · held in retest A shell (curl, bin/solr), a browser (Claude in Chrome, with saved logins) or computer use reaches Solr around solr-mcp. Deny Bash(curl *admin/collections*). Retest: blocked, and Claude offered to run it if you allow curl. wget or bin/solr delete still get through. Auto mode didn't ask first 3 Use a stricter permission mode human check A curl to a local service wasn't flagged as risky, and the model treated “you asked” as permission. Require approval for every shell command in sessions connected to data you care about. WHO HAS ANOTHER WAY IN? Reaches your machine can go around MCP MCP tools only by default Claude Code, Cursor, Copilot agent mode, Codex CLI, Claude in Chrome, Claude computer use Claude Desktop with only solr-mcp, Claude.ai, ChatGPT. Desktop gains routes once you add a shell or fetch server, Chrome or computer use. Leaving delete out of MCP prevents accidents; a deny rule only blocks the commands it names. Only Solr’s own access rules stop an agent that has another way in. October 11-14, 2026 Glasgow, Scotland
  12. HOW / PRIMITIVES MCP primitives — and how Solr MCP

    uses them Four primitives. Each has a job. Together they turn an LLM into a Solr power user. TOOLS RESOURCES PROMPTS COMPLETIONS MODEL-CONTROLLED — actions the LLM invokes APPLICATION-CONTROLLED — read-only context USER-CONTROLLED — reusable templates USER-TRIGGERED — autocomplete suggestions search solr://collections explore-collections • setupcollection Prefix-filtered, caseinsensitive view-schema • design-schema Bound to {collection} in the schema URI index-json/csv/xml-documents create-collection collections • get-collection-stats check-health list- solr://{collection}/schema LLM sees field names & types → far fewer invented field names • index-data search-collection get-schema • add-fields • addfield-types (additive only) October 11-14, 2026 Glasgow, Scotland
  13. HOW / SKILLS vs MCP Skills vs MCP — different

    layers of the agent stack Skills teach the model the playbook. MCP gives it the hands to run the play, safely. SKILLS MCP instructions for the model protocol to call external systems WHAT Folder of SKILL.md + scripts on local disk WHAT Client–server protocol over JSON-RPC (STDIO or Streamable HTTP) LOADING Progressive disclosure — name+desc only (~100 tok); body on relevance match LOADING Tool schemas often loaded up front (1k–10k+ tokens per server); some hosts defer them RUNTIME Inside the agent’s own environment, no extra process RUNTIME Separate process / container with its own runtime + deps INVOCATION LLM reads SKILL.md and follows the steps (bash, python, curl, …) INVOCATION LLM calls a typed tool; JSON-Schema-validated args; structured response SECURITY Undeclared reach: scripts and SKILL.md act with the agent’s own files, shell and network. Nothing to enumerate up front — audit it like software you install. SECURITY Declared surface: tools/list names each tool and its JSON Schema, scoped per caller. Hosts can ask consent per call. TOGETHER — a Skill drives an MCP tool User LLM + Skills Host solr-mcp Apache Solr natural-language playbook loaded Claude Code/Desktop JSON-RPC tool call real query, real schema October 11-14, 2026 Glasgow, Scotland
  14. DEMO Let's talk to Solr. docker compose up → Claude

    Desktop → plain English explore-collections → search → get-schema → add-fields → index-csv-documents [ video recording ] October 11-14, 2026 Glasgow, Scotland
  15. DEMO / COST What indexing through the model really costs

    The slow part is the model, not Solr. Every byte is re-typed as output tokens before the tool even runs, so CSV pays per byte too, even though Solr parses it. Java + Solr take milliseconds. Format Parsed by Bad document Tool reports ≈ Output tokens Opus 5.5 cost Model time JSON Server · Jackson, nested → a_b Partial: per-doc retry “X of N” + field names 30–39k $0.60–0.80 5–13 min CSV Solr’s CSV handler, verbatim All or nothing Accepted, no count 14–18k $0.30–0.36 3–6 min XML Solr · <add> only (StAX guard) All or nothing Accepted, no count 45–60k $0.90–1.20 8–20 min Markdown Server · CommonMark + YAML Partial: per-doc retry “X of N” 21–29k $0.45–0.60 4–10 min 150-show sample (mydata/shows150.*) · Claude Opus 5.5 output tokens at $20 per million · same file via curl: under 1 s, $0 Proposed fix: pass a reference, not the bytes. A new index-url tool, open for contributors; the sources it accepts differ by mode. STDIO — the server runs on your machine HTTP — the server is remote, can’t see your disk • Any local file: pass its path; Solr gets the bytes, the model one line • GitHub / S3 URL: the only route; fetched and streamed, allow-listed • GitHub / S3 URL: same tool, fetched and streamed to Solr • Local path: refused, with a pointer to the URL route October 11-14, 2026 Glasgow, Scotland
  16. INTERNALS img/spring-ai-logo.png Spring AI https://docs.spring.io/spring-ai/reference/api/effective-agents.html https://thenewstack.io/production-worthy-ai-with-spring-ai-1-0/ dependencies { // build.gradle.kts

    + libs.versions.toml implementation(libs.spring.ai.starter.mcp.server.webmvc) // Spring AI 2.0.1 implementation(libs.mcp.server.security) // org.springaicommunity 0.1.14 implementation(libs.spring.boot.starter.security) implementation(libs.spring.boot.starter.oauth2.resource.server) implementation(libs.spring.boot.starter.webmvc) // + actuator, aspectj, solr-solrj } dependencyManagement { mavenBom("org.springframework.ai:spring-ai-bom:2.0.1") } October 11-14, 2026 Glasgow, Scotland
  17. INTERNALS Spring AI MCP https://spring.io/blog/2025/09/16/spring-ai-mcp-intro-blog Annotated methods become MCP tools,

    resources, prompts, and completions. No hand-rolled JSON-RPC. @McpTool Expose a method as an MCP tool @McpResource Serve a URI (solr://{collection}/schema) @McpPrompt Register a reusable prompt template @McpComplete Bind to a URI template variable — prefixfilter suggestions @Service @Observed public class SearchService { @PreAuthorize("isAuthenticated()") @McpTool( name = "search", annotations = @McpTool.McpAnnotations(readOnlyHint = true), description = """ Search specified Solr collection with query, optional filters, facets, sorting, and pagination. ⋯ dynamic-field suffix legend + a worked example document ⋯""") public SearchResponse search( @McpToolParam(description = "Solr collection to query") String collection, @McpToolParam(description = "Solr q. Lucene syntax; {!edismax qf=…}", required = false) @Nullable String query, @McpToolParam(description = "Solr fq: one filter per entry", required = false) @Nullable List<String> filterQueries, @McpToolParam(description = "Solr facet fields", required = false) @Nullable List<String> facetFields, @McpToolParam(description = "Sort clauses applied in order", required = false) @Nullable List<SortClause> sortClauses, @McpToolParam(…) @Nullable Integer start, // pagination @McpToolParam(…) @Nullable Integer rows) throws SolrServerException, IOException { … } Schemas generated from method signatures • sync & async • STDIO / Streamable HTTP } search/SearchService.java on main — the tool schema is generated from this signature October 11-14, 2026 Glasgow, Scotland
  18. INTERNALS img/tc-logo.png Testcontainers testcontainers.com/modules/solr/ Industry-standard library. Any containerizable service. Multi-language

    (Java, Go, .NET, Python, Node). No mocks. REAL BEHAVIOR @TestConfiguration(proxyBeanMethods = false) class TestcontainersConfiguration { Query parser, analyzers, schema APIs — all real @Bean SolrContainer solr() { String img = System.getProperty( "solr.test.image", "solr:9.9-slim"); return new SolrContainer( DockerImageName.parse(img)); } VERSION MATRIX Tested: Solr 9.4 / 9.9 / 9.10 / 10 via -Dsolr.test.image @Bean DynamicPropertyRegistrar properties( SolrContainer solr) { return r -> r.add("solr.url", () -> "http://" + solr.getHost() + ":" + solr.getMappedPort(8983) + "/solr/"); } SPRING BOOT regular Spring bean MULTI-VERSION testcontainers.com/modules/solr/ } Swap Solr image via -Dsolr.test.image=solr:9.10-slim Maven coordinate: org.testcontainers:testcontainers-solr October 11-14, 2026 Glasgow, Scotland
  19. INTERNALS One test. Real Solr, real data. ConferenceEndToEndIntegrationTest boots Solr

    in Docker, indexes the DevNexus 2026 schedule, then asserts on what comes back. @SpringBootTest @Import(TestcontainersConfiguration.class) @Tag("integration") @Testcontainers(disabledWithoutDocker = true) @TestInstance(Lifecycle.PER_CLASS) @TestMethodOrder(OrderAnnotation.class) class ConferenceEndToEndIntegrationTest { WHAT IT ASSERTS — IN ORDER private static final String COLLECTION = "conferences"; private static final int TOTAL_SESSIONS = 116; @Autowired private CollectionService collectionService; @Autowired private IndexingService indexingService; @Autowired private SearchService searchService; @BeforeAll void createAndIndexConferences() throws Exception { var result = collectionService .createCollection(COLLECTION, null, null, null); assertTrue(result.success(), result.message()); var json = Files.readString( Path.of("mydata/devnexus-2026.json")); indexingService.indexJsonDocuments( COLLECTION, TestDocuments.json(json)); } 1 list-collections sees it contains("conferences") 2 health is green totalDocuments() == 116 3 search everything q=*:* → numFound == 116 4 filter query fq=track:Workshop → all workshops 5 keyword query q=title:Spring → all titles match 6 facets come back facet on id → ≥ 100 buckets 7 pagination is real rows=10 twice → new first id 8 stats agree with the index indexStats().numDocs() == 116 } src/test/java/org/apache/solr/mcp/server/collection/ConferenceEndToEndIntegrationTest.java October 11-14, 2026 Glasgow, Scotland
  20. TRANSPORT Two transports. One server. Same tools either way. The

    difference is who runs the server — and what that costs. Local — stdio · default Remote — Streamable HTTP · shared service HTTPS · OAuth 2.1 YOUR MACHINE Claude Desktop MCP client HOSTED Claude Desktop stdin / stdout child process Solr MCP SolrJ JAR · Docker Apache Solr Cursor Solr MCP SolrJ /mcp · :8080 Apache Solr Your agent docker run -i --rm ghcr.io/adityamparikh/solr-mcp:latest docker run -p 8080:8080 -e PROFILES=http ghcr.io/adityamparikh/solr-mcp:latest ADVANTAGES ADVANTAGES + Simple — the client launches it; nothing to deploy + Access to local files and programs — runs as the user + No hosting costs — runs on the laptop that’s already there + No OAuth layer — no port to reach; trust is your OS user account + Managed and maintained — one deployment, one upgrade + Authorization framework — OAuth 2.1, defined by the spec + Easy to set up — for users, it’s a URL + Scalable — stateless: any instance serves any request CHALLENGES CHALLENGES − Developer-focused setup — config plus Docker or a JAR, per machine − Scalability and resource constraints — one process per client − Maintenance and updates — every install upgrades on its own − Latency — a network hop on every tool call − Hosting — someone runs, pays for and secures it − Must be secured — anyone who can reach the port can send requests October 11-14, 2026 Glasgow, Scotland
  21. TRANSPORT + SECURITY Claude Desktop → Remote MCP Server (HTTP)

    The Bearer token rides on every request. The client — not the model — calls the server, and the server checks the token before any tool runs. User Claude Desktop Claude Model API Authorization server Solr MCP server Apache Solr MCP client · mcp-remote decides which tool Keycloak · Auth0 /mcp · resource server SolrCloud BEFORE THE SESSION · get a token, out of ba nd 1 token request, e.g. curl grant_type=client_credentials 2 access token (JWT) → mcp-remote --header aud = https://…/mcp CONNECT · discover tools 3 tools/list Authorization: Bearer <jwt> ✓ JWT: sig · iss · exp · aud — else 401 4 tool schemas EVERY QUESTION 5 question 6 prompt + tool schemas 7 tool_use: search 8 tools/call search Authorization: Bearer <jwt> ✓ JWT, then @PreAuthorize 9 SolrJ query /select 10 results 11 tool result 12 tool_result 13 final answer 14 response Shown with mcp-remote, which runs the MCP client on your machine. A custom connector runs it in Anthropic’s cloud: it needs a public HTTPS URL and a browser sign-in in place of steps 1–2. October 11-14, 2026 Glasgow, Scotland
  22. SPEC · 2026-07-28 MCP just went stateless. The 2026-07-28 revision

    turns MCP into request/response. Every request carries what the server needs to answer it. 2025-11-25 2026-07-28 Handshake initialize → initialized; capabilities come from its result None. Version and capabilities ride in every request’s _meta; server/discover on demand Sessions Mcp-Session-Id, sticky routing Removed. Any instance serves any request Elicitation Server → client. Server asks the user during a call, e.g. “delete this collection?” Kept, via MRTR: server returns input_required; client retries with the user’s answers Notifications GET stream, resources/subscribe subscriptions/listen — one opt-in POST stream Cross-call state Implicit, held in the session Explicit handles, passed back as tool arguments WHAT IT MEANS FOR SOLR MCP • Already stateless over HTTP: protocol=stateless (2025 spec); tools keep no session state. • Nothing to unwind: no sampling, roots, elicitation or log notifications. • On upgrade: Mcp-Method / Mcp-Name in CORS; confirm deletes via elicitation; Tasks for indexing. THE SPRING PATH Spring AI 2.0 MCP SDK 2.0 · spec 2025-11-25 · Boot 4.0 / 4.1 Spring AI 2.1.0-M1 25 Sep · Boot 4.2 · still SDK 2.0 · new spec in progress MCP Java SDK 2.2 Spec 2026-07-28 · in design · 5 of 23 issues closed Solr MCP main: Spring AI 1.1.7 · Boot 3.5 sb4: Spring AI 2.0.1 · Boot 4.1 DEPRECATED · still work until at least 2027-07-28 · also HTTP+SSE transport, and Dynamic Client Registration (→ CIMD) Sampling Server → client. Server borrows the client’s LLM to generate text Server calls an LLM provider API itself Roots Server → client. Server asks which folders / URIs it may work in Pass paths as tool arguments or server config Logging Server → client. Server streams log lines; client sets the level stderr (stdio) or OpenTelemetry Sources: MCP 2026-07-28 changelog · Spring AI 2.1.0-M1 release post (25 Sep 2026) · java-sdk milestone 2.2 · spring-ai#6954 October 11-14, 2026 Glasgow, Scotland
  23. SECURITY · OAUTH 2.1 OAuth 2.1 with spring-ai-community/mcp-security Three roles,

    one library module each. Solr MCP is the resource server: it checks tokens and never issues them. Authorization server 1 ask for a token Client issues tokens carries the token Keycloak · Auth0 mcp-remote · your agent 2 signed JWT Solr MCP 3 every request checks the token Bearer <JWT> resource server 4 fetch the public keys once SPRING-AI-COMMUNITY / MCP-SECURITY · ONE MODULE PER ROLE mcp-authorization-server mcp-client-security your own issuer — we use Keycloak / Auth0 Spring AI clients — we use mcp-remote THE JWT — SIGNED JSON ✓ used by Solr MCP SOLR MCP CHECKS EVERY TOKEN iss keycloak…/realms/solr ← who issued it aud solr-mcp…/mcp ← which server it’s for exp 14:00 ← when it expires October 11-14, 2026 mcp-server-security ✓ signature ✓ issuer ✓ expiry ✓ audience Any check fails → 401 Unauthorized Glasgow, Scotland
  24. SECURITY · SOLR MCP Inside Solr MCP: two checks before

    any tool runs Every tool call passes the token check, then the tool check. The code under each step is all the configuration there is. 401 Unauthorized 403 Forbidden missing, bad or expired token token valid, tool not allowed fail fail tools/call 1 Token check 2 Tool check search Apache Solr Bearer <JWT> signature · issuer · expiry · audience is the caller signed in? the tool runs /select ONE SETTING OAUTH2_ISSUER_URI points at Keycloak or Auth0 MCP-SERVER-SECURITY SPRING SECURITY SPRING AI SOLRJ McpServerOAuth2Configurer @PreAuthorize @McpTool Solr’s own auth still applies .authorizationServer(issuerUrl) ("isAuthenticated()") (name = "search") .resourcePath("/mcp") on all 15 tools .validateAudienceClaim(true) Tested with Keycloak and Auth0. Next: a scope per tool — hasAuthority('SCOPE_solr:write') October 11-14, 2026 Glasgow, Scotland
  25. SHIP & CONTRIBUTE / PACKAGING Ship it three ways Gradle-built.

    Spring Boot JAR. Jib-built Docker image. GraalVM native image opt-in. JAR DOCKER img/java-logo.png NATIVE img/docker-logo.png img/graalvm-logo.png Spring Boot fat JAR ▸ ▸ ▸ java -jar solr-mcp-*.jar Default STDIO mode for Claude Desktop ./gradlew bootRun for the dev loop GraalVM — opt-in ▸ ▸ ▸ ▸ openjdk.org October 11-14, 2026 openjdk.org ./gradlew jibDockerBuild Multi-arch: linux/amd64 + linux/arm64 Base: eclipse-temurin:25-jre Reproducible, small layered images docker.com docker.com ▸ ▸ ▸ ▸ ./gradlew bootBuildImage -Pnative Sub-second startup Lower memory footprint ./gradlew bootBuildImage -Pnative -Pprofile=http graalvm.org graalvm.org Glasgow, Scotland
  26. SHIP & CONTRIBUTE / TRY IT Five-minute quickstart Three steps

    from clone to conversation — or scan for the full hackathon guide. 1 Clone & start Solr git clone https://github.com/apache/solr-mcp.git cd solr-mcp && docker compose up -d 2 HACKATHON Hands-on guide Add to your Claude Desktop config "solr-mcp": { "command": "docker", "args": ["run","-i","--rm","ghcr.io/adityamparikh/solr-mcp:latest"], "env": { "SOLR_URL": "http://host.docker.internal:8983/solr/" } } 3 Restart Claude. Ask a question. “Show me 5 sci-fi films from the 90s.” October 11-14, 2026 adityamparikh.github.io/solr-mcp Connect a client, index data, design a schema, and run eight search scenarios — step by step. Glasgow, Scotland
  27. SHIP & CONTRIBUTE / BUILD ON IT Build your own

    client solr-mcp-client puts a REST API in front of an LLM wired to Solr MCP — your UI never embeds Spring AI, an MCP SDK, or model keys. github.com/adityamparikh/solr-mcp-client 1 POST /api/v1/chat Point it at a model and a Solr MCP server export OPENAI_API_KEY=sk-... export SOLR_MCP_JAR=/abs/path/solr-mcp.jar export SOLR_URL=http://localhost:8983/solr/ ./gradlew bootRun · POST /api/v1/stream · DELETE /api/v1/chat/{id} · GET /swagger-ui.html Your UI · curl · Swagger POST /api/v1/chat :9090 solr-mcp-client 2 Ask over HTTP — the conversation id rides in a header curl -si localhost:9090/api/v1/chat \ -H 'Content-Type: application/json' \ -H 'X-AI-Conversation-Id: user-7:session-4' \ -d '{"message":"How many workshop sessions are there?"}' SolrAssistant → Spring AI ChatClient → LLM Java 25 · Spring Boot 4.1 · Spring AI 2.0 MCP stdio | stdio-docker | http solr-mcp server 3 Swap the transport — or trade REST for a shell --spring.profiles.active=mcp-http --spring.profiles.active=mcp-stdio-docker --spring.profiles.active=cli,mcp-stdio October 11-14, 2026 SolrJ Apache Solr Repo Glasgow, Scotland
  28. Thank you Questions? LINKS CONTRIBUTE Repo github.com/apache/solr-mcp JIRA issues.apache.org/jira/browse/SOLR-17944 Apache

    Solr solr.apache.org Spring AI MCP spring.io/projects/spring-ai MCP Spec modelcontextprotocol.io Slack the-asf.slack.com October 11-14, 2026 Pick an issue github.com/apache/solr-mcp/issues Follow SOLR-17944 umbrella in ASF JIRA Sign the ICLA apache.org/licenses/contributor-agreements.html Good first areas more tools, vector search, per-tool authz, docs (#solr-dev) Glasgow, Scotland