diff --git a/.github/workflows/build-pelican.yml b/.github/workflows/build-pelican.yml index 9976fd2a2..0a870e40d 100644 --- a/.github/workflows/build-pelican.yml +++ b/.github/workflows/build-pelican.yml @@ -21,11 +21,17 @@ on: paths-ignore: - 'README.md' - 'LICENSE' - - 'build.sh' - '.editorconfig' - '.gitignore' - '.gitattributes' + # MCP docs are sourced from apache/solr-mcp (see "Fetch MCP docs" below). Changes + # there do not push here, so refresh asf-staging from solr-mcp main on a schedule. + # solr-mcp CI may also trigger this immediately via repository_dispatch / the API. + schedule: + - cron: '17 6 * * *' workflow_dispatch: + repository_dispatch: + types: [ mcp-docs-updated ] jobs: build-pelican: @@ -37,6 +43,20 @@ jobs: with: ref: ${{ github.ref == 'refs/heads/production' && 'production' || 'main' }} + # MCP docs content lives in apache/solr-mcp so it travels with the code. + # Assemble it into content/ before Pelican renders the site. MCP_DOCS_REF is a + # fixed branch name (never untrusted event input) to avoid ref/command injection. + - name: Fetch MCP docs from apache/solr-mcp + env: + MCP_DOCS_REF: main + run: | + git clone --quiet --depth 1 --branch "$MCP_DOCS_REF" \ + https://github.com/apache/solr-mcp.git /tmp/solr-mcp + rm -rf content/pages/mcp + mkdir -p content/pages content/doap + cp -R /tmp/solr-mcp/docs/site/content/pages/mcp content/pages/mcp + cp -R /tmp/solr-mcp/docs/site/content/doap/. content/doap/ + - name: Build Pelican Site uses: apache/infrastructure-actions/pelican@4deec7dce934d27491a0b1a8216f8d292548f7a4 # main 2025-04-13 with: diff --git a/.github/workflows/pr-build-pelican.yml b/.github/workflows/pr-build-pelican.yml index 8a8c55321..93f41499b 100644 --- a/.github/workflows/pr-build-pelican.yml +++ b/.github/workflows/pr-build-pelican.yml @@ -25,6 +25,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + # MCP docs content lives in apache/solr-mcp so it travels with the code. + # Assemble it into content/ so the PR build validates the full site. + - name: Fetch MCP docs from apache/solr-mcp + env: + MCP_DOCS_REF: main + run: | + git clone --quiet --depth 1 --branch "$MCP_DOCS_REF" \ + https://github.com/apache/solr-mcp.git /tmp/solr-mcp + rm -rf content/pages/mcp + mkdir -p content/pages content/doap + cp -R /tmp/solr-mcp/docs/site/content/pages/mcp content/pages/mcp + cp -R /tmp/solr-mcp/docs/site/content/doap/. content/doap/ - name: Build Pelican Site uses: apache/infrastructure-actions/pelican@4deec7dce934d27491a0b1a8216f8d292548f7a4 # main 2025-04-13 with: diff --git a/.gitignore b/.gitignore index ddffea526..36df86988 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ CLAUDE.md .cursor/ GEMINI.md .gemini/ + +# MCP docs are sourced from apache/solr-mcp at build time (see build.sh fetch_mcp_docs +# and the "Fetch MCP docs" step in .github/workflows/*pelican*.yml). Do not commit them. +/content/pages/mcp/ +/content/doap/solr-mcp.rdf diff --git a/build.sh b/build.sh index 3a6cd4435..d7ac125f9 100755 --- a/build.sh +++ b/build.sh @@ -39,6 +39,14 @@ OPTIONS=( ":pelican-help:Show all options accepted by Pelican" ) +# MCP documentation content is sourced from the apache/solr-mcp repo so that docs +# travel with the code (see https://github.com/apache/solr-mcp/tree/main/docs/site). +# It is assembled into content/ before Pelican runs. A sibling local checkout is used +# when present (for live preview); otherwise the pinned ref is cloned. +MCP_DOCS_REPO="${MCP_DOCS_REPO:-https://github.com/apache/solr-mcp.git}" +MCP_DOCS_REF="${MCP_DOCS_REF:-main}" +MCP_DOCS_LOCAL="${MCP_DOCS_LOCAL:-../solr-mcp/docs/site/content}" + function usage { echo "Usage: ./build.sh [OPTIONS] [-- ]" echo "" @@ -70,6 +78,26 @@ function _getopt_specs { echo "${short}|${long}" } +function fetch_mcp_docs { + local src tmp + if [[ -d "$MCP_DOCS_LOCAL" ]]; then + echo "Assembling MCP docs from local checkout: $MCP_DOCS_LOCAL" + src="$MCP_DOCS_LOCAL" + else + echo "Fetching MCP docs from $MCP_DOCS_REPO @ $MCP_DOCS_REF" + tmp="$(mktemp -d)" + git clone --quiet --depth 1 --branch "$MCP_DOCS_REF" "$MCP_DOCS_REPO" "$tmp" + src="$tmp/docs/site/content" + fi + # Pages: replace wholesale so removed pages don't linger. + rm -rf content/pages/mcp + mkdir -p content/pages content/doap + cp -R "$src/pages/mcp" content/pages/mcp + # DOAP: copy the MCP descriptor alongside the others (do not touch them). + cp -R "$src/doap/." content/doap/ + [[ -n "$tmp" ]] && rm -rf "$tmp" +} + function build_image { echo "Building local Docker image for Pelican, called $SOLR_LOCAL_PELICAN_IMAGE." docker build --no-cache -t $SOLR_LOCAL_PELICAN_IMAGE . @@ -174,6 +202,7 @@ else check_requirements_update fi +fetch_mcp_docs if [[ $SERVE ]]; then echo "Building Solr site locally. Goto http://localhost:8000 to view." echo "Edits you do to the source tree will be compiled immediately!" diff --git a/pelicanconf.py b/pelicanconf.py index 4d1b75c12..eedc0f6b0 100755 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -18,6 +18,10 @@ SOLR_OPERATOR_LATEST_RELEASE_DATE = datetime(2025, 3, 25) SOLR_OPERATOR_PREVIOUS_MAJOR_RELEASE = 'v0.8.1' +SOLR_MCP_LATEST_RELEASE = 'v1.0.0' +#SOLR_MCP_LATEST_RELEASE_DATE = datetime(2025, 3, 25) +#SOLR_MCP_PREVIOUS_MAJOR_RELEASE = 'v0.8.1' + # This string will be appended to all unversioned css and js resources to prevent caching surprises on edits. # The theme's htaccess file also sets a cache-control header with longer lifetime, if the v=XXXX query string is added. STATIC_RESOURCE_SUFFIX = "?v=%s" % dirhash('themes/solr/static', 'sha1')[-8:] diff --git a/themes/solr/static/css/mcp.css b/themes/solr/static/css/mcp.css new file mode 100644 index 000000000..cf97fd65c --- /dev/null +++ b/themes/solr/static/css/mcp.css @@ -0,0 +1,1033 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +html, body { + font-family: 'Helvetica Neue', sans-serif; /* substitute for proxima nova */ + color: #333; +} + +body { + overflow-x:hidden; + pointer-events: none; +} + +body > * { + pointer-events: auto; +} + +.alignleft { + float: left; +} + +.alignright { + float: right; +} + +.container { + padding: 40px 0; +} + +code, pre { + font-family: Menlo, Consolas,"Liberation Mono",Courier,monospace; + color:#4F504D; +} + +code { + font-weight: 500; +} + +/* + * Elements + */ +:focus { + outline: 0; +} + +.offset { + position: relative; + top: -150px; + padding-top: 150px; + margin-bottom: -130px; + z-index: -1000; +} + +.offset-medium { + position: relative; + top: -115px; + padding-top: 115px; + padding-bottom: 0px; + margin-bottom: -115px; + z-index: -1000; +} + +.offset-small { + position: relative; + top: -56px; + padding-top: 112px; + margin-bottom: -56px; + z-index: -1000; +} + +.btn1{ + border: 1px solid #d1d3d4; + background-color:inherit; + text-transform: uppercase; + color:#000; + padding: 0.7em 1em; + font-weight: 500; + margin: 0; +} +.btn1:hover, .btn1:focus { + color:#ff833d; + background:inherit; +} + +div.centered { + text-align: center; + padding-top: 32px; +} + +a.btn, button { + border: 1px solid #d1d3d4; + background-color:inherit; + text-transform: uppercase; + color:#000; + padding: 0.7em 1em; + font-weight: 500; + margin: 0; +} + +a.btn:hover, a.btn:focus, +button:hover, button:focus { + color:#ff833d; + background:inherit; +} + +a.btn.white, +button.white { + color:#fff; +} + +a.btn.white, +button.white:hover { + color:#262130; + background:#fff; +} + +/* + * Header + */ + +.header-section { + position: fixed; + z-index: 999; + min-width: 100%; + background:#2d7a3e; +} + +.header-fill { + padding-top: 90px; +} + +.top-bar, .top-bar .name { + background:#2d7a3e; + height: 90px; +} + +.top-bar .name .logo { + height: 100%; + position:relative; + left: 15px; + padding: 20px 0 25px 0; +} + +.top-bar-section ul li, .top-bar-section li:not(.has-form) a:not(.button) { + background: #2d7a3e; +} + +.top-bar-section li:not(.has-form) a:not(.btn):hover { + background:inherit; + color: #25202f; +} + +.top-bar-section .navigation a.selected { + color: #25202f; +} + +.top-bar-section li:not(.has-form) a.btn:hover, .top-bar-section li:not(.has-form) a.btn:focus { + background:#fff; + color: #25202f; +} + +.top-bar-section ul li>a, +.top-bar-section ul li>a.btn, +.top-bar.shrink.expanded .top-bar-section ul li>a, +.top-bar.shrink.expanded .top-bar-section ul li>a.btn { + padding: 0 10px !important; + transition: all 0.1s ease; + text-transform:uppercase; + font-size:0.92rem; +} + +.top-bar-section ul li>a.btn { + margin: 0; + background-color: transparent; + text-align:left; +} + +.top-bar.expanded .toggle-topbar a { + color:#fff; +} + +.top-bar.expanded .top-bar-section li:not(.has-form) a:not(.btn):hover { + background:#fff; +} + +/* full-width nav styles */ +@media only screen and (min-width: 47.5em) { + .top-bar-section .navigation { + margin: 20px 20px 20px 0; + } + .top-bar .name .logo { + left: 15px; + } + .top-bar .btn { + padding-top: .65rem; + padding-bottom: .55rem; + top: 2px; + text-align:center; + border: 1px solid #fff; + } + .top-bar .btn:hover { + background:#fff; + } +} + +/* shrink header styles */ +.top-bar.shrink, .top-bar.shrink .name, .top-bar.expanded .name { + height: 55px; +} + +.top-bar.shrink.expanded { + height:auto; +} + +.top-bar.shrink .name .logo, .top-bar.expanded .name .logo { + padding: 10px 0 15px 0; +} + +.top-bar.shrink .top-bar-section ul li>a, .top-bar.shrink .top-bar-section ul li>a.btn { + font-size: 0.8em; +} + +.top-bar.shrink .top-bar-section li:not(.has-form) a:not(.button) { + line-height: 35px; +} + +.top-bar.shrink .navigation { + margin: 10px 15px 10px 0; +} + +.top-bar.shrink.expanded .navigation { + margin: 0; +} + +.top-bar.shrink.expanded .top-bar-section li:not(.has-form) a:not(.button) { + line-height: 1.6; +} + +.top-bar.shrink .button { + padding: 10px 20px; +} + +/* + * Global + */ +h1, h2, h3, h4, h5 { + font-family: 'Raleway', 'Helvetica Neue', sans-serif; + font-weight:300; +} + +h1 { + margin-bottom: 20px; + color: #2d7a3e; +} + +h2 { + margin-bottom: 0.8em; + color: #2d7a3e; +} + +h3 { + color: #666; +} + +h4 { + color: #666; +} + +h5 { + color: #999; +} + +p { + line-height: 1.8em; + color:#262130; +} + +.button { + background-color: #ff833d; + text-transform: uppercase; +} + +.button:hover, +.button:focus, +.button:active { + background-color: #ff5c00; +} + +.annotation { + color: #262130; + text-transform: uppercase; + margin-bottom: 0.8em; + font-weight:400; +} + +/* + * PAGES + */ + +.homepage h1.red { + color: #2d7a3e;; +} + +.page h1, .page h2, .page h3 { + font-family: 'Raleway', 'Helvetica Neue', sans-serif; + color: #262130; +} + +.page h1, .subnav h1 , h1.news { + font-weight:300; +} + +.subnav h1 , h1.news { + margin-bottom: 30px; +} + +.subnav h1 , h1.news { + line-height:0.8; +} + +.page h1 small, .subnav h1 small, h1.news small { + font-size:0.4em; + color:#333; +} + +.page h2, .page h3 { + font-weight:500; +} + +.page h2 { + font-size:1.5em; +} + +.page h3 { + font-size:1.4em; +} + +.page p, .page ul li, .page ol li { + color:#333; +} + +.page a { + color: #2d7a3e; +} + +.page .date { + color: #2d7a3e; + text-transform:uppercase; + font-weight:500; +} + +#resources { + text-align:center; +} + +pre { + white-space:pre-wrap; + overflow:hidden; +} + +/* + * Alternate styles (green sections) + */ +.alternate .annotation { + color: #2d7a3e; +} + +.alternate h1 { + font-weight: 100; + color: #212121; +} + +.alternate h2 { + font-weight: 300; +} + +hr { + margin-bottom: 2em; + color:#e4e2dd; +} + +/* + * Small styles + */ + +.small h1 { + font-size: 2em; +} + +.small h2 { + font-size: 1.6em; +} + +.small h3 { + font-size: 1.4em; +} + +.small h4 { + font-size: 1.2em; +} + +.small h5 { + font-size: 1em; +} + +.small p { + font-size: 0.9em; +} + +/* + * Section styles + */ +section { + padding: 40px 0; + color: #333; + text-align:center; +} + +.artifacthub-widget > section { + padding: 0; +} + +section.gray { + background-color: #f9f8f8; +} + +section.orange { + background-color: #2d7a3e; + color: #fff; + padding:60px 0 80px 0; + text-align:center; + position:relative; +} + +section.orange .annotation { + color:#fff; +} + +section.orange h1 { + color: inherit; +} + +section.orange h2 { + color: inherit; +} + +section.orange p { + color:#fff; + font-weight: 300; + font-size: 1.1em; +} + +section.orange .down-arrow { + position: absolute; + left: 50%; +} + +section.orange .down-arrow .red { + color: #ff833c; +} + +section.orange .down-arrow a { + color:#fff; +} + +section.orange.full-width { + margin-left: -100%; + margin-right: -100%; + margin-bottom: 2em; +} + + +/* + * Hero + */ +.hero { + background-color: #262130; + color: #fff; + position:relative; + padding: 100px 0; +} + +.hero h1, +.hero p { + color: #fff; +} + +.hero p { + margin-bottom: 40px; + font-weight: 300; + font-size: 1.1em; +} + +.hero .button { + background-color: #305cb3; +} + +.hero .button:hover, +.hero .button:focus, +.hero .button:active { + background-color: #0045cd; +} + +.hero .down-arrow { + position: absolute; + bottom: -80px; + left: 50%; +} + +.hero .down-arrow .red { + color: #2d7a3e; +} + +.hero .down-arrow a { + color:#fff; +} + +.security { + background-color: #FFBF78; + padding-top: 10px; + padding-bottom: 0px; + display: none; +} + +.security a { + color: #262130; +} + +.topnews { + background-color: #59BD81; + padding-top: 15px; + padding-bottom: 0px; + display: none; +} + +.topnews .row p a { + color: #262130; + font-size: larger; +} + +.topnews-operator { + background-color: #59BD81; + padding-top: 15px; + padding-bottom: 0px; + display: none; +} + +.topnews-operator .row p a { + color: #262130; + font-size: larger; +} + +/* + * Footer + */ +footer { + background-color: #262130; + color: #f9f8f8; + padding: 40px 0 20px 0; +} + +footer h4 { + padding-bottom:15px; + text-transform:uppercase; + font-size: 1em; +} + +footer h4, footer ul li a, .page footer ul li a { + color: #f9f8f8; + font-family: 'Raleway', 'Helvetica Neue', sans-serif; +} + +footer ul li a, .page footer ul li a { + font-weight:300; + font-size:0.9em; +} + +footer ul { + list-style: none; + margin-left: 0; +} + +footer .copyright { + padding: 50px 0 40px 0; +} + +footer .copyright p { + color: #bbb; + font-size:0.7em; + text-align:center; +} + +/* + * Gray/white section styles + */ + +.white h1 { + line-height:0.8; +} + +.gray .annotation { + color: #262130; + font-size: 1em; +} + +.gray h1 { + color: #2d7a3e; + line-height:0.8; +} + +.gray .box h3 { + color:#000; + font-size:1.4em; + margin-bottom:20px; +} + +.gray .box p { + font-size: 0.9em; + line-height: 1.3em; + color:#333; +} + +.gray .box button { + font-size: 0.75em; + margin-bottom: 0; +} + +.gray .box button:hover { + background-color:inherit; + color:#ff833d; +} + +.gray .box:hover { + background:#fff; + border: 1px solid #333; + cursor:pointer; +} + +.gray .box:hover button { + color:#ff833d; +} + +.gray .box .img { + height:120px; +} + +.gray .box .img img { + height:95px; +} + +.full-width .gray .box { + padding:0; + border:none; +} + +.full-width .gray .box:hover { + border:none; + cursor:default; + background:inherit; +} + +/* box variants */ +.col-4 .box { + margin: 15px; + padding: 5px 5px 15px 5px; + border: solid 1px transparent +} + +.col-4 .box .title { + height: 70px; +} + +.col-3 .box { + margin: 15px; + padding: 20px 20px 30px 20px; + border: solid 1px transparent +} + +.col-3 .box .title { + height: 70px; +} + +[class*="block-grid-"] { + display: flex; + padding: 0; + margin:0; + flex-wrap: wrap; + justify-content: center; +} + +/* + * Solr books + */ +.books { + margin:40px 0; + +} + +.books > div{ + padding-left: 5px; +} + +.powered{ + line-height: 99px; + height: 99px; +} +.powered div{ + line-height: 99px; + height: 99px; + padding-right: 10px; +} + +.powered img{ + vertical-align: middle; + display: inline; +} + +/* + * Slider + * TODO: Not in use + */ +.slider-prev { + left:-25px; + color:#ffa16b; +} + +.slider-next { + right:-25px; + color:#ffa16b; +} + +.slider-prev, .slider-next { + position: absolute; + display: block; + height: 20px; + width: 20px; + cursor: pointer; + top: 50%; + margin-top: -10px; +} + +/* + * FEATURES PAGE + */ +section.list { + padding:80px 0; +} + +section.list { + text-align:left; +} + +section.list ul li { + font-family: 'Raleway', 'Helvetica Neue', sans-serif; + font-weight:300; + color: #333; + font-size: 1.2em; + padding-right:20px; +} + +section.list ul li p { + font-family: 'Helvetica Neue', sans-serif; + font-weight:300; + color: #A13016; + margin-top: 10px; + font-size: 0.8em; +} + +section.list ul li ul { + padding-top: 10px; +} + +section.list ul li ul li { + font-family: 'Helvetica Neue', sans-serif; + font-weight:300; + color: #A13016; + margin-top: 2px; + font-size: 0.96em; +} + + +.anchor-fixed { + top: 57px; + z-index: 1000; + position: fixed; +} + +/* + * Subnav style pages + */ +.sub-nav { + display:inline-block; + margin-bottom:0; +} + +.sub-nav-container { + height: 100px; + width: 1000px; + margin: 0 auto; +} + +.sub-nav-border { + padding: 20px 0; + background: white; + border-top: 1px solid #e4e2dd; + border-bottom: 1px solid #e4e2dd; + margin: 0 auto 30px auto; +} + +.sub-nav dd { + margin-bottom: 0; +} + +.sub-nav dd a { + padding-right: 30px; + padding-left: 15px; + border-right:1px solid #e4e2dd; + position: relative; + z-index: 2000; +} + +.codehilite { + margin: 10px 0; + background-color: #EEEEEE; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 15px; +} + +pre { + line-height:1.5; +} + +ul.breadcrumbs { + background-color:transparent; + border: none; +} + +/* + * Sidebar + */ + +.side-nav { + padding:25px; + border:1px solid #e4e2dd; + margin-bottom:40px; +} + +ul.side-nav > li { + border-top:1px solid #e4e2dd; + padding:10px 0 10px 10px; + margin:0; +} + +.page .side-nav li a { + color:#25202f; + font-weight:300; + font-size: 1.3em; +} + +.page .side-nav li a.active { + color:#2d7a3e; +} + +.page .side-nav li a:hover { + color:#2d7a3e; +} + +#search form, #search fieldset { + border:none; + padding:0; + margin:0; +} + +.search-box { + display: inline-block; + padding-right: 1em; + position: relative; + width: 150px; + height: 42px; +} + +#search input[type="search"] { + font-family: 'Raleway', 'Helvetica Neue', sans-serif; + font-weight:300; + height: 28px; + width: 135px; + font-size: 12px; + border: none; + box-shadow: none; + position: absolute; + top: 8px; + left: 0px; + padding-right: 26px; +} + +#search input[type="search"]:focus { + background-color: #f9f9f9; +} + +.search-button { + position:absolute; + height:23px; + width:23px; + background-color: transparent !important; + line-height: 23px !important; + padding: 0 !important; + top: 10px; + right: 17px; + margin:0; +} + +.search-button img { + padding:0; + line-height:23px; + margin:0; +} + +.nested-nav { + +} + +ul.breadcrumbs { + margin:0; + padding:0; +} + +ul.breadcrumbs a { + text-transform:none; + font-size:1.2em; +} + +.tutorials .orange { + margin-top: 40px; + margin-bottom:40px; +} + +.float-right { + float: right; +} + +img.float-right { + margin: 5px 0px 10px 10px; +} + + +.poweredby .list ul{ + list-style-type: none; +} + +.wrappable-btn { + border: 1px solid #d1d3d4; + background-color: inherit; + text-transform: uppercase; + color: #000; + padding: 0.25em 0.75em 0.05em 0.47em; + font-weight: 500; + margin: 0; + display: inline-block; + vertical-align: middle; +} +.wrappable-btn:hover, .wrappable-btn:focus { + color: #ff833d; + background: inherit; +} + +.ref-guide-badge { + background-color: #2d7a3e; + color: #fff; + display: inline-block; + text-align: center; + font-size: 0.6em; + line-height: 1.1; + font-weight: 500; + vertical-align: middle; + padding: 1px 2px; + margin: 0em 0.50em 0.30em -0.40em; +} +.wrappable-btn:hover .ref-guide-badge, .wrappable-btn:focus .ref-guide-badge { + background-color: #ff833d; +} + +ul li div.box div.img img.resizeable-solr-logo { + max-width:243px; + max-height:123px; + height:auto; + width: 100%; + border:2px solid #CCC +} + +ul li div.box h3.fixed-wrap-point-logo-title { + padding-left:9px; + padding-right:8px; +} + +section h3.asset-download { + text-align: left; + padding-top: 10px; +} + +ul li div.box div.img.logo-container { + padding: 20px; + height: auto; + width: auto; +} +ul li div.box div.img.logo-container.black-background { + background-color:#000; +} +ul li div.box div.img.logo-container.white-background { + background-color:#fff; +} +ul li div.box div.img.logo-container.orange-background { + background-color:#2d7a3e; +} +.full-width .gray .box.logo-box { + position: relative; + border: 1px solid #CCC; +} diff --git a/themes/solr/templates/_header.html b/themes/solr/templates/_header.html index b9ae4ae45..3c52bd820 100644 --- a/themes/solr/templates/_header.html +++ b/themes/solr/templates/_header.html @@ -31,6 +31,9 @@
  • Solr Operator
  • +
  • + MCP +
  • + + + +{% include "mcp/_css.html" %} + + + + +{% include "_javascript.html" %} diff --git a/themes/solr/templates/mcp/_header.html b/themes/solr/templates/mcp/_header.html new file mode 100644 index 000000000..0f0b16dc9 --- /dev/null +++ b/themes/solr/templates/mcp/_header.html @@ -0,0 +1,40 @@ +
    +
    + +
    +
    + +
    diff --git a/themes/solr/templates/mcp/base.html b/themes/solr/templates/mcp/base.html new file mode 100644 index 000000000..da0b928a7 --- /dev/null +++ b/themes/solr/templates/mcp/base.html @@ -0,0 +1,46 @@ + + + + {% include "mcp/_head.html" %} + {% block title %}{{ page.title }}{% endblock %} - Apache Solr MCP Server + {% block css %}{% endblock %} + + {% block metakeys %} + + {% endblock %} + {% block ogmeta %} + + + + + + + {% endblock %} + + {% block favicon %} + + + {% endblock %} + {% block rss %}{% endblock %} + {% block javascript %}{% endblock %} + {% include "_matomo.html" %} + + + + {% include "mcp/_header.html" %} + + {% block solr_security_warning %} + {% endblock %} + {% block hero_header %} + {% endblock %} + {% block content %} + {% endblock %} + + + {% include "_last_scripts.html" %} + + diff --git a/themes/solr/templates/mcp/client.html b/themes/solr/templates/mcp/client.html new file mode 100644 index 000000000..52c825397 --- /dev/null +++ b/themes/solr/templates/mcp/client.html @@ -0,0 +1,26 @@ +{% extends "mcp/page.html" %} + +{% block content_inner %} +
    + + +

    {{ page.title }}

    + +

    + All clients: + Claude Desktop · + Claude Code · + VS Code / Copilot · + Cursor · + JetBrains · + MCP Inspector +

    + + {{ page.content }} +
    +{% endblock content_inner %} diff --git a/themes/solr/templates/mcp/community.html b/themes/solr/templates/mcp/community.html new file mode 100644 index 000000000..d20e29389 --- /dev/null +++ b/themes/solr/templates/mcp/community.html @@ -0,0 +1,12 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Community{% endblock %} +{% block subnav_subtitle %}Join the active community of Solr MCP Server contributors.{% endblock %} +{% block subnav_nav_items %} +
    Support
    +
    Lists/Chat
    +
    Issues
    +
    Contributing
    +
    Code of Conduct
    +
    Version Control
    +{% endblock %} diff --git a/themes/solr/templates/mcp/downloads.html b/themes/solr/templates/mcp/downloads.html new file mode 100644 index 000000000..a093066e9 --- /dev/null +++ b/themes/solr/templates/mcp/downloads.html @@ -0,0 +1,20 @@ +{% extends "mcp/page.html" %} + +{% block content_inner %} +
    + + +

    {{ page.title }} + +

    + {{ page.content }} +

    This project has not made any official releases yet. See the README for instructions on building from source.

    +
    +{% endblock content_inner %} diff --git a/themes/solr/templates/mcp/features.html b/themes/solr/templates/mcp/features.html new file mode 100644 index 000000000..8bc8658b8 --- /dev/null +++ b/themes/solr/templates/mcp/features.html @@ -0,0 +1,299 @@ +{% extends "mcp/fullwidth.html" %} + +{% block fullwidth_title %}

    Features

    {% endblock %} + +{% block hero_header_inner %} +
    +
    + Apache Solr MCP Server {{ SOLR_MCP_LATEST_RELEASE }} +
    +

    Powerful MCP Tools for Solr

    +

    + 11 tools, 6 prompts, 2 resources, and argument autocompletion that let AI assistants search, index, and manage your Solr collections through natural language. +

    +
    +
    +{% endblock %} + +{% block content_inner %} + +
    +
    +
    +
    MCP Tools
    +

    Tool Reference

    +

    Each tool is callable by any MCP-compatible AI client. The AI translates natural language into the right tool calls automatically.

    +
    +
    + +
    +
    + + + + + + + + + + +
    ToolDescription
    searchFull-text search with filtering, faceting, sorting, and pagination. Accepts query strings, filter queries, facet fields, sort clauses, start offset, and row count.
    + +

    Indexing

    + + + + + + + + + + + + + + + + +
    ToolDescription
    index-json-documentsIndex documents from a JSON array string. Handles batch processing (1,000 per batch), field name sanitization, and automatic commits.
    index-csv-documentsIndex documents from a CSV string. First row is used as headers. Same batch processing and field normalization.
    index-xml-documentsIndex documents from a Solr XML string (<add><doc>...).
    + +

    Collections

    + + + + + + + + + + + + + + + + + + + + +
    ToolDescription
    list-collectionsList all available Solr collections in the cluster.
    get-collection-statsComprehensive metrics: index stats, query performance, cache hit ratios, handler throughput.
    check-healthHealth check returning status, document count, and responsiveness.
    create-collectionCreate a new collection with configurable shards, replicas, and configset. Defaults: _default configset, 1 shard, 1 replica.
    + +

    Schema

    + + + + + + + + + + + + + + + + +
    ToolDescription
    get-schemaRetrieve the complete schema definition: field definitions, field types, dynamic fields, copy fields, unique key, and schema attributes.
    add-fieldsAdditively extend a collection's schema with new fields. Takes a list of Solr Schema API field definitions; batched via SchemaRequest.MultiUpdate.
    add-field-typesAdditively extend a collection's schema with new field types: custom analyzers, dense vector fields for semantic search, autocomplete chains.
    + +

    Every tool advertises MCP behavior hints (readOnlyHint, destructiveHint, idempotentHint) so clients can build sensible approval UX rather than treating every call as worst-case destructive.

    + +
    +
    +
    + +
    +
    +
    +
    MCP Resources
    +

    Read-Only Data

    +

    MCP Resources provide data that clients can access directly without calling a tool. The schema resource supports autocompletion for collection names.

    +
    +
    + +
    +
    + + + + + + + + + + + + +
    Resource URIDescription
    solr://collectionsList of all Solr collections available in the cluster.
    solr://{collection}/schemaSchema definition for a specific collection. Supports prefix-filtered autocompletion — MCP clients can query for collection names matching what the user has typed (case-insensitive, capped at 100).
    +
    +
    +
    + +
    +
    +
    +
    MCP Prompts
    +

    Guided Workflows

    +

    Slash-command-style entry points that point the AI at the right tools in the right order for canonical Solr workflows. The framework wraps each prompt's return value as a single user-role PromptMessage.

    +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PromptArgumentsPurpose
    explore-collectionsRead-only walkthrough: list collections, characterise each by stats and health.
    setup-collectionname, purpose (optional)Validate a name, pick configset / shards / replication factor, create the collection, verify it.
    view-schemacollectionRead-only schema walkthrough.
    design-schemacollection, datasetDescription, sampleDocument (optional)Inspect schema, choose field types, apply additive schema changes.
    index-datacollection, format (json / csv / xml), sample (optional)Verify the target schema, pick the right indexing tool, confirm the result.
    search-collectioncollection, questionTranslate a natural-language question into a Solr query.
    +
    +
    +
    + +
    +
    +
    +
    MCP Completions
    +

    Argument Autocompletion

    +

    The server implements MCP completions, so clients can suggest valid values as the user types — for resource-template variables and prompt arguments. Suggestions are matched case-insensitively by prefix and capped at 100 per request.

    +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Completion targetArgumentSuggests
    solr://{collection}/schema resourcecollectionLive collection names in the cluster.
    search-collection promptcollectionLive collection names in the cluster.
    index-data promptcollectionLive collection names in the cluster.
    view-schema promptcollectionLive collection names in the cluster.
    design-schema promptcollectionLive collection names in the cluster.
    +
    +
    +
    + +
    +
    +
    +
    Platform
    +

    Enterprise-Ready Infrastructure

    +
    +
    +
    +
      +
    • +
      +
      +
      +

      STDIO & HTTP Transports

      +

      STDIO for local AI clients (Claude Desktop). HTTP for remote access, multi-client, and MCP Inspector.

      +
      +
      +
    • +
    • +
      +
      +
      +

      OAuth2 Security

      +

      JWT validation with Auth0, Keycloak, or any OAuth2/OIDC provider. Setup guide →

      +
      +
      +
    • +
    • +
      +
      +
      +

      Observability

      +

      OpenTelemetry traces, Prometheus metrics, structured logs via LGTM stack. Learn more →

      +
      +
      +
    • +
    +
    +
    + +
    +
    +
    +
    Configuration
    +

    Environment Variables

    +
    +
    + +
    +
    + + + + + + + + + + +
    VariableDescriptionDefault
    SOLR_URLSolr base URLhttp://localhost:8983/solr/
    PROFILESTransport mode: stdio or httpstdio
    HTTP_SECURITY_ENABLEDOAuth2 enforcement in HTTP mode (set false to disable for local dev)true
    OAUTH2_ISSUER_URIOAuth2 issuer URL (Auth0, Keycloak, Okta)
    OTEL_SAMPLING_PROBABILITYTracing sampling rate (0.0–1.0)1.0
    OTEL_TRACES_URLOTLP collector endpointhttp://localhost:4317
    +
    +
    +
    + +{{ super() }} +{% endblock content_inner %} diff --git a/themes/solr/templates/mcp/fullwidth.html b/themes/solr/templates/mcp/fullwidth.html new file mode 100644 index 000000000..e326919d4 --- /dev/null +++ b/themes/solr/templates/mcp/fullwidth.html @@ -0,0 +1,24 @@ +{% extends "mcp/base.html" %} + +{% block hero_header %} +
    +
    + {% block hero_header_inner %} +
    +
    + Apache Solr MCP Server {{ SOLR_MCP_LATEST_RELEASE }} +
    +

    + The Apache Solr MCP Server gives your LLM super powers in managing Solr clusters. +

    + +
    +
    + {% endblock hero_header_inner %} +
    +
    +{% endblock hero_header %} + +{% block content %} +{% block content_inner %}{{ page.content }}{% endblock %} +{% endblock %} diff --git a/themes/solr/templates/mcp/index.html b/themes/solr/templates/mcp/index.html new file mode 100644 index 000000000..d9ce9233a --- /dev/null +++ b/themes/solr/templates/mcp/index.html @@ -0,0 +1,182 @@ +{% extends "mcp/fullwidth.html" %} + +{% block bodyclass %}homepage{% endblock %} + +{% block solr_security_warning %} +{% set latest_sec_articles = (articles | selectattr("category.name", "eq", "solr/security") | list)[:1] %} +{% if (latest_sec_articles | length) > 0 %} +{% set latest_sec_date = latest_sec_articles[0].date | strftime("%Y-%m-%d") %} +
    + +
    +{% endif %} +{% endblock %} + +{% block content_inner %} +
    + +
    +
    +
    +
    + Apache Solr MCP Server +
    +

    Give AI Assistants Solr Superpowers

    +

    + A standards-compliant Model Context Protocol server that brings powerful search, indexing, and collection management capabilities to Claude and other LLM assistants. Built with Spring AI, backed by SolrJ, and ready to deploy anywhere. +

    +
    + Get Started on GitHub +
    +
    +
    +
    + +
    +
    +
    +
    + Why Use Solr MCP Server? +
    +

    Empower Your AI with Enterprise Search

    +

    + Integrate Apache Solr directly into your AI workflows. Execute complex searches, manage indexes, and analyze your data—all through natural language with an AI assistant. +

    +
    +
    +
    +
      +
    • +
      +
      +
      +

      Powerful Search

      +
      +

      Complex queries, filtering, faceting, and pagination through a natural language interface

      +
      +
    • +
    • +
      +
      +
      +

      Flexible Indexing

      +
      +

      Index documents in JSON, CSV, or XML formats with automatic field name normalization

      +
      +
    • +
    • +
      +
      +
      +

      Standards-Based

      +
      +

      Implements the Model Context Protocol specification for seamless AI integration

      +
      +
    • +
    • +
      +
      +
      +

      Multi-Collection

      +
      +

      Manage and query multiple Solr collections and schemas through a unified interface

      +
      +
    • +
    • +
      +
      +
      +

      Easy Deployment

      +
      +

      Deploy as a Docker container, Spring Boot application, or via HTTP/STDIO transports

      +
      +
    • +
    • +
      +
      +
      +

      Enterprise Ready

      +
      +

      Built on proven technologies with comprehensive error handling and logging

      +
      +
    • +
    +
    +
    + +
    +
    +
    +
    + Next Steps +
    +

    Explore the Solr MCP Server

    +
    +
    + +
    + +
    +
    +
    +

    + The Apache Software Foundation +

    +

    + The Apache Software Foundation provides support for the Apache community of open-source software projects. The Apache projects are defined by collaborative consensus based processes, an open, pragmatic software license and a desire to create high quality software that leads the way in its field. Apache Lucene, Apache Solr, Apache PyLucene, Apache Open Relevance Project and their respective logos are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. +

    +
    +

    + +

    +
    +
    +
    +{% endblock content_inner %} diff --git a/themes/solr/templates/mcp/licensing.html b/themes/solr/templates/mcp/licensing.html new file mode 100644 index 000000000..05d887174 --- /dev/null +++ b/themes/solr/templates/mcp/licensing.html @@ -0,0 +1,11 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Licensing & Notices{% endblock %} +{% block subnav_subtitle %}How the Solr MCP Server™ LICENSE and NOTICE files are built, and where to find them.{% endblock %} +{% block subnav_nav_items %} +
    Overview
    +
    Where They Live
    +
    Building
    +
    Construction
    +
    Role of the SBOM
    +{% endblock %} diff --git a/themes/solr/templates/mcp/observability.html b/themes/solr/templates/mcp/observability.html new file mode 100644 index 000000000..b25c07628 --- /dev/null +++ b/themes/solr/templates/mcp/observability.html @@ -0,0 +1,11 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Observability{% endblock %} +{% block subnav_subtitle %}Traces, metrics, and logs for the Solr MCP Server via the LGTM stack.{% endblock %} +{% block subnav_nav_items %} +
    Overview
    +
    Setup
    +
    Grafana
    +
    Actuator
    +
    Production
    +{% endblock %} diff --git a/themes/solr/templates/mcp/page.html b/themes/solr/templates/mcp/page.html new file mode 100644 index 000000000..845fadbb9 --- /dev/null +++ b/themes/solr/templates/mcp/page.html @@ -0,0 +1,11 @@ +{% extends "mcp/base.html" %} + +{% block content %} +
    + {% block subnav %} + {% endblock %} +
    + {% block content_inner %}{{ page.content }}{% endblock %} +
    +
    +{% endblock %} diff --git a/themes/solr/templates/mcp/quick-start.html b/themes/solr/templates/mcp/quick-start.html new file mode 100644 index 000000000..3b6e1ab77 --- /dev/null +++ b/themes/solr/templates/mcp/quick-start.html @@ -0,0 +1,10 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Quick Start{% endblock %} +{% block subnav_subtitle %}Get from zero to a working AI + Solr integration in under 2 minutes.{% endblock %} +{% block subnav_nav_items %} +
    Prerequisites
    +
    Start Solr
    +
    Configure Client
    +
    Try It
    +{% endblock %} diff --git a/themes/solr/templates/mcp/resources.html b/themes/solr/templates/mcp/resources.html new file mode 100644 index 000000000..6b71a8ff8 --- /dev/null +++ b/themes/solr/templates/mcp/resources.html @@ -0,0 +1,9 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Resources{% endblock %} +{% block subnav_subtitle %}Documentation, guides, and references for the Solr MCP Server.{% endblock %} +{% block subnav_nav_items %} +
    Guides
    +
    Documentation
    +
    References
    +{% endblock %} diff --git a/themes/solr/templates/mcp/security.html b/themes/solr/templates/mcp/security.html new file mode 100644 index 000000000..00f5e9dae --- /dev/null +++ b/themes/solr/templates/mcp/security.html @@ -0,0 +1,10 @@ +{% extends "mcp/subnav.html" %} + +{% block subnav_title %}Security{% endblock %} +{% block subnav_subtitle %}OAuth2 authentication for the Solr MCP Server in HTTP mode.{% endblock %} +{% block subnav_nav_items %} +
    Overview
    +
    Auth0
    +
    Keycloak
    +
    How It Works
    +{% endblock %} diff --git a/themes/solr/templates/mcp/subnav.html b/themes/solr/templates/mcp/subnav.html new file mode 100644 index 000000000..76e81656f --- /dev/null +++ b/themes/solr/templates/mcp/subnav.html @@ -0,0 +1,20 @@ +{% extends "mcp/page.html" %} + +{% block subnav %} +
    +
    +

    {% block subnav_title %}{% endblock %}
    + {% block subnav_subtitle %}{% endblock %}

    +
    +
    + +{% endblock %}