# CISO Checklist for MCP Servers: 7 Questions

> A CISO checklist for MCP servers: seven questions on hosting, sign-in, per-person identity, writes, logs, data paths and revocation.

**TL;DR** A CISO checklist for MCP servers asks seven questions about one server: who built and runs it, how people sign in, whether calls run as a named person, which tools write or delete, what is logged, where data travels, and how access is cut off. Elaichi answers those questions for every connector in its catalog at one endpoint, so the review happens once per connector rather than once per laptop. For a server you run yourself, the same seven questions apply, and you answer them from your own code.

## Why a CISO checklist for MCP servers is different from picking a gateway

Someone on your team has already asked to add an MCP server. A CISO checklist for MCP servers is what you run against that one server, before anyone's Claude or ChatGPT signs into it. Choosing a gateway or control plane is a platform decision made once. This is a per-server approval you will repeat weekly or monthly, for every new connector someone requests. So it needs to be short enough that you actually repeat it, and specific enough that two different reviewers reach the same answer.

[MCP (Model Context Protocol)](https://modelcontextprotocol.io) is the open standard that lets an AI client call tools exposed by a server. An MCP server is the thing on the other end that holds those tools. The request in front of your reviewer is a URL plus a claim about what it can reach. The spec itself is still evolving. Check the current revision at modelcontextprotocol.io before treating any version-specific detail below as permanent.

The seven questions below are vendor-neutral. They apply whether the server sits behind Elaichi, a homegrown gateway, or no gateway at all. Each question has a known-bad answer that should stop the approval, whichever product you run. Where it helps, we show how one implementation (Elaichi, which we build) answers each question, labeled as an example rather than the standard. If you are still deciding whether to run a gateway at all, [the gateway evaluation checklist](/blog/mcp-security-review-checklist/) is the right page. This one assumes that decision is behind you.

## Who built the server, and who runs it?

**The question, independent of vendor:** who wrote the tools, and who operates the process your traffic reaches at runtime? These are frequently different parties. The gap between them decides who you escalate to when a tool misbehaves, and whose security posture you are actually inheriting.

This matters because of three concrete, generalizable risks in the MCP model:

- **Supply-chain risk**: a tool's code or its description can change between the time you reviewed it and the time it runs, if you don't control the server.
- **Tool poisoning**: a tool's name and description are read by the model, not just the human. A malicious or compromised server can ship a tool whose description contains hidden instructions aimed at the calling model, not the user (OWASP's LLM application guidance covers this class of attack under prompt injection via untrusted content).
- **Confused deputy across grants**: if one server operator or one shared credential backs tools for multiple unrelated upstream apps, a bug or compromise in that one place can move laterally across every app behind it.

None of this is specific to one vendor. It is a property of any architecture where an AI client trusts a remote party to define what a "tool" does.

**Example implementation, Elaichi's catalog:** the catalog holds two kinds of connector, and a reviewer should know which one they are looking at. Most connectors Elaichi authors and operates itself. The rest are native MCP connectors: the vendor builds and runs its own MCP server, and Elaichi handles sign-in, access and audit in front of it. Datadog and Linear are both native MCP connectors, each the vendor's own server reachable through Elaichi's auth layer. The console states this on the connector's page. A native MCP connector carries a vendor support contact, which is where tool-behavior reports go; Elaichi does not review, test or fix a native MCP connector's tool code. A team can also bring its own remote MCP server into Elaichi as a connector, on Gold or Black plans. In that case the operator is you, and the rest of this checklist becomes a review of your own code and your own supply chain.

**The bad answer, in any setup:** a server nobody will name an operator for. If the response is "it's a community wrapper around the vendor's API," you are approving an unnamed third party between your AI client and production data, with no support contact and no accountable owner for its tool definitions.

## How does the server authenticate, and who holds the credential?

**The question:** separate two distinct credential questions, how the person signs in to the server, and how the server itself signs in to the app behind it. Conflating these is the single most common MCP security mistake we see in reviews.

The vendor-neutral standard to check against: does the server implement OAuth 2.1-style delegated auth with PKCE, or does it rely on static shared secrets? [OAuth](https://oauth.net/2/) is the open standard for delegating access without handing over a password. [PKCE (RFC 7636)](https://datatracker.ietf.org/doc/html/rfc7636) prevents authorization-code interception. It should be mandatory with the S256 method, because the plain method is considered insufficient by current best practice. [OAuth dynamic client registration (RFC 7591)](https://datatracker.ietf.org/doc/html/rfc7591) lets clients register themselves without a human provisioning a client ID/secret pair per app. That is useful. Ask whether a server that accepts self-registered clients also rate-limits or vets them.

**Example implementation, Elaichi:** Elaichi's MCP endpoint accepts nothing but an OAuth access token in the Authorization header. No Elaichi API token works there, no pasted API key, no browser session; a request without a valid token gets HTTP 401. Clients register via RFC 7591, and PKCE with S256 is mandatory (plain is not implemented). There is no client secret for an employee to look up or paste, and no per-user MCP address to track separately. The credential for the app *behind* the server is a separate secret entirely. Elaichi stores every connected account's secrets in a dedicated credential service, encrypted at rest with AES-256-GCM, and fetches them into memory only for the specific call that needs them. The AI client itself only ever holds an Elaichi-issued token. For a native MCP connector, Elaichi never forwards its own token upstream; the upstream OAuth server sees only a token its own authorization server issued.

**The bad answer, in any setup:** a server that asks each employee to paste a personal API key into a config file. That key typically carries the person's full account privileges, often never expires, and nothing records which AI assistant used it or when. [Why personal API keys fail as an AI credential](/blog/stop-sharing-personal-api-keys-with-ai-tools/) walks through the failure modes in detail.

## Does every call run as a named person?

**The question most servers fail:** is a tool call attributable to one employee, or does it run against a shared service account that every employee's assistant draws on? This is the difference between an audit log you can use in an incident and one you can't. "The assistant did it" is not an answer that survives an investigation.

**Example implementation, Elaichi:** every connected-tool call runs as one specific person. Over MCP, that identity is the OAuth grant behind the bearer token, and each person approves their own grant on a consent screen rather than inheriting someone else's. Permissions are looked up on each request rather than frozen into the token at issuance, so a role change applies before the token's natural expiry.

One nuance to probe in any vendor's implementation: a connection shared across a team typically runs on its *owner's* sign-in to the downstream app. So the AI-platform-side actor (who called the tool) and the app-side actor (whose credential executed it) are not always the same person. If the downstream app needs to see the individual caller, tools have to run on that person's own connection, not a shared one.

**The practical test for any server, regardless of vendor:** ask to see two different employees call the identical tool, and ask for the two resulting log records side by side. If the records are indistinguishable except for a timestamp, attribution is broken.

## Which tools write, which delete, and what stands in front of them?

**The question:** get the full tool list with per-tool classification, read vs. write vs. destructive, not a summary paragraph. Then ask [what enforces the boundary](/blog/restriction-resolver-decision-tree/) between "can read" and "can delete." In MCP there is frequently no per-call human approval step, and a single consent grant often covers every tool a connector exposes, reads and deletes alike.

A generalizable tiering heuristic, independent of any one vendor's implementation: an HTTP `DELETE` is destructive regardless of what the method is named. A `GET`/`HEAD`-style read is safe to tier as read-only. Anything else, including ambiguous or unlabeled remote-MCP tools, should default to destructive until proven otherwise. A server that defaults ambiguous tools to "safe" is making an optimistic assumption on your behalf.

**Example implementation, Elaichi:** a connector's page lists every tool with a search box and a label, Read only or Makes changes. On Stripe's page, for instance, searching "refund" returns *Create a refund* labeled Makes changes beside *View refunds* labeled Read only. Elaichi works out a tier two different ways, and a reviewer should keep them apart.

A catalog connector's tool is tiered from its HTTP verb and its method name. A list or get method counts as a read only when its verb is GET or HEAD. An HTTP DELETE is destructive whatever the method is called, and a delete method is destructive. Everything else, including a custom method, is a write.

A remote MCP connector's tool is tiered from the hints its own server declares. A read-only hint makes it a read. A hint saying it is not destructive makes it a write. A tool that declares neither, including one with no annotations at all, counts as destructive. So the cautious default applies on the remote MCP side; on the catalog side an unrecognized method lands as a write, not a delete.

The part reviewers most often get wrong: **over MCP there is no per-call approval prompt from Elaichi.** The scopes a person grants at consent time are the standing approval for that client session. One scope, `mcp:tools` ("Use your connected apps"), covers every tier of tool, deletes included. A separate scope, "Delete things," governs only Elaichi's *own* deletes, not deletes inside the connected app. Any per-call confirmation dialog an employee sees is their own AI client prompting them, not Elaichi.

To hold a client to read-only access, there are two generalizable routes. The person selects a toolbox of read-only tools at consent time, or an admin writes an explicit restriction blocking write and delete tools for that role. In Elaichi, a restriction targets a role or a single member, never a team, never the whole org. [Choosing between an allowlist and a blocklist](/blog/allowlist-vs-blocklist-mcp-tools/) covers which shape fits which app.

**One trap to test in any system:** an allow-rule that names zero tools or connectors frequently defaults to blocking *everything* for its target, rather than granting nothing additively. In Elaichi, an empty allow rule's own summary reads "Allows nothing. Every connector and tool is blocked." Confirm this behavior explicitly in whatever product you use. "Allow nothing" and "block everything" are not the same default in every system, and assuming the wrong one creates either a lockout or an open door.

## What is written to the log, and what is not?

**The question:** ask for a sample log record, not a feature bullet. Then ask specifically what does *not* get logged. The gaps matter more than the fields, because a reviewer who discovers an undocumented gap later stops trusting the rest of the log.

**Example implementation, Elaichi:** every connected-tool call that reaches execution [writes an audit row](/blog/which-tools-ai-agents-call/): one entry for each connected-tool call that reaches execution (a call refused earlier writes none). The `surface` field is one of console, api, mcp or app, and an MCP call additionally carries the calling client's id. Secret-shaped values are scrubbed from tool results via pattern matching before leaving Elaichi. It is a backstop, not a guarantee, since pattern-based scrubbing cannot catch every format.

Documented gaps, stated plainly rather than discovered later: a call refused *before* execution writes no row at all. That covers a tool withheld by a restriction, a missing scope, an unknown tool name or a rate limit. Neither a tools-list call nor a search call is logged as an audit entry. Argument values are not recorded, with one exception: the single URL-path argument that names the target object is kept as a `target_id`.

On client identity: a client name is shown as verified only when every non-loopback redirect address it registered maps to one known client. As of this writing, exactly seven clients are verified this way: Claude, ChatGPT, Cursor, Grok, Perplexity, Mistral and Devin. Any other client shows whatever name it self-registered, flagged "Name provided by the client itself." A logo on a consent screen proves nothing about who the app actually is. That generalizes: client-side branding in any OAuth consent flow is unauthenticated by default unless the platform does redirect-URI verification. [What an AI agent audit log has to capture](/blog/what-an-ai-audit-log-must-capture/) goes field by field.

Retention in Elaichi is 90 days by default. For longer retention, the log can be forwarded to your own SIEM or log store: export to your own Datadog comes with the Black plan, with Datadog as a delivery destination today.

## Where does the data travel during a call?

**The question:** draw the actual network legs a call takes, not the marketing diagram. Ask specifically where the credential is fetched, where the third-party call is made from, in which jurisdiction, and where the response gets handled.

**Example implementation, Elaichi:** for a catalog connector, the AI client calls Elaichi's endpoint. Elaichi fetches the account's credential from the credential service, applies it, and calls the third party from inside the organization's own region gateway. The third-party response is handled in that same region.

Elaichi offers three regions, EU, US and APAC, chosen at org creation and fixed afterward. For EU and US orgs, the primary data store is pinned to that jurisdiction. APAC is best-effort placement, not a contractual residency guarantee. Write that distinction down verbatim in your review notes rather than treating "available in APAC" as equivalent to "data stays in APAC."

Two exceptions belong in the review, not a footnote. Every organization's audit trail, whatever its chosen region, is stored in one log instance in the EU, stated in the [privacy policy](/privacy/), the [DPA](/dpa/) and the [GDPR page](/gdpr/). Files stored from tool results similarly go to one EU bucket for every organization. [The leg-by-leg EU residency walkthrough](/blog/eu-data-residency-ai-agents/) has the full map if cross-border audit storage is a blocker for your org.

**State this limit plainly, because it is the honest answer and it generalizes beyond this one product.** An MCP endpoint receives only tool names and arguments, never the user's original typed prompt. So it has no way to evaluate whether the *call* was the result of a prompt injection upstream in the client. Nothing on that path inspects for it, by design of what data reaches the endpoint. That work has to live in the client or model layer, not the gateway. If a vendor claims gateway-level prompt-injection defense at the MCP layer, ask exactly what signal they inspect to make that claim, since the raw prompt typically is not visible to them either.

## How is access cut off, and how fast?

**The question:** time each revocation path separately. "We support instant revocation" is frequently true for one path, an individual grant, and false for another, role changes propagating through a cache. A reviewer who does not separate these will write an incorrect incident-response runbook.

**Example implementation, Elaichi:**

Grant-level revocation is fast: removing or suspending a member revokes every live grant in the same transaction as the membership change. Elaichi re-reads the client's OAuth grant on every MCP request, so disconnecting fails the client's very next request with a 401. Removing or suspending a member revokes every live grant they hold, within the same call that removes the membership, so their clients stop at the next call. Reactivation does not restore old grants; the person has to consent again. In Elaichi, revoking a share or disconnecting an account takes effect on the caller's next call.

Role changes, team-membership changes and restriction changes are different. They resolve through a cache and take effect about two minutes. Put the real number in your runbook instead of assuming instant propagation. A gap here is where a just-demoted employee's AI assistant keeps working for longer than security assumes.

**SCIM is the path most reviewers get wrong, in any vendor's system, not just this one.** [SCIM (RFC 7644)](https://datatracker.ietf.org/doc/html/rfc7644) is how an identity provider pushes joiners and leavers to downstream apps. A SCIM deprovision event typically *suspends* a member. It does not delete the member row. Suspension revokes API tokens, grants and SCIM tokens, so MCP calls stop. But the person's owned resources and connections stay in place, and any transfer-or-delete decision about those resources only fires on an actual removal, not a suspension. Confirm this distinction explicitly with any vendor. Documentation sometimes says "deactivation removes membership" when the implementation actually suspends. Ask to see the behavior, not just the doc. [Where SCIM provisioning stops and MCP grants begin](/blog/identity-provider-scim-vs-mcp-grants/) is the longer version of this specific gap.

Two more checks to run before the person leaves, not after. A connection transferred at offboarding keeps acting in the third-party app as whoever was signed in when it was connected. That downstream app account needs deprovisioning on its own, separately from your IdP workflow. And any toolbox entries the departing member pinned for shared use stop resolving for everyone else until someone re-pins them. That is a small operational gap, but one that causes support tickets at exactly the wrong time.

## When this checklist is not the thing you need

If your problem is discovering MCP servers employees have already installed on their own laptops, none of the above helps. A gateway governs calls that route through its endpoint. Calls a client makes directly to a vendor's server never pass through it, and an MCP control plane is not a network traffic inspector looking for unapproved AI use. For that, you want endpoint detection tooling or network-level inspection: [finding the servers employees installed](/blog/find-mcp-servers-employees-installed/) is the practical next step for that specific problem.

If you have one team, one app and one assistant, you may not need a gateway or this checklist's full weight yet. [When you do not need an MCP gateway](/blog/when-you-dont-need-an-mcp-gateway/) lays out the honest case for waiting.

If the answer is to approve the server, the approval is worth more when every client lands at the same governed address rather than a different connector per assistant. Claude, ChatGPT, Cursor and Microsoft Copilot can all authenticate to the same Elaichi endpoint. So a connector approved once is governed identically, whichever client an employee picks. Browse the current catalog at [/connectors/](/connectors/), see how restriction rules are written in [MCP governance](/blog/mcp-governance/), or review team rollout patterns at [/use-cases/governance/](/use-cases/governance/).

## FAQ

### What should a CISO ask before approving an MCP server?

Seven questions: who authored the tools and who operates the server, how people sign in and who holds the app credential, whether each call runs as a named person or a shared account, which tools write or delete and what stands in front of them, what the audit log records and what it leaves out, where data travels during a call, and exactly how access is cut off. A server that cannot answer the identity question, where every employee's assistant shares one service account, should not be approved for data that matters.

### Does Elaichi ask for approval before an AI client deletes something in a connected app?

No. Over MCP there is no per-call approval step in Elaichi. The scopes a person grants on Elaichi's consent screen are the standing approval for that client, and the "Use your connected apps" box covers every tier of connected tool, deletes in the app included. Any confirmation prompt an employee sees comes from their own AI client. To hold a client to reads, pick toolboxes of read tools at consent, or write a restriction that blocks the write and delete tools for that role.

### How fast does revoking an employee's AI access actually take?

It depends on the path. Revoking an OAuth grant, removing or suspending a member, revoking a share and disconnecting an account all take effect on the client's next call, because Elaichi re-reads the grant on every request. Role changes, team-membership changes and restriction changes resolve through a cache and take effect about two minutes. A SCIM deprovision suspends a member rather than removing them, which stops their calls but leaves their resources in place.

### What does an Elaichi audit row record for an AI tool call, and what does it miss?

Each connected-tool call that reaches execution records the person, the toolbox, the tool's advertised and catalog names, the connector, the connection the call actually reached, the tool's classification, how approval was given, the surface it came from, the MCP client's id for MCP calls, and the outcome. It does not record argument values, apart from the single URL path argument that names the object, and it writes no row for a call refused before execution, such as one a restriction withheld or one missing a scope. Retention is 90 days.

### Who handles prompt injection when an AI client calls tools?

The AI client, not Elaichi. An MCP server never receives the person's typed prompt: it gets only a tool name and arguments written by the client's model, so it has nothing to judge a proposed call against. That is a structural limit rather than a gap to be filled later. Elaichi's in-app Agent, which comes with the Black plan and does see the person's typed request, runs a separate injection check of its own.

## Read next

- [Is Elaichi Secure? A Reviewer's Walkthrough](/blog/is-elaichi-secure-enough-for-enterprise-use/) — Is Elaichi secure: how sign-in, per-person grants, restrictions, the audit log and regions work, and where the MCP endpoint stops.
- [MCP restriction resolver precedence, as a decision tree](/blog/restriction-resolver-decision-tree/) — How the mcp restriction resolver precedence works across Elaichi's enforcement points, traced through one real tool call from browse to outbound request.
- [Which tools AI agents call: read the audit log](/blog/which-tools-ai-agents-call/) — One audit log across Claude, ChatGPT and Cursor records which tools AI agents call, naming the person, the client, the connector, the tool and the outcome.
