MCP security and operations, explained

Build MCP integrations
you can trust and operate.

Get the mental model, security boundaries, and operational decisions you need before opening the protocol specification.

Start with the essentials Zero dependencies · Works offline
Trust boundaryMCP messages are not permissions
Secure by designTokens stay outside JSON-RPC
MCP 2026-07-28Current protocol reference
Start here · 2 minutes

The MCP mental model.

MCP standardizes messages between a host-managed client and a server. It does not grant authority, secure tools, or make server-provided content trustworthy.

Host / AppMCP ClientTransportMCP ServerData / Tools
ProtocolDefines message shapes and capabilities.
IdentityProves who called over a protected transport.
PolicyDecides whether each action is allowed.
01

Choose a connection

Local stdio inherits process and OS boundaries. Remote HTTP needs HTTPS, a trusted issuer, and per-request authorization.

02

Discover, then constrain

Tools, prompts, schemas, and returned content are server-supplied input. Review changes, validate arguments, and keep approvals explicit.

03

Authorize every action

A tools/call names an operation; it does not grant permission. Enforce scope, role, tenant, tool, arguments, and downstream ACLs.

Protocol reference

Primitives flow in both directions.

Use this reference after the essentials. MCP 2026-07-28 defines three core server primitives; current requests declare version and client capabilities in params._meta.

Server primitives

The server exposes context and actions; the client discovers them and decides how they enter the host experience.

3 core primitives
Model-controlled

Tools

Schema-described functions that let a model retrieve information or perform an action. “Model-controlled” describes the interaction pattern, not permission: the host should expose calls for approval, and the server must still authorize every action.

Example · look up inventory tools/call → inventory.lookup({ sku: "MCP-2048" })

Discover: tools/list Use: tools/call

Application-controlled

Resources

URI-addressed data such as files, records, schemas, or API responses. The application chooses what to read, subscribe to, display, or place into model context; resource templates parameterize URIs rather than forming another primitive.

Example · read a catalog record resources/read → inventory://catalog/MCP-2048

Discover: resources/list Use: resources/read

User-controlled

Prompts

Server-authored, reusable message templates with optional arguments. “User-controlled” means the user explicitly selects one, often through a slash command or menu; the host should identify the supplying server and preview the resulting messages.

Example · prepare a stock review prompts/get → review-stock({ region: "east" })

Discover: prompts/list Use: prompts/get

Client-offered input

The client declares supported input capabilities on every request. Current servers request that input through a multi round-trip result rather than initiating a new request.

2026-07-28
Deprecated · 2026-07-28

Sampling

Sampling let a server ask the client to run an LLM generation without owning model credentials. It is deprecated in 2026-07-28; new servers should integrate directly with a model provider. Compatible clients should still gate legacy sampling and let users review prompts and results.

Legacy example · summarize tool results sampling/createMessage → "Summarize these stock changes"

2025 capability: sampling Current status: deprecated

Deprecated · 2026-07-28

Roots

Roots let a client suggest relevant filesystem locations. They never granted access or replaced operating-system permissions. Roots are deprecated in 2026-07-28; current designs should pass files or directories through tool arguments, resource URIs, or server configuration.

Legacy example · expose a workspace boundary roots/list → file:///workspaces/inventory-app

2025 capability: roots Current status: deprecated

User-controlled

Elicitation

Lets a server request user input while handling a prompt, resource read, or tool call. Current MCP returns input_required; the client collects input and retries. Form mode excludes secrets, while URL mode supports sensitive out-of-band interactions.

Example · confirm a missing field resultType: "input_required" → elicitation/create

Capability: elicitation Pattern: MRTR

Official MCP sources: 2026-07-28 overview, server primitives, base protocol and _meta, MRTR, and the deprecation registry.

Operational guide

Connect, approve, and operate a server.

MCP does not define one universal installation manifest. Configuration shape and location are host-specific; JSON-RPC methods, per-request metadata, discovery, message patterns, and transport behavior are protocol-standard.

Production readiness

Use this as your enablement gate.

Before enablement

Verify provenance, pin the release, allowlist origins and redirect URIs, assign least privilege, and review tool metadata.

At runtime

Authorize each request, validate arguments, set timeouts and limits, isolate side effects, and request approval for sensitive actions.

In operations

Audit decisions without secrets, monitor capability changes, rotate credentials, update deliberately, and keep a tested disable path.

  1. 01Choose & trustVerify owner, source, signature, package, and purpose.
  2. 02Select transportLocal stdio or protected remote HTTP.
  3. 03ConfigureSet a pinned command and args, or an allowlisted URL.
  4. 04Add identityReference Entra scopes and a token provider—not a token.
  5. 05DiscoverCall server/discover, select a version, and review capabilities/tools.
  6. 06ConstrainApply approvals, least privilege, schemas, and policy.
  7. 07OperateMonitor, update deliberately, disable, and remove cleanly.
Host-specificInstallation / connection configuration

File names such as mcp.json, settings keys, storage locations, secret references, and approval controls differ across Copilot, VS Code, Claude, and custom hosts.

