# What to require from an MCP server vendor: a buyer's checklist

October 24, 2026 · Part 1 of 4

![What to require from an MCP server vendor: a buyer's checklist. A blueprint drawing of a tall sheet with a column of check boxes standing beside a small server module.](https://pournasserian.com/_astro/lead.Bavunk-0_Z2coShU.webp)

A vendor's demo of a Model Context Protocol (MCP) server will show you an AI assistant calling its tools. That part always works in a demo. What I'd want to know before signing is everything the demo doesn't show: whether the server works without sessions, what it does with a token, how it behaves when a user cancels, and what evidence the vendor has that any of it holds. The 2026 specification is precise about most of this, which makes it a good basis for a list of requirements.

This is part 1 of a short series for the people who buy, approve and govern MCP servers rather than build them. It draws on the same facts as [my series for builders](https://pournasserian.com/writing/mcp-2026-what-a-server-does), under the [2026-07-28 specification](https://modelcontextprotocol.io/specification/2026-07-28/changelog), as I read them in October 2026, and leaves the detail to that series. 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. The AI application you use is the host. It creates one client for each server it connects to, and the model never talks to a server directly.

## In brief

1. **A compliant server is much more than a list of tools.** It describes itself, handles every request without a session, tells clients how long they may cache its answers, asks for missing input without blocking, and follows the transport rules. Most of these are MUSTs, so you can require each one by name.
2. **The security requirements can be written down.** A server that uses authorization is an OAuth 2.1 resource server: it validates every token, including who the token was issued for, and never forwards one. Every server MUST validate its inputs, rate-limit calls and sanitize its outputs.
3. **Operations have requirements of their own:** trace context continued when the client sends it, logging moved off a deprecated channel, and a short list of metrics the vendor should be able to show you.
4. **Ask for evidence rather than assurances:** the official conformance suite, tests against clients from both protocol eras, and tests in at least three hosts, one of them text-only.
5. **My advice: put the questions in writing and ask for the answers in writing.** The table at the end is meant to be forwarded.

## The protocol duties every server owes

The duties start with where a server sits. Your people talk to a host, the host's runtime holds the conversation and the approvals, and a client inside the host carries requests to the server, which reaches your systems. A server can be a local process on a laptop, over standard input and output (stdio), or a remote service over Streamable HTTP in front of your application programming interfaces (APIs) and databases.

```mermaid
flowchart TB
    user(["User"])
    subgraph host["Host application"]
        direction TB
        runtime["Host runtime<br/>conversation, approvals, UI"]
        llm["LLM"]
        client["MCP client, one per server"]
        runtime --- llm
        runtime --- client
    end
    server["MCP server<br/>local over stdio, or remote over Streamable HTTP"]
    data[("Your systems<br/>APIs, databases, files")]
    user --- runtime
    client -->|JSON-RPC| server
    server --> data
```

The 2026-07-28 revision made the protocol stateless: there is no handshake, no session and no way for a server to send a request to the client. That changes what you can require of a server. Here are the duties I'd put on the list, with the question each one turns into.

| Duty | What the specification says | What to ask |
|---|---|---|
| Discovery | Every server MUST implement [`server/discover`](https://modelcontextprotocol.io/specification/2026-07-28/server/discover), which advertises its protocol versions, capabilities and identity | Which protocol revisions does the server advertise? |
| Stateless requests | There are no sessions. The server reads the protocol version and the client's capabilities from each request, and every result carries a `resultType` (MUST) | Can any instance serve any request? Where does state that outlives a request live? |
| Caching hints | Complete results of discovery, the list methods and resource reads MUST carry `ttlMs` and `cacheScope` ([caching](https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching)) | What may be cached, for how long, and is anything cached across users that shouldn't be? |
| Transport | Over [Streamable HTTP](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http), `MCP-Protocol-Version` and `Mcp-Method` go on every request and `Mcp-Name` on tool calls, prompt requests and resource reads (MUST); a header that disagrees with the body is an error | Can our gateway apply policy per tool from those headers? |
| Asking for input | A server that needs more input returns an `input_required` result and the client retries with the answers ([Multi Round-Trip Requests](https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr), MRTR, the one way a server may ask); the state it hands back MUST be protected when it influences logic | Does the server do anything irreversible before the user's last answer? |
| Cancellation | On HTTP, a dropped connection is a cancellation (MUST) | What happens to work in flight when a user cancels? |
| Instructions | Optional: a paragraph of guidance the host may give the model | Can we read the instructions and every tool description before we connect? |

Two of the smaller rules are worth a line each. A server SHOULD return its tools in a deterministic order, which keeps the hosts' caches warm. And work that takes minutes rather than seconds belongs in the Tasks extension, where the server returns a task handle and the client polls, so nothing has to stay connected; under 2026-07-28 a dropped stream cancels the request and there is no resuming it.

## Security you can write into the contract

Authorization is OPTIONAL in the specification, so the first question is whether the server uses it at all. When it does, the rule depends on the transport: an HTTP-based server SHOULD follow the [MCP authorization specification](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization), and a local stdio server SHOULD NOT, taking its credentials from the environment instead. A remote server that uses authorization is an OAuth 2.1 resource server. It accepts and validates tokens; it doesn't issue them. Its duties:

- It MUST publish Protected Resource Metadata (Request for Comments, or RFC, 9728), the document that tells clients which authorization server issues its tokens and which scopes it supports.
- It MUST validate every token and check that the token was issued specifically for this server as its audience (RFC 8707), and return 401 for an invalid or expired one.
- It MUST only accept tokens valid for its own resources, and MUST NOT accept or transit any other token. When it calls a downstream API for the user, it gets a separate token for that API, through an on-behalf-of or token-exchange flow. Your token never travels on.
- It SHOULD name the scope the request needs in its 401 and 403 challenges, and when a valid token lacks a scope it SHOULD list every scope the operation needs in one challenge, so the client asks once. It MUST respect scope hierarchies.

Beyond authorization, the specification sets a baseline for every server. It MUST validate all tool inputs, implement access controls, rate-limit tool invocations, sanitize tool outputs, validate resource addresses and sanitize file paths, validate prompt inputs and outputs, treat the state it hands back in a round trip as attacker-controlled, and, under the Tasks extension, generate unguessable task IDs and authorize every task-related request.

My own additions are about text, because everything the model reads can steer it. Tool descriptions and instructions should be factual, with nothing that reads like "always use this server"; hosts and reviewers distrust that. Read tools should be separate from write tools, so a host can approve reads quietly and confirm writes. And no secret belongs in a skill, an instruction or a parameter mirrored into a header.

Put together, the controls form layers around every call, and a vendor should be able to say what sits at each one:

```mermaid
flowchart TB
    req(["tools/call"])
    l1["Edge<br/>WAF, rate limits,<br/>Mcp-Method / Mcp-Name policy"]
    l2["Authentication<br/>token signature, issuer,<br/>audience, expiry"]
    l3["Authorization<br/>scopes, per-tool policy,<br/>handle ownership"]
    l4["Input validation<br/>schema, ranges, allowlists,<br/>path sanitizing"]
    l5["Execution<br/>least-privilege delegated credentials,<br/>timeouts, quotas"]
    l6["Output<br/>size caps, sanitization,<br/>untrusted-content marking"]
    l7["Audit<br/>trace, log caller, tool,<br/>arguments hash, outcome"]
    res(["Result"])
    req --> l1 --> l2 --> l3 --> l4 --> l5 --> l6 --> l7 --> res
```

## Operations and evidence

A server you can't observe is a server you can't support. When a client sends OpenTelemetry trace context in a request (`traceparent`, `tracestate` and `baggage`, standardized by [SEP-414](https://modelcontextprotocol.io/seps/414-request-meta)), the server continues the trace and passes it on to everything it calls, so one trace runs from your assistant to your data. That's a convention rather than a MUST, and one caveat goes with it: `baggage` comes from the client and must never decide authorization or which tenant's data is read. MCP's own logging channel is deprecated, so logs belong on `stderr` for a local server or in OpenTelemetry for a remote one.

These are the metrics I'd ask a vendor to show, and why:

| Signal | Why you'd ask for it |
|---|---|
| Latency per method and tool, at the median and the tails | Slow tools hit the hosts' timeouts before anyone notices |
| Error rate per tool, split into tool errors and protocol errors | Tool errors show the model misusing a tool or a backend failing; a spike in protocol errors often means a schema change broke clients |
| Rate of `input_required` results per tool | A high rate suggests the tool doesn't ask for what it needs |
| Cancellations and client disconnects | Streams cut by intermediaries show up here first |
| Output size per tool | Hosts cap what a tool may return |
| Calls by client name and version | Which hosts use the server, and where host-specific bugs live |

For evidence, I'd ask what the vendor's build pipeline checks before a release. MCP has artifacts of its own, from tool schemas to skill files, and each has rules a machine can test:

```mermaid
flowchart TB
    src["Source repo<br/>code, skills, UI, prompts"]
    lint["Lint and validate<br/>tool schemas, names,<br/>header rules, skill front matter"]
    build["Build<br/>bundle the UI,<br/>normalize skill bytes,<br/>compute digests"]
    test["Test<br/>conformance suite,<br/>fake-host integration test,<br/>both protocol eras"]
    pkg["Package<br/>container image or package"]
    deploy["Deploy<br/>blue/green, stateless"]
    src --> lint --> build --> test --> pkg --> deploy
```

The tests I'd want named are the official MCP conformance suite, which [my review of MCP testing tools](https://pournasserian.com/writing/mcp-server-testing-tools-2026) records as carrying per-revision requirement sets for 2025-11-25 and 2026-07-28; an integration test against a fake host that records every message; and tests against one client from each protocol era. Beyond those, my advice is to require tests in at least three hosts, one of them text-only, because a tool whose answer is only useful as an interactive interface isn't finished.

Both eras matter because hosts adopt protocol revisions at very different speeds. A server that only speaks 2026-07-28 will look broken in any host that hasn't caught up, and a server that only speaks the older handshake can't serve the hosts that have. The clean approach, which several software development kits (SDKs) take, is to decide the era per request. Ask which era each of your hosts speaks; as of October 2026, Claude Code is the only one of the seven hosts I compared that is confirmed to use 2026-07-28.

## The questions, on one page

Here is the list I'd send. The last column says whether the basis is the specification or my advice.

| # | Question | A good answer | Basis |
|---|---|---|---|
| 1 | Which protocol revisions does the server serve? | Both the handshake era and the stateless era, decided per request, with `server/discover` implemented | MUST for discovery; the rest my advice |
| 2 | Where does state live between requests? | Nowhere in the connection: explicit handles in a shared store, checked against the caller on every call | The specification removed sessions |
| 3 | Does the server use authorization, and as what? | Over HTTP, as an OAuth 2.1 resource server that publishes Protected Resource Metadata; locally, credentials from the environment | SHOULD, SHOULD NOT and MUST |
| 4 | What does the server do with our tokens? | Validates signature, issuer, audience and expiry; forwards none; gets a separate token for each downstream API | MUST and MUST NOT |
| 5 | Which scopes does it ask for? | The smallest set that works, then step-up, naming every missing scope in one challenge | SHOULD |
| 6 | What is validated and limited? | All inputs, resource paths and prompt arguments; rate limits per caller; output sizes capped and outputs sanitized | MUST |
| 7 | Can we read every tool description and the instructions before we connect? | Yes; they're factual, versioned, and changes are announced | My advice |
| 8 | Does the server do anything irreversible before the user's last answer? | No | My advice |
| 9 | What happens when a user cancels or a connection drops? | A dropped HTTP connection cancels the request; long work runs as a task that survives it | MUST; the Tasks extension |
| 10 | How is the server observed? | It continues our trace context, exposes the metrics above, and logs off the deprecated channel | A convention; my advice |
| 11 | Which tests does it pass? | The official conformance suite for both revisions, a fake-host integration test, and tests in three hosts including a text-only one | My advice |
| 12 | Which deprecated features does it still use? | A named list, with the date each one may be removed, and none adopted since | The specification's feature lifecycle |

## Method and caveats

- Built from my guide to MCP servers, written against the 2026-07-28 specification, and reframed for the people who buy and approve servers. The builder series carries the detail behind each row; product facts are as of October 2026.
- The MUST, SHOULD and MUST NOT marks are the specification's. The questions, the "good answers", the metrics and the three-host test are my advice.
- Everything here is framed from the specification. It describes no particular vendor, product or deployment.
