mcp-scorecard 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. mcp_scorecard-0.1.1/.github/workflows/publish.yml +40 -0
  2. mcp_scorecard-0.1.1/.github/workflows/release.yml +41 -0
  3. mcp_scorecard-0.1.1/.github/workflows/test.yml +22 -0
  4. mcp_scorecard-0.1.1/.gitignore +14 -0
  5. mcp_scorecard-0.1.1/CHANGELOG.md +33 -0
  6. mcp_scorecard-0.1.1/CODE_OF_CONDUCT.md +23 -0
  7. mcp_scorecard-0.1.1/LICENSE +21 -0
  8. mcp_scorecard-0.1.1/PKG-INFO +129 -0
  9. mcp_scorecard-0.1.1/README.md +92 -0
  10. mcp_scorecard-0.1.1/SECURITY.md +26 -0
  11. mcp_scorecard-0.1.1/docs/design.md +138 -0
  12. mcp_scorecard-0.1.1/pyproject.toml +68 -0
  13. mcp_scorecard-0.1.1/scripts/extract_ts_manifest.py +65 -0
  14. mcp_scorecard-0.1.1/src/mcp_preflight/__init__.py +10 -0
  15. mcp_scorecard-0.1.1/src/mcp_preflight/checks/__init__.py +7 -0
  16. mcp_scorecard-0.1.1/src/mcp_preflight/checks/footprint.py +134 -0
  17. mcp_scorecard-0.1.1/src/mcp_preflight/checks/name.py +122 -0
  18. mcp_scorecard-0.1.1/src/mcp_preflight/checks/scoping.py +179 -0
  19. mcp_scorecard-0.1.1/src/mcp_preflight/checks/score.py +85 -0
  20. mcp_scorecard-0.1.1/src/mcp_preflight/checks/security.py +157 -0
  21. mcp_scorecard-0.1.1/src/mcp_preflight/cli.py +247 -0
  22. mcp_scorecard-0.1.1/src/mcp_preflight/data/__init__.py +0 -0
  23. mcp_scorecard-0.1.1/src/mcp_preflight/data/known_brands.py +83 -0
  24. mcp_scorecard-0.1.1/src/mcp_preflight/loader.py +243 -0
  25. mcp_scorecard-0.1.1/src/mcp_preflight/mcp_server.py +123 -0
  26. mcp_scorecard-0.1.1/src/mcp_preflight/tokens.py +30 -0
  27. mcp_scorecard-0.1.1/tests/__init__.py +0 -0
  28. mcp_scorecard-0.1.1/tests/fixtures/sample_fastmcp.py +23 -0
  29. mcp_scorecard-0.1.1/tests/test_footprint.py +15 -0
  30. mcp_scorecard-0.1.1/tests/test_loader.py +29 -0
  31. mcp_scorecard-0.1.1/tests/test_name.py +18 -0
  32. mcp_scorecard-0.1.1/tests/test_scoping.py +32 -0
  33. mcp_scorecard-0.1.1/tests/test_security.py +39 -0
