Tutorials Logic, IN info@tutorialslogic.com

MCP Extensions and Apps: Optional Capabilities and Interactive UI

Optional MCP Capabilities

Extensions add optional behavior without forcing every MCP implementation to adopt it. They use globally unique identifiers, explicit support negotiation, and a fallback path when the client or server does not understand the extension.

MCP Apps is the first official extension for interactive interfaces inside compatible hosts. A tool can reference a `ui://` resource containing HTML, CSS, and JavaScript; the host renders it in a sandboxed iframe and mediates communication through a JSON-RPC bridge.

An extension is not permission. Hosts still decide what to render, which tools an embedded app may call, what data crosses the bridge, and which actions need user consent.

Core or Extension

Need Contract Fallback
Portable tools, resources, or prompts Core MCP Required baseline behavior
Interactive UI in the conversation MCP Apps extension Structured tool result or external page
Deferred tool execution Tasks extension or pinned core tasks Synchronous result or application job API
Private product experiment Owned vendor extension Disable feature when unsupported

Extension Identity

Extension identifiers use a vendor prefix and feature name. Official extensions use the `io.modelcontextprotocol` namespace. Third parties should use a reverse-domain prefix they control, such as `com.example/approval-flow`, to prevent collisions.

The identifier names the contract, not merely a feature flag. Its documentation should define messages, metadata, lifecycle, compatibility, security, and fallback. Reusing one identifier for incompatible payloads creates the same ambiguity protocol versions are meant to avoid.

  • Use an owned, collision-resistant namespace.
  • Document the complete wire and security contract.
  • Version incompatible extension behavior deliberately.
  • Do not place ordinary application metadata in an extension namespace.

Support Negotiation

Both parties must know that an optional contract is supported before using it. The exact negotiation shape depends on the protocol revision and extension specification, so implementations should follow that extension’s current documentation rather than inventing a universal extensions field.

Host support varies. A server should preserve a useful core result when an app, task, or authorization extension is unavailable. A client should ignore unknown optional metadata safely and never activate behavior solely because a payload contains an unfamiliar key.

Record the negotiated extension set in traces. This makes failures reproducible when the same server behaves differently across hosts with different capabilities.

  • Check declared support before extension messages.
  • Keep core fallback behavior useful.
  • Ignore unknown optional metadata without granting authority.
  • Test mixed host-support combinations.

MCP Apps Contract

An MCP App combines a tool and a UI resource. The tool metadata references a `ui://` resource through `_meta.ui.resourceUri`. A compatible host fetches that resource, evaluates its declared content type and policy metadata, then renders it inside the conversation.

The app and host communicate over `postMessage` using an app-specific JSON-RPC dialect. The app can receive tool data and may request mediated actions such as calling an allowed MCP tool. It cannot directly inherit the host’s cookies, DOM access, or unrestricted connected capabilities.

Return structured tool results alongside the UI contract. Hosts without app support can still present useful data, and models can reason over fields without scraping rendered HTML.

  • Reference UI with a stable `ui://` resource URI.
  • Bundle structured data separately from presentation.
  • Treat app bridge messages as validated protocol input.
  • Provide a non-UI fallback for unsupported hosts.

App Sandbox

Web hosts render MCP Apps in sandboxed iframes. The sandbox prevents direct access to the parent page, host cookies, local storage, and parent navigation. Communication crosses a controlled message bridge instead of shared JavaScript state.

A resource can declare content-security policy and requested permissions. The host remains the enforcement point and may deny external origins, camera, microphone, open-link, or tool-call capabilities. An app should continue safely when a permission is absent.

Sandboxing reduces impact; it does not make third-party HTML trusted. Validate message origins and schemas, restrict tool proxies, sanitize displayed data, and cap resource size and network destinations.

  • Render third-party UI in a restrictive sandbox.
  • Allow only declared external origins.
  • Mediate every host or tool capability.
  • Request sensitive browser permissions at action time.

Tool Mediation

An embedded app may need to filter a chart, submit a form, or request another tool call. The host should map each bridge request to the current server, user, conversation, and allowed capability set. The app cannot broaden its own authority by naming another tool.

For consequential actions, show the exact target and values outside or above the untrusted app surface when possible. Bind approval to the action payload and invalidate it when the app changes the request.

Keep model context updates separate from external side effects. Text an app sends for conversational context is not user consent and must not trigger a privileged tool automatically.

  • Authorize app-originated tool calls independently.
  • Bind approval to the final action payload.
  • Do not treat app text as trusted host instruction.
  • Trace app, host, server, tool, and user decisions together.

App Selection

Use an MCP App when interactive visualization, complex configuration, rich media, live monitoring, or a multi-step review is materially better than text. A simple confirmation, short list, or static result usually needs only standard MCP content and host UI.

