Skip to content

feat: HTML widget support (MCP Apps UI)#626

Draft
corinagum wants to merge 17 commits into
mainfrom
cg/widgets
Draft

feat: HTML widget support (MCP Apps UI)#626
corinagum wants to merge 17 commits into
mainfrom
cg/widgets

Conversation

@corinagum

@corinagum corinagum commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator
image

Summary

Adds HTML widget support to the Teams TypeScript SDK, enabling bots to send rich interactive MCP Apps UI widgets in Teams messages.

What's included

API types (@microsoft/teams.api)

  • IHtmlWidgetPayload, IHtmlWidgetSecurityPolicy, IHtmlWidgetPermissions
  • IMcpUiCallToolResult, IHtmlWidgetCallToolResponse (wire-format wrapper)
  • IHtmlWidgetCallToolInvokeActivity and invoke response mapping
  • extendedmarkdown added to TextFormat

App helpers (@microsoft/teams.apps)

  • buildHtmlWidgetMarkdown - wraps payload in ```html-widget code fence
  • buildHtmlWidgetMessage - builds a ready-to-send message activity
  • injectWidgetProtocol - optional convenience helper that injects the MCP Apps protocol (ui/initialize handshake, size reporting, notification hooks)
  • validateSecurityPolicy - static analysis of widget HTML against declared security policy
  • widget.callTool invoke route

Internal (not exported):

  • validateHtmlWidgetPayload - runtime validation (name, html, domain) called automatically by builders

Example bot (examples/html-widgets/)

  • 9 commands demonstrating the full widget contract
  • Typed widget.callTool handler with multi-tool dispatch

Integration tests

  • Send widget, send with toolInput/toolOutput, update widget, delete widget

Preview markers

  • All public APIs marked @experimental with Diagnostic: ExperimentalTeamsHtmlWidget

Design decisions

  • Protocol injection is opt-in: injectWidgetProtocol is called internally by the builders, but widgets that implement the MCP Apps protocol themselves are returned unchanged (detected by presence of ui/initialize)
  • Notification hooks are explicit: only mapped notification names are injected; unknown names are silently ignored
  • Payload validation throws early: prevents silent client-side "Couldn't load widget" failures
  • Default security policy: restrictive defaults per MCP Apps spec (no external network, self+data resources only)
  • Security validation is advisory: validateSecurityPolicy is a static linter; CSP enforcement in the iframe is the actual security boundary

Related

Status

Draft - pending:

  • Python SDK port
  • .NET core port
  • .NET Libraries port
  • Documentation in teams-sdk/teams.md

corinagum and others added 10 commits June 19, 2026 12:09
Add types for the HTML widget contract:
- IHtmlWidgetPayload, IHtmlWidgetSecurityPolicy, IHtmlWidgetPermissions
- ICallToolRequest, IMcpUiCallToolResult
- IHtmlWidgetCallToolInvokeActivity (htmlwidget/calltool invoke)
- Add 'extendedmarkdown' to TextFormat union
- Add htmlwidget/calltool to InvokeResponseBody map

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add 'htmlwidget/calltool' -> 'widget.callTool' invoke alias
- Add WidgetCallToolRoutes type for typed handler registration
- Add buildHtmlWidgetMarkdown() and buildHtmlWidgetMessage() helpers
- Add unit tests (14 cases including edge cases)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/apps/src/utils/html-widget.ts Fixed
Comment thread packages/apps/src/utils/html-widget.ts Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class “HTML widget” (MCP Apps UI) support to the Teams TypeScript SDK by introducing new API models for widget payloads + callTool invoke wiring, app-side helpers for building/injecting widget protocol HTML, and accompanying examples + tests.

Changes:

  • Added @microsoft/teams.api models for HTML widget payloads/security policy and the htmlwidget/calltool invoke request/response contract.
  • Added @microsoft/teams.apps helpers to build widget markdown/message activities and to optionally inject the MCP Apps protocol + validate security policy references.
  • Added an examples/html-widgets sample bot and integration/unit tests covering send/update/delete and policy validation.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/integration/src/html-widgets.test.ts New integration tests for sending/updating/deleting widget messages using extendedmarkdown.
test/integration/src/fixture.ts Makes meetingId optional and stops requiring TEST_MEETING_ID for integration test config.
test/integration/jest.config.ts Increases integration test timeout for slower widget/canary operations.
packages/apps/src/utils/html-widget.ts New widget helpers: payload validation, protocol injection, markdown/message builders, security policy static validation.
packages/apps/src/utils/html-widget.spec.ts New unit tests validating protocol injection, markdown formatting, payload validation, and security policy warnings.
packages/apps/src/routes/invoke/widget-calltool.ts Adds typed route surface for widget.callTool.
packages/apps/src/routes/invoke/index.ts Adds invoke alias mapping htmlwidget/calltool -> widget.callTool and exports the new route type.
packages/apps/src/index.ts Re-exports the new HTML widget utilities from @microsoft/teams.apps.
packages/api/src/models/invoke-response.ts Adds htmlwidget/calltool invoke response body typing.
packages/api/src/models/index.ts Exports new html-widget models.
packages/api/src/models/html-widget/index.ts Barrel export for widget model types.
packages/api/src/models/html-widget/html-widget-payload.ts Defines widget payload, permissions, and security policy types.
packages/api/src/models/html-widget/call-tool-result.ts Defines MCP UI call tool result + Teams wire wrapper response type.
packages/api/src/models/html-widget/call-tool-request.ts Defines htmlwidget/calltool invoke request payload.
packages/api/src/activities/invoke/index.ts Extends InvokeActivity union to include widget callTool invoke.
packages/api/src/activities/invoke/html-widget/index.ts Barrel export for widget invoke activity types.
packages/api/src/activities/invoke/html-widget/call-tool.ts Defines the htmlwidget/calltool invoke activity shape.
package-lock.json Adds the new example workspace entry and updates lockfile dependencies.
examples/html-widgets/tsconfig.json TypeScript config for the new example workspace.
examples/html-widgets/src/widgets/update-context.ts Example widget exercising ui/update-model-context.
examples/html-widgets/src/widgets/simple.ts Minimal static widget HTML example.
examples/html-widgets/src/widgets/open-link.ts Example widget exercising ui/open-link.
examples/html-widgets/src/widgets/multi-tool.ts Example widget that calls multiple tools (tools/call) for dispatch testing.
examples/html-widgets/src/widgets/messageback.ts Example widget exercising ui/message (messageBack-like behavior).
examples/html-widgets/src/widgets/host-context.ts Example widget showing hostContext + listening for host-context-changed notifications.
examples/html-widgets/src/widgets/fullscreen.ts Example widget requesting fullscreen display mode.
examples/html-widgets/src/widgets/calltool.ts Example widget calling a refresh tool and rendering results.
examples/html-widgets/src/index.ts Example bot wiring commands + typed widget.callTool handler returning the wrapper response.
examples/html-widgets/README.md Example documentation and architecture overview for widget contract.
examples/html-widgets/package.json New example workspace package definition and scripts.
examples/html-widgets/eslint.config.js ESLint config wiring for the new example workspace.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/apps/src/utils/html-widget.ts
Comment thread packages/apps/src/utils/html-widget.ts
Comment thread packages/apps/src/index.ts
Comment thread examples/html-widgets/README.md Outdated
Comment thread packages/apps/src/utils/html-widget.ts
Comment thread packages/apps/src/utils/html-widget.ts Outdated
Comment thread examples/html-widgets/README.md Outdated
Comment thread packages/apps/src/utils/html-widget.ts Fixed
Comment thread packages/apps/src/utils/html-widget.ts Fixed
Comment thread packages/apps/src/utils/html-widget.spec.ts Fixed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants