An MCP governance checklist for the CTO

An MCP governance checklist for the CTO. A blueprint drawing of a tall sheet with a column of check boxes, ringed by a boundary line that separates it from a small server module.

When a company connects its AI assistants to its systems through the Model Context Protocol (MCP), the decisions that matter most aren’t in any server’s code. They’re about which hosts employees use, who may approve what, how identity is managed, and what gets logged. This is the list I’d hand a chief technology officer (CTO): what the specification settles, what it leaves to you, and the policy each gap needs.

This is part 2 of a short series for the people who buy, approve and govern MCP servers rather than build them, after part 1 on what to require from a vendor. It draws on the same facts as my series for builders, under the 2026-07-28 specification, as I read them in October 2026. MUST, SHOULD and MUST NOT in capitals are the specification’s words; where something is my advice, I say so.

MCP is an open standard that lets AI applications discover and use external tools, data and prompt templates through one common interface. A server connects a probabilistic system, the large language model (LLM), to deterministic systems that hold real data and take real actions, and that is where governance begins.

In brief

  1. Everything the model reads is potentially attacker-influenced, your vendors’ tool descriptions and instructions included. Most MCP security problems come from forgetting that.
  2. Three primitives have three deciders. The model decides when a tool runs, the application when a resource is read, the user when a prompt is used. Your policy should say which mechanisms each server may use.
  3. The host has duties the specification spells out: it SHOULD keep a human in the loop, confirm sensitive operations, show tool inputs before sending them, validate results, enforce timeouts and log tool usage, and it MUST treat a server’s annotations as untrusted unless the server is trusted.
  4. Identity comes in four models, chosen by who is calling. Enterprise-managed authorization puts access under your identity provider, but as of October 2026 the mainstream hosts don’t list it, so pre-registered clients with core authorization are the practical option.
  5. My advice: keep a register of approved servers with versioned definitions, separate reads from writes, write a policy for local servers, and look at what your hosts support every quarter.

Where the risk enters

Picture four zones. Your users and their host, with its model, share one. A server, with its tool descriptions, instructions and skills, belongs to whoever operates it, which for a bought server is the vendor. Your APIs and databases sit in a backend zone of their own. The fourth holds untrusted content from outside: web pages, emails, tickets and documents. Data crosses between them at three boundaries.

Untrusted content: Web pages, emails, tickets, documents; Server operator zone: MCP server, Tool descriptions, instructions, skills; User's trust zone: User, Host + model; Backend trust zone: APIs, databases; Tool descriptions, instructions, skills – MCP server; Host + model – User; Web pages, emails, tickets, documents → MCP server: boundary 3: untrusted content enters tool output; MCP server → Host + model: boundary 1: definitions and outputs flow into the model's context; MCP server → APIs, databases: boundary 2: delegated credentialsUntrusted contentServer operator zoneUser's trust zoneBackend trust zoneWeb pages, emails,tickets, documentsMCP serverTool descriptions,instructions, skillsUserHost + modelAPIs, databasesboundary 3: untrusted contententers tool outputboundary 1: definitions and outputsflow into the model's contextboundary 2: delegated credentials

The first boundary is the one most policies miss. A tool description is text the model reads, so it can steer the model as well as describe a tool. These are the threats I’d plan for, with the side of the boundary that can do something about each. Where a mitigation is a requirement of the specification, its word is in capitals.

ThreatWhat happensWhat the vendor’s server doesWhat your host does
Tool poisoningHidden instructions in a tool description or the server’s instructions steer the modelKeeps descriptions factual and reviews them like codeShows definitions to users, flags suspicious text, treats annotations as untrusted
Rug pullA server changes its tool definitions after a user approved themVersions its definitions and announces changesAsks for approval again when definitions change
Prompt injection through outputsA document, email or web page a tool returns contains instructionsMarks fetched content as data and sanitizes outputs (MUST)Separates untrusted content and confirms sensitive follow-up actions
Confused deputy and token passthroughThe server uses its own broad credentials, or forwards the user’s token, on the user’s behalfAudience-bound tokens and on-behalf-of flows, never passthrough (MUST NOT)Least-privilege scopes
Over-broad scopesOne token grants everythingA minimal set of scopes, plus step-upRequests only the challenged scopes
Data exfiltration through argumentsThe model is tricked into putting secrets into a call to an attacker’s serverValidates inputs (MUST)Shows tool inputs before calling (SHOULD)
Local server compromiseA local server runs arbitrary code on the user’s machineSigned releases, minimal dependenciesTrust prompts and sandboxing; as of October 2026, VS Code can sandbox local servers on macOS and Linux
Malicious skillsA skill tells the agent to run scripts or grant toolsShips minimal, reviewable skillsPer-skill approval bound to file digests
Interface phishingAn MCP App shows misleading contentHonest interfaces, minimal Content Security Policy domainsSandboxed iframes, clear boundaries
Resource exhaustionRunaway loops, huge outputs, floods of tasksRate limiting (MUST), output caps, per-caller quotasTimeouts and output limits

