Skip to content

Commit f511d3c

Browse files
claudemaxisbey
authored andcommitted
docs: replace MkDocs with Zensical
Migrate the v2 docs build from MkDocs Material to Zensical, the Material team's successor (as Starlette and uvicorn have done). Zensical natively re-implements search, glightbox and mkdocstrings, but — unlike MkDocs — runs no arbitrary plugins or hooks. This SDK's docs relied on three of those, so they are reimplemented as standalone build steps around `zensical build`: - API reference: `mkdocs-gen-files` + `mkdocs-literate-nav` become `scripts/docs/gen_ref_pages.py` (writes the `docs/api/` mkdocstrings stubs) and `scripts/docs/build_config.py` (splices the nested API nav into a generated `mkdocs.gen.yml`, since Zensical has no literate-nav). - llms.txt: the former MkDocs hook becomes `scripts/docs/llms_txt.py`, a post-build step over the source tree, with no dependency on build internals. `mkdocs.yml` stays the source config, with the MkDocs-only YAML tags (`!relative`, `!ENV`, `!!python/name:`) translated to the string forms Zensical understands and the emoji functions pointed at `zensical.extensions.emoji`. The generators moved out of `docs/` (Zensical publishes everything under docs_dir) into `scripts/docs/`, and `scripts/build-docs.sh` now picks the toolchain per worktree so the combined v1 (MkDocs) + v2 (Zensical) build stays correct. Adds `scripts/serve-docs.sh` for local preview. The docs dependency group drops mkdocs, mkdocs-material[imaging] and the gen-files/glightbox/literate-nav plugins for `zensical`. mkdocstrings is floored at 1.0.4 / mkdocstrings-python 2.0.5: Zensical's compatibility layer targets that API, and the older line renders API pages with an unregistered-autorefs error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CTkPwxyKkLTnqZdeiCMCzK
1 parent 74a242a commit f511d3c

14 files changed

Lines changed: 554 additions & 572 deletions

File tree