Protocol-standardMCP request behavior

server/discover, required per-request _meta, JSON-RPC methods, message patterns, and stdio or HTTP transport semantics are interoperable MCP concerns.

Illustrative host configLocal stdio server
MCP 2026-07-28

Generic example only—the exact schema and file location differ by host.

Manifest fields to understand

name
Stable, human-readable server identifier within the host.
type / transport
Selects local stdio or the host's remote HTTP transport adapter.
command, args, cwd, env
stdio launch contract. Pin executable/package versions; environment values should reference secret storage rather than contain raw secrets.
url
Remote server endpoint: modern /mcp, or legacy SSE/message endpoints when the host supports them.
auth, tokenProvider, scopes
Host-specific instructions for acquiring an audience-bound token; never an inline access token.
timeout
Launch, connection, and request limits that bound stalled or hostile servers.
enabled / approval policy
Administrative and per-tool controls for activation and sensitive actions.
version / capabilities
Requested MCP version and host policy constraints; current servers advertise support with server/discover, and clients repeat version/capabilities in params._meta.
Before enabling:
  • Pin executable paths, package identities, and versions; verify provenance before updates.
  • Treat env entries as references to a secret store or inherited variables, never raw credentials.
  • Allowlist remote origins, Entra authorities, and exact redirect URIs; require HTTPS.
  • Treat server instructions, tool descriptions, schemas, and returned content as untrusted input.
  • Keep credentials in the transport/token-provider layer—never in MCP JSON-RPC, _meta, tool arguments, or persistent application state.
System map

Six roles, three layers

MCP standardizes JSON-RPC exchanges between a host-managed client and one server. It is not an agent framework, model API, security sandbox, identity provider, or authorization policy.

01Control / architectureWho decides and orchestrates
02TransportHow protected messages move
03Service / dataWhere policy and work happen
Tip: Select any node to understand its boundary.
Lifecycle deep dive

Trace the flow when you need the wire.

Request Response Notification Policy boundary 2026-07-28: stateless POST requests; request-scoped SSE is optional.

How to read the flow: Begin with the required path, then inspect identity choices, internal policy, and optional operations. The 13 details are grouped by phase; they are not one mandatory sequence of network calls.

Step 01TrustRequired exchange

Selected exchange

Who sends what

Initiator
Receiver
Responder
Channel
Components involved
Purpose

Success looks like

Failure looks like

What MCP guarantees

What your system owns

1 / 13
Microsoft Entra ID

Two callers. One strict resource boundary.

Authorization is optional in MCP and applies to HTTP transports. When Entra protects a remote server, use delegated identity for a signed-in user or application identity for a confidential service, and validate before MCP dispatch.

01

Delegated identity

A public desktop or browser client uses MSAL Authorization Code + PKCE for a signed-in user.

  • Discover protected-resource and Entra metadata
  • Request the MCP resource and least-privilege scopes
  • Send the access token on every HTTP request
  • Never place access or refresh tokens in JSON-RPC
≠
02

Application identity

A confidential host uses an Entra workload identity rather than pretending to be a user.

  • Prefer managed identity or workload identity federation
  • Otherwise use a certificate; client secrets are last resort
  • Authorize application permissions from roles
  • Use a separate downstream token or OBO for user delegation
  1. 01
    Discover401 challenge → RFC 9728 protected-resource metadata → Entra authority metadata.
  2. 02
    AcquireMSAL + PKCE for users; managed/workload identity, certificate, or credentials for apps.
  3. 03
    PresentAuthorization carries a bearer access token on every Streamable HTTP request.
  4. 04
    ValidateVerify signature, issuer, audience, tenant, lifetime, then scp or roles.
  5. 05
    AuthorizeDerive the principal for each request and enforce scopes, roles, tenant, tool, and resource policy.
  6. 06
    Delegate safelyFor downstream APIs, use OBO when user context is required—never pass the MCP token through.
401 UnauthorizedToken missing, malformed, expired, wrong issuer/audience/tenant, or invalid signature. Include an appropriate WWW-Authenticate challenge.
403 ForbiddenToken is valid, but the required delegated scope (scp) or application permission (roles) is absent.
Hard boundary: Tokens are HTTP authorization material. They never belong in JSON-RPC params, _meta, tool arguments, model context, or logs. A tools/call names an operation—it does not grant permission.
OWASP MCP Top 10 · 2025 beta

Inspect the attack surface.

An attack surface is every place untrusted data, identity, code, or authority crosses a boundary. Expand a risk to compare an unsafe pattern with a safer design and a practical verification check.

01Locate the boundary

Identify where identity, tool metadata, arguments, content, packages, or results enter a more trusted component.

02Trace authority and data

Ask what the caller can access, what the model can influence, and which downstream side effects are possible.

03Verify the control

Test the denied path—not only the happy path—and confirm the decision is visible without leaking secrets.

Secure does not mean risk-free. The safer examples reduce exposure through least privilege, explicit validation, isolation, and auditable decisions; they still require threat modeling. Category names follow the official OWASP MCP Top 10:2025 beta snapshot and may change before final publication.

10 risks