MCP security best practices cover every link between an agent and its tools: the servers it connects to, the credentials and scopes those servers hold, and the tool descriptions the model reads. The Model Context Protocol (MCP) specification is plain about who does that work. It says the protocol "cannot enforce these security principles at the protocol level" and leaves consent, authorization and access controls to implementers [1]. This MCP security checklist collects what the specification, the project's own security guides, OWASP and the published attacks ask for, with a source for each item.
MCP security best practices, in one checklist
The checklist has three main groups. Servers covers what runs and where it comes from. Scopes and credentials covers what each server may reach. Pinned tool descriptions covers the text the model reads before it calls anything. Tool results, approvals and logs close the loop. The specification says tools "represent arbitrary code execution" and that descriptions of tool behavior, such as annotations, "should be considered untrusted, unless obtained from a trusted server" [1].
For depth on tenant isolation, audience-bound credentials, allow-lists and audit logs, see MCP access control: scoped credentials, allow-lists and audit logs.
Servers
MCP server security best practices start with knowing what is connected.
- Keep an inventory and an allow-list. Remove servers no one uses, know where each one came from and pin its version [4]. The Coalition for Secure AI (CoSAI) asks for an allow-list of approved servers with documented reviews and an inventory of each server's version, owner and purpose [20].
- Treat a registry listing as identity. An MCP Registry namespace shows which GitHub account or domain published a server [2]. The registry tells consumers to "assume minimal-to-no moderation", and it does not remove servers with security vulnerabilities [3].
- Check the exact name. OWASP calls typosquatting, such as
mcp-server-filesytemformcp-server-filesystem, a common attack vector [8]. - Pin versions, and images by digest. A launcher such as
npxpins only the top-level package, while a container image pinned by digest freezes the whole dependency tree [4]. The npm package postmark-mcp "turned malicious in v1.0.16" and copied email to an attacker through BCC [30]. - Run local servers isolated. A local server inherits the user's environment variables and can read anything the account can read, and "The stdio transport is not a sandbox" [4]. Clients that install servers in one click must show the exact command first, and should run it sandboxed with minimal privileges [6]. Deny network access where none is needed [4].
- Lock down remote servers. Validate the
Originheader on every connection, bind local HTTP servers to 127.0.0.1 and authenticate every connection [17]. In July 2025, Knostic found 1,862 MCP servers exposed to the internet, and all 119 it checked by hand listed their tools without authentication [33]. - Validate authorization URLs. Crafted input from an authorization endpoint gave mcp-remote an OS command injection flaw, CVE-2025-6514, scored 9.6 [27]. Clients must reject any scheme other than
httpandhttps, and clients deployed to a server must guard OAuth metadata fetches against server-side request forgery [6].
Scopes and credentials
Revision 2026-07-28 of the specification bases authorization on OAuth 2.1 and makes it optional [5]. The checks:
- Audience-bound tokens. Clients name the server with an OAuth resource indicator. Servers accept only tokens "issued specifically for them" and never pass a client's token on to another API [5, 6].
- Per-client consent in proxies. A proxy that uses one static client ID with a third-party authorization server must get the user's consent for each client, the project's answer to the confused deputy problem [6].
- Small scopes, raised on demand. Start with a minimal scope set and elevate through a challenge when a privileged tool is first used [6]. Publish a short
scopes_supportedlist, because a client whose challenge names no scope falls back to requesting every listed scope [6]. Wildcard scopes such as*,allandfull-accessare on the project's list of common mistakes [6]. - One credential per server. OWASP asks for scoped credentials per server, short-lived tokens over long-lived personal access tokens, and no OAuth tokens in plaintext config files [8]. In an October 2025 survey of 5,205 open-source server repositories, 53% relied on static API keys or personal access tokens and 8.5% used OAuth [11].
- Only the tools the task needs. A server may return only the tools a caller's scopes permit [16]. GitHub's MCP server, for example, enables chosen toolsets and has a read-only mode [35].
- No secrets through the model. Servers must not use form-mode elicitation to ask for passwords, API keys, tokens or payment credentials, and use URL mode so those never pass through the model's context [18].
- Authorization inside the server. Treating the scopes on a token as enough, without server-side authorization logic, is on the same list of mistakes [6]. In June 2025, a work-management software vendor said a logic flaw in its MCP server had exposed customer data to other organizations, affecting roughly 1,000 customers [31].
Pinned tool descriptions
"Tool names and descriptions are instructions your model reads," the project's local server guide says [4]. Three MCP security risks use them. In tool poisoning, a server hides instructions in a description that users do not see and the model does [7]. Trail of Bits calls it line jumping, because the attack works when the client lists the tools, before any tool is called [24]. In shadowing, one server's description changes how the agent uses another server's tools [4, 7]. In a rug pull, a server changes a definition after the user approved it [7].
The protocol does not require clients to pin definitions, and the project calls pinning "a property worth choosing a client for" [4]. The checks:
- Read the whole definition. OWASP says to "Treat the entire tool schema as a potential injection surface", input schemas and annotations included [8].
- Hash it at approval. Pin each reviewed definition with a cryptographic hash of the complete definition, because a flipped
readOnlyHintcan change approval behavior with no visible change to the description [8]. - Compare on every list, and ask again on change. Servers that declare
listChangedshould announce changes [16], and a server can also change definitions quietly [4]. OWASP says to "Re-prompt for consent when tool definitions change" [8]. - Treat annotations as hints. Clients "MUST consider tool annotations to be untrusted unless they come from trusted servers" [16]. The project's post on annotations says a server can claim to be read-only "and delete your files anyway" [15].
- Prefix tool names by server. Clients that combine servers should prefix names such as two
searchtools with a server identifier, and the specification says the name a server declares should not be relied on for this [16]. - Keep the roster small. Every configured server shares the model's context with the others [4].
Measured rates show why. In MCPTox, poisoned descriptions on 45 live servers succeeded at an average of 36.5% across 20 agent settings, and no setting refused more than 3% of the attacks [9]. A 2025 study found tool poisoning in 5.5% of 1,899 open-source servers [10]. OWASP adds that a hash detects "metadata changes, not changes to server code or behavior behind an unchanged definition" [8].
Tool results, sampling and approvals
- Treat every tool result as untrusted, including results from approved servers, and validate the next tool call in application code, independently of the model [8]. In May 2025, Invariant Labs showed a malicious GitHub issue steering an agent, through an MCP server, into leaking data from private repositories [23].
- Keep a person able to deny calls. The specification says "there SHOULD always be a human in the loop with the ability to deny tool invocations" [16]. Show full tool inputs, and never auto-approve tool calls, especially in multi-server setups [8, 16].
- Retire sampling. Revision 2026-07-28 deprecates Sampling, through which a server asks the client for a model completion, and new implementations should not add it [12]. Unit 42's proofs of concept used it to drain compute quotas, hijack conversations and covertly write a file [13]. Its defenses include approval for tool execution and rate limits on sampling [13].
Instructions planted in what an agent reads are the subject of Prompt injection: how it works and how to test an agent, and What to test before an agent buys on your behalf covers the same risk in seller listings.
Logs and testing
- Log every call with its parameters, user and time, with secrets redacted [8]. Log each scope elevation with a correlation ID [6].
- Keep a kill switch that can disable a tool or connection at once [19].
- Test servers before an agent connects. MCP Security Bench measured an average attack success rate of 40.35% across 12 attack types against ten agents [34].
Rillor's agentic security work tests the MCP servers an agent connects to for tool poisoning, descriptions changed after approval, instructions in tool results and access beyond what the task needs. It tests only systems the client owns or is authorized to test, within a written scope.
Read the full report
The full report sets out each item's source and its strength in the specification, the attacks and vulnerability records behind the checklist, the measured rates from benchmarks and scans, and all 35 sources.

