Skip to content

[Feature Request] Support the MCP Apps extension, enabling MCP servers to show interactive user interfaces #815

Description

@yurivish

Edit: This issue may be unnecessary. While I'm not 100% confident in that, I was able to create an MCP server with a user interface using the Go SDK. I haven't exercised all MCP Apps functionality (eg. my UI is not interactive) but it's possible that also does not require any changes to the Go SDK.

Original issue below, though it may be obsolete...


Is your feature request related to a problem? Please describe.

I would love to add interactive user interfaces to my Go-based MCP servers, but right now it is not possible.

A recent extension (last month) to the MCP protocol enables MCP servers to show interactive user interfaces, such as data visualizations and complex configuration workflows, directly in an MCP host.

Basically, the server provides an HTML page to be used as the UI, and the MCP protocol is extended to enable communication between that UI, the MCP server, and the MCP host. The UI can appear eg. directly inside of a chat conversation with an AI model, and can be used to interactively guide the conversation.

Here is the spec. There is also an official blog post introducing the extension, and an overview of the concept of extensions, and a docs page motivating and explaining the MCP Apps extension.

Describe the solution you'd like

I would love it if I could add rich user interfaces to my Go-based MCP servers. Right now I use JavaScript when I need to build an MCP server with a UI because there is SDK support there.

In terms of what would be required, looking at the spec I see there is a section on Client<>Server Capability Negotiation and another on Server Behavior.

It's hard to say for sure, but it's possible the server support is a relatively small effort, since most of the complexity of the spec is about the client and host.

Describe alternatives you've considered

One alternative is to use JavaScript to build my MCP servers, which I personally find unsatisfying, particularly since it is not possible to do cross-server MCP calls -- meaning that a UI can only programmatically call tools from its own MCP server, and writing the UI in a separate sever/language would be limiting.

Here is a code snippet that shows what a JS-based MCP apps server looks like when implemented using the JS SDK.

Additional context

Thanks for making this package – getting started is so simple and pleasant, and I'm very excited about being able to use Go for MCP servers! I tried to be as accurate as I can in this request, but please forgive me if I've misunderstood anything about the nature of this spec, or if the request is somehow incoherent -- still learning my way around the various protocols involved. Thanks again!

Edit: Claude Code suggests that a minimal change is needed, since most of the complexity is on the side of the host. Relevant snippet:

  1. Add Extensions field to ClientCapabilities (protocol.go:192)
 type ClientCapabilities struct {
     // ... existing fields ...
     Elicitation *ElicitationCapabilities `json:"elicitation,omitempty"`
     // Extensions describes protocol extensions that the client supports.
     // Keys are extension URIs (e.g. "io.modelcontextprotocol/ui").
     Extensions map[string]any `json:"extensions,omitempty"`
 }

No clone() update needed -- Experimental map[string]any (line 198) uses the same pattern and is not explicitly
cloned either (cp := *c copies the map header, matching existing convention).

  1. Add Extensions field to ServerCapabilities (protocol.go:1300)
type ServerCapabilities struct {
    // ... existing fields ...
    Tools *ToolCapabilities `json:"tools,omitempty"`
    // Extensions describes protocol extensions that the server supports.
    // Keys are extension URIs (e.g. "io.modelcontextprotocol/ui").
    Extensions map[string]any `json:"extensions,omitempty"`
}

Same clone story -- matches Experimental.

[...]

Once the field exists, a Go MCP server can:

  1. Set ServerOptions.Capabilities.Extensions["io.modelcontextprotocol/ui"] = map[string]any{}
  2. Set Tool.Meta["ui"] = map[string]any{"resourceUri": "ui://server/app.html"} on tools
  3. Register a resource at ui://server/app.html with MIME type text/html;profile=mcp-app
  4. Check client support via session.InitializeParams().Capabilities.Extensions["io.modelcontextprotocol/ui"]

All of this uses existing SDK primitives -- only the Extensions field is missing today.

Activity

  1. maciej-kisiel commented on Feb 23, 2026

    @maciej-kisiel
    Contributor

    Hi @yurivish, we recently merged the support for extensions field in the capabilities in #794. I would be curious what additional support you would like to see – I haven't been able to thoroughly analyze the specification from ext-apps, but community feedback will still be useful for the future.

    If it turns out that the MCP Apps story is already supported, adding some minimal example to the examples/ directory would also be very useful to others.

    Thanks!

  2. yurivish commented on Feb 26, 2026

    @yurivish
    Author

    Here's a proof-of-concept – not yet a standalone example since it requires an index.html, but I can hopefully find time soon to make this standalone and add it to examples/.

    func showStructuredData(ctx context.Context, req *mcp.CallToolRequest, input TTSInput) (*mcp.CallToolResult, any, error) {
    	return &mcp.CallToolResult{
    		Content:           []mcp.Content{&mcp.TextContent{Text: fmt.Sprintf("Displaying data: %s", input.Data)}},
    		StructuredContent: map[string]any{"data": input.Data}, // used to display the mcp apps player ui
    	}, nil, nil
    }
    
    func main() {
    	server := mcp.NewServer(&mcp.Implementation{Name: "show-data", Version: "v1.0.0"}, nil)
    
    	resourceURI := "ui://show-data/data-display"
    
    	mcp.AddTool(server, &mcp.Tool{
    		Meta: mcp.Meta{
    			"ui": map[string]any{
    				"resourceUri": resourceURI,
    			},
    		},
    		Name:        "show_structured_data",
    		Description: "Show some structured data.",
    	}, showStructuredData)
    
    	server.AddResource(&mcp.Resource{
    		URI:      resourceURI,
    		Name:     "data-display",
    		MIMEType: "text/html;profile=mcp-app",
    	}, func(_ context.Context, _ *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
    		return &mcp.ReadResourceResult{
    			Contents: []*mcp.ResourceContents{{
    				URI:      resourceURI,
    				MIMEType: "text/html;profile=mcp-app",
    				Text:     indexHTML,
    			}},
    		}, nil
    	})
    
    	if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
    		log.Fatal(err)
    	}
    }
  3. maciej-kisiel commented on Mar 10, 2026

    @maciej-kisiel
    Contributor

    I'll mark it as "needs community feedback" to signal that others may comment about their needs related to MCP Apps extension. Please send a PR with the standalone example if you find the time to create it. Otherwise, if there's no further discussion, I will probably close the issue in a few weeks.

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

    needs community feedbackMore input from users needed to inform a decision

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions