A production-quality linter for MCP (Model Context Protocol) servers
Project description
mcp-lint
A production-quality linter for MCP (Model Context Protocol) servers
mcp-lint connects to any MCP server via stdio or SSE transport, runs 23 deterministic lint rules across 4 categories, and outputs a scored report with CI/CD-friendly exit codes.
No LLM required. No API keys. Pure static analysis of your MCP server's protocol behavior.
Features
- 23 lint rules across 4 categories: Protocol, Schema, Security, Performance
- Multiple transports — stdio and SSE support
- CI/CD ready —
--fail-underflag with exit codes (0 = pass, 1 = below threshold, 2 = error) - 3 output formats — terminal (Rich), JSON, Markdown
- Rule filtering —
--include/--excludespecific rules - Zero configuration — works out of the box with sensible defaults
Installation
pip install mcp-lint
Quick Start
# Lint an MCP server via stdio
mcp-lint "python -m your_mcp_server"
# Lint via SSE
mcp-lint --url http://localhost:8000/sse
# JSON output for CI pipelines
mcp-lint "python -m your_mcp_server" --format json
# Fail CI if score drops below 80%
mcp-lint "python -m your_mcp_server" --fail-under 80
# Verbose output with details
mcp-lint "python -m your_mcp_server" -v
Lint Rules
Protocol (6 rules)
| Rule | Description | Severity |
|---|---|---|
INIT-001 |
protocolVersion is in YYYY-MM-DD format |
Error |
INIT-002 |
serverInfo has name and version |
Error |
INIT-003 |
capabilities is a valid object with known keys |
Error |
INIT-004 |
Declared capabilities match actual behavior | Warning |
TOOL-001 |
tools/list returns a valid list response |
Error |
ERR-001 |
Server returns -32601 for unknown methods |
Warning |
Schema (5 rules)
| Rule | Description | Severity |
|---|---|---|
TOOL-002 |
Every tool has name, description, and inputSchema | Error |
TOOL-003 |
Every inputSchema is valid JSON Schema | Error |
TOOL-004 |
Tool names match [a-zA-Z0-9_\-.] (1-128 chars) |
Warning |
TOOL-005 |
Required fields exist in properties | Error |
RES-001 |
Resources have uri and name | Error |
Security (8 rules)
| Rule | Description | Severity |
|---|---|---|
SEC-001 |
Flag tools with dangerous names (execute, eval, shell...) | Warning |
SEC-002 |
Flag unrestricted file path parameters | Warning |
SEC-003 |
Flag additionalProperties: true or missing |
Warning |
SEC-004 |
Detect prompt injection patterns in descriptions | Error |
SEC-005 |
Flag tracebacks in tool error responses | Warning |
SEC-006 |
Flag tools with empty inputSchema | Warning |
SEC-007 |
Flag unrestricted URL parameters (SSRF risk) | Warning |
SEC-008 |
Flag parameters without type constraints | Warning |
Performance (4 rules)
| Rule | Description | Severity |
|---|---|---|
PERF-001 |
initialize completes in under 5s |
Warning |
PERF-002 |
tools/list completes in under 2s |
Warning |
PERF-003 |
resources/list completes in under 2s |
Warning |
PERF-004 |
prompts/list completes in under 2s |
Warning |
CLI Reference
Usage: mcp-lint [OPTIONS] [COMMAND]
Arguments:
COMMAND MCP server command to run (stdio transport)
Options:
--url TEXT MCP server SSE URL
-f, --format FORMAT Output: terminal, json, markdown (default: terminal)
--fail-under FLOAT Exit 1 if score < threshold (default: 0)
--timeout FLOAT Global timeout in seconds (default: 30)
--include TEXT Comma-separated rule IDs to include
--exclude TEXT Comma-separated rule IDs to exclude
-v, --verbose Show detailed output
-V, --version Show version and exit
Scoring
Each rule produces a result: PASS (1.0), WARN (0.5), FAIL (0.0), or SKIP (excluded from scoring).
The overall score is the weighted average as a percentage, mapped to a letter grade:
| Grade | Score |
|---|---|
| A | 90-100% |
| B | 80-89% |
| C | 70-79% |
| D | 60-69% |
| F | < 60% |
CI/CD Integration
GitHub Actions
- name: Lint MCP Server
run: |
pip install mcp-lint
mcp-lint "python -m my_server" --fail-under 80 --format json
Exit Codes
| Code | Meaning |
|---|---|
0 |
All checks passed (or score >= threshold) |
1 |
Score below --fail-under threshold |
2 |
Connection error or usage error |
Development
git clone https://github.com/Luxshan2000/mcp-lint.git
cd mcp-lint
make dev # install in editable mode
make test # run tests
make lint # run ruff linter
make format # format code
make check # lint + format check + tests
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_lint-0.1.0.tar.gz.
File metadata
- Download URL: mcp_lint-0.1.0.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31f1d3f4dbf7d80f2072451a084d8e0492b8bbe4e4ba3fc6f6584f5a0c934505
|
|
| MD5 |
0fc6cd0ef9e0aa8fe9eb6f645a908f13
|
|
| BLAKE2b-256 |
891dac79d109c76a09bd20d3e45d5be08fd5a252e8a13c794767f51d43f21c9c
|
Provenance
The following attestation bundles were made for mcp_lint-0.1.0.tar.gz:
Publisher:
release.yml on Luxshan2000/mcp-lint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_lint-0.1.0.tar.gz -
Subject digest:
31f1d3f4dbf7d80f2072451a084d8e0492b8bbe4e4ba3fc6f6584f5a0c934505 - Sigstore transparency entry: 1043710477
- Sigstore integration time:
-
Permalink:
Luxshan2000/mcp-lint@269e36ba244e93bf48269c9326b9efe8ae215d2c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Luxshan2000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@269e36ba244e93bf48269c9326b9efe8ae215d2c -
Trigger Event:
push
-
Statement type:
File details
Details for the file mcp_lint-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_lint-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7653d9d5b32e16a359a2d906cc094d854fd9cf6b071036131b54b0ff9327ca1
|
|
| MD5 |
f11517d28a578ade08ed9d0aae29e75c
|
|
| BLAKE2b-256 |
a21aabe044526555607efbd46804e74f4e2a2ebd527346ca7807aad492702b13
|
Provenance
The following attestation bundles were made for mcp_lint-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Luxshan2000/mcp-lint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_lint-0.1.0-py3-none-any.whl -
Subject digest:
b7653d9d5b32e16a359a2d906cc094d854fd9cf6b071036131b54b0ff9327ca1 - Sigstore transparency entry: 1043710519
- Sigstore integration time:
-
Permalink:
Luxshan2000/mcp-lint@269e36ba244e93bf48269c9326b9efe8ae215d2c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Luxshan2000
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@269e36ba244e93bf48269c9326b9efe8ae215d2c -
Trigger Event:
push
-
Statement type: