Skip to main content

mcpscore

CI Coverage PyPI Python License

Lighthouse for MCP. Audit any MCP (Model Context Protocol) server and get a scored, actionable report in seconds.

MCP servers that break the spec fail in the worst place: silently, inside someone else's agent. A missing tool description, a stale protocol version, or an unencrypted endpoint never crashes your server. It makes agents pick the wrong tool, drop you from their registry, or leak traffic. mcpscore finds that before your users do. Deterministic, no API key, no sign-up.

pip install mcpscore
mcpscore https://mcp.deepwiki.com/mcp
Welcome to mcpscore!
Successfully connected to MCP server via Streamable HTTP: https://mcp.deepwiki.com/mcp
Transport: streamable-http
Starting the audit...
✅ Protocol version '2025-11-25' is one of the allowed versions
❌ Not using the latest protocol version: negotiated '2025-11-25', latest is '2026-07-28', and no stateless-lifecycle support was observed
✅ Server name is present: 'DeepWiki'
❌ Server title is not present in server info
✅ Declares the tools capability and serves 3 via tools/list
✅ Server uses HTTPS with valid TLS (TLSv1.3)
...
Audit finished. Final score: 78/91
Spec: 2025-11-25 negotiated (latest: 2026-07-28) · era: legacy
Readiness for MCP 2026-07-28: 3/13 (informative — not part of the main score; 4 of 21 checks assessed)

Every ❌ is one thing to fix, and every result cites the spec section or best practice it enforces. Full docs: docs.mcpscore.dev.

Audit any server, in any language

# A local Python or Node server — the transport is detected automatically
mcpscore path/to/server.py
mcpscore path/to/server.js

# Any other language: --stdio runs a command and consumes the rest of the line,
# so put every mcpscore option before it
mcpscore --stdio ./my-go-server
mcpscore --stdio java -jar server.jar
# A Python server in its own project environment (a bare `server.py` target
# runs under mcpscore's interpreter instead):
mcpscore --stdio uv run server.py

# Pass config to the server with --env; for secrets use the value-less form,
# which copies from your environment and keeps the value out of the report
API_KEY=... mcpscore --env API_KEY --stdio ./my-go-server

# A remote server (Streamable HTTP or SSE, detected automatically)
mcpscore https://your-server.example/mcp

# Behind OAuth or an API key: bring a token, or let --oauth open the browser
mcpscore https://your-server.example/mcp --token "$TOKEN"
mcpscore https://your-server.example/mcp --oauth

With uv installed: uvx mcpscore <target>. Node users can run npx @mcp-box/mcpscore <target> with uv or pipx also on PATH; the npm package launches the Python engine. See the npm setup guide. Guides: authenticated servers, CLI reference.

Use it in CI

# Machine-readable report on stdout; logs go to stderr
mcpscore https://your-server.example/mcp --json > report.json

# Failed rules as SARIF, for GitHub code scanning (upload with github/codeql-action/upload-sarif)
mcpscore https://your-server.example/mcp --sarif mcpscore.sarif

# Fail the build when the score drops below 80%
mcpscore https://your-server.example/mcp --fail-under 80

# After the audit, actually call your own server's tools and check they behave
mcpscore path/to/server.py --smoke

Rules that don't apply to your server, or matter more to you, go in a mcpscore.toml next to your code: off turns a rule off, a severity name re-ranks it, and [gate] fail_on = "high" fails the build on any failed rule counted in the main score at or above it. It changes the score in your CI only, never the badge. Details: configure rules.

Exit code Meaning
0 Audit completed and every gate passed
1 Audit never ran: usage error or a failed --oauth flow
2 Could not connect to the server
3 --fail-under or --fail-under-readiness threshold not met
4 A --smoke check failed (3 wins when both fail)

The GitHub Action wraps this into one step that gates the pull request and posts the report as a comment. Smoke mode explains what --smoke calls and why it never changes the score.

What the score measures

Each rule has a severity and a weight. Passing rules add their weight, and the score is reported as earned/maximum. Rules that cannot apply to your server are skipped and excluded from the maximum, never failed.

Severity Weight Example
CRITICAL 5 Protocol version, server name, TLS
HIGH 3 Server version, valid tool schemas
MEDIUM 2 Titles, descriptions, error hygiene
LOW 1 Capability extras, transport recommendations

105 rules run today, in four categories:

  • Protocol (17 rules): protocol version, server name, title and version, advertised capabilities, transport. SSE-only servers get migration advice.
  • Primitives (50 rules): tools, prompts, resources, and resource templates. Names, titles, descriptions, JSON Schema validity, URIs, MIME types, annotations, and pagination behavior. These decide whether an agent picks the right tool and calls it correctly.
  • Security & Auth (12 rules): TLS version and certificate, Origin validation against DNS rebinding, error responses that leak data, and for auth-gated servers the OAuth posture: the WWW-Authenticate challenge, RFC 9728 resource metadata, the RFC 8414 authorization-server chain, and PKCE enforcement.
  • Readiness (20 rules): how ready the server is for the 2026-07-28 spec revision, on its own axis. Servers already on the new stateless lifecycle get these points counted in the main score. Legacy servers see them as guidance.