Half of that table is the host’s job, which is why the choice of host is a governance decision. The specification says a client SHOULD keep a human in the loop, confirm sensitive operations, show tool inputs before sending them, validate results, enforce timeouts and log tool usage. It MUST treat tool annotations, the hints a server gives about whether a tool only reads or may destroy something, as untrusted unless the server is trusted. When you evaluate a host, those are the behaviours to check.

Who decides what

A server can offer three things, and they differ in who decides when each is used. Tools are functions with schemas, called by the model while it reasons. Resources are context identified by an address, which the application attaches or the user picks. Prompts are templates the user runs on purpose, as a slash command.

Model decides: Tools functions with schemas, tools/call, Model calls it while reasoning; Application decides: Resources context by URI, resources/read, Host attaches it as context; User decides: Prompts reusable templates, prompts/get, User runs a slash command; Tools functions with schemas → tools/call; tools/call → Model calls it while reasoning; Resources context by URI → resources/read; resources/read → Host attaches it as context; Prompts reusable templates → prompts/get; prompts/get → User runs a slash commandModel decidesApplication decidesUser decidesToolsfunctions with schemastools/callModel calls it while reasoningResourcescontext by URIresources/readHost attaches it as contextPromptsreusable templatesprompts/getUser runs a slash command

Extensions add more: skills, which are workflow instructions with supporting files; MCP Apps, interactive interfaces rendered in the conversation; and tasks, long-running work the server runs on its own. Each mechanism carries a different kind of risk, so I’d decide, per server, which ones are allowed.

MechanismWho triggers itSide effects?The policy question
ToolThe modelYes, potentiallyWhich tools may run without a person confirming?
ResourceThe application or the userNo, read-onlyWhat may be attached to a conversation, and from which servers?
PromptThe userNo; it produces messagesWho may publish prompts your people will run?
Server instructionsThe host, when it loads themNoWho reviews the paragraph the model reads first?
SkillThe model or the user, after any approvalOnly through the tools it usesWho approves a skill, and what revokes that approval?
MCP AppThe model, through a toolThrough the tools the app may callWhich servers may render interfaces, and may an app call tools without consent?
TaskThe server, per requestYes, potentiallyHow long may work run unattended, and who can cancel it?

My advice for tools is simple: separate read tools from write tools, and give writes clear, honest names. A host can then approve reads quietly and confirm writes, which keeps a person in the loop without burying them in prompts.

Which identity model fits

Core MCP authorization pictures one person in a browser, approving one client for one server. That fits consumers; in a company it causes friction and gaps. Employees shouldn’t have to understand every server’s authorization details, security teams can’t enforce one policy, and onboarding and offboarding mean authorizing, then revoking, dozens of services by hand. Two official extensions cover what the core handles poorly, and the right model depends on who is calling.

Who is calling the MCP server? → Is a human user present?; Is a human user present? → Is access governed centrally by an enterprise IdP?: yes; Is access governed centrally by an enterprise IdP? → Enterprise-Managed Authorization with an ID-JAG: yes; Is access governed centrally by an enterprise IdP? → Core MCP authorization authorization code + PKCE: no; Is a human user present? → Local process on the user's machine?: no; Local process on the user's machine? → stdio: credentials from the environment: yes; Local process on the user's machine? → OAuth Client Credentials prefer JWT assertions: noWho is calling the MCP server?Is a human user present?Is access governedcentrally by anenterprise IdP?Enterprise-ManagedAuthorizationwith an ID-JAGCore MCP authorizationauthorization code+ PKCELocal process on theuser's machine?stdio: credentialsfrom the environmentOAuth Client Credentialsprefer JWT assertionsyesyesnonoyesno
ModelWho it servesStatus, October 2026
Core authorization, an authorization code with Proof Key for Code Exchange (PKCE)A person authorizing a client for a serverPart of the specification
Enterprise-Managed AuthorizationA person whose access the company’s identity provider (IdP) governsStable extension; the official client matrix lists it in Archestra.AI and Apify’s mcpc command-line client, and no mainstream chat or IDE host
OAuth Client CredentialsA job with no person present: a pipeline, a scheduled task, a serviceDraft extension; listed in mcpc
Credentials from the environmentA local server on the user’s own machineThe specification’s rule for stdio