@@ -0,0 +1,40 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build-and-publish:
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/mcp-scorecard
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.12"
27
+
28
+ - name: Install build tooling
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+ pip install build twine
32
+
33
+ - name: Build sdist + wheel
34
+ run: python -m build
35
+
36
+ - name: Verify package metadata
37
+ run: twine check dist/*
38
+
39
+ - name: Publish to PyPI (Trusted Publisher OIDC)
40
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,41 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ with:
16
+ fetch-depth: 0
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - name: Install build tooling
24
+ run: |
25
+ python -m pip install --upgrade pip
26
+ pip install build twine
27
+
28
+ - name: Build sdist + wheel
29
+ run: python -m build
30
+
31
+ - name: Verify package metadata
32
+ run: twine check dist/*
33
+
34
+ - name: Upload to GitHub Release
35
+ env:
36
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
+ run: |
38
+ gh release upload "${GITHUB_REF##*/}" dist/* --clobber
39
+
40
+ # PyPI publishing is handled by publish.yml (Trusted Publisher / OIDC).
41
+ # This workflow only uploads the sdist + wheel to the GitHub Release.
@@ -0,0 +1,22 @@
1
+ name: test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python: ["3.10", "3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python }}
20
+ - run: pip install -e ".[dev,mcp]"
21
+ - run: pytest -q
22
+ - run: ruff check .
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ .venv/
12
+ venv/
13
+ .DS_Store
14
+ *.swp
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to `mcp-scorecard` will be documented in this file.
4
+ The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [0.1.1] — 2026-07-13
7
+
8
+ ### Changed
9
+ - Renamed from `mcp-preflight` to `mcp-scorecard` before first PyPI upload
10
+ (an unrelated `mcp-preflight` project already occupies that PyPI namespace,
11
+ and `mcp-pre-flight` was also rejected as too similar). Package, CLI, MCP
12
+ server, and repository are all `mcp-scorecard` from v0.1.1. v0.1.0 exists
13
+ only as a pre-rename local tag and was never published.
14
+
15
+ ## [0.1.0] — 2026-07-13 (unpublished)
16
+
17
+ ### Added
18
+ - Four-layer scorecard model: Passive Footprint / Use-Case Scoping / Security / Name Safety.
19
+ - AST loader for FastMCP-style Python servers (`@mcp.tool()` extraction, no code execution).
20
+ - Manifest loader for non-Python MCP servers (`tools/list` JSON).
21
+ - Layer A — passive footprint: `initial_token_load` (tiktoken cl100k), `per_tool_tokens`,
22
+ bloat detection (> 150 tok description), schema verbosity, tool count thresholds.
23
+ - Layer B — use-case scoping: when-to-use trigger detection, vague-verb scan,
24
+ overlap detection, naming-style consistency, AI-slop markers.
25
+ - Layer C — security: prompt-injection-in-description, tool-shadowing, hardcoded
26
+ secret regex sweep (AWS / GitHub / OpenAI / Anthropic / Slack / PEM).
27
+ - Layer D — name safety: case collision, Levenshtein brand similarity,
28
+ separator variants, namespace hygiene. Bundled ~50 brands + known MCPs.
29
+ - CLI: `mcp-scorecard` / `mpf` with `scan`, `footprint`, `scoping`, `security`, `name`.
30
+ - MCP server: `mcp-scorecard-mcp` exposes five preflight_* tools over stdio.
31
+ - Dogfood/validation on domain-pre-flight, rag-db-advisor, opencut-mcp, and self.
32
+ - CI: pytest on 3.10 / 3.11 / 3.12, ruff.
33
+ - TypeScript static manifest extractor: `scripts/extract_ts_manifest.py`.
@@ -0,0 +1,23 @@
1
+ # Code of Conduct
2
+
3
+ ## Standards
4
+
5
+ Be respectful and constructive. Specifically:
6
+
7
+ - Engage with the substance of contributions, not the contributor.
8
+ - Surface disagreements as questions or trade-offs, not personal critique.
9
+ - If you encounter behaviour that makes the project less welcoming to a class of people, raise it (privately if you prefer) so we can address it.
10
+
11
+ ## Scope
12
+
13
+ This applies to all project spaces: GitHub issues / PRs / discussions, the project README and docs, and any out-of-band communication that references the project.
14
+
15
+ ## Reporting
16
+
17
+ Open a private security advisory or contact the maintainer directly via the GitHub profile linked from the README. Reports are confidential.
18
+
19
+ ## Enforcement
20
+
21
+ The maintainer reserves the right to remove comments, close issues, or block accounts that repeatedly violate the standards above. Persistent or egregious violations may result in a permanent ban.
22
+
23
+ This document is intentionally short. The Contributor Covenant (https://www.contributor-covenant.org/) is the underlying inspiration; if you want a longer reference text, read it there.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ken Imoto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-scorecard
3
+ Version: 0.1.1
4
+ Summary: Pre-flight checks for MCP servers: passive token footprint, use-case scoping, security, and name safety. LLM-facing quality scorecard.
5
+ Project-URL: Homepage, https://github.com/kenimo49/mcp-scorecard
6
+ Project-URL: Repository, https://github.com/kenimo49/mcp-scorecard
7
+ Project-URL: Issues, https://github.com/kenimo49/mcp-scorecard/issues
8
+ Project-URL: Funding, https://github.com/sponsors/kenimo49
9
+ Author: Ken Imoto
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: audit,llm,mcp,model-context-protocol,pre-flight,security,token
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Security
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: click>=8.1
24
+ Requires-Dist: levenshtein>=0.25
25
+ Requires-Dist: pyyaml>=6.0
26
+ Requires-Dist: rich>=13.7
27
+ Requires-Dist: tiktoken>=0.7
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
31
+ Requires-Dist: pytest-mock>=3.12; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.5; extra == 'dev'
34
+ Provides-Extra: mcp
35
+ Requires-Dist: mcp>=1.2; extra == 'mcp'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # mcp-scorecard
39
+
40
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
41
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/kenimo49?logo=githubsponsors&label=Sponsor)](https://github.com/sponsors/kenimo49)
42
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-tip-FF5E5B?logo=kofi&logoColor=white)](https://ko-fi.com/kenimo49)
43
+
44
+ > ⚠️ **Status: v0.1 alpha — under active development.**
45
+ > Rules, thresholds, and scoring are being calibrated against real-world MCP servers.
46
+
47
+ Pre-flight checks for MCP (Model Context Protocol) servers.
48
+
49
+ `mcp-scorecard` answers one question: **"Is this MCP server safe and efficient enough for LLMs to actually use?"** — before you publish it, install it, or let it into your agent config.
50
+
51
+ Existing MCP tools cover runtime security (MCP-Scan) and protocol compliance (MCP Inspector). This one covers the missing layer: **how expensive is the server just to keep registered, and are its tools scoped well enough for an LLM to pick the right one?**
52
+
53
+ Companion tool to the book **『MCP実践セキュリティ』** (Impress NextPublishing).
54
+
55
+ ## The four layers
56
+
57
+ | Layer | What it measures | Status |
58
+ |-------|------------------|--------|
59
+ | **A. Passive Footprint** | Tokens the server steals from every LLM turn just by being listed. `tools/list` initial load, per-tool cost, bloat ratio, schema verbosity | v0.1 |
60
+ | **B. Use-Case Scoping** | Whether each tool is narrow enough that the LLM knows when to use it. When-to-use present, vague verb scan, overlap detection, naming consistency, AI Slop | v0.1 |
61
+ | **C. Security** | Own rules (prompt injection in description, tool shadowing, hardcoded secrets, transport hygiene) + optional MCP-Scan wrap | v0.1 own rules; wrap in v0.2 |
62
+ | **D. Name Safety** | Case collision, brand similarity, separator variants, namespace hygiene | v0.1 |
63
+
64
+ Design details: [docs/design.md](docs/design.md).
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pip install mcp-scorecard # CLI + library
70
+ pip install "mcp-scorecard[mcp]" # + MCP server (stdio)
71
+ ```
72
+
73
+ ## Use as a CLI
74
+
75
+ ```bash
76
+ # Full scan
77
+ mcp-scorecard scan ./path/to/server.py
78
+ mcp-scorecard scan http://localhost:8000/
79
+ mcp-scorecard scan pypi:some-mcp
80
+
81
+ # Layer-only
82
+ mcp-scorecard footprint ./server.py
83
+ mcp-scorecard scoping ./server.py
84
+ mcp-scorecard security ./server.py
85
+ mcp-scorecard name my-new-mcp
86
+
87
+ # CI-friendly
88
+ mcp-scorecard scan ./server.py --json
89
+ mcp-scorecard scan ./server.py --format sarif
90
+ # exit codes: 0=GREEN/YELLOW, 1=ORANGE, 2=RED
91
+ ```
92
+
93
+ ## Use as an MCP server (self-hosting)
94
+
95
+ Register `mcp-scorecard` itself as an MCP tool in Claude Code / Cursor / Windsurf, then ask the LLM to audit another MCP:
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "mcp-scorecard": {
101
+ "command": "mcp-scorecard-mcp"
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ Then in chat: *"score the MCP server at ./my-server.py"*.
108
+
109
+ ## Why passive footprint matters
110
+
111
+ Every tool description and inputSchema in a registered MCP server is sent to the LLM on every turn — because the model needs to see them to decide which tool to call. A single verbose server can silently burn 5,000+ tokens per turn before anyone touches it.
112
+
113
+ `mcp-scorecard footprint` measures exactly that, so you can trim before you publish.
114
+
115
+ ## Roadmap
116
+
117
+ - **v0.1** — Layers A + B + D full, Layer C own rules, CLI + MCP server
118
+ - **v0.2** — MCP-Scan wrap, SARIF, real MCP client negotiation
119
+ - **v0.3** — Book『MCP実践セキュリティ』章別ルール取り込み
120
+ - **v0.4** — Registry-source targets (`github:` / `npm:`)
121
+
122
+ ## Support this project
123
+
124
+ - 💚 [GitHub Sponsors](https://github.com/sponsors/kenimo49)
125
+ - ☕ [Ko-fi](https://ko-fi.com/kenimo49)
126
+
127
+ ## License
128
+
129
+ MIT.
@@ -0,0 +1,92 @@
1
+ # mcp-scorecard
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
+ [![GitHub Sponsors](https://img.shields.io/github/sponsors/kenimo49?logo=githubsponsors&label=Sponsor)](https://github.com/sponsors/kenimo49)
5
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-tip-FF5E5B?logo=kofi&logoColor=white)](https://ko-fi.com/kenimo49)
6
+
7
+ > ⚠️ **Status: v0.1 alpha — under active development.**
8
+ > Rules, thresholds, and scoring are being calibrated against real-world MCP servers.
9
+
10
+ Pre-flight checks for MCP (Model Context Protocol) servers.
11
+
12
+ `mcp-scorecard` answers one question: **"Is this MCP server safe and efficient enough for LLMs to actually use?"** — before you publish it, install it, or let it into your agent config.
13
+
14
+ Existing MCP tools cover runtime security (MCP-Scan) and protocol compliance (MCP Inspector). This one covers the missing layer: **how expensive is the server just to keep registered, and are its tools scoped well enough for an LLM to pick the right one?**
15
+
16
+ Companion tool to the book **『MCP実践セキュリティ』** (Impress NextPublishing).
17
+
18
+ ## The four layers
19
+
20
+ | Layer | What it measures | Status |
21
+ |-------|------------------|--------|
22
+ | **A. Passive Footprint** | Tokens the server steals from every LLM turn just by being listed. `tools/list` initial load, per-tool cost, bloat ratio, schema verbosity | v0.1 |
23
+ | **B. Use-Case Scoping** | Whether each tool is narrow enough that the LLM knows when to use it. When-to-use present, vague verb scan, overlap detection, naming consistency, AI Slop | v0.1 |
24
+ | **C. Security** | Own rules (prompt injection in description, tool shadowing, hardcoded secrets, transport hygiene) + optional MCP-Scan wrap | v0.1 own rules; wrap in v0.2 |
25
+ | **D. Name Safety** | Case collision, brand similarity, separator variants, namespace hygiene | v0.1 |
26
+
27
+ Design details: [docs/design.md](docs/design.md).
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pip install mcp-scorecard # CLI + library
33
+ pip install "mcp-scorecard[mcp]" # + MCP server (stdio)
34
+ ```
35
+
36
+ ## Use as a CLI
37
+
38
+ ```bash
39
+ # Full scan
40
+ mcp-scorecard scan ./path/to/server.py
41
+ mcp-scorecard scan http://localhost:8000/
42
+ mcp-scorecard scan pypi:some-mcp
43
+
44
+ # Layer-only
45
+ mcp-scorecard footprint ./server.py
46
+ mcp-scorecard scoping ./server.py
47
+ mcp-scorecard security ./server.py
48
+ mcp-scorecard name my-new-mcp
49
+
50
+ # CI-friendly
51
+ mcp-scorecard scan ./server.py --json
52
+ mcp-scorecard scan ./server.py --format sarif
53
+ # exit codes: 0=GREEN/YELLOW, 1=ORANGE, 2=RED
54
+ ```
55
+
56
+ ## Use as an MCP server (self-hosting)
57
+
58
+ Register `mcp-scorecard` itself as an MCP tool in Claude Code / Cursor / Windsurf, then ask the LLM to audit another MCP:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "mcp-scorecard": {
64
+ "command": "mcp-scorecard-mcp"
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ Then in chat: *"score the MCP server at ./my-server.py"*.
71
+
72
+ ## Why passive footprint matters
73
+
74
+ Every tool description and inputSchema in a registered MCP server is sent to the LLM on every turn — because the model needs to see them to decide which tool to call. A single verbose server can silently burn 5,000+ tokens per turn before anyone touches it.
75
+
76
+ `mcp-scorecard footprint` measures exactly that, so you can trim before you publish.
77
+
78
+ ## Roadmap
79
+
80
+ - **v0.1** — Layers A + B + D full, Layer C own rules, CLI + MCP server
81
+ - **v0.2** — MCP-Scan wrap, SARIF, real MCP client negotiation
82
+ - **v0.3** — Book『MCP実践セキュリティ』章別ルール取り込み
83
+ - **v0.4** — Registry-source targets (`github:` / `npm:`)
84
+
85
+ ## Support this project
86
+
87
+ - 💚 [GitHub Sponsors](https://github.com/sponsors/kenimo49)
88
+ - ☕ [Ko-fi](https://ko-fi.com/kenimo49)
89
+
90
+ ## License
91
+
92
+ MIT.
@@ -0,0 +1,26 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ The latest minor (`0.x`) is supported. Older releases receive no fixes.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ `domain-pre-flight` is a defensive / pre-flight tool; it does not handle credentials, run servers, or process untrusted input at scale. The realistic vulnerability surfaces are:
10
+
11
+ 1. The HTTP clients in `handles.py` / `rdap.py` (a malicious response could trigger excessive memory / CPU).
12
+ 2. The DNS client in `dns_sanity.py` (a malicious authoritative server could attempt DoS via large TXT records).
13
+ 3. The data-loading paths for `data/known_brands.txt` and `data/negative_meanings/*.txt` (a tampered repo could ship a poisoned word list).
14
+
15
+ To report a suspected vulnerability:
16
+
17
+ - Open a **private security advisory** at https://github.com/kenimo49/domain-pre-flight/security/advisories/new.
18
+ - Or email the maintainer directly (contact via the GitHub profile).
19
+
20
+ Please do **not** file a public issue for a suspected vulnerability.
21
+
22
+ ## What to expect
23
+
24
+ - Acknowledgement within 5 working days.
25
+ - A patch or detailed mitigation guidance within 30 days for confirmed issues.
26
+ - Public disclosure only after the fix is released; CVE assignment if applicable.
@@ -0,0 +1,138 @@
1
+ # mcp-scorecard — design doc
2
+
3
+ > Pre-flight checks for MCP servers. Answers **"is this MCP server safe and efficient enough for LLMs to use?"** before you publish or install it.
4
+
5
+ ## Positioning
6
+
7
+ Existing tools focus on runtime security (MCP-Scan / Cisco MCP-Scanner / AgentAuditKit) or protocol compliance (MCP Inspector / mcp-validator / mcp-validation). None cover the **LLM-facing quality** dimension: how much context the server consumes just by being listed, whether its tools have well-scoped use cases, and whether description prose is clear.
8
+
9
+ `mcp-scorecard` is the pre-publish scorecard that closes that gap, then wraps the security tools underneath so a single command grades your MCP end-to-end.
10
+
11
+ Companion to the book **『MCP実践セキュリティ』** — the book teaches the checks, this tool runs them.
12
+
13
+ ## Four layers
14
+
15
+ ### Layer A — Passive Footprint (differentiator, unique to this tool)
16
+
17
+ The tokens an MCP server steals from every LLM turn **just by being registered**, regardless of whether tools are called.
18
+
19
+ | Check | What it measures |
20
+ |-------|------------------|
21
+ | `initial_token_load` | Total tiktoken (cl100k) for the tools/list response: every tool name + description + inputSchema |
22
+ | `per_tool_tokens` | Token cost per tool, ranked highest → lowest |
23
+ | `bloat_ratio` | Fraction of tools whose description exceeds 150 tokens |
24
+ | `tool_count` | Total tool count. Warn > 15, fail > 30 |
25
+ | `schema_verbosity` | inputSchema tokens vs description tokens — schema-heavy tools are a common LLM budget sink |
26
+
27
+ Verdict bands: GREEN < 1,500 tokens · YELLOW 1,500–4,000 · ORANGE 4,000–8,000 · RED > 8,000 (numbers calibrated against real-world MCP servers, revised as we collect more data).
28
+
29
+ ### Layer B — Use-Case Scoping (differentiator)
30
+
31
+ Whether each tool is narrow enough that the LLM knows when to reach for it. Broad "do-anything" tools inflate footprint and cause tool-selection errors.
32
+
33
+ | Check | Detects |
34
+ |-------|---------|
35
+ | `when_to_use_present` | Does the description state a trigger condition? (e.g. "Use this when …") |
36
+ | `vague_verb_scan` | `handle`, `process`, `manage`, `deal with`, `work with`, `execute` without qualifier |
37
+ | `overlap_detection` | Semantic near-duplicates between tools (same responsibility, different names) |
38
+ | `naming_consistency` | Mixed snake_case / camelCase / kebab-case across tools |
39
+ | `description_style` | AI Slop patterns (bullet-list-of-adjectives, marketing prose) — piggy-backs on avoid-ai-writing-en heuristics |
40
+ | `input_output_coherence` | Does the description promise what the schema returns? |
41
+
42
+ ### Layer C — Security (borrow from existing tools + own rules)
43
+
44
+ Mostly borrowed. `mcp-scorecard security` shells out to MCP-Scan if installed and normalises the result, and adds a small independent ruleset for defence in depth.
45
+
46
+ Own rules:
47
+ - `prompt_injection_in_description` — imperative phrases aimed at the LLM inside tool descriptions ("ignore previous instructions", "always call …")
48
+ - `tool_shadowing` — names that impersonate common system utilities (`ls`, `read_file`, `execute`) without a namespace
49
+ - `hardcoded_secret_pattern` — regex sweep on the server source if `--source-path` given
50
+ - `transport_hygiene` — CORS, OAuth 2.1 presence for HTTP transports, DNS-rebinding headers
51
+ - `protocol_version` — reports negotiated MCP spec version, warns if pre-2025-06-18
52
+
53
+ External rules (via wrap):
54
+ - MCP-Scan / agent-scan detections (E001 prompt injection, E002 tool shadowing, W007/W008 credentials, W011 untrusted content, toxic flows)
55
+ - Optional: mcp-validation / mcp-validator for protocol compliance
56
+
57
+ ### Layer D — Name Safety
58
+
59
+ Before publishing an MCP server, is the name safe from typosquat suspicion?
60
+
61
+ | Check | Method |
62
+ |-------|--------|
63
+ | `case_collision` | Same name in different casing already registered somewhere obvious (npm / PyPI / MCP.so) |
64
+ | `brand_similarity` | Levenshtein ≤ 2 to a bundled list of well-known brands / official MCP servers |
65
+ | `separator_variants` | `mcp-scan` vs `mcpscan` vs `mcp_scan` — flag if a common one is taken |
66
+ | `namespace_hygiene` | Recommend `@vendor/tool` style for scoped names |
67
+
68
+ Bundled list starts small (~50 obvious brands + known official MCPs) and grows via `scripts/refresh_known_brands.py`.
69
+
70
+ ## Aggregate scorecard
71
+
72
+ A-F grade per layer, plus overall. JSON / Markdown / SARIF output. CI-friendly exit codes:
73
+ - `0` — GREEN / YELLOW
74
+ - `1` — ORANGE
75
+ - `2` — RED
76
+
77
+ ```
78
+ Layer A (Footprint): B (2,340 tokens across 8 tools)
79
+ Layer B (Use-case): C (3 tools missing when-to-use)
80
+ Layer C (Security): A (no findings; MCP-Scan clean)
81
+ Layer D (Name safety): A (no collisions)
82
+ -----------------------------------------
83
+ Overall: B
84
+ ```
85
+
86
+ ## CLI shape
87
+
88
+ ```
89
+ mcp-scorecard scan <target> # all layers
90
+ mcp-scorecard footprint <target> # Layer A only
91
+ mcp-scorecard scoping <target> # Layer B only
92
+ mcp-scorecard security <target> # Layer C only
93
+ mcp-scorecard name <name> # Layer D only
94
+
95
+ # targets:
96
+ # ./path/to/server.py — Python entry (stdio, subprocess launch)
97
+ # http://localhost:8000/ — HTTP transport
98
+ # pypi:some-mcp — install and scan
99
+ # npm:@scope/some-mcp — install and scan
100
+ # github:owner/repo — clone and scan
101
+ ```
102
+
103
+ ## MCP server surface (self-hosting / dogfooding)
104
+
105
+ Exposes the same layers as MCP tools so an LLM can audit an MCP server from a chat:
106
+
107
+ ```
108
+ preflight_scan(target, layers?)
109
+ preflight_footprint(target)
110
+ preflight_scoping(target)
111
+ preflight_security(target)
112
+ preflight_name_check(name)
113
+ ```
114
+
115
+ Runs via `mcp-scorecard-mcp` (stdio). Install as an MCP tool in Claude Code / Cursor and ask: *"score this MCP server"* → structured verdict.
116
+
117
+ ## Validation targets (own dogfood set)
118
+
119
+ Phase 1 uses three real MCP servers written by the author to bootstrap the calibration:
120
+
121
+ 1. **domain-pre-flight** (11 tools, mature) — reference for Layer A footprint norms
122
+ 2. **rag-db-advisor** — smaller surface
123
+ 3. **opencut-mcp** (v0.1.0) — brand-new MCP, expected clean baseline
124
+ 4. **mcp-scorecard itself** — dogfooding, README badge
125
+
126
+ ## Non-goals (v0.1)
127
+
128
+ - Runtime behaviour analysis / fuzzing
129
+ - Auto-fix
130
+ - Registry-wide scanning (crawling MCP.so etc.) — separate future project
131
+ - Payment / licensing checks
132
+
133
+ ## Roadmap
134
+
135
+ - **v0.1** — Layer A + B full, Layer C own rules only, Layer D bundled list. CLI + MCP server.
136
+ - **v0.2** — MCP-Scan wrap, SARIF output, protocol negotiation via real client
137
+ - **v0.3** — Book『MCP実践セキュリティ』章別ルール取り込み
138
+ - **v0.4** — Registry-source scanning (github: / pypi: / npm: targets)
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "mcp-scorecard"
7
+ version = "0.1.1"
8
+ description = "Pre-flight checks for MCP servers: passive token footprint, use-case scoping, security, and name safety. LLM-facing quality scorecard."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [{ name = "Ken Imoto" }]
12
+ requires-python = ">=3.10"
13
+ keywords = ["mcp", "model-context-protocol", "audit", "security", "token", "llm", "pre-flight"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Security",
22
+ "Topic :: Software Development :: Libraries :: Python Modules",
23
+ "Topic :: Software Development :: Quality Assurance",
24
+ ]
25
+ dependencies = [
26
+ "click>=8.1",
27
+ "rich>=13.7",
28
+ "tiktoken>=0.7",
29
+ "Levenshtein>=0.25",
30
+ "pyyaml>=6.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ mcp = [
35
+ "mcp>=1.2",
36
+ ]
37
+ dev = [
38
+ "pytest>=8.0",
39
+ "pytest-cov>=5.0",
40
+ "pytest-mock>=3.12",
41
+ "mypy>=1.10",
42
+ "ruff>=0.5",
43
+ ]
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/kenimo49/mcp-scorecard"
47
+ Repository = "https://github.com/kenimo49/mcp-scorecard"
48
+ Issues = "https://github.com/kenimo49/mcp-scorecard/issues"
49
+ Funding = "https://github.com/sponsors/kenimo49"
50
+
51
+ [project.scripts]
52
+ mcp-scorecard = "mcp_preflight.cli:main"
53
+ mpf = "mcp_preflight.cli:main"
54
+ mcp-scorecard-mcp = "mcp_preflight.mcp_server:run"
55
+
56
+ [tool.hatch.build.targets.wheel]
57
+ packages = ["src/mcp_preflight"]
58
+
59
+ [tool.ruff]
60
+ line-length = 100
61
+ target-version = "py310"
62
+
63
+ [tool.ruff.lint]
64
+ select = ["E", "F", "W", "I", "N", "UP", "B", "C4", "SIM"]
65
+ ignore = ["E501"]
66
+
67
+ [tool.pytest.ini_options]
68
+ testpaths = ["tests"]