Most writing about MCP server security stops at the token. Audience validation, scopes, per-user enforcement: necessary, and we have written about all of it. But a vendor security review is run by people who also own infrastructure questionnaires. After the authorization section they ask where the process runs, what it can reach, how it holds secrets, and what happens to their data in transit and at rest.
Those answers are architecture, not code. They are cheap to get right before the first deploy and expensive to retrofit. This is the deployment section of the design document we write in week one.
Draw the boundary before the diagram
An MCP server is a network service that holds high-value tokens and speaks to your product's data on behalf of named users. Treat it as its own trust zone, not as another handler inside the monolith.
In concrete terms, that usually means:
- A dedicated workload identity (IAM role, service account, managed identity) used by nothing else, so its permissions can be read in isolation.
- Its own network segment or subnet, with security-group rules written explicitly rather than inherited from the application tier.
- Its own deployment unit, so a rollback of the MCP server does not roll back the product.
The reason is blast radius. If the server is compromised through a tool bug or a poisoned input, the reviewer wants to know what the process could have reached. "It shares the application role" is a bad answer. "It has one role, and the role can call three APIs and read two secrets" is an answer that ends the thread.
Ingress: one path in
Remote MCP servers speak HTTP. Pin down the entry point:
- TLS terminated at a managed load balancer or edge, current cipher suites, HSTS on the host. No plaintext listener anywhere, including inside the VPC if you can avoid it.
- One hostname for the MCP endpoint, separate from the main API host. Separate hostnames give you separate WAF rules, separate rate limits, separate logs, and a resource identifier that is stable for audience validation and protected resource metadata.
- No direct public reachability for the compute. Traffic arrives through the load balancer; the task or pod has no public IP.
- Request limits at the edge: body size, header size, connection duration, concurrent streams. Streaming transports invite long-lived connections, so the timeouts must be chosen rather than defaulted.
If a customer requires private connectivity, it is worth knowing early whether your platform can offer it. PrivateLink-style private endpoints or a customer-dedicated ingress are real engineering, not a configuration flag, and the ask tends to arrive from the largest prospect at the worst moment.
Egress: the question nobody prepares for
Security reviewers now ask what the server calls outbound. They ask because prompt injection makes an MCP server a plausible exfiltration path: untrusted text arrives in a tool result, the model is steered into calling a tool that fetches a URL, and data leaves. Your tool design should make that hard. Your network should make it fail.
Default-deny egress with an explicit allowlist. Write down every destination the server legitimately needs: your own APIs, the identity provider's token and metadata endpoints, the log or SIEM sink, a model provider if the server uses sampling. Everything else is denied at the egress proxy or the firewall, and the denial is logged as a security event.
Two specifics that matter:
- No user-controlled URL fetching. If a tool must retrieve a URL, the allowlist belongs in the server, applied after resolution, with redirects re-checked and private address ranges refused. This is the SSRF checklist, and it applies to MCP tools exactly as it applies to webhooks.
- Egress logs are evidence. A denied outbound connection, attributed to a session and a tool call, is one of the most persuasive artifacts you can hand a reviewer. It shows a control that is on and observed, not documented and hoped for.
Secrets and keys
An MCP server handles more secret material than a typical service: its own client credentials at the identity provider, signing or verification keys, downstream API credentials, and short-lived user tokens in memory.
The rules we hold to:
- Secrets live in a managed secret store or KMS. Not in environment variables baked into an image, not in the IaC repository, not in the container's filesystem.
- Read at startup or on demand through the workload identity, cached in memory only, never written to disk.
- Rotation is a runbook that has been executed once before handover, not a paragraph. Client secrets, signing keys, and downstream credentials each get a rotation procedure with a tested rollback.
- Prefer mechanisms that avoid long-lived secrets entirely: workload identity federation to the IdP, private_key_jwt client authentication with a key in KMS, short-lived downstream credentials via token exchange.
- User access tokens are not persisted. If refresh tokens must be stored to support unattended or long-running work, they are encrypted with a key the application cannot export, scoped per user and per tenant, and deletable on offboarding.
The corollary is logging discipline. Tokens, authorization headers, and secret values are redacted at the logging boundary, and the redaction is tested. A secret in a log line is a reportable incident in most enterprise contracts.
Tenancy, data, and region
Three questions arrive together on almost every questionnaire.
Isolation. Is the MCP server shared across your customers, and if so what keeps one tenant's data out of another tenant's session? The honest answer for most B2B SaaS is that the server is multi-tenant and isolation is enforced in the data layer from token claims. That is acceptable, but only if you can show the enforcement point and the tests that prove it. If you offer a single-tenant deployment tier, say what is actually separated: compute, database, encryption key, or all three.
Persistence. The cleanest position is that the MCP server stores no customer content: it holds session state and audit events, and content passes through. If you do cache tool results, declare the store, the retention period, the encryption, and who can read it. Retention you cannot enforce with a lifecycle policy is not retention.
Region. If a customer is told their data stays in a region, every hop has to honour it: the compute, the session store, the log sink, and the model provider if the server calls one. Cross-region log aggregation is the usual leak, and it is usually discovered by the reviewer rather than the vendor.
Infrastructure as code, because the answers must stay true
Every control above is a claim about a running system. Claims drift. The defence is that the network segmentation, the egress allowlist, the IAM policy, the secret references, and the logging configuration are all declared in code, reviewed like code, and applied by a pipeline rather than a console.
That gives you three things a reviewer values: a diff history for security-relevant change, a way to answer "is staging configured like production" with evidence, and the ability to re-derive the architecture diagram from the source of truth instead of from memory. We deliver the server into the client's own repository and cloud account for the same reason. The people who will answer next year's questionnaire need to own the artifacts.
The short questionnaire
Before a build is done, we expect crisp answers to these. They are useful whether or not we are involved:
- What workload identity does the server run as, and what can that identity do?
- What is the exact ingress path, and is the compute publicly reachable?
- What outbound destinations are allowed, who approved the list, and where do denials get logged?
- Where does every secret live, and when was rotation last executed?
- What customer data, if any, is persisted by the server, for how long, and under which key?
- Which regions hold data, including logs?
- Which of the above is in code, and which is in a console?
If several of those answers are uncertain, the gap is architecture rather than authorization, and it is worth closing before a customer's reviewer finds it. That review is the first thing our security audit does, and the deployment described here, with IaC and a runbook in the client's own cloud account, is a standard part of a server build.