Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
},
{
"name": "microsoft-365-agents-toolkit",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, and eval workflows.",
"version": "1.3.1",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, serverless MCP Apps hosting on Azure Functions, and eval workflows.",
"version": "1.4.0",
"source": "./plugins/microsoft-365-agents-toolkit"
},
{
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ plugins/<plugin-name>/
- `declarative-agent-developer` skill — Scaffolding, JSON manifest authoring, capability configuration, deployment
- `teams-app-developer` skill — Build, test, and deploy code-based Teams apps: bots, CEA, tabs, message extensions, Agents Playground, Azure provision/deploy, and Slack-to-Teams migration
- `ui-widget-developer` skill — Build MCP servers with OpenAI Apps SDK widget rendering for Copilot Chat
- `mcp-apps-azure-functions` skill — Scaffold, run, and deploy a serverless MCP Apps server on Azure Functions (C# / .NET) with azd + Flex Consumption
- `m365-agent-evaluator` skill — Generate, run, and analyze evaluation suites for M365 Copilot declarative agents

- **workiq-productivity** — Read-only WorkIQ productivity insights. Bundles:
Expand Down
5 changes: 4 additions & 1 deletion PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ copilot plugin uninstall workiq-productivity
|---|--------|--------|-------------|
| 1 | [**workiq**](#workiq) | 1 | Full WorkIQ tool surface — agentic queries plus direct M365 reads and writes |
| 2 | [**workiq-preview**](#workiq-preview) | 1 | Preview build with the full entity tool surface (read + write) |
| 3 | [**microsoft-365-agents-toolkit**](#microsoft-365-agents-toolkit) | 4 | Toolkit for building M365 Copilot declarative agents |
| 3 | [**microsoft-365-agents-toolkit**](#microsoft-365-agents-toolkit) | 5 | Toolkit for building M365 Copilot declarative agents |
| 4 | [**workiq-productivity**](#workiq-productivity) | 9 | Read-only productivity insights across M365 |

---
Expand Down Expand Up @@ -162,6 +162,7 @@ copilot plugin uninstall workiq-productivity
| [**install-atk**](./plugins/microsoft-365-agents-toolkit/skills/install-atk/SKILL.md) | Install or update the M365 Agents Toolkit CLI and VS Code extension |
| [**declarative-agent-developer**](./plugins/microsoft-365-agents-toolkit/skills/declarative-agent-developer/SKILL.md) | Scaffolding, JSON manifest authoring, capability configuration, deployment |
| [**ui-widget-developer**](./plugins/microsoft-365-agents-toolkit/skills/ui-widget-developer/SKILL.md) | Build MCP servers with OpenAI Apps SDK widget rendering for Copilot Chat |
| [**mcp-apps-azure-functions**](./plugins/microsoft-365-agents-toolkit/skills/mcp-apps-azure-functions/SKILL.md) | Scaffold, run, and deploy a serverless MCP Apps server on Azure Functions (C# / .NET) with azd + Flex Consumption |
| [**m365-agent-evaluator**](./plugins/microsoft-365-agents-toolkit/skills/m365-agent-evaluator/SKILL.md) | Generate, run, and analyze evaluation suites for M365 Copilot declarative agents |

### Example prompts
Expand All @@ -170,6 +171,8 @@ copilot plugin uninstall workiq-productivity
"Scaffold a new declarative agent for HR FAQ"
"Add web search to my agent"
"Deploy my agent with ATK"
"Scaffold a serverless MCP Apps server on Azure Functions in C#"
"Deploy my MCP Apps server to Azure Flex Consumption with azd"
"Create eval prompts for my agent"
"Run my evals and explain the failures"
"Improve my agent instructions based on the latest eval results"
Expand Down
4 changes: 2 additions & 2 deletions marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
{
"name": "microsoft-365-agents-toolkit",
"source": "./plugins/microsoft-365-agents-toolkit",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, and eval workflows.",
"version": "1.3.1"
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, serverless MCP Apps hosting on Azure Functions, and eval workflows.",
"version": "1.4.0"
},
{
"name": "workiq-productivity",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "microsoft-365-agents-toolkit",
"version": "1.3.1",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, and eval workflows.",
"version": "1.4.0",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, serverless MCP Apps hosting on Azure Functions, and eval workflows.",
"skills": "./skills/"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "microsoft-365-agents-toolkit",
"version": "1.3.1",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, and eval workflows.",
"version": "1.4.0",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, serverless MCP Apps hosting on Azure Functions, and eval workflows.",
"skills": "./skills/"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "microsoft-365-agents-toolkit",
"version": "1.3.1",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, and eval workflows.",
"version": "1.4.0",
"description": "Toolkit for building and evaluating Microsoft 365 Copilot declarative agents \u2014 scaffolding, JSON manifest development, capability configuration, serverless MCP Apps hosting on Azure Functions, and eval workflows.",
"skills": "./skills/"
}
1 change: 1 addition & 0 deletions plugins/microsoft-365-agents-toolkit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ npx -y --package @microsoft/m365-copilot-eval@latest runevals --prompts-file eva
| [**install-atk**](./skills/install-atk/SKILL.md) | Install or update the ATK CLI and VS Code extension |
| [**declarative-agent-developer**](./skills/declarative-agent-developer/SKILL.md) | Scaffolding, JSON manifest authoring, capability configuration, security patterns, deployment via ATK CLI |
| [**ui-widget-developer**](./skills/ui-widget-developer/SKILL.md) | Build MCP servers with OpenAI Apps SDK widget rendering for Copilot Chat |
| [**mcp-apps-azure-functions**](./skills/mcp-apps-azure-functions/SKILL.md) | Scaffold, run, and deploy a serverless MCP Apps server on Azure Functions (C# / .NET) with azd + Flex Consumption |
| [**m365-agent-evaluator**](./skills/m365-agent-evaluator/SKILL.md) | Generate, run, and analyze evaluation suites for M365 Copilot declarative agents |

## License
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
---
name: mcp-apps-azure-functions
description: >
Scaffold, run, and deploy a serverless MCP Apps server on Azure Functions (C# / .NET isolated)
with the Azure Functions MCP extension and the Azure Developer CLI (azd). MCP Apps are MCP servers
whose tools return rich interactive UI widgets. Use when the user wants a serverless, pay-per-use
host for an MCP Apps server on the Flex Consumption plan. Covers: azd template init
(remote-mcp-functions-dotnet), building the UI app, McpToolTrigger + McpResourceTrigger +
McpMetadata patterns, local run with Azurite + Functions Core Tools, verifying with GitHub Copilot,
and deploy via azd or func with built-in Microsoft Entra auth. DO NOT USE FOR: building the MCP
server + widget without serverless hosting (use ui-widget-developer) or scaffolding the declarative
agent (use declarative-agent-developer). Triggers: "MCP Apps on Azure Functions", "serverless MCP
server", "MCP server Azure Functions C#", "azd MCP Apps", "Flex Consumption MCP", "McpToolTrigger",
"remote-mcp-functions-dotnet"
---

# MCP Apps on Azure Functions (Serverless, C# / .NET)

Build and deploy a **serverless MCP Apps server** on **Azure Functions** using the **Azure Functions
MCP extension** (C# / .NET isolated) and the **Azure Developer CLI (`azd`)**. The result is an MCP
server whose tools return **rich interactive UI widgets** — hosted on the **Flex Consumption** plan
(pay-for-what-you-use) and secured by default with **Microsoft Entra** built-in authorization.

Based on the official quickstart: [Build an MCP Apps server using Azure Functions](https://learn.microsoft.com/azure/azure-functions/scenario-mcp-apps?pivots=programming-language-csharp)
and the template repo [Azure-Samples/remote-mcp-functions-dotnet](https://github.com/Azure-Samples/remote-mcp-functions-dotnet).

## When to use

- The user wants a **serverless** hosting option for an MCP Apps server (no always-on server/VM).
- The user wants **C# / .NET** on Azure Functions with the MCP extension.
- The user wants an `azd` + Bicep deployment to the **Flex Consumption** plan following best practices.
- The user wants an MCP server whose tools render **interactive UI** (MCP Apps standard) in Copilot.

## When NOT to use

| Situation | Use instead |
|-----------|-------------|
| Build the MCP server + widget code itself (any host), design widgets | `ui-widget-developer` |
| Scaffold or configure the **declarative agent** (manifest, capabilities, deploy the agent) | `declarative-agent-developer` |
| Generate/run **evals** for an agent | `m365-agent-evaluator` |

> This skill focuses on the **serverless hosting path** on Azure Functions. It scaffolds a working
> MCP Apps server from the official template and takes it to production on Azure.

## Architecture

```
MCP host (Copilot / VS Code) ──▶ Remote MCP server on Azure Functions ──▶ MCP tool (McpToolTrigger)
(Flex Consumption, Entra auth) │ returns JSON data
ui.resourceUri ──▶ MCP resource (McpResourceTrigger)
serves bundled HTML widget
at ui://weather/index.html
```

An MCP Apps tool requires **two components**:
1. A **tool with UI metadata** that declares a `ui.resourceUri` (via `[McpMetadata]`).
2. A **resource** that serves the bundled HTML/JS at the matching `ui://` URI (via `[McpResourceTrigger]`).

## Prerequisites

Install/verify these before scaffolding (install automatically when missing — see Automation rules):

| Tool | Notes |
|------|-------|
| [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) | Required by the .NET isolated template |
| [Azure Functions Core Tools](https://learn.microsoft.com/azure/azure-functions/functions-run-local) `>= 4.5.0` | Local run + `func` publish |
| [Azure Developer CLI (`azd`)](https://aka.ms/azd) `1.23.x`+ | Provision + deploy |
| [Node.js 22](https://nodejs.org/) | Build the MCP Apps UI (`npm run build`) |
| [Azurite](https://learn.microsoft.com/azure/storage/common/storage-use-azurite) (or Docker) | Local storage emulator |
| [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) + Azure subscription | Auth + deployment target |

Optional but recommended: VS Code with the **Azure Functions** and **Azure Developer CLI** extensions.

## Workflow

### 1. Scaffold from the official azd template

```bash
azd init --template remote-mcp-functions-dotnet -e mcpweather-dotnet
cd remote-mcp-functions-dotnet
```

`-e` sets the `azd` environment name (used for the deployment context and resource names). This pulls the
full project (functions, `infra/` Bicep, `.vscode/mcp.json`, `azure.yaml`). The MCP Apps demo lives under
`src/McpWeatherApp` (with the UI app in `src/McpWeatherApp/app`).

### 2. Build the MCP Apps UI

The widget UI must be built before running — the resource serves `app/dist/index.html`.

```bash
cd src/McpWeatherApp/app
npm install
npm run build
cd ../
```

### 3. Start the storage emulator (Azurite)

Start Azurite before running the Functions host. VS Code: press F1 → `Azurite: Start`. CLI: run `azurite`
in a background process, or start the Azurite Docker container. See [references/deployment.md](references/deployment.md#local-storage-azurite).

### 4. Run the MCP server locally

- **VS Code:** press F5 (Run and Debug). When prompted, select **`src/McpWeatherApp`**.
- **CLI:** from `src/McpWeatherApp`, run `func start`.

The Functions host prints the running functions (`GetWeather`, `GetWeatherWidget`) and the local MCP endpoint.

> Spawn the Functions host and Azurite as **independent background OS processes** (see Automation rules) so
> they survive between agent turns.

### 5. Verify with GitHub Copilot

The template ships a `.vscode/mcp.json` with a `local-mcp-function` server pointing at your local endpoint.

1. With the host running, open `.vscode/mcp.json` and click **Start** above `local-mcp-function`.
2. In Copilot Chat, select **Agent** mode → **Configure tools** → enable `MCP Server: local-mcp-function`.
3. Prompt: `What's the weather in Seattle?` → approve the tool run. Because the tool declares UI metadata,
the host fetches the UI resource and renders the **interactive weather widget** in a sandboxed iframe.

### 6. Review / adapt the code

The MCP App is defined in `src/McpWeatherApp` using `[McpToolTrigger]`, `[McpMetadata]`, and
`[McpResourceTrigger]`. To rename the tool or add your own tool + widget, follow the C# patterns in
**[references/csharp-code-patterns.md](references/csharp-code-patterns.md)**.

### 7. Deploy to Azure (serverless)

`azd` provisions a Flex Consumption function app via the included Bicep and deploys the app:

```bash
azd env set DEPLOY_SERVICE weather
azd provision # pick subscription + region; vnetEnabled = false to simplify
azd deploy --service weather
```

For the full deployment flow, the Core Tools alternative, remote connection, cost notes, and
troubleshooting, see **[references/deployment.md](references/deployment.md)**.

### 8. Connect to the remote server & clean up

- Get the app name: `azd env get-value AZURE_FUNCTION_NAME`.
- In `.vscode/mcp.json`, click **Start** above `remote-mcp-function`; enter the app name; complete the
Microsoft Entra sign-in (built-in MCP authorization is on by default). Re-run the same Copilot prompt.
- When finished, remove all resources: `azd down`.

## Automation rules

- **Full automation:** install missing tools, authenticate, build the UI, start Azurite + the Functions
host, and deploy — do not ask the user to run commands manually. Only stop for interactive input that
genuinely requires the user (Azure sign-in / device code, subscription & region selection).
- **Background processes:** the Functions host (`func start` / F5) and Azurite must run as **detached OS
processes**, not inside the agent shell session (which is killed between turns). On Windows use
`Start-Process -WindowStyle Hidden`; on Linux/Mac use `nohup ... &`. Save PIDs to stop them later.
- **Build before run:** always run `npm run build` in the UI `app/` folder before starting the host, or
the widget resource returns the fallback HTML.
- **Tool naming:** MCP tool names must match `^[A-Za-z0-9_]+$` (no hyphens).
- **Region:** `azd provision` only lists regions that currently support the **Flex Consumption** plan.

## Authentication & SSO

The `remote-mcp-functions-dotnet` template secures the deployed server with **built-in Microsoft Entra
authorization** (App Service Authentication / "Easy Auth"), provisioned automatically by its Bicep — no
custom token guard is required. Because SSO is built in, you typically do **not** need `setup-sso-ui-widget`
here (that skill is for Express/raw-http servers). Use these for the model and for hardening:

- **Token-flow mental model** (how the Copilot SSO token is issued/validated and how claims reach your
tool): [`setup-sso-ui-widget` → sso-explained.md](../setup-sso-ui-widget/references/sso-explained.md).
- **Harden the Function app's Authentication blade** — audience = **client id** (not the `api://…` URI)
and allow-list the **Copilot host client id**; the same App Service Authentication feature applies to
Function apps: [`setup-sso-ui-widget` → easy-auth.md](../setup-sso-ui-widget/references/easy-auth.md).
- **Adding SSO to a server-full Express / raw-http MCP server** (from `ui-widget-developer` /
`create-mcp-app`): [`setup-sso-ui-widget`](../setup-sso-ui-widget/SKILL.md).
- **Entra SSO vs third-party OAuth** patterns for the plugin manifest:
[`declarative-agent-developer` → authentication.md](../declarative-agent-developer/references/authentication.md).

## References

- [references/csharp-code-patterns.md](references/csharp-code-patterns.md) — `McpToolTrigger`,
`McpResourceTrigger`, `McpMetadata`, the `ui.resourceUri` contract, and how to add a new tool + widget.
- [references/deployment.md](references/deployment.md) — `azd` provision/deploy, `func` Core Tools
alternative, Flex Consumption, Entra built-in auth, Azurite, cost, and troubleshooting.
Loading