afv-library/skills/platform-mcp-tool-widget-coordinate/examples/apex-invocable-source-prompt.md

4.4 KiB

Example: Apex Invocable source

A complete walkthrough of the flow when the payload source is an Apex @InvocableMethod class that already exists in the project (source = apex). This is the fallback source — when the action is deployed to a reachable org, prefer action (describe it by name via the Actions REST API; see action-name-source-prompt.md). Use apex when no org is reachable or the describe 404s.

The prompt

I have an MCP server tool backed by the GetAccountSummaryTest Apex invocable action. Build a widget that renders its output so the account summary shows up as a rich card.

Phase 1 — Input selection

  • Source: apex (the prompt names an Apex Invocable class).
  • Tool API name: getAccountSummary (from the class / invocable label Get Account Summary).

Phase 2 — Payload discovery

Read references/mcp-tool-output-discovery.md, then locate .../classes/GetAccountSummaryTest.cls.

The invocable method:

@InvocableMethod(label='Get Account Summary')
global static List<GetAccountSummaryResponse> getAccountSummary(
    List<GetAccountSummaryRequest> requests
) { ... }
  • Response class = GetAccountSummaryResponse (the List<...> element type) → payload source.
  • Request class = GetAccountSummaryRequest → excluded (tool input).
  • private class OpportunityMetrics → excluded (internal helper, not part of the invocable schema).

Enumerate @InvocableVariable fields on GetAccountSummaryResponse and map to CLT types:

Field Apex type CLT lightning:type
status String lightning__textType
message String lightning__textType
accountId Id lightning__textType
accountName String lightning__textType
accountDescription String lightning__textType
accountIndustry String lightning__textType
accountPhone String lightning__textType
accountWebsite String lightning__textType
contactCount Integer lightning__integerType
opportunityCount Integer lightning__integerType
largestOpportunityId Id lightning__textType
largestOpportunityName String lightning__textType
largestOpportunityAmount Decimal lightning__numberType
totalOpportunityAmount Decimal lightning__numberType

payloadFields = the 14 rows above.

Phase 3 — Build plan (abridged)

MCP Tool Widget Build Plan: getAccountSummaryWidget

PLAN: Render the GetAccountSummary MCP tool output as an account-summary card.

TOOL / SOURCE:
  Tool API name: getAccountSummary
  Payload source: Apex Invocable class GetAccountSummaryTest
  Response class FQN: GetAccountSummaryTest.GetAccountSummaryResponse

LIGHTNING TYPES:
  Response CLT:  getAccountSummaryResponse   (14 payload properties)
  Envelope CLT: getAccountSummary
    Renderer (default, bundle root): .../lightningTypes/getAccountSummary/renderer.json
    Envelope: actionName (text), isSuccess (boolean), outputValues (c__getAccountSummaryResponse)

WIDGET: getAccountSummaryWidget
  Renderer binding: each attribute → {!$attrs.outputValues.<field>}
  Properties omitted: status, message (envelope-status text, not rendered on the card)

GENERATION ORDER: response CLT → widget → envelope CLT

Proceed unless the next reply pushes back.

Phase 4 — Generation order

  1. Response CLT getAccountSummaryResponselightning__objectType, all 14 payloadFields (1:1 with the response class's @InvocableVariable fields — the response CLT always models the complete response, including status/message).
  2. Envelope CLT getAccountSummaryactionName, isSuccess, outputValuesc__getAccountSummaryResponse.
  3. Widget getAccountSummaryWidget — flat schema over the 12 rendered payload fields (14 minus the two Properties omitted: status fields); body binds {!$attrs.accountName} etc.
  4. Default renderer at lightningTypes/getAccountSummary/renderer.jsondefinition: @widget/c/getAccountSummaryWidget, each attribute {!$attrs.outputValues.<field>}.

Phase 5 — Validation

  • clt-reference-integrity: envelope outputValuesc__getAccountSummaryResponse, response CLT exists, no $schema/itemspass.
  • renderer-wires-widget: bundle-root renderer present, definition @widget/c/getAccountSummaryWidget, every widget prop bound as {!$attrs.outputValues.<prop>}pass.
  • field-trace: INVENTED empty; OMITTED = status, message (both in Properties omitted:) → pass.