An essential primer for building enterprise-ready MCP servers
The Model Context Protocol (MCP) is not very opinionated about distributed systems so that enterprise platforms can plug-in seamlessly
Pre-Requisites
Multi-Region and Multi-Availability Zones: High availability is fundamental to enterprise operations. Server workloads (e.g. Kubernetes, Fargate) should be deployed in globally distributed clusters with isolated availability zones in each region. Smaller companies must at-least have staging and production separation.
Continuous Integration and Continuous Deployment (CI/CD): Automated pipelines should incorporate robust quality controls. A human-in-the-loop approval step should be required before promoting workloads to production.
Observability and Security standards: Enterprises should implement platform-level observability for access logs, error logs, and system metrics (CPU, memory, latency, error rates). Adopt open security standards such as end-to-end encryption (TLS), secure authentication and authorization (OAuth/OIDC/PKI)
Familiarity with Official MCP Specification: Read the official Model Context Protocol documentation here before proceeding.
The Magnificent 10: Enterprise Essentials for MCP Servers
MCP servers must always require the initialization request to be authenticated.
For resource servers secured by OAuth
Read Authorization header to retrieve access token
Use OAuth token introspection [RFC7662] to ensure token validity
Determine user identity associated with the token
Verify JWT signature when Public Key Infrastructure (PKI) is available and securely consume payload information
For proprietary resource servers
Transform custom authentication headers (X-CO-JWT) into standard Authorization header. This will allow official MCP SDK implementation to correctly propagate auth info to MCP handlers and other abstractions
Request user identity from Domain services to ensure legitimacy of the information present in the JWT
MCP servers must implement robust session management when user state is persisted using MCP sessions. Stateless MCP servers can ignore this guideline.
Leverage a Reverse Proxy (like nginx) to solve for session affinity and load balancing. Transport layer connections cannot be serialized into a distributed cache like Redis.
No idle transports: Reclaim persisted session memory when the client explicitly ends the session (via HTTP DELETE) or when detecting TCP reset events on keep-alive GET endpoint.
No unbounded connections: Set hard timeouts for persisted sessions to prevent memory leaks (e.g., reclaim memory after 10 minutes).
MCP servers must always require tool discovery (tools/list) requests to be access controlled using OAuth scopes or other role-based mechanisms.
For resource servers secured by OAuth
Read Authorization header to retrieve access token
Use OAuth token introspection [RFC7662] to ensure token validity and retrieve a list of authorized scopes. Servers must respond with a filtered list of MCPs (tools, prompts, etc). Official MCP SDKs have implemented functionality to toggle available tools any time after the initialization phase of the lifecycle.
Require developers to design functionality using granular OAuth scopes (read:user, write:message) instead of broad ones (root, admin, api)
Enable developers to statically configure tools and other listable abstractions with the minimum set of required OAuth scopes needed to execute the MCP functionality.
For proprietary resource servers
Transform custom authentication headers (X-CO-JWT) into standard Authorization header. This will allow official MCP SDK implementation to correctly propagate auth info to MCP handlers and other abstractions.
Request user identity and RBAC information from core domain services
Listing tools must be filtered when a user or role does not have at least view permission for the resource(s) being accessed by the MCP .
MCP servers must always adopt the principle of least privilege (PoLP).
By default the server must be initialized with all MCP tools disabled.
This is especially important when integrating third-party data sources since the server configuration and tool descriptions themselves are a major attack vector. Sophisticated attackers may inject malicious prompts in tool descriptions to instruct the LLM attached with MCP clients to perform malicious actions.
Pass-through proxies that compose MCP functionality from open-source third-party servers must implement schema versioning using strategies like “Trust-on-first-use” (ToFU) and explicitly validate schema changes that occur after the initial interaction.
Rapidly changing first-party tool descriptions may also have unintended consequences for in-product agents due to the inherent stochastic/probabilistic nature of LLM inferences.
Newly released MCP tools should not be automatically granted access. MCP clients usually cache the access token and automatically reconnect using the same access token when the server is intermittently disconnected. The client-server connection may be broken by processes like Kubernetes pod disruption and rolling updates, when a new service version is being released.
Optionally, implement an auth upgrade tool to explicitly request the desired level of access control from the client using MCP Elicitations.
MCP servers must always validate tool call input parameters.
Leverage JSON schema definition of the MCP Tool
The official MCP specification publishes its entire data model using JSON schema and there are libraries that can generate schemas from runtime types defined in various languages. [shameless plug]
Implement a common solution for all tool calls using a JSON schema validation library like Ajv instead of requiring tool developers to provide custom logic for trivial validation scenarios. Business specific validations must be performed in the handler implementation.
The required array of a MCP tool’s schema will guarantee that the MCP clients are providing all the input fields required for tool execution.
In addition to primitive type checking (e.g. string, number), JSON schema can also validate formats like date, time, URI, regex, file binary and more.
All supported features are documented in the official Draft-7 specification.
MCP servers must never allow tools to request credentials, access tokens, and other secrets as input parameters.
A MCP client may gather tool inputs automatically from the environment of the host (.git, .ssh) or it may ask the LLM to gather it from the end-user. Credentials, tokens, and secrets, provided by the user would be compromised if the chat history is persisted by the LLM application and it is especially vulnerable when this data crosses enterprise trust boundary (e.g. third-party AI Coding Assistants)
When the MCP client is running in a non-user context, the LLM may keep retrying with randomly generated values for the required input, and flood the server with bad inputs, possibly causing connection saturation and impacting availability for other clients
Only accept credentials from the Authorization header (or another custom header) to ensure that the MCP host has implemented proper access control mechanisms and is able to navigate the end-user securely through a login flow. Securing client-side MCP state will be covered in a subsequent article.
MCP servers must always implement output filtering and content moderation.
MCP tools may request sensitive information which should never be shared with a LLM (e.g. JIRA tickets containing email addresses or confidential Google docs). Untrusted data sources may inject malicious prompts to instruct the LLM to compromise information about host applications or even inject prompts that exfiltrate confidential data.
Implement a common solution for all MCP tools. Basic output filtering should redact or remove well known Personally Identifiable Information (PII) like email addresses, phone numbers, credit card information, SSN, etc.
Output filtering may also be useful for LLM cost governance. At the very least, MCP servers must implement reasonable business logic to truncate the output from tool calls and limit the amount of tokens sent to the LLM.
Advanced content moderation strategies like quarantining tool responses and sanitizing ANSI codes or other invisible text, may also prevent prompt injection and prompt poisoning attacks from untrusted data sources.
MCP servers must ensure that tool call handlers don’t cause memory leaks.
No runaway handlers: Implement a hard-time out for tool call requests so that services downstream experiencing bottlenecks don’t block requests from other clients and reduce availability.
No dangling handlers: Ensure all pending downstream requests are gracefully terminated. This can be achieved by propagating a cancellation signal to the MCP handler.
MCP servers must always obfuscate error messages in tool call responses.
Error messages are yet another attack vector for prompt poisoning or prompt injection, and similar to tool descriptions, rapidly changing non-malicious error messages may also have unintended consequences for the agentic product functionality.
Never respond with detailed error messages when it's going to be interpreted by a LLM. Simply log the error message in log storage by associating it with a transaction ID and respond with the transaction ID as the error code.
MCP servers must implement distributed request tracing and observability.
Pass through transaction ID to downstream REST APIs for tracing MCP requests through various micro-services and systems.
Integrate existing platforms for timers (latency) and logging (volume, errors) for all downstream REST API calls.
Conclusion: Trust Your Guardrails
Enterprises should not let security paranoia become an excuse for gatekeeping AI tools. Overly restrictive access slows innovation, frustrates developers, and prevents teams from realizing the full potential of MCP-based integrations. Your organization already has the guardrails—identity providers, RBAC systems, encryption standards, observability platforms—that are proven to protect critical systems. Have faith in those foundations.