From 8a59e4c4d4a935ba13c43562a29856e751d14282 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Mon, 22 Jun 2026 13:32:05 +0530 Subject: [PATCH 01/15] docs: copy docs-site scaffold verbatim from JS SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copies the Hugo/Docsy site scaffold from the JS SDK repo (googleapis/mcp-toolbox-sdk-js, docs-site/) byte-for-byte. No Python-specific changes in this commit — retargeting is done in the follow-up commit so the diff against the known-good JS pipeline is reviewable in isolation. Files copied unchanged: archetypes, assets (scss + icon), layouts (home.latest, home.releases, head-end hook, navbar-version-selector, sidebar-tree), static (w3.js + favicons), go.mod, go.sum, hugo.toml, package.json (postcss deps). --- docs-site/archetypes/default.md | 5 + docs-site/assets/icons/logo.svg | 1 + docs-site/assets/scss/_styles_project.scss | 27 +++ docs-site/assets/scss/_variables_project.scss | 4 + docs-site/assets/scss/main.scss | 1 + docs-site/go.mod | 8 + docs-site/go.sum | 8 + docs-site/hugo.toml | 91 ++++++++ docs-site/layouts/_default/home.latest.html | 11 + .../layouts/_default/home.releases.releases | 7 + .../layouts/_partials/hooks/head-end.html | 1 + .../_partials/navbar-version-selector.html | 16 ++ docs-site/layouts/_partials/sidebar-tree.html | 199 ++++++++++++++++++ docs-site/package.json | 7 + .../favicons/android-chrome-192x192.png | Bin 0 -> 7530 bytes .../favicons/android-chrome-512x512.png | Bin 0 -> 28023 bytes .../static/favicons/apple-touch-icon.png | Bin 0 -> 6873 bytes docs-site/static/favicons/favicon-16x16.png | Bin 0 -> 576 bytes docs-site/static/favicons/favicon-32x32.png | Bin 0 -> 1057 bytes docs-site/static/favicons/favicon.ico | Bin 0 -> 15406 bytes docs-site/static/js/w3.js | 34 +++ 21 files changed, 420 insertions(+) create mode 100644 docs-site/archetypes/default.md create mode 100644 docs-site/assets/icons/logo.svg create mode 100644 docs-site/assets/scss/_styles_project.scss create mode 100644 docs-site/assets/scss/_variables_project.scss create mode 100644 docs-site/assets/scss/main.scss create mode 100644 docs-site/go.mod create mode 100644 docs-site/go.sum create mode 100644 docs-site/hugo.toml create mode 100644 docs-site/layouts/_default/home.latest.html create mode 100644 docs-site/layouts/_default/home.releases.releases create mode 100644 docs-site/layouts/_partials/hooks/head-end.html create mode 100644 docs-site/layouts/_partials/navbar-version-selector.html create mode 100644 docs-site/layouts/_partials/sidebar-tree.html create mode 100644 docs-site/package.json create mode 100644 docs-site/static/favicons/android-chrome-192x192.png create mode 100644 docs-site/static/favicons/android-chrome-512x512.png create mode 100644 docs-site/static/favicons/apple-touch-icon.png create mode 100644 docs-site/static/favicons/favicon-16x16.png create mode 100644 docs-site/static/favicons/favicon-32x32.png create mode 100644 docs-site/static/favicons/favicon.ico create mode 100644 docs-site/static/js/w3.js diff --git a/docs-site/archetypes/default.md b/docs-site/archetypes/default.md new file mode 100644 index 000000000..25b67521d --- /dev/null +++ b/docs-site/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/docs-site/assets/icons/logo.svg b/docs-site/assets/icons/logo.svg new file mode 100644 index 000000000..39cf8e2bc --- /dev/null +++ b/docs-site/assets/icons/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs-site/assets/scss/_styles_project.scss b/docs-site/assets/scss/_styles_project.scss new file mode 100644 index 000000000..7bfb2f3b3 --- /dev/null +++ b/docs-site/assets/scss/_styles_project.scss @@ -0,0 +1,27 @@ +@import 'td/code-dark'; + +.td-navbar { + background-color: #80a7e9 !important; +} + +.nav-tabs { + flex-wrap: nowrap; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; +} + +.td-content table { + display: table; + width: 100% !important; + margin-bottom: 1.5rem; +} + +.td-footer { + background-color: rgb(64, 63, 76) !important; + border-top: none; +} + +.td-footer, .td-footer a, .td-footer span { + color: #ffffff !important; +} \ No newline at end of file diff --git a/docs-site/assets/scss/_variables_project.scss b/docs-site/assets/scss/_variables_project.scss new file mode 100644 index 000000000..841966640 --- /dev/null +++ b/docs-site/assets/scss/_variables_project.scss @@ -0,0 +1,4 @@ +$primary: #80a7e9; +$secondary: #4484f4; + +$navbar-dark-bg: $primary; \ No newline at end of file diff --git a/docs-site/assets/scss/main.scss b/docs-site/assets/scss/main.scss new file mode 100644 index 000000000..866272c07 --- /dev/null +++ b/docs-site/assets/scss/main.scss @@ -0,0 +1 @@ +@import "td/main"; \ No newline at end of file diff --git a/docs-site/go.mod b/docs-site/go.mod new file mode 100644 index 000000000..b49fd08d9 --- /dev/null +++ b/docs-site/go.mod @@ -0,0 +1,8 @@ +module github.com/googleapis/mcp-toolbox-sdk-js/docs-site + +go 1.24.13 + +require ( + github.com/google/docsy v0.14.3 // indirect + github.com/google/docsy/dependencies v0.7.2 // indirect +) diff --git a/docs-site/go.sum b/docs-site/go.sum new file mode 100644 index 000000000..91e513190 --- /dev/null +++ b/docs-site/go.sum @@ -0,0 +1,8 @@ +github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/FortAwesome/Font-Awesome v0.0.0-20241216213156-af620534bfc3/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo= +github.com/google/docsy v0.14.3 h1:4uFgPWTPj4NT79IboVkXGi49LLQadLVfU4WNOfD/s74= +github.com/google/docsy v0.14.3/go.mod h1:1Fj1W1O3esZh7IBQ8XAYtxtg10udBXuGI89+LUQc1AU= +github.com/google/docsy/dependencies v0.7.2 h1:+t5ufoADQAj4XneFphz4A+UU0ICAxmNaRHVWtMYXPSI= +github.com/google/docsy/dependencies v0.7.2/go.mod h1:gihhs5gmgeO+wuoay4FwOzob+jYJVyQbNaQOh788lD4= +github.com/twbs/bootstrap v5.2.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= +github.com/twbs/bootstrap v5.3.8+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0= diff --git a/docs-site/hugo.toml b/docs-site/hugo.toml new file mode 100644 index 000000000..ce455fbd6 --- /dev/null +++ b/docs-site/hugo.toml @@ -0,0 +1,91 @@ +title = "MCP Toolbox JS API" + +[params] + offlineSearch = true + copyright = "Google LLC" + +# Hand-edited version lists, one per package. Newest first — the order is +# mirrored into the dropdown. Add a block before tagging a release, and only +# list versions whose /// docs already exist (or will after the +# backfill run), or the dropdown link 404s. URLs are root-relative so they +# resolve against whatever host serves the page (production or staging). +[params.versions] + [[params.versions.core]] + version = "dev" + url = "/core/dev/" + [[params.versions.core]] + version = "v1.0.0" + url = "/core/v1.0.0/" + [[params.versions.core]] + version = "v0.3.0" + url = "/core/v0.3.0/" + [[params.versions.core]] + version = "v0.2.1" + url = "/core/v0.2.1/" + [[params.versions.adk]] + version = "dev" + url = "/adk/dev/" + [[params.versions.adk]] + version = "v0.3.0" + url = "/adk/v0.3.0/" + [[params.versions.adk]] + version = "v0.2.1" + url = "/adk/v0.2.1/" + [[params.versions.adk]] + version = "v0.2.0" + url = "/adk/v0.2.0/" + +[markup.goldmark.renderer] + unsafe = true + +# Resolve TypeDoc's relative .md / _index.md links to per-version pretty URLs. +# Required because the JS docs are generated by TypeDoc (a multi-file markdown +# tree); the Go SDK's gomarkdoc output is a single page and does not need this. +[markup.goldmark.renderHooks.link] + useEmbedded = "fallback" + +[markup.highlight] + noClasses = false + style = "tango" + +[params.ui] + navbar_logo = true + sidebar_menu_foldable = true + ul_show = 2 + breadcrumb_disable = true + sidebar_menu_compact = false + showLightDarkModeMenu = true + +[[menu.main]] + name = "Documentation" + url = "https://mcp-toolbox.dev" + weight = 10 + +[[menu.main]] + name = "GitHub" + url = "https://github.com/googleapis/mcp-toolbox-sdk-js" + weight = 20 + pre = "" + +[outputFormats] + # Dropdown fragment, fetched at runtime by the navbar version selector so + # frozen old version pages show newly-added versions without a rebuild. + [outputFormats.releases] + baseName = "releases" + isPlainText = true + mediaType = "text/releases" + # Per-package "latest" redirect, hoisted to //latest/index.html. + [outputFormats.latest] + baseName = "latest" + mediaType = "text/html" + isHTML = true + +[mediaTypes."text/releases"] + suffixes = ["releases"] + +[outputs] + home = ["HTML", "JSON", "releases", "latest"] # JSON kept for offline search + +[module] + [[module.imports]] + path = "github.com/google/docsy" diff --git a/docs-site/layouts/_default/home.latest.html b/docs-site/layouts/_default/home.latest.html new file mode 100644 index 000000000..8bcec6c90 --- /dev/null +++ b/docs-site/layouts/_default/home.latest.html @@ -0,0 +1,11 @@ +{{- $pkg := .Site.Params.package | default "" -}} +{{- $target := printf "/%s/dev/" $pkg -}} +{{- with index .Site.Params.versions $pkg }} + {{- range . }}{{ if ne .version "dev" }}{{ $target = .url }}{{ break }}{{ end }}{{ end }} +{{- end -}} + + + + +Redirecting… + diff --git a/docs-site/layouts/_default/home.releases.releases b/docs-site/layouts/_default/home.releases.releases new file mode 100644 index 000000000..d3464f915 --- /dev/null +++ b/docs-site/layouts/_default/home.releases.releases @@ -0,0 +1,7 @@ +{{- $pkg := .Site.Params.package | default "" -}} +latest +{{- with index .Site.Params.versions $pkg }} + {{- range . }} +{{ .version }} + {{- end }} +{{- end -}} diff --git a/docs-site/layouts/_partials/hooks/head-end.html b/docs-site/layouts/_partials/hooks/head-end.html new file mode 100644 index 000000000..abcb1b968 --- /dev/null +++ b/docs-site/layouts/_partials/hooks/head-end.html @@ -0,0 +1 @@ + diff --git a/docs-site/layouts/_partials/navbar-version-selector.html b/docs-site/layouts/_partials/navbar-version-selector.html new file mode 100644 index 000000000..7a716f16f --- /dev/null +++ b/docs-site/layouts/_partials/navbar-version-selector.html @@ -0,0 +1,16 @@ +{{/* Require a package context: on the rootless landing $pkg is empty, which + would emit a broken //releases.releases include and a meaningless picker. */ -}} +{{ if and .Site.Params.versions .Site.Params.package -}} +{{ $pkg := .Site.Params.package | default "" -}} + +{{ end -}} diff --git a/docs-site/layouts/_partials/sidebar-tree.html b/docs-site/layouts/_partials/sidebar-tree.html new file mode 100644 index 000000000..adb5441e1 --- /dev/null +++ b/docs-site/layouts/_partials/sidebar-tree.html @@ -0,0 +1,199 @@ +{{ $context := .context -}} +{{ $sidebarRoot := .sidebarRoot -}} +{{ $sidebarRootID := .sidebarRootID -}} +{{ $cacheSidebar := .cacheSidebar -}} + +{{ with $context -}} + +{{/* When the sidebar is cached, "active" class is set client side. */ -}} +{{ $shouldDelayActive := $cacheSidebar -}} + +
+ {{ if not .Site.Params.ui.sidebar_search_disable -}} + + + + {{- else -}} + +
+ +
+
+ + {{- end }} + {{/* */ -}} + + +
+ +{{- end }}{{/* with $context */ -}} + +{{ define "section-tree-nav-section" -}} + {{/* cSpell:ignore manuallink manuallinkrelref manuallinktitle */ -}} + {{ $s := .section -}} + {{ $p := .page -}} + {{ $shouldDelayActive := .shouldDelayActive -}} + {{ $sidebarMenuTruncate := .sidebarMenuTruncate -}} + {{ $treeRoot := cond (eq .ulNr 0) true false -}} + {{ $ulNr := .ulNr -}} + {{ $ulShow := .ulShow -}} + {{ $active := and (not $shouldDelayActive) (eq $s $p) -}} + {{ $activePath := and (not $shouldDelayActive) (or (eq $p $s) ($p.IsDescendant $s)) -}} + {{ $show := cond + (or + (lt $ulNr $ulShow) + $activePath + (and (not $shouldDelayActive) (eq $s.Parent $p.Parent)) + (and (not $shouldDelayActive) (eq $s.Parent $p)) + (not $p.Site.Params.ui.sidebar_menu_compact) + (and (not $shouldDelayActive) ($p.IsDescendant $s.Parent)) + ) + true false + -}} + {{ $mid := printf "m-%s" ($s.RelPermalink | anchorize) -}} + {{ $pages_tmp := where (union $s.Pages $s.Sections).ByWeight ".Params.toc_hide" "!=" true -}} + {{ $pages := $pages_tmp | first $sidebarMenuTruncate -}} + {{ $truncatedEntryCount := sub (len $pages_tmp) $sidebarMenuTruncate -}} + + {{ if gt $truncatedEntryCount 0 -}} + {{ warnf "WARNING: %d sidebar entries have been truncated. To avoid this, increase `params.ui.sidebar_menu_truncate` to at least %d (from %d) in your config file. Section: %s" + $truncatedEntryCount (len $pages_tmp) $sidebarMenuTruncate $s.Path -}} + {{ end -}} + + {{ $withChild := gt (len $pages) 0 -}} + {{ $manualLink := + cond + (isset $s.Params "manuallink") + $s.Params.manualLink + (cond + (isset $s.Params "manuallinkrelref") + (relref $s $s.Params.manualLinkRelref) + $s.RelPermalink + ) + -}} + {{ $manualLinkTitle := + cond + (isset $s.Params "manuallinktitle") + $s.Params.manualLinkTitle + $s.Title + -}} + {{ if and $treeRoot (eq $s.Params.sidebar_root_for "self") -}} + {{ with $s.Parent -}} + {{ $manualLink = .RelPermalink -}} + {{ end -}} + {{ end -}} +
  • + {{ if (and $p.Site.Params.ui.sidebar_menu_foldable (ge $ulNr 1)) -}} + + + {{ else -}} + + {{- with $s.Params.Icon -}} + + {{- end -}} + + {{- $s.LinkTitle -}} + + {{- end -}} + {{ if $withChild -}} + {{ $ulNr := add $ulNr 1 }} +
      + {{ range $pages -}} + {{ if (not (and (eq $s $p.Site.Home) (eq .Params.toc_root true))) -}} + {{ template "section-tree-nav-section" (dict "page" $p "section" . "shouldDelayActive" $shouldDelayActive "sidebarMenuTruncate" $sidebarMenuTruncate "ulNr" $ulNr "ulShow" $ulShow) }} + {{- end }} + {{- end }} +
    + {{- end }} +
  • +{{- end -}} diff --git a/docs-site/package.json b/docs-site/package.json new file mode 100644 index 000000000..de75fcbd7 --- /dev/null +++ b/docs-site/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "autoprefixer": "^10.5.0", + "postcss": "^8.5.15", + "postcss-cli": "^11.0.1" + } +} diff --git a/docs-site/static/favicons/android-chrome-192x192.png b/docs-site/static/favicons/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..f2c81724e948fcf8b7191e99e1f17737706ae215 GIT binary patch literal 7530 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 literal 0 HcmV?d00001 diff --git a/docs-site/static/favicons/android-chrome-512x512.png b/docs-site/static/favicons/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..ad324c0d5f98e31e2a9a70a893e6b207329619a1 GIT binary patch literal 28023 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 literal 0 HcmV?d00001 diff --git a/docs-site/static/favicons/favicon-16x16.png b/docs-site/static/favicons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..51f407b9cd4caf49d1d920a9169b1a18f6806e0b GIT binary patch literal 576 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�wtC|-9T3=puG`g8}Sa0u=-l7G!s$h7{;5WY2{y;H{YpO ze*&C!>D8a3|6GajL5vRZtTj$U-V$fIrXQMS6)wTJ<3oAG{CfL8+H(asi#~_?G#|T7 zh5cf*>E!P$9sdwwO?#PsMcU)iYqubV5LDf(S7Sve;XyAIWsy2`B?N!8$G9=I0XK^5~>j|AU=cdLFbu2 zosKN_`|hrnOPWypl)j}EdQA@O@!(M96Dz$5{)tuGk?Xbg8A)R=-v<7zh=;YBbe-)> z`F=5Gu|0A8=MG%i_@qAatLLV~VKc6QuFZ>Mh`jN1Nn~R$E^S;?64_#(9OL7c>WuFagE zMSiasv{r-j*Tcq}tqm3YUtBmNx79Rp4bI|rDY>&e=DV}#OZ9Z-Lf*b?6yE)d;2$2= zHYoU$Kh$QPn$>D5s>6H{=ci!4`DisiRZso~jm6P90`Gy&;-Vezq2C_CnV_ShmpdBr za>qhG(=iDMc}>UBua9FrdJ5&l#J1wuNqU|NkUNtogF3rV*9oN1!M!7St+~p+P5D-H zF^B$7=V*HHKK3{BlcIf$l_UPKJic{#lkK64LhU%Y!#=)i^Mb6d*Xpw6O?I{X%LO^| zh9#QFhPe;pyG}gA+;b^7r$k!+Y;G#x%mtswA7jGry4TOwMRjbokCEZyGA=BQp06-Y zaA3YZ=blwmM>c2AC{^-T-cOak;4zMs1oIyfxb(<@itnY8q5Btw*)tMk;P;w;EqhYO zG#+7_h=4}U@VECPhZ9ubQ$-*!FPT&9_DV8`2uG$wtd;Y zG~||rHh!q}oawNS?he$>2A|~^a~p7`$bm7}iL+OYI6LHqZ?zKs$!Z3vy=HlM p{hV@nyJr-1Va+@6Ig)|ODEVjd84F}Akg-6<0vQWrEO2Km@P9KRT|xi= literal 0 HcmV?d00001 diff --git a/docs-site/static/js/w3.js b/docs-site/static/js/w3.js new file mode 100644 index 000000000..331fe8876 --- /dev/null +++ b/docs-site/static/js/w3.js @@ -0,0 +1,34 @@ +/* Trimmed from W3.JS 1.04 (w3schools.com): only w3.includeHTML, plus a + w3-include-html-default fallback rendered on a 404. Used by the navbar + version selector to fetch //releases.releases at runtime. */ +"use strict"; +var w3 = {}; +w3.includeHTML = function (cb) { + var z, i, elmnt, file, xhttp; + z = document.getElementsByTagName("*"); + for (i = 0; i < z.length; i++) { + elmnt = z[i]; + file = elmnt.getAttribute("w3-include-html"); + if (file) { + xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function () { + if (this.readyState == 4) { + if (this.status == 200) { elmnt.innerHTML = this.responseText; } + if (this.status == 404) { + if (elmnt.getAttribute("w3-include-html-default")) { + elmnt.innerHTML = elmnt.getAttribute("w3-include-html-default"); + } else { + elmnt.innerHTML = "Page not found."; + } + } + elmnt.removeAttribute("w3-include-html"); + w3.includeHTML(cb); + } + }; + xhttp.open("GET", file, true); + xhttp.send(); + return; + } + } + if (cb) cb(); +}; From 2d5b8fd5d201f214e583ce6f09f9b7015bb5deed Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Mon, 22 Jun 2026 13:35:50 +0530 Subject: [PATCH 02/15] docs: retarget docs-site scaffold for the Python SDK Applies the Python-specific edits on top of the verbatim JS copy. Every change is listed so it can be diffed against the JS pipeline: - hugo.toml: title -> MCP Toolbox Python API; [params.versions] rewritten to the four Python packages (core, adk, langchain, llamaindex), dev only; GitHub menu link -> the Python repo; [markup.goldmark.renderHooks.link] useEmbedded = fallback kept as a safety net for any relative .md links from pydoc-markdown's crossref processor. - go.mod: module path -> .../mcp-toolbox-sdk-python/docs-site (docsy still pinned v0.14.3, matching Go/JS). - sidebar-tree.html: cross-package links core/adk -> core/adk/langchain/llamaindex. - .gitignore: ignore Hugo build output (public/, resources/, .hugo_build.lock, node_modules/) and docs-site/package-lock.json. Verified: hugo v0.152.2 extended builds the scaffold clean (Docsy main.css compiles via PostCSS/autoprefixer); only the harmless no-layout-for-json home warning remains. --- .gitignore | 7 ++++ docs-site/go.mod | 2 +- docs-site/hugo.toml | 34 ++++++------------- docs-site/layouts/_partials/sidebar-tree.html | 6 ++++ 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index fc7b2d042..1875683e9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,10 @@ __pycache__/** **/.coverage build/ **/build/ + +# Hugo docs-site build output +node_modules/ +docs-site/public/ +docs-site/resources/ +.hugo_build.lock +docs-site/package-lock.json diff --git a/docs-site/go.mod b/docs-site/go.mod index b49fd08d9..26f9311f6 100644 --- a/docs-site/go.mod +++ b/docs-site/go.mod @@ -1,4 +1,4 @@ -module github.com/googleapis/mcp-toolbox-sdk-js/docs-site +module github.com/googleapis/mcp-toolbox-sdk-python/docs-site go 1.24.13 diff --git a/docs-site/hugo.toml b/docs-site/hugo.toml index ce455fbd6..75eb2fac8 100644 --- a/docs-site/hugo.toml +++ b/docs-site/hugo.toml @@ -1,4 +1,4 @@ -title = "MCP Toolbox JS API" +title = "MCP Toolbox Python API" [params] offlineSearch = true @@ -13,34 +13,22 @@ title = "MCP Toolbox JS API" [[params.versions.core]] version = "dev" url = "/core/dev/" - [[params.versions.core]] - version = "v1.0.0" - url = "/core/v1.0.0/" - [[params.versions.core]] - version = "v0.3.0" - url = "/core/v0.3.0/" - [[params.versions.core]] - version = "v0.2.1" - url = "/core/v0.2.1/" [[params.versions.adk]] version = "dev" url = "/adk/dev/" - [[params.versions.adk]] - version = "v0.3.0" - url = "/adk/v0.3.0/" - [[params.versions.adk]] - version = "v0.2.1" - url = "/adk/v0.2.1/" - [[params.versions.adk]] - version = "v0.2.0" - url = "/adk/v0.2.0/" + [[params.versions.langchain]] + version = "dev" + url = "/langchain/dev/" + [[params.versions.llamaindex]] + version = "dev" + url = "/llamaindex/dev/" [markup.goldmark.renderer] unsafe = true -# Resolve TypeDoc's relative .md / _index.md links to per-version pretty URLs. -# Required because the JS docs are generated by TypeDoc (a multi-file markdown -# tree); the Go SDK's gomarkdoc output is a single page and does not need this. +# Resolve relative .md / _index.md links to per-version pretty URLs. Kept as a +# safety net for any cross-links pydoc-markdown's crossref processor emits so +# none leak as raw .md hrefs once fed through Hugo. [markup.goldmark.renderHooks.link] useEmbedded = "fallback" @@ -63,7 +51,7 @@ title = "MCP Toolbox JS API" [[menu.main]] name = "GitHub" - url = "https://github.com/googleapis/mcp-toolbox-sdk-js" + url = "https://github.com/googleapis/mcp-toolbox-sdk-python" weight = 20 pre = "" diff --git a/docs-site/layouts/_partials/sidebar-tree.html b/docs-site/layouts/_partials/sidebar-tree.html index adb5441e1..775c57db1 100644 --- a/docs-site/layouts/_partials/sidebar-tree.html +++ b/docs-site/layouts/_partials/sidebar-tree.html @@ -68,6 +68,12 @@
  • ADK
  • +
  • + LangChain +
  • +
  • + LlamaIndex +
  • From 913c0245987891dd7ee2ddd07c701ac4fa3572dd Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Mon, 22 Jun 2026 13:55:46 +0530 Subject: [PATCH 03/15] docs: copy doc-generation scripts verbatim from Go SDK --- scripts/generate-api-docs.sh | 62 ++++++++++++++++++++++++++++++++++++ scripts/generate-root.sh | 47 +++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100755 scripts/generate-api-docs.sh create mode 100755 scripts/generate-root.sh diff --git a/scripts/generate-api-docs.sh b/scripts/generate-api-docs.sh new file mode 100755 index 000000000..1a51b58ed --- /dev/null +++ b/scripts/generate-api-docs.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed 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. + +set -euo pipefail + +export PATH="$PATH:$(go env GOPATH)/bin" + +PACKAGE="${1:?package required (core|tbadk|tbgenkit)}" +VERSION="${2:?version required (e.g. v1.0.0 or dev)}" +BASE_URL="${3:-/}" + +case "$PACKAGE" in + core) TITLE="Core" ;; + tbadk) TITLE="Tbadk" ;; + tbgenkit) TITLE="Tbgenkit" ;; + *) echo "Unknown package: $PACKAGE" >&2; exit 1 ;; +esac + +go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest + +# Per-build content tree in a temp dir, kept out of the checked-in +# docs-site/content so concurrent package builds never trample each other. +# The package's API reference is the home page, so /// lands +# directly on the docs (the repo README lives only at the site root). +CONTENT_DIR="$(mktemp -d)" +trap 'rm -rf "$CONTENT_DIR"' EXIT + +cat > "$CONTENT_DIR/_index.md" <> "$CONTENT_DIR/_index.md" + +cd docs-site +HUGO_PARAMS_VERSION="${VERSION}" HUGO_PARAMS_PACKAGE="${PACKAGE}" hugo \ + --minify \ + --contentDir "${CONTENT_DIR}" \ + --baseURL "${BASE_URL}${PACKAGE}/${VERSION}/" \ + --destination "public/${PACKAGE}/${VERSION}" + +# Hoist the home-scoped outputs from this version's dir up to the package root, +# where the navbar version selector fetches them. They list every version of the +# package, so they must live once per package (not per version) and are shared +# across all of this package's version pages. keep_files on deploy preserves them. +mv "public/${PACKAGE}/${VERSION}/releases.releases" "public/${PACKAGE}/releases.releases" +mkdir -p "public/${PACKAGE}/latest" +mv "public/${PACKAGE}/${VERSION}/latest.html" "public/${PACKAGE}/latest/index.html" diff --git a/scripts/generate-root.sh b/scripts/generate-root.sh new file mode 100755 index 000000000..66cc318af --- /dev/null +++ b/scripts/generate-root.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Copyright 2026 Google LLC +# +# Licensed 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. + +set -euo pipefail + +BASE_URL="${1:-/}" + +# Render the repo README (from the checked-out tag) as the root landing page. +# Built only on tag pushes so the root URL tracks the latest release and stays +# stable between main-branch dev builds. +CONTENT_DIR="$(mktemp -d)" +trap 'rm -rf "$CONTENT_DIR"' EXIT + +cat > "$CONTENT_DIR/_index.md" </ { intoc = 1 } + intoc { if (//) intoc = 0; next } + !h1done && /^# / { h1done = 1; next } + { print } +' README.md >> "$CONTENT_DIR/_index.md" + +cd docs-site +hugo \ + --minify \ + --contentDir "${CONTENT_DIR}" \ + --baseURL "${BASE_URL}" \ + --destination "public" From b0e76af1bf9f47610e08a9dd2dcdf5a4ab7a4b22 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Mon, 22 Jun 2026 13:57:05 +0530 Subject: [PATCH 04/15] docs: add pydoc-markdown pin for API doc generation --- docs-site/requirements.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs-site/requirements.txt diff --git a/docs-site/requirements.txt b/docs-site/requirements.txt new file mode 100644 index 000000000..e9079a625 --- /dev/null +++ b/docs-site/requirements.txt @@ -0,0 +1,5 @@ +# Pins the API reference doc generator used by scripts/generate-api-docs.sh. +# pydoc-markdown parses the SDK source statically (no install/import of the +# packages), pulling docspec-python transitively. Keep in sync with the version +# installed in .github/workflows/api-docs.yml. +pydoc-markdown==4.8.2 From f91f26ab6bc9939e8fc1e0f425daed5396ffbfcd Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Mon, 22 Jun 2026 13:57:21 +0530 Subject: [PATCH 05/15] docs: retarget doc-generation scripts for the Python SDK --- scripts/generate-api-docs.sh | 86 +++++++++++++++++++++++++++++------- scripts/generate-root.sh | 2 +- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/scripts/generate-api-docs.sh b/scripts/generate-api-docs.sh index 1a51b58ed..e0b469fb4 100755 --- a/scripts/generate-api-docs.sh +++ b/scripts/generate-api-docs.sh @@ -15,36 +15,90 @@ set -euo pipefail -export PATH="$PATH:$(go env GOPATH)/bin" - -PACKAGE="${1:?package required (core|tbadk|tbgenkit)}" +PACKAGE="${1:?package required (core|adk|langchain|llamaindex)}" VERSION="${2:?version required (e.g. v1.0.0 or dev)}" BASE_URL="${3:-/}" +# Absolute repo root: the pydoc-markdown config's search_path is resolved +# relative to the config file's directory (a temp dir), not the CWD, so it must +# be absolute. Captured before the later `cd docs-site`. +ROOT="$(pwd)" + +# Map the URL slug to its package title and the curated list of public modules +# to document. The list is explicit (not whole-package recursion) so internal +# surface -- utils, itransport, the mcp_transport.v* protocol impls, and every +# package's version module -- stays out of the page, matching the Go/JS docs. case "$PACKAGE" in - core) TITLE="Core" ;; - tbadk) TITLE="Tbadk" ;; - tbgenkit) TITLE="Tbgenkit" ;; - *) echo "Unknown package: $PACKAGE" >&2; exit 1 ;; + core) + TITLE="Core" + MODULES=(client sync_client tool sync_tool auth_methods protocol) ;; + adk) + TITLE="ADK" + MODULES=(client tool toolset credentials) ;; + langchain) + TITLE="LangChain" + MODULES=(client tools async_client async_tools) ;; + llamaindex) + TITLE="LlamaIndex" + MODULES=(client tools async_client async_tools) ;; + *) echo "Unknown package: $PACKAGE" >&2; exit 1 ;; esac -go install github.com/princjef/gomarkdoc/cmd/gomarkdoc@latest +DIR="packages/toolbox-${PACKAGE}" +MODULE="toolbox_${PACKAGE}" # Per-build content tree in a temp dir, kept out of the checked-in # docs-site/content so concurrent package builds never trample each other. # The package's API reference is the home page, so /// lands # directly on the docs (the repo README lives only at the site root). CONTENT_DIR="$(mktemp -d)" -trap 'rm -rf "$CONTENT_DIR"' EXIT +CFG="$(mktemp)" +# return 0 so a leftover non-zero never becomes the script's exit code, since an +# EXIT trap's last status replaces it. +cleanup() { rm -rf "$CONTENT_DIR"; rm -f "$CFG"; return 0; } +trap cleanup EXIT + +# Build the YAML module block (" - toolbox_." per line). +MODULE_YAML="" +for m in "${MODULES[@]}"; do + MODULE_YAML+=" - ${MODULE}.${m}"$'\n' +done -cat > "$CONTENT_DIR/_index.md" < a single _index.md, the Hugo section index for +# ///. Parameters render as lists (Go-SDK style); the Raises +# section is kept as pydoc-markdown emits it. +cat > "$CFG" <> "$CONTENT_DIR/_index.md" +# Prepend Docsy frontmatter (type: docs + the friendly " (<version>)" +# heading) to the generated page so Docsy renders the section index correctly. +tmp="$(mktemp)" +{ printf -- '---\ntitle: "%s"\ntype: docs\n---\n\n' "${TITLE} (${VERSION})"; cat "${CONTENT_DIR}/_index.md"; } > "$tmp" +mv "$tmp" "${CONTENT_DIR}/_index.md" cd docs-site HUGO_PARAMS_VERSION="${VERSION}" HUGO_PARAMS_PACKAGE="${PACKAGE}" hugo \ diff --git a/scripts/generate-root.sh b/scripts/generate-root.sh index 66cc318af..dba506136 100755 --- a/scripts/generate-root.sh +++ b/scripts/generate-root.sh @@ -25,7 +25,7 @@ trap 'rm -rf "$CONTENT_DIR"' EXIT cat > "$CONTENT_DIR/_index.md" <<EOF --- -title: "MCP Toolbox Go SDK" +title: "MCP Toolbox Python API Reference" type: docs --- EOF From 7d4ff0aec2742f226926874f805e71a65f6ded1e Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 14:13:38 +0530 Subject: [PATCH 06/15] docs: copy api-docs workflow verbatim from Go SDK --- .github/workflows/api-docs.yml | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/api-docs.yml diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml new file mode 100644 index 000000000..aee6d27c9 --- /dev/null +++ b/.github/workflows/api-docs.yml @@ -0,0 +1,97 @@ +# Copyright 2026 Google LLC +# +# Licensed 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. + + +name: "API Reference Deployment" +on: + push: + branches: [ 'main' ] + tags: [ '**' ] + workflow_dispatch: + +concurrency: + group: api-docs-deploy + cancel-in-progress: false + +jobs: + deploy: + # Never run on forks; docs deploy only from the upstream repository. + if: github.repository == 'googleapis/mcp-toolbox-sdk-go' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout Code + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + submodules: recursive + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version: '1.25.0' + + - name: Setup Hugo + uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3 + with: + hugo-version: '0.152.2' + extended: true + + - name: Install PostCSS Dependencies + run: | + cd docs-site + npm install postcss postcss-cli autoprefixer + + - name: Resolve build target + id: resolve + run: | + # Route the git ref to the package(s) and version to build. + # A per-package tag builds that one package; pushes to main (and manual + # dispatch) build all three as "dev". Any other tag is skipped. + REF="${GITHUB_REF}" + case "$REF" in + refs/tags/core/v*) echo "packages=core" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/core/}" >> "$GITHUB_OUTPUT" ;; + refs/tags/tbadk/v*) echo "packages=tbadk" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/tbadk/}" >> "$GITHUB_OUTPUT" ;; + refs/tags/tbgenkit/v*) echo "packages=tbgenkit" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/tbgenkit/}" >> "$GITHUB_OUTPUT" ;; + refs/tags/*) echo "packages=" >> "$GITHUB_OUTPUT"; echo "version=" >> "$GITHUB_OUTPUT" ;; + *) echo "packages=core tbadk tbgenkit" >> "$GITHUB_OUTPUT"; echo "version=dev" >> "$GITHUB_OUTPUT" ;; + esac + + # Deploys only run upstream (see job-level guard), so always use the + # production domain. + echo "BASE_URL=https://go.mcp-toolbox.dev/" >> "$GITHUB_ENV" + + - name: Build per-package docs + if: steps.resolve.outputs.packages != '' + run: | + chmod +x scripts/generate-api-docs.sh + for PKG in ${{ steps.resolve.outputs.packages }}; do + ./scripts/generate-api-docs.sh "$PKG" "${{ steps.resolve.outputs.version }}" "$BASE_URL" + done + + - name: Build root page + if: steps.resolve.outputs.packages != '' && startsWith(github.ref, 'refs/tags/') + run: | + chmod +x scripts/generate-root.sh + ./scripts/generate-root.sh "$BASE_URL" + + - name: Deploy to gh-pages + if: steps.resolve.outputs.packages != '' + uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs-site/public + keep_files: true + cname: ${{ github.repository == 'googleapis/mcp-toolbox-sdk-go' && 'go.mcp-toolbox.dev' || '' }} From 1f26da021d7d1ef8a79a999e98f5056b86074850 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 14:16:06 +0530 Subject: [PATCH 07/15] docs: retarget api-docs workflow for the Python SDK --- .github/workflows/api-docs.yml | 46 +++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml index aee6d27c9..8f1965214 100644 --- a/.github/workflows/api-docs.yml +++ b/.github/workflows/api-docs.yml @@ -27,51 +27,63 @@ concurrency: jobs: deploy: # Never run on forks; docs deploy only from the upstream repository. - if: github.repository == 'googleapis/mcp-toolbox-sdk-go' + if: github.repository == 'googleapis/mcp-toolbox-sdk-python' runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout Code - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: submodules: recursive fetch-depth: 0 - - name: Set up Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - go-version: '1.25.0' + python-version: '3.13' + + - name: Install doc generator + run: | + # pydoc-markdown parses the SDK source statically (no install/import of + # the packages), so no package build step is needed -- unlike the JS + # pipeline, which compiles types before TypeDoc runs. + pip install -r docs-site/requirements.txt - name: Setup Hugo uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3 with: hugo-version: '0.152.2' - extended: true - + extended: true + - name: Install PostCSS Dependencies run: | + # --no-workspaces installs into docs-site/node_modules (where Hugo's + # PostCSS looks). docs-site/package.json pins postcss/postcss-cli/ + # autoprefixer. cd docs-site - npm install postcss postcss-cli autoprefixer + npm install --no-workspaces - name: Resolve build target id: resolve run: | # Route the git ref to the package(s) and version to build. # A per-package tag builds that one package; pushes to main (and manual - # dispatch) build all three as "dev". Any other tag is skipped. + # dispatch) build all four as "dev". Python release tags are + # toolbox-<name>-vX.Y.Z; release-please-* and any other tag are skipped. REF="${GITHUB_REF}" case "$REF" in - refs/tags/core/v*) echo "packages=core" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/core/}" >> "$GITHUB_OUTPUT" ;; - refs/tags/tbadk/v*) echo "packages=tbadk" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/tbadk/}" >> "$GITHUB_OUTPUT" ;; - refs/tags/tbgenkit/v*) echo "packages=tbgenkit" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/tbgenkit/}" >> "$GITHUB_OUTPUT" ;; - refs/tags/*) echo "packages=" >> "$GITHUB_OUTPUT"; echo "version=" >> "$GITHUB_OUTPUT" ;; - *) echo "packages=core tbadk tbgenkit" >> "$GITHUB_OUTPUT"; echo "version=dev" >> "$GITHUB_OUTPUT" ;; + refs/tags/toolbox-core-v*) echo "packages=core" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/toolbox-core-}" >> "$GITHUB_OUTPUT" ;; + refs/tags/toolbox-adk-v*) echo "packages=adk" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/toolbox-adk-}" >> "$GITHUB_OUTPUT" ;; + refs/tags/toolbox-langchain-v*) echo "packages=langchain" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/toolbox-langchain-}" >> "$GITHUB_OUTPUT" ;; + refs/tags/toolbox-llamaindex-v*) echo "packages=llamaindex" >> "$GITHUB_OUTPUT"; echo "version=${REF#refs/tags/toolbox-llamaindex-}" >> "$GITHUB_OUTPUT" ;; + refs/tags/*) echo "packages=" >> "$GITHUB_OUTPUT"; echo "version=" >> "$GITHUB_OUTPUT" ;; + *) echo "packages=core adk langchain llamaindex" >> "$GITHUB_OUTPUT"; echo "version=dev" >> "$GITHUB_OUTPUT" ;; esac # Deploys only run upstream (see job-level guard), so always use the # production domain. - echo "BASE_URL=https://go.mcp-toolbox.dev/" >> "$GITHUB_ENV" + echo "BASE_URL=https://py.mcp-toolbox.dev/" >> "$GITHUB_ENV" - name: Build per-package docs if: steps.resolve.outputs.packages != '' @@ -93,5 +105,5 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs-site/public - keep_files: true - cname: ${{ github.repository == 'googleapis/mcp-toolbox-sdk-go' && 'go.mcp-toolbox.dev' || '' }} + keep_files: true + cname: ${{ github.repository == 'googleapis/mcp-toolbox-sdk-python' && 'py.mcp-toolbox.dev' || '' }} From 44e7b1f557b31ea0a7895931b69d4e45cfec7d6d Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 14:16:50 +0530 Subject: [PATCH 08/15] docs: seed released versions in the version selector --- docs-site/hugo.toml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs-site/hugo.toml b/docs-site/hugo.toml index 75eb2fac8..a6ec3cd5f 100644 --- a/docs-site/hugo.toml +++ b/docs-site/hugo.toml @@ -13,15 +13,51 @@ title = "MCP Toolbox Python API" [[params.versions.core]] version = "dev" url = "/core/dev/" + [[params.versions.core]] + version = "v1.1.0" + url = "/core/v1.1.0/" + [[params.versions.core]] + version = "v1.0.0" + url = "/core/v1.0.0/" + [[params.versions.core]] + version = "v0.6.0" + url = "/core/v0.6.0/" [[params.versions.adk]] version = "dev" url = "/adk/dev/" + [[params.versions.adk]] + version = "v1.0.1" + url = "/adk/v1.0.1/" + [[params.versions.adk]] + version = "v1.0.0" + url = "/adk/v1.0.0/" + [[params.versions.adk]] + version = "v0.7.0" + url = "/adk/v0.7.0/" [[params.versions.langchain]] version = "dev" url = "/langchain/dev/" + [[params.versions.langchain]] + version = "v1.0.1" + url = "/langchain/v1.0.1/" + [[params.versions.langchain]] + version = "v1.0.0" + url = "/langchain/v1.0.0/" + [[params.versions.langchain]] + version = "v0.6.0" + url = "/langchain/v0.6.0/" [[params.versions.llamaindex]] version = "dev" url = "/llamaindex/dev/" + [[params.versions.llamaindex]] + version = "v1.0.0" + url = "/llamaindex/v1.0.0/" + [[params.versions.llamaindex]] + version = "v0.7.0" + url = "/llamaindex/v0.7.0/" + [[params.versions.llamaindex]] + version = "v0.6.0" + url = "/llamaindex/v0.6.0/" [markup.goldmark.renderer] unsafe = true From 0294d12f0254f62f7eb50715ccf2379d68ef5a50 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 15:09:47 +0530 Subject: [PATCH 09/15] docs: copy api-docs backfill workflow verbatim from Go SDK --- .github/workflows/api-docs-backfill.yml | 133 ++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 .github/workflows/api-docs-backfill.yml diff --git a/.github/workflows/api-docs-backfill.yml b/.github/workflows/api-docs-backfill.yml new file mode 100644 index 000000000..068ae2e18 --- /dev/null +++ b/.github/workflows/api-docs-backfill.yml @@ -0,0 +1,133 @@ +# Copyright 2026 Google LLC +# +# Licensed 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. + + +name: "API Reference Backfill" +on: + workflow_dispatch: + inputs: + package: + description: "Package to backfill" + type: choice + options: [core, tbadk, tbgenkit] + required: true + version: + description: "Version tag to build, e.g. v1.0.0" + type: string + required: true + +# Scope per version: each run produces an independent branch/PR, so runs for +# different versions can proceed in parallel. A shared group with +# cancel-in-progress: false would make GitHub cancel a pending run whenever a +# newer one queues, silently dropping versions when several are dispatched. +concurrency: + group: api-docs-backfill-${{ github.event.inputs.package }}-${{ github.event.inputs.version }} + cancel-in-progress: false + +jobs: + backfill: + # Never run on forks; docs deploy only from the upstream repository. + if: github.repository == 'googleapis/mcp-toolbox-sdk-go' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # Build from main so the archived page carries the current version picker; + # only the package's source comes from the tag (overlaid below) so + # gomarkdoc documents that version's API. + - name: Checkout main (current layout + scripts) + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: main + submodules: recursive + + - name: Checkout tagged package source + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: refs/tags/${{ inputs.package }}/${{ inputs.version }} + path: tagged_src + sparse-checkout: ${{ inputs.package }} + + - name: Overlay tagged source onto main + env: + PKG: ${{ inputs.package }} + run: | + rm -rf "$PKG" + mv "tagged_src/$PKG" "$PKG" + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version: '1.25.0' + + - name: Setup Hugo + uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3 + with: + hugo-version: '0.152.2' + extended: true + + - name: Install PostCSS Dependencies + run: | + cd docs-site + npm install postcss postcss-cli autoprefixer + + - name: Build docs + env: + PKG: ${{ inputs.package }} + VER: ${{ inputs.version }} + # Deploys only run upstream (see job-level guard), so always use the + # production domain. + BASE_URL: https://go.mcp-toolbox.dev/ + run: | + chmod +x scripts/generate-api-docs.sh + ./scripts/generate-api-docs.sh "$PKG" "$VER" "$BASE_URL" + + # Open a PR into gh-pages instead of deploying directly, so a human reviews + # before the page goes live. Overlaying the build onto a clone of the live + # gh-pages tree mirrors keep_files: true — existing files (other versions, + # CNAME, .nojekyll) are preserved and the PR diff is just this version. + - name: Open PR against gh-pages + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PKG: ${{ inputs.package }} + VER: ${{ inputs.version }} + run: | + set -euo pipefail + BRANCH="backfill/${PKG}-${VER}" + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + WORK="$(mktemp -d)" + git clone --depth 1 --branch gh-pages --single-branch \ + "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "$WORK" + cp -R "${GITHUB_WORKSPACE}/docs-site/public/." "$WORK/" + + cd "$WORK" + git checkout -B "$BRANCH" + git add -A + if git diff --cached --quiet; then + echo "No documentation changes for ${PKG} ${VER}; skipping PR." + exit 0 + fi + git commit -m "docs(api): backfill ${PKG} ${VER}" + git push -f origin "$BRANCH" + + if gh pr view "$BRANCH" --json number >/dev/null 2>&1; then + echo "PR already open for ${BRANCH}; branch updated." + else + gh pr create --base gh-pages --head "$BRANCH" \ + --title "docs(api): backfill ${PKG} ${VER}" \ + --body "Automated API reference backfill for \`${PKG}/${VER}\`, built from main tooling with the tagged source overlaid. Merging publishes to gh-pages (additive)." + fi From 07c14f3e94a49b98fd93b4cba1178ede0b5f5dc4 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 15:11:47 +0530 Subject: [PATCH 10/15] docs: retarget api-docs backfill workflow for the Python SDK --- .github/workflows/api-docs-backfill.yml | 59 ++++++++++++++++++------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/.github/workflows/api-docs-backfill.yml b/.github/workflows/api-docs-backfill.yml index 068ae2e18..40f868275 100644 --- a/.github/workflows/api-docs-backfill.yml +++ b/.github/workflows/api-docs-backfill.yml @@ -20,7 +20,7 @@ on: package: description: "Package to backfill" type: choice - options: [core, tbadk, tbgenkit] + options: [core, adk, langchain, llamaindex] required: true version: description: "Version tag to build, e.g. v1.0.0" @@ -38,7 +38,7 @@ concurrency: jobs: backfill: # Never run on forks; docs deploy only from the upstream repository. - if: github.repository == 'googleapis/mcp-toolbox-sdk-go' + if: github.repository == 'googleapis/mcp-toolbox-sdk-python' runs-on: ubuntu-latest permissions: contents: write @@ -46,31 +46,57 @@ jobs: steps: # Build from main so the archived page carries the current version picker; # only the package's source comes from the tag (overlaid below) so - # gomarkdoc documents that version's API. + # pydoc-markdown documents that version's API. - name: Checkout main (current layout + scripts) - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: ref: main submodules: recursive + # Map the URL slug to its package directory (the slug is not the directory + # name). + - name: Resolve package directory + id: resolve + env: + PKG: ${{ inputs.package }} + run: | + case "$PKG" in + core) echo "dir=packages/toolbox-core" >> "$GITHUB_OUTPUT" ;; + adk) echo "dir=packages/toolbox-adk" >> "$GITHUB_OUTPUT" ;; + langchain) echo "dir=packages/toolbox-langchain" >> "$GITHUB_OUTPUT" ;; + llamaindex) echo "dir=packages/toolbox-llamaindex" >> "$GITHUB_OUTPUT" ;; + *) echo "Unknown package: $PKG" >&2; exit 1 ;; + esac + - name: Checkout tagged package source - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 with: - ref: refs/tags/${{ inputs.package }}/${{ inputs.version }} + ref: refs/tags/toolbox-${{ inputs.package }}-${{ inputs.version }} path: tagged_src - sparse-checkout: ${{ inputs.package }} + sparse-checkout: ${{ steps.resolve.outputs.dir }} + # Overlay only the tagged package's src/, keeping main's pyproject.toml and + # the docs tooling intact. pydoc-markdown parses src statically, so the + # archived page reflects the tagged version's API. (Go overlays the whole + # package dir; here src-only keeps the rest of main's layout in sync.) - name: Overlay tagged source onto main env: - PKG: ${{ inputs.package }} + DIR: ${{ steps.resolve.outputs.dir }} run: | - rm -rf "$PKG" - mv "tagged_src/$PKG" "$PKG" + rm -rf "$DIR/src" + mv "tagged_src/$DIR/src" "$DIR/src" - - name: Set up Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - go-version: '1.25.0' + python-version: '3.13' + + - name: Install doc generator + run: | + # pydoc-markdown parses the SDK source statically (no install/import of + # the packages), so no package build step is needed -- unlike the JS + # pipeline, which compiles types before TypeDoc runs. + pip install -r docs-site/requirements.txt - name: Setup Hugo uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3 @@ -80,8 +106,11 @@ jobs: - name: Install PostCSS Dependencies run: | + # --no-workspaces installs into docs-site/node_modules (where Hugo's + # PostCSS looks). docs-site/package.json pins postcss/postcss-cli/ + # autoprefixer. cd docs-site - npm install postcss postcss-cli autoprefixer + npm install --no-workspaces - name: Build docs env: @@ -89,7 +118,7 @@ jobs: VER: ${{ inputs.version }} # Deploys only run upstream (see job-level guard), so always use the # production domain. - BASE_URL: https://go.mcp-toolbox.dev/ + BASE_URL: https://py.mcp-toolbox.dev/ run: | chmod +x scripts/generate-api-docs.sh ./scripts/generate-api-docs.sh "$PKG" "$VER" "$BASE_URL" From 2e728191de61f9bfb7849a2d68a429e5ac7d0749 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 16:32:32 +0530 Subject: [PATCH 11/15] build(docs): commit docs-site lockfile for reproducible installs The PostCSS toolchain (autoprefixer/postcss/postcss-cli) was installed with npm install, which re-resolves the latest matching semver on every run. A broken upstream patch (e.g. browserslist 4.28.3) could then fail both the deploy and backfill workflows nondeterministically. Commit the lockfile so npm ci can install the exact, vetted versions instead. --- .gitignore | 1 - docs-site/package-lock.json | 863 ++++++++++++++++++++++++++++++++++++ 2 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 docs-site/package-lock.json diff --git a/.gitignore b/.gitignore index 1875683e9..d48c7af8c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,3 @@ node_modules/ docs-site/public/ docs-site/resources/ .hugo_build.lock -docs-site/package-lock.json diff --git a/docs-site/package-lock.json b/docs-site/package-lock.json new file mode 100644 index 000000000..f6f5be387 --- /dev/null +++ b/docs-site/package-lock.json @@ -0,0 +1,863 @@ +{ + "name": "docs-site", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "autoprefixer": "^10.5.0", + "postcss": "^8.5.15", + "postcss-cli": "^11.0.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.376", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz", + "integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.48", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", + "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-cli": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz", + "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==", + "license": "MIT", + "dependencies": { + "chokidar": "^3.3.0", + "dependency-graph": "^1.0.0", + "fs-extra": "^11.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^5.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "tinyglobby": "^0.2.12", + "yargs": "^17.0.0" + }, + "bin": { + "postcss": "index.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-load-config": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz", + "integrity": "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1", + "yaml": "^2.4.2" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + } + } + }, + "node_modules/postcss-reporter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz", + "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/thenby": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.4.1.tgz", + "integrity": "sha512-D5a/bO0KdalOE3q8MlrRmSxjbKZHT3MQmXkJP+r97Vw8MMwOZKOwUSEyTtK7eSMj2y0kyAjpYMRMZmmLw1FtNQ==", + "license": "Apache-2.0" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} From 9f035a9be2c381d0a367268c5e2a132593b6996d Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 16:33:52 +0530 Subject: [PATCH 12/15] ci(docs): install PostCSS deps with npm ci for reproducible builds Use npm ci against the committed docs-site lockfile instead of npm install, which re-resolved latest semver each run and could pull a broken upstream patch into the deploy build. --- .github/workflows/api-docs.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml index 8f1965214..4c9601938 100644 --- a/.github/workflows/api-docs.yml +++ b/.github/workflows/api-docs.yml @@ -58,11 +58,13 @@ jobs: - name: Install PostCSS Dependencies run: | - # --no-workspaces installs into docs-site/node_modules (where Hugo's - # PostCSS looks). docs-site/package.json pins postcss/postcss-cli/ - # autoprefixer. + # npm ci installs the exact versions from docs-site/package-lock.json + # into docs-site/node_modules (where Hugo's PostCSS looks), so the + # build is reproducible -- a broken upstream patch can't be pulled in. + # docs-site/package.json pins postcss/postcss-cli/autoprefixer; the + # lockfile freezes their transitive deps. cd docs-site - npm install --no-workspaces + npm ci - name: Resolve build target id: resolve From ad0926687411b0dc2c222db90ffae61b7fefa819 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 16:34:44 +0530 Subject: [PATCH 13/15] ci(docs): install PostCSS deps with npm ci for reproducible builds Use npm ci against the committed docs-site lockfile instead of npm install, which re-resolved latest semver each run and could pull a broken upstream patch into the backfill build. --- .github/workflows/api-docs-backfill.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/api-docs-backfill.yml b/.github/workflows/api-docs-backfill.yml index 40f868275..c5392da55 100644 --- a/.github/workflows/api-docs-backfill.yml +++ b/.github/workflows/api-docs-backfill.yml @@ -106,11 +106,13 @@ jobs: - name: Install PostCSS Dependencies run: | - # --no-workspaces installs into docs-site/node_modules (where Hugo's - # PostCSS looks). docs-site/package.json pins postcss/postcss-cli/ - # autoprefixer. + # npm ci installs the exact versions from docs-site/package-lock.json + # into docs-site/node_modules (where Hugo's PostCSS looks), so the + # build is reproducible -- a broken upstream patch can't be pulled in. + # docs-site/package.json pins postcss/postcss-cli/autoprefixer; the + # lockfile freezes their transitive deps. cd docs-site - npm install --no-workspaces + npm ci - name: Build docs env: From 8b0280d986ac101f1e339f8d1f9ac5bda28c98a9 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Mon, 22 Jun 2026 16:53:26 +0530 Subject: [PATCH 14/15] docs: document the API reference docs pipeline in DEVELOPER.md Add an API Reference Documentation section to the existing DEVELOPER.md covering the deploy workflow, version picker, backfill workflow (with preview), and local builds. --- DEVELOPER.md | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/DEVELOPER.md b/DEVELOPER.md index a19e12376..e0ff086ed 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -111,6 +111,122 @@ This project uses `release-please` for automated releases. The release pipeline * [`toolbox-langchain`](https://pypi.org/project/toolbox-langchain/) * [`toolbox-llamaindex`](https://pypi.org/project/toolbox-llamaindex/) +## API Reference Documentation + +The API reference is published to [py.mcp-toolbox.dev](https://py.mcp-toolbox.dev). +It is generated with +[pydoc-markdown](https://niklasrosenstein.github.io/pydoc-markdown/) and rendered +by [Hugo](https://gohugo.io/) + [Docsy](https://www.docsy.dev/) from the +`docs-site/` directory. Docs are built **per package, per version** and served at +`/<package>/<version>/` (e.g. `/core/v1.0.0/`), with a `/<package>/latest/` +redirect to the newest release. `<package>` is the URL slug: `core`, `adk`, +`langchain`, or `llamaindex`. + +pydoc-markdown parses the SDK source statically — it never imports the packages — +so no build or install of the SDK is needed before generating docs. + +### Workflows + +The `api-docs.yml` workflow deploys to the `gh-pages` branch. It runs only on the +upstream repository and uses the `api-docs-deploy` concurrency group, so it never +races another deploy. + +The automatic flow is as follows: + +* Push to `main` (or manual dispatch) → builds all four packages as `dev`. +* Push of a per-package tag → builds that one version **and** rebuilds the root + landing page. Tags are hyphenated: `toolbox-core-vX.Y.Z` builds `core`, + `toolbox-adk-vX.Y.Z` builds `adk`, and likewise for `langchain` and + `llamaindex`. +* Other tags (e.g. `release-please-*`) are skipped. + +### Adding a version to the picker + +The version dropdown and the `/<package>/latest/` redirect are driven entirely by +the hand-edited `[params.versions.<pkg>]` list in `docs-site/hugo.toml` — not by +the build's version. Before each **new release**, add a `[[params.versions.<pkg>]]` +block for the version (newest first; the first non-`dev` entry becomes `latest`). + +Add it in the **same commit you tag from**: the deploy reads `hugo.toml` from the +tagged ref and regenerates the dropdown/`latest` files in that run. Only list a +version whose `/<pkg>/<version>/` pages already exist (or will after this run), or +the dropdown link 404s. + +### Backfilling old docs + +Use the **`api-docs-backfill.yml`** (API Reference Backfill) workflow to publish +docs for a version whose pages are missing — typically releases that predate the +docs tooling, or a deployment that failed. It builds **one historical version per +run**. + +Unlike `api-docs.yml`, this workflow does **not** deploy to production directly. +Each run opens a **pull request into the `gh-pages` branch**, so the docs are +reviewed before they go live. The page is published only when you merge that PR. + +How a run works: + +1. It checks out `main` for the current docs tooling (layouts, scripts, version + picker), then overlays the requested version's package **`src/`** from its + release tag (`toolbox-<pkg>-<version>`), so pydoc-markdown documents that + version's API. Only `src/` is overlaid, so the package's `pyproject.toml` and + the docs tooling stay in sync with `main`. +2. It builds `/<package>/<version>/` (plus the package's `releases`/`latest` + files), overlays it onto a clone of the live `gh-pages` tree — existing + versions, `CNAME`, and `.nojekyll` are preserved — and opens a PR from branch + `backfill/<pkg>-<ver>` with `gh-pages` as the base. + +Steps to backfill: + +1. Make sure the version is listed in `docs-site/hugo.toml` (see + [Adding a version to the picker](#adding-a-version-to-the-picker)), so the + dropdown links to it. +2. Trigger the workflow from the Actions tab, or with: + + ```bash + gh workflow run api-docs-backfill.yml -f package=core -f version=v1.0.0 + ``` + + To catch up several versions, dispatch it once per `package`/`version`. The + concurrency group is scoped per version, so the runs are independent and none + are cancelled — each opens its own PR. +3. Review the resulting `backfill/<pkg>-<ver>` PR (the diff should be just that + version's directory) and **merge it into `gh-pages`** to publish. Re-running + the workflow for the same version updates the existing PR's branch. + +#### Previewing a backfill PR + +GitHub won't render the built HTML in the PR diff. Because the PR branch *is* the +rendered `gh-pages` tree, check it out and serve it statically — exactly what +Pages will serve after merge: + +```bash +git fetch origin backfill/<pkg>-<ver> +# Check the branch out somewhere disposable (a detached worktree keeps your +# current branch untouched). +git worktree add --detach /tmp/preview-docs origin/backfill/<pkg>-<ver> +python3 -m http.server 8099 --directory /tmp/preview-docs +# → http://localhost:8099/<pkg>/<ver>/ e.g. http://localhost:8099/core/v0.6.0/ +``` + +The version dropdown fetches `/<pkg>/releases.releases` at runtime, so links to +versions not present in this branch (other backfills) will 404 locally — that's +expected. When done, clean up: + +```bash +git worktree remove /tmp/preview-docs +``` + +### Building locally + +```bash +# Build a single package/version (base URL must end in a slash). +./scripts/generate-api-docs.sh core dev http://localhost:8080/ + +# Serve the output. +(cd docs-site/public && python3 -m http.server 8080) +# → http://localhost:8080/core/dev/ +``` + ## Support Check the existing [GitHub Issues](https://github.com/googleapis/mcp-toolbox-sdk-python/issues) for any concerns. From 812d0d4be911e4614cfffedc8414e9ea808241f5 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <twishabansal07@gmail.com> Date: Thu, 25 Jun 2026 13:35:43 +0530 Subject: [PATCH 15/15] docs: document curated module list and how to add a new package The API reference's documented surface is the curated MODULES in generate-api-docs.sh; explain that single source of truth and the steps (script case arm, api-docs.yml tag router + default build list, hugo.toml version picker) to onboard a new package. --- DEVELOPER.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/DEVELOPER.md b/DEVELOPER.md index e0ff086ed..b012acc96 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -125,6 +125,28 @@ redirect to the newest release. `<package>` is the URL slug: `core`, `adk`, pydoc-markdown parses the SDK source statically — it never imports the packages — so no build or install of the SDK is needed before generating docs. +### What gets documented + +Each package's public API is a **curated module list** in +[`scripts/generate-api-docs.sh`](./scripts/generate-api-docs.sh). The `case` block +there is the single source of truth for both the valid package slugs and the +modules rendered for each; internal modules (e.g. `utils`, the transport layer) +are deliberately left out. To document a new module, add it to that package's +`MODULES`. + +#### Adding a new package + +The package must already live under `packages/toolbox-<slug>/`. Then: + +1. Add a `case` arm (slug → `TITLE` + `MODULES`) in + [`scripts/generate-api-docs.sh`](./scripts/generate-api-docs.sh). +2. In [`.github/workflows/api-docs.yml`](./.github/workflows/api-docs.yml), add a + `refs/tags/toolbox-<slug>-v*` arm to the tag router **and** append the slug to + the default `packages=` list (the `dev` build of all packages). +3. Add a `[[params.versions.<slug>]]` block in + [`docs-site/hugo.toml`](./docs-site/hugo.toml) so the version picker lists it + (see [Adding a version to the picker](#adding-a-version-to-the-picker)). + ### Workflows The `api-docs.yml` workflow deploys to the `gh-pages` branch. It runs only on the