The MCP servers we reviewed in 2024 were mostly single-tenant. A team built a server for its own agents, ran it in its own account, and called it done. In 2025 that changed. Shared MCP infrastructure started appearing: platforms offering tool marketplaces, vendors operating MCP servers as managed services, and enterprises consolidating internal tooling onto a shared fleet. Multi-tenancy arrived, and the security model is still catching up.
This post is about what it takes to run a Model Context Protocol server safely when the callers belong to different tenants. The patterns are not novel in isolation, but the combination is specific enough to MCP that importing them from generic SaaS architecture is not quite enough.
Start With an Honest Tenancy Model
The first thing worth spending time on is deciding what a tenant actually is in your deployment. This sounds pedantic and is not. The decisions you make downstream — how credentials are scoped, how data is partitioned, how telemetry is aggregated — all depend on it.
Common MCP tenant models we see:
Organisation-as-tenant. The tenant is a customer organisation. All users and agents within the organisation share a tenant boundary. This is the model most B2B SaaS teams start with and is usually correct for enterprise deployments.
Agent-as-tenant. Each deployed agent is its own tenant. Useful when agents operate on behalf of different downstream consumers (for example, an agent platform where each end customer gets their own agent instance).
User-as-tenant. Every end user is an isolated tenant. Higher isolation cost, but appropriate for consumer products and for compliance-sensitive workflows where per-user audit trails are required.
Hybrids exist and are fine — for example, organisation-level tenancy for data but user-level scoping for quotas and audit logs. What is not fine is drifting. If the initial model is "organisation" and a product decision later requires per-user scoping, retrofitting is painful and usually incomplete.
Identity Propagation Across the Tool Chain
An MCP server almost never acts in isolation. A tool call typically originates with a user, flows through an agent framework, lands on the MCP server, and fans out to downstream APIs, databases, and third parties. Identity has to travel the whole way, or authorisation decisions downstream are made against the wrong principal.
The pattern we have found durable is to propagate three identity components on every tool call: the tenant, the user (or agent) acting on the tenant's behalf, and the invocation context (a unique identifier for the specific agent turn). These are not interchangeable. The tenant says "who is billed and who owns the data." The user says "what permissions apply." The invocation context says "what happened, together, in one logical unit of work."
Concretely, we attach these to every outbound call from the MCP server as signed headers or JWT claims. Downstream services that trust the MCP server verify the signature and use the claims for their own authorisation decisions. The MCP server never uses its own credentials to speak for a tenant, because as soon as it does, you have lost the ability to reason about authorisation from logs.
Data Isolation: Rows Are Not Enough
Multi-tenant data isolation usually starts with "add a tenant_id column and filter every query on it." That is necessary but nowhere near sufficient for MCP.
The gaps that bite:
Shared caches. If the MCP server caches tool results by input argument without tenant in the key, tenant A's result can be served to tenant B when they happen to query the same thing. We default to tenant-prefixed cache keys and periodically audit for accidental omissions.
Shared vector stores. RAG-backed tools often use a single vector index for efficiency. If tenant filtering is applied at query time only, a bug or misconfiguration can return cross-tenant results. The safer pattern is either per-tenant indexes or mandatory tenant-scoped namespaces enforced at the store layer, not the application layer.
Log and metric aggregation. Telemetry pipelines often strip tenant identifiers because they are high-cardinality. This means errors containing tenant data end up in shared dashboards where they should not be visible. Tenant ID needs to be a first-class telemetry dimension with access controls that match the data.
Backups and exports. A per-tenant export that accidentally includes another tenant's data is a disclosure incident. Tenant filtering must be enforced in the pipeline that generates the export, not just in the UI that requests it.
Compute Isolation and the Noisy Neighbour
Even if data is perfectly separated, shared compute creates its own problems. A tenant running an unusually expensive tool call can degrade latency and reliability for everyone else on the same server. This is the classic noisy-neighbour problem, and MCP makes it worse because agents are capable of generating workloads that humans would never produce — tight loops, fan-outs, and accidental recursion.
The controls we rely on:
Per-tenant concurrency caps, sized generously for normal use and aggressively for suspected abuse. A single tenant should not be able to monopolise more than a tuned fraction of total worker threads.
Per-tenant token and cost budgets that cap how much the tenant can spend on upstream resources per hour and per day. When budgets are exhausted, tools return a structured error with a clear reason code rather than hanging or failing ambiguously.
Shared-tenancy tool execution inside strong process boundaries — separate containers or at minimum separate OS processes — so that a tool crash or memory leak is contained to a single invocation rather than cascading across tenants.
Secret and Credential Scoping
Credentials are where multi-tenant isolation fails most dramatically. A pattern that works: every tenant's credentials are stored in a secrets backend with tenant-scoped access policies; the MCP server fetches credentials per invocation, passes them to the tool through a short-lived context, and clears the context on completion; credentials are never logged, never cached beyond a single call, and never propagated to downstream services outside the intended tenant.
The pattern that fails: environment variables. An MCP server that loads tenant credentials into environment variables at startup is a single bug away from cross-tenant credential exposure. Tools that introspect environment variables for configuration can be tricked into reading another tenant's secret. This architecture is comfortable because it matches twelve-factor app conventions, and it is wrong for multi-tenant MCP.
Observability That Respects Boundaries
A multi-tenant MCP server needs two classes of observability: platform-level metrics visible to operators (aggregate traffic, error rates, resource utilisation) and tenant-scoped data visible only to the tenant (their tool calls, their usage, their errors). Mixing them is a data-handling incident.
The mechanism we use is two parallel telemetry pipelines. Platform metrics strip tenant identifiers at source and are safe to expose broadly. Tenant audit data is tagged with tenant identity and stored in a logging backend that enforces per-tenant access control. Correlation between the two, when needed for incident response, requires an explicit cross-pipeline join authorised by an operator.
This matters because support and debugging workflows tend to reach for logs. "Show me what happened during this error" is a reasonable request. "Show me what happened during this error, filtered to this specific tenant, with appropriate access controls" is the request the platform should make easy.
How Safeguard Helps
Safeguard treats multi-tenant MCP isolation as a configurable policy surface rather than a per-deployment code exercise, enforcing tenant-scoped identity propagation, credential boundaries, and data partitioning at the guardrail layer. The platform continuously audits MCP servers for cross-tenant risks — shared caches missing tenant keys, vector stores without namespace enforcement, telemetry pipelines leaking tenant identifiers — and flags each with a specific remediation. Per-tenant quotas, concurrency caps, and cost budgets are applied from policy, so noisy-neighbour protection does not depend on every team remembering to build it. Tenant-scoped audit trails surface directly in the Safeguard dashboard, giving operators one place to answer "what did this tenant's agent actually do?" without risking exposure of another tenant's activity.