ExMCP.Types.V20260728 (ex_mcp v1.0.0-rc.8)

Copy Markdown View Source

Type definitions for MCP protocol version 2026-07-28.

This revision is a breaking, stateless protocol era. These types describe its wire surface. Runtime support is selected through the dual-era protocol modes, and rc.6 defaults new connections to :prefer_modern.

Important changes represented here include per-request protocol metadata, typed result envelopes, discovery, caching hints, subscriptions, and multi-round-trip input requests.

Summary

Types

A complete result with mandatory client-side caching hints.

A modern tool result whose structured content may be any JSON value.

Parameters for cooperatively cancelling one task.

Capabilities declared by a modern client on each request.

A server-directed task handle returned instead of an immediate result.

Full task state embedded in tasks/get and notifications/tasks.

The result of server/discover.

Parameters for idempotently reading one task.

A complete result returned by tasks/get.

A JSON-RPC header/body mismatch response (-32020).

Client or server implementation identity.

A server-initiated request embedded in an MRTR result.

Server-assigned input IDs mapped to requests.

An interim result requesting additional client input.

A client result satisfying one server-initiated MRTR request.

Retry fields accepted on client-initiated requests after an MRTR result.

Server-assigned input IDs mapped to client results.

A JSON object with string keys.

Any JSON Schema 2020-12 object, including extension keywords.

A value representable in JSON.

An extensible MCP _meta object.

A missing per-request client capability response (-32021).

Metadata carried by notifications, including subscription correlation.

The numeric elicitation schema from the 2026-07-28 generator.

Metadata required on every modern request.

Common fields present on every modern result.

Metadata carried by results.

A recognized or negotiated extension result discriminator.

Capabilities returned by a modern server from server/discover.

Notification categories selected by subscriptions/listen.

A request that opens a long-lived notification stream.

Parameters for subscriptions/listen.

The graceful close result for subscriptions/listen.

Metadata on the graceful close result of a subscription stream.

Fields common to task handles and detailed task state.

Lifecycle state of a task in the official Tasks extension.

A tool definition using unrestricted JSON Schema 2020-12 objects.

An unsupported protocol version response (-32022).

Parameters for submitting responses to outstanding task inputs.

Functions

Returns the protocol version described by this module.

Types

cacheable_result()

@type cacheable_result() :: %{
  :resultType => result_type(),
  :ttlMs => non_neg_integer(),
  :cacheScope => :public | :private,
  optional(:_meta) => result_meta_object(),
  optional(atom() | String.t()) => any()
}

A complete result with mandatory client-side caching hints.

call_tool_result()

@type call_tool_result() :: %{
  :resultType => result_type(),
  :content => [ExMCP.Types.content()],
  optional(:structuredContent) => json_value(),
  optional(:isError) => boolean(),
  optional(:_meta) => result_meta_object()
}

A modern tool result whose structured content may be any JSON value.

cancel_task_request_params()

@type cancel_task_request_params() :: %{
  _meta: request_meta_object(),
  taskId: String.t()
}

Parameters for cooperatively cancelling one task.

client_capabilities()

@type client_capabilities() :: %{
  optional(:experimental) => %{optional(String.t()) => json_object()},
  optional(:roots) => %{},
  optional(:sampling) => %{
    optional(:context) => json_object(),
    optional(:tools) => json_object()
  },
  optional(:elicitation) => %{
    optional(:form) => json_object(),
    optional(:url) => json_object()
  },
  optional(:extensions) => %{optional(String.t()) => json_object()}
}

Capabilities declared by a modern client on each request.

create_task_result()

@type create_task_result() :: %{
  :resultType => :task,
  :taskId => String.t(),
  :status => task_status(),
  :createdAt => String.t(),
  :lastUpdatedAt => String.t(),
  :ttlMs => non_neg_integer(),
  optional(:pollIntervalMs) => non_neg_integer(),
  optional(:statusMessage) => String.t(),
  optional(:_meta) => result_meta_object()
}

A server-directed task handle returned instead of an immediate result.

detailed_task()

@type detailed_task() :: %{
  :taskId => String.t(),
  :status => task_status(),
  :createdAt => String.t(),
  :lastUpdatedAt => String.t(),
  :ttlMs => non_neg_integer(),
  optional(:pollIntervalMs) => non_neg_integer(),
  optional(:statusMessage) => String.t(),
  optional(:inputRequests) => input_requests(),
  optional(:result) => json_object(),
  optional(:error) => json_object()
}

