MCP remote servers have stopped behaving like “special AI infrastructure” and started behaving like normal stateless HTTP services, which forces a rethink of how you secure, route, rate-limit, and audit tool execution in production. If you’re still operating MCP as if it needs sticky sessions, bespoke ingress, or ad-hoc auth, you’re now paying reliability and security tax for no benefit.
What changed in the MCP roadmap direction
The MCP project’s updated roadmap explicitly frames the direction: with the 2026-07-28 release, “a remote MCP server is now no different from any other HTTP workload”. (blog.modelcontextprotocol.io) That statement is not marketing fluff; it’s a signal to move your operational model from “agent tool plugin” to “API product”.
Under the hood, the ecosystem has been converging on Streamable HTTP as the standard way to run remote MCP servers (with SSE treated as legacy for existing clients). (modelcontextprotocol.io) The practical consequence is that a remote MCP server should sit comfortably behind the same infrastructure you already trust for internal and external APIs: a load balancer, an API gateway, WAF, service mesh, standard logging and tracing, and your normal SRE playbooks.
If you’re deciding whether to invest in MCP now, the timing is straightforward: the protocol is maturing from “works in demos” to “operates at scale”, and the roadmap is pushing hard on HTTP-native deployment and enterprise-ready identity. (blog.modelcontextprotocol.io)
“Just HTTP” does not mean “just another endpoint”
MCP over Streamable HTTP is still JSON-RPC semantics at the application layer: you aren’t modelling tool calls as REST resources, you’re exchanging method calls. The transport spec is explicit that the server exposes a single HTTP endpoint path (for example /mcp) and clients send JSON-RPC messages via HTTP POST (and may receive either a single JSON response or an SSE stream depending on server behaviour). (modelcontextprotocol.io)
That difference matters operationally because:
- Your gateway policies often key off URL paths and HTTP verbs. With MCP you’ll have far fewer of those knobs.
- Observability needs to attach meaning to method names (e.g.
tools/call) and tool names, not toGET /thing/123. - Safety and security are less about HTTP shape and more about capability control: what tools exist, which inputs they accept, and who is allowed to invoke them.
The 2026-07-28 direction strengthens the idea that the server should not rely on implicit conversational “session state” to behave correctly behind proxies and load balancers. That is exactly what makes it operationally boring — in a good way. (blog.modelcontextprotocol.io)
Identity: where to terminate authn/z (and where not to)
If you only take one thing away: separate “who is calling the MCP server” from “what downstream systems the tool touches”. Conflating them is how you end up with either broken UX (endless logins) or broken security (a shared backend token everyone can use).
Pattern A: Gateway-terminated identity (recommended for enterprise)
Terminate end-user or service identity at the edge (API gateway / ingress), then forward a bounded identity context to the MCP server.
- Use your existing OAuth/OIDC (or mTLS for service-to-service) to authenticate.
- Convert the result into headers your MCP server understands (e.g. user ID, tenant, roles, risk level), and sign those headers if they cross trust boundaries.
- Authorise per tool (and often per tenant) inside the MCP server, not in the model.
This aligns with the security guidance that HTTP-based transports need proper client-server authentication/authorisation and transport-layer protections. (coalitionforsecureai.org)
Pattern B: MCP server terminates identity (use when you cannot control the client)
If you are publishing a remote server to broad client ecosystems, you may not control the gateway or the caller. In that case the MCP server must do the heavy lifting: validate tokens, enforce tenant isolation, and rate-limit aggressively.
This is where teams get caught: they ship a tool server as if it were a “public API” but without the discipline of a public API. If you cannot run it like a public API, do not publish it as a remote MCP server.
Pattern C: Dual auth (endpoint identity + downstream delegated auth)
Many real tools act as a broker to downstream systems (databases, SaaS APIs, internal microservices). You often need two distinct authorisation layers:
- Identity for calling the MCP endpoint.
- A separate delegated token to call the downstream API on the user’s behalf.
This “two-layer” reality is increasingly discussed in MCP security work because downstream auth is its own failure and abuse domain. (coalitionforsecureai.org)
Routing and gateways: treat “tool calls” as API operations
Once MCP is “just HTTP”, the obvious move is to put it behind your existing API gateway. The catch is that MCP compresses many operations into one endpoint, so you must re-create the missing routing and policy boundaries.
A practical approach:
- Route
/mcplike any other service. - Enforce payload size limits and timeouts at the gateway.
- Use request classification based on method and tool name.
The MCP project has been moving toward standardised HTTP headers and discovery mechanisms to make this sort of classification more gateway-friendly. The Go SDK release notes for 2026-07-28 explicitly mention “standardised HTTP headers” and a new server/discover RPC that replaces the old initialise handshake. (github.com)
If you can avoid parsing JSON in the gateway, do. Gateways are good at header-based policy; they are usually terrible places to run complex JSON policy logic.
Tool versioning and change control: don’t let “capability drift” ship to prod
The operational problem with tool servers is not that they go down. It’s that they change.
A tool surface is a capability contract: when you add a tool or broaden a schema, you may be granting the model new powers. When you remove or tighten a tool, you can break agents in subtle ways.
What the MCP ecosystem gives you today is more aligned with software package metadata than with “API versions”: remote server publishing uses server.json with a version, and remote servers are registered via remotes entries pointing at Streamable HTTP endpoints. (modelcontextprotocol.io)
Operationally, you should still impose API-grade discipline:
- Treat tool definitions as versioned artefacts.
- Require review for any tool addition or schema widening.
- Pin clients to a reviewed server version where you can.
A useful rule: new tools are a permission change; changing an input schema is a permission change; widening a scope is a permission change. Handle them like you would a new OAuth scope.
Rate limiting and abuse controls: the expensive part is usually downstream
The biggest cost and risk in MCP is rarely the HTTP handler; it’s what a tool can cause downstream:
- Bursty requests to internal search or analytics.
- Costly third-party API calls.
- Data exfiltration via “helpful” tools.
Put rate limits at three layers:
- Edge/global: protect the service and your budget.
- Tenant/user: stop one tenant melting shared infrastructure.
- Tool-specific: a “cheap read” tool and a “bulk export” tool should not share the same quotas.
Also enforce payload and recursion limits. The MCP security guidance explicitly calls out payload limits as a required control (to reduce large payload and recursive payload DoS). (coalitionforsecureai.org)
Audit and traceability: you need an answerable story
In an enterprise setting, you will be asked:
- Which user triggered this action?
- Which tool ran, with what inputs?
- What downstream calls were made?
- What data did we return?
- What failed, and what retried?
“Just HTTP” helps because your existing logs, traces, and correlation IDs work. But you must design the application-level audit record.
A minimum viable audit event per tool call:
- Timestamp, request ID, trace ID
- Caller identity (user, service, tenant)
- Tool name and tool version
- Normalised input summary (redacted)
- Downstream targets touched (service names, not secrets)
- Outcome: success, partial success, failure
- Error classification: timeout, authz denied, validation error, downstream 5xx
If you cannot store the inputs safely (PII, secrets), store an irreversible hash plus a redacted structural summary.
Failure modes to design for (and when the right answer is “don’t do this”)
Once MCP servers behave like stateless HTTP services, you inherit the same failure modes as any distributed system — plus a few agent-specific twists.
Timeouts and retries
Design for retries as if every request may be repeated.
- Make tool operations idempotent where possible.
- If they are not idempotent (e.g. “create invoice”), require an idempotency key, and persist the result keyed by (tenant, user, idempotency key).
- Assume clients and gateways may retry on network errors and 5xx.
Partial tool success
Many tool calls are composites: “fetch data, transform, write, notify”. If you can’t make the whole thing atomic, you must make partial outcomes explicit.
- Return structured partial results.
- Emit audit events per sub-operation.
- Prefer compensating actions over silent best-effort.
Streaming and long-lived responses
Streamable HTTP may use SSE for streaming messages. (modelcontextprotocol.io) That means you need to consider:
- Reverse proxy buffering (which can destroy streaming behaviour).
- Idle timeouts in gateways and CDNs.
- Backpressure: what happens if the client reads slowly.
If you cannot guarantee streaming correctness through your network path, do not rely on streaming for correctness. Use streaming for UX, not for state.
Cross-origin and local-server exposure
If you run servers locally (or you allow local endpoints), treat the transport security warnings seriously. The Streamable HTTP spec calls out validating the Origin header to prevent DNS rebinding, binding to localhost for local servers, and implementing proper authentication. (modelcontextprotocol.io)
If you are tempted to expose a local MCP server on 0.0.0.0 without strong auth because “it’s only for dev”, don’t. That habit survives into production.
A pragmatic deployment checklist
If you’re moving from “demo MCP server” to “operated MCP service”, this is the boring checklist that prevents the boring outages.
- Terminate TLS at a controlled edge and enforce modern TLS settings.
- Authenticate every request (user or service), and authorise per tool.
- Enforce payload size limits and request timeouts at gateway and app layers.
- Implement idempotency keys for non-idempotent tools.
- Put per-tenant and per-tool rate limits in place.
- Add structured audit events for every tool call (with redaction).
- Add distributed tracing with stable correlation IDs.
- Run canary releases for tool surface changes; treat new tools as permission changes.
- Document failure behaviour per tool: retryable vs non-retryable errors.
Where Codeversols fits (briefly, and honestly)
Teams usually don’t struggle with writing the MCP handler; they struggle with getting the operational details right while shipping product work. Codeversols builds and operates software across web, cloud and AI, and we can help you design the “boring” parts — identity boundaries, gateway policy, tool versioning, and auditability — so your MCP servers behave like the HTTP workloads your organisation already knows how to run.
Close
The 2026-07-28 direction is a gift to engineering leaders: remote MCP servers can now be treated as standard stateless HTTP services, so you can apply proven patterns instead of inventing new ones. The work doesn’t disappear; it moves to the right places: gateway policy, explicit authorisation, tool surface governance, and hardening against timeouts, retries, and partial success. If you treat tool execution as an API product with a capability contract, MCP becomes deployable infrastructure rather than experimental glue.



