modelcontextprotocol / modelcontextprotocol/kotlin-sdk

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

Open
#1,007 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
1.5k
Forks
248
Avg merge
1d 20h
Merged PRs (30d)
23

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing types in kotlin-sdk-core, especially the tools.kt and resources.kt areas, along with the server and client session entry points named in the proposal. Then examine the planned core unit tests and server/client integration tests. Done means the architecture is agreed and the capability, resource, tool-binding, client-resolution, and verification work is implemented across the listed modules.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
api, backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.