.github/workflows/deploy-docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ on:
1414
- src/mcp/**
1515
- src/mcp-types/**
1616
- scripts/build-docs.sh
17+
- scripts/docs/**
1718
- pyproject.toml
1819
- uv.lock
1920
- .github/workflows/deploy-docs.yml

.github/workflows/shared.yml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,13 @@ jobs:
139139
- name: Check README snippets are up to date
140140
run: uv run --frozen scripts/update_readme_snippets.py --check
141141

142-
# `mkdocs.yml` sets `strict: true` and `pymdownx.snippets: check_paths: true`,
143-
# but until this job existed the docs were only ever built post-merge by
144-
# `deploy-docs.yml`, so a broken link, a missing nav target, or a deleted
145-
# `docs_src/` include went green on the PR and broke the next deploy of main.
146-
# This is the check path; `deploy-docs.yml` stays the deploy path.
142+
# `zensical build --strict` fails on broken links / missing nav targets and
143+
# `pymdownx.snippets: check_paths: true` fails on a deleted `docs_src/`
144+
# include; the llms_txt step additionally re-resolves every snippet and link.
145+
# Until this job existed the docs were only ever built post-merge by
146+
# `deploy-docs.yml`, so those failures went green on the PR and broke the next
147+
# deploy of main. This is the check path; `deploy-docs.yml` stays the deploy
148+
# path.
147149
docs:
148150
runs-on: ubuntu-latest
149151
steps:
@@ -171,8 +173,7 @@ jobs:
171173
- name: Install dependencies
172174
run: uv sync --frozen --all-extras --python 3.10
173175

176+
# Zensical runs no MkDocs plugins/hooks: generate the API reference and
177+
# the concrete config, build strictly, then generate llms.txt.
174178
- name: Build the docs in strict mode
175-
run: uv run --frozen --no-sync mkdocs build --strict
176-
env:
177-
# Silence mkdocs-material's MkDocs 2.0 warning banner in CI logs.
178-
NO_MKDOCS_2_WARNING: "1"
179+
run: bash scripts/docs/build.sh

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,13 @@ venv.bak/
141141
# Rope project settings
142142
.ropeproject
143143

144-
# mkdocs documentation
144+
# documentation
145145
/site
146146
/.worktrees/
147+
# Generated at build time by docs/hooks/ (the API reference tree and the
148+
# concrete Zensical config spliced from mkdocs.yml).
149+
/docs/api/
150+
/mkdocs.gen.yml
147151

148152
# mypy
149153
.mypy_cache/

docs/hooks/gen_ref_pages.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

docs/hooks/llms_txt.py

Lines changed: 0 additions & 184 deletions
This file was deleted.

mkdocs.yml

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
site_name: MCP Python SDK
22
site_description: The official Python SDK for the Model Context Protocol
3-
strict: true
43

54
repo_name: modelcontextprotocol/python-sdk
65
repo_url: https://github.com/modelcontextprotocol/python-sdk
@@ -10,6 +9,9 @@ site_url: https://py.sdk.modelcontextprotocol.io/v2/
109
# TODO(Marcelo): Add Anthropic copyright?
1110
# copyright: © Model Context Protocol 2025 to present
1211

12+
# The "API Reference" entry is a placeholder: `scripts/docs/gen_ref_pages.py`
13+
# generates the `docs/api/` tree and `scripts/docs/build_config.py` splices the
14+
# real nested nav in before the build. See `scripts/build-docs.sh`.
1315
nav:
1416
- MCP Python SDK: index.md
1517
- "What's new in v2": whats-new.md
@@ -122,13 +124,6 @@ theme:
122124
extra_css:
123125
- extra.css
124126

125-
# https://www.mkdocs.org/user-guide/configuration/#validation
126-
validation:
127-
omitted_files: warn
128-
absolute_links: warn
129-
unrecognized_links: warn
130-
anchors: warn
131-
132127
markdown_extensions:
133128
- tables
134129
- admonition
@@ -138,29 +133,28 @@ markdown_extensions:
138133
- pymdownx.caret
139134
- pymdownx.critic
140135
- pymdownx.mark
141-
- pymdownx.superfences
142136
# Code examples live as complete, importable, tested files under `docs_src/`
143137
# and are included into pages with `--8<-- "docs_src/<chapter>/tutorialNNN.py"`
144-
# (resolved against the repo root regardless of the build's working
145-
# directory; the extension's default base_path is the CWD).
146-
# `check_paths: true` + `strict: true` turn a renamed/deleted example into a
147-
# build failure instead of a silently empty code block.
138+
# (resolved against the repo root, which is the build's working directory).
139+
# `check_paths: true` turns a renamed/deleted example into a build failure
140+
# instead of a silently empty code block.
148141
- pymdownx.snippets:
149-
base_path: !relative $config_dir
142+
base_path: [.]
150143
check_paths: true
151144
- pymdownx.tilde
152145
- pymdownx.inlinehilite
153146
- pymdownx.highlight:
154147
pygments_lang_class: true
155-
- pymdownx.extra:
156-
pymdownx.superfences:
157-
custom_fences:
158-
- name: mermaid
159-
class: mermaid
160-
format: !!python/name:pymdownx.superfences.fence_code_format
148+
- pymdownx.superfences:
149+
custom_fences:
150+
- name: mermaid
151+
class: mermaid
152+
format: pymdownx.superfences.fence_code_format
153+
# Zensical re-implements the emoji extension; the generator/index functions
154+
# live under `zensical.extensions.emoji`, not `material.extensions.emoji`.
161155
- pymdownx.emoji:
162-
emoji_index: !!python/name:material.extensions.emoji.twemoji
163-
emoji_generator: !!python/name:material.extensions.emoji.to_svg
156+
emoji_index: zensical.extensions.emoji.twemoji
157+
emoji_generator: zensical.extensions.emoji.to_svg
164158
options:
165159
custom_icons:
166160
- docs/.overrides/.icons
@@ -170,23 +164,13 @@ markdown_extensions:
170164
custom_checkbox: true
171165
- sane_lists # this means you can start a list from any number
172166

173-
watch:
174-
- src
175-
- docs_src
176-
177-
hooks:
178-
- docs/hooks/llms_txt.py
179-
167+
# Zensical natively re-implements `search`, `glightbox` and `mkdocstrings`; it
168+
# does not run arbitrary MkDocs plugins or hooks, so the former `gen-files`,
169+
# `literate-nav`, `social` and `llms_txt` hook are handled by the standalone
170+
# scripts under `scripts/docs/` invoked around the build (see build-docs.sh).
180171
plugins:
181172
- search
182-
- social:
183-
enabled: !ENV [ENABLE_SOCIAL_CARDS, false]
184173
- glightbox
185-
- gen-files:
186-
scripts:
187-
- docs/hooks/gen_ref_pages.py
188-
- literate-nav:
189-
nav_file: SUMMARY.md
190174
- mkdocstrings:
191175
handlers:
192176
python:

0 commit comments

Comments
 (0)