Community-maintained FDE reference. Not an official Vercel or Anthropic project. About this project
Capability primitives
Deprecation notice (SEP-2577). The Roots, Sampling, and Logging features are deprecated as of the 2026-07-28 revision. They remain fully functional for at least a twelve-month window and are documented below because you will meet them in deployed servers, but new implementations should not adopt them. Suggested migrations: pass directories or files via tool parameters, resource URIs, or server configuration instead of roots; integrate directly with LLM provider APIs instead of sampling (on Vercel, that is the AI SDK or AI Gateway); log to
stderr(stdio) or use OpenTelemetry instead of MCP logging. See the deprecated features registry.
Plain-language explanation
TL;DR: MCP exposes three core building blocks (tools, resources, and prompts) and a set of auxiliary ones (sampling, elicitation, progress, cancellation, logging, roots, completions). Each primitive is controlled by a different actor: the model picks tools, the application picks resources, the user picks prompts, and the host mediates everything else. As of 2026-07-28, the server-initiated primitives no longer arrive as server requests: a server that needs model inference or user input returns an input_required result, and the client retries the original request with the answers attached (the MRTR pattern).
SDK status. Wire status: the pinned stack (
mcp-handler2.1.1 on@modelcontextprotocol/server2.0.0) serves the 2026-07-28 contract natively over Streamable HTTP and falls back to stateless 2025-11-25 Streamable HTTP for legacy clients; the SDKClientdefaults to that legacy handshake unless you opt in to modern version negotiation, so the examples’ in-memory test suites exercise only the legacy path.
The easiest way to remember the primitives is “who is in charge of pulling the trigger.” A tool is an action the AI model can choose to invoke (“create issue,” “send email”), so the model is in control, but the host must gate it with user consent. A resource is a piece of context (a file, a row, a snapshot) that the application or user attaches to the model’s context window; the model never reaches for resources on its own. A prompt is a reusable template the user explicitly chooses from a menu, like “Summarize this PR.” The remaining primitives are smaller and compose with the core three to handle long-running work, isolation, and user assistance.
The rule of thumb most teams remember: tools are verbs, resources are nouns, prompts are templates. Auxiliary primitives are protocol plumbing that makes the core three usable in real applications. On Vercel, all of them travel over the Streamable HTTP transport, and 2026-07-28 fits them to the platform: nothing a server needs from the client outlives the current request’s response stream, because what used to be a server-initiated request is now just a result asking for a retry with more input. Serverless sessions explains why that shape matters here.
| Primitive | Controlled by | Declared via | Typical use |
|---|---|---|---|
| Tools | Model | Server capability, listed by tools/list | Side-effectful actions the model decides to take |
| Resources | Application or user | Server capability, listed by resources/list, resources/templates/list | Read-only context the host attaches to the model |
| Prompts | User | Server capability, listed by prompts/list | Saved, parameterized message templates the user picks |
| Sampling (deprecated) | Server (requests via MRTR); client (fulfills on retry) | sampling in per-request client capabilities | Server asks the client to run model inference |
| Elicitation | Server (requests via MRTR); client (fulfills on retry) | elicitation in per-request client capabilities | Server asks the user for structured input via the client |
| Progress | Server | Inline on existing requests | Long-running tool or read reports incremental status |
| Cancellation | Either side | Stream close (HTTP) or notification (stdio) | Aborting work that is no longer needed |
| Logging (deprecated) | Server | Per-request logLevel in _meta | Server emits structured logs scoped to a request |
| Roots (deprecated) | Client | roots in per-request client capabilities; server asks via MRTR | Client declares which file:// roots are in bounds |
| Completions | Server | Server capability flag | Argument autocompletion for prompts and resource templates |
Formal protocol perspective
The MCP specification splits primitives into server features (tools, resources, prompts, completions, logging) and client features (sampling, roots, elicitation), with progress and cancellation as cross-cutting patterns defined under the base protocol. Each feature is gated by a capability declaration, and with the initialize handshake gone, the declaration is per request: clients list the relevant capabilities in _meta (io.modelcontextprotocol/clientCapabilities) on every request, servers advertise theirs via the mandatory server/discover RPC, and a server MUST NOT rely on a capability the current request did not declare (violations get MissingRequiredClientCapabilityError, -32021). Optional protocol extensions, including the tasks extension (io.modelcontextprotocol/tasks), are negotiated through the extensions map both capability objects gained in this revision. Every result also carries a required resultType: "complete" for final results, "input_required" for MRTR interim results, and clients MUST treat an absent resultType from earlier-protocol servers as "complete".
Tools are defined in the spec’s Tools section. The server MUST declare the tools capability, and exposes tools/list (paginated, with an optional cursor) and tools/call. Each tool has a name, a description, an inputSchema (JSON Schema), an optional outputSchema, optional annotations such as readOnlyHint or destructiveHint (which clients MUST treat as untrusted unless the server is trusted), and optional icons metadata. JSON Schema 2020-12 remains the default dialect, and 2026-07-28 loosens the rules (SEP-2106): inputSchema and outputSchema may use any JSON Schema 2020-12 keywords, structuredContent may be any JSON value, network $refs MUST NOT be auto-dereferenced, and validators SHOULD bound composition-keyword cost. Schema properties may carry an x-mcp-header annotation to mirror an argument into an Mcp-Param-{Name} HTTP header for edge routing (SEP-2243). Two more 2026-07-28 obligations: servers SHOULD return tools in deterministic order (client caching, LLM prompt-cache hit rates), and tools/list results MUST carry ttlMs and cacheScope ("public"/"private") freshness hints via the CacheableResult interface (SEP-2549). Call results carry an unstructured content array whose items may be text, image, audio, resource links, or embedded resources, plus optional structuredContent and an isError flag defaulting to false. The error-channel line (SEP-1303) is unchanged and the tooling finally agrees with it: input-validation and business-logic failures are tool execution errors, returned as a normal result with isError: true so the model can read the feedback and self-correct, while unknown tools and malformed requests are JSON-RPC protocol errors (the spec’s example uses -32602 for an unknown tool). The TypeScript SDK v2 (2.0.0) now matches the spec here: unknown tool names are rejected as protocol errors, no longer returned as isError results the way SDK 1.x did. The server may emit notifications/tools/list_changed, delivered only on a subscriptions/listen stream the client opened with toolsListChanged: true.
Resources are defined in the Resources section. The server exposes resources/list for concrete URIs, resources/templates/list for resource templates (URI patterns with {placeholders}), and resources/read to fetch contents; all of these results MUST carry ttlMs/cacheScope. Reading a missing resource returns -32602 (Invalid params); the old -32002 code is retired in this revision, though clients SHOULD still accept it from older servers. The 2025-11-25 resources/subscribe and resources/unsubscribe RPCs are gone: a client that wants per-URI updates lists the URIs in the resourceSubscriptions filter of a subscriptions/listen request and receives notifications/resources/updated (tagged with io.modelcontextprotocol/subscriptionId) on that stream; notifications/resources/list_changed signals catalog-level changes the same way. On a serverless deployment, a long-lived listen stream lives inside one function invocation’s maxDuration budget; that constraint and its workarounds are covered in serverless sessions.
Prompts are defined in the Prompts section. The server exposes prompts/list (also a CacheableResult) and prompts/get. A prompt definition includes a name, a description, a list of arguments (each with a description and a required flag), and optional icons. prompts/get returns a messages array the host can hand to the model verbatim or splice into a larger conversation.
Sampling (deprecated, SEP-2577) is defined in the Sampling section of client features. The server no longer sends sampling/createMessage as its own request. When a tool call (or resources/read or prompts/get) needs a model completion, the server returns an InputRequiredResult whose inputRequests map contains a CreateMessageRequest; the client fulfills it, keeping control over model access and a human in the loop: it surfaces the request to the user, may edit or decline it, and retries the original request with the completion in inputResponses. Sampling requests may still carry tools and a toolChoice directive (SEP-1577) when the client declares sampling.tools; the client still mediates, so the trust boundary is unchanged. The includeContext values "thisServer" and "allServers" are deprecated (SEP-2596): omit the field or use "none".
Elicitation is defined in the Elicitation section of client features, in two modes declared as sub-capabilities (elicitation: { form: {}, url: {} }; an empty object means form-only for backwards compatibility). Like sampling, it is delivered through MRTR: the server returns an InputRequiredResult containing an elicitation/create input request, and the client answers on the retry. Form mode supplies a requestedSchema: a flat object of primitive-typed fields only, where enums may be titled or untitled and single-select or multi-select, and string, number, and enum fields may declare default values. URL mode hands the user off to a URL for out-of-band flows such as third-party authorization. The 2025-11-25 correlation machinery (elicitationId, notifications/elicitation/complete, and the -32042 URLElicitationRequiredError) is removed in this revision: the client learns the outcome by retrying the original request, and a server that needs to correlate across retries encodes its own identifier in the opaque requestState field. The two modes keep their hard security split: servers MUST NOT request secrets such as passwords, API keys, or payment credentials through form mode, and MUST use URL mode for those, precisely so sensitive data never transits the client or the model context. The ElicitResult in either mode carries an action of accept, decline, or cancel.
Progress and cancellation are defined as base-protocol patterns. Progress is notifications/progress, sent on the originating request’s response stream and tagged with a progressToken from that request’s _meta. Cancellation is transport-shaped in 2026-07-28: on Streamable HTTP, the client closes the request’s SSE response stream and the server MUST treat that as cancellation; the notifications/cancelled message survives only on stdio, where there is no per-request stream to close. Both are best-effort.
Logging (deprecated, SEP-2577) is defined in the Logging utility. logging/setLevel is removed: verbosity is now opt-in per request via io.modelcontextprotocol/logLevel in _meta, and servers MUST NOT emit notifications/message for requests that did not include it. Emitted messages carry level, logger, and data, and flow only on the response stream of the request that opted in. Do not confuse this with Vercel runtime logs: MCP logging flows to the connected host, while console.log flows to your Vercel dashboard and log drains. The migration path (OpenTelemetry, whose traceparent/tracestate/baggage keys are now reserved in _meta) is the direction of travel; see Observability.
Roots (deprecated, SEP-2577) are defined in the Roots section of client features. The client declares the roots capability per request; a server that wants the list returns an InputRequiredResult containing a roots/list input request and receives the roots in inputResponses on the retry. notifications/roots/list_changed is removed. Each root URI MUST be a file:// URI. Roots describe the host’s local filesystem, so for a deployed Vercel server they are usually irrelevant context; the deprecation migration (pass directories via tool parameters, resource URIs, or server config) is what most servers did anyway.
Completions are defined in the Completion utility. The client calls completion/complete with a reference to a prompt or a resource template plus the partial argument; the server returns ranked candidates with pagination metadata.
In this repo’s examples, all of these register through an exported configureServer(server) function using the TypeScript SDK, keeping the protocol surface separate from the Next.js route shell; the pages stay implementation-agnostic and the examples carry the code.
Request / lifecycle flow
The three core primitives and the actor in charge of each, with the auxiliary primitives shown as supporting flows:
Diagram source (Mermaid)
flowchart LR
Model([Model]) -->|invokes| Tools[Tools]
App([Application/Host]) -->|attaches| Resources[Resources]
User([User]) -->|selects| Prompts[Prompts]
Tools --> Server[(Server)]
Resources --> Server
Prompts --> Server
Server -.->|input_required results carrying sampling, elicitation, roots requests| Host[(Host)]
Host -.->|retries with inputResponses, completions, stream-close cancellation| ServerSolid arrows are the primary trigger path for the three core primitives. Dashed arrows show the auxiliary loop that replaced server-initiated requests: the server hands back an input_required result naming what it needs (a model completion, user input, the roots list), and the host retries the original request carrying the answers. Progress and log notifications still ride the SSE response stream of the request that triggered them, which is why they are bounded by that invocation’s lifetime on Vercel; standing change notifications ride a subscriptions/listen stream instead.
Key messages / state transitions
tools/list- client to server, request. Returns{ tools: [...], nextCursor?, resultType: "complete", ttlMs, cacheScope }. Servers SHOULD order tools deterministically. Re-issued afternotifications/tools/list_changedor whenttlMslapses.tools/call- client to server, request. Fields:name,arguments. Returns{ resultType: "complete", content: [...], structuredContent?, isError? }, wherecontentis the unstructured array (text, image, audio, resource link, embedded resource),structuredContentmatches the tool’s optionaloutputSchema, andisErrordefaults tofalse. Input-validation failures come back asisError: trueresults (SEP-1303), not protocol errors, so the model can self-correct; unknown tool names are protocol errors. May instead returnresultType: "input_required"(see MRTR below).resources/list/resources/templates/list- client to server, requests. Return concrete URIs and URI templates respectively, withttlMs/cacheScope.resources/read- client to server, request. Field:uri. Returns{ contents: [...], resultType, ttlMs, cacheScope }. Unknown URI: error-32602.subscriptions/listen- client to server, request. Params: anotificationsfilter (toolsListChanged,promptsListChanged,resourcesListChanged,resourceSubscriptions: [uris]). The response stream opens withnotifications/subscriptions/acknowledgedand then carries only the opted-in types, each tagged withio.modelcontextprotocol/subscriptionId. Replacesresources/subscribe/resources/unsubscribeand the GET stream.notifications/resources/updated- server to client, notification on a listen stream. Fields:uri, plus the subscription id in_meta.prompts/list- client to server, request. Returns prompt metadata withttlMs/cacheScope.prompts/get- client to server, request. Fields:name,arguments. Returns{ messages: [...] }.- MRTR interim result - server to client, response to
tools/call,resources/read, orprompts/getonly. Shape:{ resultType: "input_required", inputRequests?, requestState? }, whereinputRequestsmaps server-chosen keys toElicitRequest,CreateMessageRequest, orListRootsRequestobjects, andrequestStateis an opaque string the client MUST echo unmodified. At least one of the two fields is always present. - MRTR retry - client to server: the original request re-sent with a new JSON-RPC id, plus
inputResponses(keyed to matchinputRequests) and the echoedrequestState. elicitation/create(insideinputRequests) - form mode:messageplusrequestedSchema(flat, primitive-typed fields; enums titled or untitled, single- or multi-select; optional defaults);modedefaults to"form". URL mode:mode: "url",message,url. TheElicitResultininputResponsesis{ action, content? }withactionone ofaccept,decline,cancel; URL-mode accepts omitcontent.sampling/createMessage(insideinputRequests) - fields:messages,modelPreferences?,systemPrompt?,maxTokens, optionaltools?plustoolChoice?. TheCreateMessageResultininputResponsescarries the completion.roots/list(insideinputRequests) - no fields. The result ininputResponsescarries the client’sfile://roots.notifications/progress- server to client, notification on the originating request’s response stream. Fields:progressToken,progress, optionaltotal.- Cancellation - client to server. Streamable HTTP: close the request’s SSE response stream. stdio:
notifications/cancelledwithrequestId, optionalreason. notifications/message- server to client, notification on the response stream of a request whose_metaincludedio.modelcontextprotocol/logLevel. Fields:level,logger?,data.completion/complete- client to server, request. Fields:ref(prompt or template),argument. Returns ranked candidates.- Removed in 2026-07-28 -
logging/setLevel,notifications/roots/list_changed,resources/subscribe,resources/unsubscribe,notifications/elicitation/complete, theelicitationIdfield, andping.
Common misconceptions
- Misconception: The model picks resources the way it picks tools. Reality: Resources are application-controlled. The host or the user decides which resources the model sees; the model has no
resources/readcapability of its own. See the spec’s Resources section. - Misconception: A tool with
readOnlyHint: trueis safe to auto-approve. Reality: Annotations are non-binding self-descriptions, and the spec says clients MUST treat them as untrusted unless the server is trusted. Consent decisions remain a host responsibility. The query-vs-command pattern shows what annotations are actually for. - Misconception: Prompts are system prompts. Reality: Prompts are user-invoked templates returned to the host as a message list. They are not injected silently; the user explicitly selects them.
- Misconception: Sampling lets a server use its own model. Reality: Sampling is the reverse: the server asks the host to run inference on its behalf, now by returning an
input_requiredresult rather than sending a request. The host may decline, and since the feature is deprecated, new servers should call provider APIs directly instead. - Misconception: The server pushes elicitation and sampling requests to the client mid-call. Reality: Not since 2025-11-25. Under MRTR the server returns instead of asks: the tool call ends with
resultType: "input_required", and a second, independent tool call carries the answers. Nothing is in flight while the user thinks. - Misconception: Form-mode elicitation is fine for collecting an API key, since the user typed it willingly. Reality: The spec forbids it. Servers MUST NOT request credentials or payment details through form mode and MUST use URL mode, which keeps the secret out of the client, the model context, and every log in between.
- Misconception: Cancellation guarantees the work stops. Reality: Cancellation is best-effort. The receiver may have already completed the request, and side effects already executed are not rolled back. On Streamable HTTP the cancellation signal is simply closing the response stream.
- Misconception: Roots are enforced by MCP. Reality: Roots are a declaration the client makes; enforcement is a server-implementation responsibility. Treat roots as guidance, and back it with real isolation (for untrusted work on Vercel, that is Sandbox) if it matters. The feature is deprecated; prefer explicit tool parameters.
- Misconception: Completions are autocomplete for tool arguments. Reality:
completion/completeis scoped to prompts and resource templates only; tool-argument completion remains out of scope in 2026-07-28.
Debugging notes
- Symptom:
tools/listreturns nothing even though the server clearly registers tools. Likely cause: the tools are registered after the request is served, or the server does not advertise thetoolscapability. Where to look: thecapabilitiesobject in theserver/discoverresult; with the SDK, confirm the tools are registered insideconfigureServerbefore the handler is built. - Symptom:
client.callTool()behavior changed between SDK majors for a tool name that does not exist. Likely cause: nothing is wrong; SDK 2.0.0 rejects unknown tool names with a protocol error (matching the spec), where SDK 1.x returnedisError: trueresults. Schema-invalid arguments on a known tool still come back asisError: trueresults in both. Where to look: assert a rejection for unknown names andresult.isError === truefor invalid arguments in your vitest suites. See Testing. - Symptom: a watched resource never fires
notifications/resources/updated. Likely cause: the URI was not in theresourceSubscriptionsfilter of thesubscriptions/listenrequest, or the server’s acknowledgment silently omitted a notification type it does not support. Where to look: thenotifications/subscriptions/acknowledgedframe first (it echoes the subset the server agreed to honor), then serverless sessions for how long a listen stream can actually live on a function. - Symptom: a tool call keeps returning
resultType: "input_required"in a loop. Likely cause: the retry is missing some of the requestedinputResponses, so the server keeps re-asking (the spec tells it to re-request rather than error), or the client mutatedrequestStateand the server rejected it. Where to look: key-by-key equality betweeninputRequestsand the retry’sinputResponses, and byte equality ofrequestStateacross the round trip. - Symptom:
-32021errors on tool calls that use elicitation or sampling. Likely cause: the client did not declare the corresponding capability inio.modelcontextprotocol/clientCapabilitieson that request; per-request declaration means a capability declared on one call does not carry to the next. Where to look: the_metaof the exact failing request. - Symptom: progress notifications never reach the host from the deployed server. Likely cause: there was no
progressTokenin the originating request’s_meta, or the notifications were emitted after the tool result was already sent, when the stream is gone. Where to look: the_metaof the originating request, and the ordering of emits relative to the returned result. - Symptom: no log messages arrive even though the server calls the logging API. Likely cause: the request’s
_metadid not includeio.modelcontextprotocol/logLevel; servers MUST NOT emitnotifications/messagewithout it. Where to look: the request_meta, then remember the feature is deprecated and consider OpenTelemetry. - Useful observability hooks: per-primitive counters (
tools/callinvocations,resources/readreads, prompt selections), latency histograms per tool name, a counter ofinput_requiredresults and how many retries resolve them, and a count of-32021capability rejections; that last one is a misbehaving-or-compromised-peer detector. See Observability.
Security implications
Each primitive crosses a different trust boundary, and the right control lives at a different layer. The security checklist has the full inventory; the per-primitive shape:
Tools are the highest-risk primitive because the model decides when to invoke them. The host must implement consent: at minimum a confirmation surface for first use and for anything flagged destructiveHint, remembering the flags are advisory. The server MUST validate all tool inputs and sanitize outputs regardless of what the client checked, because on Vercel your endpoint is reachable by any client, not just well-behaved ones. Parameters mirrored into Mcp-Param-* headers via x-mcp-header are visible to every intermediary; never annotate sensitive fields. See the security checklist.
Resources look innocuous because they are read-only, but they are the most common vector for prompt injection: content fetched from a server becomes part of the model’s context. Treat resource contents as untrusted network input, even from your own deployment. A subscriptions/listen stream with auto-refresh creates an attacker-driven push channel into the model’s context; subscribe deliberately, and respect cacheScope: "private" when anything user-specific could otherwise land in a shared cache.
Prompts are user-controlled and therefore lower risk, but a server can still smuggle instructions into the returned messages array. Render prompt previews before sending to the model, and never auto-execute a prompt without the user’s explicit selection.
Sampling (deprecated) inverts the usual direction: the server is asking to use the host’s model, and the host’s token budget. The consent gate now lives at input_required handling: inspect the embedded CreateMessageRequest, cap maxTokens, let the user edit or decline, and only then retry. With tool calling inside sampling, the client also decides which tools the sampled completion may see; expose the minimum.
Elicitation is where users hand data to servers, so the mode split is the control: secrets go through URL mode only, and clients MUST show the full URL and get explicit consent before opening it, without prefetching. The requestState blob that correlates an elicitation across retries passes through the client, so the spec is blunt: servers MUST treat it as attacker-controlled input and integrity-protect it (HMAC or AEAD) whenever it influences authorization, resource access, or business logic, binding it to the verified principal with a short TTL. A server running elicitation-driven flows on Vercel MUST bind the resulting state to the verified user identity from authorization; Identity and principals explains why that distinction is load-bearing on a multi-tenant deployment.
Roots (deprecated) are an isolation hint, not an enforcement mechanism; if isolation matters, use real sandboxing. Logging (deprecated) can exfiltrate sensitive data twice on Vercel: once through notifications/message into the host, and once through runtime logs into your log drains; scrub both paths. Completions are low-risk but still let a server influence what the user types; treat candidates as suggestions, not assertions.
Runnable example
The resources-server example exercises the resource primitive end-to-end, including list, read, and templates:
- Example:
examples/resources-server(in the repository)
Run it and watch how resources/list returns concrete URIs while resources/templates/list returns parameterized patterns, and how a resources/read of a templated URI resolves. For the input-loop primitives, examples/sampling-server (in the repository) and examples/elicitation-server (in the repository) drive sampling and elicitation against an in-memory client whose handlers you control; observe that the server receives an accept, decline, or cancel and handles each distinctly. Note that the examples exercise the SDK’s current client-callback API rather than raw MRTR frames, and the sampling example carries its own deprecation banner.
Related
- MCP internals overview - the stateless per-request model these primitives ride on.
- Transports - how results, streams, and
subscriptions/listenare actually delivered over Streamable HTTP. - Serverless sessions - why long-lived streams and cross-request state need a home outside the function instance.
- Tasks - the official extension for work that outlives a request.
- Query vs command - tool annotations put to honest work.
- Client-side elicitation - the host’s obligations for form and URL mode.
- Sampling request handling - the host-side consent gate, now at
input_requiredhandling.
Bibliography
- Model Context Protocol Specification, Tools, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/tools
- Model Context Protocol Specification, Resources, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/resources
- Model Context Protocol Specification, Prompts, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/prompts
- Model Context Protocol Specification, Multi Round-Trip Requests, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr
- Model Context Protocol Specification, Subscriptions, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions
- Model Context Protocol Specification, Caching, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching
- Model Context Protocol Specification, Completion, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/completion
- Model Context Protocol Specification, Logging, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/logging
- Model Context Protocol Specification, Sampling, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/client/sampling
- Model Context Protocol Specification, Roots, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/client/roots
- Model Context Protocol Specification, Elicitation, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/client/elicitation
- Model Context Protocol Specification, Progress, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/progress
- Model Context Protocol Specification, Cancellation, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/cancellation
- Model Context Protocol Specification, Deprecated Features, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/deprecated
- Model Context Protocol, Security Best Practices - https://modelcontextprotocol.io/docs/2026-07-28/tutorials/security/security_best_practices
- JSON-RPC 2.0 Specification - https://www.jsonrpc.org/specification
- Model Context Protocol, official site - https://modelcontextprotocol.io