Repository navigation
Releases
mcp-lint v1.2
mcp-lint v1.2 lints remote MCP servers, adds a CI gate for rug pulls, and is the first release on PyPI.
pip install mcp-linterThe package is mcp-linter; the command is still mcp-lint.
What's new
- Streamable HTTP transport.
run,lockandinit-fixturestake--urlinstead of a launch command.--header "Name: value"is for non-secret headers.--header-env "Name=VAR"reads a secret header value from an environment variable. - GitHub Action and pre-commit hook for
lock --check.action.ymlis a composite Action that works with acommandor aurland writes the report to the job summary..pre-commit-hooks.yamladds the hookmcp-lint-lock. - PyPI releases. Publishing uses Trusted Publishing, so no API token is stored.
Secret handling over HTTP
- The URL is shown only as
scheme://host. Locks and reports store a hash of the scheme, host, port and path, never user info or the query string. - Header values are never stored or hashed, so rotating a token isn't a lock change.
--header-envis refused over plainhttp://unless the host is loopback, and plainhttp://clients ignore proxy environment variables.- A redirect to another origin isn't followed, so headers aren't sent there.
- If a server echoes a secret back,
runandlock --checkredact it, andlockandinit-fixturesrefuse to write it to disk.
Changed
- Now requires
mcp>=2.3andhttpx2. run --jsonaddsserver.transport.
Known limits
- Benign query values such as
?mode=readcount as secrets. - Tokens in the URL path get no echo protection.
proxyandevalare stdio only.
Requires Python 3.10+.
mcp-lint v1.1
mcp-lint v1.1 adds MCP security checks. v1.0 asked whether a server's tools are easy for an agent to use. v1.1 also asks whether they can be trusted.
What's new
-
S8: hidden text in tool metadata. A server can hide instructions where the model reads them but the user doesn't. S8 searches every description, nested schema field, parameter name and enum value for:
- invisible characters: Unicode TAG-block, zero-width and bidi;
- HTML comments;
- secret paths such as
~/.sshand.env; - phrases aimed at the model, such as "do not tell the user";
- mentions of other servers' tools.
It is quiet on the 18 real servers surveyed.
-
mcp-lint lock/lock --check: a tool lockfile against rug pulls. It records a hash of each tool's definition inmcp-lint.lock. On each check, it reports any change to text the model reads, or any schema that now accepts or asks for more, as an error.lock --checkexits non-zero, so it can gate CI. -
I1 install lint and
mcp-lint check-config. These read Claude Desktop, Claude Code, Cursor and VS Code MCP configs and flag:npx/uvx/pipxpackages with no exact version;- git sources not pinned to a commit;
- container images without a digest;
pip installwithout--require-hashes.
Known-bad releases (postmark-mcp 1.0.16; litellm 1.82.7, 1.82.8, 1.107.0) are errors, and
run,proxy,lockandinit-fixturesrefuse to launch them.
Fixes
run --jsonnow stores a hash of the launch command (server.command_sha256), not the command itself, so tokens passed as arguments don't end up in reports. Breaking for scripts that readserver.command.- Tools nested more than 64 levels deep are rejected cleanly on every platform.
Also
- CI runs the tests on Ubuntu with Python 3.10–3.13 and on Windows with 3.13, and builds the wheel.
Requires Python 3.10+.
mcp-lint v1.0
First release of mcp-lint: a CLI that checks MCP servers against Anthropic's guidance on writing tools for agents.
What's in it
mcp-lint: static rules S1–S7 (tool definitions) and probe rules P1–P5 (real calls with a minimal environment), with a token-weighted score per tool and per server.mcp-lint proxy -- <server>: wraps a server without changing it and fixes what the linter flags: paging for large outputs, replacement descriptions from a JSON file, andisErroron error text returned as success.mcp-lint eval: a reproducible before/after experiment that runs Claude Code against real servers.
Does it matter? On 15 held-out tasks across server-filesystem, markitdown-mcp and mcp-server-git (Claude Haiku, 3 runs each), agent success went from 53% to 98% with the proxy's fixes. The worst-scored server gained the most. See eval/REPORT.md for the full numbers and caveats.
Requires Python 3.10+.