Connecting an AI agent to an MCP server hands that server a credential, a channel into the model's context and the ability to act on your systems, yet most teams decide whether to trust it by reading its README. A Model Context Protocol (MCP) server is code you did not write, often run by a party you have no contract with, that can change its tools after you approve it. This guide gives a repeatable, evidence-based method for assessing an MCP server before connection across four domains: identity, permissions, provenance and change control. It produces a score, a decision and conditions you can enforce. It is written for security architects, platform teams running MCP gateways and the reviewers who sign off new servers. The approval workflow itself is covered in the MCP Gateway and MCP Server Governance Guide; this page is the assessment that workflow needs.
Key takeaways
- Assess four domains, not one. Who the server is and how it authenticates, what it can do, where its code came from, and how changes reach you are separate questions with separate evidence.
- The specification sets a testable floor. For remote servers using MCP authorisation, the 2026-07-28 revision requires Protected Resource Metadata (RFC 9728), audience-bound tokens via the resource parameter (RFC 8707) and forbids token passthrough. Test these, do not take them on trust.
- Tool annotations are claims, not controls. The specification says clients must treat tool annotations as untrusted unless they come from trusted servers, so classify every tool yourself.
- Change control is where trust breaks. A server can pass review and then change: the postmark-mcp package worked honestly for 15 versions before one line began copying every email to an attacker.
- Trust is conditional and expires. Approve with enforced conditions (pinned version, tool allowlist, scopes, gateway routing) and a re-assessment trigger, never as a permanent yes.
Scope the assessment first
The same checks do not apply to every server. Decide three things before scoring, because they change which evidence you collect.
| Question | Options | What changes in the assessment |
|---|---|---|
| Transport | Local (stdio) or remote (Streamable HTTP) | Local servers run as the user with that user's files and environment, and the specification says stdio implementations should take credentials from the environment rather than use the OAuth flow. Remote servers are assessed against the authorisation specification. |
| Operator | First party (the service's own vendor), third-party host, self-hosted | A third-party host sees every credential and request that passes through it, so the host is assessed as well as the code |
| Reach | Read-only public data, internal read, write, destructive or administrative | Sets the evidence depth and the minimum score for approval |
For local servers on developer machines, see the Local MCP Server Security Guide; for servers you operate, the Remote MCP Server Hardening Guide.
Domain 1: identity and authentication
The question is whether the server proves who it is, and whether the tokens it receives can only be used by it. The checks below are drawn from the MCP authorisation specification revision 2026-07-28 (current when checked on 28 October 2026) and the 2025-11-25 revision it builds on. Authorisation is optional in MCP, so a remote server that offers none is a finding in itself.
| Check | How to test | Pass evidence | Weight |
|---|---|---|---|
| Protected Resource Metadata | Request without a token; expect HTTP 401 with a WWW-Authenticate header carrying resource_metadata, or a document at /.well-known/oauth-protected-resource | Document lists at least one entry in authorization_servers | High |
| Audience binding | Present a valid token issued for a different resource | Server rejects it with 401 | Critical |
| No token passthrough | Review architecture and ask the operator; for self-hosted code, inspect upstream calls | Server uses its own separate token for upstream APIs | Critical |
| Tokens only in headers | Inspect client configuration and documentation | Authorization: Bearer header only, never in the URL query string | High |
| PKCE and issuer checks | Check authorisation server metadata for code_challenge_methods_supported (S256) and authorization_response_iss_parameter_supported | S256 present; iss returned and validated (RFC 9207) | Medium |
| Client registration | Check which mechanism the authorisation server supports | Pre-registration or Client ID Metadata Documents; Dynamic Client Registration is deprecated in 2026-07-28 and retained for compatibility | Medium |
| Token lifetime | Inspect issued token expiry and refresh behaviour | Short-lived access tokens; refresh tokens rotated for public clients | Medium |
| Static key fallback | Read setup documentation | No requirement for a long-lived, broadly scoped API key when OAuth is available | High |
The Smithery.ai MCP hosting breach shows why the static key and query string checks carry weight: researchers on a compromised hosted server captured a client's API key that was passed in the query string. Any key you give a third-party hosted server is visible to that host. See the MCP Authorisation Specification Guide for the protocol detail and the Confused Deputy in AI Agents Guide for why passthrough is forbidden.
Domain 2: permissions and tool surface
An MCP server's real permission set is the union of the credential it holds and the tools it exposes. Assess both.
- Tool inventory: call tools/list and record every tool name, description and input schema. Classify each as read, write, destructive or administrative yourself. The specification warns that clients must treat annotations such as hints about read-only or destructive behaviour as untrusted unless the server is trusted, which at assessment time it is not yet.
- Description review: read tool descriptions as content that will enter the model's context. Instructions aimed at the model, references to other tools or servers, and requests for secrets are red flags for tool poisoning. See the MCP Security Best Practices Explained.
- Scope requests: compare scopes in the WWW-Authenticate challenge and scopes_supported with what the use case needs. The specification intends scopes_supported to be the minimal set for basic functionality, with more requested by step-up. A server that asks for broad write or offline_access scopes up front scores lower.
- Authorisation-aware tool lists: in 2026-07-28 the tool set may vary by the caller's authorisation but must not vary per connection. A server whose tool list changes unpredictably between identical calls fails this check.
- Name collisions: tool names are only unique within a server. If your agent connects to several servers, check for collisions such as two search tools, and require the client or gateway to prefix tool names by server.
- Server-side safeguards: the specification requires servers to validate inputs, enforce access control, rate limit and sanitise outputs. Ask for evidence, such as test reports or documented limits.
This maps directly to OWASP LLM06:2025 Excessive Agency, which recommends minimising extensions, their functionality and their permissions. See the AI Agent Tool and Plugin Security Guide.
Domain 3: provenance
Provenance answers who published the code and whether what you run is what they published.
| Evidence | What it proves | What it does not prove |
|---|---|---|
| MCP Registry entry under a verified namespace | The publisher controls the GitHub account (io.github.<user> via GitHub OAuth or OIDC) or the domain (DNS or HTTP challenge) | That the code is safe. The registry has been in preview since 8 September 2025. |
| Package published by the service's own vendor | The server comes from the organisation that runs the API it wraps | That a look-alike package is not also present; check the exact package name |
| npm provenance or equivalent Sigstore attestation | The package was built from a stated repository and workflow; verify with npm audit signatures (npm 9.5.0 or later) | Absence of malicious code; npm says provenance is a verifiable link to audit, not a safety guarantee |
| SBOM and dependency scan | Known vulnerable or malicious dependencies at the pinned version | Logic added by the author |
| Source review of the pinned version | What the code does with credentials, files and network | Future versions |
| Operator due diligence (hosted servers) | How the host stores customer credentials, isolates builds and handles incidents | Behaviour of individual servers on the platform |
The postmark-mcp malicious MCP server is the reference case: an unofficial package copied from the vendor's public code, published by an unrelated npm account, imitated a real email service. A provenance check that asked "is this the vendor's own package?" would have stopped it before version 1.0.16 added the hidden BCC. See the Sigstore Guide and the AI Supply Chain and AI-BOM Guide.
Domain 4: change control
Every other domain describes the server on the day you assessed it. Change control decides whether that assessment still holds tomorrow.
- Version pinning: local servers pinned to an exact version and integrity hash; no "latest" tags in client configuration. Remote servers recorded by canonical URI and the protocol revisions they support (the 2026-07-28 server/discover call returns supported versions and capabilities).
- Tool definition baseline: store a hash of the full tools/list response at approval. Servers that declare the listChanged capability notify subscribed clients when the list changes; treat that notification, or any hash mismatch, as a re-assessment trigger and block new or changed tools until reviewed.
- Upgrade review: diff each new version before rollout. In the postmark-mcp case, Snyk found the single added BCC line was the only notable difference between versions 1.0.15 and 1.0.18.
- Operator change notice: for hosted and vendor servers, require notice of new tools, scope changes and sub-processors in the contract or terms.
- Kill path: the ability to disconnect the server from all agents at the gateway and revoke its tokens in one action. See the MCP Incident Response Playbook.
Scoring and decisions
Score each domain from 0 to 3 using the evidence above: 0 means failed or no evidence on a critical check, 1 means significant gaps, 2 means acceptable with conditions, 3 means strong evidence. This rubric is our method, not a standard; record the evidence behind every score so a second reviewer can reproduce it.
| Server reach | Minimum per domain | Minimum total (of 12) | Decision if met | Mandatory conditions |
|---|---|---|---|---|
| Read-only public data | 1 | 6 | Approve | Pinned version or approved URI |
| Internal read | 2 | 8 | Approve with conditions | Per-user OAuth, read scopes only, gateway routing, tool allowlist |
| Write | 2 | 9 | Approve with conditions | As above plus human confirmation for write tools and full call logging |
| Destructive or administrative | 3 on identity and change control, 2 elsewhere | 10 | Approve for named agents only | As above plus first-party or self-hosted operator, short-lived tokens, quarterly re-assessment |
Any 0 on a critical check (audience binding, passthrough, provenance of the package) means reject or sandbox only, whatever the total. A server below the threshold can often be made acceptable by self-hosting a reviewed version, removing tools at the gateway or narrowing its credential, then re-scoring.
Small versus large organisations: a small team can run the identity and provenance checks by hand in under an hour per server and approve only vendor-published servers. A large organisation should automate the protocol tests and tools/list hashing in the MCP gateway, keep a private registry of approved servers and versions, and reserve manual review for write and administrative reach.
Running the assessment
- Intake: record the server, transport, operator, requested agents and users, and the use case. Reject requests without a named owner.
- Automated tests: run the identity checks and capture tools/list and its hash from an isolated test client with a test account.
- Manual review: classify tools, review descriptions and scopes, check provenance and, for write reach, review the source of the pinned version.
- Score and decide: apply the rubric, write the conditions and set the re-assessment date and triggers.
- Pilot: enable for one agent and a small user group through the gateway with full logging for two weeks. Compare actual tool calls with the approved tool list.
- Release: add to the private registry or allowlist with the pinned version and tool hash.
- Roll back: if the pilot or later monitoring shows unexpected behaviour, remove the server from the allowlist, revoke its tokens and rotate any credential it could read.
Detection and measurement
- Log at the gateway: server identity, tool name, arguments (redacted), caller agent and user, result size and errors for every tools/call.
- Alert on: tool list hash changes, calls to tools not on the approved list, new upstream destinations from self-hosted servers, and spikes in data returned.
- Metrics: percentage of connected servers with a current assessment; median days from a change trigger to re-assessment; percentage of servers on pinned versions; number of servers using static API keys; share of approved servers that are vendor-published or self-hosted.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev. 5 | SA-9 External System Services, SR-3 Supply Chain Controls and Processes, SR-4 Provenance, SR-6 Supplier Assessments and Reviews, CM-3 Configuration Change Control, CM-14 Signed Components, AC-6 Least Privilege, AC-4 Information Flow Enforcement | Supplier assessment, provenance, change control and least privilege for each server |
| NIST CSF 2.0 | GV.SC-07, ID.AM-02, PR.PS-01 | Third-party risk across the relationship, inventory, configuration management |
| OWASP Top 10 for LLM Applications 2025 | LLM06 Excessive Agency, LLM03 Supply Chain | Tool surface and third-party component risk |
| Zero trust | Per-request authorisation, audience-bound tokens, continuous verification | See the Zero Trust Identity Guide |
Common failure patterns
- Trusting a name: installing a package that looks like the vendor's official server, as postmark-mcp users did.
- One-time approval: approving a server once and accepting all later versions and tool changes automatically.
- Believing annotations: allowing tools marked read-only to run without confirmation, when the specification says those hints are untrusted.
- Ignoring the host: assessing the code but not the third-party platform that runs it and sees every credential passed to it, the lesson of the Smithery.ai case.
- Shared static keys: one broadly scoped API key used by every user of a server, so a compromise of the server is a compromise of the account.
- No kill path: servers configured separately on each developer machine, with no central way to disconnect them.
Practitioner checklist
- Classify every server by transport, operator and reach before assessing it.
- Test Protected Resource Metadata, audience rejection and the absence of token passthrough on remote servers.
- Inventory and classify every tool yourself; do not rely on annotations.
- Confirm the publisher through the vendor, a verified registry namespace or package provenance.
- Pin versions and store a hash of the approved tools/list response.
- Score the four domains, apply the reach thresholds and record evidence.
- Enforce conditions at the MCP gateway: tool allowlist, scopes, logging, confirmation for writes.
- Re-assess on version change, tool list change, scope change, operator incident and on a fixed date.
Standards and references
- Model Context Protocol: Authorization (revision 2026-07-28)
- Model Context Protocol: Tools (revision 2026-07-28)
- Model Context Protocol: Authorization (revision 2025-11-25)
- Model Context Protocol: Versioning
- Model Context Protocol: MCP Registry
- OWASP: Top 10 for LLM Applications 2025
- npm Docs: Generating provenance statements
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: MCP Gateway and MCP Server Governance Guide · MCP Registry and Server Publishing Security Guide · MCP Security Testing Guide · Zero Trust Identity Guide