Skip to content

Commit 7f54b8c

Browse files
mikekistlerCopilot
andcommitted
Add MCP Apps conceptual documentation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7753c53 commit 7f54b8c

3 files changed

Lines changed: 156 additions & 1 deletion

File tree

docs/concepts/apps/apps.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
---
2+
title: MCP Apps
3+
author: mikekistler
4+
description: How to use the MCP Apps extension to deliver interactive UIs from MCP servers.
5+
uid: apps
6+
---
7+
8+
# MCP Apps
9+
10+
[MCP Apps] is an extension to the Model Context Protocol that enables MCP servers to deliver interactive user interfaces — dashboards, forms, visualizations, and more — directly inside conversational AI clients.
11+
12+
[MCP Apps]: https://modelcontextprotocol.io/specification/draft/extensions/apps
13+
14+
> [!IMPORTANT]
15+
> MCP Apps support is experimental. All types are marked with `[Experimental("MCPEXP003")]` and require suppressing that diagnostic to use.
16+
17+
## Installation
18+
19+
MCP Apps is provided in the `ModelContextProtocol.Extensions.Apps` package, which layers on top of the core SDK:
20+
21+
```shell
22+
dotnet add package ModelContextProtocol.Extensions.Apps
23+
```
24+
25+
## Overview
26+
27+
The MCP Apps extension introduces the concept of **UI resources** — HTML pages served by the MCP server that a client can display alongside the conversation. Tools can be associated with a UI resource so the client knows which interface to show when a tool is called.
28+
29+
The key concepts are:
30+
31+
- **UI capability negotiation** — Client and server declare support via `extensions["io.modelcontextprotocol/ui"]`
32+
- **UI resources** — HTML content served with the MIME type `text/html;profile=mcp-app`
33+
- **Tool UI metadata** — Tools declare their associated UI resource in `_meta.ui`
34+
35+
## Associating tools with UI resources
36+
37+
### Using the builder extension (recommended)
38+
39+
The simplest approach is to apply `[McpAppUi]` attributes to your tool methods and call `WithMcpApps()` on the server builder:
40+
41+
```csharp
42+
[McpServerToolType]
43+
public class WeatherTools
44+
{
45+
[McpServerTool, Description("Get current weather for a location")]
46+
[McpAppUi(ResourceUri = "ui://weather/view.html")]
47+
public static string GetWeather(string location) => $"Weather for {location}";
48+
49+
[McpServerTool, Description("Get forecast (model-only tool)")]
50+
[McpAppUi(ResourceUri = "ui://weather/forecast.html", Visibility = [McpUiToolVisibility.Model])]
51+
public static string GetForecast(string location) => $"Forecast for {location}";
52+
}
53+
```
54+
55+
```csharp
56+
builder.Services.AddMcpServer()
57+
.WithTools<WeatherTools>()
58+
.WithMcpApps();
59+
```
60+
61+
The `WithMcpApps()` call registers a post-configuration step that processes all registered tools and applies `[McpAppUi]` attribute metadata to their `_meta.ui` field automatically.
62+
63+
### Using the attribute with manual processing
64+
65+
If you create tools manually (without `WithMcpApps()`), you can still use the attribute and process tools explicitly:
66+
67+
```csharp
68+
var tools = new[]
69+
{
70+
McpServerTool.Create(typeof(WeatherTools).GetMethod(nameof(WeatherTools.GetWeather))!),
71+
McpServerTool.Create(typeof(WeatherTools).GetMethod(nameof(WeatherTools.GetForecast))!),
72+
};
73+
74+
McpApps.ApplyAppUiAttributes(tools);
75+
```
76+
77+
### Using the programmatic API
78+
79+
For full control, use `McpApps.SetAppUi` to set UI metadata directly:
80+
81+
```csharp
82+
var tool = McpServerTool.Create((string location) => $"Weather for {location}");
83+
84+
McpApps.SetAppUi(tool, new McpUiToolMeta
85+
{
86+
ResourceUri = "ui://weather/view.html",
87+
Visibility = [McpUiToolVisibility.Model, McpUiToolVisibility.App],
88+
});
89+
```
90+
91+
## Checking client capabilities
92+
93+
During a session, you can check whether the connected client supports MCP Apps:
94+
95+
```csharp
96+
[McpServerTool, Description("Get weather")]
97+
[McpAppUi(ResourceUri = "ui://weather/view.html")]
98+
public static string GetWeather(McpServer server, string location)
99+
{
100+
var uiCapability = McpApps.GetUiCapability(server.ClientCapabilities);
101+
if (uiCapability is not null)
102+
{
103+
// Client supports MCP Apps — the UI will be displayed
104+
}
105+
106+
return $"Weather for {location}";
107+
}
108+
```
109+
110+
## Tool visibility
111+
112+
The `Visibility` property controls which principals can invoke the tool:
113+
114+
| Value | Meaning |
115+
| - | - |
116+
| `McpUiToolVisibility.Model` | Only the LLM can call this tool |
117+
| `McpUiToolVisibility.App` | Only the app UI can call this tool |
118+
| Both (or null/empty) | Both the model and app can call the tool (default) |
119+
120+
## UI resources
121+
122+
UI resources are HTML pages registered with the MCP server using the `ui://` URI scheme and the `text/html;profile=mcp-app` MIME type. The `McpUiResourceMeta` type provides metadata for these resources, including:
123+
124+
- **CSP (Content Security Policy)** — Controls allowed origins for network requests and resource loads
125+
- **Permissions** — Sandbox permissions (scripts, forms, popups, etc.)
126+
- **Domain** — Dedicated origin for OAuth flows and CORS
127+
- **PrefersBorder** — Whether the host should render a visual border
128+
129+
## Constants
130+
131+
The <xref:ModelContextProtocol.Server.McpApps> class provides constants for protocol values:
132+
133+
| Constant | Value | Usage |
134+
| - | - | - |
135+
| `McpApps.ResourceMimeType` | `text/html;profile=mcp-app` | MIME type for UI resources |
136+
| `McpApps.ExtensionId` | `io.modelcontextprotocol/ui` | Key in `extensions` capability dictionary |
137+
138+
## Serialization
139+
140+
MCP Apps types use source-generated JSON serialization for Native AOT compatibility. Use `McpApps.SerializerOptions` when serializing extension types:
141+
142+
```csharp
143+
var json = JsonSerializer.Serialize(toolMeta, McpApps.SerializerOptions);
144+
var deserialized = JsonSerializer.Deserialize<McpUiToolMeta>(json, McpApps.SerializerOptions);
145+
```

docs/concepts/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@ Install the SDK and build your first MCP client and server.
3939
| [Stateless and Stateful](stateless/stateless.md) | Learn when to use stateless vs. stateful mode for HTTP servers and how to configure sessions. |
4040
| [HTTP Context](httpcontext/httpcontext.md) | Learn how to access the underlying `HttpContext` for a request. |
4141
| [MCP Server Handler Filters](filters.md) | Learn how to add filters to the handler pipeline. Filters let you wrap the original handler with additional functionality. |
42+
43+
### Extensions
44+
45+
| Title | Description |
46+
| - | - |
47+
| [MCP Apps](apps/apps.md) | Learn how to use the MCP Apps extension to deliver interactive UIs from MCP servers. |

docs/concepts/toc.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,8 @@ items:
4444
- name: HTTP Context
4545
uid: httpcontext
4646
- name: Filters
47-
uid: filters
47+
uid: filters
48+
- name: Extensions
49+
items:
50+
- name: MCP Apps
51+
uid: apps

0 commit comments

Comments
 (0)