--fail-under. This is the whole GitLab
job:
.gitlab-ci.yml
Step 1: Install and gate
.gitlab-ci.yml
--fail-under 90 makes mcpscore exit with code 3 when the score, as a
rounded percentage, is below 90. GitLab fails a job whose script exits with
anything but 0, so the threshold is the gate. The other codes a job can see
are 2 when mcpscore cannot connect and 1 for a usage error; the
troubleshooting page lists them all.
Pin the version you tested. A new mcpscore release can add rules, and an
unpinned install would move your score on a day your server did not change.
Bump the pin in its own merge request, where a score change has one cause.
Check it: set the threshold above your current score, for example
--fail-under 100, and push. The job fails with Gate failed — --fail-under 100. Put the real threshold back once you have seen it fail.
Step 2: Keep the report
.gitlab-ci.yml
--json writes the full report to stdout; the log lines go to stderr, so
redirecting stdout captures clean JSON. --sarif writes the failed rules as
SARIF 2.1.0. Both files are written before the gate runs, so a failed job
still has them. when: always tells GitLab to keep the artifacts when the
job fails, which is when you need them.
The JSON carries the score, the maximum and one entry per rule:
schema_version and described in the
stability contract.
Step 3: Audit a server behind auth
Add a masked CI/CD variable namedMCPSCORE_TOKEN in the project settings.
mcpscore reads it without a flag and sends it as Authorization: Bearer,
so the job file does not change and the token never appears in it.
--fail-under, because a score from a handful of checks cannot show the
threshold was met. See Audit a server behind auth.
Step 4: Audit the server in your repository
A server in the repository is audited the same way as a URL: put--stdio
and the command that starts it where the URL was. --stdio takes the rest of
the line, so every mcpscore option goes before it.
.gitlab-ci.yml
--stdio node build/index.js. Smoke mode adds
--smoke to also call the server’s read-only tools; a failed smoke check
exits 4.
Step 5: Report without blocking
To see the score on every pipeline before you enforce it, let the job fail on the gate without failing the pipeline:.gitlab-ci.yml
3 now shows as a warning. Exit code 2, a server mcpscore could
not reach, still fails the pipeline, because that is a broken deployment and
not a lower score.
Any other CI
Jenkins, CircleCI, Buildkite, Azure Pipelines and the rest run shell commands, and a shell command’s exit code decides the step. This script works in all of them. It needs Python for mcpscore andjq to print the
summary.
mcpscore-gate.sh
-s test skips the summary instead of
failing on an empty file. Archive mcpscore.json and mcpscore.sarif with
your CI’s artifact step. SARIF is the format GitHub code scanning reads; the
GitHub Action uploads it
for you.
Recap
- Install a pinned mcpscore and gate with
--fail-under. - Keep the report with
--jsonand--sarif, as artifacts saved even when the job fails. - Pass a token through the masked
MCPSCORE_TOKENvariable. - Audit the server in your repository with
--stdioand its start command. - Report without blocking with
allow_failure: exit_codes: [3].
What’s next
- Configure rules to turn off rules that do not fit your
server, or fail the gate on any HIGH finding with
[gate]. - Improve your score for the fixes most servers need.
- Troubleshooting when the job exits
2.