Skip to main content
A POST /api/v2/murph/chat response always carries the assistant’s text answer. On turns where Murph runs a tool that has a canonical interactive surface, the response also carries a structured rendering artifact for the in-product UI and other direct REST clients. These named REST fields are not an MCP Apps protocol. External hosts such as Claude or ChatGPT do not receive the /murph/chat response when they call the ask_murph MCP tool; they receive the standard MCP tool result described below.
Each artifact field is optional and nullable. A client that does not render MCP Apps can ignore every artifact and show the text answer alone — the answer is always self-contained.

How a REST client renders an artifact

Every artifact names the MCP App that renders it and the data to hand it:
  1. Load the MCP App at the artifact’s resourceUri.
  2. Pass the artifact’s data object to the app as the tool result’s structuredContent. The app routes on data.endpoint to the named view.
The host decides where to place the surface — the in-product Murph UI renders the discovery widget above the text answer, for example.

discoveryMcpui

Emitted on a successful discover_products tool call. Renders the product discovery surface — a browsable, selectable list of the discovered products grouped by storefront, with per-product brief-relevance reasoning.
When this artifact is present, Murph’s text answer is a concise orientation (totals, price range, any recommended plans) plus next steps — it deliberately does not re-list every product, because the widget already shows the full, selectable set.

Other rendering artifacts

The chat response uses the same pattern for other canonical surfaces: Each carries kind, resourceUri, canonicalSurface, and a data payload to hand the app as structuredContent; creativeMcpui additionally carries a refresh directive describing the tool call that reloads the surface, and inventoryMcpui carries the esaId and the initial selector filters.

ask_murph MCP tool result (conformant MCP Apps)

The artifacts above ride the REST /api/v2/murph/chat response as named fields — the in-product Murph UI reads them directly. An external MCP Apps host (Claude, ChatGPT) that calls the ask_murph MCP tool does not receive that REST response directly; it receives a standard tool result. Some result kinds retain named compatibility data inside structuredContent, but rendering is selected by standard result metadata:
  • It selects one primary widget per turn — this result contract carries a single render payload. Precedence, highest-intent first: mcpAppWidgetcreativeIntentMcpuiinventoryMcpuicreativeMcpuidiscoveryMcpuisellerAnalyticsmurphEscalations.
  • The result embeds that widget’s ui:// resource in content and sets a per-call _meta (ui.resourceUri and the legacy ui/resourceUri) so the host loads the right MCP App for this result.
  • For api-call-style widgets (discovery, inventory, creative, creative-intent), the app reads the flat api-call envelope (success, endpoint, params, data), so that envelope is spread onto the top level of structuredContent where ontoolresult reads it. The now-redundant named field is dropped so the payload isn’t carried twice.
  • Launch widgets (mcpAppWidget) and named-field panels (sellerAnalytics, murphEscalations) carry no api-call envelope; their data already sits under their named key in structuredContent, which the host hands the app.
A turn that produced several widgets still renders one in a generic host; the in-product drawer can show all of them via the REST fields above.

Sales Agent validation handoff

The Agent page can pass a server-recognized validation context to ask_murph. It supplies identifiers only: the Agent, its returned skill version, an available profile, and, when present, a Source. It never supplies credentials or expands the caller’s authority. A transaction validation can return salesAgentValidation with status: "PENDING_CONFIRMATION". Its runId, implementationRevision, generation, pendingStepId, and nextAction: "CONFIRM_TRANSACTION_STEP" identify the one no-spend action waiting for the owner. implementationRevision is read-only evidence. To continue the run, return agentId, skillVersion, and profile: "transaction" with the returned runId and pendingStepId, then map generation to confirmationGeneration and nextAction to confirmation. The service issues a separate, generation-fenced confirmation before staging a media buy and before activating the sandbox campaign. Do not construct or reuse a confirmation from another run. A stale, expired, cancelled, or consumed confirmation cannot be replayed; start a new validation. A completed result identifies its implementation revision and cleanup outcome. It is validation evidence, not a certificate or authorization for a client connection.

Protected Sales Agent certification request

A directly authenticated administrator of the Agent owner’s organization can ask Murph to record a request for protected technical certification evaluation. The request is accepted only when the exact current implementation already has an unexpired protected fixture and immutable evaluation template. The owner cannot provide either value, dispatch the work, or report an assertion result. Murph returns salesAgentCertificationRequest when it records that intent:
actionUid identifies the immutable owner request and implementationRevision identifies the implementation it applies to. The QUEUED_FOR_PROTECTED_EVALUATION status means a protected system must still recheck the pinned fixture and template before it can create or dispatch any work. It does not mean a provider test ran, an assertion passed, or the Agent is certified. Creative and complete-suite certification results remain separate evidence.

Conversational MCP profile

The existing Murph MCP endpoint also exposes a portable conversation profile. MCP clients on buyer and seller accounts use the same two tools; existing ask_murph calls keep their current request and response shape.

chat

Call chat to begin a conversation or add a turn. The request has one message and may include up to five Base64 attachments, each no larger than 1 MiB after decoding.
A completed response is a normal MCP CallToolResult. Read the portable turn from structuredContent.conversation:
status is completed, input_required, or failed. Messages contain only display-safe user and assistant text; tool traces, internal context, and credentials are never returned. A protocol failure instead sets isError and may return only text or an error object in structuredContent. When a turn declares an app widget, it appears as structuredContent.widget. The result selects the widget through the standard _meta.ui.resourceUri directive. Hosts must use that shared MCP Apps contract; they must not infer a widget or route from Murph’s text.

Progress on a long turn

A chat turn runs Murph’s full tool loop, so an involved question can take minutes to answer. Set the MCP protocol’s _meta.progressToken on the tools/call request and the server sends notifications/progress messages while the turn works, so a host can show the caller that a long turn is running rather than hung. Each notification carries a short message describing the current phase — “Reading the docs…”, “Checking your account…”, “Writing it up…” — written in the language the conversation is already being answered in. Internal tool names are never sent; the phrases group tools by intent. The first notification goes out before the turn starts, so a turn that calls no tools still reports that it began. progress increments on each distinct phase and no total is sent, because the number of phases is not known in advance — render it as indeterminate progress rather than a percentage. Progress is advisory. The tool result stays the authoritative answer, a client may ignore the notifications, and a client that sends no progress token gets exactly the synchronous behaviour it got before. The portable profile also permits the MCP Tasks extension for a turn that a server does not complete synchronously. Such a result is the native CreateTaskResult task envelope (taskId, status, createdAt, lastUpdatedAt, ttl, and optional pollInterval), which a client polls or cancels using MCP Tasks. Murph’s current orchestration completes this profile call synchronously.

get_conversation

Call get_conversation with a conversation ID to read display-safe turns. Set after to the opaque cursor from nextAfter to request the following page.
The structured result contains conversationId, turns, and nextAfter when another page is available. It does not create an agent-initiated message or subscribe the caller to notifications.

Token usage

Every POST /api/v2/murph/chat response carries a usage object reporting the turn’s token consumption, cumulative across the tool-loop iterations of the turn.
The model reports cache reads and creations separately from inputTokens — they are not included in it. To get the true total input volume for a turn, sum inputTokens + cacheReadInputTokens + cacheCreationInputTokens. Murph caches its system prompt and tool surface, so on a warm conversation cacheReadInputTokens is typically the largest of the three.

Conversation scope

Set a Murph conversation’s account or advertiser scope.

Ask Murph

How Murph works as the in-product assistant.