Full task state embedded in tasks/get and notifications/tasks.

discover_result()

@type discover_result() :: %{
  :resultType => result_type(),
  :ttlMs => non_neg_integer(),
  :cacheScope => :public | :private,
  :supportedVersions => [String.t()],
  :capabilities => server_capabilities(),
  optional(:instructions) => String.t(),
  optional(:_meta) => result_meta_object()
}

The result of server/discover.

get_task_request_params()

@type get_task_request_params() :: %{_meta: request_meta_object(), taskId: String.t()}

Parameters for idempotently reading one task.

get_task_result()

@type get_task_result() :: %{
  :resultType => :complete,
  :taskId => String.t(),
  :status => task_status(),
  :createdAt => String.t(),
  :lastUpdatedAt => String.t(),
  :ttlMs => non_neg_integer(),
  optional(:pollIntervalMs) => non_neg_integer(),
  optional(:statusMessage) => String.t(),
  optional(:inputRequests) => input_requests(),
  optional(:result) => json_object(),
  optional(:error) => json_object(),
  optional(:_meta) => result_meta_object()
}

A complete result returned by tasks/get.

header_mismatch_error()

@type header_mismatch_error() :: %{
  :jsonrpc => String.t(),
  optional(:id) => request_id(),
  error: %{:code => -32020, :message => String.t(), optional(:data) => any()}
}

A JSON-RPC header/body mismatch response (-32020).

implementation()

@type implementation() :: %{
  :name => String.t(),
  :version => String.t(),
  optional(:title) => String.t(),
  optional(:description) => String.t(),
  optional(:websiteUrl) => String.t(),
  optional(:icons) => [ExMCP.Types.V20251125.icon()]
}

Client or server implementation identity.

input_request()

@type input_request() :: %{method: String.t(), params: map()}

A server-initiated request embedded in an MRTR result.

input_requests()

@type input_requests() :: %{optional(String.t()) => input_request()}

Server-assigned input IDs mapped to requests.

input_required_result()

@type input_required_result() :: %{
  :resultType => result_type(),
  optional(:inputRequests) => input_requests(),
  optional(:requestState) => String.t(),
  optional(:_meta) => result_meta_object()
}

An interim result requesting additional client input.

input_response()

@type input_response() :: map()

A client result satisfying one server-initiated MRTR request.

input_response_request_params()

@type input_response_request_params() :: %{
  :_meta => request_meta_object(),
  optional(:inputResponses) => input_responses(),
  optional(:requestState) => String.t(),
  optional(atom() | String.t()) => any()
}

Retry fields accepted on client-initiated requests after an MRTR result.

input_responses()

@type input_responses() :: %{optional(String.t()) => input_response()}

Server-assigned input IDs mapped to client results.

json_object()

@type json_object() :: %{optional(String.t()) => json_value()}

A JSON object with string keys.

json_schema()

@type json_schema() :: map()

Any JSON Schema 2020-12 object, including extension keywords.

json_value()

@type json_value() ::
  String.t()
  | number()
  | boolean()
  | nil
  | [json_value()]
  | %{optional(String.t()) => json_value()}

A value representable in JSON.

log_level()

@type log_level() :: ExMCP.Types.log_level()

meta_object()

@type meta_object() :: %{optional(String.t()) => any()}

An extensible MCP _meta object.

missing_required_client_capability_error()

@type missing_required_client_capability_error() :: %{
  :jsonrpc => String.t(),
  optional(:id) => request_id(),
  error: %{
    code: -32021,
    message: String.t(),
    data: %{requiredCapabilities: client_capabilities()}
  }
}

A missing per-request client capability response (-32021).

notification_meta_object()

@type notification_meta_object() :: %{
  optional(:"io.modelcontextprotocol/subscriptionId") => request_id(),
  optional(String.t()) => any()
}

Metadata carried by notifications, including subscription correlation.

number_schema()

@type number_schema() :: %{
  :type => :number | :integer,
  optional(:title) => String.t(),
  optional(:description) => String.t(),
  optional(:minimum) => number(),
  optional(:maximum) => number(),
  optional(:default) => number()
}

The numeric elicitation schema from the 2026-07-28 generator.

progress_token()

@type progress_token() :: ExMCP.Types.progress_token()

request_id()

@type request_id() :: ExMCP.Types.request_id()

request_meta_object()

