Tool result messages reach MCP clients with HTML entities

Problem/Motivation

ToolApi::execute() casts the Tool API result message to a string and returns it as MCP text content:

$formatted = $tool->getFormattedResult();
$message = (string) $formatted->getMessage();

Tools build result messages as TranslatableMarkup, and @ placeholders HTML-escape their values. Quotes in a message reach the MCP client as entities. For example, a canvas_tools publish denial from canvas_tools!15 (merged) reads:

Publish failed: Unable to update entities: 'About us'.

The model reads ' literally. Tool API tracks the same bug for tool:run and tool_ai_connector in tool#3583042 (closed), which names this module as a follow-up.

Proposed resolution

Render the message as plain text before returning it:

use Drupal\Component\Render\PlainTextOutput;

$message = PlainTextOutput::renderFromHtml((string) $formatted->getMessage());

Remaining tasks

  • Test: a tool whose failure message has quotes in a placeholder returns them unescaped from tools/call.