Skip to content

feat: capability-based widget rendering using MCP Apps client negotiation #538

@jirispilka

Description

@jirispilka

Problem

Widget rendering is currently gated behind a server-side ui=openai URL parameter. This is wrong for two reasons:

  1. It's not spec-compliant — MCP Apps (SEP-1865) defines a proper capability negotiation mechanism: clients advertise io.modelcontextprotocol/ui in their capabilities during initialize, and servers should use this to decide whether to expose widget metadata.
  2. It couples widget support to a proprietary mode — any client that wants widgets has to know to pass ui=openai, which is an Apify-specific convention, not a standard.

What should happen

During the MCP initialize handshake, the server should inspect the client's capabilities. If the client supports text/html;profile=mcp-app (MCP Apps), expose widget metadata (_meta.ui.*) in tool definitions. If not, serve text-only responses — no widget metadata, no resource URIs.

This is already partially scaffolded (see res/TODO-mcp-apps-migration.md) but the capability flag is currently informational only.

Additional consideration: opt-out switch

Even when a client supports MCP Apps, it may be useful to allow disabling widgets:

  • Users who prefer plain text responses
  • Testing scenarios where widget rendering gets in the way
  • Debugging to isolate issues

A query parameter mcp-apps=off would let anyone explicitly opt out of widget rendering regardless of client capabilities.

Internal repo impact

This change will require updates in apify-mcp-server-internal — the hosted server passes ui=openai today and will need to be updated to align with the new capability-based approach.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    t-aiIssues owned by the AI team.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions