Registrati

MCP extensions

This article is not available in Italian yet. It is shown in English.

An MCP extension is an optional addition to the Model Context Protocol specification that defines capabilities beyond the core protocol. An extension has a unique identifier, is specified in its own document and works only when both the client and the server declare support for it. The specification names three kinds of purpose: modular features such as authentication, specialized ones such as industry-specific logic, and experimental ones incubated for possible inclusion in the core.

The framework for extensions was defined by SEP-2133, and the extensions field of capabilities became part of the protocol schema in specification version 2026-07-28. The first official extension, MCP Apps, was announced on 26 January 2026. Official extensions are developed in repositories of the Model Context Protocol GitHub organization. The general structure of the protocol is described in What is MCP; the per-request capability model that extensions rely on is described in Stateless MCP.

Overview

Property Value
Identifier format {vendor-prefix}/{extension-name}, prefix in reverse DNS notation
Official prefix io.modelcontextprotocol
Negotiation extensions field of client and server capabilities
Stages Experimental, Beta, Stable; promotion to the core is possible
Official repositories ext- repositories of the modelcontextprotocol GitHub organization
Governing documents SEP-2133 (framework), SEP-3392 (lifecycle)
Official extensions MCP Apps, Tasks, OAuth Client Credentials, Enterprise-Managed Authorization, Skills over MCP, Server Cards
Default state in SDKs Disabled, explicit opt-in required

The problem extensions solve

Every feature of the core specification has to be implemented by every SDK. Some features are needed only in certain environments, such as enterprise identity management, and some are not yet settled.

Extensions separate these features from the core. An extension evolves under its own maintainers, and implementations adopt it only when they need it.

The experimental tasks of version 2025-11-25 lived in the core, and implementation experience revealed problems with their handshake, the blocking tasks/result method and the scope of tasks/list. SEP-2663 moved them into an extension to give the feature time to incubate independently of the core. MCP Apps took the opposite route: MCP-UI and the OpenAI Apps SDK had developed separate approaches to interactive results, and the extension unified them.

History

The table lists the events that shaped the extension mechanism and the official extensions.

Date Event
4 June 2025 SEP-990, the basis of Enterprise-Managed Authorization, is created
21 November 2025 SEP-1865 "MCP Apps - Interactive User Interfaces for MCP" is created
25 November 2025 Specification 2025-11-25 with experimental tasks in the core
26 January 2026 MCP Apps, the first official extension: revision 2026-01-26 of its specification
23 April 2026 SEP-2640 "Skills Extension" is created
27 April 2026 SEP-2663 "Tasks Extension" is created
28 July 2026 Specification 2026-07-28: the extensions field in capabilities, tasks moved to io.modelcontextprotocol/tasks, revisions of the authorization extensions keyed to 2026-07-28
25 September 2026 SEP-3392 "Extension Lifecycle" is created: stages Experimental, Beta and Stable

Extension identifiers

An extension is identified by a string of the form {vendor-prefix}/{extension-name}. The identifier follows the rules for _meta keys, except that the prefix is mandatory. The prefix is a series of labels separated by dots and should be a reversed domain name that the author owns: a company with example.com uses com.example/my-extension. Any prefix whose second label is modelcontextprotocol or mcp is reserved for MCP.

The table lists the identifiers of official extensions.

Extension Identifier Repository
MCP Apps io.modelcontextprotocol/ui ext-apps
Tasks io.modelcontextprotocol/tasks ext-tasks
OAuth Client Credentials io.modelcontextprotocol/oauth-client-credentials ext-auth
Enterprise-Managed Authorization io.modelcontextprotocol/enterprise-managed-authorization ext-auth
Skills over MCP io.modelcontextprotocol/skills ext-skills

The identifier does not change when the extension moves from one stage to another. A breaking change also keeps the identifier. A new identifier, such as io.modelcontextprotocol/my-extension-v2, is used only when the old and new behavior must coexist under one protocol revision. SEP-2133 originally required a new identifier for every breaking change; SEP-3392 replaced that rule.

Negotiation

Declaring support

Support is declared in the extensions field of capabilities: a map from identifiers to settings objects. An empty object means support without settings. Each extension defines the schema of its own settings. In a stateless protocol the client declares extensions in every request, inside _meta["io.modelcontextprotocol/clientCapabilities"]:

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "location": "New York" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {
        "extensions": {
          "io.modelcontextprotocol/ui": { "mimeTypes": ["text/html;profile=mcp-app"] },
          "io.modelcontextprotocol/tasks": {}
        }
      }
    }
  }
}

The server declares its extensions in the capabilities returned by server/discover:

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "supportedVersions": ["2026-07-28"],
    "capabilities": {
      "tools": {},
      "resources": {},
      "extensions": {
        "io.modelcontextprotocol/ui": {},
        "io.modelcontextprotocol/skills": { "directoryRead": true }
      }
    },
    "ttlMs": 3600000,
    "cacheScope": "public"
  }
}

A server must not assume support declared in an earlier request.

Versions with the handshake

Before 2026-07-28 many SDKs already exchanged extensions in capabilities.extensions of the initialize request and response. The field is not part of the published schemas of those versions; if the other side omits it, the extension is treated as unsupported.

What extensions may add

An extension may add methods, notifications, _meta keys, settings and values of resultType. The set of resultType values a client accepts consists of the core values plus those of extensions advertised in capabilities. Tasks, for example, reserve the method prefix tasks/, the notification prefix notifications/tasks/ and the resultType value "task".

Official, experimental and third-party extensions

Official extensions live in repositories of the modelcontextprotocol GitHub organization with the ext- prefix and use the io.modelcontextprotocol prefix. Each repository lists its Extension Maintainers in MAINTAINERS.md, and each extension is associated with a Working Group or an Interest Group. Core Maintainers keep the authority to change, deprecate or remove any official extension.

Experimental extensions are an incubation path for Working Groups and Interest Groups. They live under specification/experimental/ of an ext- repository or in a repository with the experimental-ext- prefix. Published packages must show their experimental status, and implementers should pin a tag or commit, because two revisions need not be compatible.

Extensions developed outside the MCP organization are not recognized by MCP governance; SEP-2133 calls them unofficial. They should use a reversed domain of their author as the prefix and follow the same negotiation rules.

Lifecycle and governance

Stages

SEP-3392 defines the stages of an extension. The directory that holds its specification shows the stage: specification/experimental/, specification/beta/ or specification/stable/.

Stage Allowed changes Entry What implementers can expect
Experimental Any change at any time Added by an Extension Maintainer Nothing; the design may disappear
Beta Any change, breaking changes rare and documented Extensions Track SEP Real use; documented breaking changes
Stable Only with a new core protocol revision Second Extensions Track SEP Fixed behavior within a protocol revision
Core As for the core specification Standards Track SEP As for the core specification

Changes are approved by Extension Maintainers without Core Maintainer review. A Beta extension that makes a breaking change should add or increment a revision string in its settings object, so that peers can detect a mismatch. A Stable extension is published as immutable revisions keyed to core protocol revisions, for example specification/stable/<name>/2026-07-28/.

Creation and promotion

An extension starts as Experimental. To enter Beta, its authors submit an Extensions Track SEP and state whether the extension is meant to become Stable or to move into the core. At least one reference implementation in an official SDK is required before review, and Core Maintainers decide on acceptance. To become Stable, a second SEP needs two independent, interoperating implementations, one on the client side and one on the server side, and a conformance scenario.

A Standards Track SEP can promote an extension into the core in protocol revision R. For requests that declare R or later the feature is core behavior; for earlier revisions the extension still applies.

SDK support

Supporting extensions is not required for protocol conformance, and SDK maintainers decide which ones to implement. Extensions are disabled by default and require explicit opt-in by the developer.

Current stages

The table lists the stages of official extensions on the extensions overview page.

Extension Stage
OAuth Client Credentials Stable
Enterprise-Managed Authorization Stable
MCP Apps Stable
Tasks Beta, intended for the core
Skills over MCP Beta, destination not stated
Server Cards Beta, destination not stated

Tasks

Purpose

The Tasks extension lets a server answer tools/call with a task handle instead of the final result. A task is a durable state machine that carries the execution state of a request and is identified by a taskId generated by the server. The client polls the task and retrieves the result later, also after reconnecting. Only tools/call can create tasks in the current revision.

Creation is decided by the server. The client declares the extension in the capabilities of its requests and must handle both result shapes; there is no separate flag for task creation. A server must not return a task to a client that did not declare the extension.

Creating and polling a task

The examples omit _meta for brevity. A long-running call returns a result with resultType: "task":

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "task",
    "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
    "status": "working",
    "statusMessage": "Build started.",
    "createdAt": "2026-08-10T10:30:00Z",
    "lastUpdatedAt": "2026-08-10T10:30:00Z",
    "ttlMs": 3600000,
    "pollIntervalMs": 5000
  }
}

The server must not send this result until the task is durably created, so that a tasks/get for the returned ID succeeds. ttlMs is the lifetime from creation, or null for unlimited. pollIntervalMs is the suggested polling interval, and servers may rate-limit clients that poll more often. The client polls with tasks/get:

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tasks/get",
  "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" }
}

On Streamable HTTP the client sets the Mcp-Name header of tasks/get, tasks/update and tasks/cancel to the task ID, so that intermediaries can route the request to the instance that holds the task.

Statuses

The table lists the statuses of a task.

