17 min read

MCP for enterprise: protocol, security and boundaries

How to embed MCP in the corporate environment: the protocol primitives, the security model, schema bloat, call auditing and the choice between MCP, REST and Kafka.

Victor Buzin · Founder & Principal Engineer, AnetLab
16+ years in enterprise development: .NET, AI/LLM systems, RAG, MCP. Author of the material and the practices behind it.

1. The integration tax: why standardizing the context matters

A client from the financial sector came with a task that we closed in less than a month. Five to ten scattered connectors: to Jira, to the internal documentation library, to a legacy SQL base, to several accounting systems. Each one had its own authentication, its own parser and its own logic for packing the data into the model context window.

The result was an operational swamp. Every integration needed a custom Python script, a specific parsing logic to “pack” the data into the LLM context window, and a hand-rolled wrapper for the authentication. When the team decided to change the LLM provider, half of the integration code had to be rewritten, because the new model expected the tool signatures in a different format (a function call versus JSON-mode instructions, for example).

That is the “integration tax” — the hidden cost of building non-standard bridges for passing context to the AI. It is not just a development cost; it is a maintenance and security liability. Every custom script is a potential place where hardcoded credentials can hide, and one more point of failure when the schemas of the external APIs change.

The Model Context Protocol (MCP) appeared exactly to solve this problem. By standardizing the way the AI models (hosts) interact with the data and the tools (servers), it takes us from the “N x M” problem (where every model needs its own connector to every tool) to a “1 x N” model.

Thesis: MCP is a useful protocol for building AI-native tools; however, adopting it in a corporate environment requires clear decisions about the trust boundaries, the scope of the permissions, the auditability and what the protocol was never designed for.


2. What MCP solves: the primitives of AI interaction

MCP is an open standard that lets AI applications interact with external data and functionality through a universal bidirectional interface. It works primarily on JSON-RPC 2.0, providing a concise standardized message format that abstracts away the underlying transport.

In a corporate environment MCP solves three main problems through its key primitives:

A. Resources: the “nouns” of the context

Resources are read-only data sources that provide the information for grounding the answers of the LLM. Think of them as URIs that return structured or unstructured data.

  • Example: postgres://db-primary/schema/orders_table or confluence://page/12345.
  • Enterprise value: standardizing the context extraction. Instead of writing custom logic for every application, you define the structure of the URI. Then you can instruct the LLM: “look at the resource at this URI” to get the current data. This is especially useful for working with dynamic configs, logs or documentation without writing specific parsers.

B. Tools: the “verbs” of action

Tools are executable functions that the model can call. They have side effects: writing to a database, sending a message to Slack or triggering a CI/CD pipeline.

  • Example: create_jira_issue(title: string, priority: string).
  • Enterprise value: strict schema compliance. By using JSON Schema to define the tools, the model knows exactly which inputs are required. That reduces the number of “hallucinated parameters” and allows the validation to happen on the server side before the action touches the production systems. Unlike simple APIs, the MCP tools are discoverable: the model can request the list of the tools and their descriptions at runtime.

C. Prompts: the “instructions” of the workflow

Prompts are reusable templates that guide the behavior of the model. They serve as a communication layer that encapsulates the best practices for a specific task.

  • Example: Security-Audit-Template.
  • Enterprise value: consistency. You can guarantee that every developer asking for a “Code Review” gets the same high-quality system prompt, regardless of the interface or the model in use. This centralizes the prompt engineering, turning the prompts into versioned assets instead of hidden strings in the application code.

3. The anatomy of an enterprise MCP server

For industrial use it is important to understand what is inside an MCP server beyond the simple “hello world” examples. An enterprise MCP server includes:

  1. The transport layer handler:
    • Local: stdio (standard input/output) for local scripts.
    • Remote: Streamable HTTP over HTTPS — the standard network transport of MCP (in the 2025-06-18 specification it replaced the legacy HTTP+SSE).
  2. The capability registry: the list of the tools, the resources and the prompts that the server supports. This list is served to the client dynamically on connect. That allows a “hot swap” of the capabilities: you can add a new tool to the server without restarting the client application.
  3. The schema validator: a strict middleware that intercepts the tool calls. Before the code runs, the validator checks the JSON body of the request against the registered schema. If the model has “hallucinated” an extra field, the server rejects the request with a clear 400-level error, forcing the model to try again correctly.
  4. The backend connector: the logic that interacts directly with Jira, Salesforce or SQL. In a mature architecture this layer manages the connection pool, the authentication and the retry strategies (exponential backoff).
  5. The telemetry middleware: the hooks for logging and tracing. Every request has to generate an OpenTelemetry trace that links the “thought” of the LLM to the specific database query or API call.

4. Where MCP sits in the corporate architecture

A common mistake is to treat MCP as a replacement for the API management layer (APIM). That is not the case. MCP sits above your APIs, acting as a “semantic adapter” for the AI.

The three-layer model:

  1. The host application:
    • For users: Claude Desktop, Cursor, Zed.
    • For the enterprise: a custom internal AI Gateway built on LangGraph, Semantic Kernel or a proprietary agent framework.
  2. The MCP client: a library (Python, TypeScript, Go) that manages the connections to the servers, the protocol negotiation and provides the interface for the model.
  3. The MCP server: a stateless microservice. It works as an adapter, translating the AI-centric JSON-RPC calls into traditional backend requests.

Deployment strategies

  • Containerized microservice: running the MCP servers as small containers on Amazon ECS or Azure Container Apps. This lets you use granular IAM roles (for example, the “Jira-MCP-Server” role has access to Jira only).
  • Edge proxy: to work with sensitive local data, the MCP server can run on an edge node or in a virtual desktop (VDI), exposing the local resources to the protected host only.

5. The boundaries: where MCP does NOT fit

Pragmatism is the key to success. If you try to use MCP for everything, you end up with a slow and fragile system.

A. MCP is NOT designed for transferring large volumes of data. If you need to synchronize a million records from the database into a vector store, do not use an MCP Resource. The overhead of serializing into JSON-RPC, the round trip to the host and the potential call back into another service are extremely inefficient. Use ETL pipelines for moving the data and MCP for targeted context extraction.

B. MCP is NOT designed for long-running asynchronous tasks. In its current form MCP is optimized for a request-response model. If a tool call starts a 10-minute job, the connection will most likely time out.

  • The right approach: use an MCP tool to start the job, which returns a job_id. Provide a separate resource or tool that the model can call to poll the status or to fetch the final result.

C. MCP is NOT a “universal connector” for legacy interfaces. If your old system has no API and requires scraping or RPA, MCP will not be a magic solution. You still need the underlying service or API. MCP is the interface to that service, not a driver for the UI.

D. MCP does NOT fit real-time low-latency systems. If you are building AI to control a high-speed robot or to do high-frequency trading, the abstraction levels of MCP (JSON-RPC + model tokenization) add hundreds of milliseconds of latency. For hard real-time tasks use the direct SDKs.


6. The security model: beyond the local process

Security is the stage where most MCP adoption projects get stuck. The move from a local stdio process to a network server opens up a huge attack surface.

Transport layer security (TLS)

In a remote configuration all the traffic has to be encrypted.

  • TLS 1.3: mandatory. No exceptions for “internal only” traffic.
  • mTLS (Mutual TLS): the gold standard. It guarantees that the MCP server accepts connections only from a specific AI Gateway (host). That prevents the lateral movement of an attacker inside the network.

Authentication: OAuth 2.1 and PKCE

The Model Context Protocol specification recommends OAuth 2.1 with PKCE for authorization.

  • The flow: when a user opens the AI chat, the host redirects him to the corporate IdP (Okta/Azure AD). The user allows the AI to “read his tickets”. The host receives an access token, which it includes in every request to the MCP.
  • Audience validation: the MCP server has to check that the aud (audience) field in the token matches its own ID. That prevents an attacker from using a token from the “File Server MCP” to access the “Production DB MCP”.

The “Shadow MCP” risk