Six separate Packaging rules score a published npm or PyPI listing with --package npm:name or --package pypi:name. The package is read from the registry and never downloaded or run, and its score has its own denominator.

How it all fits together: scoring methodology. Every rule with its weight and the spec revisions it applies to: rules reference.

JSON report

--json writes one JSON document to stdout. rule_id values are stable across releases and are the key to build tooling on. Names and messages can be reworded.

{
  "schema_version": 1,
  "mcpscore_version": "1.11.0",
  "target": "https://mcp.deepwiki.com/mcp",
  "transport": "streamable-http",
  "score": 78,
  "max_score": 91,
  "partial": false,
  "spec": { "negotiated_version": "2025-11-25", "latest_version": "2026-07-28", "era": "legacy" },
  "results": [
    {
      "rule_id": "protocol_version_allowed",
      "severity": "CRITICAL",
      "severity_value": 5,
      "passed": true,
      "message": "✅ Protocol version '2025-11-25' is one of the allowed versions",
      "details": {
        "basis": "MCP 2025-11-25 Lifecycle §Version Negotiation (server MUST respond with a version it supports)"
      }
    }
  ]
}

What is stable and what moves between releases: stability contract.

Score badge

Every server audited on mcpscore.dev gets a badge URL keyed by the server URL, and a report link keyed the same way. Embed it once and it shows the latest score forever.

[![mcpscore score](https://mcpscore.dev/api/v1/servers/badge.svg?url=https%3A%2F%2Fyour-server.example%2Fmcp)](https://mcpscore.dev/s?url=https%3A%2F%2Fyour-server.example%2Fmcp)

The report page on mcpscore.dev has this snippet prefilled for your server. Details: score badge.

When it fails

Error connecting to the MCP server: https://... (exit 2)

  • Cause: the URL answered, but not as an MCP endpoint. The log above it shows the legacy handshake failing and the modern-only probe finding nothing.
  • Fix: point at the MCP endpoint itself, usually ending in /mcp.

Server script not found: ./server.py (exit 2)

  • Cause: the path does not exist relative to where you ran the command.
  • Fix: check the path. For non-Python, non-Node servers use --stdio <command>.

'server.py' is a script, not an executable command (exit 2)

  • Cause: --stdio executes a program, and a bare script name is looked up on PATH like any other command.
  • Fix: name the interpreter: --stdio uv run server.py or --stdio python server.py. Lines the audited server process writes to stderr appear in the output prefixed with server stderr:; the extra launches the sessionless probes make are silent.

A local server starts and then the audit hangs or exits 2

  • Cause: the server's runtime is not on PATH, or it needs an environment variable it did not get.
  • Fix: run the command yourself first. Pass config with --env NAME=VALUE, secrets with --env NAME.

PARTIAL score: 24/27 from 10 of 78 checks

  • Cause: the server answered 401 and you passed no credential, so only the auth, TLS, and transport surface was scored.
  • Fix: pass --token, --header, or --oauth. See authenticated servers.

A rule flags a protocol version mcpscore does not recognize

  • Cause: your server is newer than the installed mcpscore.
  • Fix: upgrade, and if it persists, open an issue with the version.

Requirements

  • Python 3.11 or newer.
  • For local servers, the server's own runtime on PATH: Node.js for .js targets, Python for .py targets, and whatever --stdio names for the rest.

Use as a library

The package is fully typed (py.typed). MCPClient connects and collects, MCPAuditor runs the rules and builds the same report the CLI prints.

Contributing

CONTRIBUTING.md covers the development setup and how to add a rule. MISSION.md says why the project exists. SECURITY.md is for security reports. CHANGELOG.md lists every release. Bugs and ideas go to GitHub issues.

License

MIT. See LICENSE.

Metadata

Release files for mcpscore 1.20.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcpscore 1.20.0
File Size Uploaded
mcpscore-1.20.0.tar.gz 379.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcpscore 1.20.0
File Interpreter ABI Platform
mcpscore-1.20.0-py3-none-any.whl Python 3 none any Details

Total release size: 593.2 kB

Release files / mcpscore-1.20.0.tar.gz

Download URL mcpscore-1.20.0.tar.gz
Size 379.8 kB
Tags Source
SHA-256 checksum
How to use checksums
82a72b9bdd08d819f0d5cc0a097984fc22dc0d86e00798b00d55235aad7a4249
BLAKE2b-256 checksum
How to use checksums
2e2900a0039dfb28325f0301f8a004a163fd970ca3cb2a6ecb767b0623d3b5be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / mcpscore-1.20.0-py3-none-any.whl

Download URL mcpscore-1.20.0-py3-none-any.whl
Size 213.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e87daa70738e65019fdce149fc17cd606bdab130732eb94d34c48e9382991719
BLAKE2b-256 checksum
How to use checksums
ef88de64a4fec07e18abef6ed8526e0a8d31efa972e3c5aa89cd1762c8a2e78b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release history Release notifications | RSS feed

1.22.2

2 release files

1.21.1

2 release files

1.21.0

2 release files

This release

1.20.0 This release

2 release files

1.19.0

2 release files

1.18.0

2 release files

1.17.0

2 release files

1.16.0

2 release files

1.15.0

2 release files

1.14.2

2 release files

1.14.1

2 release files

1.14.0

2 release files

1.10.0

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page