Stable — breaking changes only with a major version
Rule identifiers
Every check has arule_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.
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 theMCPSCORE_TOKENenvironment variable) — is stable. New flags may be added; existing flags keep their meaning. mcpscore --versionprintsmcpscore <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
--oauthflow (timeout, refusal, registration or token-exchange failure); 2 connection failure to the target server with no fallback available. --jsonwrites 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 booleanauthenticated 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 CImin-scorethreshold means something slightly different on either side of this flag.
Messages, details, and rule metadata
Human-readablemessage 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. Theirrule_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.