Just like Shadow IT was a problem in the 2010s, Shadow MCP is the risk of the 2020s. Developers can easily spin up local MCP servers bypassing the corporate proxies.

  • Defense: allow the AI host to connect only to a managed allowlist of MCP server URLs. Block the launch of unauthorized child processes on the workstations.

7. The identity dilemma: propagating the user context

The main architectural trap is the “service account trap”. Many teams configure the MCP server to connect to the database under a single high-privileged account (for example ai-bot-sa). When the AI uses that tool, it effectively gets “god mode” regardless of who the end user is.

The right path: identity propagation

For real security in the enterprise you have to propagate the identity of the user from the host to the MCP server and on to the backend resource.

  1. On-Behalf-Of (OBO) flow: use RFC 8693 (Token Exchange). The MCP server receives the user token and exchanges it for a token whose scope is limited to the target backend (Jira, for example).
  2. Row-Level Security (RLS): make sure the database or the API on the backend applies the access rights based on the user ID from the token. If “User A” is not allowed to see the payroll table, the MCP tool has to return an access error, even if the AI model thinks it can call it.

8. The schema bloat problem and the efficiency of the context

A subtle but serious problem of MCP is the schema bloat. Every tool and every resource added to the server increases the system prompt of the model. If you have 50 tools with detailed JSON schemas, they can easily eat up 5000+ tokens. This is not only a question of cost, but also a question of the quality of the reasoning: the models perform worse when they are offered too many options (the “Lost in the Middle” phenomenon).

Optimization strategies:

  1. Capability discovery: send the schemas only of the systems that are relevant to the role of the user. An HR employee does not need to see the schema of the tool for deploying Kubernetes clusters.
  2. Dynamic server connection: the host should activate the connection to a specific MCP server only if the user request triggers a certain intent (a request about tasks involves Jira-MCP, for example).
  3. Context cleanup: if a tool was used once and is not needed anymore, the host should remove its description from the subsequent turns of the conversation to save the budget.

9. Operational considerations: running MCP at scale

Running one server is easy, running fifty is hard. Operationalizing MCP requires a focus on observability.

Monitoring and logging

You need observability at the level of the “reasoning”. The ordinary logs show that a tool was called. You need to know why.

  • Trace ID propagation: it is necessary to use the headers to pass the Trace ID through the whole protocol.
  • Audit: store the “Observation” (the result of the tool call) together with the “Action” (the call itself). This is critical for debugging the situations where the AI makes a mistake in the logic.

Error handling and hallucinations

Models often hallucinate parameters — for example, trying to pass a field into a tool that is not in the schema.

  • Informative errors: the MCP server has to return a clear JSON-RPC error. “Invalid Parameter” is too little; the error has to be: “Invalid Parameter ‘date’: Expected YYYY-MM-DD, received MM-DD-YYYY”. That lets the model correct itself on the next step.

Everything that cannot be fixed automatically has to end up in the log as a separate event with a call identifier. Without that, the incident analysis turns into reading the logs by time.

Three things turned out to be unexpected in this migration — three things that the protocol documentation does not cover.

The schemas of the different connectors do not match in the types. Dates, currencies and identifiers arrive in different formats, and the model starts passing the date sometimes in ISO, sometimes in the local format. This is not fixed with a prompt, but with a shared normalization layer at the input of the MCP server: one type — one representation.

Part of the connectors turned out to be stateful connectors. Sessions and cursors cannot be kept in the process of the server if it restarts or runs in several replicas. The cursor had to be moved into a separate store — otherwise a repeated request lost the position and returned an incomplete result without an error.

The call audit had to be collected not in the servers, but in the gateway. When every connector writes its own log, the incident analysis turns into reading five different formats. A single log at the gateway level — with the call identifier, the user, the tool and the result — paid off faster than optimizing the connectors themselves.

And an honest limitation: about a third of the connectors could not be moved to MCP — they had no stable API, they required scraping or RPA. MCP does not cure that. It standardizes the interface to what is already programmatically accessible, but it does not turn the inaccessible into the accessible.


10. Development lifecycle: CI/CD and testing of MCP

Since the MCP servers are the “hands” of your AI, they require careful testing.

