Est.

Hosting MCP Servers on Kubernetes in the Enterprise

Kubernetes handles the operational demands enterprise MCP fleets actually have.

Reporter · · 13 min read
Cover illustration for “Hosting MCP Servers on Kubernetes in the Enterprise”
MCP Architecture · September 2, 2026 · 13 min read · 2,900 words

MCP is turning into the wiring behind enterprise AI: one protocol, letting many agents talk to many data sources without a custom integration for every pair. A public registry tracking MCP servers went from roughly 1,200 entries in the first quarter of 2025 to more than 9,400 by mid-April 2026, a jump of over seven times in fourteen months. Most of those servers were never put behind anything resembling production infrastructure, and that gap is the whole story here. The adoption curve outran the plumbing, and nobody stopped to lay pipe.

That growth rate says something operational, not just something about popularity. When a protocol spreads that fast, teams spin up a server to solve today's problem and move to the next ticket, and nobody goes back to check whether the thing survives a restart.

Ad hoc MCP deployment fails in a few predictable ways. A server runs on a single box with no failover, so a crash takes down every agent that depends on it. Access controls, where they exist at all, aren't scoped to what the agent is supposed to do; a support bot's MCP server ends up able to touch the same data as a finance tool because nobody drew a line between them. There's often no record of what the agent touched or when, which turns any post-incident review into guesswork. And the servers pile up outside any registry, so six months in, nobody can say with confidence how many MCP servers the organization is running, let alone what each one can reach.

Kubernetes isn't a nice-to-have here; it's the only approach that actually fits the problem. Scheduling, isolation, role-based access control, and built-in observability map onto exactly what enterprise MCP needs to run safely at scale. Bolting governance onto a fleet of ad hoc servers after the fact doesn't work, because by then the fleet has already outgrown whoever was supposed to be tracking it. What follows walks through how Kubernetes fixes that, piece by piece, so MCP infrastructure ends up accountable, not just wide.

Diagram: MCP Registry Growth: 1,200 to 9,400 Servers in Fourteen Months. Visualizes: Show the explosive growth of MCP server adoption versus the lack of production-grade infrastructure behind it.

What the shift to stateless Streamable HTTP transport actually unlocked

MCP's original transport, HTTP plus Server-Sent Events, tied session state to one specific server process. On Kubernetes, that's a real problem: a standard round-robin load balancer sends the first request to pod A and the second to pod B, and pod B has no idea what session you're talking about. The result is a flat "400 Session Not Found."

Teams worked around this with sticky session affinity, pinning a client to one pod for the life of its session. That fixes the error but breaks the thing Kubernetes is actually good at: spreading load evenly and scaling pods up and down based on demand. Affinity means uneven load, and uneven load means autoscaling decisions built on bad signals. Worse, a pod restart, which Kubernetes does routinely and for good reasons, silently wipes out whatever session state lived on that pod. The other common fix, a shared Redis store holding session state outside any single pod, works, but it adds a network hop to every request and one more system somebody has to babysit.

HTTP+SSE was deprecated as of the 2025-03-26 spec revision, and Streamable HTTP is now the standard, stateless by design. The MCP Transport Working Group laid out a roadmap in December 2025 aiming for full statelessness by the June 2026 spec release, and the 2026-07-28 specification finished that work, according to Google's engineering blog covering the update.

What changes in practice is worth sitting with. MCP servers can run as ordinary Kubernetes pods behind ordinary load balancers, no sticky sessions, no special routing rules. Horizontal scaling works the same way it does for any REST API: add pods, and the load balancer spreads requests across them. Serverless and edge platforms like Cloud Run or Cloudflare Workers become real options for MCP hosting, using the same codebase you'd run in a cluster, and Streamable HTTP also holds up under load, benchmarking around 10 milliseconds of latency.

