Securing an MCP server means deciding what its tools may do before an agent calls them, and verifying what happened after. Input filtering, prompt hardening and detection of malicious instructions address part of the problem. Those can detect and prevent specific attacks. Pair them with an authorization check between the model and the tool that evaluates whether the request is permitted, and with isolation around the server process.
Below are the questions worth answering, in order.
What are you actually securing?
You are securing four surfaces, not one. The first is the set of tools the server exposes, each a callable capability. The second is the credentials behind those tools, because a tool acts as whatever token the server holds, not as the model. The third is network reach: what the server process can touch, outbound and laterally. The fourth is the trust you place in tool descriptions and results, which flow back into the model's context and can carry instructions with them.
We map all four before we touch anything else. If that list looks familiar, it is the same map we draw in what an MCP server actually exposes. Securing the server is what you do once you can see it clearly.
Why isn't authentication enough?
Authentication answers who connected. It does not answer what the tool may then do. An OAuth flow can prove the caller is your agent and still leave that agent holding a token with write access to every repository in the org. The connection is authenticated. The capability is unbounded. Those are two different problems, and people keep solving the first and shipping the second.
The fix is least privilege per tool. Each tool gets its own narrow token, scoped to the smallest action it needs, with a short lifetime. A tool that reads issues does not carry a credential that can also close them. That way, even a fully authenticated agent can only do what the specific tool it called was scoped to do.
Containing prompt injection
Use action controls alongside content defenses. The real defect is not that a malicious instruction exists somewhere in the context. It is that untrusted input can reach a privileged action without anything in between deciding whether that action is allowed. Removing a disallowed execution path limits what an injected instruction can cause. Allowed tools and the model’s output can still carry risk.
Tool results are untrusted input. A deterministic allowlist rejects calls outside its scope; inspection and isolation address risks that remain within allowed calls.
So the control is an allowlist that runs before the call: this environment may invoke these tools, with these parameters, against these resources, and nothing else. It does not read the model's intent or try to guess whether an instruction was planted. It checks the requested call against a policy and permits or denies. We make the full argument in prompt injection is an authorization problem.
What 2026-07-28 changes
The identity layer under MCP was already concrete before the latest revision. The 2025-06-18 revision classified MCP servers as OAuth resource servers and required clients to implement RFC 8707 resource indicators, so servers can reject tokens not intended for them when audience validation is correctly enforced. Before that, a token minted for a low value server could be presented to a high value one that trusted the same issuer. The 2025-11-25 revision added OpenID Connect discovery, incremental scope consent through WWW-Authenticate, Client ID Metadata Documents as the recommended way to register a client, alignment with RFC 9728 for protected resource metadata and experimental tasks.
The 2026-07-28 revision, now the current specification, changes the shape of the protocol. It removes protocol level sessions and the initialize handshake, so the core is stateless and every request carries its own protocol version and capabilities. A server that needs state across calls mints an explicit handle and receives it back as an ordinary tool argument, which is one more parameter your policy has to check. On the identity side, authorization servers should include the iss parameter per RFC 9207 and clients must validate it before redeeming an authorization code, which closes the mix up attack where one authorization server collects a code issued by another. None of this replaces per tool authorization. It makes the identity layer underneath it trustworthy, which is a precondition, not a substitute.
Update, September 3, 2026: an earlier version of this section dated the resource server classification to a "2026-11-25 revision" and described 2026-07-28 as a release candidate. The classification and RFC 8707 date from 2025-06-18, and 2026-07-28 is now the final specification. The section was rewritten against the published changelogs.
What do you keep after deployment?
You keep evidence of every call. Scoping tools and constraining credentials decides what can happen. Evidence tells you what did happen, which helps reviewers establish which policy was applied and what the destination observed. For each call you record the tool, the parameters, a non-secret credential reference, the result and whether it matched the allowlist. Then you can check reality against intent instead of assuming they agreed. We go deeper on this in evidence for agent work.
The checklist
Concrete steps, in the order we apply them:
- Scope the tools. Each environment gets only the specific tools it needs, allowlisted, not every tool the server exposes.
- Scope the credentials. One narrow token per tool, smallest action, short lifetime, never reflected back into a result the model can read.
- Constrain the network. Declare where each tool may egress and which internal hosts it may reach. Deny the rest.
- Validate inputs against policy. Check the requested call and its parameters against the allowlist before it runs.
- Log per call. Record the tool, necessary arguments, a non-secret credential reference, the authorization decision and the observed result for each invocation. Redact secrets and sensitive content.
- Verify against policy. Compare what was called with what was permitted, and flag anything that drifted.
What this means for defenders
An MCP server is where models meet real systems, so it is where a capability decision earns the most. Authenticate the connection, then decide per tool what the connection may do, treat every result as untrusted and keep evidence you can verify. This reduces exposure, but a harmful action may still fit an overly broad policy. Test permitted operations, input handling and routes around the enforcement point as well.
For calls routed through a configured Oktsec enforcement point, tool policies constrain supported requests and decisions are recorded. Configure the corresponding egress path separately; a gateway does not automatically restrict every network connection a backend process can make.
For a scoped review of your implementation, see MCP penetration testing with Oktsec Assessment: tool authorization, tenant isolation, connected access and reproducible remediation evidence.