Skip to content

Comments

Type-check docstring code examples via companion files and unified sync script#2119

Open
jonathanhefner wants to merge 6 commits intomodelcontextprotocol:mainfrom
jonathanhefner:sync-snippets-script
Open

Type-check docstring code examples via companion files and unified sync script#2119
jonathanhefner wants to merge 6 commits intomodelcontextprotocol:mainfrom
jonathanhefner:sync-snippets-script

Conversation

@jonathanhefner
Copy link
Member

Docstring code examples in src/mcp/ were previously raw text — invisible to pyright and ruff, so type errors and style drift went unnoticed. This PR introduces a system for keeping those examples in standalone, type-checked companion files that are synced back into the docstrings automatically.

The old update_readme_snippets.py is replaced with sync_snippets.py, a superset that handles README.v2.md, docs/**/*.md, and src/**/*.py docstrings. It adds region extraction (# region / # endregion markers) so a single companion file can supply multiple snippets. For docstrings specifically, <!-- snippet-source #RegionName --> markers derive the companion path automatically from the target file's location (src/mcp/foo.pyexamples/snippets/docstrings/mcp/foo.py), avoiding line-length violations from embedding full paths.

42 code examples across the public API surface (MCPServer, Client, ClientSession, Context, ResponseRouter, task support, OAuth providers, etc.) are extracted into 19 companion files under examples/snippets/docstrings/mcp/, mirroring the source tree. Each example is wrapped in a named function with typed parameters, so pyright and ruff check them on every CI run — catching signature changes, renamed parameters, and moved imports at CI time rather than when a user copies a broken example.

Conventions for the snippet system (region naming, function-parameter pattern, # type: ignore prohibition, editing workflow) are documented in CLAUDE.md.


@Kludex, I was told you were thinking about moving examples/snippets/ to docs/snippets/. Would you prefer that docstring snippets live in docs/snippets/docstrings/? (Or anywhere else other than examples/snippets/docstrings/?)

The new script is a superset of the old one. It continues to handle the
existing `<!-- snippet-source -->` markers in `README.v2.md`, and adds
support for syncing code snippets into Python docstrings and markdown
docs under `docs/`.

New capabilities beyond the old script:

- Region extraction from example files using `# region` / `# endregion`
  markers, so a single example file can provide multiple snippets
- All source paths resolve relative to the repository root
- Scans `src/**/*.py` and `docs/**/*.md` in addition to the README
- Caches file contents and extracted regions for efficiency

The marker format uses HTML comments (`<!-- snippet-source -->` /
`<!-- /snippet-source -->`), which are invisible when rendered by
`mkdocstrings` and do not interfere with `pymdownx.superfences` code
fence parsing.
Add support for `<!-- snippet-source #region_name -->` markers that omit
the companion file path. The path is derived from the target file's
location using the mapping `src/X` → `examples/snippets/docstrings/X`.

This eliminates line-length violations on marker lines in docstrings,
since the full companion path no longer needs to be embedded in every
marker. The full-path form continues to work for non-`src/` targets like
markdown files.
Move inline code examples from docstrings in `src/mcp/` into standalone
companion files at `examples/snippets/docstrings/mcp/`, mirroring the
source tree structure. The `scripts/sync_snippets.py` script keeps the
docstring content in sync with the companion files via
`<!-- snippet-source #RegionName -->` markers.

This ensures all docstring examples are checked by pyright and ruff,
catching type errors and style drift that would otherwise go unnoticed
in raw docstring text. The pattern follows the TypeScript SDK's approach
of one companion file per source file, with each example in a named
function whose parameters supply typed context.

19 companion files cover 42 code examples across the public API surface:
`MCPServer`, `Client`, `ClientSession`, `Context`, `ResponseRouter`,
`ServerTaskContext`, `ExperimentalTaskHandlers`,
`ClientCredentialsOAuthProvider`, `PrivateKeyJWTOAuthProvider`,
`SignedJWTParameters`, and others.

All source markers use path-less form (`#RegionName`) — the companion
path is derived automatically from the target file location. Region
names follow `ClassName_methodName_variant` without abbreviation.

Pyright execution environment for the companion files suppresses only
"unused artifact" diagnostics inherent to example code
(`reportUnusedFunction`, `reportUnusedVariable`, `reportAbstractUsage`,
`reportUnusedClass`, `reportPrivateUsage`). All actual type-checking
rules remain enabled.
Add a "Docstring Code Examples" section covering the companion file
system: directory layout, `<!-- snippet-source #RegionName -->` markers,
`ClassName_methodName_variant` naming, the function-parameter pattern
for typed dependencies, and the prohibition on type-suppression comments
inside regions.
`sync_snippets.py` also syncs snippet-source markers in `docs/**/*.md`
and `README.v2.md`, not just `src/` docstrings. Add a short section
after "Docstring Code Examples" noting that these files use explicit
paths (path-less `#Region` markers are only supported in `src/` files).
The previous documentation had two flat sections where the docstring
section contained all the detail and the markdown section referred to it
vaguely. Reorganize into a `## Code Snippet System` intro covering
shared concepts (marker format, region extraction, naming conventions,
function wrappers, typed params, `# type: ignore` prohibition, pyright
workflow) with `### Markdown Code Examples` and
`### Docstring Code Examples` subsections covering only what is unique
to each target type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant