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://&lt;your-tunnel&gt;/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://&lt;your-tunnel&gt;/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">&lt;add&gt;&lt;doc&gt;&lt;field name="…"&gt;</code>.
+            The server checks that it is an <code 
class="inline">&lt;add&gt;</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:
-&lt;shows&gt;
-  &lt;show&gt;
-    &lt;id&gt;hbo-001&lt;/id&gt;
-    &lt;title&gt;Game of Thrones&lt;/title&gt;
-    &lt;platform&gt;HBO Max&lt;/platform&gt;
-    &lt;genres&gt;Fantasy&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Adventure&lt;/genres&gt;
-    &lt;release_year&gt;2011&lt;/release_year&gt;
-    &lt;end_year&gt;2019&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;8&lt;/seasons&gt;
-    &lt;episodes&gt;73&lt;/episodes&gt;
-    &lt;creators&gt;David Benioff&lt;/creators&gt;
-    &lt;creators&gt;D.B. Weiss&lt;/creators&gt;
-    &lt;cast&gt;Emilia Clarke&lt;/cast&gt;
-    &lt;cast&gt;Peter Dinklage&lt;/cast&gt;
-    &lt;cast&gt;Kit Harington&lt;/cast&gt;
-    &lt;cast&gt;Lena Headey&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;9.2&lt;/imdb_rating&gt;
-    &lt;description&gt;Nine noble families fight for control over the lands of 
Westeros, while an ancient enemy returns after being dormant for 
millennia.&lt;/description&gt;
-    &lt;tags&gt;fantasy&lt;/tags&gt;
-    &lt;tags&gt;dragons&lt;/tags&gt;
-    &lt;tags&gt;epic&lt;/tags&gt;
-    &lt;tags&gt;george-rr-martin&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;netflix-001&lt;/id&gt;
-    &lt;title&gt;Stranger Things&lt;/title&gt;
-    &lt;platform&gt;Netflix&lt;/platform&gt;
-    &lt;genres&gt;Sci-Fi&lt;/genres&gt;
-    &lt;genres&gt;Horror&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;release_year&gt;2016&lt;/release_year&gt;
-    &lt;end_year&gt;2025&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;5&lt;/seasons&gt;
-    &lt;episodes&gt;42&lt;/episodes&gt;
-    &lt;creators&gt;Matt Duffer&lt;/creators&gt;
-    &lt;creators&gt;Ross Duffer&lt;/creators&gt;
-    &lt;cast&gt;Millie Bobby Brown&lt;/cast&gt;
-    &lt;cast&gt;Finn Wolfhard&lt;/cast&gt;
-    &lt;cast&gt;Winona Ryder&lt;/cast&gt;
-    &lt;cast&gt;David Harbour&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-14&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.7&lt;/imdb_rating&gt;
-    &lt;description&gt;A group of kids in 1980s Indiana uncover supernatural 
mysteries and government conspiracies tied to a parallel 
dimension.&lt;/description&gt;
-    &lt;tags&gt;80s&lt;/tags&gt;
-    &lt;tags&gt;supernatural&lt;/tags&gt;
-    &lt;tags&gt;coming-of-age&lt;/tags&gt;
-    &lt;tags&gt;monsters&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;hulu-001&lt;/id&gt;
-    &lt;title&gt;The Handmaid&#x27;s Tale&lt;/title&gt;
-    &lt;platform&gt;Hulu&lt;/platform&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Sci-Fi&lt;/genres&gt;
-    &lt;genres&gt;Dystopian&lt;/genres&gt;
-    &lt;release_year&gt;2017&lt;/release_year&gt;
-    &lt;end_year&gt;2025&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;6&lt;/seasons&gt;
-    &lt;episodes&gt;66&lt;/episodes&gt;
-    &lt;creators&gt;Bruce Miller&lt;/creators&gt;
-    &lt;cast&gt;Elisabeth Moss&lt;/cast&gt;
-    &lt;cast&gt;Joseph Fiennes&lt;/cast&gt;
-    &lt;cast&gt;Yvonne Strahovski&lt;/cast&gt;
-    &lt;cast&gt;Samira Wiley&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.4&lt;/imdb_rating&gt;
-    &lt;description&gt;Set in a dystopian future, a woman is forced to live as 
a concubine under a fundamentalist theocratic dictatorship.&lt;/description&gt;
-    &lt;tags&gt;dystopian&lt;/tags&gt;
-    &lt;tags&gt;feminist&lt;/tags&gt;
-    &lt;tags&gt;atwood&lt;/tags&gt;
-    &lt;tags&gt;theocracy&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;disney-001&lt;/id&gt;
-    &lt;title&gt;The Mandalorian&lt;/title&gt;
-    &lt;platform&gt;Disney+&lt;/platform&gt;
-    &lt;genres&gt;Sci-Fi&lt;/genres&gt;
-    &lt;genres&gt;Action&lt;/genres&gt;
-    &lt;genres&gt;Adventure&lt;/genres&gt;
-    &lt;release_year&gt;2019&lt;/release_year&gt;
-    &lt;status&gt;Ongoing&lt;/status&gt;
-    &lt;seasons&gt;3&lt;/seasons&gt;
-    &lt;episodes&gt;24&lt;/episodes&gt;
-    &lt;creators&gt;Jon Favreau&lt;/creators&gt;
-    &lt;cast&gt;Pedro Pascal&lt;/cast&gt;
-    &lt;cast&gt;Carl Weathers&lt;/cast&gt;
-    &lt;cast&gt;Giancarlo Esposito&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-14&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.6&lt;/imdb_rating&gt;
-    &lt;description&gt;The travels of a lone bounty hunter in the outer 
reaches of the galaxy, far from the authority of the New 
Republic.&lt;/description&gt;
-    &lt;tags&gt;star-wars&lt;/tags&gt;
-    &lt;tags&gt;space-western&lt;/tags&gt;
-    &lt;tags&gt;grogu&lt;/tags&gt;
-    &lt;tags&gt;baby-yoda&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;hbo-002&lt;/id&gt;
-    &lt;title&gt;Succession&lt;/title&gt;
-    &lt;platform&gt;HBO Max&lt;/platform&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Comedy&lt;/genres&gt;
-    &lt;release_year&gt;2018&lt;/release_year&gt;
-    &lt;end_year&gt;2023&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;4&lt;/seasons&gt;
-    &lt;episodes&gt;39&lt;/episodes&gt;
-    &lt;creators&gt;Jesse Armstrong&lt;/creators&gt;
-    &lt;cast&gt;Brian Cox&lt;/cast&gt;
-    &lt;cast&gt;Jeremy Strong&lt;/cast&gt;
-    &lt;cast&gt;Kieran Culkin&lt;/cast&gt;
-    &lt;cast&gt;Sarah Snook&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.9&lt;/imdb_rating&gt;
-    &lt;description&gt;The Roy family controls the biggest media and 
entertainment company in the world, but their patriarch&#x27;s health is 
failing.&lt;/description&gt;
-    &lt;tags&gt;media&lt;/tags&gt;
-    &lt;tags&gt;family-drama&lt;/tags&gt;
-    &lt;tags&gt;satire&lt;/tags&gt;
-    &lt;tags&gt;wealth&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;prime-001&lt;/id&gt;
-    &lt;title&gt;The Boys&lt;/title&gt;
-    &lt;platform&gt;Amazon Prime Video&lt;/platform&gt;
-    &lt;genres&gt;Action&lt;/genres&gt;
-    &lt;genres&gt;Sci-Fi&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;release_year&gt;2019&lt;/release_year&gt;
-    &lt;status&gt;Ongoing&lt;/status&gt;
-    &lt;seasons&gt;4&lt;/seasons&gt;
-    &lt;episodes&gt;32&lt;/episodes&gt;
-    &lt;creators&gt;Eric Kripke&lt;/creators&gt;
-    &lt;cast&gt;Karl Urban&lt;/cast&gt;
-    &lt;cast&gt;Jack Quaid&lt;/cast&gt;
-    &lt;cast&gt;Antony Starr&lt;/cast&gt;
-    &lt;cast&gt;Erin Moriarty&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.7&lt;/imdb_rating&gt;
-    &lt;description&gt;A group of vigilantes set out to take down corrupt 
superheroes who abuse their powers.&lt;/description&gt;
-    &lt;tags&gt;superheroes&lt;/tags&gt;
-    &lt;tags&gt;satire&lt;/tags&gt;
-    &lt;tags&gt;violent&lt;/tags&gt;
-    &lt;tags&gt;comic-adaptation&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;netflix-002&lt;/id&gt;
-    &lt;title&gt;The Crown&lt;/title&gt;
-    &lt;platform&gt;Netflix&lt;/platform&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Historical&lt;/genres&gt;
-    &lt;genres&gt;Biography&lt;/genres&gt;
-    &lt;release_year&gt;2016&lt;/release_year&gt;
-    &lt;end_year&gt;2023&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;6&lt;/seasons&gt;
-    &lt;episodes&gt;60&lt;/episodes&gt;
-    &lt;creators&gt;Peter Morgan&lt;/creators&gt;
-    &lt;cast&gt;Claire Foy&lt;/cast&gt;
-    &lt;cast&gt;Olivia Colman&lt;/cast&gt;
-    &lt;cast&gt;Imelda Staunton&lt;/cast&gt;
-    &lt;cast&gt;Matt Smith&lt;/cast&gt;
-    &lt;country&gt;UK&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.6&lt;/imdb_rating&gt;
-    &lt;description&gt;The reign of Queen Elizabeth II from her wedding in 
1947 through the early 21st century.&lt;/description&gt;
-    &lt;tags&gt;royalty&lt;/tags&gt;
-    &lt;tags&gt;british&lt;/tags&gt;
-    &lt;tags&gt;period-drama&lt;/tags&gt;
-    &lt;tags&gt;politics&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;prime-002&lt;/id&gt;
-    &lt;title&gt;The Marvelous Mrs. Maisel&lt;/title&gt;
-    &lt;platform&gt;Amazon Prime Video&lt;/platform&gt;
-    &lt;genres&gt;Comedy&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Period&lt;/genres&gt;
-    &lt;release_year&gt;2017&lt;/release_year&gt;
-    &lt;end_year&gt;2023&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;5&lt;/seasons&gt;
-    &lt;episodes&gt;43&lt;/episodes&gt;
-    &lt;creators&gt;Amy Sherman-Palladino&lt;/creators&gt;
-    &lt;cast&gt;Rachel Brosnahan&lt;/cast&gt;
-    &lt;cast&gt;Alex Borstein&lt;/cast&gt;
-    &lt;cast&gt;Michael Zegen&lt;/cast&gt;
-    &lt;cast&gt;Tony Shalhoub&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.7&lt;/imdb_rating&gt;
-    &lt;description&gt;A 1950s New York housewife discovers she has a talent 
for stand-up comedy.&lt;/description&gt;
-    &lt;tags&gt;50s&lt;/tags&gt;
-    &lt;tags&gt;stand-up&lt;/tags&gt;
-    &lt;tags&gt;feminist&lt;/tags&gt;
-    &lt;tags&gt;new-york&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;hbo-003&lt;/id&gt;
-    &lt;title&gt;The Last of Us&lt;/title&gt;
-    &lt;platform&gt;HBO Max&lt;/platform&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Horror&lt;/genres&gt;
-    &lt;genres&gt;Sci-Fi&lt;/genres&gt;
-    &lt;release_year&gt;2023&lt;/release_year&gt;
-    &lt;status&gt;Ongoing&lt;/status&gt;
-    &lt;seasons&gt;2&lt;/seasons&gt;
-    &lt;episodes&gt;16&lt;/episodes&gt;
-    &lt;creators&gt;Craig Mazin&lt;/creators&gt;
-    &lt;creators&gt;Neil Druckmann&lt;/creators&gt;
-    &lt;cast&gt;Pedro Pascal&lt;/cast&gt;
-    &lt;cast&gt;Bella Ramsey&lt;/cast&gt;
-    &lt;cast&gt;Anna Torv&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.7&lt;/imdb_rating&gt;
-    &lt;description&gt;After a global pandemic destroys civilization, a 
hardened survivor takes charge of a 14-year-old girl who may be humanity&#x27;s 
last hope.&lt;/description&gt;
-    &lt;tags&gt;post-apocalyptic&lt;/tags&gt;
-    &lt;tags&gt;zombies&lt;/tags&gt;
-    &lt;tags&gt;video-game-adaptation&lt;/tags&gt;
-    &lt;tags&gt;fungal&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;hulu-002&lt;/id&gt;
-    &lt;title&gt;The Bear&lt;/title&gt;
-    &lt;platform&gt;Hulu&lt;/platform&gt;
-    &lt;genres&gt;Comedy&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;release_year&gt;2022&lt;/release_year&gt;
-    &lt;status&gt;Ongoing&lt;/status&gt;
-    &lt;seasons&gt;3&lt;/seasons&gt;
-    &lt;episodes&gt;28&lt;/episodes&gt;
-    &lt;creators&gt;Christopher Storer&lt;/creators&gt;
-    &lt;cast&gt;Jeremy Allen White&lt;/cast&gt;
-    &lt;cast&gt;Ebon Moss-Bachrach&lt;/cast&gt;
-    &lt;cast&gt;Ayo Edebiri&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.6&lt;/imdb_rating&gt;
-    &lt;description&gt;A young chef from the fine dining world returns to 
Chicago to run his family&#x27;s sandwich shop after a heartbreaking 
death.&lt;/description&gt;
-    &lt;tags&gt;cooking&lt;/tags&gt;
-    &lt;tags&gt;chicago&lt;/tags&gt;
-    &lt;tags&gt;family&lt;/tags&gt;
-    &lt;tags&gt;anxiety&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;netflix-003&lt;/id&gt;
-    &lt;title&gt;Squid Game&lt;/title&gt;
-    &lt;platform&gt;Netflix&lt;/platform&gt;
-    &lt;genres&gt;Thriller&lt;/genres&gt;
-    &lt;genres&gt;Drama&lt;/genres&gt;
-    &lt;genres&gt;Survival&lt;/genres&gt;
-    &lt;release_year&gt;2021&lt;/release_year&gt;
-    &lt;end_year&gt;2025&lt;/end_year&gt;
-    &lt;status&gt;Ended&lt;/status&gt;
-    &lt;seasons&gt;3&lt;/seasons&gt;
-    &lt;episodes&gt;22&lt;/episodes&gt;
-    &lt;creators&gt;Hwang Dong-hyuk&lt;/creators&gt;
-    &lt;cast&gt;Lee Jung-jae&lt;/cast&gt;
-    &lt;cast&gt;Park Hae-soo&lt;/cast&gt;
-    &lt;cast&gt;Wi Ha-joon&lt;/cast&gt;
-    &lt;cast&gt;HoYeon Jung&lt;/cast&gt;
-    &lt;country&gt;South Korea&lt;/country&gt;
-    &lt;language&gt;Korean&lt;/language&gt;
-    &lt;rating&gt;TV-MA&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.0&lt;/imdb_rating&gt;
-    &lt;description&gt;Hundreds of cash-strapped contestants accept an 
invitation to compete in deadly children&#x27;s games for a tempting 
prize.&lt;/description&gt;
-    &lt;tags&gt;korean&lt;/tags&gt;
-    &lt;tags&gt;survival&lt;/tags&gt;
-    &lt;tags&gt;dystopian&lt;/tags&gt;
-    &lt;tags&gt;social-commentary&lt;/tags&gt;
-  &lt;/show&gt;
-  &lt;show&gt;
-    &lt;id&gt;netflix-004&lt;/id&gt;
-    &lt;title&gt;Wednesday&lt;/title&gt;
-    &lt;platform&gt;Netflix&lt;/platform&gt;
-    &lt;genres&gt;Comedy&lt;/genres&gt;
-    &lt;genres&gt;Horror&lt;/genres&gt;
-    &lt;genres&gt;Mystery&lt;/genres&gt;
-    &lt;release_year&gt;2022&lt;/release_year&gt;
-    &lt;status&gt;Ongoing&lt;/status&gt;
-    &lt;seasons&gt;2&lt;/seasons&gt;
-    &lt;episodes&gt;16&lt;/episodes&gt;
-    &lt;creators&gt;Alfred Gough&lt;/creators&gt;
-    &lt;creators&gt;Miles Millar&lt;/creators&gt;
-    &lt;cast&gt;Jenna Ortega&lt;/cast&gt;
-    &lt;cast&gt;Catherine Zeta-Jones&lt;/cast&gt;
-    &lt;cast&gt;Luis Guzmán&lt;/cast&gt;
-    &lt;cast&gt;Gwendoline Christie&lt;/cast&gt;
-    &lt;country&gt;USA&lt;/country&gt;
-    &lt;language&gt;English&lt;/language&gt;
-    &lt;rating&gt;TV-14&lt;/rating&gt;
-    &lt;imdb_rating&gt;8.1&lt;/imdb_rating&gt;
-    &lt;description&gt;Wednesday Addams navigates a supernatural boarding 
school while solving a murder mystery.&lt;/description&gt;
-    &lt;tags&gt;gothic&lt;/tags&gt;
-    &lt;tags&gt;teen&lt;/tags&gt;
-    &lt;tags&gt;supernatural&lt;/tags&gt;
-    &lt;tags&gt;addams-family&lt;/tags&gt;
-  &lt;/show&gt;
-&lt;/shows&gt;</code></pre></div>
+&lt;add&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;hbo-001&lt;/field&gt;
+    &lt;field name="title"&gt;Game of Thrones&lt;/field&gt;
+    &lt;field name="platform"&gt;HBO Max&lt;/field&gt;
+    &lt;field name="genres"&gt;Fantasy&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Adventure&lt;/field&gt;
+    &lt;field name="release_year"&gt;2011&lt;/field&gt;
+    &lt;field name="end_year"&gt;2019&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;8&lt;/field&gt;
+    &lt;field name="episodes"&gt;73&lt;/field&gt;
+    &lt;field name="creators"&gt;David Benioff&lt;/field&gt;
+    &lt;field name="creators"&gt;D.B. Weiss&lt;/field&gt;
+    &lt;field name="cast"&gt;Emilia Clarke&lt;/field&gt;
+    &lt;field name="cast"&gt;Peter Dinklage&lt;/field&gt;
+    &lt;field name="cast"&gt;Kit Harington&lt;/field&gt;
+    &lt;field name="cast"&gt;Lena Headey&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;9.2&lt;/field&gt;
+    &lt;field name="description"&gt;Nine noble families fight for control over 
the lands of Westeros, while an ancient enemy returns after being dormant for 
millennia.&lt;/field&gt;
+    &lt;field name="tags"&gt;fantasy&lt;/field&gt;
+    &lt;field name="tags"&gt;dragons&lt;/field&gt;
+    &lt;field name="tags"&gt;epic&lt;/field&gt;
+    &lt;field name="tags"&gt;george-rr-martin&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;netflix-001&lt;/field&gt;
+    &lt;field name="title"&gt;Stranger Things&lt;/field&gt;
+    &lt;field name="platform"&gt;Netflix&lt;/field&gt;
+    &lt;field name="genres"&gt;Sci-Fi&lt;/field&gt;
+    &lt;field name="genres"&gt;Horror&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="release_year"&gt;2016&lt;/field&gt;
+    &lt;field name="end_year"&gt;2025&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;5&lt;/field&gt;
+    &lt;field name="episodes"&gt;42&lt;/field&gt;
+    &lt;field name="creators"&gt;Matt Duffer&lt;/field&gt;
+    &lt;field name="creators"&gt;Ross Duffer&lt;/field&gt;
+    &lt;field name="cast"&gt;Millie Bobby Brown&lt;/field&gt;
+    &lt;field name="cast"&gt;Finn Wolfhard&lt;/field&gt;
+    &lt;field name="cast"&gt;Winona Ryder&lt;/field&gt;
+    &lt;field name="cast"&gt;David Harbour&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-14&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.7&lt;/field&gt;
+    &lt;field name="description"&gt;A group of kids in 1980s Indiana uncover 
supernatural mysteries and government conspiracies tied to a parallel 
dimension.&lt;/field&gt;
+    &lt;field name="tags"&gt;80s&lt;/field&gt;
+    &lt;field name="tags"&gt;supernatural&lt;/field&gt;
+    &lt;field name="tags"&gt;coming-of-age&lt;/field&gt;
+    &lt;field name="tags"&gt;monsters&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;hulu-001&lt;/field&gt;
+    &lt;field name="title"&gt;The Handmaid's Tale&lt;/field&gt;
+    &lt;field name="platform"&gt;Hulu&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Sci-Fi&lt;/field&gt;
+    &lt;field name="genres"&gt;Dystopian&lt;/field&gt;
+    &lt;field name="release_year"&gt;2017&lt;/field&gt;
+    &lt;field name="end_year"&gt;2025&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;6&lt;/field&gt;
+    &lt;field name="episodes"&gt;66&lt;/field&gt;
+    &lt;field name="creators"&gt;Bruce Miller&lt;/field&gt;
+    &lt;field name="cast"&gt;Elisabeth Moss&lt;/field&gt;
+    &lt;field name="cast"&gt;Joseph Fiennes&lt;/field&gt;
+    &lt;field name="cast"&gt;Yvonne Strahovski&lt;/field&gt;
+    &lt;field name="cast"&gt;Samira Wiley&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.4&lt;/field&gt;
+    &lt;field name="description"&gt;Set in a dystopian future, a woman is 
forced to live as a concubine under a fundamentalist theocratic 
dictatorship.&lt;/field&gt;
+    &lt;field name="tags"&gt;dystopian&lt;/field&gt;
+    &lt;field name="tags"&gt;feminist&lt;/field&gt;
+    &lt;field name="tags"&gt;atwood&lt;/field&gt;
+    &lt;field name="tags"&gt;theocracy&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;disney-001&lt;/field&gt;
+    &lt;field name="title"&gt;The Mandalorian&lt;/field&gt;
+    &lt;field name="platform"&gt;Disney+&lt;/field&gt;
+    &lt;field name="genres"&gt;Sci-Fi&lt;/field&gt;
+    &lt;field name="genres"&gt;Action&lt;/field&gt;
+    &lt;field name="genres"&gt;Adventure&lt;/field&gt;
+    &lt;field name="release_year"&gt;2019&lt;/field&gt;
+    &lt;field name="status"&gt;Ongoing&lt;/field&gt;
+    &lt;field name="seasons"&gt;3&lt;/field&gt;
+    &lt;field name="episodes"&gt;24&lt;/field&gt;
+    &lt;field name="creators"&gt;Jon Favreau&lt;/field&gt;
+    &lt;field name="cast"&gt;Pedro Pascal&lt;/field&gt;
+    &lt;field name="cast"&gt;Carl Weathers&lt;/field&gt;
+    &lt;field name="cast"&gt;Giancarlo Esposito&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-14&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.6&lt;/field&gt;
+    &lt;field name="description"&gt;The travels of a lone bounty hunter in the 
outer reaches of the galaxy, far from the authority of the New 
Republic.&lt;/field&gt;
+    &lt;field name="tags"&gt;star-wars&lt;/field&gt;
+    &lt;field name="tags"&gt;space-western&lt;/field&gt;
+    &lt;field name="tags"&gt;grogu&lt;/field&gt;
+    &lt;field name="tags"&gt;baby-yoda&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;hbo-002&lt;/field&gt;
+    &lt;field name="title"&gt;Succession&lt;/field&gt;
+    &lt;field name="platform"&gt;HBO Max&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Comedy&lt;/field&gt;
+    &lt;field name="release_year"&gt;2018&lt;/field&gt;
+    &lt;field name="end_year"&gt;2023&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;4&lt;/field&gt;
+    &lt;field name="episodes"&gt;39&lt;/field&gt;
+    &lt;field name="creators"&gt;Jesse Armstrong&lt;/field&gt;
+    &lt;field name="cast"&gt;Brian Cox&lt;/field&gt;
+    &lt;field name="cast"&gt;Jeremy Strong&lt;/field&gt;
+    &lt;field name="cast"&gt;Kieran Culkin&lt;/field&gt;
+    &lt;field name="cast"&gt;Sarah Snook&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.9&lt;/field&gt;
+    &lt;field name="description"&gt;The Roy family controls the biggest media 
and entertainment company in the world, but their patriarch's health is 
failing.&lt;/field&gt;
+    &lt;field name="tags"&gt;media&lt;/field&gt;
+    &lt;field name="tags"&gt;family-drama&lt;/field&gt;
+    &lt;field name="tags"&gt;satire&lt;/field&gt;
+    &lt;field name="tags"&gt;wealth&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;prime-001&lt;/field&gt;
+    &lt;field name="title"&gt;The Boys&lt;/field&gt;
+    &lt;field name="platform"&gt;Amazon Prime Video&lt;/field&gt;
+    &lt;field name="genres"&gt;Action&lt;/field&gt;
+    &lt;field name="genres"&gt;Sci-Fi&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="release_year"&gt;2019&lt;/field&gt;
+    &lt;field name="status"&gt;Ongoing&lt;/field&gt;
+    &lt;field name="seasons"&gt;4&lt;/field&gt;
+    &lt;field name="episodes"&gt;32&lt;/field&gt;
+    &lt;field name="creators"&gt;Eric Kripke&lt;/field&gt;
+    &lt;field name="cast"&gt;Karl Urban&lt;/field&gt;
+    &lt;field name="cast"&gt;Jack Quaid&lt;/field&gt;
+    &lt;field name="cast"&gt;Antony Starr&lt;/field&gt;
+    &lt;field name="cast"&gt;Erin Moriarty&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.7&lt;/field&gt;
+    &lt;field name="description"&gt;A group of vigilantes set out to take down 
corrupt superheroes who abuse their powers.&lt;/field&gt;
+    &lt;field name="tags"&gt;superheroes&lt;/field&gt;
+    &lt;field name="tags"&gt;satire&lt;/field&gt;
+    &lt;field name="tags"&gt;violent&lt;/field&gt;
+    &lt;field name="tags"&gt;comic-adaptation&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;netflix-002&lt;/field&gt;
+    &lt;field name="title"&gt;The Crown&lt;/field&gt;
+    &lt;field name="platform"&gt;Netflix&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Historical&lt;/field&gt;
+    &lt;field name="genres"&gt;Biography&lt;/field&gt;
+    &lt;field name="release_year"&gt;2016&lt;/field&gt;
+    &lt;field name="end_year"&gt;2023&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;6&lt;/field&gt;
+    &lt;field name="episodes"&gt;60&lt;/field&gt;
+    &lt;field name="creators"&gt;Peter Morgan&lt;/field&gt;
+    &lt;field name="cast"&gt;Claire Foy&lt;/field&gt;
+    &lt;field name="cast"&gt;Olivia Colman&lt;/field&gt;
+    &lt;field name="cast"&gt;Imelda Staunton&lt;/field&gt;
+    &lt;field name="cast"&gt;Matt Smith&lt;/field&gt;
+    &lt;field name="country"&gt;UK&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.6&lt;/field&gt;
+    &lt;field name="description"&gt;The reign of Queen Elizabeth II from her 
wedding in 1947 through the early 21st century.&lt;/field&gt;
+    &lt;field name="tags"&gt;royalty&lt;/field&gt;
+    &lt;field name="tags"&gt;british&lt;/field&gt;
+    &lt;field name="tags"&gt;period-drama&lt;/field&gt;
+    &lt;field name="tags"&gt;politics&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;prime-002&lt;/field&gt;
+    &lt;field name="title"&gt;The Marvelous Mrs. Maisel&lt;/field&gt;
+    &lt;field name="platform"&gt;Amazon Prime Video&lt;/field&gt;
+    &lt;field name="genres"&gt;Comedy&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Period&lt;/field&gt;
+    &lt;field name="release_year"&gt;2017&lt;/field&gt;
+    &lt;field name="end_year"&gt;2023&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;5&lt;/field&gt;
+    &lt;field name="episodes"&gt;43&lt;/field&gt;
+    &lt;field name="creators"&gt;Amy Sherman-Palladino&lt;/field&gt;
+    &lt;field name="cast"&gt;Rachel Brosnahan&lt;/field&gt;
+    &lt;field name="cast"&gt;Alex Borstein&lt;/field&gt;
+    &lt;field name="cast"&gt;Michael Zegen&lt;/field&gt;
+    &lt;field name="cast"&gt;Tony Shalhoub&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.7&lt;/field&gt;
+    &lt;field name="description"&gt;A 1950s New York housewife discovers she 
has a talent for stand-up comedy.&lt;/field&gt;
+    &lt;field name="tags"&gt;50s&lt;/field&gt;
+    &lt;field name="tags"&gt;stand-up&lt;/field&gt;
+    &lt;field name="tags"&gt;feminist&lt;/field&gt;
+    &lt;field name="tags"&gt;new-york&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;hbo-003&lt;/field&gt;
+    &lt;field name="title"&gt;The Last of Us&lt;/field&gt;
+    &lt;field name="platform"&gt;HBO Max&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Horror&lt;/field&gt;
+    &lt;field name="genres"&gt;Sci-Fi&lt;/field&gt;
+    &lt;field name="release_year"&gt;2023&lt;/field&gt;
+    &lt;field name="status"&gt;Ongoing&lt;/field&gt;
+    &lt;field name="seasons"&gt;2&lt;/field&gt;
+    &lt;field name="episodes"&gt;16&lt;/field&gt;
+    &lt;field name="creators"&gt;Craig Mazin&lt;/field&gt;
+    &lt;field name="creators"&gt;Neil Druckmann&lt;/field&gt;
+    &lt;field name="cast"&gt;Pedro Pascal&lt;/field&gt;
+    &lt;field name="cast"&gt;Bella Ramsey&lt;/field&gt;
+    &lt;field name="cast"&gt;Anna Torv&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.7&lt;/field&gt;
+    &lt;field name="description"&gt;After a global pandemic destroys 
civilization, a hardened survivor takes charge of a 14-year-old girl who may be 
humanity's last hope.&lt;/field&gt;
+    &lt;field name="tags"&gt;post-apocalyptic&lt;/field&gt;
+    &lt;field name="tags"&gt;zombies&lt;/field&gt;
+    &lt;field name="tags"&gt;video-game-adaptation&lt;/field&gt;
+    &lt;field name="tags"&gt;fungal&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;hulu-002&lt;/field&gt;
+    &lt;field name="title"&gt;The Bear&lt;/field&gt;
+    &lt;field name="platform"&gt;Hulu&lt;/field&gt;
+    &lt;field name="genres"&gt;Comedy&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="release_year"&gt;2022&lt;/field&gt;
+    &lt;field name="status"&gt;Ongoing&lt;/field&gt;
+    &lt;field name="seasons"&gt;3&lt;/field&gt;
+    &lt;field name="episodes"&gt;28&lt;/field&gt;
+    &lt;field name="creators"&gt;Christopher Storer&lt;/field&gt;
+    &lt;field name="cast"&gt;Jeremy Allen White&lt;/field&gt;
+    &lt;field name="cast"&gt;Ebon Moss-Bachrach&lt;/field&gt;
+    &lt;field name="cast"&gt;Ayo Edebiri&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.6&lt;/field&gt;
+    &lt;field name="description"&gt;A young chef from the fine dining world 
returns to Chicago to run his family's sandwich shop after a heartbreaking 
death.&lt;/field&gt;
+    &lt;field name="tags"&gt;cooking&lt;/field&gt;
+    &lt;field name="tags"&gt;chicago&lt;/field&gt;
+    &lt;field name="tags"&gt;family&lt;/field&gt;
+    &lt;field name="tags"&gt;anxiety&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;netflix-003&lt;/field&gt;
+    &lt;field name="title"&gt;Squid Game&lt;/field&gt;
+    &lt;field name="platform"&gt;Netflix&lt;/field&gt;
+    &lt;field name="genres"&gt;Thriller&lt;/field&gt;
+    &lt;field name="genres"&gt;Drama&lt;/field&gt;
+    &lt;field name="genres"&gt;Survival&lt;/field&gt;
+    &lt;field name="release_year"&gt;2021&lt;/field&gt;
+    &lt;field name="end_year"&gt;2025&lt;/field&gt;
+    &lt;field name="status"&gt;Ended&lt;/field&gt;
+    &lt;field name="seasons"&gt;3&lt;/field&gt;
+    &lt;field name="episodes"&gt;22&lt;/field&gt;
+    &lt;field name="creators"&gt;Hwang Dong-hyuk&lt;/field&gt;
+    &lt;field name="cast"&gt;Lee Jung-jae&lt;/field&gt;
+    &lt;field name="cast"&gt;Park Hae-soo&lt;/field&gt;
+    &lt;field name="cast"&gt;Wi Ha-joon&lt;/field&gt;
+    &lt;field name="cast"&gt;HoYeon Jung&lt;/field&gt;
+    &lt;field name="country"&gt;South Korea&lt;/field&gt;
+    &lt;field name="language"&gt;Korean&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-MA&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.0&lt;/field&gt;
+    &lt;field name="description"&gt;Hundreds of cash-strapped contestants 
accept an invitation to compete in deadly children's games for a tempting 
prize.&lt;/field&gt;
+    &lt;field name="tags"&gt;korean&lt;/field&gt;
+    &lt;field name="tags"&gt;survival&lt;/field&gt;
+    &lt;field name="tags"&gt;dystopian&lt;/field&gt;
+    &lt;field name="tags"&gt;social-commentary&lt;/field&gt;
+  &lt;/doc&gt;
+  &lt;doc&gt;
+    &lt;field name="id"&gt;netflix-004&lt;/field&gt;
+    &lt;field name="title"&gt;Wednesday&lt;/field&gt;
+    &lt;field name="platform"&gt;Netflix&lt;/field&gt;
+    &lt;field name="genres"&gt;Comedy&lt;/field&gt;
+    &lt;field name="genres"&gt;Horror&lt;/field&gt;
+    &lt;field name="genres"&gt;Mystery&lt;/field&gt;
+    &lt;field name="release_year"&gt;2022&lt;/field&gt;
+    &lt;field name="status"&gt;Ongoing&lt;/field&gt;
+    &lt;field name="seasons"&gt;2&lt;/field&gt;
+    &lt;field name="episodes"&gt;16&lt;/field&gt;
+    &lt;field name="creators"&gt;Alfred Gough&lt;/field&gt;
+    &lt;field name="creators"&gt;Miles Millar&lt;/field&gt;
+    &lt;field name="cast"&gt;Jenna Ortega&lt;/field&gt;
+    &lt;field name="cast"&gt;Catherine Zeta-Jones&lt;/field&gt;
+    &lt;field name="cast"&gt;Luis Guzmán&lt;/field&gt;
+    &lt;field name="cast"&gt;Gwendoline Christie&lt;/field&gt;
+    &lt;field name="country"&gt;USA&lt;/field&gt;
+    &lt;field name="language"&gt;English&lt;/field&gt;
+    &lt;field name="rating"&gt;TV-14&lt;/field&gt;
+    &lt;field name="imdb_rating"&gt;8.1&lt;/field&gt;
+    &lt;field name="description"&gt;Wednesday Addams navigates a supernatural 
boarding school while solving a murder mystery.&lt;/field&gt;
+    &lt;field name="tags"&gt;gothic&lt;/field&gt;
+    &lt;field name="tags"&gt;teen&lt;/field&gt;
+    &lt;field name="tags"&gt;supernatural&lt;/field&gt;
+    &lt;field name="tags"&gt;addams-family&lt;/field&gt;
+  &lt;/doc&gt;
+&lt;/add&gt;</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 
&quot;dragon&quot; 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 &quot;a group of&quot;.">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 &quot;a group of&quot;.">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>&lt;add&gt;</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&gt;&amp;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>
 

Reply via email to