close
Skip to main content
From the first stable release (1.1.0), mcpscore commits to a stability contract so CI integrations and report consumers can depend on it. This page is that contract.

Stable — breaking changes only with a major version

Rule identifiers

Every check has a rule_id (e.g. tools_description_present_in_all). A rule_id is never renamed and never reused for a different check. Rules may be added in any release; a rule may be retired (stops running) but its identifier is never given a new meaning. Integrations should key on rule_id — not on rule names, messages, or positions, which may be reworded or reordered in any release.

Report schema

The --json report carries schema_version (currently 1). Within a schema version:
  • Existing fields keep their names, types, and meanings.
  • New fields may be added in any release — consumers must ignore unknown fields.
  • Field removals or type changes bump schema_version.
The report’s top-level shape: schema_version, mcpscore_version, generated_at, target, transport, score, max_score, authenticated, partial, partial_reason, incomplete_listings[], server_info, package, summary, results[], skipped_rules[], spec, readiness. server_info is either null when server identity could not be observed, or an object containing the name and version reported by the server during initialization or modern discovery. Baseline consumers can use it to distinguish a server release change from an mcpscore engine release change. package is null for every server audit. It is an object only for a package audit (mcpscore --package <coordinate>), and its presence is the marker that this report’s score is not comparable to a server report’s: a package audit runs the packaging rules and nothing else, so score/max_score come from a different, disjoint rule set. Consumers that compare or aggregate scores must branch on it. The object carries registry, identifier, requested_version, resolved_version, outcome, error, repository_url, license, published_at, withdrawn, and executed — the last is always false and records that the package was read from its registry, never downloaded or run. For a package audit transport is null and spec.negotiated_version is null: a coordinate names something installable, not something running.

CLI interface

  • The invocation shape — mcpscore <target> with --json, --header, --token (and the MCPSCORE_TOKEN environment variable) — is stable. New flags may be added; existing flags keep their meaning.
  • mcpscore --version prints mcpscore <version> on stdout and exits 0, with no other output and without needing a target. Scripts may parse it.
  • Exit codes are a contract: 0 audit completed (regardless of score); 1 the audit was never attempted — a usage error or a failed --oauth flow (timeout, refusal, registration or token-exchange failure); 2 connection failure to the target server with no fallback available.
  • --json writes exactly one JSON document to stdout; all logs go to stderr. Pipelines may rely on stdout being clean JSON.

Credential handling

Header and token values are never logged and never written to the report — only the boolean authenticated flag is recorded. This is a permanent commitment, not a default.

Evolving by design — expect movement between releases

The score

The score is ruleset-dependent and the ruleset grows. score and max_score are severity-weighted sums over the rules that ran: adding rules (most releases) changes both, so a score is comparable only within the same mcpscore version against the same server. Track mcpscore_version alongside any score you store. We would rather grow the checks than freeze the number early; a calibrated scoring frame is planned to revisit this once the ruleset stabilizes. Two flags qualify a score further:
  • partial: true — only the observable surface of an auth-gated server was scored; not comparable to a full audit.
  • readiness.counted_in_main: true — a modern-lifecycle server’s readiness points are included in the main score (see methodology); a CI min-score threshold means something slightly different on either side of this flag.

Messages, details, and rule metadata

Human-readable message strings, details contents (including the basis citations), severities, and category groupings may be improved in any release. They are for humans and for context — not for keying logic.

Readiness rules

Readiness rules target the next spec revision, so the readiness rule set turns over at each revision: rules for a now-current revision migrate into the main axis and new readiness rules appear for the next draft. Their rule_ids still follow the never-reused rule.

Versioning

mcpscore follows SemVer: breaking changes to anything in the “Stable” section require a major version; rule additions and score movement are minor-version territory; pre-releases (bN) may change anything and exact-pin their dependencies.