Implements the design at design/workiq-integration.md.
Why
Microsoft's Work IQ (preview, May 2026) exposes M365 data (Mail, Calendar, Teams, SharePoint, OneDrive, Word, Copilot Search, User, Dataverse) as HTTP MCP servers grounded in the Copilot intelligence layer. The differentiator vs raw Graph is semantic ranking and Copilot-grounded search.
Three constraints make integration awkward:
- Per-user delegated auth only — every call requires a token for a specific user holding an M365 Copilot license. No app-only / client-credentials.
- Interactive OAuth assumed — standard clients use OAuth 2.1 + PKCE with a loopback redirect. The agent pod has no browser.
- Expiring bearer over HTTP — tokens expire in ~1h; the current bridge sets headers once on
HttpClient.DefaultRequestHeaders and would silently 401 after the first hour.
Design splits responsibility: UI tier (Blazor/CLI) runs MSAL interactive/device-code, ships the serialized token cache to the agent over the bus; agent persists to its own PVC and does AcquireTokenSilent per request via a DelegatingHandler. UI tier stays credential-free (no k8s Secret RBAC, no PVC mount).
Prerequisite decision
Is Copilot licensing worth it for what Work IQ adds over Graph? If the agent's M365 needs are primarily CRUD, the existing ms-365 MCP server hits Graph directly and avoids the per-user Copilot license. This should be answered before starting Phase 1.
Phased plan
Phase 1 — Bridge auth infrastructure
Can land and be unit-tested without any Work IQ involvement; reusable for any future bearer-auth MCP server.
Phase 2 — MSAL token plumbing (no Work IQ yet)
Phase 3 — UI tier MSAL flow
Phase 4 — Entra app registration + wire-up
Phase 5 — Re-consent UX and failure-mode polish
Out of scope (v1)
- Multi-user Work IQ access via UserProxy plumbing — v2.
- Token-broker microservice — not needed while everything that calls Work IQ runs in the agent process.
- App-only / client-credentials path — re-check at each Work IQ preview milestone.
Open questions
- Whether to ship Work IQ servers in the default seeded
mcp.json or require the operator to register them manually after consent (probably the latter — keeps the seed list working without a license).
- Whether the Blazor MSAL redirect URI should be the loopback
http://localhost:8080/callback or a route in the Blazor app itself (depends on how Blazor is hosted in practice).
- Cache file format: raw MSAL bytes vs an envelope that also tracks
AccountId, expiry, scopes (for diagnostics without parsing MSAL internals).
Success criteria
References
Implements the design at
design/workiq-integration.md.Why
Microsoft's Work IQ (preview, May 2026) exposes M365 data (Mail, Calendar, Teams, SharePoint, OneDrive, Word, Copilot Search, User, Dataverse) as HTTP MCP servers grounded in the Copilot intelligence layer. The differentiator vs raw Graph is semantic ranking and Copilot-grounded search.
Three constraints make integration awkward:
HttpClient.DefaultRequestHeadersand would silently 401 after the first hour.Design splits responsibility: UI tier (Blazor/CLI) runs MSAL interactive/device-code, ships the serialized token cache to the agent over the bus; agent persists to its own PVC and does
AcquireTokenSilentper request via aDelegatingHandler. UI tier stays credential-free (no k8s Secret RBAC, no PVC mount).Prerequisite decision
Is Copilot licensing worth it for what Work IQ adds over Graph? If the agent's M365 needs are primarily CRUD, the existing ms-365 MCP server hits Graph directly and avoids the per-user Copilot license. This should be answered before starting Phase 1.
Phased plan
Phase 1 — Bridge auth infrastructure
Can land and be unit-tested without any Work IQ involvement; reusable for any future bearer-auth MCP server.
McpServerAuthConfigrecord; add optionalAuthfield toMcpBridgeServerConfigITokenProvider+ITokenProviderRegistryinterfaces inRockBot.Tools.McpBearerInjectionHandler : DelegatingHandler— calls provider per request, retries once on 401 withforceRefresh: trueMcpBridgeService.ConnectServerAsyncbuilds the auth-bearingHttpClientvia the handler whenconfig.Authis set; otherwise unchangedHeadersandAuthcoexist on the same serverPhase 2 — MSAL token plumbing (no Work IQ yet)
WorkIqAuthCacheUpdatedandWorkIqAuthExpiredmessage types underRockBot.Messaging.Abstractions(or wherever auth messages belong)TokenCacheStorein the agent — subscribes toauth.workiq.cache, persists to/data/agent/secrets/workiq-cache.bin(mode 0600), loads into MSAL on startupMsalTokenProviderimplementingITokenProvider; registered in DI with tenant/client/scopes from configmap/data/agent/secrets/with correct ownership/permissionsWorkIQ__TenantId,WorkIQ__ClientId; values land inappsettings-style configMsalUiRequiredExceptiontriggersWorkIqAuthExpiredpublishPhase 3 — UI tier MSAL flow
http://localhost:8080/callback(or whatever fits the Blazor host model)rockbot auth workiqcommand → MSAL device-code flowWorkIqAuthCacheUpdatedWorkIqAuthExpired; surfaces a "Reconnect M365" bannerPhase 4 — Entra app registration + wire-up
deploy/)WorkIQ-*permissions for the servers we want enabled (Mail and Calendar minimum; expand as needed)mcp.json(or document the registration UX) usingauth.profile: "workiq"workiq-mail→ returns resultsPhase 5 — Re-consent UX and failure-mode polish
ToolErrorfrom Work IQ servers withMsalUiRequiredExceptionupstream carries an actionable message ("M365 connection expired — open Blazor and click Reconnect")deploy/runbook for the Entra registration and license requirementsOut of scope (v1)
Open questions
mcp.jsonor require the operator to register them manually after consent (probably the latter — keeps the seed list working without a license).http://localhost:8080/callbackor a route in the Blazor app itself (depends on how Blazor is hosted in practice).AccountId, expiry, scopes (for diagnostics without parsing MSAL internals).Success criteria
workiq-mailandworkiq-calendartools end-to-end after a Blazor consentmcp.jsonat any pointReferences
design/workiq-integration.mddesign/mcp-bridge.md(the bridge this extends)design/security.md(trust boundaries this respects)