Skip to content

viant/mcp-ui

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

viant/mcp-ui

Typed Go SDK for the MCP UI / MCP Apps extension.

This module is the dedicated extension layer for UI-specific MCP behavior. It exists to keep the boundaries clean between:

  • github.com/viant/mcp-protocol — official MCP schema mirror
  • github.com/viant/mcp — transport/runtime
  • github.com/viant/mcp-ui — UI extension capability, metadata, resources, browser envelope contracts, and compatibility helpers

Why this repo exists

UI support for MCP needs its own layer.

This repo owns:

  • typed _meta.ui helpers
  • typed UI extension capability helpers
  • ui://... resource builders
  • browser host/guest postMessage envelope types
  • exact compatibility switching between negotiated UI resources and explicit embedded fallback

This repo intentionally does not own:

  • core MCP schema definitions
  • MCP transport implementations
  • Agently-specific server behavior
  • Forge-specific rendering behavior

Scope

Today this module focuses on the extension contract itself.

That means:

  • typed capability negotiation
  • typed _meta.ui metadata
  • canonical ui://... resource construction
  • browser host/guest envelope types
  • exact compatibility switching between negotiated UI resources and explicit embedded fallback

It does not try to be:

  • a browser host implementation
  • an MCP server framework
  • a product-specific UI toolkit
  • a replacement for mcp-protocol or mcp

Status

The SDK surface is active and usable.

Implemented in the current worktree:

  • capability helpers in capabilities
  • typed metadata helpers in meta
  • resource builders in resource
  • browser envelope types in appproto
  • compatibility switching in compat

The current compatibility rule is exact:

  • if UI extension capability is negotiated, use _meta.ui.resourceUri plus resources/read
  • if UI extension capability is not negotiated, embedded fallback is allowed only when _meta.ui.fallback = "embedded" is explicitly present

Current maturity in this repo:

  • the SDK contract is implemented and test-backed
  • compatibility switching is implemented and test-backed
  • browser-host rollout, production review, and product-specific policy remain downstream concerns for consuming projects

In other words: this repo is ready to be used as an extension SDK, while deployment posture is decided by downstream hosts.

Specification pin

This SDK targets the MCP Apps extension proposed by SEP-1865.

All extension identifiers, MIME types, and _meta.ui.* key spellings in this repo are pinned to that SHA.

Key exported concepts

Pinned identifiers:

  • extension capability key: io.modelcontextprotocol/ui
  • UI resource MIME type: text/html;profile=mcp-app
  • canonical tool metadata field: _meta.ui.resourceUri

Current metadata surface includes:

  • resourceUri
  • allowedTools
  • allowedToolBundles
  • contentHash
  • protocolVersion
  • rendererUrl
  • sandbox
  • legacy raw csp
  • structured cspPolicy
  • fallback

Package map

capabilities

Capability helpers for the UI extension.

Use it to:

  • advertise UI support on client/server capabilities
  • detect whether the peer negotiated UI support

Main exports:

  • ExtensionName
  • ResourceMimeType
  • Capability
  • SetClientCapability
  • SetServerCapability
  • GetClientCapability
  • GetServerCapability

meta

Typed _meta.ui helpers for tools and resources.

Use it to:

  • advertise ui://... resources on tools
  • attach render/security hints to resources
  • carry structured CSP policy and explicit embedded-fallback intent

Main exports:

  • ToolUI
  • ResourceUI
  • CSPPolicy
  • SetToolUI
  • GetToolUI
  • SetResourceUI
  • GetResourceUI
  • SetReadResultContentsUI
  • GetReadResultContentsUI

resource

Builders for ui://... resources and resource contents.

Use it to:

  • create MCP resource declarations
  • create resources/read HTML contents
  • create embedded HTML fallback resources
  • compute canonical content hashes

Main exports:

  • ValidateUIURI
  • ContentHash
  • NewHTMLResource
  • NewHTMLContents
  • NewReadResultHTMLContents
  • NewEmbeddedHTMLResource

appproto

Browser host/guest postMessage contract.

This is explicitly not MCP JSON-RPC.

Use it to type and validate:

  • mcpui:tools-call
  • mcpui:message
  • mcpui:open-link
  • mcpui:host-ready
  • mcpui:tool-input
  • mcpui:tool-input-partial
  • mcpui:tool-result
  • mcpui:teardown