There's a narrow exception, and it should stay narrow. Some use cases genuinely need stateful context chains, conversations that build on prior turns in a way that's expensive to reconstruct from scratch. For those, the interim pattern pairs an in-process cache for data that doesn't change with Redis for data that does, plus explicit Kubernetes resource limits so a pod holding session state doesn't get evicted mid-conversation. That case should stay the exception, since treating it as the default architecture just reintroduces the sticky-session mess that statelessness was supposed to kill.

How Kubernetes maps onto the operational demands enterprise MCP actually has

Enterprise MCP isn't one server talking to one agent. It's a fleet: dozens or hundreds of servers, each with its own data access, its own consumers, its own blast radius if something breaks. That's a fleet management problem, and Kubernetes was built to manage fleets. Anyone treating MCP as a single-server deployment decision is solving the wrong problem from the start, and it shows up later as an outage nobody can explain.

The match runs close to one-to-one. Kubernetes scheduling and self-healing keep the desired number of MCP pods running and restart anything that dies, covering baseline resilience a single-instance deployment simply can't offer. Horizontal pod autoscaling matters because a single MCP server instance comfortably handles somewhere north of 50 concurrent sessions before performance drops off; once traffic nears that line, Kubernetes adds pods without anyone needing to step in manually.

Namespace isolation draws a logical wall between servers with different data access scopes. A finance agent's MCP server and an HR agent's MCP server shouldn't share a runtime boundary, and namespaces enforce that without standing up separate clusters for every team. Network policies push that same boundary down to the network layer, controlling which agents can even reach which servers, not just what they're allowed to do once they connect.

RBAC constrains what each MCP server's service account can do inside the cluster. That matters because it limits not just what an agent asks for, but what the server is capable of returning even if asked nicely. Secrets management keeps credentials and API keys out of container images and out of plaintext environment variables, storing them instead in Kubernetes Secrets or an external vault. Built-in observability hooks push metrics, logs, and traces into tools organizations already run, Prometheus, Grafana, OpenTelemetry, without custom instrumentation for every server that gets deployed.

Add it up and the governance case makes itself: every server in the cluster is named, scheduled, and monitored. That's the opposite of shadow deployment, where servers pile up with no identity anyone in the organization can account for. Standalone containers give you portability but skip all of this, and cloud functions scale well but hand you less control over isolation. Kubernetes is the only one of the three that gives you both, plus the audit trail enterprises actually need when someone asks what data an agent could reach last Tuesday.

Containerizing an MCP server and writing the manifests that matter

The basic idea is simple: write down the state you want, and Kubernetes keeps enforcing it. Manifests, or Helm values if you're templating them, describe the end state; the control loop handles the rest.

Getting the container image right matters before any manifest gets written. Start from a minimal base image; a smaller image means a smaller attack surface and faster pulls when pods scale up. Run the process as a non-root user in the Dockerfile, a basic step that blocks a wide class of container escape attempts before they start, and never bake credentials into the image itself; inject them at runtime through Secrets or a vault sidecar instead.

From there, a handful of manifest elements do the real work. The Deployment sets replica count, container image, the port the server listens on (typically HTTP, given Streamable HTTP transport), and liveness and readiness probes. The Service exposes that deployment inside the cluster, using ClusterIP if access stays internal, or a LoadBalancer or Ingress if outside clients need in. A ConfigMap holds non-sensitive configuration like transport mode or tool registration, while a Secret holds API keys and OAuth client credentials, never placed directly in the Deployment spec. Resource requests and limits stop a runaway tool call from starving the pods sitting next to it, and they're also what lets the scheduler pack workloads efficiently across nodes.

Helm is the packaging layer that makes this repeatable. The Red Hat containers project publishes a Helm chart for the Kubernetes MCP server on GHCR, with OAuth, telemetry, and resource limits all configurable through values.yaml. Because Helm charts version the entire configuration, promoting a change from staging to production becomes something you can audit and repeat, not something someone remembers to do by hand on a Friday afternoon. OpenShift compatibility comes built in for organizations already running that distribution.