Enterprise-managed authorization is the one to watch. The organization’s IdP (Okta, Microsoft Entra ID or a corporate single sign-on system) becomes the decision-maker: the user signs in to the host with corporate single sign-on (SSO), the host trades that sign-in for an Identity Assertion JSON Web Token (JWT) Authorization Grant (ID-JAG) at the IdP, and exchanges the grant for an access token, with the IdP applying its policy on groups, roles and conditional access before anything is issued. What the organization gets is central policy, one sign-in, enforcement before a token exists, revocation in one place and an audit trail. It needs support on the IdP’s side as well as in the host, so check with your IdP vendor.

For callers with no person present, the client-credentials extension allows two credential formats, and the guidance prefers a signed JWT assertion to a client secret: the private key stays with the service, the assertion lives minutes, and a leak gives a limited window rather than silent impersonation until someone rotates the secret.

Whatever the model, two rules from part 1 hold: a server validates every token’s audience, and it never forwards your token to another system. If Entra ID is your IdP, expect clients to be pre-registered, since as of October 2026 it supports neither open Dynamic Client Registration nor Client ID Metadata Documents.

Approvals for skills, apps and local servers

Skills are the mechanism with the clearest approval rules. The Skills extension lets a host gate loading behind approval, per skill or per server, and makes approval mandatory for four things: running code on the host, granting tools through an allowed-tools list, reading files across servers, and activating a nested skill. A host MUST verify every file it loads against the digest the server published, and a persisted approval binds to the complete set of files, so any changed, added or removed file revokes it. A host MUST NOT fetch skill files ahead of need, MUST stop same-named skills from silently replacing each other, and tags loaded content with the server it came from. Those are the behaviours I’d check in a host, and the reason a skill’s approval is worth recording.

MCP Apps run in a host-controlled sandboxed iframe with a Content Security Policy built from the domains the server declared; the host may tighten it and MUST NOT loosen it, and SHOULD log the policy for audit. The host decides what an app may do: it may restrict which tools the app can call, disable link opening, or require the user’s consent before forwarding a tool call. A tool an app calls on its own behalf can be hidden from the model altogether. The policy question is which servers may render interfaces at all, and whether an app’s tool calls need consent.

Local servers trade operational simplicity for supply-chain and trust concerns, because they run code on the user’s machine. If you allow them, my advice is to require signed, versioned packages with minimal dependencies, secrets read from the environment, and the host’s sandboxing where it exists. A local HTTP server should bind to localhost and validate the Origin header, or a web page can reach it.

The checklist

Each row is a decision I’d want written down before the first server is approved.

DecisionWhat to write down
HostsWhich AI applications are approved, and which of the host duties above each one performs
The registerEvery approved server, with its tool definitions and instructions as reviewed, versioned, and re-approved when they change
Reads and writesWhich tools run without confirmation, and that writes always confirm
MechanismsPer server: tools, resources, prompts, instructions, skills, apps, tasks, each allowed or not
IdentityThe authorization model per server; scopes kept minimal; no token passthrough, in the contract; how access is revoked
ApprovalsWho approves a skill, and that approval dies with any changed file; which servers may render apps, and whether app tool calls need consent
LoggingTool usage logged by the host; trace context continued end to end; an audit record of the caller, the tool, a hash of the arguments and the outcome
LimitsRate limits, output caps and timeouts, on the server and in the host
Local serversAllowed or not; if allowed, signed packages, sandboxing, secrets from the environment
ReviewA look at what the hosts support every quarter, and the server’s own telemetry as the record of which hosts use it

Method and caveats

  • Built from my guide to MCP servers, written against the 2026-07-28 specification, and reframed for the people who govern a deployment. The builder series has the detail behind each row; product facts, such as which hosts list an extension, are as of October 2026.
  • The MUST, SHOULD and MUST NOT marks are the specification’s or its extensions’. The zones, the policy questions and the checklist are my way of organizing the decisions, not a list from the specification.
  • Everything here is framed from the specification. It describes no particular company, vendor or deployment.