Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
[This topic is pre-release documentation and is subject to change.]
This article explains how to use AI code generation tools like GitHub Copilot CLI or Claude Code to generate interactive model context protocol (MCP) apps for your model-driven Power Apps MCP tools. MCP apps are self-contained HTML files that render a tool's JSON output visually as cards, charts, dashboards, or maps inside any MCP Apps compatible host, including Microsoft 365 Copilot, Claude, and Visual Studio Code.
If you have an MCP tool that returns JSON data, the generate-mcp-app-ui skill can produce a polished, theme-aware widget that displays that data in a compact visual format directly inside a chat conversation.
Important
- This is a preview feature.
- Preview features aren’t meant for production use and may have restricted functionality. These features are available before an official release so that customers can get early access and provide feedback.
- MCP apps support in Microsoft 365 Copilot Chat is generally available as of March 2026. Power Apps support for MCP apps in declarative agents is currently in public preview. For the full announcement, see MCP Apps now available in Copilot Chat.
What you can do with the generate-mcp-app-ui skill
- Create visual widgets for any MCP tool by describing what you want and pasting the tool's JSON output.
- Choose the right visual for your data, such as charts for numeric trends, cards for structured records, tables for comparisons, maps for coordinates, and so on.
- Support light and dark themes automatically through Fluent UI design tokens.
- Add interactivity so widgets can call your tool again at runtime (for example, a refresh button).
- Refine the UX iteratively by describing changes in natural language. For example, "make the gallery compact," "add a chart," or "use a card layout."
Prerequisites
Software requirements
| Component | Minimum version | More information |
|---|---|---|
| GitHub Copilot CLI, Claude Code, or other code generation tool | Latest | Claude Code, GitHub Copilot CLI |
| A modern browser | Any | For previewing generated widgets locally |
Additional requirements
- An MCP tool that returns JSON output. Your tool's output type must be set to JSON.
- A working internet connection. Widgets load Fluent UI and other libraries from the Content Delivery Network (CDN) at runtime.
Install the plugin
Run the following installer command from GitHub Copilot CLI or Claude Code. The installer automatically detects available tools and installs all Power Platform plugins, including generate-mcp-app-ui.
/plugin marketplace add microsoft/power-platform-skills
To install only the MCP App widget skill:
/plugin install mcp-apps@power-platform-skills
Tip
Turn on auto-update to automatically receive skill updates. Use the /plugin command, navigate to Marketplaces, choose the marketplace, and turn on auto-update.
Skills overview
| Skill | Command | Description |
|---|---|---|
| MCP Apps widget generator | /generate-mcp-app-ui |
Generate a self-contained MCP app widget (HTML file) for an MCP tool's JSON output |
The skill is also triggered by natural language phrases such as "create a widget," "build a widget for my tool," or "make an MCP app."
Generate a widget
Follow these steps to create a new widget for an MCP tool.
Create and test a custom tool from model-driven app designers and copy the full JSON output. Make sure the tool's output type is set to JSON. More information: Create custom tools
Invoke the skill and describe what you want displayed, pasting the JSON output into the conversation:
/generate-mcp-app-ui Visualizes flights using an animated arc map for routes and a synchronized Gantt timeline for departure and arrival schedules, enabling quick understanding of flight coverage, timing, and overlaps. Here's an example of the tool's output: {"flight_records":[{"Departure Time":"2024-07-02T05:00:00Z","Arrival Time":"2024-07-02T07:30:00Z","Flight Name":"Zava 1001","Status":"Active","Airport":"Seattle-Tacoma","Airport1":"Los Angeles Intl"},{"Departure Time":"2024-07-02T03:00:00Z","Arrival Time":"2024-07-02T10:00:00Z","Flight Name":"Zava 103","Status":"Active","Airport":"Seattle-Tacoma","Airport1":"Hartsfield-Jackson"}]}Review the generated HTML file. The skill writes a self-contained HTML file, for example,
flight-map.html, to your working directory.Preview in a browser. Open the HTML file locally as widget has the fallback option for testing. You can ask chat agent to add standalone HTML preview if missing.
Iterate. Describe any changes directly in the chat:
- "Make the map larger"
- "Add tool tips on the Chart"
- "Decrease the height and fit in 250 pixels with responsive layout and no scroll bars"
Note
The skill requires actual JSON from your tool—not sample or mock data. The data shape drives the widget generation. If you paste mock data, the generated widget might not work correctly when connected to the real tool.
Deploy your widget
Once your widget is ready, copy the HTML file to the UX input for corresponding tool and it will be returned as the tool's UI response. Refer to your create custom tools documentation for details.
Add interactivity with callServerTool
If you also provide your tool's name when invoking the skill, the generated widget can include interactive tool-call integration. This allows the widget to call your tool again at runtime. For example a refresh button on the tool UX can call itself.
/generate-mcp-app-ui Show the current weather conditions with a refresh button. Tool name: get_weather. Tool output: {"city":"Seattle","temp_f":54,"condition":"Overcast","humidity":78,"forecast":[...]}
The skill wires up app.callServerTool in the widget so that when users select Refresh, the widget fetches updated data directly from your tool.
If you don't provide a tool name, the widget is read-only and renders only the data delivered through the ontoolresult callback.
- Microsoft 365 Copilot chat: See MCP apps in Copilot Chat for deployment paths including sideloading for testing, deploying through the Microsoft 365 admin center for organizational use, and publishing to the Microsoft 365 agent store.
- Power Apps declarative agents: See Power Apps MCP declarative agent documentation for how to connect MCP tools with model-driven apps.
- Other MCP hosts: Consult your host's documentation for the MCP apps widget registration process.
Widget technical details
MCP apps protocol
Widgets communicate with the chat host using the App class from the @modelcontextprotocol/ext-apps package. The protocol manages these callbacks and methods.
| Callback / method | Description |
|---|---|
app.ontoolresult |
Fires when the host delivers tool data. Your data is always at result.structuredContent—not result.data or result itself. |
app.onhostcontextchanged |
Fires when the host context changes, including theme (ctx.theme is 'light' or 'dark'). |
app.onteardown |
Fires when the widget is removed from the conversation. |
app.connect() |
Establishes communication with the host. All event handlers must be registered before calling connect(). |
app.getHostContext() |
Returns the current host context (including initial theme) after connect() completes. |
app.callServerTool({ name, arguments }) |
Calls a tool interactively. Returns result.isError and result.structuredContent. |
CDN imports
Widgets load all dependencies from CDN. No build step or local installation is required. Dependencies come in two formats:
ECMAScript Modules (ESM) — imported inside
<script type="module">using a URL ending in/+esmUniversal Module Definition (UMD) — loaded via a plain
<script src>tag; registers itself globally as a side effectLibrary Format URL Purpose @modelcontextprotocol/ext-appsESM cdn.jsdelivr.net/npm/@modelcontextprotocol/ext-apps/+esmMCP apps Appclass@fluentui/tokensESM cdn.jsdelivr.net/npm/@fluentui/tokens/+esmwebLightTheme/webDarkThemetoken sets@fluentui/web-components@betaUMD unpkg.com/@fluentui/web-components@beta/dist/web-components.min.jsFluent UI custom elements
Visual states
Every widget handles three states:
| State | Guidance |
|---|---|
| Loading | Show a <fluent-spinner> with a contextual message ("Finding attractions…" not just "Loading…"). |
| Loaded | Render the content compactly. Use the full available width. |
| Error | Show a friendly message and a "Try again" button. If the widget uses callServerTool, the button re-invokes the tool. |
Fluent UI components
The following Fluent UI web components are available in widgets:
<fluent-card>, <fluent-button>, <fluent-text-input>, <fluent-textarea>, <fluent-dropdown>, <fluent-listbox>, <fluent-option>, <fluent-checkbox>, <fluent-spinner>, <fluent-divider>, <fluent-badge>, <fluent-switch>, <fluent-tooltip>
Theme support
Widgets support light and dark themes through Fluent UI design tokens. The widget applies the correct token values when the host's theme changes via onhostcontextchanged. Always use token variables, for example, var(--colorNeutralForeground1), rather than hardcoded color values to ensure correct rendering in both themes.
Color tokens
| Use | Token |
|---|---|
| Primary text | var(--colorNeutralForeground1) |
| Secondary text | var(--colorNeutralForeground2) |
| Primary background | var(--colorNeutralBackground1) |
| Card/hover background | var(--colorNeutralBackground2) |
| Brand/accent | var(--colorBrandBackground) |
| Text on brand surface | var(--colorNeutralForegroundOnBrand) |
| Borders | var(--colorNeutralStroke1) |
| Error text | var(--colorStatusDangerForeground1) |
| Success text | var(--colorStatusSuccessForeground1) |
Never use hardcoded hexidecimal or RGB values. Don't invent token names not listed here.
Best practices
- Provide real test data. The skill analyzes the actual JSON structure to select the right visual. Mock data produces widgets that break when connected to the real tool.
- Be specific about the visual. Describe the format you want, such as map, chart, table, or card layout. Vague descriptions lead to generic results.
- Start with one view. Widgets are compact conversation cards, not full applications. No tabs, page navigation, or search bars that duplicate the chat input.
- Test with both themes. Preview in light and dark mode to verify contrast and readability.
- Match the visual to the data. Maps for coordinates, charts for numeric or trend data, cards for structured records, tables for comparisons.
Limitations
- Widgets must load all external libraries from CDN. An internet connection is required at runtime.
- Full screen display mode requires additional implementation beyond what the skill generates.
- The skill doesn't handle MCP server registration or deployment to the Microsoft 365 admin center. You must complete those steps separately.
- Authentication (OAuth 2.1, Microsoft Entra SSO) is handled by the MCP host environment, not the widget HTML itself.