v1.10.0
Added
-
mcpscore identifies itself in every handshake. The legacy
initialize
handshake now sendsclientInfo: {"name": "mcpscore", "version": <installed version>}instead of the MCP SDK's anonymous default (mcp/0.1.0); the
modern probes and the status-recovery path already did, and all three now
share one constant so they cannot drift apart. Etiquette for server
operators and gateways that segment traffic by client identity: audit
traffic is now recognizable — and greppable — as mcpscore in server logs.
Scores are unaffected. -
--fail-underand--fail-under-readiness: the CI gate, in the CLI.
mcpscore <target> --fail-under 80exits with the new code 3 when the
main score percentage (rounded, matching the GitHub Action's arithmetic)
is below the threshold;--fail-under-readinessgates the readiness axis
the same way and is skipped when readiness was not assessed. Exit codes
0/1/2 keep their documented meanings exactly; without the flags nothing
changes. A partial audit always fails a--fail-undergate: its
percentage covers only the observable surface (an auth-gated server with
a clean auth posture normalizes to 100% on a handful of checks), so it
cannot demonstrate the threshold — pass a credential to audit behind the
gate. Package audits gate on their packaging percentage. Previously this
capability existed only insidemcpscore-action; it now belongs to the
CLI, so GitLab CI, Jenkins, Makefiles, and pre-commit hooks get the same
gate, and the Action can delegate instead of reimplementing it. -
Package Audits guide (
docs/package-audits.mdx) — the--package
feature finally has a docs page: what the six packaging rules check, why
the package is never downloaded or executed, and why package scores share
no denominator with server scores. -
"Why did my score change?" section in the scoring methodology —
version-to-version ruleset growth, partial vs full audits, readiness
promotion, and server-side variance (rolling deploys, rate-limited
probes) as the causes of score movement. -
Docs publish from release tags. A new
publish-docs.ymlworkflow
fast-forwards adocs-livebranch to each stable release tag, so
docs.mcpscore.dev describes the released engine instead of main (the
Mintlify app deploys fromdocs-live).
Fixed
-
Docs freshness pass: example CLI outputs regenerated from real 1.9.0 runs
(the index example claimed 2025-11-25 was the latest spec revision; the
authenticated-servers partial example carried a 1.2.0-era check count),
the methodology page no longer calls 2026-07-28 a release candidate in one
place and final in another, the GitHub Action page'sversionexamples no
longer suggest 0.8.0, a stale readiness anchor is fixed, the index no
longer repeats its own subtitle as its first sentence, and the rules
reference intro no longer repeats its frontmatter description. -
supportedVersionscovers the negotiated legacy version. The new LOW
protocol_version_supported_versions_include_negotiatedrule judges
dual-era servers whoseserver/discoverresponse omits the protocol
version their legacyinitializehandshake actually negotiated (observed
in the wild on huggingface.co/mcp, which declares only 2026-07-28 while
negotiating 2025-11-25). The finding's advice: add the version to
supportedVersions, or disable the legacy lifecycle if it was meant to
be retired. Deliberately scoped to the one legacy version the audit
observed — a session negotiates a single version, so the rule proves
"the negotiated version is listed", never full exhaustiveness. LOW
because the specification definessupportedVersionsdescriptively
("protocol versions the server supports") without an explicit
completeness MUST — though its ownUnsupportedProtocolVersionError
example mixes eras insupported— so the omission is treated as a
consistency finding, not a violation. Modern-only and legacy-only
servers skip as not-applicable; the check uses the legacy session's own
negotiated version (session_protocol_version), so modern evidence can
never manufacture the finding.