Unit testing the “semantic interface”

Testing an MCP server is not only checking the code, but also checking the schema.

  • Schema validation: use the tests to make sure the JSON schemas are valid and do not contain confusing descriptions that could throw the LLM off.
  • Prompt injection testing: run the sets of “jailbreak” requests against the MCP server in staging, to check the resilience of the input validation.

CI/CD for the tools

When you update an MCP server, you are effectively changing the “contract” with the AI model.

  • Semantic versioning: treat the MCP tools like public APIs. Do not remove parameters without a major version bump.
  • Integration tests with an LLM: in the CI/CD pipeline run a cheap model (Claude Haiku, for example) against the new version of the server, to make sure it discovers and uses the tools correctly.

11. The reference architecture: the Gateway pattern

At the enterprise level we use the Enterprise Context Gateway architecture. This pattern separates the identity of the user from the execution of the tools.

Refer to the Marp presentation below for a visualization of this process.

  1. The user interface: a chat or an IDE extension.
  2. The identity layer: manages the OIDC/OAuth sessions.
  3. The orchestrator (the host): manages the state of the conversation and decides which MCP server to poll.
  4. The Context Gateway (the proxy): a centralized API Gateway (Kong or Azure APIM, for example), which routes the requests to the internal MCP servers, manages the rate limiting and the audit.
  5. A mesh of MCP servers: isolated containers per domain (HR-MCP, Eng-MCP, Sales-MCP), running in private subnets.
  6. Audit Vault: a storage for the “Thought — Action — Observation” logs for compliance.

12. Artifact: the integration decision table

Use this table when designing the architecture, to choose how to open new capabilities to your AI agents.

Characteristic MCP Server REST API (Direct) Event Bus (Kafka) Direct SDK/Lib
Primary use case Discovery and actions for an LLM Standard software integration Async sync / ETL Speed-critical tasks
Model context Native. Schemas for the LLM No. Needs a wrapper No. Incompatible No. Manual glue
Scalability High (stateless containers) Very high Massive Low (coupling)
Auth model OAuth 2.1 / PKCE API keys / OAuth 2.0 SASL / IAM Hardcoded / IAM
Auditability High (tool calls) Medium (URL level) High (event log) Low (function calls)
Development Fast (with decorators) Medium High complexity Low (direct code)
Maintenance Low (weak coupling) Medium High High (version coupling)

13. Frequently asked questions (FAQs)

Q1: Can I use MCP with any LLM provider (OpenAI, Google, AWS)? A: Yes. Although the protocol was initiated by Anthropic, it is an open standard. All you need is an “MCP client” (a host) that can translate the output of the model (function calling) into the MCP JSON-RPC format. Most corporate AI platforms already implement this abstraction.

Q2: How is MCP different from the “Tools” in LangChain? A: The LangChain tools are code-level abstractions inside a specific library. MCP is an abstraction at the level of the protocol. That means you can write an MCP server in Go and a host in Python will consume it without problems. It is the difference between “a class in Java” and “a REST API”.

Q3: Is the stdio transport safe for production? A: No. stdio is meant for local development. For cloud corporate environments use the Streamable HTTP transport over HTTPS — in the MCP specification it replaced the legacy HTTP+SSE.

Q4: How do you prevent the model from calling the expensive tools too often? A: Implement rate limiting at the Context Gateway level. You can also assign a “cost weight” to specific tools and limit the daily budget of the user for the tool calls.

Q5: Can one MCP server call another one? A: In theory yes, but it is not recommended to keep things simple. It is better to have one orchestrator (host) that manages several servers. If a chain is unavoidable, make sure the Trace ID is propagated.


CTA: Unifying the context is work with the boundaries: which tools are available to the agent at all, who is accountable for the call, what the audit looks like. If you need to assemble such an MCP environment yourself, see how we do it: projects and contact.


Victor Buzin — the founder of AnetLab. Works on integrating AI into corporate systems: MCP, RAG, .NET and Azure.

Read also

Request

Discuss the task

Leave your name and email — I reply within one working day. If the task is urgent, write directly toproject@anetlab.ru.