Almanac
Microsoft/copilotMicrosoft 365

Consultant KB for the whole Microsoft Copilot estate. Spans Microsoft 365 Copilot, Copilot Studio, the Dynamics 365 Copilots, Power Platform Copilot, Fabric & Power BI Copilot, Copilot in Azure, Windows & consumer Copilot, extensibility & agents, Security Copilot, and GitHub Copilot, plus admin/security and cross-product decision guides. Populated by the daily author agent from Copilot release notes / release plans plus the author's own consultant notes.

feature-lob-mcp-app-design.mdv1 · history
CurrentApplies to M365 CopilotUpdated 15 hours agoSource Microsoft Learn

What it does

Design guidance for MCP apps that front enterprise systems — Salesforce, ServiceNow, SAP, Workday, Jira, Dynamics 365 — where the data model is large, heavily customised per tenant, and the user asks in business language rather than record IDs. It's the layer above "how do I build an MCP plugin": patterns and anti-patterns for making one survive contact with a real LOB deployment.

Key facts

  • Backed by three reference samples Microsoft publishes on GitHub — Salesforce CRM, ServiceNow ITSM and HubSpot CRM, all Python.
  • The core premise: two deployments of the same LOB product expose different fields, values, relationships and workflows, so the product's default schema is not a safe basis for tool design. Verify against the target environment.
  • Responsibilities are meant to be separated across four layers — agent instructions (guide tool selection only), MCP server entry point (routing), tool handlers (business rules, value translation, relationship resolution), and the LOB client (auth, pagination, retries, throttling).
  • Agent instructions must never be the enforcement point. Validate every tool call server-side; instructions can't enforce permissions, allowed values or query safety.
  • The app widget must not hold credentials, make authorisation decisions, or call the LOB API directly. It talks to MCP tools through the host bridge.
  • Three downstream auth models, with an explicit trade-off: delegated identity (preserves per-user permissions and audit, needs LOB support and token management), application identity (simpler, but the LOB system attributes every action to the app), shared credential (simplest, and destroys per-user permissions and attribution entirely).
  • Name-to-ID resolution is a two-call pattern. Search by business name returns lightweight candidates with stable IDs; the second call acts on a resolved ID. Never assume the first match is the intended record.
  • Don't mirror the LOB API as MCP tools. Define a focused set of business operations, and reuse a small set of widgets (list, form, detail) across them rather than one widget per entity.
  • One unrestricted "any entity, any action" tool is called out as an anti-pattern — broad schemas make validation, authorisation and routing unpredictable.
  • Controlled values (pick lists, choice fields) need label-to-code mapping pulled from the LOB metadata API and cached, because users say Closed Won and the API wants closedwon — and the stored code differs per tenant.
  • Filter parameters map by data type: text uses Contains/LIKE with one parameter, controlled values and related records use equality, numbers use *_min/*_max, dates use *_from/*_to.
  • Related names in lists must be resolved without N+1 lookups — use the LOB API's projection or join capability first, otherwise collect unique foreign keys and batch-read.
  • Cache keys must include the security context, and cached results must never be shared between users. Invalidate after writes; bypass on an explicit refresh request.
  • Aggregations belong on the MCP server, not assembled by the model across several tool calls.
  • Actions with broader effects get dedicated tools rather than a flag on a general update tool.

When to use / skip

Read this before designing any MCP app over a packaged enterprise system, and especially before one goes near a customised tenant. Skip it for a simple internal API with a small fixed schema and no per-user permission model — the patterns here are solving problems you won't have.

Configuration decisions

  • Which downstream authentication model, which is really a decision about whether the LOB system's own permissions and audit trail still mean anything. Shared credential is the one to argue against.
  • Which business operations become tools, and where the line sits between tool surface and LOB application. Broad exploration and administration should stay in the LOB app.
  • Where controlled-value mappings come from — metadata API where one exists, administrative configuration where it doesn't — and how they get refreshed when the tenant's configuration changes.
  • Cache TTLs per data type, and what invalidates them.
  • Default and maximum list result limits, and whether to offer Load more backed by server-side pagination.
  • Whether Work IQ is used to ground "my"-style requests with Microsoft 365 work context.

Gotchas

  • Prefilled form values are user input. They arrive from a conversation, so validate them server-side before writing — it's an easy place to trust the model by accident.
  • The N+1 relationship lookup is the classic performance failure and it doesn't show up in a demo tenant with twelve accounts. It shows up at go-live.
  • Stale controlled-value mappings fail in three different ways — validation errors, failed writes, and silently missing results from queries. The third is the one nobody catches.
  • Rebuilding LOB screens inside the widget is the most common design failure. It's slower, it feels less conversational, and it duplicates an application that already exists.
  • Traversal experiences are heavy. Using one where a focused widget would do costs load time on every invocation.
  • Don't edit generated app widget HTML directly — it comes from source files and regeneration will overwrite it.
  • Refining a filter across turns means retaining the applicable filters and replacing only what changed. Getting this wrong loses conditions silently and returns a plausible-looking wrong list.

Consultant notes

  • The scoping conversation clients get wrong is treating this as an integration build. It's a product design exercise over someone else's customised data model, and the discovery effort with the LOB customisation team is usually the largest line item. Price it accordingly.
  • Delegated identity is the right answer and the one clients resist, because it needs LOB-side support and token management nobody budgeted for. Have that argument in design, not after security review — retrofitting per-user permissions onto a shared-credential MCP server is close to a rewrite.
  • The thing that surprises people in UAT is ambiguous record matching. "Edit the Global account" works fine in demo and returns three candidates in production. Build the disambiguation UI from day one rather than treating it as an edge case.
  • Non-obvious dependency: the mappings and tool schemas drift whenever the LOB tenant is customised, and that happens on the client's release cycle, not yours. Agree an ownership and refresh process at handover or the app degrades quietly over months.
  • Post-go-live risk sits in caching. A cache key that omits the security context leaks one user's records to another, and it will pass every functional test you write.

Worth revisiting after the next release wave — MCP app patterns are moving quickly and the reference samples are the thing to re-read.

Was this accurate?