This is an automated email from the ASF dual-hosted git repository.
epugh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-mcp.git
The following commit(s) were added to refs/heads/main by this push:
new 8c7df099 docs(events): point the Community over Code card at the
Spring Boot 4 build (#250)
8c7df099 is described below
commit 8c7df0996e4aa4dacef62cc4452331393084dffa
Author: Aditya Parikh <[email protected]>
AuthorDate: Mon Oct 26 15:42:35 2026 -0400
docs(events): point the Community over Code card at the Spring Boot 4 build
(#250)
* docs(events): point the Community over Code card at the Spring Boot 4
build
The coc2026 image, native images and JAR are now built from the Spring
Boot 4.1 / Spring AI 2.0 line (apache/solr-mcp#23), which carries
everything on main, so the card describes what that build does:
- Fifteen tools, with the three alias tools in the toolbox table.
- Step 3: CSV, XML and Markdown samples come from main's
src/test/resources. CSV and XML go to Solr's own handlers, which
report the payload accepted instead of a count. XML is Solr update
XML, so its field names match JSON and the show_ prefix notes go;
the Option B XML paste is converted to <add><doc> form. Markdown is
one multi-record file and one tool call; its description is in
content, which the step 6 note now says.
- Step 4: one outcome, an empty facet (#175 is in the image).
- Native Docker images are prebuilt for amd64 and arm64.
- Observability: OTLP/HTTP on 4318 with a URL per signal,
ClassName#method span names, timers in milliseconds, JVM metrics over
OTLP rather than /actuator/prometheus.
- Security: protected resource metadata for /mcp is served at the
RFC 9728 path-suffixed URL.
- Sizes (52 MB JAR, ~170 MB image) and the verified-against footer.
- Table cards: fifteen tools, and ChatGPT in the client list.
Every step was replayed against the published image for all four
formats, including the Option B pastes, the observability panel against
grafana/otel-lgtm 0.33.0, and the security panel against Keycloak.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): cover schema-aware assistants in step 4 and Markdown in
step 6
Running the card through Codex showed two places where an assistant
following it faithfully gets a different result from the one printed.
Step 4: an assistant that reads the schema first facets on platform_str,
the string copy schemaless mode makes of every text field, and gets real
buckets. The note now says so and gives the follow-up that shows the
empty facet on platform itself, which is still the lesson.
Step 6: Markdown documents keep the description in content, so "whose
description contains" finds nothing. The Markdown path now gets its own
prompt that names the content field; it returns the same two shows.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): say what a rejected bearer token looks like from the client
A token that reaches the server but fails validation (expired, or the
wrong aud) is now refused with HTTP 401 before the MCP session starts,
so the client shows the server's tools as missing rather than an Access
Denied result. Verified with Codex against Keycloak.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): set HTTP_SECURITY_ENABLED when building native http
Spring AOT fixes the security filter chain inside a native binary, so a
native http server ignores HTTP_SECURITY_ENABLED at run time and, with no
OAuth2 issuer, answers every tool call with Access Denied. The card's
native http build commands now set it for the build, and a note says
the switch only counts at build time and that the prebuilt
coc2026-native-http image is built with security off.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): filter the native builds panel by runtime and transport
The panel listed all four forms with stdio and http commands side by side.
It now follows the Run via and Transport choices from step 0, like the rest
of the page: JAR shows the JVM jar and the native binary, Docker shows the
Jib and native images, and each shows only the stdio or http commands. The
build-time security note appears only for http.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): bind the MCP server to localhost in every http command
The http commands published port 8080 on all interfaces, and the JAR and
native binary listen on all interfaces by default. With security switched
off for the hackathon, anyone on the same conference Wi-Fi could reach a
participant's MCP server and, through it, their Solr. The page already
said the insecure setup was "bound to localhost"; now the commands do it.
Docker publishes on 127.0.0.1 (-p 127.0.0.1:8080:8080). The JAR and the
native binary set SERVER_ADDRESS=127.0.0.1, in both shell and PowerShell
forms, including the secured Keycloak and Auth0 walkthroughs. Clients,
the ngrok tunnel and mcp-remote all connect via localhost, so nothing
else changes.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): keep Solr, Grafana and Keycloak off the conference network
Solr was published on every interface with no authentication, so anyone
on the same Wi-Fi could read or delete a participant's collections. LGTM
(Grafana, OTLP) and the Keycloak walkthrough, which uses admin/admin, had
the same exposure.
Each is now published on 127.0.0.1 only. The MCP server's container used
to reach Solr and LGTM through the host (host.docker.internal), which a
loopback-only port breaks on Linux. Step 1 therefore creates a solr-mcp
Docker network: Solr and LGTM join it, every Docker command and client
config replaces --add-host with --network=solr-mcp, and SOLR_URL and the
OTLP URLs use container names. JAR users still use localhost unchanged.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
* docs(events): bring the card's client setup up to date
- ChatGPT: add the server through "Add custom MCP server" and create it
as a plugin; the developer-mode app flow is gone.
- MCP Inspector 2.x takes one argument per line in the Arguments field;
a single pasted line reaches docker as one argument and fails with
"unknown shorthand flag". Its Environment field configures the docker
client, not the container.
- JetBrains AI Assistant: configure through Settings | Tools | AI
Assistant | Model Context Protocol (MCP); .junie/mcp/mcp.json is
Junie's file.
- Claude Desktop is now an official beta on Ubuntu and Debian.
- Zed schema re-verified on 1.23.2.
- LGTM: publish only the OTLP/HTTP port the server exports to.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: Aditya Parikh <[email protected]>
---------
Signed-off-by: Aditya Parikh <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
docs/events/coc2026-glasgow/site/index.html | 1134 +++++++++++---------
docs/events/coc2026-glasgow/site/slides.html | 13 +-
docs/events/coc2026-glasgow/site/table-card.html | 4 +-
.../coc2026-glasgow/solr-mcp-table-card.html | 4 +-
4 files changed, 610 insertions(+), 545 deletions(-)
diff --git a/docs/events/coc2026-glasgow/site/index.html
b/docs/events/coc2026-glasgow/site/index.html
index d7e905df..3e602fd7 100644
--- a/docs/events/coc2026-glasgow/site/index.html
+++ b/docs/events/coc2026-glasgow/site/index.html
@@ -530,8 +530,8 @@ details.panel > summary .hint {
</div>
<h1>Talk to <em>Apache Solr</em> in plain English.</h1>
<p class="standfirst">
- Solr MCP is a Model Context Protocol server that hands your AI assistant
twelve Solr
- tools — search, indexing, schema and collection management. This card
takes you from
+ Solr MCP is a Model Context Protocol server that hands your AI assistant
fifteen Solr
+ tools — search, indexing, schema, collection and alias management. This
card takes you from
nothing installed to running faceted queries against a real index. Ten
minutes, no
Solr syntax required.
</p>
@@ -539,7 +539,7 @@ details.panel > summary .hint {
<span><b>Time</b> ~10 min</span>
<span><b>Needs</b> Docker, or Java 25</span>
<span><b>Dataset</b> 61 streaming shows</span>
- <span><b>Tools</b> 12 · 2 resources · 6 prompts</span>
+ <span><b>Tools</b> 15 · 2 resources · 6 prompts</span>
</div>
<div class="share">
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iOTAwIiBjbGFzcz0ic2Vnbm8iPjxnIHRyYW5zZm9ybT0ic2NhbGUoMjApIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDQ1djQ1aC00NXoiLz48cGF0aCBjbGFzcz0icXJsaW5lIiBzdHJva2U9IiMxNTE3MWEiIGQ9Ik00IDQuNWg3bTMgMGgybTEgMGgxbTEgMGgxbTMgMGgybTIgMGgxbTIgMGgxbTMgMGg3bS0zNyAxaDFtNSAwaDFtMSAwaDJtMiAwaDFtMiAwaDFtMiAwaDFtMiAwaDFtMSAwaDFtMSAwaDJtMyAwaDFtNSAw
[...]
@@ -656,7 +656,7 @@ details.panel > summary .hint {
<h3>Get the JAR</h3>
<p>
- Prebuilt, so you don't need Git or Gradle — 53 MB:
+ Prebuilt, so you don't need Git or Gradle — 52 MB:
</p>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -LO
https://github.com/adityamparikh/solr-mcp/releases/download/coc2026/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
@@ -694,13 +694,17 @@ sdk install java 25-tem</code></pre></div>
</div>
<p>
SolrCloud mode with embedded ZooKeeper, which is what the collection
tools need.
- Ready in about seven seconds.
+ Ready in about seven seconds. The first line creates a private Docker
network: the server's
+ container joins it later and reaches Solr by its name, <code
class="inline">solr-mcp-demo</code>.
+ Solr's port is published on <code class="inline">127.0.0.1</code> only,
so it answers on
+ your laptop and nobody else on the conference Wi-Fi can reach it.
</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker run -d --name solr-mcp-demo -p
8983:8983 solr:9-slim solr start -c -f</code></pre></div>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker network create solr-mcp
+docker run -d --name solr-mcp-demo --network=solr-mcp -p 127.0.0.1:8983:8983
solr:9-slim solr start -c -f</code></pre></div>
<p data-runtime="docker">
- While that boots, pull the server image too. It is ~155 MB, and several
clients time out
+ While that boots, pull the server image too. It is ~170 MB, and several
clients time out
a first connection at 60 seconds — long enough to look like a broken
config when it is
really just a download:
</p>
@@ -773,16 +777,17 @@ sdk install java 25-tem</code></pre></div>
In HTTP mode the server is a process you start yourself, in a terminal
you keep open.
Every client then connects to <code
class="inline">http://localhost:8080/mcp</code>.
</p>
- <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 8080:8080 --rm \
- --add-host=host.docker.internal:host-gateway \
+ <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 127.0.0.1:8080:8080 --rm \
+ --network=solr-mcp \
-e PROFILES=http \
-e HTTP_SECURITY_ENABLED=false \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
- <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
HTTP_SECURITY_ENABLED=false SOLR_URL=http://localhost:8983/solr/ \
+ <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
SERVER_ADDRESS=127.0.0.1 HTTP_SECURITY_ENABLED=false \
+ SOLR_URL=http://localhost:8983/solr/ \
java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="codeblock" data-runtime="jar" data-os="windows"><button
class="copy" type="button">Copy</button><pre><code><span class="tok-c">#
PowerShell</span>
-$env:PROFILES="http"; $env:HTTP_SECURITY_ENABLED="false";
$env:SOLR_URL="http://localhost:8983/solr/"
+$env:PROFILES="http"; $env:SERVER_ADDRESS="127.0.0.1";
$env:HTTP_SECURITY_ENABLED="false"; $env:SOLR_URL="http://localhost:8983/solr/"
java -jar C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
Ready when <code class="inline">curl
http://localhost:8080/actuator/health</code> answers
@@ -795,7 +800,10 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
HTTP mode requires OAuth2 out of the box (<code
class="inline">HTTP_SECURITY_ENABLED</code>
defaults to <b>true</b>, the issuer is <code
class="inline">OAUTH2_ISSUER_URI</code>).
<code class="inline">HTTP_SECURITY_ENABLED=false</code> is for a
laptop at a hackathon,
- bound to localhost. Never run it that way on anything other people
can reach; the
+ bound to localhost: the commands above listen on <code
class="inline">127.0.0.1</code>
+ only (<code class="inline">-p 127.0.0.1:8080:8080</code> for Docker,
+ <code class="inline">SERVER_ADDRESS</code> for the JAR), so nobody
else on the
+ conference Wi-Fi can reach it. Never run it that way on anything
other people can reach; the
<a href="#secured">Security setup</a> panel below walks through
turning it on, start to finish.
</p>
</div>
@@ -807,8 +815,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<h3>Claude Code</h3>
<div data-transport="stdio">
<div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>claude mcp add solr-mcp -- docker run -i
--rm \
- --add-host=host.docker.internal:host-gateway \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
<div class="codeblock" data-runtime="jar"><button class="copy"
type="button">Copy</button><pre><code>claude mcp add solr-mcp \
-e SOLR_URL=http://localhost:8983/solr/ \
@@ -832,8 +840,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<h3>Codex</h3>
<div data-transport="stdio">
<div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>codex mcp add solr-mcp -- docker run -i
--rm \
- --add-host=host.docker.internal:host-gateway \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
<div class="codeblock" data-runtime="jar"><button class="copy"
type="button">Copy</button><pre><code>codex mcp add solr-mcp \
--env SOLR_URL=http://localhost:8983/solr/ \
@@ -856,8 +864,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div data-transport="http">
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>codex mcp add solr-mcp --url
http://localhost:8080/mcp</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
- Codex prints <q>may or may not require login</q> — ignore it, there is
no login on an
- unsecured server. Verify with <code class="inline">codex mcp
list</code>; the server must
+ No login is needed on an unsecured server; if your Codex version prints
+ <q>may or may not require login</q>, ignore it. Verify with <code
class="inline">codex mcp list</code>; the server must
already be running when Codex starts.
</p>
</div>
@@ -887,10 +895,10 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
</p>
</div>
<ol style="font-size:.92rem;color:var(--ink-2);line-height:1.6">
- <li><b>Settings → Security and login</b>: turn on <b>Developer
mode</b> (Pro, Plus, Business, Enterprise, Education; workspace admins may need
to allow it).</li>
- <li>Open <b>ChatGPT Plugins</b>, press <b>+</b>, and create a
developer-mode app.</li>
- <li>Name it <code class="inline">solr-mcp</code>; under
<b>Connection</b> enter <code
class="inline">https://<your-tunnel>/mcp</code>; choose <b>No
authentication</b>.</li>
- <li>Create it and check the discovered tools — there should be
twelve. Enable the app in a chat.</li>
+ <li>On the web, open <b>ChatGPT Plugins</b>, press <b>+</b>, then
<b>Add custom MCP server</b>. In a workspace, an admin may need to allow custom
MCP servers.</li>
+ <li>Name it <code class="inline">solr-mcp</code>; under
<b>Connection</b> enter the Server URL <code
class="inline">https://<your-tunnel>/mcp</code>; choose <b>No
authentication</b>.</li>
+ <li>Select <b>I understand and want to continue</b>, then <b>Create
as a plugin</b>.</li>
+ <li>Install the plugin, then use it in a chat. It should expose
fifteen tools.</li>
</ol>
<p style="font-size:.86rem;color:var(--ink-2)">
ChatGPT asks before running tools it treats as writes, which is most
of them. After
@@ -903,7 +911,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div data-client="claude-desktop">
<h3>Claude Desktop</h3>
<div data-transport="stdio">
- <p>Edit the config file, then <b>fully quit and reopen</b> Claude
Desktop:</p>
+ <p>Edit the config file (<b>Settings → Developer → Edit Config</b> opens
it), then
+ <b>fully quit and reopen</b> Claude Desktop:</p>
<div class="codeblock" data-os="macos"><button class="copy"
type="button">Copy</button><pre><code>~/Library/Application
Support/Claude/claude_desktop_config.json</code></pre></div>
<div class="codeblock" data-os="windows wsl"><button class="copy"
type="button">Copy</button><pre><code>%APPDATA%\Claude\claude_desktop_config.json</code></pre></div>
<div class="codeblock" data-os="linux"><button class="copy"
type="button">Copy</button><pre><code>~/.config/Claude/claude_desktop_config.json</code></pre></div>
@@ -917,9 +926,10 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="note warn" data-os="linux">
<span class="tag">On Linux</span>
<p>
- There is no official Claude Desktop build for Linux. That path is
where community
- builds look; if you're on Linux, <b>Claude Code</b> or <b>MCP
Inspector</b> is the
- smoother route.
+ Claude Desktop for Linux is an official beta for Ubuntu 22.04+ and
Debian 12+. Anthropic
+ doesn't document its config path; if the file above has no effect,
open the one the
+ app reads from <b>Settings → Developer → Edit Config</b>. <b>Claude
Code</b> or
+ <b>MCP Inspector</b> is the smoother route on Linux.
</p>
</div>
@@ -928,8 +938,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<span class="tok-s">"solr-mcp"</span>: {
<span class="tok-s">"command"</span>: <span
class="tok-s">"docker"</span>,
<span class="tok-s">"args"</span>: [<span class="tok-s">"run"</span>,
<span class="tok-s">"-i"</span>, <span class="tok-s">"--rm"</span>,
- <span
class="tok-s">"--add-host=host.docker.internal:host-gateway"</span>,
- <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://host.docker.internal:8983/solr/"</span>,
+ <span class="tok-s">"--network=solr-mcp"</span>,
+ <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://solr-mcp-demo:8983/solr/"</span>,
<span
class="tok-s">"ghcr.io/adityamparikh/solr-mcp:coc2026"</span>]
}
}
@@ -982,8 +992,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<span class="tok-s">"type"</span>: <span class="tok-s">"stdio"</span>,
<span class="tok-s">"command"</span>: <span
class="tok-s">"docker"</span>,
<span class="tok-s">"args"</span>: [<span class="tok-s">"run"</span>,
<span class="tok-s">"-i"</span>, <span class="tok-s">"--rm"</span>,
- <span
class="tok-s">"--add-host=host.docker.internal:host-gateway"</span>,
- <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://host.docker.internal:8983/solr/"</span>,
+ <span class="tok-s">"--network=solr-mcp"</span>,
+ <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://solr-mcp-demo:8983/solr/"</span>,
<span
class="tok-s">"ghcr.io/adityamparikh/solr-mcp:coc2026"</span>]
}
}
@@ -1022,8 +1032,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<span class="tok-s">"solr-mcp"</span>: {
<span class="tok-s">"command"</span>: <span
class="tok-s">"docker"</span>,
<span class="tok-s">"args"</span>: [<span class="tok-s">"run"</span>,
<span class="tok-s">"-i"</span>, <span class="tok-s">"--rm"</span>,
- <span
class="tok-s">"--add-host=host.docker.internal:host-gateway"</span>,
- <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://host.docker.internal:8983/solr/"</span>,
+ <span class="tok-s">"--network=solr-mcp"</span>,
+ <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://solr-mcp-demo:8983/solr/"</span>,
<span
class="tok-s">"ghcr.io/adityamparikh/solr-mcp:coc2026"</span>]
}
}
@@ -1054,7 +1064,7 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div data-transport="stdio">
<p>
Zed has a form for this, which is the easier route here — no JSON, and
it validates as
- you type. <b>Settings → AI → General → MCP Servers → Add Server → Add
Local MCP
+ you type. <b>Settings → AI → General → MCP Servers → Add Server → Add
Local
Server</b>, then:
</p>
<div class="tablewrap" data-runtime="docker">
@@ -1062,7 +1072,7 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<tbody>
<tr><th>Server Name</th><td><code>solr-mcp</code></td></tr>
<tr><th>Command</th><td><code>docker</code></td></tr>
- <tr><th>Arguments</th><td><code>run -i --rm
--add-host=host.docker.internal:host-gateway -e
SOLR_URL=http://host.docker.internal:8983/solr/
ghcr.io/adityamparikh/solr-mcp:coc2026</code></td></tr>
+ <tr><th>Arguments</th><td><code>run -i --rm --network=solr-mcp -e
SOLR_URL=http://solr-mcp-demo:8983/solr/
ghcr.io/adityamparikh/solr-mcp:coc2026</code></td></tr>
<tr><th>Timeout</th><td>60 is fine <em>once the image is
pulled</em> — see below</td></tr>
</tbody>
</table>
@@ -1084,7 +1094,7 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="note warn" data-runtime="docker">
<span class="tag">Pull the image first</span>
<p>
- Zed's default timeout is <b>60 seconds</b>, and a first run has to
fetch ~155 MB. On
+ Zed's default timeout is <b>60 seconds</b>, and a first run has to
fetch ~170 MB. On
venue wifi that can outrun the timeout, and the failure looks like a
broken config
rather than a slow download. Run
<code class="inline">docker pull
ghcr.io/adityamparikh/solr-mcp:coc2026</code> once
@@ -1100,8 +1110,8 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<span class="tok-s">"solr-mcp"</span>: {
<span class="tok-s">"command"</span>: <span
class="tok-s">"docker"</span>,
<span class="tok-s">"args"</span>: [<span class="tok-s">"run"</span>,
<span class="tok-s">"-i"</span>, <span class="tok-s">"--rm"</span>,
- <span
class="tok-s">"--add-host=host.docker.internal:host-gateway"</span>,
- <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://host.docker.internal:8983/solr/"</span>,
+ <span class="tok-s">"--network=solr-mcp"</span>,
+ <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://solr-mcp-demo:8983/solr/"</span>,
<span
class="tok-s">"ghcr.io/adityamparikh/solr-mcp:coc2026"</span>],
<span class="tok-s">"env"</span>: {}
}
@@ -1117,9 +1127,9 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
}
}</code></pre></div>
<div class="note good">
- <span class="tag">Zed schema — verified 1.16.2</span>
+ <span class="tag">Zed schema — verified 1.23.2</span>
<p>
- Verified against Zed <b>1.16.2</b>. Zed's schema takes <code
class="inline">command</code>
+ Verified against Zed <b>1.23.2</b>. Zed's schema takes <code
class="inline">command</code>
as a plain string with <code class="inline">args</code> and
<code class="inline">env</code> alongside it — there is no
<code class="inline">source</code> key, and adding one makes Zed's
settings
@@ -1151,15 +1161,16 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div data-client="intellij">
<h3>IntelliJ IDEA / JetBrains</h3>
<div data-transport="stdio">
- <p>Needs the AI Assistant plugin. Either drop a file at
- <code class="inline">.junie/mcp/mcp.json</code> in your project
root:</p>
+ <p>Needs the AI Assistant plugin. Open <b>Settings | Tools | AI
Assistant | Model Context
+ Protocol (MCP)</b>, click <b>Add</b>, choose <b>STDIO</b> in the
<b>New MCP Server</b> dialog,
+ and paste:</p>
<div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>{
<span class="tok-s">"mcpServers"</span>: {
<span class="tok-s">"solr-mcp"</span>: {
<span class="tok-s">"command"</span>: <span
class="tok-s">"docker"</span>,
<span class="tok-s">"args"</span>: [<span class="tok-s">"run"</span>,
<span class="tok-s">"-i"</span>, <span class="tok-s">"--rm"</span>,
- <span
class="tok-s">"--add-host=host.docker.internal:host-gateway"</span>,
- <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://host.docker.internal:8983/solr/"</span>,
+ <span class="tok-s">"--network=solr-mcp"</span>,
+ <span class="tok-s">"-e"</span>, <span
class="tok-s">"SOLR_URL=http://solr-mcp-demo:8983/solr/"</span>,
<span
class="tok-s">"ghcr.io/adityamparikh/solr-mcp:coc2026"</span>]
}
}
@@ -1174,20 +1185,18 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
}
}</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
- …or add it through <b>Settings → Tools → AI Assistant → MCP Servers →
Add</b>,
- transport <b>STDIO</b>.
+ Using Junie, JetBrains' coding agent, instead? It reads the same JSON
from
+ <code class="inline">.junie/mcp/mcp.json</code> in your project root.
</p>
</div>
<div data-transport="http">
- <p>Same file, <code class="inline">.junie/mcp/mcp.json</code>, with a
URL instead of a command:</p>
+ <p>Same dialog — <b>Settings | Tools | AI Assistant | Model Context
Protocol (MCP)</b> →
+ <b>Add</b> — but choose <b>Streamable HTTP</b> and paste a URL instead
of a command:</p>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>{
<span class="tok-s">"mcpServers"</span>: {
<span class="tok-s">"solr-mcp"</span>: { <span class="tok-s">"url"</span>:
<span class="tok-s">"http://localhost:8080/mcp"</span> }
}
}</code></pre></div>
- <p style="font-size:.86rem;color:var(--ink-2)">
- …or <b>Settings → Tools → AI Assistant → MCP Servers → Add</b>,
transport <b>HTTP</b>.
- </p>
</div>
</div>
@@ -1200,19 +1209,35 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<em>see</em> what MCP actually is, and the fastest way to prove the
server works.
</p>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>npx
@modelcontextprotocol/inspector</code></pre></div>
- <p>Opens at <code class="inline">http://localhost:6274</code>. Choose
<b>STDIO</b>, then:</p>
- <div class="tablewrap">
- <table>
- <tbody>
- <tr
data-runtime="docker"><th>Command</th><td><code>docker</code></td></tr>
- <tr data-runtime="docker"><th>Arguments</th><td><code>run -i --rm
--add-host=host.docker.internal:host-gateway -e
SOLR_URL=http://host.docker.internal:8983/solr/
ghcr.io/adityamparikh/solr-mcp:coc2026</code></td></tr>
- <tr
data-runtime="jar"><th>Command</th><td><code>java</code></td></tr>
- <tr data-runtime="jar"><th>Arguments</th><td><code>-jar
/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></td></tr>
- </tbody>
- </table>
- </div>
<p>
- Hit <b>Connect</b>, then <b>List Tools</b>. You should see twelve.
Click
+ Opens at <code class="inline">http://localhost:6274</code>. Add a
server, choose
+ <b>stdio</b>, set <b>Command</b> to
+ <code class="inline" data-runtime="docker">docker</code><code
class="inline" data-runtime="jar">java</code>,
+ and paste this into <b>Arguments</b>. That field takes <b>one argument
per line</b>:
+ pasted as one line, the whole string reaches
+ <span data-runtime="docker">docker as a single argument and it fails
with
+ <code class="inline">unknown shorthand flag</code>.</span><span
data-runtime="jar">java
+ as a single argument.</span>
+ </p>
+ <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>run
+-i
+--rm
+--network=solr-mcp
+-e
+SOLR_URL=http://solr-mcp-demo:8983/solr/
+ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
+ <div class="codeblock" data-runtime="jar"><button class="copy"
type="button">Copy</button><pre><code>-jar
+/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
+ <p style="font-size:.86rem;color:var(--ink-2)">
+ Leave the <b>Environment</b> field empty — it sets variables for the
+ <span data-runtime="docker"><code class="inline">docker</code> client,
not the container,
+ which is why <code class="inline">SOLR_URL</code> goes in as
+ <code class="inline">-e</code>.</span><span
data-runtime="jar">launcher; the jar's
+ default <code class="inline">SOLR_URL</code> already points at
+ <code class="inline">localhost:8983</code>.</span>
+ </p>
+ <p>
+ Hit <b>Connect</b>, then <b>List Tools</b>. You should see fifteen.
Click
<code class="inline">list-collections</code> and run it — that
round-trip is the whole
protocol in one click.
</p>
@@ -1287,54 +1312,48 @@ java -jar
C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
</div>
</div>
<div data-format="csv">
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -O
https://raw.githubusercontent.com/adityamparikh/solr-mcp/feat/shows-sample-formats/src/test/resources/shows.csv</code></pre></div>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -O
https://raw.githubusercontent.com/apache/solr-mcp/main/src/test/resources/shows.csv</code></pre></div>
<div class="prompts">
<div class="prompt">
- <q>Index the contents of ./shows.csv into the shows-auto
collection.<span class="why">calls <b>index-csv-documents</b> — expect 61 of
61</span></q>
+ <q>Index the contents of ./shows.csv into the shows-auto
collection.<span class="why">calls <b>index-csv-documents</b> — Solr accepts
the payload; the collection then holds 61</span></q>
<button class="copy-sm" type="button" data-copy="Index the
contents of ./shows.csv into the shows-auto collection.">Copy</button>
</div>
</div>
<p style="font-size:.86rem;color:var(--ink-2)">
- Multi-valued fields (<code class="inline">genres</code>, <code
class="inline">cast</code>…)
- are repeated column headers; every non-empty cell becomes one
value. Numbers arrive as
- text and Solr's parsers still guess numeric types, so the next
step plays out the same.
+ The server hands the file to Solr's own CSV handler, which reports
that it accepted the
+ payload rather than a document count. Multi-valued fields (<code
class="inline">genres</code>,
+ <code class="inline">cast</code>…) are repeated column headers;
every non-empty cell becomes
+ one value. Numbers arrive as text and Solr's parsers still guess
numeric types, so the next
+ step plays out the same.
</p>
</div>
<div data-format="xml">
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -O
https://raw.githubusercontent.com/adityamparikh/solr-mcp/feat/shows-sample-formats/src/test/resources/shows.xml</code></pre></div>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -O
https://raw.githubusercontent.com/apache/solr-mcp/main/src/test/resources/shows.xml</code></pre></div>
<div class="prompts">
<div class="prompt">
- <q>Index the contents of ./shows.xml into the shows-auto
collection.<span class="why">calls <b>index-xml-documents</b> — expect 61 of
61</span></q>
+ <q>Index the contents of ./shows.xml into the shows-auto
collection.<span class="why">calls <b>index-xml-documents</b> — Solr accepts
the payload; the collection then holds 61</span></q>
<button class="copy-sm" type="button" data-copy="Index the
contents of ./shows.xml into the shows-auto collection.">Copy</button>
</div>
</div>
- <div class="note warn">
- <span class="tag">XML field names differ</span>
- <p>
- The XML tool flattens nested elements by path, so every field
lands prefixed with the
- record element: <code class="inline">show_platform</code>,
- <code class="inline">show_imdb_rating</code>, and the show's
- <code class="inline">id</code> becomes <code
class="inline">show_id</code> while Solr
- assigns its own <code class="inline">id</code>. Later prompts on
this card say
- <code class="inline">platform</code>; with XML, say
- <code class="inline">show_platform</code>, or pick another
format for steps 4–7.
- </p>
- </div>
+ <p style="font-size:.86rem;color:var(--ink-2)">
+ The file is Solr's own update format — <code
class="inline"><add><doc><field name="…"></code>.
+ The server checks that it is an <code
class="inline"><add></code> block (no deletes, no
+ commits) and passes it to Solr unchanged, so the field names are
the same as in JSON.
+ </p>
</div>
<div data-format="markdown">
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -L
https://github.com/adityamparikh/solr-mcp/archive/refs/heads/feat/shows-sample-formats.tar.gz
\
- | tar xz --strip-components=4
'solr-mcp-feat-shows-sample-formats/src/test/resources/shows-markdown'</code></pre></div>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -O
https://raw.githubusercontent.com/apache/solr-mcp/main/src/test/resources/shows-markdown.md</code></pre></div>
<div class="prompts">
<div class="prompt">
- <q>Index every file in ./shows-markdown into the shows-auto
collection, one document per file.<span class="why">calls
<b>index-markdown-documents</b> 61 times — one document per Markdown
file</span></q>
- <button class="copy-sm" type="button" data-copy="Index every file
in ./shows-markdown into the shows-auto collection, one document per
file.">Copy</button>
+ <q>Index the contents of ./shows-markdown.md into the shows-auto
collection.<span class="why">calls <b>index-markdown-documents</b> once —
expect 61 of 61</span></q>
+ <button class="copy-sm" type="button" data-copy="Index the
contents of ./shows-markdown.md into the shows-auto collection.">Copy</button>
</div>
</div>
<p style="font-size:.86rem;color:var(--ink-2)">
- One Markdown document is one Solr document: the fields live in
YAML front matter and
- the description is the body, which also lands as <code
class="inline">content</code>
- with the title in <code class="inline">headings</code>. Sixty-one
files means sixty-one
- tool calls; watch the assistant work through them.
+ The file holds 61 Markdown documents, each opening with its own
YAML front matter, and
+ the server splits it into one Solr document per show. The fields
live in the front
+ matter; the description is the body, which lands in <code
class="inline">content</code>,
+ with the title in <code class="inline">headings</code>.
</p>
</div>
</div>
@@ -1383,330 +1402,330 @@
netflix-004,Wednesday,Netflix,Comedy,Horror,Mystery,2022,,Ongoing,2,16,Alfred Go
</div>
<div data-format="xml">
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>Index this XML into the shows-auto
collection:
-<shows>
- <show>
- <id>hbo-001</id>
- <title>Game of Thrones</title>
- <platform>HBO Max</platform>
- <genres>Fantasy</genres>
- <genres>Drama</genres>
- <genres>Adventure</genres>
- <release_year>2011</release_year>
- <end_year>2019</end_year>
- <status>Ended</status>
- <seasons>8</seasons>
- <episodes>73</episodes>
- <creators>David Benioff</creators>
- <creators>D.B. Weiss</creators>
- <cast>Emilia Clarke</cast>
- <cast>Peter Dinklage</cast>
- <cast>Kit Harington</cast>
- <cast>Lena Headey</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>9.2</imdb_rating>
- <description>Nine noble families fight for control over the lands of
Westeros, while an ancient enemy returns after being dormant for
millennia.</description>
- <tags>fantasy</tags>
- <tags>dragons</tags>
- <tags>epic</tags>
- <tags>george-rr-martin</tags>
- </show>
- <show>
- <id>netflix-001</id>
- <title>Stranger Things</title>
- <platform>Netflix</platform>
- <genres>Sci-Fi</genres>
- <genres>Horror</genres>
- <genres>Drama</genres>
- <release_year>2016</release_year>
- <end_year>2025</end_year>
- <status>Ended</status>
- <seasons>5</seasons>
- <episodes>42</episodes>
- <creators>Matt Duffer</creators>
- <creators>Ross Duffer</creators>
- <cast>Millie Bobby Brown</cast>
- <cast>Finn Wolfhard</cast>
- <cast>Winona Ryder</cast>
- <cast>David Harbour</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-14</rating>
- <imdb_rating>8.7</imdb_rating>
- <description>A group of kids in 1980s Indiana uncover supernatural
mysteries and government conspiracies tied to a parallel
dimension.</description>
- <tags>80s</tags>
- <tags>supernatural</tags>
- <tags>coming-of-age</tags>
- <tags>monsters</tags>
- </show>
- <show>
- <id>hulu-001</id>
- <title>The Handmaid's Tale</title>
- <platform>Hulu</platform>
- <genres>Drama</genres>
- <genres>Sci-Fi</genres>
- <genres>Dystopian</genres>
- <release_year>2017</release_year>
- <end_year>2025</end_year>
- <status>Ended</status>
- <seasons>6</seasons>
- <episodes>66</episodes>
- <creators>Bruce Miller</creators>
- <cast>Elisabeth Moss</cast>
- <cast>Joseph Fiennes</cast>
- <cast>Yvonne Strahovski</cast>
- <cast>Samira Wiley</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.4</imdb_rating>
- <description>Set in a dystopian future, a woman is forced to live as
a concubine under a fundamentalist theocratic dictatorship.</description>
- <tags>dystopian</tags>
- <tags>feminist</tags>
- <tags>atwood</tags>
- <tags>theocracy</tags>
- </show>
- <show>
- <id>disney-001</id>
- <title>The Mandalorian</title>
- <platform>Disney+</platform>
- <genres>Sci-Fi</genres>
- <genres>Action</genres>
- <genres>Adventure</genres>
- <release_year>2019</release_year>
- <status>Ongoing</status>
- <seasons>3</seasons>
- <episodes>24</episodes>
- <creators>Jon Favreau</creators>
- <cast>Pedro Pascal</cast>
- <cast>Carl Weathers</cast>
- <cast>Giancarlo Esposito</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-14</rating>
- <imdb_rating>8.6</imdb_rating>
- <description>The travels of a lone bounty hunter in the outer
reaches of the galaxy, far from the authority of the New
Republic.</description>
- <tags>star-wars</tags>
- <tags>space-western</tags>
- <tags>grogu</tags>
- <tags>baby-yoda</tags>
- </show>
- <show>
- <id>hbo-002</id>
- <title>Succession</title>
- <platform>HBO Max</platform>
- <genres>Drama</genres>
- <genres>Comedy</genres>
- <release_year>2018</release_year>
- <end_year>2023</end_year>
- <status>Ended</status>
- <seasons>4</seasons>
- <episodes>39</episodes>
- <creators>Jesse Armstrong</creators>
- <cast>Brian Cox</cast>
- <cast>Jeremy Strong</cast>
- <cast>Kieran Culkin</cast>
- <cast>Sarah Snook</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.9</imdb_rating>
- <description>The Roy family controls the biggest media and
entertainment company in the world, but their patriarch's health is
failing.</description>
- <tags>media</tags>
- <tags>family-drama</tags>
- <tags>satire</tags>
- <tags>wealth</tags>
- </show>
- <show>
- <id>prime-001</id>
- <title>The Boys</title>
- <platform>Amazon Prime Video</platform>
- <genres>Action</genres>
- <genres>Sci-Fi</genres>
- <genres>Drama</genres>
- <release_year>2019</release_year>
- <status>Ongoing</status>
- <seasons>4</seasons>
- <episodes>32</episodes>
- <creators>Eric Kripke</creators>
- <cast>Karl Urban</cast>
- <cast>Jack Quaid</cast>
- <cast>Antony Starr</cast>
- <cast>Erin Moriarty</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.7</imdb_rating>
- <description>A group of vigilantes set out to take down corrupt
superheroes who abuse their powers.</description>
- <tags>superheroes</tags>
- <tags>satire</tags>
- <tags>violent</tags>
- <tags>comic-adaptation</tags>
- </show>
- <show>
- <id>netflix-002</id>
- <title>The Crown</title>
- <platform>Netflix</platform>
- <genres>Drama</genres>
- <genres>Historical</genres>
- <genres>Biography</genres>
- <release_year>2016</release_year>
- <end_year>2023</end_year>
- <status>Ended</status>
- <seasons>6</seasons>
- <episodes>60</episodes>
- <creators>Peter Morgan</creators>
- <cast>Claire Foy</cast>
- <cast>Olivia Colman</cast>
- <cast>Imelda Staunton</cast>
- <cast>Matt Smith</cast>
- <country>UK</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.6</imdb_rating>
- <description>The reign of Queen Elizabeth II from her wedding in
1947 through the early 21st century.</description>
- <tags>royalty</tags>
- <tags>british</tags>
- <tags>period-drama</tags>
- <tags>politics</tags>
- </show>
- <show>
- <id>prime-002</id>
- <title>The Marvelous Mrs. Maisel</title>
- <platform>Amazon Prime Video</platform>
- <genres>Comedy</genres>
- <genres>Drama</genres>
- <genres>Period</genres>
- <release_year>2017</release_year>
- <end_year>2023</end_year>
- <status>Ended</status>
- <seasons>5</seasons>
- <episodes>43</episodes>
- <creators>Amy Sherman-Palladino</creators>
- <cast>Rachel Brosnahan</cast>
- <cast>Alex Borstein</cast>
- <cast>Michael Zegen</cast>
- <cast>Tony Shalhoub</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.7</imdb_rating>
- <description>A 1950s New York housewife discovers she has a talent
for stand-up comedy.</description>
- <tags>50s</tags>
- <tags>stand-up</tags>
- <tags>feminist</tags>
- <tags>new-york</tags>
- </show>
- <show>
- <id>hbo-003</id>
- <title>The Last of Us</title>
- <platform>HBO Max</platform>
- <genres>Drama</genres>
- <genres>Horror</genres>
- <genres>Sci-Fi</genres>
- <release_year>2023</release_year>
- <status>Ongoing</status>
- <seasons>2</seasons>
- <episodes>16</episodes>
- <creators>Craig Mazin</creators>
- <creators>Neil Druckmann</creators>
- <cast>Pedro Pascal</cast>
- <cast>Bella Ramsey</cast>
- <cast>Anna Torv</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.7</imdb_rating>
- <description>After a global pandemic destroys civilization, a
hardened survivor takes charge of a 14-year-old girl who may be humanity's
last hope.</description>
- <tags>post-apocalyptic</tags>
- <tags>zombies</tags>
- <tags>video-game-adaptation</tags>
- <tags>fungal</tags>
- </show>
- <show>
- <id>hulu-002</id>
- <title>The Bear</title>
- <platform>Hulu</platform>
- <genres>Comedy</genres>
- <genres>Drama</genres>
- <release_year>2022</release_year>
- <status>Ongoing</status>
- <seasons>3</seasons>
- <episodes>28</episodes>
- <creators>Christopher Storer</creators>
- <cast>Jeremy Allen White</cast>
- <cast>Ebon Moss-Bachrach</cast>
- <cast>Ayo Edebiri</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.6</imdb_rating>
- <description>A young chef from the fine dining world returns to
Chicago to run his family's sandwich shop after a heartbreaking
death.</description>
- <tags>cooking</tags>
- <tags>chicago</tags>
- <tags>family</tags>
- <tags>anxiety</tags>
- </show>
- <show>
- <id>netflix-003</id>
- <title>Squid Game</title>
- <platform>Netflix</platform>
- <genres>Thriller</genres>
- <genres>Drama</genres>
- <genres>Survival</genres>
- <release_year>2021</release_year>
- <end_year>2025</end_year>
- <status>Ended</status>
- <seasons>3</seasons>
- <episodes>22</episodes>
- <creators>Hwang Dong-hyuk</creators>
- <cast>Lee Jung-jae</cast>
- <cast>Park Hae-soo</cast>
- <cast>Wi Ha-joon</cast>
- <cast>HoYeon Jung</cast>
- <country>South Korea</country>
- <language>Korean</language>
- <rating>TV-MA</rating>
- <imdb_rating>8.0</imdb_rating>
- <description>Hundreds of cash-strapped contestants accept an
invitation to compete in deadly children's games for a tempting
prize.</description>
- <tags>korean</tags>
- <tags>survival</tags>
- <tags>dystopian</tags>
- <tags>social-commentary</tags>
- </show>
- <show>
- <id>netflix-004</id>
- <title>Wednesday</title>
- <platform>Netflix</platform>
- <genres>Comedy</genres>
- <genres>Horror</genres>
- <genres>Mystery</genres>
- <release_year>2022</release_year>
- <status>Ongoing</status>
- <seasons>2</seasons>
- <episodes>16</episodes>
- <creators>Alfred Gough</creators>
- <creators>Miles Millar</creators>
- <cast>Jenna Ortega</cast>
- <cast>Catherine Zeta-Jones</cast>
- <cast>Luis Guzmán</cast>
- <cast>Gwendoline Christie</cast>
- <country>USA</country>
- <language>English</language>
- <rating>TV-14</rating>
- <imdb_rating>8.1</imdb_rating>
- <description>Wednesday Addams navigates a supernatural boarding
school while solving a murder mystery.</description>
- <tags>gothic</tags>
- <tags>teen</tags>
- <tags>supernatural</tags>
- <tags>addams-family</tags>
- </show>
-</shows></code></pre></div>
+<add>
+ <doc>
+ <field name="id">hbo-001</field>
+ <field name="title">Game of Thrones</field>
+ <field name="platform">HBO Max</field>
+ <field name="genres">Fantasy</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Adventure</field>
+ <field name="release_year">2011</field>
+ <field name="end_year">2019</field>
+ <field name="status">Ended</field>
+ <field name="seasons">8</field>
+ <field name="episodes">73</field>
+ <field name="creators">David Benioff</field>
+ <field name="creators">D.B. Weiss</field>
+ <field name="cast">Emilia Clarke</field>
+ <field name="cast">Peter Dinklage</field>
+ <field name="cast">Kit Harington</field>
+ <field name="cast">Lena Headey</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">9.2</field>
+ <field name="description">Nine noble families fight for control over
the lands of Westeros, while an ancient enemy returns after being dormant for
millennia.</field>
+ <field name="tags">fantasy</field>
+ <field name="tags">dragons</field>
+ <field name="tags">epic</field>
+ <field name="tags">george-rr-martin</field>
+ </doc>
+ <doc>
+ <field name="id">netflix-001</field>
+ <field name="title">Stranger Things</field>
+ <field name="platform">Netflix</field>
+ <field name="genres">Sci-Fi</field>
+ <field name="genres">Horror</field>
+ <field name="genres">Drama</field>
+ <field name="release_year">2016</field>
+ <field name="end_year">2025</field>
+ <field name="status">Ended</field>
+ <field name="seasons">5</field>
+ <field name="episodes">42</field>
+ <field name="creators">Matt Duffer</field>
+ <field name="creators">Ross Duffer</field>
+ <field name="cast">Millie Bobby Brown</field>
+ <field name="cast">Finn Wolfhard</field>
+ <field name="cast">Winona Ryder</field>
+ <field name="cast">David Harbour</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-14</field>
+ <field name="imdb_rating">8.7</field>
+ <field name="description">A group of kids in 1980s Indiana uncover
supernatural mysteries and government conspiracies tied to a parallel
dimension.</field>
+ <field name="tags">80s</field>
+ <field name="tags">supernatural</field>
+ <field name="tags">coming-of-age</field>
+ <field name="tags">monsters</field>
+ </doc>
+ <doc>
+ <field name="id">hulu-001</field>
+ <field name="title">The Handmaid's Tale</field>
+ <field name="platform">Hulu</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Sci-Fi</field>
+ <field name="genres">Dystopian</field>
+ <field name="release_year">2017</field>
+ <field name="end_year">2025</field>
+ <field name="status">Ended</field>
+ <field name="seasons">6</field>
+ <field name="episodes">66</field>
+ <field name="creators">Bruce Miller</field>
+ <field name="cast">Elisabeth Moss</field>
+ <field name="cast">Joseph Fiennes</field>
+ <field name="cast">Yvonne Strahovski</field>
+ <field name="cast">Samira Wiley</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.4</field>
+ <field name="description">Set in a dystopian future, a woman is
forced to live as a concubine under a fundamentalist theocratic
dictatorship.</field>
+ <field name="tags">dystopian</field>
+ <field name="tags">feminist</field>
+ <field name="tags">atwood</field>
+ <field name="tags">theocracy</field>
+ </doc>
+ <doc>
+ <field name="id">disney-001</field>
+ <field name="title">The Mandalorian</field>
+ <field name="platform">Disney+</field>
+ <field name="genres">Sci-Fi</field>
+ <field name="genres">Action</field>
+ <field name="genres">Adventure</field>
+ <field name="release_year">2019</field>
+ <field name="status">Ongoing</field>
+ <field name="seasons">3</field>
+ <field name="episodes">24</field>
+ <field name="creators">Jon Favreau</field>
+ <field name="cast">Pedro Pascal</field>
+ <field name="cast">Carl Weathers</field>
+ <field name="cast">Giancarlo Esposito</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-14</field>
+ <field name="imdb_rating">8.6</field>
+ <field name="description">The travels of a lone bounty hunter in the
outer reaches of the galaxy, far from the authority of the New
Republic.</field>
+ <field name="tags">star-wars</field>
+ <field name="tags">space-western</field>
+ <field name="tags">grogu</field>
+ <field name="tags">baby-yoda</field>
+ </doc>
+ <doc>
+ <field name="id">hbo-002</field>
+ <field name="title">Succession</field>
+ <field name="platform">HBO Max</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Comedy</field>
+ <field name="release_year">2018</field>
+ <field name="end_year">2023</field>
+ <field name="status">Ended</field>
+ <field name="seasons">4</field>
+ <field name="episodes">39</field>
+ <field name="creators">Jesse Armstrong</field>
+ <field name="cast">Brian Cox</field>
+ <field name="cast">Jeremy Strong</field>
+ <field name="cast">Kieran Culkin</field>
+ <field name="cast">Sarah Snook</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.9</field>
+ <field name="description">The Roy family controls the biggest media
and entertainment company in the world, but their patriarch's health is
failing.</field>
+ <field name="tags">media</field>
+ <field name="tags">family-drama</field>
+ <field name="tags">satire</field>
+ <field name="tags">wealth</field>
+ </doc>
+ <doc>
+ <field name="id">prime-001</field>
+ <field name="title">The Boys</field>
+ <field name="platform">Amazon Prime Video</field>
+ <field name="genres">Action</field>
+ <field name="genres">Sci-Fi</field>
+ <field name="genres">Drama</field>
+ <field name="release_year">2019</field>
+ <field name="status">Ongoing</field>
+ <field name="seasons">4</field>
+ <field name="episodes">32</field>
+ <field name="creators">Eric Kripke</field>
+ <field name="cast">Karl Urban</field>
+ <field name="cast">Jack Quaid</field>
+ <field name="cast">Antony Starr</field>
+ <field name="cast">Erin Moriarty</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.7</field>
+ <field name="description">A group of vigilantes set out to take down
corrupt superheroes who abuse their powers.</field>
+ <field name="tags">superheroes</field>
+ <field name="tags">satire</field>
+ <field name="tags">violent</field>
+ <field name="tags">comic-adaptation</field>
+ </doc>
+ <doc>
+ <field name="id">netflix-002</field>
+ <field name="title">The Crown</field>
+ <field name="platform">Netflix</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Historical</field>
+ <field name="genres">Biography</field>
+ <field name="release_year">2016</field>
+ <field name="end_year">2023</field>
+ <field name="status">Ended</field>
+ <field name="seasons">6</field>
+ <field name="episodes">60</field>
+ <field name="creators">Peter Morgan</field>
+ <field name="cast">Claire Foy</field>
+ <field name="cast">Olivia Colman</field>
+ <field name="cast">Imelda Staunton</field>
+ <field name="cast">Matt Smith</field>
+ <field name="country">UK</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.6</field>
+ <field name="description">The reign of Queen Elizabeth II from her
wedding in 1947 through the early 21st century.</field>
+ <field name="tags">royalty</field>
+ <field name="tags">british</field>
+ <field name="tags">period-drama</field>
+ <field name="tags">politics</field>
+ </doc>
+ <doc>
+ <field name="id">prime-002</field>
+ <field name="title">The Marvelous Mrs. Maisel</field>
+ <field name="platform">Amazon Prime Video</field>
+ <field name="genres">Comedy</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Period</field>
+ <field name="release_year">2017</field>
+ <field name="end_year">2023</field>
+ <field name="status">Ended</field>
+ <field name="seasons">5</field>
+ <field name="episodes">43</field>
+ <field name="creators">Amy Sherman-Palladino</field>
+ <field name="cast">Rachel Brosnahan</field>
+ <field name="cast">Alex Borstein</field>
+ <field name="cast">Michael Zegen</field>
+ <field name="cast">Tony Shalhoub</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.7</field>
+ <field name="description">A 1950s New York housewife discovers she
has a talent for stand-up comedy.</field>
+ <field name="tags">50s</field>
+ <field name="tags">stand-up</field>
+ <field name="tags">feminist</field>
+ <field name="tags">new-york</field>
+ </doc>
+ <doc>
+ <field name="id">hbo-003</field>
+ <field name="title">The Last of Us</field>
+ <field name="platform">HBO Max</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Horror</field>
+ <field name="genres">Sci-Fi</field>
+ <field name="release_year">2023</field>
+ <field name="status">Ongoing</field>
+ <field name="seasons">2</field>
+ <field name="episodes">16</field>
+ <field name="creators">Craig Mazin</field>
+ <field name="creators">Neil Druckmann</field>
+ <field name="cast">Pedro Pascal</field>
+ <field name="cast">Bella Ramsey</field>
+ <field name="cast">Anna Torv</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.7</field>
+ <field name="description">After a global pandemic destroys
civilization, a hardened survivor takes charge of a 14-year-old girl who may be
humanity's last hope.</field>
+ <field name="tags">post-apocalyptic</field>
+ <field name="tags">zombies</field>
+ <field name="tags">video-game-adaptation</field>
+ <field name="tags">fungal</field>
+ </doc>
+ <doc>
+ <field name="id">hulu-002</field>
+ <field name="title">The Bear</field>
+ <field name="platform">Hulu</field>
+ <field name="genres">Comedy</field>
+ <field name="genres">Drama</field>
+ <field name="release_year">2022</field>
+ <field name="status">Ongoing</field>
+ <field name="seasons">3</field>
+ <field name="episodes">28</field>
+ <field name="creators">Christopher Storer</field>
+ <field name="cast">Jeremy Allen White</field>
+ <field name="cast">Ebon Moss-Bachrach</field>
+ <field name="cast">Ayo Edebiri</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.6</field>
+ <field name="description">A young chef from the fine dining world
returns to Chicago to run his family's sandwich shop after a heartbreaking
death.</field>
+ <field name="tags">cooking</field>
+ <field name="tags">chicago</field>
+ <field name="tags">family</field>
+ <field name="tags">anxiety</field>
+ </doc>
+ <doc>
+ <field name="id">netflix-003</field>
+ <field name="title">Squid Game</field>
+ <field name="platform">Netflix</field>
+ <field name="genres">Thriller</field>
+ <field name="genres">Drama</field>
+ <field name="genres">Survival</field>
+ <field name="release_year">2021</field>
+ <field name="end_year">2025</field>
+ <field name="status">Ended</field>
+ <field name="seasons">3</field>
+ <field name="episodes">22</field>
+ <field name="creators">Hwang Dong-hyuk</field>
+ <field name="cast">Lee Jung-jae</field>
+ <field name="cast">Park Hae-soo</field>
+ <field name="cast">Wi Ha-joon</field>
+ <field name="cast">HoYeon Jung</field>
+ <field name="country">South Korea</field>
+ <field name="language">Korean</field>
+ <field name="rating">TV-MA</field>
+ <field name="imdb_rating">8.0</field>
+ <field name="description">Hundreds of cash-strapped contestants
accept an invitation to compete in deadly children's games for a tempting
prize.</field>
+ <field name="tags">korean</field>
+ <field name="tags">survival</field>
+ <field name="tags">dystopian</field>
+ <field name="tags">social-commentary</field>
+ </doc>
+ <doc>
+ <field name="id">netflix-004</field>
+ <field name="title">Wednesday</field>
+ <field name="platform">Netflix</field>
+ <field name="genres">Comedy</field>
+ <field name="genres">Horror</field>
+ <field name="genres">Mystery</field>
+ <field name="release_year">2022</field>
+ <field name="status">Ongoing</field>
+ <field name="seasons">2</field>
+ <field name="episodes">16</field>
+ <field name="creators">Alfred Gough</field>
+ <field name="creators">Miles Millar</field>
+ <field name="cast">Jenna Ortega</field>
+ <field name="cast">Catherine Zeta-Jones</field>
+ <field name="cast">Luis Guzmán</field>
+ <field name="cast">Gwendoline Christie</field>
+ <field name="country">USA</field>
+ <field name="language">English</field>
+ <field name="rating">TV-14</field>
+ <field name="imdb_rating">8.1</field>
+ <field name="description">Wednesday Addams navigates a supernatural
boarding school while solving a murder mystery.</field>
+ <field name="tags">gothic</field>
+ <field name="tags">teen</field>
+ <field name="tags">supernatural</field>
+ <field name="tags">addams-family</field>
+ </doc>
+</add></code></pre></div>
</div>
<div data-format="markdown">
- <p style="font-size:.86rem">Three shows, three Markdown documents,
three tool calls:</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>Index each of the following three
Markdown documents into the shows-auto collection, one at a time:
+ <p style="font-size:.86rem">Three shows, three Markdown documents, one
tool call:</p>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>Index the following three Markdown
documents into the shows-auto collection:
---
id: hbo-001
@@ -1845,7 +1864,7 @@ Set in a dystopian future, a woman is forced to live as a
concubine under a fund
<div class="prompts">
<div class="prompt">
- <q>Show me the breakdown of shows-auto by platform.<span
class="why">calls <b>search</b> with a facet — this will not go well</span></q>
+ <q>Show me the breakdown of shows-auto by platform.<span
class="why">calls <b>search</b> with a facet — this may not go the way you
expect</span></q>
<button class="copy-sm" type="button" data-copy="Show me the breakdown
of shows-auto by platform.">Copy</button>
</div>
<div class="prompt">
@@ -1855,14 +1874,10 @@ Set in a dystopian future, a woman is forced to live as
a concubine under a fund
</div>
<h3>What Solr guessed</h3>
- <p style="font-size:.86rem;color:var(--ink-2)" data-format="csv markdown">
- The table below was captured from the JSON path. CSV and Markdown
deliver the same values as
- text; Solr's schemaless chain parses numeric-looking text before
choosing a type, so expect the
- same guesses.
- </p>
- <p style="font-size:.86rem;color:var(--ink-2)" data-format="xml">
- With XML every name below carries the <code class="inline">show_</code>
prefix
- (<code class="inline">show_platform</code>, <code
class="inline">show_imdb_rating</code>).
+ <p style="font-size:.86rem;color:var(--ink-2)" data-format="csv xml
markdown">
+ The table below was captured from the JSON path. CSV, XML and Markdown
deliver the same values
+ as text; Solr's schemaless chain parses numeric-looking text before
choosing a type, so expect
+ the same guesses.
</p>
<div class="tablewrap">
<table>
@@ -1885,26 +1900,19 @@ Set in a dystopian future, a woman is forced to live as
a concubine under a fund
</p>
<div class="note bug">
- <span class="tag">You'll see one of two things here</span>
- <p>
- Either an empty breakdown — <code class="inline">"facets": {
"platform": {} }</code> —
- or a <code class="inline">ClassCastException: ArrayList cannot be cast
to NamedList</code>.
- Which one depends on whether your image predates
- <a
href="https://github.com/apache/solr-mcp/pull/175">apache/solr-mcp#175</a>.
Both make
- the same point, and neither is your fault.
- </p>
+ <span class="tag">What you'll see</span>
<p>
- The exception is worth understanding because it isn't about this field
type: the trigger
- is <b>any facet that comes back with zero buckets</b>. Solr serializes
an empty facet as
- <code class="inline">[]</code>, and the response parser hands that to
SolrJ as a plain
- list where a <code class="inline">NamedList</code> is expected — so an
ordinary search on
- a well-typed field whose filter matches nothing hits it too. #175
fixes that by deciding
- from the response path rather than the array's shape.
+ Either an empty breakdown — <code class="inline">"facets": {
"platform": {} }</code> — or,
+ if your assistant read the schema first, real buckets on
+ <code class="inline">platform_str</code>. Schemaless mode quietly
copies every text field
+ into a <code class="inline">*_str</code> string field, and a
schema-aware assistant facets
+ on the copy instead. Ask it to <q>facet on the platform field
itself</q> and you get the
+ empty result: <code class="inline">text_general</code> yields no facet
buckets at all.
</p>
<p>
- Either way, the lesson is the one below: <code
class="inline">text_general</code> yields
- no facet buckets at all. Step 5 gives <code
class="inline">platform</code> real buckets,
- and the question starts answering itself.
+ The copies are a patch, not a design: one per text field, capped at
256 characters, and no
+ help for the numbers. Step 5 gives <code
class="inline">platform</code> real buckets, and
+ the question starts answering itself.
</p>
</div>
@@ -1940,7 +1948,7 @@ Set in a dystopian future, a woman is forced to live as a
concubine under a fund
</div>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker rm -f solr-mcp-demo
-docker run -d --name solr-mcp-demo -p 8983:8983 solr:9-slim solr start -c
-f</code></pre></div>
+docker run -d --name solr-mcp-demo --network=solr-mcp -p 127.0.0.1:8983:8983
solr:9-slim solr start -c -f</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
Takes about seven seconds. Wait for the collections endpoint to answer
before continuing.
</p>
@@ -2025,10 +2033,14 @@ docker run -d --name solr-mcp-demo -p 8983:8983
solr:9-slim solr start -c -f</co
<q>Which shows have "dragon" in the title?<span class="why"><b>q</b> ·
full-text on an analyzed field → 1 hit, House of the Dragon</span></q>
<button class="copy-sm" type="button" data-copy="Which shows have
"dragon" in the title?">Copy</button>
</div>
- <div class="prompt">
+ <div class="prompt" data-format="json csv xml">
<q>Find shows whose description contains the exact phrase "a group
of".<span class="why"><b>q</b> · phrase query → 2 hits, The Boys and Stranger
Things</span></q>
<button class="copy-sm" type="button" data-copy="Find shows whose
description contains the exact phrase "a group of".">Copy</button>
</div>
+ <div class="prompt" data-format="markdown">
+ <q>Find shows whose content field contains the exact phrase "a group
of".<span class="why"><b>q</b> · phrase query → 2 hits, The Boys and Stranger
Things (Markdown puts the description in <code>content</code>)</span></q>
+ <button class="copy-sm" type="button" data-copy="Find shows whose
content field contains the exact phrase "a group of".">Copy</button>
+ </div>
<div class="prompt">
<q>Show me everything on Netflix.<span class="why"><b>fq</b> · exact
string filter → 20 hits</span></q>
<button class="copy-sm" type="button" data-copy="Show me everything on
Netflix.">Copy</button>
@@ -2113,12 +2125,15 @@ docker run -d --name solr-mcp-demo -p 8983:8983
solr:9-slim solr start -c -f</co
<thead><tr><th>Tool</th><th>Does</th></tr></thead>
<tbody>
<tr><td><code>search</code></td><td>Query, filter, facet, sort,
paginate</td></tr>
- <tr><td><code>index-json-documents</code></td><td>Index from a JSON
string</td></tr>
- <tr><td><code>index-csv-documents</code></td><td>Index from
CSV</td></tr>
- <tr><td><code>index-xml-documents</code></td><td>Index from
XML</td></tr>
+ <tr><td><code>index-json-documents</code></td><td>Index a JSON array
of documents</td></tr>
+ <tr><td><code>index-csv-documents</code></td><td>Index CSV through
Solr's CSV handler</td></tr>
+ <tr><td><code>index-xml-documents</code></td><td>Index Solr update
XML — <code><add></code> blocks only</td></tr>
<tr><td><code>index-markdown-documents</code></td><td>Index from
Markdown — YAML front matter plus body text</td></tr>
<tr><td><code>create-collection</code></td><td>New collection,
optional configset / shards / replicas</td></tr>
<tr><td><code>list-collections</code></td><td>Everything in the
cluster</td></tr>
+ <tr><td><code>list-aliases</code></td><td>Aliases and the
collections they point to</td></tr>
+ <tr><td><code>create-alias</code></td><td>Point an alias at one or
more collections, or repoint it</td></tr>
+ <tr><td><code>delete-alias</code></td><td>Remove an alias — the
collections stay</td></tr>
<tr><td><code>get-collection-stats</code></td><td>Index, query,
cache and handler metrics</td></tr>
<tr><td><code>check-health</code></td><td>Ping and document
count</td></tr>
<tr><td><code>get-schema</code></td><td>Fields, types, dynamic
fields, copy fields</td></tr>
@@ -2174,18 +2189,19 @@ cd solr-mcp
<summary>Native builds and every way to run it <span class="hint">jar ·
native binary · Docker × stdio · http</span></summary>
<div class="panel-body">
<p>
- Six ways to run the server, from one checkout. Each row is a build
command and a run
- command; <b>stdio</b> is launched by your client, <b>http</b> is a
process you start
- yourself (<a href="#s2">step 2</a>). Everything here uses the clone
from
- <a href="#build-local">Build it yourself</a>, with Solr from step 1
running.
+ Each form below has a build command and a run command, for the <b>Run
via</b> and
+ <b>Transport</b> you picked in <a href="#s0">step 0</a>. <b>JAR</b>
shows what runs
+ directly on your machine, the JVM jar and the native binary.
<b>Docker</b> shows the two
+ images. Everything here uses the clone from <a
href="#build-local">Build it yourself</a>,
+ with Solr from step 1 running.
</p>
<table>
<thead><tr><th>Form</th><th>stdio</th><th>http</th><th>Needs</th></tr></thead>
<tbody>
- <tr><td>JVM jar</td><td><a href="#bn-jar">one build,
both</a></td><td><a href="#bn-jar">same jar</a></td><td>JDK 25</td></tr>
- <tr><td>JVM Docker image (Jib)</td><td><a href="#bn-docker">one
image, both</a></td><td><a href="#bn-docker">same image</a></td><td>JDK 25,
Docker</td></tr>
- <tr><td>Native binary</td><td><a href="#bn-bin">build with
stdio</a></td><td><a href="#bn-bin">build with http</a></td><td>GraalVM JDK
25</td></tr>
- <tr><td>Native Docker image</td><td><a
href="#bn-ndocker">…-native-stdio</a></td><td><a
href="#bn-ndocker">…-native-http</a></td><td>Docker only</td></tr>
+ <tr data-runtime="jar"><td>JVM jar</td><td><a href="#bn-jar">one
build, both</a></td><td><a href="#bn-jar">same jar</a></td><td>JDK 25</td></tr>
+ <tr data-runtime="jar"><td>Native binary</td><td><a
href="#bn-bin">build with stdio</a></td><td><a href="#bn-bin">build with
http</a></td><td>GraalVM JDK 25</td></tr>
+ <tr data-runtime="docker"><td>JVM Docker image (Jib)</td><td><a
href="#bn-docker">one image, both</a></td><td><a href="#bn-docker">same
image</a></td><td>JDK 25, Docker</td></tr>
+ <tr data-runtime="docker"><td>Native Docker image</td><td><a
href="#bn-ndocker">…-native-stdio</a></td><td><a
href="#bn-ndocker">…-native-http</a></td><td>Docker only</td></tr>
</tbody>
</table>
<p style="font-size:.86rem;color:var(--ink-2)">
@@ -2196,76 +2212,113 @@ cd solr-mcp
Solr from step 1.
</p>
+ <div data-runtime="jar">
<h3 id="bn-jar">JVM jar</h3>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>./gradlew build
<span class="tok-c"># build/libs/solr-mcp-1.0.0-SNAPSHOT.jar</span>
+ <div class="codeblock" data-transport="stdio"><button class="copy"
type="button">Copy</button><pre><code>./gradlew build
<span class="tok-c"># build/libs/solr-mcp-1.0.0-SNAPSHOT.jar</span>
<span class="tok-c"># stdio: your client runs this</span>
SOLR_URL=http://localhost:8983/solr/ \
- java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar
+ java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
+ <div class="codeblock" data-transport="http"><button class="copy"
type="button">Copy</button><pre><code>./gradlew build
<span class="tok-c"># build/libs/solr-mcp-1.0.0-SNAPSHOT.jar</span>
<span class="tok-c"># http: you run this</span>
-PROFILES=http HTTP_SECURITY_ENABLED=false SOLR_URL=http://localhost:8983/solr/
\
+PROFILES=http SERVER_ADDRESS=127.0.0.1 HTTP_SECURITY_ENABLED=false \
+ SOLR_URL=http://localhost:8983/solr/ \
java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
- <h3 id="bn-docker">JVM Docker image (Jib)</h3>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>./gradlew jibDockerBuild
<span class="tok-c"># solr-mcp:latest</span>
-
-<span class="tok-c"># stdio: your client runs this (-i keeps stdin open)</span>
-docker run -i --rm --add-host=host.docker.internal:host-gateway \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
- solr-mcp:latest
-
-<span class="tok-c"># http</span>
-docker run -p 8080:8080 --rm --add-host=host.docker.internal:host-gateway \
- -e PROFILES=http -e HTTP_SECURITY_ENABLED=false \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
- solr-mcp:latest</code></pre></div>
-
<h3 id="bn-bin">Native binary (host OS only)</h3>
<p>
Needs GraalVM JDK 25 on <code class="inline">JAVA_HOME</code>. The
first compile takes
several minutes. The binary only runs on the OS and CPU you built it
on.
</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># stdio</span>
+ <div class="codeblock" data-transport="stdio"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># stdio: your client
runs the binary</span>
./gradlew nativeCompile -Pnative
-SOLR_URL=http://localhost:8983/solr/ build/native/nativeCompile/solr-mcp
-
-<span class="tok-c"># http (a separate build: the transport is baked in)</span>
-./gradlew nativeCompile -Pnative -Pprofile=http
-PROFILES=http HTTP_SECURITY_ENABLED=false SOLR_URL=http://localhost:8983/solr/
\
+SOLR_URL=http://localhost:8983/solr/
build/native/nativeCompile/solr-mcp</code></pre></div>
+ <div class="codeblock" data-transport="http"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># http (the transport
and the security switch are baked in at build time)</span>
+HTTP_SECURITY_ENABLED=false ./gradlew nativeCompile -Pnative -Pprofile=http
+PROFILES=http SERVER_ADDRESS=127.0.0.1 HTTP_SECURITY_ENABLED=false \
+ SOLR_URL=http://localhost:8983/solr/ \
build/native/nativeCompile/solr-mcp</code></pre></div>
+ </div>
+
+ <div data-runtime="docker">
+ <h3 id="bn-docker">JVM Docker image (Jib)</h3>
+ <div class="codeblock" data-transport="stdio"><button class="copy"
type="button">Copy</button><pre><code>./gradlew jibDockerBuild
<span class="tok-c"># solr-mcp:latest</span>
+
+<span class="tok-c"># stdio: your client runs this (-i keeps stdin open)</span>
+docker run -i --rm --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ solr-mcp:latest</code></pre></div>
+ <div class="codeblock" data-transport="http"><button class="copy"
type="button">Copy</button><pre><code>./gradlew jibDockerBuild
<span class="tok-c"># solr-mcp:latest</span>
+
+<span class="tok-c"># http: you run this</span>
+docker run -p 127.0.0.1:8080:8080 --rm --network=solr-mcp \
+ -e PROFILES=http -e HTTP_SECURITY_ENABLED=false \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ solr-mcp:latest</code></pre></div>
<h3 id="bn-ndocker">Native Docker image</h3>
<p>
- Built inside a Linux builder container, so it works on macOS, Linux
and Windows without
- installing GraalVM. Needs Docker and a few minutes.
+ Prebuilt for this event, for Intel and Apple-silicon machines alike —
nothing to build:
</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># stdio</span>
-./gradlew bootBuildImage -Pnative <span class="tok-c">#
solr-mcp:latest-native-stdio</span>
-docker run -i --rm --add-host=host.docker.internal:host-gateway \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
- solr-mcp:latest-native-stdio
-
-<span class="tok-c"># http</span>
-./gradlew bootBuildImage -Pnative -Pprofile=http <span class="tok-c">#
solr-mcp:latest-native-http</span>
-docker run -p 8080:8080 --rm --add-host=host.docker.internal:host-gateway \
+ <div class="codeblock" data-transport="stdio"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># stdio: your client
runs this</span>
+docker run -i --rm --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ ghcr.io/adityamparikh/solr-mcp:coc2026-native-stdio</code></pre></div>
+ <div class="codeblock" data-transport="http"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># http: you run
this</span>
+docker run -p 127.0.0.1:8080:8080 --rm --network=solr-mcp \
-e PROFILES=http -e HTTP_SECURITY_ENABLED=false \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ ghcr.io/adityamparikh/solr-mcp:coc2026-native-http</code></pre></div>
+ <p>
+ Or build it yourself, inside a Linux builder container, so it works on
macOS, Linux and
+ Windows without installing GraalVM. Needs Docker and a few minutes.
+ </p>
+ <div class="codeblock" data-transport="stdio"><button class="copy"
type="button">Copy</button><pre><code>./gradlew bootBuildImage -Pnative
<span class="tok-c"># solr-mcp:latest-native-stdio</span>
+docker run -i --rm --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ solr-mcp:latest-native-stdio</code></pre></div>
+ <div class="codeblock" data-transport="http"><button class="copy"
type="button">Copy</button><pre><code>HTTP_SECURITY_ENABLED=false ./gradlew
bootBuildImage -Pnative -Pprofile=http <span class="tok-c">#
solr-mcp:latest-native-http</span>
+docker run -p 127.0.0.1:8080:8080 --rm --network=solr-mcp \
+ -e PROFILES=http -e HTTP_SECURITY_ENABLED=false \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
solr-mcp:latest-native-http</code></pre></div>
+ </div>
+
<div class="note warn">
<span class="tag">Mixing them up fails quietly</span>
- <p>
+ <p data-runtime="docker">
The <code class="inline">-native-stdio</code> image has no web
server in it, and the
<code class="inline">-native-http</code> image has no stdio
transport. Pointing a client
at the wrong one gives a timeout, not a helpful error.
</p>
+ <p data-runtime="jar">
+ A native binary built without <code
class="inline">-Pprofile=http</code> has no web
+ server in it, and one built with it has no stdio transport. Pointing
a client at the
+ wrong one gives a timeout, not a helpful error.
+ </p>
</div>
- <p style="font-size:.86rem;color:var(--ink-2)">
- To use any of these with a client, take the matching config from
- <a href="#s2">step 2</a> and swap in the image tag or binary path. Use
- <code class="inline">solr-mcp:latest</code> where it says
- <code class="inline">ghcr.io/…</code>, or the binary's absolute path
where it says
- <em>JAR</em>.
+ <div class="note warn" data-transport="http">
+ <span class="tag">Native http picks its security when it is
built</span>
+ <p>
+ Spring AOT fixes the security setup inside the binary, so
+ <code class="inline">HTTP_SECURITY_ENABLED</code> only counts at
build time; at run time
+ a native http server ignores it. That is why the build commands
above set it. Built
+ without it, every tool answers <q>Access Denied</q> until you
configure OAuth2
+ (<a href="#secured">Security setup</a>).<span data-runtime="docker">
The prebuilt
+ <code class="inline">coc2026-native-http</code> image is built with
security off, for
+ use on your own machine only.</span>
+ </p>
+ </div>
+ <p style="font-size:.86rem;color:var(--ink-2)" data-runtime="docker">
+ To use one of these images with a client, take the matching config from
+ <a href="#s2">step 2</a> and put the image tag above where it says
+ <code class="inline">ghcr.io/adityamparikh/solr-mcp:coc2026</code>.
+ </p>
+ <p style="font-size:.86rem;color:var(--ink-2)" data-runtime="jar">
+ To use these with a client, take the matching config from <a
href="#s2">step 2</a>. For
+ the native binary, put its absolute path in place of
+ <code class="inline">java -jar
/absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code>.
</p>
</div>
</details>
@@ -2299,35 +2352,39 @@ docker run -p 8080:8080 --rm
--add-host=host.docker.internal:host-gateway \
</p>
<h3>1. Start LGTM</h3>
- <p style="font-size:.86rem;color:var(--ink-2)">Grafana on 3000, the OTLP
receiver on 4317 (gRPC) and 4318 (HTTP). The loop waits for the collector;
Grafana answers first, and export only works once the collector is up.</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker run -d --name lgtm -p 3000:3000 -p
4317:4317 -p 4318:4318 grafana/otel-lgtm
+ <p style="font-size:.86rem;color:var(--ink-2)">Grafana on 3000 and the
OTLP/HTTP receiver on 4318, which is what the server exports to. The loop waits
for the collector; Grafana answers first, and export only works once the
collector is up.</p>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker run -d --name lgtm
--network=solr-mcp -p 127.0.0.1:3000:3000 -p 127.0.0.1:4318:4318
grafana/otel-lgtm:0.33.0
until docker logs lgtm 2>&1 | grep -q "up and running"; do sleep 2; done
echo "LGTM ready"</code></pre></div>
<h3>2. Restart the server pointed at it</h3>
<p style="font-size:.86rem;color:var(--ink-2)" data-runtime="docker">
- Stop the step 2 server first — this one listens on 8080 too. The
server sends to
- <code class="inline">localhost:4317</code> by default, which inside a
container is the
- container itself, so <code class="inline">OTEL_TRACES_URL</code> sends
it to your laptop
- instead. Despite the name it covers logs as well as traces.
+ Stop the step 2 server first — this one listens on 8080 too. The
server exports over
+ OTLP/HTTP to <code class="inline">localhost:4318</code> by default,
which inside a container
+ is the container itself, so these three variables send traces, metrics
and logs to the
+ <code class="inline">lgtm</code> container instead, by name over the
+ <code class="inline">solr-mcp</code> network. Each is the full URL for
its signal.
</p>
<p style="font-size:.86rem;color:var(--ink-2)" data-runtime="jar">
Stop the step 2 server first — this one listens on 8080 too. From a
plain JAR the default
- <code class="inline">localhost:4317</code> is already right, so the
command is the same as
+ <code class="inline">localhost:4318</code> is already right, so the
command is the same as
step 2: nothing to add.
</p>
- <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 8080:8080 --rm \
- --add-host=host.docker.internal:host-gateway \
+ <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 127.0.0.1:8080:8080 --rm \
+ --network=solr-mcp \
-e PROFILES=http \
-e HTTP_SECURITY_ENABLED=false \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
- -e OTEL_TRACES_URL=http://host.docker.internal:4317 \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
+ -e OTEL_TRACES_URL=http://lgtm:4318/v1/traces \
+ -e OTEL_METRICS_URL=http://lgtm:4318/v1/metrics \
+ -e OTEL_LOGS_URL=http://lgtm:4318/v1/logs \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
- <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
HTTP_SECURITY_ENABLED=false SOLR_URL=http://localhost:8983/solr/ \
+ <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
SERVER_ADDRESS=127.0.0.1 HTTP_SECURITY_ENABLED=false \
+ SOLR_URL=http://localhost:8983/solr/ \
java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="codeblock" data-runtime="jar" data-os="windows"><button
class="copy" type="button">Copy</button><pre><code><span class="tok-c">#
PowerShell</span>
-$env:PROFILES="http"; $env:HTTP_SECURITY_ENABLED="false";
$env:SOLR_URL="http://localhost:8983/solr/"
+$env:PROFILES="http"; $env:SERVER_ADDRESS="127.0.0.1";
$env:HTTP_SECURITY_ENABLED="false"; $env:SOLR_URL="http://localhost:8983/solr/"
java -jar C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<h3>3. Make some traffic</h3>
@@ -2351,28 +2408,29 @@ curl -s -X POST http://localhost:8080/mcp -H
"Content-Type: application/json" \
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>{resource.service.name="solr-mcp"}</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
Open an <code class="inline">http post /mcp</code> trace. Inside it
sit the security filter
- chain and one span named for the tool — <code
class="inline">search-service#search</code>,
- <code class="inline">indexing-service#…</code> — with its duration.
Traces take up to a minute to
+ chain and one span named for the tool — <code
class="inline">SearchService#search</code>,
+ <code class="inline">IndexingService#…</code> — with its duration.
Traces take up to a minute to
become searchable — an empty result right after the calls is normal,
so give it thirty
seconds and run the query again.
</p>
<p style="font-size:.86rem;color:var(--ink-2)">
- Now open the <code
class="inline">collection-service#check-health</code> trace from the
+ Now open the <code class="inline">CollectionService#checkHealth</code>
trace from the
failing call and click <b>Logs for this span</b>: Loki opens on its
<code class="inline">WARN Health check failed</code> line, matched by
trace ID. Each
- log line links back the same way. Request metrics land in
<b>Prometheus</b> once a
- minute; pick it in Explore and run:
+ log line links back the same way. Metrics land in <b>Prometheus</b>
once a minute, in
+ milliseconds; pick it in Explore and run:
</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>http_server_request_duration_seconds_count{job="solr-mcp"}</code></pre></div>
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>http_server_requests_milliseconds_count{job="solr-mcp"}</code></pre></div>
<div class="note warn">
<span class="tag">What you won't see</span>
<p>
<b>Logs on successful calls</b> — the services only log when
something fails, so for
the searches <em>Logs for this span</em> comes up empty. That's
expected, not broken.
- <b>JVM metrics</b> aren't exported either; they're served for
scraping:
- <code class="inline">curl -s localhost:8080/actuator/prometheus |
grep jvm_memory_used</code>.
And the call to Solr has no span of its own; its time is inside the
tool span.
+ JVM, Tomcat and per-tool metrics arrive the same way — try
+ <code class="inline">jvm_memory_used_bytes{job="solr-mcp"}</code> or
+ <code
class="inline">method_observed_milliseconds_count{job="solr-mcp"}</code>.
</p>
</div>
@@ -2404,7 +2462,7 @@ curl -s -X POST http://localhost:8080/mcp -H
"Content-Type: application/json" \
<h3>1. Start Keycloak</h3>
<p style="font-size:.86rem;color:var(--ink-2)">Port 8180, so it does not
collide with the MCP server. The loop waits until Keycloak actually answers;
the container is "up" long before that.</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker run -d --name keycloak -p
8180:8080 \
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker run -d --name keycloak -p
127.0.0.1:8180:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:26.0 start-dev
@@ -2460,18 +2518,18 @@ curl -sf
"$KC/realms/solr-mcp/.well-known/openid-configuration" >/dev/null && ec
<code class="inline">localhost:8180</code> is not your laptop, and the
issuer name has
to be identical in the container and in the tokens, which takes more
setup than a card.
</p>
- <div class="codeblock" data-os="macos linux wsl"><button class="copy"
type="button">Copy</button><pre><code>PROFILES=http HTTP_SECURITY_ENABLED=true \
+ <div class="codeblock" data-os="macos linux wsl"><button class="copy"
type="button">Copy</button><pre><code>PROFILES=http SERVER_ADDRESS=127.0.0.1
HTTP_SECURITY_ENABLED=true \
OAUTH2_ISSUER_URI=http://localhost:8180/realms/solr-mcp \
SOLR_URL=http://localhost:8983/solr/ \
java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="codeblock" data-os="windows"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># PowerShell</span>
-$env:PROFILES="http"; $env:HTTP_SECURITY_ENABLED="true";
$env:OAUTH2_ISSUER_URI="http://localhost:8180/realms/solr-mcp";
$env:SOLR_URL="http://localhost:8983/solr/"
+$env:PROFILES="http"; $env:SERVER_ADDRESS="127.0.0.1";
$env:HTTP_SECURITY_ENABLED="true";
$env:OAUTH2_ISSUER_URI="http://localhost:8180/realms/solr-mcp";
$env:SOLR_URL="http://localhost:8983/solr/"
java -jar C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">Leave that terminal open.
In another one, wait for
<code class="inline">curl http://localhost:8080/actuator/health</code>
to answer
<code class="inline">{"status":"UP"}</code>, then read back the
audience the server expects.
This is the value the mapper in step 2 has to match, character for
character:</p>
- <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -s
http://localhost:8080/.well-known/oauth-protected-resource | jq -r .resource
+ <div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>curl -s
http://localhost:8080/.well-known/oauth-protected-resource/mcp | jq -r .resource
# http://localhost:8080/mcp</code></pre></div>
<h3>4. Get a token</h3>
@@ -2518,7 +2576,7 @@ curl -s -X POST http://localhost:8080/mcp -H
"Content-Type: application/json" \
<div data-transport="http">
<p style="font-size:.86rem;color:var(--ink-2)" data-runtime="docker">
- Make sure your Solr MCP Docker container is running and port 8080 is
published (<code class="inline">-p 8080:8080</code>) so your client can reach
<code class="inline">http://localhost:8080/mcp</code>.
+ Make sure your Solr MCP Docker container is running and port 8080 is
published (<code class="inline">-p 127.0.0.1:8080:8080</code>) so your client
can reach <code class="inline">http://localhost:8080/mcp</code>.
</p>
<p style="font-size:.86rem;color:var(--ink-2)" data-runtime="jar">
Make sure your Solr MCP JAR process from step 3 is running and
listening on port 8080 before connecting your client.
@@ -2530,10 +2588,10 @@ curl -s -X POST http://localhost:8080/mcp -H
"Content-Type: application/json" \
Dataset: <code class="inline">shows-auto</code> was indexed from CSV
in step 3. The verification query checks that collection.
</p>
<p style="font-size:.86rem;color:var(--ink-2)" data-format="xml">
- Dataset: <code class="inline">shows-auto</code> was indexed from XML
in step 3 (fields carry the <code class="inline">show_</code> prefix). The
verification query checks that collection.
+ Dataset: <code class="inline">shows-auto</code> was indexed from XML
in step 3. The verification query checks that collection.
</p>
<p style="font-size:.86rem;color:var(--ink-2)" data-format="markdown">
- Dataset: <code class="inline">shows-auto</code> was indexed from
Markdown in step 3. The verification query checks that collection.
+ Dataset: <code class="inline">shows-auto</code> was indexed from
Markdown in step 3. The verification query checks that collection. Markdown
keeps each description in the body, so it is in <code
class="inline">content</code>, not <code class="inline">description</code>: the
phrase question finds its hits there.
</p>
<!-- ── Claude Code ── -->
@@ -2543,13 +2601,15 @@ curl -s -X POST http://localhost:8080/mcp -H
"Content-Type: application/json" \
--header "Authorization: Bearer $TOKEN"
claude mcp list # ✔ Connected — true with or without the header, so also
run:
claude -p "Call the list-collections tool on the solr-mcp MCP server and reply
with its raw result"
-# ["shows-auto", ...] ← the proof. "Access Denied" here means the header did
not reach the server.</code></pre></div>
+# ["shows-auto", ...] ← the proof. "Access Denied" here means the header did
not reach the server.
+# Tools missing, or the server fails to connect: the token reached it and was
rejected (expired, or wrong aud) with HTTP 401.</code></pre></div>
<div class="codeblock" data-os="windows"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># PowerShell</span>
claude mcp add --transport http solr-mcp http://localhost:8080/mcp `
--header "Authorization: Bearer $TOKEN"
claude mcp list <span class="tok-c"># ✔ Connected — true with or without
the header, so also run:</span>
claude -p "Call the list-collections tool on the solr-mcp MCP server and reply
with its raw result"
-<span class="tok-c"># ["shows-auto", ...] ← the proof. "Access Denied" here
means the header did not reach the server.</span></code></pre></div>
+<span class="tok-c"># ["shows-auto", ...] ← the proof. "Access Denied" here
means the header did not reach the server.</span>
+<span class="tok-c"># Tools missing, or the server fails to connect: the token
reached it and was rejected (expired, or wrong aud) with HTTP
401.</span></code></pre></div>
</div>
<!-- ── Codex ── -->
@@ -2564,13 +2624,15 @@ claude -p "Call the list-collections tool on the
solr-mcp MCP server and reply w
codex mcp add solr-mcp --url http://localhost:8080/mcp --bearer-token-env-var
SOLR_MCP_TOKEN
codex mcp list # Auth: Bearer token — true with or without a valid
token, so also run:
codex exec "Call the list-collections tool on the solr-mcp MCP server and
reply with its raw result"
-# ["shows-auto", ...] ← the proof. "Access Denied" here means the token did
not reach the server.</code></pre></div>
+# ["shows-auto", ...] ← the proof. "Access Denied" here means the token did
not reach the server.
+# Tools missing, or the server fails to connect: the token reached it and was
rejected (expired, or wrong aud) with HTTP 401.</code></pre></div>
<div class="codeblock" data-os="windows"><button class="copy"
type="button">Copy</button><pre><code><span class="tok-c"># PowerShell</span>
$env:SOLR_MCP_TOKEN = $TOKEN
codex mcp add solr-mcp --url http://localhost:8080/mcp --bearer-token-env-var
SOLR_MCP_TOKEN
codex mcp list <span class="tok-c"># Auth: Bearer token — true with or
without a valid token, so also run:</span>
codex exec "Call the list-collections tool on the solr-mcp MCP server and
reply with its raw result"
-<span class="tok-c"># ["shows-auto", ...] ← the proof. "Access Denied" here
means the token did not reach the server.</span></code></pre></div>
+<span class="tok-c"># ["shows-auto", ...] ← the proof. "Access Denied" here
means the token did not reach the server.</span>
+<span class="tok-c"># Tools missing, or the server fails to connect: the token
reached it and was rejected (expired, or wrong aud) with HTTP
401.</span></code></pre></div>
<p style="font-size:.86rem;color:var(--ink-2)">
The token expires after about five minutes; restart Codex after
refreshing it so it re-reads the variable.
</p>
@@ -2602,9 +2664,10 @@ codex exec "Call the list-collections tool on the
solr-mcp MCP server and reply
<div class="note warn" data-os="linux">
<span class="tag">On Linux</span>
<p>
- There is no official Claude Desktop build for Linux. That path
is where community
- builds look; if you're on Linux, <b>Claude Code</b> or <b>MCP
Inspector</b> is the
- smoother route.
+ Claude Desktop for Linux is an official beta for Ubuntu 22.04+
and Debian 12+. Anthropic
+ doesn't document its config path; if the file above has no effect,
open the one the
+ app reads from <b>Settings → Developer → Edit Config</b>. <b>Claude
Code</b> or
+ <b>MCP Inspector</b> is the smoother route on Linux.
</p>
</div>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>{
@@ -2668,7 +2731,7 @@ codex exec "Call the list-collections tool on the
solr-mcp MCP server and reply
<!-- ── IntelliJ ── -->
<div data-client="intellij">
<h4>IntelliJ IDEA / JetBrains (via mcp-remote)</h4>
- <p style="font-size:.86rem;color:var(--ink-2)">In <code
class="inline">.junie/mcp/mcp.json</code> or IDE Settings, proxy through <code
class="inline">mcp-remote</code> to forward the bearer header on each
request:</p>
+ <p style="font-size:.86rem;color:var(--ink-2)">In <b>Settings |
Tools | AI Assistant | Model Context Protocol (MCP)</b> → <b>Add</b> →
<b>STDIO</b> (or Junie's <code class="inline">.junie/mcp/mcp.json</code>),
proxy through <code class="inline">mcp-remote</code> to forward the bearer
header on each request:</p>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>{
"mcpServers": {
"solr-mcp": {
@@ -2766,19 +2829,20 @@ claude mcp remove solr-mcp</code></pre></div>
</li>
</ol>
- <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 8080:8080 --rm \
+ <div class="codeblock" data-runtime="docker"><button class="copy"
type="button">Copy</button><pre><code>docker run -p 127.0.0.1:8080:8080 --rm \
+ --network=solr-mcp \
-e PROFILES=http \
-e HTTP_SECURITY_ENABLED=true \
-e OAUTH2_ISSUER_URI=https://YOUR-TENANT.us.auth0.com/ \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre></div>
- <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
HTTP_SECURITY_ENABLED=true \
+ <div class="codeblock" data-runtime="jar" data-os="macos linux
wsl"><button class="copy" type="button">Copy</button><pre><code>PROFILES=http
SERVER_ADDRESS=127.0.0.1 HTTP_SECURITY_ENABLED=true \
OAUTH2_ISSUER_URI=https://YOUR-TENANT.us.auth0.com/ \
SOLR_URL=http://localhost:8983/solr/ \
java -jar /absolute/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<div class="codeblock" data-runtime="jar" data-os="windows"><button
class="copy" type="button">Copy</button><pre><code><span class="tok-c">#
PowerShell</span>
-$env:PROFILES="http"; $env:HTTP_SECURITY_ENABLED="true";
$env:OAUTH2_ISSUER_URI="https://YOUR-TENANT.us.auth0.com/";
$env:SOLR_URL="http://localhost:8983/solr/"
+$env:PROFILES="http"; $env:SERVER_ADDRESS="127.0.0.1";
$env:HTTP_SECURITY_ENABLED="true";
$env:OAUTH2_ISSUER_URI="https://YOUR-TENANT.us.auth0.com/";
$env:SOLR_URL="http://localhost:8983/solr/"
java -jar C:/path/to/solr-mcp-1.0.0-SNAPSHOT.jar</code></pre></div>
<ol start="4"
style="max-width:var(--measure);color:var(--ink-2);padding-left:1.1rem;font-size:.86rem">
@@ -2843,7 +2907,7 @@ EOF
</tr>
<tr>
<td>Connects, but every Solr call fails</td>
- <td><code>SOLR_URL</code> is wrong for the context. From
<b>inside</b> a container use <code>host.docker.internal</code>; from a plain
JAR use <code>localhost</code>. The <code>--add-host</code> flag in every
Docker command here is what makes that name resolve on Linux — it needs Docker
20.10+.</td>
+ <td><code>SOLR_URL</code> is wrong for the context. From
<b>inside</b> a container use <code>http://solr-mcp-demo:8983/solr/</code>,
which resolves because both containers are on the <code>solr-mcp</code> network
from step 1; from a plain JAR use <code>localhost</code>. If Docker says
<code>network solr-mcp not found</code>, run <code>docker network create
solr-mcp</code> and restart Solr with the step 1 command.</td>
</tr>
<tr>
<td><code>Solr instance is not running in SolrCloud
mode</code></td>
@@ -2862,7 +2926,7 @@ EOF
</div>
<h3>Start completely over</h3>
<div class="codeblock"><button class="copy"
type="button">Copy</button><pre><code>docker rm -f solr-mcp-demo
-docker run -d --name solr-mcp-demo -p 8983:8983 solr:9-slim solr start -c
-f</code></pre></div>
+docker run -d --name solr-mcp-demo --network=solr-mcp -p 127.0.0.1:8983:8983
solr:9-slim solr start -c -f</code></pre></div>
</div>
</details>
@@ -2899,7 +2963,7 @@ docker run -d --name solr-mcp-demo -p 8983:8983
solr:9-slim solr start -c -f</co
Community over Code 2026 hackathon session; the container image it
references is a personal
pre-release build, not an Apache release.
</p>
- <p>Verified against Solr 9 (SolrCloud), Spring Boot 3.5.14, solr-mcp
1.0.0-SNAPSHOT.</p>
+ <p>Verified against Solr 9 (SolrCloud), Spring Boot 4.1.1, Spring AI 2.0.1,
solr-mcp 1.0.0-SNAPSHOT.</p>
<div class="footer-events">
<a class="ac-banner" href="https://events.apache.org/" title="Apache
Events Calendar">
<img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOoAAAA8CAIAAADnkbErAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TpUVaFOwgopChOtlFRRxrFYpQIdQKrTqYXPoFTRqSFBdHwbXg4Mdi1cHFWVcHV0EQ/ABxdXFSdJES/5cWWsR4cNyPd/ced+8AoVFhmtUTBzTdNtPJhJjNrYqBVwQxgDBGIcjMMuYkKQXP8XUPH1/vYjzL+9yfI6zmLQb4ROI4M0ybeIN4ZtM2OO8TR1hJVonPiSdMuiDxI9eVFr9xLros8MyImUnPE0eIxWIXK13MSqZGPE0cVTWd8oVsi1XOW5y1So2178lfGMrrK8tcpzmCJBaxBAkiFNRQRgU2YrTqpFhI037Cwz/s+iVyKeQqg5FjAVVokF0/+B/87tYqTE22kkIJoPfFcT7GgMAu0Kw7zvex4z
[...]
diff --git a/docs/events/coc2026-glasgow/site/slides.html
b/docs/events/coc2026-glasgow/site/slides.html
index 2fa36c86..0cf1c892 100644
--- a/docs/events/coc2026-glasgow/site/slides.html
+++ b/docs/events/coc2026-glasgow/site/slides.html
@@ -92,7 +92,7 @@ tbody tr:last-child td{border-bottom:none}
</div>
<p class="num">Glasgow 2026</p>
<h1>Talk to <em>Apache Solr</em><br>in plain English</h1>
- <p class="lead">Twelve Solr tools, handed to your AI assistant over MCP.</p>
+ <p class="lead">Fifteen Solr tools, handed to your AI assistant over MCP.</p>
<img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iOTAwIiBjbGFzcz0ic2Vnbm8iPjxnIHRyYW5zZm9ybT0ic2NhbGUoMjApIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDQ1djQ1aC00NXoiLz48cGF0aCBjbGFzcz0icXJsaW5lIiBzdHJva2U9IiMxNTE3MWEiIGQ9Ik00IDQuNWg3bTMgMGgybTEgMGgxbTEgMGgxbTMgMGgybTIgMGgxbTIgMGgxbTMgMGg3bS0zNyAxaDFtNSAwaDFtMSAwaDJtMiAwaDFtMiAwaDFtMiAwaDFtMiAwaDFtMSAwaDFtMSAwaDJtMyAwaDFtNSAwaD
[...]
<p class="foot">Scan to follow along — everything in this deck is on that
page.</p>
<div class="tags">
@@ -123,7 +123,7 @@ tbody tr:last-child td{border-bottom:none}
That translation layer is the entire product — the server exposes Solr
operations as MCP
tools, and any MCP client can call them.</p>
<ul>
- <li><b>12 tools</b> — search, index (JSON/CSV/XML/Markdown), collections,
schema</li>
+ <li><b>15 tools</b> — search, index (JSON/CSV/XML/Markdown), collections,
aliases, schema</li>
<li><b>2 resources</b> — live collection list, live schema</li>
<li><b>6 prompts</b> — guided workflows your client may surface as slash
commands</li>
</ul>
@@ -132,14 +132,15 @@ tbody tr:last-child td{border-bottom:none}
<section class="slide">
<p class="num">03 — Ten minutes, start to query</p>
<h2>No clone, no build</h2>
- <pre><code><span class="tok-c"># 1. Solr — SolrCloud in one container</span>
-docker run -d --name solr-mcp-demo -p 8983:8983 \
+ <pre><code><span class="tok-c"># 1. Solr — SolrCloud in one container, on
localhost only</span>
+docker network create solr-mcp
+docker run -d --name solr-mcp-demo --network=solr-mcp -p 127.0.0.1:8983:8983 \
solr:9-slim solr start -c -f
<span class="tok-c"># 2. The server — Claude Code shown; every client is on
the card</span>
claude mcp add solr-mcp -- docker run -i --rm \
- --add-host=host.docker.internal:host-gateway \
- -e SOLR_URL=http://host.docker.internal:8983/solr/ \
+ --network=solr-mcp \
+ -e SOLR_URL=http://solr-mcp-demo:8983/solr/ \
ghcr.io/adityamparikh/solr-mcp:coc2026</code></pre>
<p>Then talk to it. Claude Desktop, Claude Code, Codex, ChatGPT, VS Code /
Copilot, Cursor, Zed, IntelliJ,
or MCP Inspector — the card has the exact block for each.</p>
diff --git a/docs/events/coc2026-glasgow/site/table-card.html
b/docs/events/coc2026-glasgow/site/table-card.html
index 1640dc36..69a73864 100644
--- a/docs/events/coc2026-glasgow/site/table-card.html
+++ b/docs/events/coc2026-glasgow/site/table-card.html
@@ -62,14 +62,14 @@
<img class="coc-mark"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnYAAADNCAYAAAA1xj1mAABy4UlEQVR4XuydCXwcZd3Hg7x4veKNByLN7k6yc21aDLeiFUFREYE2SQERVCyK8EpfsG2yc22SHlCoioKkSVrAu4qviqIcXqCAUJA2V48cvQu9jxy72ST7/v8zs+3kye7OzO7OZtM+38/n/0mbzHPMzHP85jn+T0kJhUKhUCgUCoVCoVAoFAqFQqFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBQKhZInTiJ/QaFQKBQKhUIpchKrS06OP8xcEF/JLB1a4X9yaEXgX0NNgefg519jzYGfjTxU9pXog/4yMhyFQqFQKBQKpYiIN5ddOtzM/D3WEhhJPFyWGFvFJMZWHrME/B9/P9LC7IHrftjf7Hs/GQeFQqFQKBQKZRLZ2XT6W+OtgbtHVjIxF
[...]
<p class="eyebrow">Community over Code 2026 · Glasgow</p>
<h1>Talk to <em>Apache Solr</em><br>in plain English</h1>
- <p class="sub">An MCP server that hands your AI assistant twelve Solr tools.
Ten minutes from nothing installed to faceted queries.</p>
+ <p class="sub">An MCP server that hands your AI assistant fifteen Solr
tools. Ten minutes from nothing installed to faceted queries.</p>
<img class="qr"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iOTAwIiBjbGFzcz0ic2Vnbm8iPjxnIHRyYW5zZm9ybT0ic2NhbGUoMjApIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDQ1djQ1aC00NXoiLz48cGF0aCBjbGFzcz0icXJsaW5lIiBzdHJva2U9IiMxNTE3MWEiIGQ9Ik00IDQuNWg3bTMgMGgybTEgMGgxbTEgMGgxbTMgMGgybTIgMGgxbTIgMGgxbTMgMGg3bS0zNyAxaDFtNSAwaDFtMSAwaDJtMiAwaDFtMiAwaDFtMiAwaDFtMiAwaDFtMSAwaDFtMSAwaDJtMyA
[...]
<p class="scan">Scan to get started</p>
<div class="steps">
<div class="step"><span class="n">1</span><span class="t">Start Solr — one
<code>docker run</code>, no clone</span></div>
- <div class="step"><span class="n">2</span><span class="t">Connect your
assistant — Claude, Codex, Copilot, Cursor, Zed, IntelliJ or MCP
Inspector</span></div>
+ <div class="step"><span class="n">2</span><span class="t">Connect your
assistant — Claude, Codex, ChatGPT, Copilot, Cursor, Zed, IntelliJ or MCP
Inspector</span></div>
<div class="step"><span class="n">3</span><span class="t">Index 61 shows
and ask it questions</span></div>
</div>
diff --git a/docs/events/coc2026-glasgow/solr-mcp-table-card.html
b/docs/events/coc2026-glasgow/solr-mcp-table-card.html
index 1640dc36..69a73864 100644
--- a/docs/events/coc2026-glasgow/solr-mcp-table-card.html
+++ b/docs/events/coc2026-glasgow/solr-mcp-table-card.html
@@ -62,14 +62,14 @@
<img class="coc-mark"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnYAAADNCAYAAAA1xj1mAABy4UlEQVR4XuydCXwcZd3Hg7x4veKNByLN7k6yc21aDLeiFUFREYE2SQERVCyK8EpfsG2yc22SHlCoioKkSVrAu4qviqIcXqCAUJA2V48cvQu9jxy72ST7/v8zs+3kye7OzO7OZtM+38/n/0mbzHPMzHP85jn+T0kJhUKhUCgUCoVCoVAoFAqFQqFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBQKhZInTiJ/QaFQKBQKhUIpchKrS06OP8xcEF/JLB1a4X9yaEXgX0NNgefg519jzYGfjTxU9pXog/4yMhyFQqFQKBQKpYiIN5ddOtzM/D3WEhhJPFyWGFvFJMZWHrME/B9/P9LC7IHrftjf7Hs/GQeFQqFQKBQKZRLZ2XT6W+OtgbtHVjIxF
[...]
<p class="eyebrow">Community over Code 2026 · Glasgow</p>
<h1>Talk to <em>Apache Solr</em><br>in plain English</h1>
- <p class="sub">An MCP server that hands your AI assistant twelve Solr tools.
Ten minutes from nothing installed to faceted queries.</p>
+ <p class="sub">An MCP server that hands your AI assistant fifteen Solr
tools. Ten minutes from nothing installed to faceted queries.</p>
<img class="qr"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5MDAiIGhlaWdodD0iOTAwIiBjbGFzcz0ic2Vnbm8iPjxnIHRyYW5zZm9ybT0ic2NhbGUoMjApIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMCAwaDQ1djQ1aC00NXoiLz48cGF0aCBjbGFzcz0icXJsaW5lIiBzdHJva2U9IiMxNTE3MWEiIGQ9Ik00IDQuNWg3bTMgMGgybTEgMGgxbTEgMGgxbTMgMGgybTIgMGgxbTIgMGgxbTMgMGg3bS0zNyAxaDFtNSAwaDFtMSAwaDJtMiAwaDFtMiAwaDFtMiAwaDFtMiAwaDFtMSAwaDFtMSAwaDJtMyA
[...]
<p class="scan">Scan to get started</p>
<div class="steps">
<div class="step"><span class="n">1</span><span class="t">Start Solr — one
<code>docker run</code>, no clone</span></div>
- <div class="step"><span class="n">2</span><span class="t">Connect your
assistant — Claude, Codex, Copilot, Cursor, Zed, IntelliJ or MCP
Inspector</span></div>
+ <div class="step"><span class="n">2</span><span class="t">Connect your
assistant — Claude, Codex, ChatGPT, Copilot, Cursor, Zed, IntelliJ or MCP
Inspector</span></div>
<div class="step"><span class="n">3</span><span class="t">Index 61 shows
and ask it questions</span></div>
</div>