Answers · MCP security
How do I detect when an MCP server changes its tool descriptions after I approved it (a rug pull)?
Short answer: An MCP rug pull, a term from Invariant Labs' April 2025 tool-poisoning research, is a server changing its tool definitions after you approved them: the description you reviewed was harmless, and the one your model reads today carries injected instructions. Approving a server once is therefore not enough. At approval, record a hash of each tool's name, description and input schema (plus output schema and annotations if present); every time the client fetches tools/list, recompute and compare; and when anything differs, fail closed: disable the changed tool, show the diff, and require a fresh approval. Pin package and image versions for local servers so updates are deliberate, and remember a remote server can change at any time, so for remote servers the hash comparison is your only signal.
Checklist
- At approval, fetch tools/list and store, per tool, a SHA-256 over a canonical serialization of name, title, description, inputSchema, outputSchema and annotations. Canonical JSON (for example RFC 8785, JSON Canonicalization Scheme) keeps key order and whitespace from changing the hash.
- Store a server-level hash over the sorted set of tool hashes too, so an added or removed tool is caught, not only an edited one.
- Re-check on every tools/list response, at session start and whenever the server sends notifications/tools/list_changed. Don't assume a server without that notification never changes.
- Fail closed: if a tool's hash differs, do not expose that tool to the model until a person reviews the diff and approves the new version. A new tool starts unapproved.
- Show the diff, not just "changed": the old and new description and schema side by side, with invisible or zero-width characters made visible.
- Pin local servers: an exact package version (no @latest or unpinned npx/uvx), a lockfile, or a container image by digest. An update is then a decision you make, followed by a re-approval.
- Log every approval and every detected change with the server, tool, old and new hash and time, so you can tell when a definition changed and which sessions saw it.
Why hashing the definition works
- The model reads the full tool description and schema, including text the user interface may truncate or hide, so that text is what must not change unseen.
- Tool annotations such as readOnlyHint or destructiveHint are hints from the server, not guarantees; include them in the hash, but don't trust them as a security control.
- Hashing does not tell you a definition is safe. It tells you it is the same one you reviewed, which is what approval needs to mean.
What it does not catch
- A server can keep its definitions identical and change what the tool does on the server side, or return injected text in tool results. Treat tool results as untrusted data and keep confirmations on for actions that write, send, pay or delete.
- A definition that was malicious when you first approved it hashes cleanly forever, so read the definitions at approval, not only their hashes.
Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Has this MCP server's tool list changed since it was recorded, and what exactly changed?”
{
"tool": "precall_check",
"arguments": {
"url": "<the server's https URL>",
"tool": "<optional tool name>"
}
}- check_tool_integrity re-probes a server registered on Rightshold and compares the tool definitions it serves now with the recorded fingerprint: unchanged, changed (with a plain diff of tools added, removed, description changed or schema changed) or unreachable, which is never reported as unchanged.
- precall_check also scans the definitions for invisible text and warns when another registered server offers the same tool name with a different definition (shadowing).
- The tool-definition fingerprint construction is published at /security/spec, free to implement in your own client.
Rightshold compares tool definitions with the fingerprints it has on record and scans for invisible text. An unchanged answer means the definitions match the record, not that a server is safe.
Sources
- Invariant Labs: MCP Security Notification: Tool Poisoning Attacks (rug pulls, April 2025)
- MCP specification: Tools (list changed notification, annotations)
- MCP specification: Security Best Practices
- RFC 8785: JSON Canonicalization Scheme
- OWASP MCP Security Cheat Sheet
Related
- How to vet an MCP server before installing it
- How to stop Log-To-Leak style prompt injection through MCP tools
- MCP server health receipts
- Tool-definition fingerprint spec
Not legal advice. Updated 2026-10-29. JSON · Markdown · All answers
Get a free API key in one call
No card and no email needed. 100 free credits; the license and policy checks stay free without a key.
curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_... # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
-H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'
