Skip to content

fix: 2nd-pass audit Major — protocol contract test, wheel fallback coverage, dead modular example, clone-vs-starter boundary#33

Merged
heznpc merged 1 commit into
mainfrom
fix/2nd-pass-major-2026-05-21
May 21, 2026
Merged

fix: 2nd-pass audit Major — protocol contract test, wheel fallback coverage, dead modular example, clone-vs-starter boundary#33
heznpc merged 1 commit into
mainfrom
fix/2nd-pass-major-2026-05-21

Conversation

@heznpc
Copy link
Copy Markdown
Member

@heznpc heznpc commented May 21, 2026

Resolves all 4 Major findings from the second-pass audit. Companion to PR #32 (which fixed the 2 Critical findings).

[M1] tests/test_tools.py — add test_greet_registered_on_server

Parallels test_server_info.py and test_code_review.py (both already had this). Calls mcp.list_tools() and verifies the greet tool is wired in and that the generated JSON Schema actually reflects Annotated[..., Field(min_length, max_length)] constraints. Without this, FastMCP's schema generation was an unverified link in the MCP protocol contract.

[M2] tests/test_server_info.py — cover wheel-install fallback path

Existing tests walk the source tree and find pyproject.toml. That's the dev/editable-install path. When a user does pip install my-mcp-server from a wheel, pyproject.toml is NOT shipped — _read_pyproject returns None and _server_metadata falls back to importlib.metadata.version(). That branch (server_info.py:51-56) was previously 0% covered.

Three new tests via monkeypatch:

  • _read_pyproject returns None → version comes from importlib.metadata.
  • _read_pyproject returns None AND importlib.metadata raises PackageNotFoundError → returns "0.0.0" fallback.
  • pyproject.toml exists but has no [project] table → covers server_info.py:42 exit.

server_info.py coverage: 79% → 96%.

[M3] src/my_mcp_server/tools/greet.py — delete dead modular example

The file defined greet_formal + a register() function, but server.py never called from my_mcp_server.tools.greet import register to wire it in. 100% dead code, 0% test coverage. Updated server.py:71-74 comment to describe the modular pattern in prose without referencing the deleted file.

[M4] SECURITY.md — distinguish code-level vs runtime GitHub settings

Previous text was misleading for clones: GitHub does NOT copy secret_scanning / push_protection / dependabot_security_updates / branch protection when a template is cloned. Clones inherited the false belief "I'm safe because the starter is."

Added a new section "What clones inherit vs. what they don't" with the exact gh api invocations clones can run to replicate the toggles on their own fork.

Coverage delta

Metric Before After
Tests 17 21
Total coverage 70.64% 84.69%
server_info.py 79% 96%
tools/greet.py 0% (10 dead LOC) — (deleted)

Test plan

  • ruff check . / ruff format --check . / mypy src/ all clean
  • All 21 tests pass locally with coverage gate
  • CI matrix (3.11/3.12/3.13) green
  • CodeQL analyze (python) + analyze (actions) green

…verage, dead modular example, clone-vs-starter boundary

Resolves all 4 Major findings from the second-pass audit on PR #32.

[M1] tests/test_tools.py: add `test_greet_registered_on_server`
- Parallels test_server_info.py and test_code_review.py, both of which had
  an equivalent registration assertion already.
- Calls `mcp.list_tools()` and verifies the greet tool is wired in AND that
  the generated JSON Schema actually reflects the Annotated[..., Field(
  min_length, max_length)] constraints. Without this, FastMCP's schema
  generation was an unverified link in the protocol contract.

[M2] tests/test_server_info.py: cover wheel-install fallback path
- The existing tests all walk the source tree and find pyproject.toml.
  That's the dev/editable-install path. When a user does `pip install
  my-mcp-server` from a wheel, pyproject.toml is NOT shipped — _read_pyproject
  returns None and _server_metadata must fall back to
  importlib.metadata.version(). That branch (server_info.py:51-56) was
  previously 0% covered.
- Three new tests via monkeypatch:
  · `_read_pyproject` returns None → version comes from importlib.metadata.
  · `_read_pyproject` returns None AND importlib.metadata raises
    PackageNotFoundError → returns "0.0.0" fallback.
  · pyproject.toml exists but has no [project] table → covers the
    server_info.py:42 exit.
- server_info.py coverage: 79% → 96%.

[M3] src/my_mcp_server/tools/greet.py: delete dead modular example
- The file defined `greet_formal` + a `register()` function, but server.py
  never called `from my_mcp_server.tools.greet import register` to wire it
  in. 100% dead code with 0% test coverage.
- Updated server.py:71-74 comment to describe the modular pattern in
  prose without referencing the deleted file.

[M4] SECURITY.md: distinguish code-level vs runtime GitHub settings
- Previous text "Repo-side toggles enabled — Secret scanning + push
  protection + Dependabot security updates + branch protection on main"
  was misleading for clones: GitHub does NOT copy these settings when a
  template is cloned into a new repo. Clones inherited the false belief
  that "I'm safe because the starter is."
- Added a new section "What clones inherit vs. what they don't" with the
  exact `gh api` invocations clones can run to replicate the toggles on
  their own fork.

Coverage moved 70.64% → 84.69% (also benefits from M3 deletion of the
0%-covered dead module). 21 tests pass (was 17).
@heznpc heznpc enabled auto-merge (squash) May 21, 2026 13:19
@heznpc heznpc merged commit 972c58c into main May 21, 2026
8 checks passed
@heznpc heznpc deleted the fix/2nd-pass-major-2026-05-21 branch May 21, 2026 13:20
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