@tomfletcher2929/mcplint
v0.1.2
Published
Lint and score Model Context Protocol (MCP) server tool definitions before you publish — name/schema validity, description quality, token weight, and safety annotations for destructive tools. CLI + library.
Downloads
520
Maintainers
Readme
mcplint
Lint and score your MCP server's tool definitions before you publish — so the model can actually choose them, and they don't quietly bloat every request's context window.
mcplint checks name/schema validity, description quality, token weight, and safety on destructive tools, then gives you a 0–100 score and a CI gate.
Quick start
# install once, then use the short `mcplint` command shown below
npm install -g @tomfletcher2929/mcplint
mcplint tools.json
# or run it without installing:
npx @tomfletcher2929/mcplint tools.jsonLint a static file — a tools array, or an MCP tools/list result ({ "tools": [...] }):
mcplint tools.json # lint + score (free)
mcplint tools.json --ci --min 90 # exit 1 below 90 — drop into CI (free)
mcplint tools.json --json # machine-readable
mcplint tools.json --report # shareable Markdown report (Pro)
mcplint tools.json --report --format html # standalone HTML report (Pro)
mcplint tools.json --watch # re-lint on every save (Pro)Watch mode (Pro) lints once, then re-lints and re-prints on every change
until you quit — pair it with --report to keep a report fresh, or --json to
pipe scores into a dashboard. A static file is watched for saves; a live server
has no file, so it's re-linted on a timer (--interval <seconds>, default 3):
mcplint tools.json --watch # re-lint the file on save
mcplint --cmd node --watch -- dist/server.js # re-lint a live server every 3s
mcplint --cmd node --watch --interval 10 -- dist/server.js # …every 10sOr lint a live server — mcplint spawns it, runs initialize + tools/list
over stdio, and lints exactly what it advertises to a model. Put the server's
own command and args after a literal --:
mcplint --cmd node --ci -- dist/server.js # lint your built server in CI
mcplint --cmd npx -- -y @scope/your-mcp-server # lint a published server
mcplint --cmd python --json -- -m your_server # any stdio MCP serverEverything after -- is passed to the server untouched, so its flags can never
clash with mcplint's (and can't silently disarm --ci). The live path runs the
same rules and scoring as the file path — so a passing file is a passing server.
Lint several sources at once (Pro)
Pass more than one source — files and/or one live --cmd server — to lint them
all in a single pass with a combined summary:
mcplint a.json b.json # several files
mcplint a.json b.json --cmd node --ci -- dist/server.js # files + a live server, gated in CI
mcplint a.json b.json --json # one JSON object per sourceEach source is scored independently and listed on its own row; --ci then fails
if any source breaches --min or has errors (a source that can't even be
linted counts as a failure — never a silent pass). --report and --watch act
on a single source, so run those one source at a time.
What it checks
- valid, unique tool names (
[A-Za-z0-9_-], ≤ 128 chars —snake_caseandkebab-caseboth pass, per the MCP spec) - present, useful, non-placeholder descriptions — not too short, not token-bloated
- object input schemas; required params actually defined in properties
- destructive tools (
delete/drop/exec…) flag their risk in the description
Destructive detection is deliberately conservative: names like
reset_passwordorexecute_querydraw adestructive-safetywarning (not an error) — document the risk in the description to clear it.
Free vs Pro
- Free (no key, always works): lint, score,
--json, and the--cigate — for a single file or a single live--cmdserver. - Pro (one-off):
--reportexport (Markdown or--format html), watch mode, and the multi-source view (several sources in one pass).
→ Get mcplint Pro — you'll be emailed a licence key. Activate it with an environment variable:
export MCPLINT_LICENSE_KEY="mcpl_…" # macOS / Linux
setx MCPLINT_LICENSE_KEY "mcpl_…" # Windows (takes effect in new shells)The key is verified offline — no account, no sign-in, no phone-home. One licence works on all your machines.
Use as a library
import { lint, parseTools } from "@tomfletcher2929/mcplint";
const result = lint(parseTools(JSON.parse(rawJson)));
console.log(result.score, result.findings);MIT-licensed engine. Automated linting catches structure and hygiene, not intent — review findings in context.