Readiness probes deserve more thought than they usually get. An MCP server that hasn't finished registering its tools shouldn't take traffic yet, and a probe that skips that startup window is a common, quiet cause of intermittent 5xx errors in early deployments. It looks like a networking bug, when it's usually a probe that fired too early.

Kubernetes-native MCP tooling: kmcp, kagent, and agentgateway

Raw manifests describe a container, but they don't describe an MCP server, its lifecycle, its transport negotiation, or how MCP clients are supposed to find it in the first place. That gap is where purpose-built tooling comes in, and skipping it means rebuilding the same wiring by hand for every server you stand up.

kmcp treats MCP servers as first-class Kubernetes resources. It introduces an MCPServer custom resource, so a server is a named, typed object in the cluster rather than an anonymous pod that happens to run MCP code. It supports both stdio, for local development, and Streamable HTTP, for production, configured at deploy time, and it handles service discovery and port mapping on its own, cutting out manual wiring between clients and servers.

kagent takes a different angle: it makes the cluster itself something an agent can reason about. Launched in March 2025, it moved quickly into the CNCF and has grown to more than 800 community members and over 100 contributors. Instead of just being a place agents get deployed into, the cluster becomes part of the runtime the agent understands.

agentgateway sits at the layer between MCP clients and servers, functioning as an agent-native data plane that handles routing, authentication, and policy enforcement in one place rather than scattering that logic across every server separately.

The governance payoff is direct. An MCPServer custom resource is, by definition, a registry entry. Every server that exists in the cluster is known to the cluster, addressable, and subject to policy, the opposite of a server someone stood up on a spare VM and forgot to mention. Teams starting from scratch should look at kmcp for lifecycle management first; teams with an existing Kubernetes footprint can layer kagent on top of deployments that already work.

Scaling, multi-tenancy, and the deployment modes that fit different organizational shapes

Two deployment modes cover almost every situation, and only one of them belongs in production. Local, stdio-based deployment fits a single developer or admin working with one client on one machine, fine for prototyping, wrong for anything shared. In-cluster deployment over Streamable HTTP, load-balanced across multiple clients and tenants, is the only mode that makes sense once MCP moves past a demo. Anyone running stdio in production has already made their first mistake.

Inside the cluster, multi-tenancy comes down to how namespaces get drawn. Namespace-per-team keeps each business unit's MCP servers in their own namespace, with their own RBAC bindings and network policies, so a misconfigured server in one namespace can't spill into another. Namespace-per-sensitivity separates servers touching regulated data, PII, financial records, from servers running general productivity tools. Some organizations combine both: one shared infrastructure plane, but isolated data paths within it, which keeps cost down while still holding a real wall between what different servers can reach.

Autoscaling needs different signals than most workloads, and this is where teams get it wrong most often. CPU and memory usage are weak proxies for MCP load, because tool calls tend to be I/O-bound, waiting on a database or an external API, rather than compute-bound. Better signals are active connection count, request queue depth, or custom metrics fed through something like KEDA. Set thresholds on CPU alone and pods scale too late, after the queue's already backed up.

Access modes are worth configuring deliberately too. The Kubernetes MCP server supports read-only, non-destructive, and fully permissioned modes, letting operators scope what a server can actually do inside the cluster, not just who's allowed to reach it over the network. Before setting any HPA thresholds, run a load test that measures Time-to-First-Token and latency at the P50, P95, and P99 percentiles under sustained load. Baseline the real tool call latency, because a synthetic HTTP ping tells you almost nothing about how the server behaves once five tool calls are queued behind a slow database query.

Managed Kubernetes options from AWS, Google Cloud, and Azure

