[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-microsoft-ui-widget-developer":3,"mdc-6nn7si-key":37,"related-org-microsoft-ui-widget-developer":4427,"related-repo-microsoft-ui-widget-developer":4619},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":26,"repoUrl":27,"updatedAt":28,"license":29,"forks":30,"topics":31,"repo":32,"sourceUrl":35,"mdContent":36},"ui-widget-developer","build MCP servers with UI widget support","Build MCP servers for Copilot Chat using the OpenAI Apps SDK or MCP Apps SDK widget rendering support (any language). Use this skill when:\n- Creating MCP servers that integrate with M365 Copilot declarative agents\n- Building rich interactive widgets (React + Fluent UI) that render in Copilot Chat\n- Implementing tools that return structuredContent for widget rendering\n- Adapting an existing MCP server to support Copilot widget rendering\n- Setting up devtunnels for localhost MCP server exposure\n- Configuring mcpPlugin.json manifests with RemoteMCPServer runtime\nDo NOT use this skill for general agent development (scaffolding, manifests, deployment) — use declarative-agent-developer instead. This skill is ONLY for MCP server + widget development.\nTriggers: \"MCP server for Copilot\", \"OpenAI Apps SDK\", \"Copilot widget\", \"structuredContent\", \"MCP plugin\", \"devtunnels MCP\", \"OAI app\", \"widget rendering\", \"UI widget\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"microsoft","Microsoft","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fmicrosoft.png",[12,16,17,20,23],{"name":13,"slug":14,"type":15},"Copilot","copilot","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"MCP","mcp",{"name":21,"slug":22,"type":15},"Agents","agents",{"name":24,"slug":25,"type":15},"API Development","api-development",947,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fwork-iq","2026-07-18T05:15:52.988447",null,109,[],{"repoUrl":27,"stars":26,"forks":30,"topics":33,"description":34},[],"MCP Server and CLI for accessing Work IQ","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fwork-iq\u002Ftree\u002FHEAD\u002Fplugins\u002Fmicrosoft-365-agents-toolkit\u002Fskills\u002Fui-widget-developer","---\nname: ui-widget-developer\ndescription: |\n  Build MCP servers for Copilot Chat using the OpenAI Apps SDK or MCP Apps SDK widget rendering support (any language). Use this skill when:\n  - Creating MCP servers that integrate with M365 Copilot declarative agents\n  - Building rich interactive widgets (React + Fluent UI) that render in Copilot Chat\n  - Implementing tools that return structuredContent for widget rendering\n  - Adapting an existing MCP server to support Copilot widget rendering\n  - Setting up devtunnels for localhost MCP server exposure\n  - Configuring mcpPlugin.json manifests with RemoteMCPServer runtime\n  Do NOT use this skill for general agent development (scaffolding, manifests, deployment) — use declarative-agent-developer instead. This skill is ONLY for MCP server + widget development.\n  Triggers: \"MCP server for Copilot\", \"OpenAI Apps SDK\", \"Copilot widget\", \"structuredContent\", \"MCP plugin\", \"devtunnels MCP\", \"OAI app\", \"widget rendering\", \"UI widget\"\n---\n\n# Copilot MCP Server Development\n\n## Telemetry Tagging\n\nBefore running any `atk` CLI commands, set the session environment variable so all CLI invocations are tagged as skill-initiated:\n```bash\nexport ATK_CLI_SKILL=true\n```\nRun this once at the start of the session. All subsequent `atk` commands in the same terminal will inherit it.\n\n## 🔀 PATH SELECTION\n\n**Before proceeding, ask the user which path they want to take using AskUserQuestion.** Both are supported for M365 Copilot widget rendering. Present the tradeoffs and let them choose:\n\n| | **OAI Apps** (this skill) | **MCP Apps Extension** (`modelcontextprotocol\u002Fext-apps`) |\n|---|---|---|\n| **Standard** | OpenAI-specific | Official MCP standard |\n| **Works in** | ChatGPT + M365 Copilot | M365 Copilot, ChatGPT, VSCode, and more |\n| **Maturity** | Battle-tested, production-ready | New official standard, growing ecosystem |\n| **Design** | OpenAI Apps SDK | MCP Apps protocol (cross-platform) |\n| **When to choose** | Existing OAI app investment | Prefer the open standard, want broadest client support |\n\n**Ask:** _\"Would you like to build an OAI app (OpenAI Apps SDK — battle-tested, works in ChatGPT and M365 Copilot) or an MCP app (new official standard — works in M365 Copilot, ChatGPT, VSCode, and more)?\"_\n\n- **OAI apps** → Continue below. This skill covers everything you need.\n- **MCP apps** → Install the `modelcontextprotocol\u002Fext-apps` plugin (see below), then use the appropriate skill from that plugin.\n\n### MCP Apps: Install ext-apps Plugin\n\nIf the user chooses MCP Apps, do this automatically (do not stop at explanation-only):\n\n1. Run `\u002Fplugin marketplace add modelcontextprotocol\u002Fext-apps`\n2. Run `\u002Fplugin install mcp-apps@mcp-apps`\n3. Confirm the plugin is available, then invoke the correct ext-apps skill based on user intent\n\nIf plugin commands are unavailable in the current environment, provide the exact commands below and ask the user to run them once, then continue by invoking the selected ext-apps skill.\n\nReference commands:\n\n```\nTo build an MCP App, install the ext-apps plugin from the marketplace:\n\n1. \u002Fplugin marketplace add modelcontextprotocol\u002Fext-apps\n2. \u002Fplugin install mcp-apps@mcp-apps\n\nThen use one of these skills from that plugin:\n- create-mcp-app      — Scaffold a new MCP App with interactive UI from scratch\n- add-app-to-server   — Add interactive UI to an existing MCP server's tools\n- migrate-oai-app     — Convert an existing OAI app to use MCP Apps\n- convert-web-app     — Turn a web app into a hybrid web + MCP App\n\nAfter installing, invoke the relevant skill to continue.\n```\n\n> **Note:** The ext-apps plugin lives in the external `modelcontextprotocol\u002Fext-apps` marketplace — it is not part of this plugin collection.\n\n**Handoff mapping after install:**\n- New MCP app from scratch → `create-mcp-app`\n- Add app UI to existing MCP server → `add-app-to-server`\n- Migrate existing OAI app → `migrate-oai-app`\n- Convert an existing web app → `convert-web-app`\n\n---\n\n## 📛 PROJECT DETECTION 📛\n\nThis skill triggers when building MCP servers with OAI app or widget rendering for Microsoft 365 Copilot Chat. The MCP server can be written in any language that supports the MCP protocol (TypeScript, Python, C#, etc.). The agent project and MCP server may live in the same repo, separate folders, or entirely different projects.\n\n## Scenario Routing\n\n| Starting Point | What You Need | Path |\n|---------------|---------------|------|\n| **Prefer MCP Apps standard** | Cross-platform widget support (M365 Copilot, ChatGPT, VSCode, and more) | Install `modelcontextprotocol\u002Fext-apps`, then use `create-mcp-app` or `add-app-to-server` — see [Path Selection](#-path-selection) above |\n| **From scratch** (no agent, no MCP server) | Full OAI app setup | Delegate agent scaffolding to `declarative-agent-developer` first, then return here for MCP server + widgets |\n| **Existing M365 agent, new MCP server** | MCP server + widgets + mcpPlugin.json | Start at [Implementation](#implementation) |\n| **Existing MCP server, add Copilot widgets** | Widget support added to existing server | Start at [Copilot Widget Protocol](references\u002Fcopilot-widget-protocol.md#adaptation-checklist-existing-mcp-server) |\n| **Language choice** (non-TypeScript) | Protocol requirements | See [Copilot Widget Protocol](references\u002Fcopilot-widget-protocol.md) for what to implement, [MCP Server Pattern (TypeScript)](references\u002Fmcp-server-pattern.md) as a reference |\n\n---\n\n## 🚨 CRITICAL EXECUTION RULES 🚨\n\n\n**FLUENT UI ENFORCEMENT (REQUIRED):** Widget implementations MUST use React + Fluent UI components. Before writing any widget code, the agent MUST read and follow:\n- `references\u002Fwidget-patterns.md`\n- `references\u002Fbest-practices.md`\n**FLUENT UI PACKAGE REQUIREMENT (REQUIRED):** The widget project MUST include Fluent UI dependencies before implementation. At minimum, install and keep these in the widget package dependencies:\n- `@fluentui\u002Freact-components`\n- `react`\n- `react-dom`\n\nIf any of these packages are missing, install them automatically before continuing with widget code generation.\n\nIf the generated widget does not include React entry files (for example `widgets\u002Fsrc\u002F\u003Cwidget-name>\u002Fmain.tsx` and a React component file) and Fluent imports from `@fluentui\u002Freact-components`, the task is incomplete and MUST be corrected before returning results.\n\n**NO RAW HTML-ONLY WIDGETS (DEFAULT):** Do not implement app content directly with static HTML templates and inline JS as the final widget solution. A minimal shell HTML file is allowed only as a loader for built React assets. Raw\u002Fself-contained HTML-only widgets are allowed only when the user explicitly requests a non-React prototype.\n\n**SSO HANDOFF (REQUIRED AT COMPLETION):** Once the ui-widget agent is fully scaffolded, running, and provisioned, your final completion summary MUST end by offering the optional SSO next step — see [Next Step — Add SSO](#next-step--add-sso-optional). List it in your \"next steps\" and ask the user if they want to wire Entra SSO via the `setup-sso-ui-widget` skill. Do NOT omit this offer, even if you also list other suggestions.\n\n**BACKGROUND PROCESSES:** MCP server and devtunnel MUST be spawned as independent OS processes — NOT run inside the agent's shell session. `isBackground: true`, `mode: \"async\"`, and `Start-Job` all run inside the agent's shell session and will be killed between messages. The only reliable approach is to spawn a detached OS process.\n\n**Windows — use `Start-Process -WindowStyle Hidden`:**\n```powershell\n# Start devtunnel\n$t = Start-Process -FilePath \"devtunnel\" `\n    -ArgumentList \"host\",\"\u003Ctunnel-name>\",\"-a\" `\n    -WindowStyle Hidden -PassThru `\n    -RedirectStandardOutput \"tunnel.log\" -RedirectStandardError \"tunnel-err.log\"\n\n# Start MCP server — use cmd.exe \u002Fc to set the working directory and inherit PATH\n$s = Start-Process -FilePath \"cmd.exe\" `\n    -ArgumentList \"\u002Fc\",\"cd \u002Fd \u003Cabs-path-to-mcp-server> && \u003Cstart-command>\" `\n    -WindowStyle Hidden -PassThru `\n    -RedirectStandardOutput \"server.log\" -RedirectStandardError \"server-err.log\"\n\n# Save PIDs so they can be stopped later\n\"$($t.Id),$($s.Id)\" | Out-File pids.txt\nWrite-Host \"Started tunnel PID $($t.Id), server PID $($s.Id)\"\n```\nTo stop: `Stop-Process -Id (Get-Content pids.txt).Split(',')` or `Stop-Process -Id \u003Cpid>`.\n\n**Linux\u002FMac — use `nohup` with `&`:**\n```bash\nnohup devtunnel host \u003Ctunnel-name> > tunnel.log 2>tunnel-err.log &\necho \"tunnel:$!\" >> pids.txt\nnohup \u003Cstart-command> > server.log 2>server-err.log &\necho \"server:$!\" >> pids.txt\n```\nTo stop: `kill $(grep -oP '\\d+' pids.txt)`.\n\nAfter starting, tail the logs to confirm both processes are up before proceeding:\n```powershell\n# Windows\nStart-Sleep 3; Get-Content tunnel.log, server.log\n```\n```bash\n# Linux\u002FMac\nsleep 3 && tail tunnel.log server.log\n```\n\n**FULL AUTOMATION:** Never tell the user to run commands manually. Install tools, authenticate, start services — do everything automatically. Only ask the user for interactive input that truly requires them (like device code confirmation during `devtunnel user login -g -d`). If a tool isn't installed, install it. If a service needs starting, start it. The user expects full automation.\n\n**PATH SELECTION (REQUIRED — STOP BEFORE ANY CODE):** You MUST use `AskUserQuestion` to ask the user whether they want OAI Apps or MCP Apps Extension before writing any code, running any commands, or making any architectural decisions.\n\n**There is no exception to this rule.** The most common failure mode is reasoning \"the user's request makes it obvious, so asking is redundant.\" This reasoning is always wrong — invoke `AskUserQuestion` regardless. A user saying \"build an MCP server with widgets\" is NOT an answer to this question. A user invoking this skill by name is NOT an answer. Only an explicit answer to the question counts. See [PATH SELECTION](#-path-selection) above for the exact question to ask.\n\n**AGENT PROVISIONING:** Re-provisioning is only required when the **agent manifest** changes (e.g., mcpPlugin.json tool definitions, MCP server URL, declarativeAgent.json, instruction.txt). MCP server code changes (tool implementations, React widget code, server logic) do **NOT** require re-provisioning the agent — running or deploying the server picks up changes automatically.\n\nWhen provisioning is needed:\n1. **Bump the version** in `manifest.json` (increment the patch version, e.g., `1.0.0` → `1.0.1`)\n2. **Deploy the agent:**\n   ```bash\n   npx -y --package @microsoft\u002Fm365agentstoolkit-cli atk provision --env local\n   ```\n\n**WIDGET TESTING LINKS:** Every time you return to the user with a result while the MCP server is running, you MUST include links to ALL widgets so they can test them locally. Format:\n```\n🧪 Test widgets locally:\n- http:\u002F\u002Flocalhost:3001\u002Fwidgets\u002Fwidget-name.html\n- http:\u002F\u002Flocalhost:3001\u002Fwidgets\u002Fanother-widget.html\n```\nList every `.html` file in the `mcp-server\u002Fwidgets\u002F` directory (or equivalent widget folder). This helps users verify widget rendering before testing in Copilot.\n\n**AUTO-DEPLOY ON COMPLETION (REQUIRED — DO NOT SKIP):** When coding is complete, proceed automatically without waiting for the user:\n1. Start MCP server + devtunnel in the background (per BACKGROUND PROCESSES above)\n2. Run E2E verification with MCP Inspector (per MCP TOOL CONFIGURATION RULE below) — fix any failures before continuing\n3. Provision the agent if needed (per AGENT PROVISIONING above)\n4. Print a project summary in this format:\n```\n## ✅ \u003CProject Name> — Ready\n\n### Widgets\n- [widget-name.html](http:\u002F\u002Flocalhost:\u003CPORT>\u002Fwidgets\u002Fwidget-name.html)\n- [widget-name2.html](http:\u002F\u002Flocalhost:\u003CPORT>\u002Fwidgets\u002Fwidget-name2.html)\n\n### Endpoints\n- MCP server: http:\u002F\u002Flocalhost:\u003CPORT>\u002Fmcp\n- MCP via tunnel: https:\u002F\u002F\u003Ctunnel-url>\u002Fmcp\n\n### Test in Copilot\nLocal:      https:\u002F\u002Fm365.cloud.microsoft\u002Fchat\u002F?titleId={M365_TITLE_ID from env\u002F.env.local}\nOther envs: {SHARE_LINK from env\u002F.env.{environment}}\n```\n\n**AGENT PROJECT DELEGATION:** This skill builds MCP servers and widgets, NOT declarative agent projects. If the user's request involves creating or configuring the declarative agent itself (scaffolding, `m365agents.yml`, `m365agents.local.yml`, `declarativeAgent.json`, manifest lifecycle), delegate to the `declarative-agent-developer` skill.\n\n**MCP RESOURCE REGISTRATION:** Every widget MUST have a matching MCP resource. Without resources, Copilot cannot fetch widget shells through the MCP protocol and widgets will not render.\n\nFor each new widget, complete this checklist:\n1. ☐ Create a widget shell HTML file in `widgets\u002F` and a React widget entry under `widgets\u002Fsrc\u002F\u003Cwidget-name>\u002F` (see widget-patterns.md)\n2. ☐ Define a `ui:\u002F\u002Fwidget\u002F\u003Cname>.html` URI constant\n3. ☐ Add a `Resource` entry to the `resources` array with:\n   - `uri`: the `ui:\u002F\u002Fwidget\u002F\u003Cname>.html` URI\n   - `mimeType`: `\"text\u002Fhtml+skybridge\"`\n   - `_meta`: CSP config with `openai\u002FwidgetDomain` and `openai\u002FwidgetCSP` (from environment)\n4. ☐ Add a handler for `resources\u002Fread` that returns the widget shell HTML for this URI\n5. ☐ Add the tool with `_meta.openai\u002FoutputTemplate` pointing to the same `ui:\u002F\u002Fwidget\u002F\u003Cname>.html` URI\n6. ☐ Verify the server capabilities include `resources: {}` in the initialize response\n\n**Widget shell + asset considerations:**\n- **Preferred (React + Fluent UI)**: Resource HTML should be a minimal shell that links to built JS\u002FCSS assets served from the MCP server's `\u002Fassets\u002F` route.\n- **Exception only**: Self-contained HTML via `resources\u002Fread` is for explicit user-requested prototypes only. Default and production path is React + Fluent UI.\n\nExample shell for React build output:\n  ```html\n  \u003C!doctype html>\u003Chtml>\u003Chead>\n    \u003Cscript type=\"module\" src=\"${serverUrl}\u002Fassets\u002Fmy-widget.js\">\u003C\u002Fscript>\n    \u003Clink rel=\"stylesheet\" href=\"${serverUrl}\u002Fassets\u002Fmy-widget.css\">\n  \u003C\u002Fhead>\u003Cbody>\n    \u003Cdiv id=\"widget-root\">\u003C\u002Fdiv>\n  \u003C\u002Fbody>\u003C\u002Fhtml>\n  ```\n  Use the `WIDGET_BASE_URL` or `MCP_SERVER_URL` environment variable for the asset URL base (see mcp-server-pattern.md \"Configurable Widget Base URL\" section).\n\nSee [mcp-server-pattern.md](references\u002Fmcp-server-pattern.md) for the complete resource and asset serving patterns.\n\n---\n\n## ⚠️ MCP TOOL CONFIGURATION RULE ⚠️\n\n**NEVER manually write tool definitions in `mcpPlugin.json`.** Always use MCP Inspector to get the complete tool definitions from the running MCP server.\n\n**TOOL NAMING CONVENTION:** Tool names MUST match the pattern `^[A-Za-z0-9_]+$` (letters, numbers, and underscores only). **NEVER use hyphens (-) in tool names.** Use underscores instead (e.g., `render_profile` not `render-profile`).\n\n**MANDATORY WORKFLOW:**\n1. **Start the MCP server** (in background)\n2. **Use MCP Inspector** to get the latest tool definitions:\n   ```bash\n   npx @modelcontextprotocol\u002Finspector@0.20.0 --cli https:\u002F\u002Fmy-mcp-server.example.com --transport http --method tools\u002Flist\n   ```\n3. **Copy the COMPLETE tool definition** from the inspector (including `name`, `description`, `inputSchema`, `_meta`, `annotations`, `title`)\n4. **Paste into `mcpPlugin.json`** under `runtimes[].spec.mcp_tool_description.tools` (inside the `RemoteMCPServer` runtime's `spec` object)\n5. **Run E2E verification** through the devtunnel — call each tool and confirm the response contains `structuredContent` and `_meta.openai\u002FwidgetAccessible: true`:\n   ```bash\n   npx @modelcontextprotocol\u002Finspector@0.20.0 --cli https:\u002F\u002F\u003Ctunnel-url>\u002Fmcp --transport http --method tools\u002Fcall --tool-name \u003Ctool_name>\n   ```\n   Also verify `GET https:\u002F\u002F\u003Ctunnel-url>\u002Fhealth` returns `{\"status\":\"ok\"}`. Fix any failures before provisioning.\n\nThe MCP Inspector shows the exact tool schema from your server. Copy it completely — do not manually write or modify these definitions. This ensures `mcpPlugin.json` stays in sync with the MCP server.\n\n---\n\nBuild MCP servers that integrate with Microsoft 365 Copilot Chat and render rich interactive widgets.\n\n## Architecture\n\n```\nM365 Copilot ──▶ mcpPlugin.json ──▶ MCP Server ──▶ structuredContent ──▶ React + Fluent UI Widget\n     │              (RemoteMCPServer)    (Streamable HTTP)                  (window.openai.toolOutput)\n     │\n     └── Capabilities (People, etc.) provide data to pass to MCP tools\n```\n\n## Project Structure\n\nExample project structure, not a hard requirement but a common pattern for organizing MCP server + widget development:\n\n```\nproject\u002F\n├── appPackage\u002F\n│   ├── manifest.json           # Teams manifest (bump version on deploy)\n│   ├── declarativeAgent.json   # Agent config + capabilities\n│   ├── mcpPlugin.json          # Tool definitions with _meta\n│   └── instruction.txt         # Agent behavior instructions\n├── mcp-server\u002F\n│   ├── src\u002Findex.ts            # Server with Streamable HTTP\n│   ├── widgets\u002F                # Widget shells + React source\n│   │   ├── my-widget.html      # Minimal shell returned by resources\u002Fread\n│   │   └── src\u002Fmy-widget\u002F      # React + Fluent UI source\n│   ├── assets\u002F                 # Built widget bundles served at \u002Fassets\n│   └── package.json\n├── scripts\u002F\n│   ├── setup-devtunnel.sh      # Linux\u002FMac devtunnel setup\n│   └── setup-devtunnel.ps1     # Windows devtunnel setup\n└── env\u002F.env.local              # MCP_SERVER_URL, MCP_SERVER_DOMAIN\n```\n\n**Language note**: This shows a TypeScript project layout. For Python, replace `mcp-server\u002Fsrc\u002Findex.ts` with your Python entry point (e.g., `server.py`). For C#, use a standard .NET project structure. The `appPackage\u002F`, `widgets\u002F`, `scripts\u002F`, and `env\u002F` directories are language-agnostic.\n\n## Copilot Widget Protocol\n\nYour MCP server must implement these protocol requirements to render widgets in Copilot Chat. This applies regardless of language:\n\n1. **Streamable HTTP transport** — `\u002Fmcp` endpoint handling POST, GET, DELETE with session management\n2. **CORS headers** — Origin-checking on `\u002Fmcp` allowing `m365.cloud.microsoft` and `*.m365.cloud.microsoft`, with required MCP headers\n3. **Server capabilities** — `initialize` response must declare `resources: {}` and `tools: {}`\n4. **MCP resources** — Register widgets with `ui:\u002F\u002Fwidget\u002F\u003Cname>.html` URIs, `text\u002Fhtml+skybridge` mime type, and CSP `_meta`\n5. **Tool response format** — Return `content` (text) + `structuredContent` (widget data) + `_meta` with `openai\u002FoutputTemplate`\n6. **Widget serving** — HTTP route at `\u002Fwidgets\u002F*.html` for shell files and `\u002Fassets\u002F*` for built bundles, both with origin-checking CORS\n\nFor full protocol details, JSON shapes, and an adaptation checklist for existing MCP servers, see [references\u002Fcopilot-widget-protocol.md](references\u002Fcopilot-widget-protocol.md).\n\n## Implementation\n\n### MCP Server Pattern (TypeScript Reference)\n\nSee [references\u002Fmcp-server-pattern.md](references\u002Fmcp-server-pattern.md) for complete implementation.\n\n> For other languages, implement the requirements described in [Copilot Widget Protocol](references\u002Fcopilot-widget-protocol.md) using your language's MCP SDK. See the [Language SDK References](references\u002Fcopilot-widget-protocol.md#language-sdk-references) table for SDK packages.\n\nCore requirements:\n- Expose Streamable HTTP transport on `\u002Fmcp`\n- Return `structuredContent` + `_meta` with `openai\u002FoutputTemplate`\n- Serve widgets via HTTP endpoint\n- Handle CORS for cross-origin requests\n- Handle partial data gracefully (fill in \"Unknown\" for missing fields)\n\nTool response format:\n```typescript\nreturn {\n  content: [{ type: \"text\", text: \"Summary\" }],\n  structuredContent: { \u002F* widget data *\u002F },\n  _meta: { \"openai\u002FoutputTemplate\": \"ui:\u002F\u002Fwidget\u002Fname.html\", \"openai\u002FwidgetAccessible\": true }\n};\n```\n\n### Handling Partial Data\n\nAlways normalize input data to handle missing fields:\n\n```typescript\nserver.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => {\n  const args = request.params.arguments as { title?: string; items?: Partial\u003CItem>[] };\n\n  \u002F\u002F Normalize data - fill in \"Unknown\" for missing fields\n  const title = args.title || \"Default Title\";\n  const items = (args.items || []).map(item => ({\n    name: item.name || \"Unknown\",\n    value: item.value || \"Unknown\",\n  }));\n\n  \u002F\u002F Build structuredContent for widget\n  const structuredContent = { title, items };\n  \u002F\u002F ...\n});\n```\n\n### Widget Pattern\n\nSee [references\u002Fwidget-patterns.md](references\u002Fwidget-patterns.md) for complete examples.\n\nCore requirements:\n- Use React + Fluent UI components (`@fluentui\u002Freact-components`)\n- Ensure widget package dependencies include `@fluentui\u002Freact-components`, `react`, and `react-dom`\n- Theme with `FluentProvider` (`webLightTheme`\u002F`webDarkTheme`) and Fluent `tokens`\n- Access data through shared hooks (e.g., `useOpenAiGlobal(\"toolOutput\")`)\n- Debug fallback: embedded mock data when `window.openai` unavailable\n- Handle \"Unknown\" values gracefully (e.g., hide action buttons)\n\n### Plugin Schema\n\nSee [references\u002Fplugin-schema.md](references\u002Fplugin-schema.md) for mcpPlugin.json format.\n\nCore requirements:\n- Schema `v2.4` with `RemoteMCPServer` runtime\n- `run_for_functions` array matching tool names\n- `_meta` in tool definitions for widget binding\n- `inputSchema` - make properties optional for flexibility, describe defaults in descriptions\n\n## DevTunnels Setup\n\n> **Local testing only.** DevTunnels are for development and testing on your machine. Before sharing the agent more broadly, deploy both the MCP server and widget assets to a hosted environment (e.g., Azure App Service, Azure Static Web Apps, or another hosting provider) and update the agent manifest URLs accordingly.\n\nDevTunnels expose your localhost MCP server to M365 Copilot using **named tunnels** for stable URLs. See [references\u002Fdevtunnels.md](references\u002Fdevtunnels.md) for setup scripts, command reference, and troubleshooting.\n\nThe setup script (`npm run tunnel` \u002F `npm run tunnel:win`):\n1. Creates a named tunnel on first run (or reuses the existing one)\n2. Starts hosting the tunnel on the configured port\n3. Updates `env\u002F.env.local` with `MCP_SERVER_URL` and `MCP_SERVER_DOMAIN` (first run only)\n4. Continues hosting the tunnel\n\n### Quick Start\n\n**Terminal 1 - Start MCP Server:**\n```bash\ncd mcp-server\nnpm install\nnpm run dev\n```\n\n**Terminal 2 - Start DevTunnel:**\n```bash\nnpm run tunnel\n# Or on Windows:\nnpm run tunnel:win\n```\n\nOn first run, provision the agent once the tunnel is up (see AGENT PROVISIONING rule). On subsequent runs the tunnel URL is stable — no re-provisioning needed unless the agent manifest changes.\n\n## Development Workflow\n\n1. **Start the MCP server** (dev mode with hot reload):\n   - TypeScript: `cd mcp-server && npm install && npm run dev`\n   - Python: `cd mcp-server && pip install -r requirements.txt && python server.py`\n   - C#: `cd mcp-server && dotnet run`\n\n2. **Start the devtunnel** (creates named tunnel on first run, reuses on subsequent runs):\n   ```bash\n   npm run tunnel\n   ```\n\n3. **Provision + test** — see AGENT PROVISIONING rule for when this is needed; bump `version` in manifest.json if Copilot doesn't reflect changes\n\n## Best Practices\n\nSee [references\u002Fbest-practices.md](references\u002Fbest-practices.md) for detailed guidance.\n\nKey points:\n1. **Rendering tools**: Accept data as input, don't fetch internally\n2. **Instructions**: Tell agent to use capabilities FIRST, then pass data to MCP tools\n3. **Themes**: Use `FluentProvider` + Fluent `tokens` for dark\u002Flight support\n4. **Debug mode**: Include fallback data for local widget testing\n5. **Partial data**: Handle missing fields with \"Unknown\" defaults\n6. **Action buttons**: Hide email\u002Fchat buttons when data is \"Unknown\"\n7. **Version bumping**: Bump manifest version when changes aren't reflected in Copilot\n\n## Next Step — Add SSO (optional)\n\nOnce the ui-widget agent is scaffolded, running, and provisioned, you can add **Entra SSO** — so your MCP tools receive the signed-in user's verified identity — with the companion skill in this same plugin:\n\n▶ **`setup-sso-ui-widget`** — registers an Entra app, reuses your existing dev tunnel, injects a minimal JWKS token guard into your MCP server, wires `mcpPlugin.json` auth, and sideloads. SSO only, no OBO. (Run `\u002Fsetup-sso-ui-widget` from the project root.)\n\n**Tell the user** (after the build\u002Fprovision completes):\n> **Your ui-widget agent is ready.** 🎉 Want me to wire up **SSO** next, so your tools get the signed-in user's identity? I can run the **`setup-sso-ui-widget`** skill — just say the word.\n",{"data":38,"body":39},{"name":4,"description":6},{"type":40,"children":41},"root",[42,51,58,73,113,125,131,142,296,312,344,351,356,386,391,396,406,427,435,482,486,492,497,503,703,706,712,722,777,782,802,812,838,872,888,1030,1050,1073,1262,1273,1278,1301,1350,1368,1386,1410,1434,1439,1533,1543,1552,1573,1583,1606,1615,1654,1664,1669,1837,1845,1883,1888,2163,2183,2194,2197,2203,2220,2261,2269,2564,2576,2579,2584,2590,2599,2605,2610,2619,2673,2678,2683,2857,2867,2872,2878,2888,2910,2915,2966,2971,3190,3196,3201,3700,3706,3716,3720,3820,3826,3837,3841,3894,3900,3913,3932,3953,3997,4003,4011,4061,4069,4116,4121,4127,4225,4231,4241,4246,4333,4339,4351,4381,4391,4421],{"type":43,"tag":44,"props":45,"children":47},"element","h1",{"id":46},"copilot-mcp-server-development",[48],{"type":49,"value":50},"text","Copilot MCP Server Development",{"type":43,"tag":52,"props":53,"children":55},"h2",{"id":54},"telemetry-tagging",[56],{"type":49,"value":57},"Telemetry Tagging",{"type":43,"tag":59,"props":60,"children":61},"p",{},[62,64,71],{"type":49,"value":63},"Before running any ",{"type":43,"tag":65,"props":66,"children":68},"code",{"className":67},[],[69],{"type":49,"value":70},"atk",{"type":49,"value":72}," CLI commands, set the session environment variable so all CLI invocations are tagged as skill-initiated:",{"type":43,"tag":74,"props":75,"children":80},"pre",{"className":76,"code":77,"language":78,"meta":79,"style":79},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export ATK_CLI_SKILL=true\n","bash","",[81],{"type":43,"tag":65,"props":82,"children":83},{"__ignoreMap":79},[84],{"type":43,"tag":85,"props":86,"children":89},"span",{"class":87,"line":88},"line",1,[90,96,102,108],{"type":43,"tag":85,"props":91,"children":93},{"style":92},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[94],{"type":49,"value":95},"export",{"type":43,"tag":85,"props":97,"children":99},{"style":98},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[100],{"type":49,"value":101}," ATK_CLI_SKILL",{"type":43,"tag":85,"props":103,"children":105},{"style":104},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[106],{"type":49,"value":107},"=",{"type":43,"tag":85,"props":109,"children":110},{"style":98},[111],{"type":49,"value":112},"true\n",{"type":43,"tag":59,"props":114,"children":115},{},[116,118,123],{"type":49,"value":117},"Run this once at the start of the session. All subsequent ",{"type":43,"tag":65,"props":119,"children":121},{"className":120},[],[122],{"type":49,"value":70},{"type":49,"value":124}," commands in the same terminal will inherit it.",{"type":43,"tag":52,"props":126,"children":128},{"id":127},"path-selection",[129],{"type":49,"value":130},"🔀 PATH SELECTION",{"type":43,"tag":59,"props":132,"children":133},{},[134,140],{"type":43,"tag":135,"props":136,"children":137},"strong",{},[138],{"type":49,"value":139},"Before proceeding, ask the user which path they want to take using AskUserQuestion.",{"type":49,"value":141}," Both are supported for M365 Copilot widget rendering. Present the tradeoffs and let them choose:",{"type":43,"tag":143,"props":144,"children":145},"table",{},[146,186],{"type":43,"tag":147,"props":148,"children":149},"thead",{},[150],{"type":43,"tag":151,"props":152,"children":153},"tr",{},[154,158,168],{"type":43,"tag":155,"props":156,"children":157},"th",{},[],{"type":43,"tag":155,"props":159,"children":160},{},[161,166],{"type":43,"tag":135,"props":162,"children":163},{},[164],{"type":49,"value":165},"OAI Apps",{"type":49,"value":167}," (this skill)",{"type":43,"tag":155,"props":169,"children":170},{},[171,176,178,184],{"type":43,"tag":135,"props":172,"children":173},{},[174],{"type":49,"value":175},"MCP Apps Extension",{"type":49,"value":177}," (",{"type":43,"tag":65,"props":179,"children":181},{"className":180},[],[182],{"type":49,"value":183},"modelcontextprotocol\u002Fext-apps",{"type":49,"value":185},")",{"type":43,"tag":187,"props":188,"children":189},"tbody",{},[190,212,233,254,275],{"type":43,"tag":151,"props":191,"children":192},{},[193,202,207],{"type":43,"tag":194,"props":195,"children":196},"td",{},[197],{"type":43,"tag":135,"props":198,"children":199},{},[200],{"type":49,"value":201},"Standard",{"type":43,"tag":194,"props":203,"children":204},{},[205],{"type":49,"value":206},"OpenAI-specific",{"type":43,"tag":194,"props":208,"children":209},{},[210],{"type":49,"value":211},"Official MCP standard",{"type":43,"tag":151,"props":213,"children":214},{},[215,223,228],{"type":43,"tag":194,"props":216,"children":217},{},[218],{"type":43,"tag":135,"props":219,"children":220},{},[221],{"type":49,"value":222},"Works in",{"type":43,"tag":194,"props":224,"children":225},{},[226],{"type":49,"value":227},"ChatGPT + M365 Copilot",{"type":43,"tag":194,"props":229,"children":230},{},[231],{"type":49,"value":232},"M365 Copilot, ChatGPT, VSCode, and more",{"type":43,"tag":151,"props":234,"children":235},{},[236,244,249],{"type":43,"tag":194,"props":237,"children":238},{},[239],{"type":43,"tag":135,"props":240,"children":241},{},[242],{"type":49,"value":243},"Maturity",{"type":43,"tag":194,"props":245,"children":246},{},[247],{"type":49,"value":248},"Battle-tested, production-ready",{"type":43,"tag":194,"props":250,"children":251},{},[252],{"type":49,"value":253},"New official standard, growing ecosystem",{"type":43,"tag":151,"props":255,"children":256},{},[257,265,270],{"type":43,"tag":194,"props":258,"children":259},{},[260],{"type":43,"tag":135,"props":261,"children":262},{},[263],{"type":49,"value":264},"Design",{"type":43,"tag":194,"props":266,"children":267},{},[268],{"type":49,"value":269},"OpenAI Apps SDK",{"type":43,"tag":194,"props":271,"children":272},{},[273],{"type":49,"value":274},"MCP Apps protocol (cross-platform)",{"type":43,"tag":151,"props":276,"children":277},{},[278,286,291],{"type":43,"tag":194,"props":279,"children":280},{},[281],{"type":43,"tag":135,"props":282,"children":283},{},[284],{"type":49,"value":285},"When to choose",{"type":43,"tag":194,"props":287,"children":288},{},[289],{"type":49,"value":290},"Existing OAI app investment",{"type":43,"tag":194,"props":292,"children":293},{},[294],{"type":49,"value":295},"Prefer the open standard, want broadest client support",{"type":43,"tag":59,"props":297,"children":298},{},[299,304,306],{"type":43,"tag":135,"props":300,"children":301},{},[302],{"type":49,"value":303},"Ask:",{"type":49,"value":305}," ",{"type":43,"tag":307,"props":308,"children":309},"em",{},[310],{"type":49,"value":311},"\"Would you like to build an OAI app (OpenAI Apps SDK — battle-tested, works in ChatGPT and M365 Copilot) or an MCP app (new official standard — works in M365 Copilot, ChatGPT, VSCode, and more)?\"",{"type":43,"tag":313,"props":314,"children":315},"ul",{},[316,327],{"type":43,"tag":317,"props":318,"children":319},"li",{},[320,325],{"type":43,"tag":135,"props":321,"children":322},{},[323],{"type":49,"value":324},"OAI apps",{"type":49,"value":326}," → Continue below. This skill covers everything you need.",{"type":43,"tag":317,"props":328,"children":329},{},[330,335,337,342],{"type":43,"tag":135,"props":331,"children":332},{},[333],{"type":49,"value":334},"MCP apps",{"type":49,"value":336}," → Install the ",{"type":43,"tag":65,"props":338,"children":340},{"className":339},[],[341],{"type":49,"value":183},{"type":49,"value":343}," plugin (see below), then use the appropriate skill from that plugin.",{"type":43,"tag":345,"props":346,"children":348},"h3",{"id":347},"mcp-apps-install-ext-apps-plugin",[349],{"type":49,"value":350},"MCP Apps: Install ext-apps Plugin",{"type":43,"tag":59,"props":352,"children":353},{},[354],{"type":49,"value":355},"If the user chooses MCP Apps, do this automatically (do not stop at explanation-only):",{"type":43,"tag":357,"props":358,"children":359},"ol",{},[360,371,381],{"type":43,"tag":317,"props":361,"children":362},{},[363,365],{"type":49,"value":364},"Run ",{"type":43,"tag":65,"props":366,"children":368},{"className":367},[],[369],{"type":49,"value":370},"\u002Fplugin marketplace add modelcontextprotocol\u002Fext-apps",{"type":43,"tag":317,"props":372,"children":373},{},[374,375],{"type":49,"value":364},{"type":43,"tag":65,"props":376,"children":378},{"className":377},[],[379],{"type":49,"value":380},"\u002Fplugin install mcp-apps@mcp-apps",{"type":43,"tag":317,"props":382,"children":383},{},[384],{"type":49,"value":385},"Confirm the plugin is available, then invoke the correct ext-apps skill based on user intent",{"type":43,"tag":59,"props":387,"children":388},{},[389],{"type":49,"value":390},"If plugin commands are unavailable in the current environment, provide the exact commands below and ask the user to run them once, then continue by invoking the selected ext-apps skill.",{"type":43,"tag":59,"props":392,"children":393},{},[394],{"type":49,"value":395},"Reference commands:",{"type":43,"tag":74,"props":397,"children":401},{"className":398,"code":400,"language":49},[399],"language-text","To build an MCP App, install the ext-apps plugin from the marketplace:\n\n1. \u002Fplugin marketplace add modelcontextprotocol\u002Fext-apps\n2. \u002Fplugin install mcp-apps@mcp-apps\n\nThen use one of these skills from that plugin:\n- create-mcp-app      — Scaffold a new MCP App with interactive UI from scratch\n- add-app-to-server   — Add interactive UI to an existing MCP server's tools\n- migrate-oai-app     — Convert an existing OAI app to use MCP Apps\n- convert-web-app     — Turn a web app into a hybrid web + MCP App\n\nAfter installing, invoke the relevant skill to continue.\n",[402],{"type":43,"tag":65,"props":403,"children":404},{"__ignoreMap":79},[405],{"type":49,"value":400},{"type":43,"tag":407,"props":408,"children":409},"blockquote",{},[410],{"type":43,"tag":59,"props":411,"children":412},{},[413,418,420,425],{"type":43,"tag":135,"props":414,"children":415},{},[416],{"type":49,"value":417},"Note:",{"type":49,"value":419}," The ext-apps plugin lives in the external ",{"type":43,"tag":65,"props":421,"children":423},{"className":422},[],[424],{"type":49,"value":183},{"type":49,"value":426}," marketplace — it is not part of this plugin collection.",{"type":43,"tag":59,"props":428,"children":429},{},[430],{"type":43,"tag":135,"props":431,"children":432},{},[433],{"type":49,"value":434},"Handoff mapping after install:",{"type":43,"tag":313,"props":436,"children":437},{},[438,449,460,471],{"type":43,"tag":317,"props":439,"children":440},{},[441,443],{"type":49,"value":442},"New MCP app from scratch → ",{"type":43,"tag":65,"props":444,"children":446},{"className":445},[],[447],{"type":49,"value":448},"create-mcp-app",{"type":43,"tag":317,"props":450,"children":451},{},[452,454],{"type":49,"value":453},"Add app UI to existing MCP server → ",{"type":43,"tag":65,"props":455,"children":457},{"className":456},[],[458],{"type":49,"value":459},"add-app-to-server",{"type":43,"tag":317,"props":461,"children":462},{},[463,465],{"type":49,"value":464},"Migrate existing OAI app → ",{"type":43,"tag":65,"props":466,"children":468},{"className":467},[],[469],{"type":49,"value":470},"migrate-oai-app",{"type":43,"tag":317,"props":472,"children":473},{},[474,476],{"type":49,"value":475},"Convert an existing web app → ",{"type":43,"tag":65,"props":477,"children":479},{"className":478},[],[480],{"type":49,"value":481},"convert-web-app",{"type":43,"tag":483,"props":484,"children":485},"hr",{},[],{"type":43,"tag":52,"props":487,"children":489},{"id":488},"project-detection",[490],{"type":49,"value":491},"📛 PROJECT DETECTION 📛",{"type":43,"tag":59,"props":493,"children":494},{},[495],{"type":49,"value":496},"This skill triggers when building MCP servers with OAI app or widget rendering for Microsoft 365 Copilot Chat. The MCP server can be written in any language that supports the MCP protocol (TypeScript, Python, C#, etc.). The agent project and MCP server may live in the same repo, separate folders, or entirely different projects.",{"type":43,"tag":52,"props":498,"children":500},{"id":499},"scenario-routing",[501],{"type":49,"value":502},"Scenario Routing",{"type":43,"tag":143,"props":504,"children":505},{},[506,527],{"type":43,"tag":147,"props":507,"children":508},{},[509],{"type":43,"tag":151,"props":510,"children":511},{},[512,517,522],{"type":43,"tag":155,"props":513,"children":514},{},[515],{"type":49,"value":516},"Starting Point",{"type":43,"tag":155,"props":518,"children":519},{},[520],{"type":49,"value":521},"What You Need",{"type":43,"tag":155,"props":523,"children":524},{},[525],{"type":49,"value":526},"Path",{"type":43,"tag":187,"props":528,"children":529},{},[530,581,612,639,665],{"type":43,"tag":151,"props":531,"children":532},{},[533,541,546],{"type":43,"tag":194,"props":534,"children":535},{},[536],{"type":43,"tag":135,"props":537,"children":538},{},[539],{"type":49,"value":540},"Prefer MCP Apps standard",{"type":43,"tag":194,"props":542,"children":543},{},[544],{"type":49,"value":545},"Cross-platform widget support (M365 Copilot, ChatGPT, VSCode, and more)",{"type":43,"tag":194,"props":547,"children":548},{},[549,551,556,558,563,565,570,572,579],{"type":49,"value":550},"Install ",{"type":43,"tag":65,"props":552,"children":554},{"className":553},[],[555],{"type":49,"value":183},{"type":49,"value":557},", then use ",{"type":43,"tag":65,"props":559,"children":561},{"className":560},[],[562],{"type":49,"value":448},{"type":49,"value":564}," or ",{"type":43,"tag":65,"props":566,"children":568},{"className":567},[],[569],{"type":49,"value":459},{"type":49,"value":571}," — see ",{"type":43,"tag":573,"props":574,"children":576},"a",{"href":575},"#-path-selection",[577],{"type":49,"value":578},"Path Selection",{"type":49,"value":580}," above",{"type":43,"tag":151,"props":582,"children":583},{},[584,594,599],{"type":43,"tag":194,"props":585,"children":586},{},[587,592],{"type":43,"tag":135,"props":588,"children":589},{},[590],{"type":49,"value":591},"From scratch",{"type":49,"value":593}," (no agent, no MCP server)",{"type":43,"tag":194,"props":595,"children":596},{},[597],{"type":49,"value":598},"Full OAI app setup",{"type":43,"tag":194,"props":600,"children":601},{},[602,604,610],{"type":49,"value":603},"Delegate agent scaffolding to ",{"type":43,"tag":65,"props":605,"children":607},{"className":606},[],[608],{"type":49,"value":609},"declarative-agent-developer",{"type":49,"value":611}," first, then return here for MCP server + widgets",{"type":43,"tag":151,"props":613,"children":614},{},[615,623,628],{"type":43,"tag":194,"props":616,"children":617},{},[618],{"type":43,"tag":135,"props":619,"children":620},{},[621],{"type":49,"value":622},"Existing M365 agent, new MCP server",{"type":43,"tag":194,"props":624,"children":625},{},[626],{"type":49,"value":627},"MCP server + widgets + mcpPlugin.json",{"type":43,"tag":194,"props":629,"children":630},{},[631,633],{"type":49,"value":632},"Start at ",{"type":43,"tag":573,"props":634,"children":636},{"href":635},"#implementation",[637],{"type":49,"value":638},"Implementation",{"type":43,"tag":151,"props":640,"children":641},{},[642,650,655],{"type":43,"tag":194,"props":643,"children":644},{},[645],{"type":43,"tag":135,"props":646,"children":647},{},[648],{"type":49,"value":649},"Existing MCP server, add Copilot widgets",{"type":43,"tag":194,"props":651,"children":652},{},[653],{"type":49,"value":654},"Widget support added to existing server",{"type":43,"tag":194,"props":656,"children":657},{},[658,659],{"type":49,"value":632},{"type":43,"tag":573,"props":660,"children":662},{"href":661},"references\u002Fcopilot-widget-protocol.md#adaptation-checklist-existing-mcp-server",[663],{"type":49,"value":664},"Copilot Widget Protocol",{"type":43,"tag":151,"props":666,"children":667},{},[668,678,683],{"type":43,"tag":194,"props":669,"children":670},{},[671,676],{"type":43,"tag":135,"props":672,"children":673},{},[674],{"type":49,"value":675},"Language choice",{"type":49,"value":677}," (non-TypeScript)",{"type":43,"tag":194,"props":679,"children":680},{},[681],{"type":49,"value":682},"Protocol requirements",{"type":43,"tag":194,"props":684,"children":685},{},[686,688,693,695,701],{"type":49,"value":687},"See ",{"type":43,"tag":573,"props":689,"children":691},{"href":690},"references\u002Fcopilot-widget-protocol.md",[692],{"type":49,"value":664},{"type":49,"value":694}," for what to implement, ",{"type":43,"tag":573,"props":696,"children":698},{"href":697},"references\u002Fmcp-server-pattern.md",[699],{"type":49,"value":700},"MCP Server Pattern (TypeScript)",{"type":49,"value":702}," as a reference",{"type":43,"tag":483,"props":704,"children":705},{},[],{"type":43,"tag":52,"props":707,"children":709},{"id":708},"critical-execution-rules",[710],{"type":49,"value":711},"🚨 CRITICAL EXECUTION RULES 🚨",{"type":43,"tag":59,"props":713,"children":714},{},[715,720],{"type":43,"tag":135,"props":716,"children":717},{},[718],{"type":49,"value":719},"FLUENT UI ENFORCEMENT (REQUIRED):",{"type":49,"value":721}," Widget implementations MUST use React + Fluent UI components. Before writing any widget code, the agent MUST read and follow:",{"type":43,"tag":313,"props":723,"children":724},{},[725,734,750,759,768],{"type":43,"tag":317,"props":726,"children":727},{},[728],{"type":43,"tag":65,"props":729,"children":731},{"className":730},[],[732],{"type":49,"value":733},"references\u002Fwidget-patterns.md",{"type":43,"tag":317,"props":735,"children":736},{},[737,743,748],{"type":43,"tag":65,"props":738,"children":740},{"className":739},[],[741],{"type":49,"value":742},"references\u002Fbest-practices.md",{"type":43,"tag":135,"props":744,"children":745},{},[746],{"type":49,"value":747},"FLUENT UI PACKAGE REQUIREMENT (REQUIRED):",{"type":49,"value":749}," The widget project MUST include Fluent UI dependencies before implementation. At minimum, install and keep these in the widget package dependencies:",{"type":43,"tag":317,"props":751,"children":752},{},[753],{"type":43,"tag":65,"props":754,"children":756},{"className":755},[],[757],{"type":49,"value":758},"@fluentui\u002Freact-components",{"type":43,"tag":317,"props":760,"children":761},{},[762],{"type":43,"tag":65,"props":763,"children":765},{"className":764},[],[766],{"type":49,"value":767},"react",{"type":43,"tag":317,"props":769,"children":770},{},[771],{"type":43,"tag":65,"props":772,"children":774},{"className":773},[],[775],{"type":49,"value":776},"react-dom",{"type":43,"tag":59,"props":778,"children":779},{},[780],{"type":49,"value":781},"If any of these packages are missing, install them automatically before continuing with widget code generation.",{"type":43,"tag":59,"props":783,"children":784},{},[785,787,793,795,800],{"type":49,"value":786},"If the generated widget does not include React entry files (for example ",{"type":43,"tag":65,"props":788,"children":790},{"className":789},[],[791],{"type":49,"value":792},"widgets\u002Fsrc\u002F\u003Cwidget-name>\u002Fmain.tsx",{"type":49,"value":794}," and a React component file) and Fluent imports from ",{"type":43,"tag":65,"props":796,"children":798},{"className":797},[],[799],{"type":49,"value":758},{"type":49,"value":801},", the task is incomplete and MUST be corrected before returning results.",{"type":43,"tag":59,"props":803,"children":804},{},[805,810],{"type":43,"tag":135,"props":806,"children":807},{},[808],{"type":49,"value":809},"NO RAW HTML-ONLY WIDGETS (DEFAULT):",{"type":49,"value":811}," Do not implement app content directly with static HTML templates and inline JS as the final widget solution. A minimal shell HTML file is allowed only as a loader for built React assets. Raw\u002Fself-contained HTML-only widgets are allowed only when the user explicitly requests a non-React prototype.",{"type":43,"tag":59,"props":813,"children":814},{},[815,820,822,828,830,836],{"type":43,"tag":135,"props":816,"children":817},{},[818],{"type":49,"value":819},"SSO HANDOFF (REQUIRED AT COMPLETION):",{"type":49,"value":821}," Once the ui-widget agent is fully scaffolded, running, and provisioned, your final completion summary MUST end by offering the optional SSO next step — see ",{"type":43,"tag":573,"props":823,"children":825},{"href":824},"#next-step--add-sso-optional",[826],{"type":49,"value":827},"Next Step — Add SSO",{"type":49,"value":829},". List it in your \"next steps\" and ask the user if they want to wire Entra SSO via the ",{"type":43,"tag":65,"props":831,"children":833},{"className":832},[],[834],{"type":49,"value":835},"setup-sso-ui-widget",{"type":49,"value":837}," skill. Do NOT omit this offer, even if you also list other suggestions.",{"type":43,"tag":59,"props":839,"children":840},{},[841,846,848,854,856,862,864,870],{"type":43,"tag":135,"props":842,"children":843},{},[844],{"type":49,"value":845},"BACKGROUND PROCESSES:",{"type":49,"value":847}," MCP server and devtunnel MUST be spawned as independent OS processes — NOT run inside the agent's shell session. ",{"type":43,"tag":65,"props":849,"children":851},{"className":850},[],[852],{"type":49,"value":853},"isBackground: true",{"type":49,"value":855},", ",{"type":43,"tag":65,"props":857,"children":859},{"className":858},[],[860],{"type":49,"value":861},"mode: \"async\"",{"type":49,"value":863},", and ",{"type":43,"tag":65,"props":865,"children":867},{"className":866},[],[868],{"type":49,"value":869},"Start-Job",{"type":49,"value":871}," all run inside the agent's shell session and will be killed between messages. The only reliable approach is to spawn a detached OS process.",{"type":43,"tag":59,"props":873,"children":874},{},[875],{"type":43,"tag":135,"props":876,"children":877},{},[878,880,886],{"type":49,"value":879},"Windows — use ",{"type":43,"tag":65,"props":881,"children":883},{"className":882},[],[884],{"type":49,"value":885},"Start-Process -WindowStyle Hidden",{"type":49,"value":887},":",{"type":43,"tag":74,"props":889,"children":893},{"className":890,"code":891,"language":892,"meta":79,"style":79},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Start devtunnel\n$t = Start-Process -FilePath \"devtunnel\" `\n    -ArgumentList \"host\",\"\u003Ctunnel-name>\",\"-a\" `\n    -WindowStyle Hidden -PassThru `\n    -RedirectStandardOutput \"tunnel.log\" -RedirectStandardError \"tunnel-err.log\"\n\n# Start MCP server — use cmd.exe \u002Fc to set the working directory and inherit PATH\n$s = Start-Process -FilePath \"cmd.exe\" `\n    -ArgumentList \"\u002Fc\",\"cd \u002Fd \u003Cabs-path-to-mcp-server> && \u003Cstart-command>\" `\n    -WindowStyle Hidden -PassThru `\n    -RedirectStandardOutput \"server.log\" -RedirectStandardError \"server-err.log\"\n\n# Save PIDs so they can be stopped later\n\"$($t.Id),$($s.Id)\" | Out-File pids.txt\nWrite-Host \"Started tunnel PID $($t.Id), server PID $($s.Id)\"\n","powershell",[894],{"type":43,"tag":65,"props":895,"children":896},{"__ignoreMap":79},[897,905,914,923,932,941,951,960,969,978,986,995,1003,1012,1021],{"type":43,"tag":85,"props":898,"children":899},{"class":87,"line":88},[900],{"type":43,"tag":85,"props":901,"children":902},{},[903],{"type":49,"value":904},"# Start devtunnel\n",{"type":43,"tag":85,"props":906,"children":908},{"class":87,"line":907},2,[909],{"type":43,"tag":85,"props":910,"children":911},{},[912],{"type":49,"value":913},"$t = Start-Process -FilePath \"devtunnel\" `\n",{"type":43,"tag":85,"props":915,"children":917},{"class":87,"line":916},3,[918],{"type":43,"tag":85,"props":919,"children":920},{},[921],{"type":49,"value":922},"    -ArgumentList \"host\",\"\u003Ctunnel-name>\",\"-a\" `\n",{"type":43,"tag":85,"props":924,"children":926},{"class":87,"line":925},4,[927],{"type":43,"tag":85,"props":928,"children":929},{},[930],{"type":49,"value":931},"    -WindowStyle Hidden -PassThru `\n",{"type":43,"tag":85,"props":933,"children":935},{"class":87,"line":934},5,[936],{"type":43,"tag":85,"props":937,"children":938},{},[939],{"type":49,"value":940},"    -RedirectStandardOutput \"tunnel.log\" -RedirectStandardError \"tunnel-err.log\"\n",{"type":43,"tag":85,"props":942,"children":944},{"class":87,"line":943},6,[945],{"type":43,"tag":85,"props":946,"children":948},{"emptyLinePlaceholder":947},true,[949],{"type":49,"value":950},"\n",{"type":43,"tag":85,"props":952,"children":954},{"class":87,"line":953},7,[955],{"type":43,"tag":85,"props":956,"children":957},{},[958],{"type":49,"value":959},"# Start MCP server — use cmd.exe \u002Fc to set the working directory and inherit PATH\n",{"type":43,"tag":85,"props":961,"children":963},{"class":87,"line":962},8,[964],{"type":43,"tag":85,"props":965,"children":966},{},[967],{"type":49,"value":968},"$s = Start-Process -FilePath \"cmd.exe\" `\n",{"type":43,"tag":85,"props":970,"children":972},{"class":87,"line":971},9,[973],{"type":43,"tag":85,"props":974,"children":975},{},[976],{"type":49,"value":977},"    -ArgumentList \"\u002Fc\",\"cd \u002Fd \u003Cabs-path-to-mcp-server> && \u003Cstart-command>\" `\n",{"type":43,"tag":85,"props":979,"children":981},{"class":87,"line":980},10,[982],{"type":43,"tag":85,"props":983,"children":984},{},[985],{"type":49,"value":931},{"type":43,"tag":85,"props":987,"children":989},{"class":87,"line":988},11,[990],{"type":43,"tag":85,"props":991,"children":992},{},[993],{"type":49,"value":994},"    -RedirectStandardOutput \"server.log\" -RedirectStandardError \"server-err.log\"\n",{"type":43,"tag":85,"props":996,"children":998},{"class":87,"line":997},12,[999],{"type":43,"tag":85,"props":1000,"children":1001},{"emptyLinePlaceholder":947},[1002],{"type":49,"value":950},{"type":43,"tag":85,"props":1004,"children":1006},{"class":87,"line":1005},13,[1007],{"type":43,"tag":85,"props":1008,"children":1009},{},[1010],{"type":49,"value":1011},"# Save PIDs so they can be stopped later\n",{"type":43,"tag":85,"props":1013,"children":1015},{"class":87,"line":1014},14,[1016],{"type":43,"tag":85,"props":1017,"children":1018},{},[1019],{"type":49,"value":1020},"\"$($t.Id),$($s.Id)\" | Out-File pids.txt\n",{"type":43,"tag":85,"props":1022,"children":1024},{"class":87,"line":1023},15,[1025],{"type":43,"tag":85,"props":1026,"children":1027},{},[1028],{"type":49,"value":1029},"Write-Host \"Started tunnel PID $($t.Id), server PID $($s.Id)\"\n",{"type":43,"tag":59,"props":1031,"children":1032},{},[1033,1035,1041,1042,1048],{"type":49,"value":1034},"To stop: ",{"type":43,"tag":65,"props":1036,"children":1038},{"className":1037},[],[1039],{"type":49,"value":1040},"Stop-Process -Id (Get-Content pids.txt).Split(',')",{"type":49,"value":564},{"type":43,"tag":65,"props":1043,"children":1045},{"className":1044},[],[1046],{"type":49,"value":1047},"Stop-Process -Id \u003Cpid>",{"type":49,"value":1049},".",{"type":43,"tag":59,"props":1051,"children":1052},{},[1053],{"type":43,"tag":135,"props":1054,"children":1055},{},[1056,1058,1064,1066,1072],{"type":49,"value":1057},"Linux\u002FMac — use ",{"type":43,"tag":65,"props":1059,"children":1061},{"className":1060},[],[1062],{"type":49,"value":1063},"nohup",{"type":49,"value":1065}," with ",{"type":43,"tag":65,"props":1067,"children":1069},{"className":1068},[],[1070],{"type":49,"value":1071},"&",{"type":49,"value":887},{"type":43,"tag":74,"props":1074,"children":1076},{"className":76,"code":1075,"language":78,"meta":79,"style":79},"nohup devtunnel host \u003Ctunnel-name> > tunnel.log 2>tunnel-err.log &\necho \"tunnel:$!\" >> pids.txt\nnohup \u003Cstart-command> > server.log 2>server-err.log &\necho \"server:$!\" >> pids.txt\n",[1077],{"type":43,"tag":65,"props":1078,"children":1079},{"__ignoreMap":79},[1080,1144,1183,1230],{"type":43,"tag":85,"props":1081,"children":1082},{"class":87,"line":88},[1083,1088,1094,1099,1104,1109,1114,1119,1124,1129,1134,1139],{"type":43,"tag":85,"props":1084,"children":1086},{"style":1085},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1087],{"type":49,"value":1063},{"type":43,"tag":85,"props":1089,"children":1091},{"style":1090},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1092],{"type":49,"value":1093}," devtunnel",{"type":43,"tag":85,"props":1095,"children":1096},{"style":1090},[1097],{"type":49,"value":1098}," host",{"type":43,"tag":85,"props":1100,"children":1101},{"style":104},[1102],{"type":49,"value":1103}," \u003C",{"type":43,"tag":85,"props":1105,"children":1106},{"style":1090},[1107],{"type":49,"value":1108},"tunnel-nam",{"type":43,"tag":85,"props":1110,"children":1111},{"style":98},[1112],{"type":49,"value":1113},"e",{"type":43,"tag":85,"props":1115,"children":1116},{"style":104},[1117],{"type":49,"value":1118},">",{"type":43,"tag":85,"props":1120,"children":1121},{"style":104},[1122],{"type":49,"value":1123}," >",{"type":43,"tag":85,"props":1125,"children":1126},{"style":1090},[1127],{"type":49,"value":1128}," tunnel.log",{"type":43,"tag":85,"props":1130,"children":1131},{"style":104},[1132],{"type":49,"value":1133}," 2>",{"type":43,"tag":85,"props":1135,"children":1136},{"style":1090},[1137],{"type":49,"value":1138},"tunnel-err.log",{"type":43,"tag":85,"props":1140,"children":1141},{"style":104},[1142],{"type":49,"value":1143}," &\n",{"type":43,"tag":85,"props":1145,"children":1146},{"class":87,"line":907},[1147,1153,1158,1163,1168,1173,1178],{"type":43,"tag":85,"props":1148,"children":1150},{"style":1149},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[1151],{"type":49,"value":1152},"echo",{"type":43,"tag":85,"props":1154,"children":1155},{"style":104},[1156],{"type":49,"value":1157}," \"",{"type":43,"tag":85,"props":1159,"children":1160},{"style":1090},[1161],{"type":49,"value":1162},"tunnel:",{"type":43,"tag":85,"props":1164,"children":1165},{"style":98},[1166],{"type":49,"value":1167},"$!",{"type":43,"tag":85,"props":1169,"children":1170},{"style":104},[1171],{"type":49,"value":1172},"\"",{"type":43,"tag":85,"props":1174,"children":1175},{"style":104},[1176],{"type":49,"value":1177}," >>",{"type":43,"tag":85,"props":1179,"children":1180},{"style":1090},[1181],{"type":49,"value":1182}," pids.txt\n",{"type":43,"tag":85,"props":1184,"children":1185},{"class":87,"line":916},[1186,1190,1194,1199,1204,1208,1212,1217,1221,1226],{"type":43,"tag":85,"props":1187,"children":1188},{"style":1085},[1189],{"type":49,"value":1063},{"type":43,"tag":85,"props":1191,"children":1192},{"style":104},[1193],{"type":49,"value":1103},{"type":43,"tag":85,"props":1195,"children":1196},{"style":1090},[1197],{"type":49,"value":1198},"start-comman",{"type":43,"tag":85,"props":1200,"children":1201},{"style":98},[1202],{"type":49,"value":1203},"d",{"type":43,"tag":85,"props":1205,"children":1206},{"style":104},[1207],{"type":49,"value":1118},{"type":43,"tag":85,"props":1209,"children":1210},{"style":104},[1211],{"type":49,"value":1123},{"type":43,"tag":85,"props":1213,"children":1214},{"style":1090},[1215],{"type":49,"value":1216}," server.log",{"type":43,"tag":85,"props":1218,"children":1219},{"style":104},[1220],{"type":49,"value":1133},{"type":43,"tag":85,"props":1222,"children":1223},{"style":1090},[1224],{"type":49,"value":1225},"server-err.log",{"type":43,"tag":85,"props":1227,"children":1228},{"style":104},[1229],{"type":49,"value":1143},{"type":43,"tag":85,"props":1231,"children":1232},{"class":87,"line":925},[1233,1237,1241,1246,1250,1254,1258],{"type":43,"tag":85,"props":1234,"children":1235},{"style":1149},[1236],{"type":49,"value":1152},{"type":43,"tag":85,"props":1238,"children":1239},{"style":104},[1240],{"type":49,"value":1157},{"type":43,"tag":85,"props":1242,"children":1243},{"style":1090},[1244],{"type":49,"value":1245},"server:",{"type":43,"tag":85,"props":1247,"children":1248},{"style":98},[1249],{"type":49,"value":1167},{"type":43,"tag":85,"props":1251,"children":1252},{"style":104},[1253],{"type":49,"value":1172},{"type":43,"tag":85,"props":1255,"children":1256},{"style":104},[1257],{"type":49,"value":1177},{"type":43,"tag":85,"props":1259,"children":1260},{"style":1090},[1261],{"type":49,"value":1182},{"type":43,"tag":59,"props":1263,"children":1264},{},[1265,1266,1272],{"type":49,"value":1034},{"type":43,"tag":65,"props":1267,"children":1269},{"className":1268},[],[1270],{"type":49,"value":1271},"kill $(grep -oP '\\d+' pids.txt)",{"type":49,"value":1049},{"type":43,"tag":59,"props":1274,"children":1275},{},[1276],{"type":49,"value":1277},"After starting, tail the logs to confirm both processes are up before proceeding:",{"type":43,"tag":74,"props":1279,"children":1281},{"className":890,"code":1280,"language":892,"meta":79,"style":79},"# Windows\nStart-Sleep 3; Get-Content tunnel.log, server.log\n",[1282],{"type":43,"tag":65,"props":1283,"children":1284},{"__ignoreMap":79},[1285,1293],{"type":43,"tag":85,"props":1286,"children":1287},{"class":87,"line":88},[1288],{"type":43,"tag":85,"props":1289,"children":1290},{},[1291],{"type":49,"value":1292},"# Windows\n",{"type":43,"tag":85,"props":1294,"children":1295},{"class":87,"line":907},[1296],{"type":43,"tag":85,"props":1297,"children":1298},{},[1299],{"type":49,"value":1300},"Start-Sleep 3; Get-Content tunnel.log, server.log\n",{"type":43,"tag":74,"props":1302,"children":1304},{"className":76,"code":1303,"language":78,"meta":79,"style":79},"# Linux\u002FMac\nsleep 3 && tail tunnel.log server.log\n",[1305],{"type":43,"tag":65,"props":1306,"children":1307},{"__ignoreMap":79},[1308,1317],{"type":43,"tag":85,"props":1309,"children":1310},{"class":87,"line":88},[1311],{"type":43,"tag":85,"props":1312,"children":1314},{"style":1313},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[1315],{"type":49,"value":1316},"# Linux\u002FMac\n",{"type":43,"tag":85,"props":1318,"children":1319},{"class":87,"line":907},[1320,1325,1331,1336,1341,1345],{"type":43,"tag":85,"props":1321,"children":1322},{"style":1085},[1323],{"type":49,"value":1324},"sleep",{"type":43,"tag":85,"props":1326,"children":1328},{"style":1327},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1329],{"type":49,"value":1330}," 3",{"type":43,"tag":85,"props":1332,"children":1333},{"style":104},[1334],{"type":49,"value":1335}," &&",{"type":43,"tag":85,"props":1337,"children":1338},{"style":1085},[1339],{"type":49,"value":1340}," tail",{"type":43,"tag":85,"props":1342,"children":1343},{"style":1090},[1344],{"type":49,"value":1128},{"type":43,"tag":85,"props":1346,"children":1347},{"style":1090},[1348],{"type":49,"value":1349}," server.log\n",{"type":43,"tag":59,"props":1351,"children":1352},{},[1353,1358,1360,1366],{"type":43,"tag":135,"props":1354,"children":1355},{},[1356],{"type":49,"value":1357},"FULL AUTOMATION:",{"type":49,"value":1359}," Never tell the user to run commands manually. Install tools, authenticate, start services — do everything automatically. Only ask the user for interactive input that truly requires them (like device code confirmation during ",{"type":43,"tag":65,"props":1361,"children":1363},{"className":1362},[],[1364],{"type":49,"value":1365},"devtunnel user login -g -d",{"type":49,"value":1367},"). If a tool isn't installed, install it. If a service needs starting, start it. The user expects full automation.",{"type":43,"tag":59,"props":1369,"children":1370},{},[1371,1376,1378,1384],{"type":43,"tag":135,"props":1372,"children":1373},{},[1374],{"type":49,"value":1375},"PATH SELECTION (REQUIRED — STOP BEFORE ANY CODE):",{"type":49,"value":1377}," You MUST use ",{"type":43,"tag":65,"props":1379,"children":1381},{"className":1380},[],[1382],{"type":49,"value":1383},"AskUserQuestion",{"type":49,"value":1385}," to ask the user whether they want OAI Apps or MCP Apps Extension before writing any code, running any commands, or making any architectural decisions.",{"type":43,"tag":59,"props":1387,"children":1388},{},[1389,1394,1396,1401,1403,1408],{"type":43,"tag":135,"props":1390,"children":1391},{},[1392],{"type":49,"value":1393},"There is no exception to this rule.",{"type":49,"value":1395}," The most common failure mode is reasoning \"the user's request makes it obvious, so asking is redundant.\" This reasoning is always wrong — invoke ",{"type":43,"tag":65,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":49,"value":1383},{"type":49,"value":1402}," regardless. A user saying \"build an MCP server with widgets\" is NOT an answer to this question. A user invoking this skill by name is NOT an answer. Only an explicit answer to the question counts. See ",{"type":43,"tag":573,"props":1404,"children":1405},{"href":575},[1406],{"type":49,"value":1407},"PATH SELECTION",{"type":49,"value":1409}," above for the exact question to ask.",{"type":43,"tag":59,"props":1411,"children":1412},{},[1413,1418,1420,1425,1427,1432],{"type":43,"tag":135,"props":1414,"children":1415},{},[1416],{"type":49,"value":1417},"AGENT PROVISIONING:",{"type":49,"value":1419}," Re-provisioning is only required when the ",{"type":43,"tag":135,"props":1421,"children":1422},{},[1423],{"type":49,"value":1424},"agent manifest",{"type":49,"value":1426}," changes (e.g., mcpPlugin.json tool definitions, MCP server URL, declarativeAgent.json, instruction.txt). MCP server code changes (tool implementations, React widget code, server logic) do ",{"type":43,"tag":135,"props":1428,"children":1429},{},[1430],{"type":49,"value":1431},"NOT",{"type":49,"value":1433}," require re-provisioning the agent — running or deploying the server picks up changes automatically.",{"type":43,"tag":59,"props":1435,"children":1436},{},[1437],{"type":49,"value":1438},"When provisioning is needed:",{"type":43,"tag":357,"props":1440,"children":1441},{},[1442,1475],{"type":43,"tag":317,"props":1443,"children":1444},{},[1445,1450,1452,1458,1460,1466,1468,1474],{"type":43,"tag":135,"props":1446,"children":1447},{},[1448],{"type":49,"value":1449},"Bump the version",{"type":49,"value":1451}," in ",{"type":43,"tag":65,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":49,"value":1457},"manifest.json",{"type":49,"value":1459}," (increment the patch version, e.g., ",{"type":43,"tag":65,"props":1461,"children":1463},{"className":1462},[],[1464],{"type":49,"value":1465},"1.0.0",{"type":49,"value":1467}," → ",{"type":43,"tag":65,"props":1469,"children":1471},{"className":1470},[],[1472],{"type":49,"value":1473},"1.0.1",{"type":49,"value":185},{"type":43,"tag":317,"props":1476,"children":1477},{},[1478,1483],{"type":43,"tag":135,"props":1479,"children":1480},{},[1481],{"type":49,"value":1482},"Deploy the agent:",{"type":43,"tag":74,"props":1484,"children":1486},{"className":76,"code":1485,"language":78,"meta":79,"style":79},"npx -y --package @microsoft\u002Fm365agentstoolkit-cli atk provision --env local\n",[1487],{"type":43,"tag":65,"props":1488,"children":1489},{"__ignoreMap":79},[1490],{"type":43,"tag":85,"props":1491,"children":1492},{"class":87,"line":88},[1493,1498,1503,1508,1513,1518,1523,1528],{"type":43,"tag":85,"props":1494,"children":1495},{"style":1085},[1496],{"type":49,"value":1497},"npx",{"type":43,"tag":85,"props":1499,"children":1500},{"style":1090},[1501],{"type":49,"value":1502}," -y",{"type":43,"tag":85,"props":1504,"children":1505},{"style":1090},[1506],{"type":49,"value":1507}," --package",{"type":43,"tag":85,"props":1509,"children":1510},{"style":1090},[1511],{"type":49,"value":1512}," @microsoft\u002Fm365agentstoolkit-cli",{"type":43,"tag":85,"props":1514,"children":1515},{"style":1090},[1516],{"type":49,"value":1517}," atk",{"type":43,"tag":85,"props":1519,"children":1520},{"style":1090},[1521],{"type":49,"value":1522}," provision",{"type":43,"tag":85,"props":1524,"children":1525},{"style":1090},[1526],{"type":49,"value":1527}," --env",{"type":43,"tag":85,"props":1529,"children":1530},{"style":1090},[1531],{"type":49,"value":1532}," local\n",{"type":43,"tag":59,"props":1534,"children":1535},{},[1536,1541],{"type":43,"tag":135,"props":1537,"children":1538},{},[1539],{"type":49,"value":1540},"WIDGET TESTING LINKS:",{"type":49,"value":1542}," Every time you return to the user with a result while the MCP server is running, you MUST include links to ALL widgets so they can test them locally. Format:",{"type":43,"tag":74,"props":1544,"children":1547},{"className":1545,"code":1546,"language":49},[399],"🧪 Test widgets locally:\n- http:\u002F\u002Flocalhost:3001\u002Fwidgets\u002Fwidget-name.html\n- http:\u002F\u002Flocalhost:3001\u002Fwidgets\u002Fanother-widget.html\n",[1548],{"type":43,"tag":65,"props":1549,"children":1550},{"__ignoreMap":79},[1551],{"type":49,"value":1546},{"type":43,"tag":59,"props":1553,"children":1554},{},[1555,1557,1563,1565,1571],{"type":49,"value":1556},"List every ",{"type":43,"tag":65,"props":1558,"children":1560},{"className":1559},[],[1561],{"type":49,"value":1562},".html",{"type":49,"value":1564}," file in the ",{"type":43,"tag":65,"props":1566,"children":1568},{"className":1567},[],[1569],{"type":49,"value":1570},"mcp-server\u002Fwidgets\u002F",{"type":49,"value":1572}," directory (or equivalent widget folder). This helps users verify widget rendering before testing in Copilot.",{"type":43,"tag":59,"props":1574,"children":1575},{},[1576,1581],{"type":43,"tag":135,"props":1577,"children":1578},{},[1579],{"type":49,"value":1580},"AUTO-DEPLOY ON COMPLETION (REQUIRED — DO NOT SKIP):",{"type":49,"value":1582}," When coding is complete, proceed automatically without waiting for the user:",{"type":43,"tag":357,"props":1584,"children":1585},{},[1586,1591,1596,1601],{"type":43,"tag":317,"props":1587,"children":1588},{},[1589],{"type":49,"value":1590},"Start MCP server + devtunnel in the background (per BACKGROUND PROCESSES above)",{"type":43,"tag":317,"props":1592,"children":1593},{},[1594],{"type":49,"value":1595},"Run E2E verification with MCP Inspector (per MCP TOOL CONFIGURATION RULE below) — fix any failures before continuing",{"type":43,"tag":317,"props":1597,"children":1598},{},[1599],{"type":49,"value":1600},"Provision the agent if needed (per AGENT PROVISIONING above)",{"type":43,"tag":317,"props":1602,"children":1603},{},[1604],{"type":49,"value":1605},"Print a project summary in this format:",{"type":43,"tag":74,"props":1607,"children":1610},{"className":1608,"code":1609,"language":49},[399],"## ✅ \u003CProject Name> — Ready\n\n### Widgets\n- [widget-name.html](http:\u002F\u002Flocalhost:\u003CPORT>\u002Fwidgets\u002Fwidget-name.html)\n- [widget-name2.html](http:\u002F\u002Flocalhost:\u003CPORT>\u002Fwidgets\u002Fwidget-name2.html)\n\n### Endpoints\n- MCP server: http:\u002F\u002Flocalhost:\u003CPORT>\u002Fmcp\n- MCP via tunnel: https:\u002F\u002F\u003Ctunnel-url>\u002Fmcp\n\n### Test in Copilot\nLocal:      https:\u002F\u002Fm365.cloud.microsoft\u002Fchat\u002F?titleId={M365_TITLE_ID from env\u002F.env.local}\nOther envs: {SHARE_LINK from env\u002F.env.{environment}}\n",[1611],{"type":43,"tag":65,"props":1612,"children":1613},{"__ignoreMap":79},[1614],{"type":49,"value":1609},{"type":43,"tag":59,"props":1616,"children":1617},{},[1618,1623,1625,1631,1632,1638,1639,1645,1647,1652],{"type":43,"tag":135,"props":1619,"children":1620},{},[1621],{"type":49,"value":1622},"AGENT PROJECT DELEGATION:",{"type":49,"value":1624}," This skill builds MCP servers and widgets, NOT declarative agent projects. If the user's request involves creating or configuring the declarative agent itself (scaffolding, ",{"type":43,"tag":65,"props":1626,"children":1628},{"className":1627},[],[1629],{"type":49,"value":1630},"m365agents.yml",{"type":49,"value":855},{"type":43,"tag":65,"props":1633,"children":1635},{"className":1634},[],[1636],{"type":49,"value":1637},"m365agents.local.yml",{"type":49,"value":855},{"type":43,"tag":65,"props":1640,"children":1642},{"className":1641},[],[1643],{"type":49,"value":1644},"declarativeAgent.json",{"type":49,"value":1646},", manifest lifecycle), delegate to the ",{"type":43,"tag":65,"props":1648,"children":1650},{"className":1649},[],[1651],{"type":49,"value":609},{"type":49,"value":1653}," skill.",{"type":43,"tag":59,"props":1655,"children":1656},{},[1657,1662],{"type":43,"tag":135,"props":1658,"children":1659},{},[1660],{"type":49,"value":1661},"MCP RESOURCE REGISTRATION:",{"type":49,"value":1663}," Every widget MUST have a matching MCP resource. Without resources, Copilot cannot fetch widget shells through the MCP protocol and widgets will not render.",{"type":43,"tag":59,"props":1665,"children":1666},{},[1667],{"type":49,"value":1668},"For each new widget, complete this checklist:",{"type":43,"tag":357,"props":1670,"children":1671},{},[1672,1693,1706,1792,1805,1824],{"type":43,"tag":317,"props":1673,"children":1674},{},[1675,1677,1683,1685,1691],{"type":49,"value":1676},"☐ Create a widget shell HTML file in ",{"type":43,"tag":65,"props":1678,"children":1680},{"className":1679},[],[1681],{"type":49,"value":1682},"widgets\u002F",{"type":49,"value":1684}," and a React widget entry under ",{"type":43,"tag":65,"props":1686,"children":1688},{"className":1687},[],[1689],{"type":49,"value":1690},"widgets\u002Fsrc\u002F\u003Cwidget-name>\u002F",{"type":49,"value":1692}," (see widget-patterns.md)",{"type":43,"tag":317,"props":1694,"children":1695},{},[1696,1698,1704],{"type":49,"value":1697},"☐ Define a ",{"type":43,"tag":65,"props":1699,"children":1701},{"className":1700},[],[1702],{"type":49,"value":1703},"ui:\u002F\u002Fwidget\u002F\u003Cname>.html",{"type":49,"value":1705}," URI constant",{"type":43,"tag":317,"props":1707,"children":1708},{},[1709,1711,1717,1719,1725,1727],{"type":49,"value":1710},"☐ Add a ",{"type":43,"tag":65,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":49,"value":1716},"Resource",{"type":49,"value":1718}," entry to the ",{"type":43,"tag":65,"props":1720,"children":1722},{"className":1721},[],[1723],{"type":49,"value":1724},"resources",{"type":49,"value":1726}," array with:\n",{"type":43,"tag":313,"props":1728,"children":1729},{},[1730,1748,1765],{"type":43,"tag":317,"props":1731,"children":1732},{},[1733,1739,1741,1746],{"type":43,"tag":65,"props":1734,"children":1736},{"className":1735},[],[1737],{"type":49,"value":1738},"uri",{"type":49,"value":1740},": the ",{"type":43,"tag":65,"props":1742,"children":1744},{"className":1743},[],[1745],{"type":49,"value":1703},{"type":49,"value":1747}," URI",{"type":43,"tag":317,"props":1749,"children":1750},{},[1751,1757,1759],{"type":43,"tag":65,"props":1752,"children":1754},{"className":1753},[],[1755],{"type":49,"value":1756},"mimeType",{"type":49,"value":1758},": ",{"type":43,"tag":65,"props":1760,"children":1762},{"className":1761},[],[1763],{"type":49,"value":1764},"\"text\u002Fhtml+skybridge\"",{"type":43,"tag":317,"props":1766,"children":1767},{},[1768,1774,1776,1782,1784,1790],{"type":43,"tag":65,"props":1769,"children":1771},{"className":1770},[],[1772],{"type":49,"value":1773},"_meta",{"type":49,"value":1775},": CSP config with ",{"type":43,"tag":65,"props":1777,"children":1779},{"className":1778},[],[1780],{"type":49,"value":1781},"openai\u002FwidgetDomain",{"type":49,"value":1783}," and ",{"type":43,"tag":65,"props":1785,"children":1787},{"className":1786},[],[1788],{"type":49,"value":1789},"openai\u002FwidgetCSP",{"type":49,"value":1791}," (from environment)",{"type":43,"tag":317,"props":1793,"children":1794},{},[1795,1797,1803],{"type":49,"value":1796},"☐ Add a handler for ",{"type":43,"tag":65,"props":1798,"children":1800},{"className":1799},[],[1801],{"type":49,"value":1802},"resources\u002Fread",{"type":49,"value":1804}," that returns the widget shell HTML for this URI",{"type":43,"tag":317,"props":1806,"children":1807},{},[1808,1810,1816,1818,1823],{"type":49,"value":1809},"☐ Add the tool with ",{"type":43,"tag":65,"props":1811,"children":1813},{"className":1812},[],[1814],{"type":49,"value":1815},"_meta.openai\u002FoutputTemplate",{"type":49,"value":1817}," pointing to the same ",{"type":43,"tag":65,"props":1819,"children":1821},{"className":1820},[],[1822],{"type":49,"value":1703},{"type":49,"value":1747},{"type":43,"tag":317,"props":1825,"children":1826},{},[1827,1829,1835],{"type":49,"value":1828},"☐ Verify the server capabilities include ",{"type":43,"tag":65,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":49,"value":1834},"resources: {}",{"type":49,"value":1836}," in the initialize response",{"type":43,"tag":59,"props":1838,"children":1839},{},[1840],{"type":43,"tag":135,"props":1841,"children":1842},{},[1843],{"type":49,"value":1844},"Widget shell + asset considerations:",{"type":43,"tag":313,"props":1846,"children":1847},{},[1848,1866],{"type":43,"tag":317,"props":1849,"children":1850},{},[1851,1856,1858,1864],{"type":43,"tag":135,"props":1852,"children":1853},{},[1854],{"type":49,"value":1855},"Preferred (React + Fluent UI)",{"type":49,"value":1857},": Resource HTML should be a minimal shell that links to built JS\u002FCSS assets served from the MCP server's ",{"type":43,"tag":65,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":49,"value":1863},"\u002Fassets\u002F",{"type":49,"value":1865}," route.",{"type":43,"tag":317,"props":1867,"children":1868},{},[1869,1874,1876,1881],{"type":43,"tag":135,"props":1870,"children":1871},{},[1872],{"type":49,"value":1873},"Exception only",{"type":49,"value":1875},": Self-contained HTML via ",{"type":43,"tag":65,"props":1877,"children":1879},{"className":1878},[],[1880],{"type":49,"value":1802},{"type":49,"value":1882}," is for explicit user-requested prototypes only. Default and production path is React + Fluent UI.",{"type":43,"tag":59,"props":1884,"children":1885},{},[1886],{"type":49,"value":1887},"Example shell for React build output:",{"type":43,"tag":74,"props":1889,"children":1893},{"className":1890,"code":1891,"language":1892,"meta":79,"style":79},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!doctype html>\u003Chtml>\u003Chead>\n  \u003Cscript type=\"module\" src=\"${serverUrl}\u002Fassets\u002Fmy-widget.js\">\u003C\u002Fscript>\n  \u003Clink rel=\"stylesheet\" href=\"${serverUrl}\u002Fassets\u002Fmy-widget.css\">\n\u003C\u002Fhead>\u003Cbody>\n  \u003Cdiv id=\"widget-root\">\u003C\u002Fdiv>\n\u003C\u002Fbody>\u003C\u002Fhtml>\n","html",[1894],{"type":43,"tag":65,"props":1895,"children":1896},{"__ignoreMap":79},[1897,1939,2009,2069,2094,2140],{"type":43,"tag":85,"props":1898,"children":1899},{"class":87,"line":88},[1900,1905,1911,1916,1921,1925,1929,1934],{"type":43,"tag":85,"props":1901,"children":1902},{"style":104},[1903],{"type":49,"value":1904},"\u003C!",{"type":43,"tag":85,"props":1906,"children":1908},{"style":1907},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1909],{"type":49,"value":1910},"doctype",{"type":43,"tag":85,"props":1912,"children":1913},{"style":92},[1914],{"type":49,"value":1915}," html",{"type":43,"tag":85,"props":1917,"children":1918},{"style":104},[1919],{"type":49,"value":1920},">\u003C",{"type":43,"tag":85,"props":1922,"children":1923},{"style":1907},[1924],{"type":49,"value":1892},{"type":43,"tag":85,"props":1926,"children":1927},{"style":104},[1928],{"type":49,"value":1920},{"type":43,"tag":85,"props":1930,"children":1931},{"style":1907},[1932],{"type":49,"value":1933},"head",{"type":43,"tag":85,"props":1935,"children":1936},{"style":104},[1937],{"type":49,"value":1938},">\n",{"type":43,"tag":85,"props":1940,"children":1941},{"class":87,"line":907},[1942,1947,1952,1957,1961,1965,1970,1974,1979,1983,1987,1992,1996,2001,2005],{"type":43,"tag":85,"props":1943,"children":1944},{"style":104},[1945],{"type":49,"value":1946},"  \u003C",{"type":43,"tag":85,"props":1948,"children":1949},{"style":1907},[1950],{"type":49,"value":1951},"script",{"type":43,"tag":85,"props":1953,"children":1954},{"style":92},[1955],{"type":49,"value":1956}," type",{"type":43,"tag":85,"props":1958,"children":1959},{"style":104},[1960],{"type":49,"value":107},{"type":43,"tag":85,"props":1962,"children":1963},{"style":104},[1964],{"type":49,"value":1172},{"type":43,"tag":85,"props":1966,"children":1967},{"style":1090},[1968],{"type":49,"value":1969},"module",{"type":43,"tag":85,"props":1971,"children":1972},{"style":104},[1973],{"type":49,"value":1172},{"type":43,"tag":85,"props":1975,"children":1976},{"style":92},[1977],{"type":49,"value":1978}," src",{"type":43,"tag":85,"props":1980,"children":1981},{"style":104},[1982],{"type":49,"value":107},{"type":43,"tag":85,"props":1984,"children":1985},{"style":104},[1986],{"type":49,"value":1172},{"type":43,"tag":85,"props":1988,"children":1989},{"style":1090},[1990],{"type":49,"value":1991},"${serverUrl}\u002Fassets\u002Fmy-widget.js",{"type":43,"tag":85,"props":1993,"children":1994},{"style":104},[1995],{"type":49,"value":1172},{"type":43,"tag":85,"props":1997,"children":1998},{"style":104},[1999],{"type":49,"value":2000},">\u003C\u002F",{"type":43,"tag":85,"props":2002,"children":2003},{"style":1907},[2004],{"type":49,"value":1951},{"type":43,"tag":85,"props":2006,"children":2007},{"style":104},[2008],{"type":49,"value":1938},{"type":43,"tag":85,"props":2010,"children":2011},{"class":87,"line":916},[2012,2016,2021,2026,2030,2034,2039,2043,2048,2052,2056,2061,2065],{"type":43,"tag":85,"props":2013,"children":2014},{"style":104},[2015],{"type":49,"value":1946},{"type":43,"tag":85,"props":2017,"children":2018},{"style":1907},[2019],{"type":49,"value":2020},"link",{"type":43,"tag":85,"props":2022,"children":2023},{"style":92},[2024],{"type":49,"value":2025}," rel",{"type":43,"tag":85,"props":2027,"children":2028},{"style":104},[2029],{"type":49,"value":107},{"type":43,"tag":85,"props":2031,"children":2032},{"style":104},[2033],{"type":49,"value":1172},{"type":43,"tag":85,"props":2035,"children":2036},{"style":1090},[2037],{"type":49,"value":2038},"stylesheet",{"type":43,"tag":85,"props":2040,"children":2041},{"style":104},[2042],{"type":49,"value":1172},{"type":43,"tag":85,"props":2044,"children":2045},{"style":92},[2046],{"type":49,"value":2047}," href",{"type":43,"tag":85,"props":2049,"children":2050},{"style":104},[2051],{"type":49,"value":107},{"type":43,"tag":85,"props":2053,"children":2054},{"style":104},[2055],{"type":49,"value":1172},{"type":43,"tag":85,"props":2057,"children":2058},{"style":1090},[2059],{"type":49,"value":2060},"${serverUrl}\u002Fassets\u002Fmy-widget.css",{"type":43,"tag":85,"props":2062,"children":2063},{"style":104},[2064],{"type":49,"value":1172},{"type":43,"tag":85,"props":2066,"children":2067},{"style":104},[2068],{"type":49,"value":1938},{"type":43,"tag":85,"props":2070,"children":2071},{"class":87,"line":925},[2072,2077,2081,2085,2090],{"type":43,"tag":85,"props":2073,"children":2074},{"style":104},[2075],{"type":49,"value":2076},"\u003C\u002F",{"type":43,"tag":85,"props":2078,"children":2079},{"style":1907},[2080],{"type":49,"value":1933},{"type":43,"tag":85,"props":2082,"children":2083},{"style":104},[2084],{"type":49,"value":1920},{"type":43,"tag":85,"props":2086,"children":2087},{"style":1907},[2088],{"type":49,"value":2089},"body",{"type":43,"tag":85,"props":2091,"children":2092},{"style":104},[2093],{"type":49,"value":1938},{"type":43,"tag":85,"props":2095,"children":2096},{"class":87,"line":934},[2097,2101,2106,2111,2115,2119,2124,2128,2132,2136],{"type":43,"tag":85,"props":2098,"children":2099},{"style":104},[2100],{"type":49,"value":1946},{"type":43,"tag":85,"props":2102,"children":2103},{"style":1907},[2104],{"type":49,"value":2105},"div",{"type":43,"tag":85,"props":2107,"children":2108},{"style":92},[2109],{"type":49,"value":2110}," id",{"type":43,"tag":85,"props":2112,"children":2113},{"style":104},[2114],{"type":49,"value":107},{"type":43,"tag":85,"props":2116,"children":2117},{"style":104},[2118],{"type":49,"value":1172},{"type":43,"tag":85,"props":2120,"children":2121},{"style":1090},[2122],{"type":49,"value":2123},"widget-root",{"type":43,"tag":85,"props":2125,"children":2126},{"style":104},[2127],{"type":49,"value":1172},{"type":43,"tag":85,"props":2129,"children":2130},{"style":104},[2131],{"type":49,"value":2000},{"type":43,"tag":85,"props":2133,"children":2134},{"style":1907},[2135],{"type":49,"value":2105},{"type":43,"tag":85,"props":2137,"children":2138},{"style":104},[2139],{"type":49,"value":1938},{"type":43,"tag":85,"props":2141,"children":2142},{"class":87,"line":943},[2143,2147,2151,2155,2159],{"type":43,"tag":85,"props":2144,"children":2145},{"style":104},[2146],{"type":49,"value":2076},{"type":43,"tag":85,"props":2148,"children":2149},{"style":1907},[2150],{"type":49,"value":2089},{"type":43,"tag":85,"props":2152,"children":2153},{"style":104},[2154],{"type":49,"value":2000},{"type":43,"tag":85,"props":2156,"children":2157},{"style":1907},[2158],{"type":49,"value":1892},{"type":43,"tag":85,"props":2160,"children":2161},{"style":104},[2162],{"type":49,"value":1938},{"type":43,"tag":59,"props":2164,"children":2165},{},[2166,2168,2174,2175,2181],{"type":49,"value":2167},"Use the ",{"type":43,"tag":65,"props":2169,"children":2171},{"className":2170},[],[2172],{"type":49,"value":2173},"WIDGET_BASE_URL",{"type":49,"value":564},{"type":43,"tag":65,"props":2176,"children":2178},{"className":2177},[],[2179],{"type":49,"value":2180},"MCP_SERVER_URL",{"type":49,"value":2182}," environment variable for the asset URL base (see mcp-server-pattern.md \"Configurable Widget Base URL\" section).",{"type":43,"tag":59,"props":2184,"children":2185},{},[2186,2187,2192],{"type":49,"value":687},{"type":43,"tag":573,"props":2188,"children":2189},{"href":697},[2190],{"type":49,"value":2191},"mcp-server-pattern.md",{"type":49,"value":2193}," for the complete resource and asset serving patterns.",{"type":43,"tag":483,"props":2195,"children":2196},{},[],{"type":43,"tag":52,"props":2198,"children":2200},{"id":2199},"️-mcp-tool-configuration-rule-️",[2201],{"type":49,"value":2202},"⚠️ MCP TOOL CONFIGURATION RULE ⚠️",{"type":43,"tag":59,"props":2204,"children":2205},{},[2206,2218],{"type":43,"tag":135,"props":2207,"children":2208},{},[2209,2211,2217],{"type":49,"value":2210},"NEVER manually write tool definitions in ",{"type":43,"tag":65,"props":2212,"children":2214},{"className":2213},[],[2215],{"type":49,"value":2216},"mcpPlugin.json",{"type":49,"value":1049},{"type":49,"value":2219}," Always use MCP Inspector to get the complete tool definitions from the running MCP server.",{"type":43,"tag":59,"props":2221,"children":2222},{},[2223,2228,2230,2236,2238,2243,2245,2251,2253,2259],{"type":43,"tag":135,"props":2224,"children":2225},{},[2226],{"type":49,"value":2227},"TOOL NAMING CONVENTION:",{"type":49,"value":2229}," Tool names MUST match the pattern ",{"type":43,"tag":65,"props":2231,"children":2233},{"className":2232},[],[2234],{"type":49,"value":2235},"^[A-Za-z0-9_]+$",{"type":49,"value":2237}," (letters, numbers, and underscores only). ",{"type":43,"tag":135,"props":2239,"children":2240},{},[2241],{"type":49,"value":2242},"NEVER use hyphens (-) in tool names.",{"type":49,"value":2244}," Use underscores instead (e.g., ",{"type":43,"tag":65,"props":2246,"children":2248},{"className":2247},[],[2249],{"type":49,"value":2250},"render_profile",{"type":49,"value":2252}," not ",{"type":43,"tag":65,"props":2254,"children":2256},{"className":2255},[],[2257],{"type":49,"value":2258},"render-profile",{"type":49,"value":2260},").",{"type":43,"tag":59,"props":2262,"children":2263},{},[2264],{"type":43,"tag":135,"props":2265,"children":2266},{},[2267],{"type":49,"value":2268},"MANDATORY WORKFLOW:",{"type":43,"tag":357,"props":2270,"children":2271},{},[2272,2282,2341,2392,2431],{"type":43,"tag":317,"props":2273,"children":2274},{},[2275,2280],{"type":43,"tag":135,"props":2276,"children":2277},{},[2278],{"type":49,"value":2279},"Start the MCP server",{"type":49,"value":2281}," (in background)",{"type":43,"tag":317,"props":2283,"children":2284},{},[2285,2290,2292],{"type":43,"tag":135,"props":2286,"children":2287},{},[2288],{"type":49,"value":2289},"Use MCP Inspector",{"type":49,"value":2291}," to get the latest tool definitions:\n",{"type":43,"tag":74,"props":2293,"children":2295},{"className":76,"code":2294,"language":78,"meta":79,"style":79},"npx @modelcontextprotocol\u002Finspector@0.20.0 --cli https:\u002F\u002Fmy-mcp-server.example.com --transport http --method tools\u002Flist\n",[2296],{"type":43,"tag":65,"props":2297,"children":2298},{"__ignoreMap":79},[2299],{"type":43,"tag":85,"props":2300,"children":2301},{"class":87,"line":88},[2302,2306,2311,2316,2321,2326,2331,2336],{"type":43,"tag":85,"props":2303,"children":2304},{"style":1085},[2305],{"type":49,"value":1497},{"type":43,"tag":85,"props":2307,"children":2308},{"style":1090},[2309],{"type":49,"value":2310}," @modelcontextprotocol\u002Finspector@0.20.0",{"type":43,"tag":85,"props":2312,"children":2313},{"style":1090},[2314],{"type":49,"value":2315}," --cli",{"type":43,"tag":85,"props":2317,"children":2318},{"style":1090},[2319],{"type":49,"value":2320}," https:\u002F\u002Fmy-mcp-server.example.com",{"type":43,"tag":85,"props":2322,"children":2323},{"style":1090},[2324],{"type":49,"value":2325}," --transport",{"type":43,"tag":85,"props":2327,"children":2328},{"style":1090},[2329],{"type":49,"value":2330}," http",{"type":43,"tag":85,"props":2332,"children":2333},{"style":1090},[2334],{"type":49,"value":2335}," --method",{"type":43,"tag":85,"props":2337,"children":2338},{"style":1090},[2339],{"type":49,"value":2340}," tools\u002Flist\n",{"type":43,"tag":317,"props":2342,"children":2343},{},[2344,2349,2351,2357,2358,2364,2365,2371,2372,2377,2378,2384,2385,2391],{"type":43,"tag":135,"props":2345,"children":2346},{},[2347],{"type":49,"value":2348},"Copy the COMPLETE tool definition",{"type":49,"value":2350}," from the inspector (including ",{"type":43,"tag":65,"props":2352,"children":2354},{"className":2353},[],[2355],{"type":49,"value":2356},"name",{"type":49,"value":855},{"type":43,"tag":65,"props":2359,"children":2361},{"className":2360},[],[2362],{"type":49,"value":2363},"description",{"type":49,"value":855},{"type":43,"tag":65,"props":2366,"children":2368},{"className":2367},[],[2369],{"type":49,"value":2370},"inputSchema",{"type":49,"value":855},{"type":43,"tag":65,"props":2373,"children":2375},{"className":2374},[],[2376],{"type":49,"value":1773},{"type":49,"value":855},{"type":43,"tag":65,"props":2379,"children":2381},{"className":2380},[],[2382],{"type":49,"value":2383},"annotations",{"type":49,"value":855},{"type":43,"tag":65,"props":2386,"children":2388},{"className":2387},[],[2389],{"type":49,"value":2390},"title",{"type":49,"value":185},{"type":43,"tag":317,"props":2393,"children":2394},{},[2395,2405,2407,2413,2415,2421,2423,2429],{"type":43,"tag":135,"props":2396,"children":2397},{},[2398,2400],{"type":49,"value":2399},"Paste into ",{"type":43,"tag":65,"props":2401,"children":2403},{"className":2402},[],[2404],{"type":49,"value":2216},{"type":49,"value":2406}," under ",{"type":43,"tag":65,"props":2408,"children":2410},{"className":2409},[],[2411],{"type":49,"value":2412},"runtimes[].spec.mcp_tool_description.tools",{"type":49,"value":2414}," (inside the ",{"type":43,"tag":65,"props":2416,"children":2418},{"className":2417},[],[2419],{"type":49,"value":2420},"RemoteMCPServer",{"type":49,"value":2422}," runtime's ",{"type":43,"tag":65,"props":2424,"children":2426},{"className":2425},[],[2427],{"type":49,"value":2428},"spec",{"type":49,"value":2430}," object)",{"type":43,"tag":317,"props":2432,"children":2433},{},[2434,2439,2441,2447,2448,2454,2456,2546,2548,2554,2556,2562],{"type":43,"tag":135,"props":2435,"children":2436},{},[2437],{"type":49,"value":2438},"Run E2E verification",{"type":49,"value":2440}," through the devtunnel — call each tool and confirm the response contains ",{"type":43,"tag":65,"props":2442,"children":2444},{"className":2443},[],[2445],{"type":49,"value":2446},"structuredContent",{"type":49,"value":1783},{"type":43,"tag":65,"props":2449,"children":2451},{"className":2450},[],[2452],{"type":49,"value":2453},"_meta.openai\u002FwidgetAccessible: true",{"type":49,"value":2455},":\n",{"type":43,"tag":74,"props":2457,"children":2459},{"className":76,"code":2458,"language":78,"meta":79,"style":79},"npx @modelcontextprotocol\u002Finspector@0.20.0 --cli https:\u002F\u002F\u003Ctunnel-url>\u002Fmcp --transport http --method tools\u002Fcall --tool-name \u003Ctool_name>\n",[2460],{"type":43,"tag":65,"props":2461,"children":2462},{"__ignoreMap":79},[2463],{"type":43,"tag":85,"props":2464,"children":2465},{"class":87,"line":88},[2466,2470,2474,2478,2483,2488,2493,2498,2502,2507,2511,2515,2519,2524,2529,2533,2538,2542],{"type":43,"tag":85,"props":2467,"children":2468},{"style":1085},[2469],{"type":49,"value":1497},{"type":43,"tag":85,"props":2471,"children":2472},{"style":1090},[2473],{"type":49,"value":2310},{"type":43,"tag":85,"props":2475,"children":2476},{"style":1090},[2477],{"type":49,"value":2315},{"type":43,"tag":85,"props":2479,"children":2480},{"style":1090},[2481],{"type":49,"value":2482}," https:\u002F\u002F",{"type":43,"tag":85,"props":2484,"children":2485},{"style":104},[2486],{"type":49,"value":2487},"\u003C",{"type":43,"tag":85,"props":2489,"children":2490},{"style":1090},[2491],{"type":49,"value":2492},"tunnel-ur",{"type":43,"tag":85,"props":2494,"children":2495},{"style":98},[2496],{"type":49,"value":2497},"l",{"type":43,"tag":85,"props":2499,"children":2500},{"style":104},[2501],{"type":49,"value":1118},{"type":43,"tag":85,"props":2503,"children":2504},{"style":1090},[2505],{"type":49,"value":2506},"\u002Fmcp",{"type":43,"tag":85,"props":2508,"children":2509},{"style":1090},[2510],{"type":49,"value":2325},{"type":43,"tag":85,"props":2512,"children":2513},{"style":1090},[2514],{"type":49,"value":2330},{"type":43,"tag":85,"props":2516,"children":2517},{"style":1090},[2518],{"type":49,"value":2335},{"type":43,"tag":85,"props":2520,"children":2521},{"style":1090},[2522],{"type":49,"value":2523}," tools\u002Fcall",{"type":43,"tag":85,"props":2525,"children":2526},{"style":1090},[2527],{"type":49,"value":2528}," --tool-name",{"type":43,"tag":85,"props":2530,"children":2531},{"style":104},[2532],{"type":49,"value":1103},{"type":43,"tag":85,"props":2534,"children":2535},{"style":1090},[2536],{"type":49,"value":2537},"tool_nam",{"type":43,"tag":85,"props":2539,"children":2540},{"style":98},[2541],{"type":49,"value":1113},{"type":43,"tag":85,"props":2543,"children":2544},{"style":104},[2545],{"type":49,"value":1938},{"type":49,"value":2547},"\nAlso verify ",{"type":43,"tag":65,"props":2549,"children":2551},{"className":2550},[],[2552],{"type":49,"value":2553},"GET https:\u002F\u002F\u003Ctunnel-url>\u002Fhealth",{"type":49,"value":2555}," returns ",{"type":43,"tag":65,"props":2557,"children":2559},{"className":2558},[],[2560],{"type":49,"value":2561},"{\"status\":\"ok\"}",{"type":49,"value":2563},". Fix any failures before provisioning.",{"type":43,"tag":59,"props":2565,"children":2566},{},[2567,2569,2574],{"type":49,"value":2568},"The MCP Inspector shows the exact tool schema from your server. Copy it completely — do not manually write or modify these definitions. This ensures ",{"type":43,"tag":65,"props":2570,"children":2572},{"className":2571},[],[2573],{"type":49,"value":2216},{"type":49,"value":2575}," stays in sync with the MCP server.",{"type":43,"tag":483,"props":2577,"children":2578},{},[],{"type":43,"tag":59,"props":2580,"children":2581},{},[2582],{"type":49,"value":2583},"Build MCP servers that integrate with Microsoft 365 Copilot Chat and render rich interactive widgets.",{"type":43,"tag":52,"props":2585,"children":2587},{"id":2586},"architecture",[2588],{"type":49,"value":2589},"Architecture",{"type":43,"tag":74,"props":2591,"children":2594},{"className":2592,"code":2593,"language":49},[399],"M365 Copilot ──▶ mcpPlugin.json ──▶ MCP Server ──▶ structuredContent ──▶ React + Fluent UI Widget\n     │              (RemoteMCPServer)    (Streamable HTTP)                  (window.openai.toolOutput)\n     │\n     └── Capabilities (People, etc.) provide data to pass to MCP tools\n",[2595],{"type":43,"tag":65,"props":2596,"children":2597},{"__ignoreMap":79},[2598],{"type":49,"value":2593},{"type":43,"tag":52,"props":2600,"children":2602},{"id":2601},"project-structure",[2603],{"type":49,"value":2604},"Project Structure",{"type":43,"tag":59,"props":2606,"children":2607},{},[2608],{"type":49,"value":2609},"Example project structure, not a hard requirement but a common pattern for organizing MCP server + widget development:",{"type":43,"tag":74,"props":2611,"children":2614},{"className":2612,"code":2613,"language":49},[399],"project\u002F\n├── appPackage\u002F\n│   ├── manifest.json           # Teams manifest (bump version on deploy)\n│   ├── declarativeAgent.json   # Agent config + capabilities\n│   ├── mcpPlugin.json          # Tool definitions with _meta\n│   └── instruction.txt         # Agent behavior instructions\n├── mcp-server\u002F\n│   ├── src\u002Findex.ts            # Server with Streamable HTTP\n│   ├── widgets\u002F                # Widget shells + React source\n│   │   ├── my-widget.html      # Minimal shell returned by resources\u002Fread\n│   │   └── src\u002Fmy-widget\u002F      # React + Fluent UI source\n│   ├── assets\u002F                 # Built widget bundles served at \u002Fassets\n│   └── package.json\n├── scripts\u002F\n│   ├── setup-devtunnel.sh      # Linux\u002FMac devtunnel setup\n│   └── setup-devtunnel.ps1     # Windows devtunnel setup\n└── env\u002F.env.local              # MCP_SERVER_URL, MCP_SERVER_DOMAIN\n",[2615],{"type":43,"tag":65,"props":2616,"children":2617},{"__ignoreMap":79},[2618],{"type":49,"value":2613},{"type":43,"tag":59,"props":2620,"children":2621},{},[2622,2627,2629,2635,2637,2643,2645,2651,2652,2657,2658,2664,2665,2671],{"type":43,"tag":135,"props":2623,"children":2624},{},[2625],{"type":49,"value":2626},"Language note",{"type":49,"value":2628},": This shows a TypeScript project layout. For Python, replace ",{"type":43,"tag":65,"props":2630,"children":2632},{"className":2631},[],[2633],{"type":49,"value":2634},"mcp-server\u002Fsrc\u002Findex.ts",{"type":49,"value":2636}," with your Python entry point (e.g., ",{"type":43,"tag":65,"props":2638,"children":2640},{"className":2639},[],[2641],{"type":49,"value":2642},"server.py",{"type":49,"value":2644},"). For C#, use a standard .NET project structure. The ",{"type":43,"tag":65,"props":2646,"children":2648},{"className":2647},[],[2649],{"type":49,"value":2650},"appPackage\u002F",{"type":49,"value":855},{"type":43,"tag":65,"props":2653,"children":2655},{"className":2654},[],[2656],{"type":49,"value":1682},{"type":49,"value":855},{"type":43,"tag":65,"props":2659,"children":2661},{"className":2660},[],[2662],{"type":49,"value":2663},"scripts\u002F",{"type":49,"value":863},{"type":43,"tag":65,"props":2666,"children":2668},{"className":2667},[],[2669],{"type":49,"value":2670},"env\u002F",{"type":49,"value":2672}," directories are language-agnostic.",{"type":43,"tag":52,"props":2674,"children":2676},{"id":2675},"copilot-widget-protocol",[2677],{"type":49,"value":664},{"type":43,"tag":59,"props":2679,"children":2680},{},[2681],{"type":49,"value":2682},"Your MCP server must implement these protocol requirements to render widgets in Copilot Chat. This applies regardless of language:",{"type":43,"tag":357,"props":2684,"children":2685},{},[2686,2703,2735,2764,2794,2831],{"type":43,"tag":317,"props":2687,"children":2688},{},[2689,2694,2696,2701],{"type":43,"tag":135,"props":2690,"children":2691},{},[2692],{"type":49,"value":2693},"Streamable HTTP transport",{"type":49,"value":2695}," — ",{"type":43,"tag":65,"props":2697,"children":2699},{"className":2698},[],[2700],{"type":49,"value":2506},{"type":49,"value":2702}," endpoint handling POST, GET, DELETE with session management",{"type":43,"tag":317,"props":2704,"children":2705},{},[2706,2711,2713,2718,2720,2726,2727,2733],{"type":43,"tag":135,"props":2707,"children":2708},{},[2709],{"type":49,"value":2710},"CORS headers",{"type":49,"value":2712}," — Origin-checking on ",{"type":43,"tag":65,"props":2714,"children":2716},{"className":2715},[],[2717],{"type":49,"value":2506},{"type":49,"value":2719}," allowing ",{"type":43,"tag":65,"props":2721,"children":2723},{"className":2722},[],[2724],{"type":49,"value":2725},"m365.cloud.microsoft",{"type":49,"value":1783},{"type":43,"tag":65,"props":2728,"children":2730},{"className":2729},[],[2731],{"type":49,"value":2732},"*.m365.cloud.microsoft",{"type":49,"value":2734},", with required MCP headers",{"type":43,"tag":317,"props":2736,"children":2737},{},[2738,2743,2744,2750,2752,2757,2758],{"type":43,"tag":135,"props":2739,"children":2740},{},[2741],{"type":49,"value":2742},"Server capabilities",{"type":49,"value":2695},{"type":43,"tag":65,"props":2745,"children":2747},{"className":2746},[],[2748],{"type":49,"value":2749},"initialize",{"type":49,"value":2751}," response must declare ",{"type":43,"tag":65,"props":2753,"children":2755},{"className":2754},[],[2756],{"type":49,"value":1834},{"type":49,"value":1783},{"type":43,"tag":65,"props":2759,"children":2761},{"className":2760},[],[2762],{"type":49,"value":2763},"tools: {}",{"type":43,"tag":317,"props":2765,"children":2766},{},[2767,2772,2774,2779,2781,2787,2789],{"type":43,"tag":135,"props":2768,"children":2769},{},[2770],{"type":49,"value":2771},"MCP resources",{"type":49,"value":2773}," — Register widgets with ",{"type":43,"tag":65,"props":2775,"children":2777},{"className":2776},[],[2778],{"type":49,"value":1703},{"type":49,"value":2780}," URIs, ",{"type":43,"tag":65,"props":2782,"children":2784},{"className":2783},[],[2785],{"type":49,"value":2786},"text\u002Fhtml+skybridge",{"type":49,"value":2788}," mime type, and CSP ",{"type":43,"tag":65,"props":2790,"children":2792},{"className":2791},[],[2793],{"type":49,"value":1773},{"type":43,"tag":317,"props":2795,"children":2796},{},[2797,2802,2804,2810,2812,2817,2819,2824,2825],{"type":43,"tag":135,"props":2798,"children":2799},{},[2800],{"type":49,"value":2801},"Tool response format",{"type":49,"value":2803}," — Return ",{"type":43,"tag":65,"props":2805,"children":2807},{"className":2806},[],[2808],{"type":49,"value":2809},"content",{"type":49,"value":2811}," (text) + ",{"type":43,"tag":65,"props":2813,"children":2815},{"className":2814},[],[2816],{"type":49,"value":2446},{"type":49,"value":2818}," (widget data) + ",{"type":43,"tag":65,"props":2820,"children":2822},{"className":2821},[],[2823],{"type":49,"value":1773},{"type":49,"value":1065},{"type":43,"tag":65,"props":2826,"children":2828},{"className":2827},[],[2829],{"type":49,"value":2830},"openai\u002FoutputTemplate",{"type":43,"tag":317,"props":2832,"children":2833},{},[2834,2839,2841,2847,2849,2855],{"type":43,"tag":135,"props":2835,"children":2836},{},[2837],{"type":49,"value":2838},"Widget serving",{"type":49,"value":2840}," — HTTP route at ",{"type":43,"tag":65,"props":2842,"children":2844},{"className":2843},[],[2845],{"type":49,"value":2846},"\u002Fwidgets\u002F*.html",{"type":49,"value":2848}," for shell files and ",{"type":43,"tag":65,"props":2850,"children":2852},{"className":2851},[],[2853],{"type":49,"value":2854},"\u002Fassets\u002F*",{"type":49,"value":2856}," for built bundles, both with origin-checking CORS",{"type":43,"tag":59,"props":2858,"children":2859},{},[2860,2862,2866],{"type":49,"value":2861},"For full protocol details, JSON shapes, and an adaptation checklist for existing MCP servers, see ",{"type":43,"tag":573,"props":2863,"children":2864},{"href":690},[2865],{"type":49,"value":690},{"type":49,"value":1049},{"type":43,"tag":52,"props":2868,"children":2870},{"id":2869},"implementation",[2871],{"type":49,"value":638},{"type":43,"tag":345,"props":2873,"children":2875},{"id":2874},"mcp-server-pattern-typescript-reference",[2876],{"type":49,"value":2877},"MCP Server Pattern (TypeScript Reference)",{"type":43,"tag":59,"props":2879,"children":2880},{},[2881,2882,2886],{"type":49,"value":687},{"type":43,"tag":573,"props":2883,"children":2884},{"href":697},[2885],{"type":49,"value":697},{"type":49,"value":2887}," for complete implementation.",{"type":43,"tag":407,"props":2889,"children":2890},{},[2891],{"type":43,"tag":59,"props":2892,"children":2893},{},[2894,2896,2900,2902,2908],{"type":49,"value":2895},"For other languages, implement the requirements described in ",{"type":43,"tag":573,"props":2897,"children":2898},{"href":690},[2899],{"type":49,"value":664},{"type":49,"value":2901}," using your language's MCP SDK. See the ",{"type":43,"tag":573,"props":2903,"children":2905},{"href":2904},"references\u002Fcopilot-widget-protocol.md#language-sdk-references",[2906],{"type":49,"value":2907},"Language SDK References",{"type":49,"value":2909}," table for SDK packages.",{"type":43,"tag":59,"props":2911,"children":2912},{},[2913],{"type":49,"value":2914},"Core requirements:",{"type":43,"tag":313,"props":2916,"children":2917},{},[2918,2928,2951,2956,2961],{"type":43,"tag":317,"props":2919,"children":2920},{},[2921,2923],{"type":49,"value":2922},"Expose Streamable HTTP transport on ",{"type":43,"tag":65,"props":2924,"children":2926},{"className":2925},[],[2927],{"type":49,"value":2506},{"type":43,"tag":317,"props":2929,"children":2930},{},[2931,2933,2938,2940,2945,2946],{"type":49,"value":2932},"Return ",{"type":43,"tag":65,"props":2934,"children":2936},{"className":2935},[],[2937],{"type":49,"value":2446},{"type":49,"value":2939}," + ",{"type":43,"tag":65,"props":2941,"children":2943},{"className":2942},[],[2944],{"type":49,"value":1773},{"type":49,"value":1065},{"type":43,"tag":65,"props":2947,"children":2949},{"className":2948},[],[2950],{"type":49,"value":2830},{"type":43,"tag":317,"props":2952,"children":2953},{},[2954],{"type":49,"value":2955},"Serve widgets via HTTP endpoint",{"type":43,"tag":317,"props":2957,"children":2958},{},[2959],{"type":49,"value":2960},"Handle CORS for cross-origin requests",{"type":43,"tag":317,"props":2962,"children":2963},{},[2964],{"type":49,"value":2965},"Handle partial data gracefully (fill in \"Unknown\" for missing fields)",{"type":43,"tag":59,"props":2967,"children":2968},{},[2969],{"type":49,"value":2970},"Tool response format:",{"type":43,"tag":74,"props":2972,"children":2976},{"className":2973,"code":2974,"language":2975,"meta":79,"style":79},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","return {\n  content: [{ type: \"text\", text: \"Summary\" }],\n  structuredContent: { \u002F* widget data *\u002F },\n  _meta: { \"openai\u002FoutputTemplate\": \"ui:\u002F\u002Fwidget\u002Fname.html\", \"openai\u002FwidgetAccessible\": true }\n};\n","typescript",[2977],{"type":43,"tag":65,"props":2978,"children":2979},{"__ignoreMap":79},[2980,2994,3078,3105,3182],{"type":43,"tag":85,"props":2981,"children":2982},{"class":87,"line":88},[2983,2989],{"type":43,"tag":85,"props":2984,"children":2986},{"style":2985},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[2987],{"type":49,"value":2988},"return",{"type":43,"tag":85,"props":2990,"children":2991},{"style":104},[2992],{"type":49,"value":2993}," {\n",{"type":43,"tag":85,"props":2995,"children":2996},{"class":87,"line":907},[2997,3002,3006,3011,3016,3020,3024,3028,3032,3036,3041,3046,3050,3054,3059,3063,3068,3073],{"type":43,"tag":85,"props":2998,"children":2999},{"style":1907},[3000],{"type":49,"value":3001},"  content",{"type":43,"tag":85,"props":3003,"children":3004},{"style":104},[3005],{"type":49,"value":887},{"type":43,"tag":85,"props":3007,"children":3008},{"style":98},[3009],{"type":49,"value":3010}," [",{"type":43,"tag":85,"props":3012,"children":3013},{"style":104},[3014],{"type":49,"value":3015},"{",{"type":43,"tag":85,"props":3017,"children":3018},{"style":1907},[3019],{"type":49,"value":1956},{"type":43,"tag":85,"props":3021,"children":3022},{"style":104},[3023],{"type":49,"value":887},{"type":43,"tag":85,"props":3025,"children":3026},{"style":104},[3027],{"type":49,"value":1157},{"type":43,"tag":85,"props":3029,"children":3030},{"style":1090},[3031],{"type":49,"value":49},{"type":43,"tag":85,"props":3033,"children":3034},{"style":104},[3035],{"type":49,"value":1172},{"type":43,"tag":85,"props":3037,"children":3038},{"style":104},[3039],{"type":49,"value":3040},",",{"type":43,"tag":85,"props":3042,"children":3043},{"style":1907},[3044],{"type":49,"value":3045}," text",{"type":43,"tag":85,"props":3047,"children":3048},{"style":104},[3049],{"type":49,"value":887},{"type":43,"tag":85,"props":3051,"children":3052},{"style":104},[3053],{"type":49,"value":1157},{"type":43,"tag":85,"props":3055,"children":3056},{"style":1090},[3057],{"type":49,"value":3058},"Summary",{"type":43,"tag":85,"props":3060,"children":3061},{"style":104},[3062],{"type":49,"value":1172},{"type":43,"tag":85,"props":3064,"children":3065},{"style":104},[3066],{"type":49,"value":3067}," }",{"type":43,"tag":85,"props":3069,"children":3070},{"style":98},[3071],{"type":49,"value":3072},"]",{"type":43,"tag":85,"props":3074,"children":3075},{"style":104},[3076],{"type":49,"value":3077},",\n",{"type":43,"tag":85,"props":3079,"children":3080},{"class":87,"line":916},[3081,3086,3090,3095,3100],{"type":43,"tag":85,"props":3082,"children":3083},{"style":1907},[3084],{"type":49,"value":3085},"  structuredContent",{"type":43,"tag":85,"props":3087,"children":3088},{"style":104},[3089],{"type":49,"value":887},{"type":43,"tag":85,"props":3091,"children":3092},{"style":104},[3093],{"type":49,"value":3094}," {",{"type":43,"tag":85,"props":3096,"children":3097},{"style":1313},[3098],{"type":49,"value":3099}," \u002F* widget data *\u002F",{"type":43,"tag":85,"props":3101,"children":3102},{"style":104},[3103],{"type":49,"value":3104}," },\n",{"type":43,"tag":85,"props":3106,"children":3107},{"class":87,"line":925},[3108,3113,3117,3121,3125,3129,3133,3137,3141,3146,3150,3154,3158,3163,3167,3171,3177],{"type":43,"tag":85,"props":3109,"children":3110},{"style":1907},[3111],{"type":49,"value":3112},"  _meta",{"type":43,"tag":85,"props":3114,"children":3115},{"style":104},[3116],{"type":49,"value":887},{"type":43,"tag":85,"props":3118,"children":3119},{"style":104},[3120],{"type":49,"value":3094},{"type":43,"tag":85,"props":3122,"children":3123},{"style":104},[3124],{"type":49,"value":1157},{"type":43,"tag":85,"props":3126,"children":3127},{"style":1907},[3128],{"type":49,"value":2830},{"type":43,"tag":85,"props":3130,"children":3131},{"style":104},[3132],{"type":49,"value":1172},{"type":43,"tag":85,"props":3134,"children":3135},{"style":104},[3136],{"type":49,"value":887},{"type":43,"tag":85,"props":3138,"children":3139},{"style":104},[3140],{"type":49,"value":1157},{"type":43,"tag":85,"props":3142,"children":3143},{"style":1090},[3144],{"type":49,"value":3145},"ui:\u002F\u002Fwidget\u002Fname.html",{"type":43,"tag":85,"props":3147,"children":3148},{"style":104},[3149],{"type":49,"value":1172},{"type":43,"tag":85,"props":3151,"children":3152},{"style":104},[3153],{"type":49,"value":3040},{"type":43,"tag":85,"props":3155,"children":3156},{"style":104},[3157],{"type":49,"value":1157},{"type":43,"tag":85,"props":3159,"children":3160},{"style":1907},[3161],{"type":49,"value":3162},"openai\u002FwidgetAccessible",{"type":43,"tag":85,"props":3164,"children":3165},{"style":104},[3166],{"type":49,"value":1172},{"type":43,"tag":85,"props":3168,"children":3169},{"style":104},[3170],{"type":49,"value":887},{"type":43,"tag":85,"props":3172,"children":3174},{"style":3173},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[3175],{"type":49,"value":3176}," true",{"type":43,"tag":85,"props":3178,"children":3179},{"style":104},[3180],{"type":49,"value":3181}," }\n",{"type":43,"tag":85,"props":3183,"children":3184},{"class":87,"line":934},[3185],{"type":43,"tag":85,"props":3186,"children":3187},{"style":104},[3188],{"type":49,"value":3189},"};\n",{"type":43,"tag":345,"props":3191,"children":3193},{"id":3192},"handling-partial-data",[3194],{"type":49,"value":3195},"Handling Partial Data",{"type":43,"tag":59,"props":3197,"children":3198},{},[3199],{"type":49,"value":3200},"Always normalize input data to handle missing fields:",{"type":43,"tag":74,"props":3202,"children":3204},{"className":2973,"code":3203,"language":2975,"meta":79,"style":79},"server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => {\n  const args = request.params.arguments as { title?: string; items?: Partial\u003CItem>[] };\n\n  \u002F\u002F Normalize data - fill in \"Unknown\" for missing fields\n  const title = args.title || \"Default Title\";\n  const items = (args.items || []).map(item => ({\n    name: item.name || \"Unknown\",\n    value: item.value || \"Unknown\",\n  }));\n\n  \u002F\u002F Build structuredContent for widget\n  const structuredContent = { title, items };\n  \u002F\u002F ...\n});\n",[3205],{"type":43,"tag":65,"props":3206,"children":3207},{"__ignoreMap":79},[3208,3271,3377,3384,3392,3442,3516,3562,3607,3624,3631,3639,3676,3684],{"type":43,"tag":85,"props":3209,"children":3210},{"class":87,"line":88},[3211,3216,3220,3225,3230,3234,3239,3243,3249,3253,3258,3262,3267],{"type":43,"tag":85,"props":3212,"children":3213},{"style":98},[3214],{"type":49,"value":3215},"server",{"type":43,"tag":85,"props":3217,"children":3218},{"style":104},[3219],{"type":49,"value":1049},{"type":43,"tag":85,"props":3221,"children":3222},{"style":1149},[3223],{"type":49,"value":3224},"setRequestHandler",{"type":43,"tag":85,"props":3226,"children":3227},{"style":98},[3228],{"type":49,"value":3229},"(CallToolRequestSchema",{"type":43,"tag":85,"props":3231,"children":3232},{"style":104},[3233],{"type":49,"value":3040},{"type":43,"tag":85,"props":3235,"children":3236},{"style":92},[3237],{"type":49,"value":3238}," async",{"type":43,"tag":85,"props":3240,"children":3241},{"style":104},[3242],{"type":49,"value":177},{"type":43,"tag":85,"props":3244,"children":3246},{"style":3245},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[3247],{"type":49,"value":3248},"request",{"type":43,"tag":85,"props":3250,"children":3251},{"style":104},[3252],{"type":49,"value":887},{"type":43,"tag":85,"props":3254,"children":3255},{"style":1085},[3256],{"type":49,"value":3257}," CallToolRequest",{"type":43,"tag":85,"props":3259,"children":3260},{"style":104},[3261],{"type":49,"value":185},{"type":43,"tag":85,"props":3263,"children":3264},{"style":92},[3265],{"type":49,"value":3266}," =>",{"type":43,"tag":85,"props":3268,"children":3269},{"style":104},[3270],{"type":49,"value":2993},{"type":43,"tag":85,"props":3272,"children":3273},{"class":87,"line":907},[3274,3279,3284,3289,3294,3298,3303,3307,3312,3317,3321,3326,3331,3336,3341,3346,3350,3355,3359,3364,3368,3373],{"type":43,"tag":85,"props":3275,"children":3276},{"style":92},[3277],{"type":49,"value":3278},"  const",{"type":43,"tag":85,"props":3280,"children":3281},{"style":98},[3282],{"type":49,"value":3283}," args",{"type":43,"tag":85,"props":3285,"children":3286},{"style":104},[3287],{"type":49,"value":3288}," =",{"type":43,"tag":85,"props":3290,"children":3291},{"style":98},[3292],{"type":49,"value":3293}," request",{"type":43,"tag":85,"props":3295,"children":3296},{"style":104},[3297],{"type":49,"value":1049},{"type":43,"tag":85,"props":3299,"children":3300},{"style":98},[3301],{"type":49,"value":3302},"params",{"type":43,"tag":85,"props":3304,"children":3305},{"style":104},[3306],{"type":49,"value":1049},{"type":43,"tag":85,"props":3308,"children":3309},{"style":98},[3310],{"type":49,"value":3311},"arguments",{"type":43,"tag":85,"props":3313,"children":3314},{"style":2985},[3315],{"type":49,"value":3316}," as",{"type":43,"tag":85,"props":3318,"children":3319},{"style":104},[3320],{"type":49,"value":3094},{"type":43,"tag":85,"props":3322,"children":3323},{"style":1907},[3324],{"type":49,"value":3325}," title",{"type":43,"tag":85,"props":3327,"children":3328},{"style":104},[3329],{"type":49,"value":3330},"?:",{"type":43,"tag":85,"props":3332,"children":3333},{"style":1085},[3334],{"type":49,"value":3335}," string",{"type":43,"tag":85,"props":3337,"children":3338},{"style":104},[3339],{"type":49,"value":3340},";",{"type":43,"tag":85,"props":3342,"children":3343},{"style":1907},[3344],{"type":49,"value":3345}," items",{"type":43,"tag":85,"props":3347,"children":3348},{"style":104},[3349],{"type":49,"value":3330},{"type":43,"tag":85,"props":3351,"children":3352},{"style":1085},[3353],{"type":49,"value":3354}," Partial",{"type":43,"tag":85,"props":3356,"children":3357},{"style":104},[3358],{"type":49,"value":2487},{"type":43,"tag":85,"props":3360,"children":3361},{"style":1085},[3362],{"type":49,"value":3363},"Item",{"type":43,"tag":85,"props":3365,"children":3366},{"style":104},[3367],{"type":49,"value":1118},{"type":43,"tag":85,"props":3369,"children":3370},{"style":1907},[3371],{"type":49,"value":3372},"[] ",{"type":43,"tag":85,"props":3374,"children":3375},{"style":104},[3376],{"type":49,"value":3189},{"type":43,"tag":85,"props":3378,"children":3379},{"class":87,"line":916},[3380],{"type":43,"tag":85,"props":3381,"children":3382},{"emptyLinePlaceholder":947},[3383],{"type":49,"value":950},{"type":43,"tag":85,"props":3385,"children":3386},{"class":87,"line":925},[3387],{"type":43,"tag":85,"props":3388,"children":3389},{"style":1313},[3390],{"type":49,"value":3391},"  \u002F\u002F Normalize data - fill in \"Unknown\" for missing fields\n",{"type":43,"tag":85,"props":3393,"children":3394},{"class":87,"line":934},[3395,3399,3403,3407,3411,3415,3419,3424,3428,3433,3437],{"type":43,"tag":85,"props":3396,"children":3397},{"style":92},[3398],{"type":49,"value":3278},{"type":43,"tag":85,"props":3400,"children":3401},{"style":98},[3402],{"type":49,"value":3325},{"type":43,"tag":85,"props":3404,"children":3405},{"style":104},[3406],{"type":49,"value":3288},{"type":43,"tag":85,"props":3408,"children":3409},{"style":98},[3410],{"type":49,"value":3283},{"type":43,"tag":85,"props":3412,"children":3413},{"style":104},[3414],{"type":49,"value":1049},{"type":43,"tag":85,"props":3416,"children":3417},{"style":98},[3418],{"type":49,"value":2390},{"type":43,"tag":85,"props":3420,"children":3421},{"style":104},[3422],{"type":49,"value":3423}," ||",{"type":43,"tag":85,"props":3425,"children":3426},{"style":104},[3427],{"type":49,"value":1157},{"type":43,"tag":85,"props":3429,"children":3430},{"style":1090},[3431],{"type":49,"value":3432},"Default Title",{"type":43,"tag":85,"props":3434,"children":3435},{"style":104},[3436],{"type":49,"value":1172},{"type":43,"tag":85,"props":3438,"children":3439},{"style":104},[3440],{"type":49,"value":3441},";\n",{"type":43,"tag":85,"props":3443,"children":3444},{"class":87,"line":943},[3445,3449,3453,3457,3461,3466,3470,3475,3479,3484,3488,3493,3498,3503,3507,3511],{"type":43,"tag":85,"props":3446,"children":3447},{"style":92},[3448],{"type":49,"value":3278},{"type":43,"tag":85,"props":3450,"children":3451},{"style":98},[3452],{"type":49,"value":3345},{"type":43,"tag":85,"props":3454,"children":3455},{"style":104},[3456],{"type":49,"value":3288},{"type":43,"tag":85,"props":3458,"children":3459},{"style":1907},[3460],{"type":49,"value":177},{"type":43,"tag":85,"props":3462,"children":3463},{"style":98},[3464],{"type":49,"value":3465},"args",{"type":43,"tag":85,"props":3467,"children":3468},{"style":104},[3469],{"type":49,"value":1049},{"type":43,"tag":85,"props":3471,"children":3472},{"style":98},[3473],{"type":49,"value":3474},"items",{"type":43,"tag":85,"props":3476,"children":3477},{"style":104},[3478],{"type":49,"value":3423},{"type":43,"tag":85,"props":3480,"children":3481},{"style":1907},[3482],{"type":49,"value":3483}," [])",{"type":43,"tag":85,"props":3485,"children":3486},{"style":104},[3487],{"type":49,"value":1049},{"type":43,"tag":85,"props":3489,"children":3490},{"style":1149},[3491],{"type":49,"value":3492},"map",{"type":43,"tag":85,"props":3494,"children":3495},{"style":1907},[3496],{"type":49,"value":3497},"(",{"type":43,"tag":85,"props":3499,"children":3500},{"style":3245},[3501],{"type":49,"value":3502},"item",{"type":43,"tag":85,"props":3504,"children":3505},{"style":92},[3506],{"type":49,"value":3266},{"type":43,"tag":85,"props":3508,"children":3509},{"style":1907},[3510],{"type":49,"value":177},{"type":43,"tag":85,"props":3512,"children":3513},{"style":104},[3514],{"type":49,"value":3515},"{\n",{"type":43,"tag":85,"props":3517,"children":3518},{"class":87,"line":953},[3519,3524,3528,3533,3537,3541,3545,3549,3554,3558],{"type":43,"tag":85,"props":3520,"children":3521},{"style":1907},[3522],{"type":49,"value":3523},"    name",{"type":43,"tag":85,"props":3525,"children":3526},{"style":104},[3527],{"type":49,"value":887},{"type":43,"tag":85,"props":3529,"children":3530},{"style":98},[3531],{"type":49,"value":3532}," item",{"type":43,"tag":85,"props":3534,"children":3535},{"style":104},[3536],{"type":49,"value":1049},{"type":43,"tag":85,"props":3538,"children":3539},{"style":98},[3540],{"type":49,"value":2356},{"type":43,"tag":85,"props":3542,"children":3543},{"style":104},[3544],{"type":49,"value":3423},{"type":43,"tag":85,"props":3546,"children":3547},{"style":104},[3548],{"type":49,"value":1157},{"type":43,"tag":85,"props":3550,"children":3551},{"style":1090},[3552],{"type":49,"value":3553},"Unknown",{"type":43,"tag":85,"props":3555,"children":3556},{"style":104},[3557],{"type":49,"value":1172},{"type":43,"tag":85,"props":3559,"children":3560},{"style":104},[3561],{"type":49,"value":3077},{"type":43,"tag":85,"props":3563,"children":3564},{"class":87,"line":962},[3565,3570,3574,3578,3582,3587,3591,3595,3599,3603],{"type":43,"tag":85,"props":3566,"children":3567},{"style":1907},[3568],{"type":49,"value":3569},"    value",{"type":43,"tag":85,"props":3571,"children":3572},{"style":104},[3573],{"type":49,"value":887},{"type":43,"tag":85,"props":3575,"children":3576},{"style":98},[3577],{"type":49,"value":3532},{"type":43,"tag":85,"props":3579,"children":3580},{"style":104},[3581],{"type":49,"value":1049},{"type":43,"tag":85,"props":3583,"children":3584},{"style":98},[3585],{"type":49,"value":3586},"value",{"type":43,"tag":85,"props":3588,"children":3589},{"style":104},[3590],{"type":49,"value":3423},{"type":43,"tag":85,"props":3592,"children":3593},{"style":104},[3594],{"type":49,"value":1157},{"type":43,"tag":85,"props":3596,"children":3597},{"style":1090},[3598],{"type":49,"value":3553},{"type":43,"tag":85,"props":3600,"children":3601},{"style":104},[3602],{"type":49,"value":1172},{"type":43,"tag":85,"props":3604,"children":3605},{"style":104},[3606],{"type":49,"value":3077},{"type":43,"tag":85,"props":3608,"children":3609},{"class":87,"line":971},[3610,3615,3620],{"type":43,"tag":85,"props":3611,"children":3612},{"style":104},[3613],{"type":49,"value":3614},"  }",{"type":43,"tag":85,"props":3616,"children":3617},{"style":1907},[3618],{"type":49,"value":3619},"))",{"type":43,"tag":85,"props":3621,"children":3622},{"style":104},[3623],{"type":49,"value":3441},{"type":43,"tag":85,"props":3625,"children":3626},{"class":87,"line":980},[3627],{"type":43,"tag":85,"props":3628,"children":3629},{"emptyLinePlaceholder":947},[3630],{"type":49,"value":950},{"type":43,"tag":85,"props":3632,"children":3633},{"class":87,"line":988},[3634],{"type":43,"tag":85,"props":3635,"children":3636},{"style":1313},[3637],{"type":49,"value":3638},"  \u002F\u002F Build structuredContent for widget\n",{"type":43,"tag":85,"props":3640,"children":3641},{"class":87,"line":997},[3642,3646,3651,3655,3659,3663,3667,3671],{"type":43,"tag":85,"props":3643,"children":3644},{"style":92},[3645],{"type":49,"value":3278},{"type":43,"tag":85,"props":3647,"children":3648},{"style":98},[3649],{"type":49,"value":3650}," structuredContent",{"type":43,"tag":85,"props":3652,"children":3653},{"style":104},[3654],{"type":49,"value":3288},{"type":43,"tag":85,"props":3656,"children":3657},{"style":104},[3658],{"type":49,"value":3094},{"type":43,"tag":85,"props":3660,"children":3661},{"style":98},[3662],{"type":49,"value":3325},{"type":43,"tag":85,"props":3664,"children":3665},{"style":104},[3666],{"type":49,"value":3040},{"type":43,"tag":85,"props":3668,"children":3669},{"style":98},[3670],{"type":49,"value":3345},{"type":43,"tag":85,"props":3672,"children":3673},{"style":104},[3674],{"type":49,"value":3675}," };\n",{"type":43,"tag":85,"props":3677,"children":3678},{"class":87,"line":1005},[3679],{"type":43,"tag":85,"props":3680,"children":3681},{"style":1313},[3682],{"type":49,"value":3683},"  \u002F\u002F ...\n",{"type":43,"tag":85,"props":3685,"children":3686},{"class":87,"line":1014},[3687,3692,3696],{"type":43,"tag":85,"props":3688,"children":3689},{"style":104},[3690],{"type":49,"value":3691},"}",{"type":43,"tag":85,"props":3693,"children":3694},{"style":98},[3695],{"type":49,"value":185},{"type":43,"tag":85,"props":3697,"children":3698},{"style":104},[3699],{"type":49,"value":3441},{"type":43,"tag":345,"props":3701,"children":3703},{"id":3702},"widget-pattern",[3704],{"type":49,"value":3705},"Widget Pattern",{"type":43,"tag":59,"props":3707,"children":3708},{},[3709,3710,3714],{"type":49,"value":687},{"type":43,"tag":573,"props":3711,"children":3712},{"href":733},[3713],{"type":49,"value":733},{"type":49,"value":3715}," for complete examples.",{"type":43,"tag":59,"props":3717,"children":3718},{},[3719],{"type":49,"value":2914},{"type":43,"tag":313,"props":3721,"children":3722},{},[3723,3734,3756,3790,3802,3815],{"type":43,"tag":317,"props":3724,"children":3725},{},[3726,3728,3733],{"type":49,"value":3727},"Use React + Fluent UI components (",{"type":43,"tag":65,"props":3729,"children":3731},{"className":3730},[],[3732],{"type":49,"value":758},{"type":49,"value":185},{"type":43,"tag":317,"props":3735,"children":3736},{},[3737,3739,3744,3745,3750,3751],{"type":49,"value":3738},"Ensure widget package dependencies include ",{"type":43,"tag":65,"props":3740,"children":3742},{"className":3741},[],[3743],{"type":49,"value":758},{"type":49,"value":855},{"type":43,"tag":65,"props":3746,"children":3748},{"className":3747},[],[3749],{"type":49,"value":767},{"type":49,"value":863},{"type":43,"tag":65,"props":3752,"children":3754},{"className":3753},[],[3755],{"type":49,"value":776},{"type":43,"tag":317,"props":3757,"children":3758},{},[3759,3761,3767,3768,3774,3776,3782,3784],{"type":49,"value":3760},"Theme with ",{"type":43,"tag":65,"props":3762,"children":3764},{"className":3763},[],[3765],{"type":49,"value":3766},"FluentProvider",{"type":49,"value":177},{"type":43,"tag":65,"props":3769,"children":3771},{"className":3770},[],[3772],{"type":49,"value":3773},"webLightTheme",{"type":49,"value":3775},"\u002F",{"type":43,"tag":65,"props":3777,"children":3779},{"className":3778},[],[3780],{"type":49,"value":3781},"webDarkTheme",{"type":49,"value":3783},") and Fluent ",{"type":43,"tag":65,"props":3785,"children":3787},{"className":3786},[],[3788],{"type":49,"value":3789},"tokens",{"type":43,"tag":317,"props":3791,"children":3792},{},[3793,3795,3801],{"type":49,"value":3794},"Access data through shared hooks (e.g., ",{"type":43,"tag":65,"props":3796,"children":3798},{"className":3797},[],[3799],{"type":49,"value":3800},"useOpenAiGlobal(\"toolOutput\")",{"type":49,"value":185},{"type":43,"tag":317,"props":3803,"children":3804},{},[3805,3807,3813],{"type":49,"value":3806},"Debug fallback: embedded mock data when ",{"type":43,"tag":65,"props":3808,"children":3810},{"className":3809},[],[3811],{"type":49,"value":3812},"window.openai",{"type":49,"value":3814}," unavailable",{"type":43,"tag":317,"props":3816,"children":3817},{},[3818],{"type":49,"value":3819},"Handle \"Unknown\" values gracefully (e.g., hide action buttons)",{"type":43,"tag":345,"props":3821,"children":3823},{"id":3822},"plugin-schema",[3824],{"type":49,"value":3825},"Plugin Schema",{"type":43,"tag":59,"props":3827,"children":3828},{},[3829,3830,3835],{"type":49,"value":687},{"type":43,"tag":573,"props":3831,"children":3833},{"href":3832},"references\u002Fplugin-schema.md",[3834],{"type":49,"value":3832},{"type":49,"value":3836}," for mcpPlugin.json format.",{"type":43,"tag":59,"props":3838,"children":3839},{},[3840],{"type":49,"value":2914},{"type":43,"tag":313,"props":3842,"children":3843},{},[3844,3863,3874,3884],{"type":43,"tag":317,"props":3845,"children":3846},{},[3847,3849,3855,3856,3861],{"type":49,"value":3848},"Schema ",{"type":43,"tag":65,"props":3850,"children":3852},{"className":3851},[],[3853],{"type":49,"value":3854},"v2.4",{"type":49,"value":1065},{"type":43,"tag":65,"props":3857,"children":3859},{"className":3858},[],[3860],{"type":49,"value":2420},{"type":49,"value":3862}," runtime",{"type":43,"tag":317,"props":3864,"children":3865},{},[3866,3872],{"type":43,"tag":65,"props":3867,"children":3869},{"className":3868},[],[3870],{"type":49,"value":3871},"run_for_functions",{"type":49,"value":3873}," array matching tool names",{"type":43,"tag":317,"props":3875,"children":3876},{},[3877,3882],{"type":43,"tag":65,"props":3878,"children":3880},{"className":3879},[],[3881],{"type":49,"value":1773},{"type":49,"value":3883}," in tool definitions for widget binding",{"type":43,"tag":317,"props":3885,"children":3886},{},[3887,3892],{"type":43,"tag":65,"props":3888,"children":3890},{"className":3889},[],[3891],{"type":49,"value":2370},{"type":49,"value":3893}," - make properties optional for flexibility, describe defaults in descriptions",{"type":43,"tag":52,"props":3895,"children":3897},{"id":3896},"devtunnels-setup",[3898],{"type":49,"value":3899},"DevTunnels Setup",{"type":43,"tag":407,"props":3901,"children":3902},{},[3903],{"type":43,"tag":59,"props":3904,"children":3905},{},[3906,3911],{"type":43,"tag":135,"props":3907,"children":3908},{},[3909],{"type":49,"value":3910},"Local testing only.",{"type":49,"value":3912}," DevTunnels are for development and testing on your machine. Before sharing the agent more broadly, deploy both the MCP server and widget assets to a hosted environment (e.g., Azure App Service, Azure Static Web Apps, or another hosting provider) and update the agent manifest URLs accordingly.",{"type":43,"tag":59,"props":3914,"children":3915},{},[3916,3918,3923,3925,3930],{"type":49,"value":3917},"DevTunnels expose your localhost MCP server to M365 Copilot using ",{"type":43,"tag":135,"props":3919,"children":3920},{},[3921],{"type":49,"value":3922},"named tunnels",{"type":49,"value":3924}," for stable URLs. See ",{"type":43,"tag":573,"props":3926,"children":3928},{"href":3927},"references\u002Fdevtunnels.md",[3929],{"type":49,"value":3927},{"type":49,"value":3931}," for setup scripts, command reference, and troubleshooting.",{"type":43,"tag":59,"props":3933,"children":3934},{},[3935,3937,3943,3945,3951],{"type":49,"value":3936},"The setup script (",{"type":43,"tag":65,"props":3938,"children":3940},{"className":3939},[],[3941],{"type":49,"value":3942},"npm run tunnel",{"type":49,"value":3944}," \u002F ",{"type":43,"tag":65,"props":3946,"children":3948},{"className":3947},[],[3949],{"type":49,"value":3950},"npm run tunnel:win",{"type":49,"value":3952},"):",{"type":43,"tag":357,"props":3954,"children":3955},{},[3956,3961,3966,3992],{"type":43,"tag":317,"props":3957,"children":3958},{},[3959],{"type":49,"value":3960},"Creates a named tunnel on first run (or reuses the existing one)",{"type":43,"tag":317,"props":3962,"children":3963},{},[3964],{"type":49,"value":3965},"Starts hosting the tunnel on the configured port",{"type":43,"tag":317,"props":3967,"children":3968},{},[3969,3971,3977,3978,3983,3984,3990],{"type":49,"value":3970},"Updates ",{"type":43,"tag":65,"props":3972,"children":3974},{"className":3973},[],[3975],{"type":49,"value":3976},"env\u002F.env.local",{"type":49,"value":1065},{"type":43,"tag":65,"props":3979,"children":3981},{"className":3980},[],[3982],{"type":49,"value":2180},{"type":49,"value":1783},{"type":43,"tag":65,"props":3985,"children":3987},{"className":3986},[],[3988],{"type":49,"value":3989},"MCP_SERVER_DOMAIN",{"type":49,"value":3991}," (first run only)",{"type":43,"tag":317,"props":3993,"children":3994},{},[3995],{"type":49,"value":3996},"Continues hosting the tunnel",{"type":43,"tag":345,"props":3998,"children":4000},{"id":3999},"quick-start",[4001],{"type":49,"value":4002},"Quick Start",{"type":43,"tag":59,"props":4004,"children":4005},{},[4006],{"type":43,"tag":135,"props":4007,"children":4008},{},[4009],{"type":49,"value":4010},"Terminal 1 - Start MCP Server:",{"type":43,"tag":74,"props":4012,"children":4014},{"className":76,"code":4013,"language":78,"meta":79,"style":79},"cd mcp-server\nnpm install\nnpm run dev\n",[4015],{"type":43,"tag":65,"props":4016,"children":4017},{"__ignoreMap":79},[4018,4031,4044],{"type":43,"tag":85,"props":4019,"children":4020},{"class":87,"line":88},[4021,4026],{"type":43,"tag":85,"props":4022,"children":4023},{"style":1149},[4024],{"type":49,"value":4025},"cd",{"type":43,"tag":85,"props":4027,"children":4028},{"style":1090},[4029],{"type":49,"value":4030}," mcp-server\n",{"type":43,"tag":85,"props":4032,"children":4033},{"class":87,"line":907},[4034,4039],{"type":43,"tag":85,"props":4035,"children":4036},{"style":1085},[4037],{"type":49,"value":4038},"npm",{"type":43,"tag":85,"props":4040,"children":4041},{"style":1090},[4042],{"type":49,"value":4043}," install\n",{"type":43,"tag":85,"props":4045,"children":4046},{"class":87,"line":916},[4047,4051,4056],{"type":43,"tag":85,"props":4048,"children":4049},{"style":1085},[4050],{"type":49,"value":4038},{"type":43,"tag":85,"props":4052,"children":4053},{"style":1090},[4054],{"type":49,"value":4055}," run",{"type":43,"tag":85,"props":4057,"children":4058},{"style":1090},[4059],{"type":49,"value":4060}," dev\n",{"type":43,"tag":59,"props":4062,"children":4063},{},[4064],{"type":43,"tag":135,"props":4065,"children":4066},{},[4067],{"type":49,"value":4068},"Terminal 2 - Start DevTunnel:",{"type":43,"tag":74,"props":4070,"children":4072},{"className":76,"code":4071,"language":78,"meta":79,"style":79},"npm run tunnel\n# Or on Windows:\nnpm run tunnel:win\n",[4073],{"type":43,"tag":65,"props":4074,"children":4075},{"__ignoreMap":79},[4076,4092,4100],{"type":43,"tag":85,"props":4077,"children":4078},{"class":87,"line":88},[4079,4083,4087],{"type":43,"tag":85,"props":4080,"children":4081},{"style":1085},[4082],{"type":49,"value":4038},{"type":43,"tag":85,"props":4084,"children":4085},{"style":1090},[4086],{"type":49,"value":4055},{"type":43,"tag":85,"props":4088,"children":4089},{"style":1090},[4090],{"type":49,"value":4091}," tunnel\n",{"type":43,"tag":85,"props":4093,"children":4094},{"class":87,"line":907},[4095],{"type":43,"tag":85,"props":4096,"children":4097},{"style":1313},[4098],{"type":49,"value":4099},"# Or on Windows:\n",{"type":43,"tag":85,"props":4101,"children":4102},{"class":87,"line":916},[4103,4107,4111],{"type":43,"tag":85,"props":4104,"children":4105},{"style":1085},[4106],{"type":49,"value":4038},{"type":43,"tag":85,"props":4108,"children":4109},{"style":1090},[4110],{"type":49,"value":4055},{"type":43,"tag":85,"props":4112,"children":4113},{"style":1090},[4114],{"type":49,"value":4115}," tunnel:win\n",{"type":43,"tag":59,"props":4117,"children":4118},{},[4119],{"type":49,"value":4120},"On first run, provision the agent once the tunnel is up (see AGENT PROVISIONING rule). On subsequent runs the tunnel URL is stable — no re-provisioning needed unless the agent manifest changes.",{"type":43,"tag":52,"props":4122,"children":4124},{"id":4123},"development-workflow",[4125],{"type":49,"value":4126},"Development Workflow",{"type":43,"tag":357,"props":4128,"children":4129},{},[4130,4175,4207],{"type":43,"tag":317,"props":4131,"children":4132},{},[4133,4137,4139],{"type":43,"tag":135,"props":4134,"children":4135},{},[4136],{"type":49,"value":2279},{"type":49,"value":4138}," (dev mode with hot reload):",{"type":43,"tag":313,"props":4140,"children":4141},{},[4142,4153,4164],{"type":43,"tag":317,"props":4143,"children":4144},{},[4145,4147],{"type":49,"value":4146},"TypeScript: ",{"type":43,"tag":65,"props":4148,"children":4150},{"className":4149},[],[4151],{"type":49,"value":4152},"cd mcp-server && npm install && npm run dev",{"type":43,"tag":317,"props":4154,"children":4155},{},[4156,4158],{"type":49,"value":4157},"Python: ",{"type":43,"tag":65,"props":4159,"children":4161},{"className":4160},[],[4162],{"type":49,"value":4163},"cd mcp-server && pip install -r requirements.txt && python server.py",{"type":43,"tag":317,"props":4165,"children":4166},{},[4167,4169],{"type":49,"value":4168},"C#: ",{"type":43,"tag":65,"props":4170,"children":4172},{"className":4171},[],[4173],{"type":49,"value":4174},"cd mcp-server && dotnet run",{"type":43,"tag":317,"props":4176,"children":4177},{},[4178,4183,4185],{"type":43,"tag":135,"props":4179,"children":4180},{},[4181],{"type":49,"value":4182},"Start the devtunnel",{"type":49,"value":4184}," (creates named tunnel on first run, reuses on subsequent runs):",{"type":43,"tag":74,"props":4186,"children":4188},{"className":76,"code":4187,"language":78,"meta":79,"style":79},"npm run tunnel\n",[4189],{"type":43,"tag":65,"props":4190,"children":4191},{"__ignoreMap":79},[4192],{"type":43,"tag":85,"props":4193,"children":4194},{"class":87,"line":88},[4195,4199,4203],{"type":43,"tag":85,"props":4196,"children":4197},{"style":1085},[4198],{"type":49,"value":4038},{"type":43,"tag":85,"props":4200,"children":4201},{"style":1090},[4202],{"type":49,"value":4055},{"type":43,"tag":85,"props":4204,"children":4205},{"style":1090},[4206],{"type":49,"value":4091},{"type":43,"tag":317,"props":4208,"children":4209},{},[4210,4215,4217,4223],{"type":43,"tag":135,"props":4211,"children":4212},{},[4213],{"type":49,"value":4214},"Provision + test",{"type":49,"value":4216}," — see AGENT PROVISIONING rule for when this is needed; bump ",{"type":43,"tag":65,"props":4218,"children":4220},{"className":4219},[],[4221],{"type":49,"value":4222},"version",{"type":49,"value":4224}," in manifest.json if Copilot doesn't reflect changes",{"type":43,"tag":52,"props":4226,"children":4228},{"id":4227},"best-practices",[4229],{"type":49,"value":4230},"Best Practices",{"type":43,"tag":59,"props":4232,"children":4233},{},[4234,4235,4239],{"type":49,"value":687},{"type":43,"tag":573,"props":4236,"children":4237},{"href":742},[4238],{"type":49,"value":742},{"type":49,"value":4240}," for detailed guidance.",{"type":43,"tag":59,"props":4242,"children":4243},{},[4244],{"type":49,"value":4245},"Key points:",{"type":43,"tag":357,"props":4247,"children":4248},{},[4249,4259,4269,4293,4303,4313,4323],{"type":43,"tag":317,"props":4250,"children":4251},{},[4252,4257],{"type":43,"tag":135,"props":4253,"children":4254},{},[4255],{"type":49,"value":4256},"Rendering tools",{"type":49,"value":4258},": Accept data as input, don't fetch internally",{"type":43,"tag":317,"props":4260,"children":4261},{},[4262,4267],{"type":43,"tag":135,"props":4263,"children":4264},{},[4265],{"type":49,"value":4266},"Instructions",{"type":49,"value":4268},": Tell agent to use capabilities FIRST, then pass data to MCP tools",{"type":43,"tag":317,"props":4270,"children":4271},{},[4272,4277,4279,4284,4286,4291],{"type":43,"tag":135,"props":4273,"children":4274},{},[4275],{"type":49,"value":4276},"Themes",{"type":49,"value":4278},": Use ",{"type":43,"tag":65,"props":4280,"children":4282},{"className":4281},[],[4283],{"type":49,"value":3766},{"type":49,"value":4285}," + Fluent ",{"type":43,"tag":65,"props":4287,"children":4289},{"className":4288},[],[4290],{"type":49,"value":3789},{"type":49,"value":4292}," for dark\u002Flight support",{"type":43,"tag":317,"props":4294,"children":4295},{},[4296,4301],{"type":43,"tag":135,"props":4297,"children":4298},{},[4299],{"type":49,"value":4300},"Debug mode",{"type":49,"value":4302},": Include fallback data for local widget testing",{"type":43,"tag":317,"props":4304,"children":4305},{},[4306,4311],{"type":43,"tag":135,"props":4307,"children":4308},{},[4309],{"type":49,"value":4310},"Partial data",{"type":49,"value":4312},": Handle missing fields with \"Unknown\" defaults",{"type":43,"tag":317,"props":4314,"children":4315},{},[4316,4321],{"type":43,"tag":135,"props":4317,"children":4318},{},[4319],{"type":49,"value":4320},"Action buttons",{"type":49,"value":4322},": Hide email\u002Fchat buttons when data is \"Unknown\"",{"type":43,"tag":317,"props":4324,"children":4325},{},[4326,4331],{"type":43,"tag":135,"props":4327,"children":4328},{},[4329],{"type":49,"value":4330},"Version bumping",{"type":49,"value":4332},": Bump manifest version when changes aren't reflected in Copilot",{"type":43,"tag":52,"props":4334,"children":4336},{"id":4335},"next-step-add-sso-optional",[4337],{"type":49,"value":4338},"Next Step — Add SSO (optional)",{"type":43,"tag":59,"props":4340,"children":4341},{},[4342,4344,4349],{"type":49,"value":4343},"Once the ui-widget agent is scaffolded, running, and provisioned, you can add ",{"type":43,"tag":135,"props":4345,"children":4346},{},[4347],{"type":49,"value":4348},"Entra SSO",{"type":49,"value":4350}," — so your MCP tools receive the signed-in user's verified identity — with the companion skill in this same plugin:",{"type":43,"tag":59,"props":4352,"children":4353},{},[4354,4356,4364,4366,4371,4373,4379],{"type":49,"value":4355},"▶ ",{"type":43,"tag":135,"props":4357,"children":4358},{},[4359],{"type":43,"tag":65,"props":4360,"children":4362},{"className":4361},[],[4363],{"type":49,"value":835},{"type":49,"value":4365}," — registers an Entra app, reuses your existing dev tunnel, injects a minimal JWKS token guard into your MCP server, wires ",{"type":43,"tag":65,"props":4367,"children":4369},{"className":4368},[],[4370],{"type":49,"value":2216},{"type":49,"value":4372}," auth, and sideloads. SSO only, no OBO. (Run ",{"type":43,"tag":65,"props":4374,"children":4376},{"className":4375},[],[4377],{"type":49,"value":4378},"\u002Fsetup-sso-ui-widget",{"type":49,"value":4380}," from the project root.)",{"type":43,"tag":59,"props":4382,"children":4383},{},[4384,4389],{"type":43,"tag":135,"props":4385,"children":4386},{},[4387],{"type":49,"value":4388},"Tell the user",{"type":49,"value":4390}," (after the build\u002Fprovision completes):",{"type":43,"tag":407,"props":4392,"children":4393},{},[4394],{"type":43,"tag":59,"props":4395,"children":4396},{},[4397,4402,4404,4409,4411,4419],{"type":43,"tag":135,"props":4398,"children":4399},{},[4400],{"type":49,"value":4401},"Your ui-widget agent is ready.",{"type":49,"value":4403}," 🎉 Want me to wire up ",{"type":43,"tag":135,"props":4405,"children":4406},{},[4407],{"type":49,"value":4408},"SSO",{"type":49,"value":4410}," next, so your tools get the signed-in user's identity? I can run the ",{"type":43,"tag":135,"props":4412,"children":4413},{},[4414],{"type":43,"tag":65,"props":4415,"children":4417},{"className":4416},[],[4418],{"type":49,"value":835},{"type":49,"value":4420}," skill — just say the word.",{"type":43,"tag":4422,"props":4423,"children":4424},"style",{},[4425],{"type":49,"value":4426},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":4428,"total":4618},[4429,4451,4470,4491,4506,4523,4534,4545,4560,4575,4594,4606],{"slug":4430,"name":4430,"fn":4431,"description":4432,"org":4433,"tags":4434,"stars":4448,"repoUrl":4449,"updatedAt":4450},"rushstack-best-practices","manage Rush monorepos with best practices","Provides best practices and guidance for working with Rush monorepos. Use when the user is working in a Rush-based repository, asks about Rush commands (install, update, build, rebuild), needs help with project selection, dependency management, build caching, subspace configuration, or troubleshooting Rush-specific issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4435,4438,4441,4442,4445],{"name":4436,"slug":4437,"type":15},"Engineering","engineering",{"name":4439,"slug":4440,"type":15},"Local Development","local-development",{"name":9,"slug":8,"type":15},{"name":4443,"slug":4444,"type":15},"Project Management","project-management",{"name":4446,"slug":4447,"type":15},"Rush","rush",6484,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frushstack","2026-04-06T18:34:44.965032",{"slug":4452,"name":4452,"fn":4453,"description":4454,"org":4455,"tags":4456,"stars":4467,"repoUrl":4468,"updatedAt":4469},"azure-ai-agents-persistent-dotnet","build AI agents with Azure .NET SDK","Azure AI Agents Persistent SDK for .NET. Low-level SDK for creating and managing AI agents with threads, messages, runs, and tools. Use for agent CRUD, conversation threads, streaming responses, function calling, file search, and code interpreter. Triggers: \"PersistentAgentsClient\", \"persistent agents\", \"agent threads\", \"agent runs\", \"streaming agents\", \"function calling agents .NET\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4457,4460,4461,4464],{"name":4458,"slug":4459,"type":15},".NET","net",{"name":21,"slug":22,"type":15},{"name":4462,"slug":4463,"type":15},"Azure","azure",{"name":4465,"slug":4466,"type":15},"LLM","llm",2804,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills","2026-07-03T16:32:10.297433",{"slug":4471,"name":4471,"fn":4472,"description":4473,"org":4474,"tags":4475,"stars":4467,"repoUrl":4468,"updatedAt":4490},"azure-ai-anomalydetector-java","build anomaly detection applications with Java","Build anomaly detection applications with Azure AI Anomaly Detector SDK for Java. Use when implementing univariate\u002Fmultivariate anomaly detection, time-series analysis, or AI-powered monitoring.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4476,4479,4480,4483,4486,4487],{"name":4477,"slug":4478,"type":15},"Analytics","analytics",{"name":4462,"slug":4463,"type":15},{"name":4481,"slug":4482,"type":15},"Data Analysis","data-analysis",{"name":4484,"slug":4485,"type":15},"Java","java",{"name":9,"slug":8,"type":15},{"name":4488,"slug":4489,"type":15},"Monitoring","monitoring","2026-05-13T06:14:16.261754",{"slug":4492,"name":4492,"fn":4493,"description":4494,"org":4495,"tags":4496,"stars":4467,"repoUrl":4468,"updatedAt":4505},"azure-ai-contentsafety-java","build content moderation applications with Azure AI","Build content moderation applications with Azure AI Content Safety SDK for Java. Use when implementing text\u002Fimage analysis, blocklist management, or harm detection for hate, violence, sexual content, and self-harm.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4497,4500,4501,4502],{"name":4498,"slug":4499,"type":15},"AI Infrastructure","ai-infrastructure",{"name":4462,"slug":4463,"type":15},{"name":4484,"slug":4485,"type":15},{"name":4503,"slug":4504,"type":15},"Security","security","2026-07-07T06:53:31.293235",{"slug":4507,"name":4507,"fn":4508,"description":4509,"org":4510,"tags":4511,"stars":4467,"repoUrl":4468,"updatedAt":4522},"azure-ai-contentsafety-py","detect harmful content with Azure AI Content Safety","Azure AI Content Safety SDK for Python. Use for detecting harmful content in text and images with multi-severity classification.\nTriggers: \"azure-ai-contentsafety\", \"ContentSafetyClient\", \"content moderation\", \"harmful content\", \"text analysis\", \"image analysis\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4512,4513,4516,4517,4518,4521],{"name":4462,"slug":4463,"type":15},{"name":4514,"slug":4515,"type":15},"Compliance","compliance",{"name":4465,"slug":4466,"type":15},{"name":9,"slug":8,"type":15},{"name":4519,"slug":4520,"type":15},"Python","python",{"name":4503,"slug":4504,"type":15},"2026-07-18T05:14:23.017504",{"slug":4524,"name":4524,"fn":4525,"description":4526,"org":4527,"tags":4528,"stars":4467,"repoUrl":4468,"updatedAt":4533},"azure-ai-language-conversations-py","implement conversational language understanding with Python","Implement Conversational Language Understanding (CLU) using the azure-ai-language-conversations Python SDK. Use when working with ConversationAnalysisClient to analyze conversation intent and entities, building NLP features, or integrating language understanding into applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4529,4530,4531,4532],{"name":4477,"slug":4478,"type":15},{"name":4462,"slug":4463,"type":15},{"name":4465,"slug":4466,"type":15},{"name":4519,"slug":4520,"type":15},"2026-07-31T05:54:29.068751",{"slug":4535,"name":4535,"fn":4536,"description":4537,"org":4538,"tags":4539,"stars":4467,"repoUrl":4468,"updatedAt":4544},"azure-ai-translation-text-py","translate text using Azure AI services","Azure AI Text Translation SDK for real-time text translation, transliteration, language detection, and dictionary lookup. Use for translating text content in applications.\nTriggers: \"text translation\", \"translator\", \"translate text\", \"transliterate\", \"TextTranslationClient\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4540,4541,4542,4543],{"name":24,"slug":25,"type":15},{"name":4462,"slug":4463,"type":15},{"name":9,"slug":8,"type":15},{"name":4519,"slug":4520,"type":15},"2026-07-18T05:14:16.988376",{"slug":4546,"name":4546,"fn":4547,"description":4548,"org":4549,"tags":4550,"stars":4467,"repoUrl":4468,"updatedAt":4559},"azure-ai-vision-imageanalysis-py","analyze images with Azure AI Vision","Azure AI Vision Image Analysis SDK for captions, tags, objects, OCR, people detection, and smart cropping. Use for computer vision and image understanding tasks.\nTriggers: \"image analysis\", \"computer vision\", \"OCR\", \"object detection\", \"ImageAnalysisClient\", \"image caption\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4551,4552,4555,4558],{"name":4462,"slug":4463,"type":15},{"name":4553,"slug":4554,"type":15},"Computer Vision","computer-vision",{"name":4556,"slug":4557,"type":15},"Images","images",{"name":4519,"slug":4520,"type":15},"2026-07-18T05:14:18.007737",{"slug":4561,"name":4561,"fn":4562,"description":4563,"org":4564,"tags":4565,"stars":4467,"repoUrl":4468,"updatedAt":4574},"azure-appconfiguration-java","manage configuration with Azure App Configuration","Azure App Configuration SDK for Java. Centralized application configuration management with key-value settings, feature flags, and snapshots.\nTriggers: \"ConfigurationClient java\", \"app configuration java\", \"feature flag java\", \"configuration setting java\", \"azure config java\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4566,4567,4570,4573],{"name":4462,"slug":4463,"type":15},{"name":4568,"slug":4569,"type":15},"Configuration","configuration",{"name":4571,"slug":4572,"type":15},"Feature Flags","feature-flags",{"name":4484,"slug":4485,"type":15},"2026-07-03T16:32:01.278468",{"slug":4576,"name":4576,"fn":4577,"description":4578,"org":4579,"tags":4580,"stars":4467,"repoUrl":4468,"updatedAt":4593},"azure-cosmos-rust","build applications with Azure Cosmos DB","Azure Cosmos DB library for Rust (NoSQL API). Document CRUD, containers, and globally distributed data.\nTriggers: \"cosmos db rust\", \"CosmosClient rust\", \"document crud rust\", \"NoSQL rust\", \"partition key rust\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4581,4584,4587,4590],{"name":4582,"slug":4583,"type":15},"Cosmos DB","cosmos-db",{"name":4585,"slug":4586,"type":15},"Database","database",{"name":4588,"slug":4589,"type":15},"NoSQL","nosql",{"name":4591,"slug":4592,"type":15},"Rust","rust","2026-07-31T05:54:27.021432",{"slug":4595,"name":4595,"fn":4577,"description":4596,"org":4597,"tags":4598,"stars":4467,"repoUrl":4468,"updatedAt":4605},"azure-cosmos-ts","Azure Cosmos DB JavaScript\u002FTypeScript SDK (@azure\u002Fcosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: \"Cosmos DB\", \"@azure\u002Fcosmos\", \"CosmosClient\", \"document CRUD\", \"NoSQL queries\", \"bulk operations\", \"partition key\", \"container.items\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4599,4600,4601,4602,4603],{"name":4582,"slug":4583,"type":15},{"name":4585,"slug":4586,"type":15},{"name":9,"slug":8,"type":15},{"name":4588,"slug":4589,"type":15},{"name":4604,"slug":2975,"type":15},"TypeScript","2026-07-03T16:31:19.368382",{"slug":4607,"name":4607,"fn":4608,"description":4609,"org":4610,"tags":4611,"stars":4467,"repoUrl":4468,"updatedAt":4617},"azure-data-tables-java","build table storage applications with Java","Build table storage applications with Azure Tables SDK for Java. Use when working with Azure Table Storage or Cosmos DB Table API for NoSQL key-value data, schemaless storage, or structured data at scale.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4612,4613,4614,4615,4616],{"name":4462,"slug":4463,"type":15},{"name":4582,"slug":4583,"type":15},{"name":4585,"slug":4586,"type":15},{"name":4484,"slug":4485,"type":15},{"name":4588,"slug":4589,"type":15},"2026-05-13T06:14:17.582229",267,{"items":4620,"total":1014},[4621,4641,4661,4672,4688,4703,4716],{"slug":4622,"name":4622,"fn":4623,"description":4624,"org":4625,"tags":4626,"stars":26,"repoUrl":27,"updatedAt":4640},"action-item-extractor","extract action items from meetings","Extract action items with owners, deadlines, and priorities from meeting content",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4627,4630,4631,4634,4637],{"name":4628,"slug":4629,"type":15},"Meetings","meetings",{"name":9,"slug":8,"type":15},{"name":4632,"slug":4633,"type":15},"Productivity","productivity",{"name":4635,"slug":4636,"type":15},"Summarization","summarization",{"name":4638,"slug":4639,"type":15},"Task Management","task-management","2026-04-06T18:35:30.007473",{"slug":4642,"name":4642,"fn":4643,"description":4644,"org":4645,"tags":4646,"stars":26,"repoUrl":27,"updatedAt":4660},"channel-audit","audit and clean up Microsoft Teams channels","Audit Teams channels across your teams — identify inactive channels, low‑engagement conversations, channels with no recent posts, and recommend cleanup actions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4647,4650,4653,4654,4657],{"name":4648,"slug":4649,"type":15},"Audit","audit",{"name":4651,"slug":4652,"type":15},"Messaging","messaging",{"name":9,"slug":8,"type":15},{"name":4655,"slug":4656,"type":15},"Microsoft Teams","microsoft-teams",{"name":4658,"slug":4659,"type":15},"Operations","operations","2026-04-06T18:35:22.45187",{"slug":4662,"name":4662,"fn":4663,"description":4664,"org":4665,"tags":4666,"stars":26,"repoUrl":27,"updatedAt":4671},"channel-digest","generate digests for Microsoft Teams channels","Summarize activity across multiple Teams channels into a single consolidated digest — key discussions, decisions, mentions, and action items.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4667,4668,4669,4670],{"name":4651,"slug":4652,"type":15},{"name":9,"slug":8,"type":15},{"name":4655,"slug":4656,"type":15},{"name":4635,"slug":4636,"type":15},"2026-04-06T18:35:25.021901",{"slug":4673,"name":4673,"fn":4674,"description":4675,"org":4676,"tags":4677,"stars":26,"repoUrl":27,"updatedAt":4687},"daily-outlook-triage","triage Outlook inbox and calendar daily","Get a quick summary of your day by pulling your inbox emails and calendar meetings. Helps you triage and prioritize your workday.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4678,4679,4682,4685,4686],{"name":9,"slug":8,"type":15},{"name":4680,"slug":4681,"type":15},"Outlook Calendar","outlook-calendar",{"name":4683,"slug":4684,"type":15},"Outlook Email","outlook-email",{"name":4632,"slug":4633,"type":15},{"name":4635,"slug":4636,"type":15},"2026-04-06T18:35:28.767999",{"slug":609,"name":609,"fn":4689,"description":4690,"org":4691,"tags":4692,"stars":26,"repoUrl":27,"updatedAt":4702},"build and deploy declarative agents for M365","Create, build, deploy, and localize declarative agents for M365 Copilot and Teams. USE THIS SKILL for ANY task involving a declarative agent — including localization, scaffolding, editing manifests, adding capabilities, and deploying. Localization requires tokenized manifests and language files that only this skill knows how to produce. Triggers: \"create agent\", \"create a declarative agent\", \"new declarative agent\", \"scaffold an agent\", \"new agent project\", \"add a capability\", \"add a plugin\", \"configure my agent\", \"deploy my agent\", \"fix my agent manifest\", \"edit my agent\", \"localize my agent\", \"add localization\", \"translate my agent\", \"multi-language agent\", \"add an API plugin\", \"add an MCP plugin\", \"add OAuth to my plugin\", \"review instructions\", \"improve instructions\", \"fix my instructions\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4693,4694,4695,4698,4699],{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":4696,"slug":4697,"type":15},"Deployment","deployment",{"name":9,"slug":8,"type":15},{"name":4700,"slug":4701,"type":15},"Microsoft 365","microsoft-365","2026-04-06T18:35:42.309091",{"slug":4704,"name":4704,"fn":4705,"description":4706,"org":4707,"tags":4708,"stars":26,"repoUrl":27,"updatedAt":4715},"email-analytics","analyze email volume and response patterns","Analyze your email patterns over a time period — volume trends, top senders, response time estimates, busiest days, and unread backlog statistics.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4709,4710,4713,4714],{"name":4477,"slug":4478,"type":15},{"name":4711,"slug":4712,"type":15},"Email","email",{"name":9,"slug":8,"type":15},{"name":4632,"slug":4633,"type":15},"2026-04-06T18:35:26.264312",{"slug":4717,"name":4717,"fn":4718,"description":4719,"org":4720,"tags":4721,"stars":26,"repoUrl":27,"updatedAt":4729},"install-atk","install and update M365 Agents Toolkit","Install or update the M365 Agents Toolkit (ATK) CLI and VS Code extension. Triggers: \"install atk\", \"update atk\", \"install agents toolkit\", \"update agents toolkit\", \"install the toolkit\", \"setup atk\", \"get atk\", \"install atk cli\", \"install atk extension\", \"install atk vsix\", \"update the vs code extension\", \"install latest atk\", \"upgrade atk\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[4722,4723,4726,4727,4728],{"name":21,"slug":22,"type":15},{"name":4724,"slug":4725,"type":15},"CLI","cli",{"name":4439,"slug":4440,"type":15},{"name":9,"slug":8,"type":15},{"name":4700,"slug":4701,"type":15},"2026-04-06T18:35:40.873947"]