A standalone web app may be simpler when the experience needs independent navigation, broad browser APIs, direct customer identity, or use outside an MCP conversation. Extension adoption should solve an interface problem, not decorate every tool response.

Experience Best Surface Reason
Interactive metric exploration MCP App Conversation context stays beside a rich visualization.
One yes-or-no approval Host confirmation UI A full embedded app adds unnecessary surface.
Public account portal Standalone web app Independent identity and navigation are primary.
Structured data for model reasoning Core tool result Presentation is not the main requirement.

Extension Testing

Test supported and unsupported hosts, unknown metadata, malformed bridge messages, denied permissions, missing UI resources, content-security-policy violations, oversized payloads, app reloads, and tool errors. The fallback must remain understandable when rendering fails.

For security review, attempt cross-origin messaging, unauthorized tool calls, parent navigation, secret access, and prompt injection inside app data. Measure startup latency, resource size, bridge failures, and action-confirmation outcomes.

  • Verify fallback without extension support.
  • Fuzz bridge message schemas and origins.
  • Test denied permissions and unavailable tools.
  • Review interactive actions as complete trajectories.

Extension Fallback

Extensions are negotiated by owned identifiers and are not implied by core MCP revision support. A host and server must agree on the exact extension contract before sending extension messages or metadata. Unknown extensions should be ignored or rejected according to their contract without breaking portable core capabilities.

MCP Apps add an interactive surface in a sandboxed iframe and communicate with the host through a mediated bridge. The sandbox cannot be treated as same-origin application code: the host controls allowed tools, links, and other capabilities, while every bridge message and resulting tool call remains validated and authorized.

Return useful structured tool content even when an app cannot render. Test unsupported hosts, denied UI policy, missing assets, bridge disconnects, and a successful non-visual fallback. An interactive chart is an enhancement; the underlying result contract is what preserves interoperability.

  • Negotiate exact extension identifiers before use.
  • Keep extension failure isolated from core MCP behavior.
  • Mediate iframe messages and tool access through host policy.
  • Provide a useful structured fallback for non-app hosts.

Extension Fallback Examples

Tool Metadata for an MCP App

The tool points to a UI resource while keeping a typed result contract for hosts that do not render the app.

Tool Metadata for an MCP App
{
  "name": "sales_dashboard",
  "description": "Return regional sales metrics for an approved reporting period.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "period": { "type": "string", "pattern": "^[0-9]{4}-Q[1-4]$" }
    },
    "required": ["period"],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "regions": { "type": "array" }
    },
    "required": ["regions"]
  },
  "_meta": {
    "ui": { "resourceUri": "ui://sales/dashboard" }
  }
}
  • The `ui://` resource is presentation, while `outputSchema` remains the data contract.
  • Authorization for the reporting period still occurs in trusted server code.

Choose an App Fallback

A host selects an interactive surface only after extension support and policy are both present.

Choose an App Fallback
def render_mode(host_extensions: set[str], policy_allows_ui: bool) -> str:
    app_id = "io.modelcontextprotocol/ui"
    if app_id in host_extensions and policy_allows_ui:
        return "SANDBOXED_MCP_APP"
    return "STRUCTURED_RESULT"

print(render_mode({"io.modelcontextprotocol/ui"}, True))
print(render_mode(set(), True))
print(render_mode({"io.modelcontextprotocol/ui"}, False))
Output
SANDBOXED_MCP_APP
STRUCTURED_RESULT
STRUCTURED_RESULT

Capability support does not override local host policy.

Before you move on

Extension Design Review

4 checks
  • The extension has an owned identifier and documented fallback.
  • Support is negotiated under the exact extension contract.
  • MCP App resources run in a restricted sandbox with mediated tools.
  • Structured core results remain useful when UI support is absent.

Extension Decisions

0 of 2 checked

Q1. What should a server return when a host cannot render its MCP App?

Q2. Does an app bridge request automatically inherit the user’s connected tool permissions?

Extension Risks

  • UI-only tool result

    Return structured data so unsupported hosts and models still receive useful output.
  • Trusted iframe assumption

    Sandbox the app and validate every bridge message and proxied tool call.
  • No support fallback

    Test the same workflow on a host that does not advertise the extension.

Try this next

Extension Exercises

0 of 3 completed

  1. Classify a chart, confirmation, setup wizard, and static report as core MCP, MCP App, host UI, or standalone web app.
  2. List app messages, allowed tools, required approvals, denied permissions, and trace fields for one interactive workflow.
  3. Test missing UI resources, unknown extension support, denied CSP origins, and an unavailable downstream tool.

Extension Questions

No. MCP Apps is an official extension. Hosts may support it selectively, so servers should retain useful structured fallback results.

Not always. It is best for interactive experiences that benefit from remaining inside an MCP conversation. Independent portals and broad browser workflows may be simpler as standalone applications.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.