mcpscore.toml next to your code turns rules off and
re-ranks the rest by rule_id, and the score you see in CI is the score under
that policy. The badge and mcpscore.dev never read it. They always show the
canonical score.
mcpscore.toml
Build the file one entry at a time
The steps below build that file against the one-tool server from smoke mode. With no configuration it scores118/140, and two of its failed rules are server_websiteurl_present
and server_title_present. Every rule_id is in the rules reference.
Create mcpscore.toml in the directory you run mcpscore from, or anywhere
above it inside the repository.
Step 1: Turn a rule off
mcpscore.toml
140 becomes 139. It appears in the report’s
skipped_rules with reason disabled-by-config.
Step 2: Re-rank a rule
A severity name instead ofoff keeps the rule running and changes its weight.
server_title_present is MEDIUM by default, worth 2 points. Make it
critical, worth 5:
mcpscore.toml
118 and the maximum grows by 3.
The weights are 1, 2, 3 and 5 points for low, medium, high and
critical.
Step 3: Fail the build on it
Add a[gate] table. Any failed rule counted in the main score at or above
fail_on exits with code 3:
mcpscore.toml
3, the same code as --fail-under, so a CI step that
already fails on a low score now fails on this rule too. Re-ranking in Step 2
is what put the rule over the line. A rule that is off never trips the gate.
Step 4: Fix the server and watch it pass
Give the server a title:server.py
0. The rule your team cares most about now guards every
change, and the website score still counts it at its default weight.
What each entry does
Values are case-insensitive. A
rule_id that mcpscore doesn’t know, including
one it has retired, is warned about and ignored, so a file written for a newer
release still works on an older one. Any other value is a usage error and exit
code 1.
Where the file lives
mcpscore looks in this order and prints the file it used on theConfig: line:
--config FILE, any path. A missing file is a usage error.- Otherwise the nearest configuration, walking up from the working directory.
The walk stops at the repository root, the first directory that contains
.git. In each directory amcpscore.tomlwins over apyproject.tomlwith a[tool.mcpscore]table, and a nearer file wins over one further up.
pyproject.toml takes the same entries under tool.mcpscore:
pyproject.toml
--no-config ignores all of it. That is how you reproduce the canonical
number inside a configured repository:
What it changes, and what it doesn’t
A configuration changes the score for the run that used it. It does not touch the badge or the report on mcpscore.dev, which only show audits run by the website itself, with every rule at its default weight. Two teams with different files get different numbers for the same server. Compare configured scores only across runs with the sameconfig.sha256, which the report carries.
In the JSON report the applied configuration is a config block:
min-score gates the configured score, the PR comment carries the same
qualifier, and a [gate] failure fails the job with the rule named.
When it fails
Usage error: mcpscore.toml: rule 'server_websiteurl_present' has value 'skip'; expected off, low, medium, high, or critical (exit 1)
- Cause: an unsupported value.
offis the one spelling. - Fix: use
offor a severity name.
Config: unknown rule 'server_titel_present'; ignored
- Cause: a
rule_idthis release doesn’t have, or a typo. - Fix: check the id in the rules reference.
Config: rule 'readiness_2026_origin_validation' was retired in mcpscore 1.20.0; ignored
- Cause: the rule was removed from the engine. The retired-rules table in the rules reference says why, and names the replacement when there is one.
- Fix: delete the line.
Usage error: missing.toml: cannot read config file: No such file or directory (exit 1)
- Cause:
--configpoints at a file that does not exist. - Fix: correct the path, or drop
--configand let discovery find the file.
- Cause: the badge is canonical by design and never applies a configuration.
- Fix: none needed. Your CI number and the badge answer different questions.
Recap
- Turn a rule off with
rule_id = "off". - Re-rank a rule with a severity name.
- Fail the build with
[gate] fail_on. - Fix the server, and the same file keeps guarding it.
What’s next
Rules reference
Every
rule_id you can turn off or re-rankGitHub Action
Gate pull requests on the configured score
Stability contract
The
config report block, field by fieldScoring methodology
What the default weights mean before you change them