Managed Kubernetes trades operational overhead for dependency: less patching and upgrading to do yourself, more reliance on the provider's release schedule, pricing, and integration choices. Each of the three major clouds has moved on MCP specifically over the past year, though none of them replaces the work covered above; they just run it on someone else's control plane. Anyone picking a managed option expecting it to solve governance on its own is going to be disappointed six months in, once the fleet's grown past what the dashboard shows.

Amazon EKS and ECS announced fully managed MCP servers in preview in November 2025. The package includes automatic updates and patching, IAM-based access control, and audit logging through CloudTrail. It fits organizations already standardized on AWS and comfortable managing access through IAM policy.

Google's managed MCP servers, launched in December 2025 on GKE, expose BigQuery, Google Maps, GCE, and GKE itself as standardized MCP tools. Enterprise deployments run over remote Streamable HTTP, with stdio kept available for local development. One demonstrated use case: an agent detects a pod crash through GKE's tools, cross-references VM metrics from GCE, and kicks off remediation, cutting mean-time-to-resolution from hours down to minutes. This setup fits data-heavy workloads already built on BigQuery or GKE, and less so anyone starting from zero.

Microsoft positions Kubernetes-native MCP deployment through AKS and Container Apps, with a gateway layer handling session-aware routing and scaling. It's the natural pick for organizations already invested in AKS and the wider Microsoft ecosystem, and a strange one to adopt from scratch.

All three operationalize the same transport and scaling foundations covered earlier. None of them, on its own, solves identity, access policy, or governance across servers running on different platforms, and that work stays with whoever operates the deployment, regardless of which managed plane they picked. Pretending otherwise is how governance gaps open up down the road.

The security vulnerabilities that Kubernetes deployment must address, not just inherit

Diagram: CVE Severity and the MCP Attack Surface. Visualizes: Visualize the concrete, documented security incidents that make Kubernetes hardening non-optional for MCP.

MCP wasn't built with enterprise security as a first requirement. The original specification shipped without mandatory authentication, resting on an implicit assumption that servers were benign actors. That assumption hasn't held up, and the incident list below is the proof, not a hypothetical.

Start with exposed endpoints. A vulnerability class documented in June 2025 and nicknamed "NeighborJack" found hundreds of MCP servers bound to 0.0.0.0 by default, reachable by anything on the same network. Researchers identified 492 MCP servers open to abuse specifically because they lacked authentication or encryption, and that's not a sophisticated attack; it's a server left with the front door wide open.

CVE-2025-6514, rated 9.6 on the CVSS scale, was the first large-scale remote code execution attack against MCP clients. Attackers used it to dump credentials, modify source files, and plant backdoors, partly because clients accepted connections from servers they'd never verified. CVE-2025-49596, an RCE flaw in MCP Inspector, could be triggered just by visiting a malicious website, no extra access needed. It was patched in MCP Inspector 0.14.1 by adding session token authentication, and it's a reminder that developer tooling inside the MCP ecosystem carries its own attack surface, not just the servers running in production.

Tool poisoning is subtler and, longer term, probably the bigger risk. An empirical study analyzing thousands of open-source MCP servers found that roughly one in eighteen showed signs of it: altered tool descriptions, injected false responses, data flows quietly redirected somewhere they shouldn't go. Prompt injection sits at the top of the OWASP Top 10 for LLM Applications 2025, and that ranking means even more inside MCP environments, where one injected prompt can reach across every tool and data source the agent touches.

Kubernetes gives you the primitives to contain all of this: network policies, RBAC, namespace isolation. What it doesn't do is configure them for you. Someone still has to decide which agent gets which scope, and someone still has to notice when a server starts behaving differently than it used to. That's the governance layer products like MCPManager, built by Usercentrics, are meant to sit on top of: a way to keep every server in the cluster recorded as a named, scheduled, monitored resource with a clear access footprint, instead of letting the fleet grow the way most MCP deployments have grown so far, fast, and mostly unaccounted for.

Sources

  1. tmdevlab.com
Filed underMCP Architecture

More in MCP Architecture