Skip to content

[Proposal] SEP-1865: MCP Apps (Interactive User Interfaces) architecture & SDK integration design (#802) #1007

Description

@ump45nose

Proposal: SEP-1865 MCP Apps (Interactive User Interfaces) Architecture & SDK Integration Design (#802)

Motivation & Context

Tracking implementation of SEP-1865 in kotlin-sdk for the 2026-07-28 MCP specification release (aligned with umbrella issue #842).

As conversational AI systems and agentic hosts evolve, plain-text and markdown responses are insufficient for workflows requiring interactive visual feedback, form rendering, interactive charts, and dashboard state visualization.

SEP-1865 standardizes MCP Apps as an official extension under the SEP-2133 Extensions Framework:

  1. Predeclared UI Resources: Declared through the ui:// URI scheme with mime-type text/html;profile=mcp-app. Predeclaring templates allows hosts to prefetch, cache, and audit visual templates prior to runtime tool execution.
  2. Tool-to-UI Association: Tools bind to their visual interfaces through standardized metadata (_meta["ui"]), linking execution output to interactive displays.
  3. Bi-directional Communication: The UI sandboxed iframe communicates with the host using standard JSON-RPC, reusing existing MCP protocol primitives for tool invocations, prompts, and updates.
  4. Security & Auditability: Mandatory iframe sandboxing, origin isolation, and user approval gates for UI-initiated actions.

This proposal outlines the Kotlin Multiplatform architecture to implement SEP-1865 across kotlin-sdk-core, kotlin-sdk-server, and kotlin-sdk-client.


Proposed Architecture & Component Design

1. Capability Negotiation & Constants (kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/)
  • Extension Identifier & MIME Types:
    public object McpAppsExtension {
        public const val EXTENSION_ID: String = "io.modelcontextprotocol/apps"
        public const val EXTENSION_VERSION: String = "1.0.0"
        public const val UI_URI_SCHEME: String = "ui"
        public const val MCP_APP_MIME_TYPE: String = "text/html;profile=mcp-app"
        public const val UI_META_KEY: String = "ui"
    }
  • Apps Capability Descriptor:
    @Serializable
    public data class AppsCapabilities(
        val formats: List<String> = listOf(McpAppsExtension.MCP_APP_MIME_TYPE),
        val externalIframes: Boolean = false,
    )
    Advertised under ClientCapabilities.extensions[McpAppsExtension.EXTENSION_ID] and ServerCapabilities.extensions[McpAppsExtension.EXTENSION_ID].
2. Data Models & Metadata DSL (kotlin-sdk-core & kotlin-sdk-server)
  • Tool UI Binding Metadata:
    In types/tools.kt and types/resources.kt:
    @Serializable
    public data class ToolUiMetadata(
        val resourceUri: String, // e.g. "ui://charts/stock-view"
        val preferredDisplay: String? = null, // "inline" | "sidecar" | "modal"
        val autoRender: Boolean = true,
    )
  • Ergonomic Server Tool Registration DSL:
    // Registering a UI-bound tool
    server.addTool(
        name = "query_metrics",
        description = "Retrieves and displays service metrics",
        ui = ToolUiMetadata("ui://metrics/dashboard")
    ) { params ->
        // Standard tool execution returning data
        CallToolResult(
            content = listOf(
                TextContent("Metrics retrieved successfully"),
                EmbeddedDataContent(jsonResult)
            )
        )
    }
    
    // Predeclaring the matching UI resource
    server.addUiResource(
        uri = "ui://metrics/dashboard",
        name = "Service Metrics Dashboard",
        htmlContent = loadResourceTemplate("dashboard.html")
    )
3. UI Resource Registration & Serving (kotlin-sdk-server)
  • In ServerSession:
    • Helper extension addUiResource(uri, name, htmlContent, description) that registers an underlying Resource with mimeType = McpAppsExtension.MCP_APP_MIME_TYPE.
    • Validates that the URI conforms strictly to the ui:// scheme.
    • Exposes resources/read handlers that serve the HTML template directly to client hosts.
4. Client Host UI Integration Plumbing (kotlin-sdk-client)
  • UI Resource Resolver:
    Provide client utilities to resolve and inspect UI-enabled tools:
    public suspend fun ClientSession.getToolUiResource(tool: Tool): ResourceContents? {
        val uiUri = tool.meta?.get(McpAppsExtension.UI_META_KEY)
            ?.jsonObject?.get("resourceUri")?.jsonPrimitive?.contentOrNull ?: return null
        
        val readResult = this.readResource(ReadResourceRequestParams(uri = uiUri))
        return readResult.contents.firstOrNull()
    }
  • Sandboxed Message Bridge:
    Provide an interface for hosts embedding WebView / iframe environments (e.g. desktop Compose Multiplatform, Android WebView, or browser JS) to pipe JSON-RPC messages between the sandboxed UI and ClientSession.
5. Testing & Verification Plan
  • Unit Tests (kotlin-sdk-core):
    • Serialization and metadata extraction of ToolUiMetadata in Tool definitions.
    • Validation of ui:// URI schemes and MIME type enforcement.
  • Integration Tests (kotlin-sdk-server & kotlin-sdk-client):
    • Register a UI resource and an associated tool.
    • Client retrieves tool catalog via tools/list, detects UI binding, fetches the UI template via resources/read, and executes tools/call.
  • Conformance Scenarios:
    • Validate against the MCP Apps test scenarios in modelcontextprotocol/conformance and ext-apps reference suite.

Next Steps

Upon review and consensus on the MCP Apps integration:

  1. Land McpAppsExtension constants and ToolUiMetadata in kotlin-sdk-core.
  2. Add addUiResource and UI-binding DSL helpers in kotlin-sdk-server.
  3. Provide client-side template resolution helpers in kotlin-sdk-client.
  4. Add sample project demonstrating Compose Multiplatform / WebView hosting of MCP Apps.

AI assistance disclosure: AI was used to discover this opportunity and draft the change or text. The submission was checked against the prepared artifact and recorded verification evidence.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions