A practical security review for an MCP server

Review an MCP server as a privileged protocol adapter: verify tool semantics, OAuth boundaries, token audience, downstream delegation, input handling, isolation, logging and consent.

Categories: Agent security, Architecture & engineering Series: Secure agents

An MCP server can turn a model-selected tool call into access to files, databases, SaaS APIs or local execution. That makes it a protocol endpoint and a privileged adapter. A security review must cover both roles: conformance at the MCP boundary and the authority the server exercises behind it.

The review objective is not “is MCP secure?” It is whether this server, for this client and workflow, can be trusted to expose these tools with these identities, data and downstream effects.

Freeze the protocol and deployment scope

Record the MCP specification version, SDK and dependencies; transport; local or remote topology; hosting account; clients; authorisation server; downstream APIs; tool inventory; resource and prompt features; and data classifications. Capture the effective configuration rather than a sample repository.

The specification changes over time, so requirements must be evaluated against the version deployed. The 2025-06-18 MCP specification describes security principles around consent, data privacy, tool safety and sampling, but also notes that protocol mechanisms cannot enforce every principle. Host, client, server and target systems each carry responsibilities.

Draw trust boundaries and data flows. OWASP threat-modeling guidance provides a practical structure: model the system, identify threats, decide mitigations, then validate them. For MCP, include discovery metadata, redirect flow, token issuance, session or task state and every upstream service.

Start with an exposure decision. A local single-user server, an internal remote service and a public multi-tenant endpoint do not share the same attacker model. Record who can reach the transport, who can register a client, which users can discover tools and whether the server accepts connections from arbitrary hosts. Security inherited from “internal” placement should be tested against actual routing, proxies and remote-access paths.

Review every tool as an authorisation surface

Build a tool inventory with purpose, input schema, output sensitivity, downstream operation, identity used, side effects, reversibility, approval and owner. Test the implementation, not only the description.

Prefer narrow tools whose names and schemas match business operations. create_invoice_draft permits stronger validation than run_query; read_repo_file is easier to constrain than execute_command. Reject unknown fields, enforce bounds and canonicalize resource identifiers before policy checks. Return the minimum data needed and avoid exposing stack traces, tokens or internal paths.

Treat descriptions and annotations as untrusted display data unless their provenance is controlled. A server should not gain more authority because its own description claims a tool is safe. The client should not treat annotation text as a policy override.

For each side effect, verify authorisation at the server or downstream resource. User consent in a client interface does not replace tenant, resource, field and transaction policy.

Verify the OAuth resource boundary

For HTTP deployments using MCP authorisation, inspect metadata discovery, redirect URI validation, PKCE, state handling, token storage, expiry and refresh. The MCP authorisation specification requires protected resource metadata, the resource parameter and validation that a token was issued for the MCP server. Test tokens with the wrong issuer, audience, signature, scope and expiry.

Audience validation is essential. A valid token intended for another service must fail. The server must not pass the client’s token through to an upstream API; it should act as an OAuth client to that API and obtain a separate, audience-correct token with narrower scope. This avoids a confused-deputy path and makes downstream authority explicit.

OAuth security best current practice adds current guidance on exact redirect matching, PKCE, sender-constrained tokens and refresh-token protections. RFC 9728 defines protected resource metadata. Check the library’s actual defaults and error handling; standards in a dependency list are not proof that the deployment enforces them.

Trace identity to every downstream effect

Determine whether the server acts as the user, a workload, a shared service or some combination. Preserve both delegator and actor where the downstream policy needs them. Avoid a server-wide credential that gives every connected client the same access.

For each tool, constrain audience, scopes, resource, tenant, lifetime and delegation. Keep secrets out of model-visible responses and logs. Rotate credentials and prove revocation propagates to sessions, queued tasks and connection pools.

Test horizontal and vertical access: another tenant’s resource, another user’s task, an administrative method, a hidden field and a value over the transaction limit. Also test whether a guessed or leaked task/session identifier exposes results. Authentication proves who called; authorisation must still decide what that caller can do.

Treat server content as potentially hostile

Resources and tool outputs may contain content controlled by third parties. A compromised or malicious server can return instructions that influence the host model. Label provenance, minimise raw content, and prevent one server’s output from silently authorising calls to another server.

Test tool-name and description manipulation, oversized or deeply nested payloads, malformed JSON-RPC messages, duplicate identifiers, unexpected content types, embedded URLs, binary content and error-response leakage. Fuzz parsing and schema boundaries. Rate-limit expensive methods and cap result sizes to prevent resource exhaustion.

If the server can request sampling or other client-side capabilities, verify that the host applies the expected user controls and that the server does not receive more prompt or model output than intended.

Review notifications, cancellation and progress channels too. A tool that continues after the client believes it was cancelled can create unauthorised late effects. Ensure request identifiers cannot collide across tenants, cancellation applies to the authenticated caller’s task, and notifications cannot be used to inject misleading approval or status information into another session. Where work becomes asynchronous, bind stored results and task lookup to the same authorisation context.

Inspect runtime and supply-chain controls

Run the server with a dedicated identity, minimal filesystem access, constrained network egress and no unnecessary host mounts. For local STDIO servers, remember that they execute on the user’s machine and may inherit environment variables; review installation, update and credential handling accordingly. For remote servers, review TLS, ingress, tenancy, secret storage and regional data path.

Pin and scan dependencies, verify release provenance where available, and establish a controlled update path. An apparently small MCP package can bridge directly to privileged local or cloud APIs, so review ownership, maintenance and incident channels as well as code.

Operationally, define rate limits, concurrency ceilings, timeouts and a safe degraded mode per tool. One expensive query or recursive agent interaction should not starve every client. Confirm that health endpoints and metrics do not disclose tool arguments or token metadata, and that operators can disable one tool without taking down read-only capabilities needed for diagnosis.

Demand evidence from adversarial tests

A practical acceptance run should include:

  • unauthorised tool discovery and invocation;
  • wrong-audience and expired tokens;
  • redirect and discovery manipulation;
  • cross-tenant resource identifiers;
  • token passthrough attempts;
  • prompt injection in resources and tool outputs;
  • argument smuggling and schema boundary cases;
  • server, authorisation service and downstream API outages;
  • cancellation and emergency revocation; and
  • log reconstruction of an allowed and denied effect.

Verify actual downstream state. Record client, server, specification and configuration versions with the evidence. Findings should distinguish protocol non-conformance, implementation vulnerability, unsafe tool design and deployment misconfiguration because the remediation owners differ.

Approve the server only for a defined tool set, identity model and workflow. A new tool or downstream API changes the security case even if the protocol version does not. MCP makes integrations discoverable and interoperable; a disciplined review makes their authority visible and testable.

Get the agent release checklist

Working through this decision?

Tell us about the agent workflow and the question behind it, and we will suggest the smallest useful next step.

A little more clarity

Questions worth asking.

Start with the questions that shape a better decision.

Does MCP certification or protocol compatibility establish that a server is secure?

No. Compatibility establishes interoperability properties. Security depends on the server's tools, authority, deployment, downstream APIs, data handling and operational controls.

Can an MCP server pass the client's token to an upstream API?

The reviewed MCP authorisation specification prohibits token passthrough. The server should obtain a separate downstream token intended for the upstream resource and with only required authority.

Are tool descriptions trusted instructions?

Hosts should treat tool descriptions and annotations as untrusted unless they come from a trusted server. Review provenance and avoid allowing description text to grant authority or override policy.