Status Meaning Additional field
working The request is being processed None
input_required The server needs input from the client inputRequests
completed The request finished; terminal result
failed A JSON-RPC error occurred during execution; terminal error
cancelled The task was cancelled; terminal None

A tool result with isError: true is a completed task with the error inside result. The failed status is reserved for protocol errors.

Input during execution

When the task needs input, tasks/get returns status: "input_required" and an inputRequests map in the format of Multi Round-Trip Requests. The client answers with tasks/update:

JSON
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tasks/update",
  "params": {
    "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
    "inputResponses": {
      "approve_deploy": { "action": "accept", "content": { "approved": true } }
    }
  }
}

The server acknowledges with an empty result that has resultType: "complete". The acknowledgement is eventually consistent: the status seen by tasks/get may change later. Each key of inputRequests is unique for the lifetime of the task, and the server ignores answers to unknown or already answered keys. A completed task returns the result the original request would have returned:

JSON
{
  "jsonrpc": "2.0",
  "id": 9,
  "result": {
    "resultType": "complete",
    "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
    "status": "completed",
    "createdAt": "2026-08-10T10:30:00Z",
    "lastUpdatedAt": "2026-08-10T10:52:00Z",
    "ttlMs": 3600000,
    "pollIntervalMs": 5000,
    "result": {
      "content": [{ "type": "text", "text": "Deployed build 1842 to staging." }],
      "isError": false
    }
  }
}

Cancellation and notifications

tasks/cancel signals the intent to cancel. The server must acknowledge it but is not obliged to stop the work, and the task may still reach completed. Instead of polling, a client can open subscriptions/listen with a taskIds filter and receive notifications/tasks with the full task state.

Differences from 2025-11-25

The experimental tasks of 2025-11-25 are not wire-compatible with the extension. The blocking tasks/result method and tasks/list are removed, the task parameter of tools/call is ignored, and the capability declarations tasks.requests.*, tasks.cancel and tasks.list are replaced by the extension identifier. Task IDs must be hard to guess, and every task request is checked for authorization.

MCP Apps

Components

MCP Apps (io.modelcontextprotocol/ui) let a server deliver an interactive HTML interface that the host renders inside the conversation. The extension combines two primitives: a UI resource with the ui:// URI scheme and the MIME type text/html;profile=mcp-app, and a tool that refers to that resource in _meta.ui.resourceUri:

JSON
{
  "name": "get_weather",
  "description": "Get current weather for a location",
  "inputSchema": {
    "type": "object",
    "properties": { "location": { "type": "string" } }
  },
  "_meta": {
    "ui": {
      "resourceUri": "ui://weather-server/dashboard",
      "visibility": ["model", "app"]
    }
  }
}

The host fetches the interface with resources/read, possibly before the tool is called. The resource content may carry _meta.ui.csp with the external origins the interface may contact:

JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "resultType": "complete",
    "contents": [
      {
        "uri": "ui://weather-server/dashboard",
        "mimeType": "text/html;profile=mcp-app",
        "text": "<!DOCTYPE html><html><body>...</body></html>",
        "_meta": { "ui": { "csp": { "connectDomains": ["https://api.example.com"] } } }
      }
    ],
    "ttlMs": 3600000,
    "cacheScope": "public"
  }
}

visibility controls who can call the tool. The value "model" makes it available to the model, "app" to the interface of the same server. A tool with ["app"] only is excluded from the model's tool list. Resources and tools are covered in MCP resources and MCP tools.

Sandbox

The interface runs in a sandboxed iframe without access to the DOM, cookies or storage of the host. A web host places it behind a sandbox proxy on a different origin. If the resource declares no CSP, the host applies a restrictive default that blocks external connections, and it must not allow domains that were not declared.

Communication between the interface and the host

The interface and the host exchange JSON-RPC 2.0 messages over postMessage. The specification describes this as a dialect of MCP in which the interface acts as a client of the host.

Host (AI application)
 |
 +-- MCP client ------ tools/call, resources/read ------ MCP server
 |
 +-- sandbox proxy (separate origin)
       |
       +-- iframe with the interface --- postMessage, JSON-RPC

The exchange starts with ui/initialize and ui/notifications/initialized. The host sends the tool arguments in ui/notifications/tool-input and the result in ui/notifications/tool-result. The interface can call tools of its server with tools/call, which the host forwards and may subject to user approval. It can also send a message to the chat with ui/message, add data to the model's context with ui/update-model-context and ask the host to open a link with ui/open-link. Before removing the interface the host sends ui/resource-teardown.

Fallback

A host without MCP Apps support treats the tool as an ordinary tool and shows its text result. For this reason the tool must return meaningful content even when an interface is available, and servers should provide a text-only behavior for every tool with an interface.

Enterprise-Managed Authorization