@type request_meta_object() :: %{
  :"io.modelcontextprotocol/protocolVersion" => String.t(),
  :"io.modelcontextprotocol/clientCapabilities" => client_capabilities(),
  optional(:"io.modelcontextprotocol/clientInfo") => implementation(),
  optional(:"io.modelcontextprotocol/logLevel") => log_level(),
  optional(:progressToken) => progress_token(),
  optional(String.t()) => any()
}

Metadata required on every modern request.

result()

@type result() :: %{
  :resultType => result_type(),
  optional(:_meta) => result_meta_object(),
  optional(atom() | String.t()) => any()
}

Common fields present on every modern result.

result_meta_object()

@type result_meta_object() :: %{
  optional(:"io.modelcontextprotocol/serverInfo") => implementation(),
  optional(String.t()) => any()
}

Metadata carried by results.

result_type()

@type result_type() :: String.t()

A recognized or negotiated extension result discriminator.

server_capabilities()

@type server_capabilities() :: %{
  optional(:experimental) => %{optional(String.t()) => json_object()},
  optional(:logging) => json_object(),
  optional(:completions) => json_object(),
  optional(:prompts) => %{optional(:listChanged) => boolean()},
  optional(:resources) => %{
    optional(:subscribe) => boolean(),
    optional(:listChanged) => boolean()
  },
  optional(:tools) => %{optional(:listChanged) => boolean()},
  optional(:extensions) => %{optional(String.t()) => json_object()}
}

Capabilities returned by a modern server from server/discover.

subscription_filter()

@type subscription_filter() :: %{
  optional(:toolsListChanged) => boolean(),
  optional(:promptsListChanged) => boolean(),
  optional(:resourcesListChanged) => boolean(),
  optional(:resourceSubscriptions) => [String.t()],
  optional(:taskIds) => [String.t()]
}

Notification categories selected by subscriptions/listen.

subscriptions_listen_request()

@type subscriptions_listen_request() :: %{
  jsonrpc: String.t(),
  id: request_id(),
  method: String.t(),
  params: subscriptions_listen_request_params()
}

A request that opens a long-lived notification stream.

subscriptions_listen_request_params()

@type subscriptions_listen_request_params() :: %{
  _meta: request_meta_object(),
  notifications: subscription_filter()
}

Parameters for subscriptions/listen.

subscriptions_listen_result()

@type subscriptions_listen_result() :: %{
  resultType: result_type(),
  _meta: subscriptions_listen_result_meta_object()
}

The graceful close result for subscriptions/listen.

subscriptions_listen_result_meta_object()

@type subscriptions_listen_result_meta_object() :: %{
  :"io.modelcontextprotocol/subscriptionId" => request_id(),
  optional(:"io.modelcontextprotocol/serverInfo") => implementation(),
  optional(String.t()) => any()
}

Metadata on the graceful close result of a subscription stream.

task()

@type task() :: %{
  :taskId => String.t(),
  :status => task_status(),
  :createdAt => String.t(),
  :lastUpdatedAt => String.t(),
  :ttlMs => non_neg_integer(),
  optional(:pollIntervalMs) => non_neg_integer(),
  optional(:statusMessage) => String.t()
}

Fields common to task handles and detailed task state.

task_status()

@type task_status() :: :working | :input_required | :completed | :failed | :cancelled

Lifecycle state of a task in the official Tasks extension.

tool()

@type tool() :: %{
  :name => String.t(),
  :inputSchema => json_schema(),
  optional(:title) => String.t(),
  optional(:description) => String.t(),
  optional(:outputSchema) => json_schema(),
  optional(:annotations) => ExMCP.Types.tool_annotations(),
  optional(:icons) => [ExMCP.Types.V20251125.icon()],
  optional(:_meta) => meta_object()
}

A tool definition using unrestricted JSON Schema 2020-12 objects.

unsupported_protocol_version_error()

@type unsupported_protocol_version_error() :: %{
  :jsonrpc => String.t(),
  optional(:id) => request_id(),
  error: %{
    code: -32022,
    message: String.t(),
    data: %{supported: [String.t()], requested: String.t()}
  }
}

An unsupported protocol version response (-32022).

update_task_request_params()

@type update_task_request_params() :: %{
  _meta: request_meta_object(),
  taskId: String.t(),
  inputResponses: input_responses()
}

Parameters for submitting responses to outstanding task inputs.

Functions

protocol_version()

@spec protocol_version() :: String.t()

Returns the protocol version described by this module.