All skills
microsoft avatar

/ui-widget-developer

@a43d2c6
by microsoftmicrosoft/skills3.1k stars
351

Build MCP servers for Copilot Chat using the OpenAI Apps SDK or MCP Apps SDK widget rendering support (any language). Use this skill when: - Creating MCP servers that integrate with M365 Copilot declarative agents - Building rich interactive widgets (React + Fluent UI) that render in Copilot Chat - Implementing tools that return structuredContent for widget rendering - Adapting an existing MCP server to support Copilot widget rendering - Setting up devtunnels for localhost MCP server exposure - Configuring mcpPlugin.json manifests with RemoteMCPServer runtime 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. Triggers: "MCP server for Copilot", "OpenAI Apps SDK", "Copilot widget", "structuredContent", "MCP plugin", "devtunnels MCP", "OAI app", "widget rendering", "UI widget"

Use this Skill: https://skilld.dev/gh/microsoft/skills/ui-widget-developer

This session only. Nothing lands on disk.

referencesplugin-schema.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

MCP Plugin Schema

mcpPlugin.json configuration for M365 Copilot declarative agents.

Naming note: The property key for tool definitions in the runtime spec is mcp_tool_description. Older documentation may reference x-mcp_tool_description with the x- prefix — this older form is no longer supported and can cause MCP agent provisioning failures. Always use mcp_tool_description (without x-) in new configurations.

⚠️ CRITICAL: Use MCP Inspector ⚠️

NEVER manually write tool definitions. Always use MCP Inspector to get the complete tool definitions from your running MCP server:

npx @modelcontextprotocol/inspector@0.20.0

Copy the COMPLETE tool definition from the inspector (including name, description, inputSchema, _meta, annotations, title) and paste into mcpPlugin.json.

Complete Example

{
  "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.4/schema.json",
  "schema_version": "v2.4",
  "name_for_human": "My Plugin",
  "description_for_human": "Short description for users",
  "description_for_model": "Detailed description for Copilot. Explain when and how to use each tool. Be specific about what data to pass.",
  "contact_email": "support@example.com",
  "namespace": "myplugin",
  "legal_info_url": "https://example.com/legal",
  "privacy_policy_url": "https://example.com/privacy",
  "capabilities": {
    "conversation_starters": [
      {
        "title": "Starter title",
        "text": "What Copilot says when clicked"
      }
    ]
  },
  "runtimes": [
    {
      "type": "RemoteMCPServer",
      "auth": {
        "type": "None"
      },
      "run_for_functions": [
        "tool_name_1",
        "tool_name_2"
      ],
      "spec": {
        "url": "${{MCP_SERVER_URL}}/mcp",
        "mcp_tool_description": {
          "tools": [
            {
              "name": "tool_name_1",
              "title": "Human-Readable Title",
              "description": "Detailed description of what the tool does and when to use it.",
              "inputSchema": {
                "type": "object",
                "properties": {
                  "param1": {
                    "type": "string",
                    "description": "Description with examples"
                  },
                  "param2": {
                    "type": "array",
                    "description": "Array description",
                    "items": {
                      "type": "object",
                      "properties": {
                        "field1": { "type": "string" },
                        "field2": { "type": "string" }
                      },
                      "required": ["field1"]
                    }
                  }
                },
                "required": ["param1", "param2"],
                "additionalProperties": false
              },
              "_meta": {
                "openai/outputTemplate": "ui://widget/my-widget.html",
                "openai/widgetAccessible": true,
                "openai/toolInvocation/invoking": "Processing...",
                "openai/toolInvocation/invoked": "Done"
              },
              "annotations": {
                "destructiveHint": false,
                "openWorldHint": false,
                "readOnlyHint": true
              }
            }
          ]
        }
      }
    }
  ],
  "functions": [
    {
      "name": "tool_name_1",
      "description": "Same description as in tools array"
    }
  ]
}

Note: The tool definition above should be copied from MCP Inspector, not manually written.

Required Fields

Field Description
$schema Must be v2.4 schema URL
schema_version Must be "v2.4"
name_for_human Display name
description_for_human Short user-facing description
description_for_model Detailed description for Copilot
runtimes Array with RemoteMCPServer config
functions Array of function name/description pairs

Runtime Configuration

{
  "type": "RemoteMCPServer",
  "auth": { "type": "None" },
  "run_for_functions": ["tool1", "tool2"],
  "spec": {
    "url": "${{MCP_SERVER_URL}}/mcp",
    "mcp_tool_description": { "tools": [...] }
  }
}

Auth Types

  • "None" - No authentication
  • "OAuthPluginVault" - OAuth via plugin vault

Tool Definition

{
  "name": "tool_name",
  "title": "Display Title",
  "description": "When and how to use this tool",
  "inputSchema": { /* JSON Schema */ },
  "_meta": {
    "openai/outputTemplate": "ui://widget/name.html",
    "openai/widgetAccessible": true,
    "openai/toolInvocation/invoking": "Loading...",
    "openai/toolInvocation/invoked": "Loaded"
  },
  "annotations": {
    "destructiveHint": false,
    "openWorldHint": false,
    "readOnlyHint": true
  }
}

_meta Fields

Field Description
openai/outputTemplate Widget URI (ui://widget/name.html)
openai/widgetAccessible Enable widget rendering (true)
openai/toolInvocation/invoking Message while executing
openai/toolInvocation/invoked Message when complete

Annotations

Field Description
destructiveHint Tool modifies data (false for rendering tools)
openWorldHint Tool accesses external systems
readOnlyHint Tool only reads/renders data (true for rendering tools)

Input Schema Patterns

Object with required fields

{
  "type": "object",
  "properties": {
    "name": { "type": "string", "description": "Full name (e.g., 'John Doe')" },
    "email": { "type": "string", "description": "Email address" }
  },
  "required": ["name", "email"],
  "additionalProperties": false
}

Nested object

{
  "type": "object",
  "properties": {
    "person": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "title": { "type": "string" }
      },
      "required": ["name"]
    }
  },
  "required": ["person"]
}

Array of objects

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": { "type": "string" },
      "value": { "type": "string" }
    },
    "required": ["id", "value"]
  }
}

Environment Variables

Use ${{VAR_NAME}} syntax for environment variables:

  • ${{MCP_SERVER_URL}} - Full server URL (e.g., https://tunnel.devtunnels.ms)
  • ${{MCP_SERVER_DOMAIN}} - Domain only for validDomains

Define in env/.env.local:

MCP_SERVER_URL=https://your-tunnel.devtunnels.ms
MCP_SERVER_DOMAIN=your-tunnel.devtunnels.ms

Common Errors

Error Fix
name_for_model unrecognized Remove it (not in v2.4)
MCP runtime type invalid Use RemoteMCPServer
transport unrecognized Remove it
run_for_functions required Add array of tool names
Missing auth Add { "type": "None" }

Source: SKILL.md on GitHub

2 warnings3mo3 checks · Risk SAFE
  • Gen Agent Trust Hub3mo

    This skill provides a comprehensive framework for developing Model Context Protocol (MCP) servers and interactive widgets for Microsoft 365 Copilot. It includes automation for environment configuration, local service management, and robust reference implementations. The security analysis found that the skill follows industry best practices for local development, including path security and input validation.

  • Socket3mo

    1 alert: gptAnomaly

  • Snyk3mo

    Risk: MEDIUM · 1 issue

Signed by skilld at a43d2c6. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 4 months ago

README badge

README badge for microsoft/skills/ui-widget-developer