Skip to content

v1.10.0

Choose a tag to compare

@a-akimov a-akimov released this 28 Aug 07:05
b93c320

Added

  • mcpscore identifies itself in every handshake. The legacy initialize
    handshake now sends clientInfo: {"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-under and --fail-under-readiness: the CI gate, in the CLI.
    mcpscore <target> --fail-under 80 exits with the new code 3 when the
    main score percentage (rounded, matching the GitHub Action's arithmetic)
    is below the threshold; --fail-under-readiness gates 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-under gate: 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 inside mcpscore-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.yml workflow
    fast-forwards a docs-live branch to each stable release tag, so
    docs.mcpscore.dev describes the released engine instead of main (the
    Mintlify app deploys from docs-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's version examples 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.

  • supportedVersions covers the negotiated legacy version. The new LOW
    protocol_version_supported_versions_include_negotiated rule judges
    dual-era servers whose server/discover response omits the protocol
    version their legacy initialize handshake 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 defines supportedVersions descriptively
    ("protocol versions the server supports") without an explicit
    completeness MUST — though its own UnsupportedProtocolVersionError
    example mixes eras in supported — 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.