Methodology
anlyon.dev reads what a server says its tools are (names, descriptions, input schemas and annotations) and runs fixed rules over that text. The same input always gives the same result. No model writes a score, and no finding is not a safety guarantee.
On this pageShowHide
The four groupsLink to this section
Every tool lands in exactly one group, the most consequential one its definition supports. The permissions block follows the group.
Deletes or cancelsdestructive
Removes, cancels or revokes something.
Claude Code:
denyCan't be undoneirreversible
Sends, pays, publishes or merges: once done, it cannot be taken back.
Claude Code:
askChanges thingswrite
Creates or changes something that can be changed back.
Claude Code:
askOnly readsread
Looks things up and changes nothing.
Claude Code:
allow
Tools come from the server itself, through an anonymous initialize and tools/list. anlyon.dev never signs in, never calls a tool, and never runs a third-party package.
How a tool is sorted into a groupLink to this section
- The verb in the tool name#class-name-verb
- The first known verb in the tool name sets its class: read words such as "get", "list" and "search" give read; change words such as "create", "update" and "add" give write; money words ("refund", "charge", "payout"), send words ("send", "notify", "reply") and final words ("merge", "publish", "transfer") give irreversible; removal words ("delete", "remove", "cancel", "archive", "revoke") give destructive. "post" followed by "message" or "email" is a send. In a name that is not a read, a money or send word right after a plain verb ("create_refund") and a second verb after "and" also count. A money word followed by "method", "link" or "setting" is configuration, not a payment.
- The first verb of the description#class-description-verb
- The first verb of the description's first sentence, after words like "Use this tool to", is read with the same word lists. It sets the class when the name has no known verb, and otherwise can only raise it.
- Wording that says a change is final#class-final-wording
- A description that says "cannot be undone", "irreversible" or "permanently delete" raises the class to at least irreversible.
- An amount and a currency in the input#class-money-input
- An input field named amount with a currency field beside it, at the top level or one object down (amount_money.amount), raises a tool that is not a read to irreversible, because it moves money. Fields such as unit_amount on a price or amount_off on a coupon do not count: they define a number for later.
- Recipients in the input#class-recipient-input
- An input field named "to" or "recipients", at the top level or one object down, raises a tool that is not a read to irreversible, because what it sends cannot be taken back.
- A statement or command in the input#class-code-input
- A top-level string input named "sql", "statement", "command", "cmd", "script", "code", "javascript" or "shell" raises a read to write, because what it runs can change anything it can reach.
- No known verb#class-default-write
- A tool whose name and description name no known verb is counted as a write. A read has to be named, because a read is allowed by default in the permissions block.
- Annotations can only raise a class#class-annotations
- MCP annotations are the server's own hints. destructiveHint: true raises the class to destructive, and readOnlyHint: false raises a read to a write. readOnlyHint: true and destructiveHint: false never lower a class: where they disagree with the tool's own words, the scan reports an annotation conflict instead.
What the findings look forLink to this section
- Text addressed to the model#model-directed-text
- Phrases that address the model rather than describe the tool: tags such as "<IMPORTANT>" or "<SYSTEM>", "ignore previous instructions", "do not tell the user" and similar instructions to keep something from the user, and "before using this tool, read". These are the patterns of published tool-poisoning examples. Checked in the titles, description and input schema strings.
- References to secrets on disk#sensitive-path
- Paths where keys and secrets usually live: ~/.ssh, id_rsa and other SSH key names, .env files, ~/.aws and AWS key names, credentials files and .git-credentials, MCP client configs (mcp.json, claude_desktop_config.json, ~/.cursor/), .netrc, .npmrc, .pypirc, .pgpass, .gnupg, Docker and Kubernetes configs, and /etc/passwd or /etc/shadow.
- The word "credentials"#credentials-mention
- The word "credential" or "credentials" outside a path. Many tools mention credentials for ordinary reasons, so this is information only.
- Mentions of other tools or servers#tool-shadowing
- A tool that names a tool this server does not list (for example "the send_email tool", "mcp_tool_send_email" or "mcp__other__send_email"), or uses wording such as "other servers", "all other tools" or "when this tool is available". A description that steers how the model uses another server's tools is how tool shadowing works. A name counts when it is written as an identifier (send_email, sendEmail) or in quotes, next to the word "tool". Mentions of the server's own tools are not reported.
- Base64 strings#base64-blob
- A run of 40 or more base64 characters that mixes upper case, lower case and digits, or ends in = padding, outside a URL. When it decodes to readable text, the text is shown, and the finding is high when that text contains model-directed phrases.
- Long descriptions#long-description
- A description over 2,000 characters. Long descriptions are not wrong in themselves, but they are where extra instructions are easiest to miss, so the length is shown.
- Annotations that disagree with the tool#annotation-conflict
- Where the server's annotations disagree with its own definition: readOnlyHint: true on a tool whose name, description or input give a higher class (a tool named "delete_*", for example), destructiveHint: false on a tool whose words say it removes something, destructiveHint: true on a tool named as a read, readOnlyHint: false on a tool named as a read, and readOnlyHint and destructiveHint both true.
- Install scripts that reach the network#install-script-network
- A "preinstall", "install" or "postinstall" script in the package.json that contains curl, wget, fetch or http. npm runs these scripts on install, before the server is started. Read from the published package manifest; the package is never run.
- Install scripts#install-script
- A "preinstall", "install" or "postinstall" script in the package.json that does not reach the network by these patterns. Information only: npm runs it on install.
- Duplicate tool names#duplicate-tool-name
- Two or more tools with the same name in one tools/list. A client keeps one of them, and which one depends on the client.
Hashes, permissions and what a scan isLink to this section
- The definition hash#definition-hash
- Each scan records the sha256 of the server's normalised tool definitions (name, title, description, input schema and annotations, with keys sorted and tools sorted by name). A different hash means a tool definition changed, and the change is shown as a diff.
- The Claude Code permissions block#claude-code-permissions
- A block for .claude/settings.json with one mcp__<server>__<tool> rule per tool: read tools in allow, write and irreversible tools in ask, destructive tools in deny. It is built from the same classes as the scan, as a starting point to review.
- What a scan is and is not#scope
- A scan reads tool definitions only: the tools/list a server publishes and its package manifest. It never runs the package, calls a tool or signs in. Every finding is evidence with a place and an excerpt, found by fixed rules with no model in the loop, and the same definitions always give the same result. No finding is not a safety guarantee: a check only sees the patterns it looks for, and a scan is a point in time.
How Agent Skills are checkedLink to this section
A skill is a folder with a SKILL.md and, often, scripts. Its files are read from GitHub as text and never run. A skill gets every label that applies; the first one below is the most consequential.
- Destructive commands
- Ships or asks for commands that delete or overwrite: rm -rf, force pushes, DROP TABLE and the like.
- Reaches the network
- Its scripts or instructions fetch from or send to the network.
- Runs commands
- Allows a shell or ships scripts the agent runs.
- Edits files
- Allows the agent to write or edit files.
- Instructions only
- Text only: no shell, no file writes, no scripts.
- Tools the skill allows#skill-allowed-tools
- The allowed-tools line in SKILL.md's frontmatter. Bash allows commands; Write, Edit, MultiEdit and NotebookEdit allow file changes; WebFetch and WebSearch reach the network. A narrowed form such as Bash(git status:*) still counts as a shell.
- Scripts it ships#skill-scripts
- Python, shell, JavaScript, TypeScript, Ruby and PowerShell files in the skill's folder are scripts the agent can run. Their text is read for network calls, destructive commands and secret paths. They are never run.
- Network calls#skill-network
- curl, wget, requests, urllib, httpx, fetch(, axios, Invoke-WebRequest, or an http(s) URL in a script. A URL the instructions tell the agent to open counts too.
- Destructive commands#skill-destructive
- rm -rf, shutil.rmtree, git push --force, git reset --hard, git clean -fd, DROP TABLE or DATABASE, TRUNCATE, kubectl delete, terraform destroy and similar, in a script or in an instruction.
- Code fetched and run#skill-remote-code
- A download piped straight into a shell, such as curl ... | sh, in a script or an instruction.
- Commands built at run time#skill-dynamic-exec
- A script that passes a command string to a shell (shell=True, os.system, child_process, execSync) or evaluates code (eval, exec). Common and often fine; it means what runs depends on input.
- Secrets on disk#skill-secret-paths
- ~/.ssh, id_rsa, .env files, ~/.aws/credentials, .netrc, .npmrc tokens, mentioned in a script or the instructions.
- Instructions to hide things or skip checks#skill-model-directed
- Phrases such as "do not tell the user", "ignore previous instructions", "without asking", "skip confirmation" or <IMPORTANT> tags in SKILL.md.
- Bundled binaries#skill-binaries
- Executables or libraries (.exe, .dll, .so, .dylib, .bin) in the skill's folder, which no text check can read.
Found a wrong group or a missed pattern? Tell us.