The Enterprise-Managed Authorization extension (io.modelcontextprotocol/enterprise-managed-authorization) makes the organization's identity provider (IdP) the point where access to MCP servers is decided. Without it, every user authorizes every client on every server separately. With it, administrators define in the IdP which users may use which clients with which servers and scopes. The basics of MCP authorization with OAuth are described in MCP authorization.

The extension is a profile of the IETF draft Identity Assertion JWT Authorization Grant. The flow has three steps:

  1. The user signs in to the MCP client through the enterprise IdP with OpenID Connect or SAML, and the client keeps the identity assertion.
  2. The client sends a token exchange request (RFC 8693) to the IdP with requested_token_type equal to urn:ietf:params:oauth:token-type:id-jag. The IdP evaluates its policies and returns an Identity Assertion JWT Authorization Grant (ID-JAG).
  3. The client presents the ID-JAG to the authorization server of the MCP server as a JWT bearer grant (RFC 7523) and receives an access token.

The client does not redirect the user to the authorization server of the MCP server. It learns that the server supports the profile from the value urn:ietf:params:oauth:grant-profile:id-jag in authorization_grant_profiles_supported of the authorization server metadata. The IdP sees only the issuance of the token, not the MCP traffic.

The same repository contains OAuth Client Credentials (io.modelcontextprotocol/oauth-client-credentials), an extension for machine-to-machine access without user interaction, such as CI pipelines and background services.

Skills over MCP

Skills over MCP (io.modelcontextprotocol/skills) let a server publish Agent Skills: directories with a SKILL.md file and supporting files. SEP-2640 has the status Final, and the extensions overview lists the extension as Beta. A server that declares it must also declare resources and implement skills/list and skills/get; the files are read with resources/read under skill:// URIs.

Reading SKILL.md does not activate a skill. The host loads it through its own skill path, which verifies the content and asks for user approval where required. The extension requires hosts to treat skill content as untrusted input; risks of instructions in such content are covered in prompt injection.

Behavior without extension support

If one side supports an extension and the other does not, the supporting side must either fall back to core behavior or reject the request with an error. Extensions should document their fallback. The table lists the behavior defined by each official extension.

Extension Peer without support Defined behavior
Tasks Client Server returns the ordinary result; task methods return -32021
MCP Apps Host Tool works as a text-only tool
Enterprise-Managed Authorization Client Server falls back to core authorization or rejects the client
Skills over MCP Server Client does not send skills/list or skills/get
Any Client sees an unknown resultType The result is invalid for the client

The specification does not define one error code for all extensions.

Extension, core feature and experimental capability

Three mechanisms add optional behavior to MCP. The table compares them.

Core feature Extension Experimental capability
Where it is specified Core specification Extension document in an ext- repository Not specified
Declared in Named capability, such as tools capabilities.extensions capabilities.experimental
Identifier Field name in the schema vendor-prefix/name Arbitrary key
Who approves changes Core Maintainers Extension Maintainers Not defined
Change points Protocol revisions Depends on the stage Any time
Required for conformance Per the specification No Not defined

Changes to a core feature go through SEPs approved by Core Maintainers, and its deprecation follows the feature lifecycle policy described in Stateless MCP.

The experimental field of ClientCapabilities and ServerCapabilities holds non-standard capabilities as a map of names to objects. The schema defines no process, prefix or document for them, while an experimental extension has a Working Group, a repository and a path to Beta.

Terms

Term Meaning
MCP extension Optional addition to the specification outside the core protocol, declared in capabilities
Extension identifier String of the form vendor-prefix/name that identifies an extension in capabilities
Official extension Extension in an ext- repository of the MCP organization with the io.modelcontextprotocol prefix
Experimental extension Extension in incubation with no stability promise, linked to a Working or Interest Group
Extension stage Maturity level of an extension: Experimental, Beta or Stable
Task Durable state of a long-running request that the client polls by taskId
UI resource Resource with a ui:// URI that contains an HTML interface for MCP Apps
ID-JAG Identity Assertion JWT Authorization Grant: token from the enterprise IdP exchanged for an access token
Skill Directory with SKILL.md and supporting files served by the Skills extension

Sources

Series

Model Context Protocol (MCP)
  1. What is MCP (Model Context Protocol)
  2. Tools in MCP
  3. Resources and resource templates in MCP
  4. Prompts in MCP
  5. MCP transports: stdio and Streamable HTTP
  6. Stateless MCP: changes in 2026-07-28
  7. Authorization in MCP
  8. MCP security
  9. MCP extensionsCurrent
  10. MCP server over an existing API
  11. Testing MCP servers: the basics
  12. Evaluating an MCP server with models
  13. Regression testing of an MCP server
  14. Publishing an MCP server to the MCP Registry

Wiki articles are written and maintained by the ComplexQA team.