compat

Exact compatibility switching helpers.

Use it to:

  • decide whether a tool/resource should use negotiated UI-resource flow
  • decide whether explicit embedded fallback is allowed
  • build embedded fallback from canonical resources/read output

Actionable example

The example below shows a full minimal flow:

  1. declare UI capability on the server
  2. advertise a ui://... resource on a tool
  3. publish the matching resource
  4. choose negotiated UI-resource flow vs embedded fallback
package main

import (
	"context"
	"fmt"

	"github.com/viant/mcp-protocol/schema"
	"github.com/viant/mcp-ui/capabilities"
	"github.com/viant/mcp-ui/compat"
	"github.com/viant/mcp-ui/meta"
	"github.com/viant/mcp-ui/resource"
)

func main() {
	const (
		uri  = "ui://example.demo/widget/show_status"
		html = "<!DOCTYPE html><html><body><h1>Status OK</h1></body></html>"
	)

	// 1. Server advertises UI capability.
	serverCaps := &schema.ServerCapabilities{}
	capabilities.SetServerCapability(serverCaps, capabilities.Capability{
		ProtocolVersion: "1.0.0",
		MimeTypes:       []string{capabilities.ResourceMimeType},
	})

	// 2. Tool advertises a UI resource and explicit embedded fallback.
	tool := &schema.Tool{Name: "show_status"}
	meta.SetToolUI(tool, meta.ToolUI{
		ResourceUri: uri,
		Fallback:    meta.FallbackEmbedded,
	})

	// 3. Resource carries canonical UI metadata.
	uiMeta := meta.ResourceUI{
		ContentHash:     resource.ContentHash(html),
		ProtocolVersion: "1.0.0",
		CSPPolicy: &meta.CSPPolicy{
			ScriptSrc: []string{"https://cdn.example"},
		},
	}

	res, err := resource.NewHTMLResource(
		uri,
		"show_status",
		ptr("Demo status widget"),
		ptr("Demo Status"),
		nil,
		uiMeta,
	)
	if err != nil {
		panic(err)
	}

	readContents, err := resource.NewReadResultHTMLContents(uri, html, uiMeta)
	if err != nil {
		panic(err)
	}

	// 4. Client decides whether to use negotiated UI-resource flow
	//    or explicit embedded fallback.
	clientCaps := &schema.ClientCapabilities{}
	mode := compat.SelectToolMode(clientCaps, meta.ToolUI{
		ResourceUri: uri,
		Fallback:    meta.FallbackEmbedded,
	})

	fmt.Println("tool:", tool.Name)
	fmt.Println("resource:", res.Uri)
	fmt.Println("mode:", mode.String())
	fmt.Println("read mime:", *readContents.MimeType)
	fmt.Println("read hash:", uiMeta.ContentHash)

	// If the peer had no UI capability and you needed fallback:
	reader := compatReader{contents: *readContents}
	embedded, err := compat.BuildEmbeddedFallback(context.Background(), reader, uri)
	if err != nil {
		panic(err)
	}
	fmt.Println("embedded type:", embedded.Type)
}

type compatReader struct {
	contents schema.ReadResourceResultContentsElem
}

func (r compatReader) ReadResource(context.Context, string) (*schema.ReadResourceResult, error) {
	return &schema.ReadResourceResult{
		Contents: []schema.ReadResourceResultContentsElem{r.contents},
	}, nil
}

func ptr[T any](v T) *T { return &v }

Development

Local replace in a consumer repo:

replace github.com/viant/mcp-ui => ../mcp-ui

This repo itself uses:

replace github.com/viant/mcp-protocol => ../mcp-protocol

Testing

Run the package tests from this repo root:

go test ./...

For the package-level suites used most often during development:

go test ./capabilities ./meta ./resource ./compat ./appproto

Boundaries

This repo:

  • depends on github.com/viant/mcp-protocol
  • must not depend on:
    • github.com/viant/agently-core
    • github.com/viant/agently
    • github.com/viant/forge

That separation is intentional: this SDK defines the extension contract, while hosts and products consume it downstream.

License

Apache 2.0. See LICENSE.

About

Typed Go SDK for the MCP UI / MCP Apps extension.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages