Guide·Model Context Protocol

What an MCP server actually exposes.

An MCP server feels like a tidy adapter. In an audit it reads as an authenticated gateway into your systems. Here is the map we draw before reviewing one.

The short version

  • An MCP server is not just a tool list; it is a credentialed bridge between a model and real systems.
  • The real attack surface is four things: tools, the credentials behind them, network reach, and the trust placed in tool descriptions.
  • Tool descriptions and results are untrusted input: they can carry injection straight into the model.
  • Audit each tool as a capability, scope its credentials, and put a deterministic policy between the model and the call.

The Model Context Protocol made agent tooling composable, and that is exactly why it concentrates risk. One MCP server can hand a model a dozen tools, each backed by a credential, each able to reach a system that matters. When we audit one, the first job is to stop seeing "an integration" and start seeing what it actually grants.

It comes down to four surfaces. Map these and you have the real picture; skip them and you are trusting a README.

1. The tool surface

Every tool an MCP server registers is a callable capability. The interesting question is never "what is this tool for?" but "what is the worst single call?" A tool named search_docs that accepts an arbitrary path can read files. A run_query tool with a writable connection can mutate data. A create_issue tool can be turned into an outbound notification channel.

We enumerate every tool, every parameter, and the maximal effect of one call, independent of how the model is "supposed" to use it. Agents do not stay inside intended use, and neither do attackers steering them.

2. The credentials behind the tools

Tools do not act as the model. They act as whatever token the server holds. This is where scope quietly becomes everything. An MCP server wired to a personal access token with broad repo scope does not give the agent "GitHub access" - it gives it that token's access, to every repo, indefinitely.

The recurring finding: credentials provisioned for developer convenience, not agent least-privilege. One broad token shared across every tool, where each tool needed a sliver of it.

For each credential we ask: what scope does it carry, what is its lifetime, can it be narrowed per tool, and is it ever exposed back to the model in an error message or result payload? The last one matters more than teams expect.

3. Network reach

A tool that can fetch a URL is an egress path. A tool that can reach an internal hostname is a pivot. MCP servers frequently run with whatever network the host process has, which in a CI runner or a dev container can be a lot. We map what the server can reach, outbound to the internet and laterally to internal services, because that defines where data can go and where an injected instruction can send it.

4. The trust placed in tool descriptions and results

This is the subtle one, and the one most reviews miss. Tool descriptions, parameter hints and tool results all flow back into the model's context. That means a compromised or malicious MCP server can inject instructions through a tool description, and a benign server can relay an injection that lives in the data it returns: a web page, an issue body, a row in a table.

Tool results are untrusted input. Treat every byte that returns from a tool the way you would treat a request body from the open internet.

If you accept that framing, the prompt-injection problem and the MCP problem are the same problem wearing different clothes: untrusted input arriving at a privileged action. Which points to the same fix.

What to enforce

You cannot audit your way to safety once and be done; MCP servers and their tools change. So the controls have to live at the boundary, deterministically:

  1. Allow-list tools per environment. An agent environment gets the specific tools it needs, not every tool the server happens to expose.
  2. Scope credentials to the tool. Narrow tokens, short lifetimes, and never reflect a secret back into a result the model can read.
  3. Constrain network reach. Declare where each tool may egress and which internal hosts it may touch.
  4. Verify after the fact. Record which tools were called, with what, and compare against the policy that was supposed to be in force.
mcp-host · tool inventoryscoped
1read_repo    token: repo:read · ttl 1h ok
2run_tests   net: none          ok
3fetch_url   egress: allow.list only scoped
4run_query   conn: read-write → deny
5evidence → reported for review
The same MCP server, seen as capabilities and credentials instead of a tool list.

The takeaway

An MCP server is one of the highest-leverage things to get right, because it sits exactly where models meet systems. Audit it as a credentialed gateway, scope every tool to least privilege, treat all results as untrusted, and keep verifiable evidence of what was called. Do that and MCP becomes what it should be: a controlled surface, not a quiet bypass.


Oktsec governs MCP hosts as first-class agent environments: scoped tools, signed policy, verified evidence. See supported environments →