Loading
fix: #3618726 Send tool messages to MCP clients as plain text
Closes #3618726 (closed)
ToolApi::execute() sent markup to MCP clients as raw HTML. Placeholders escape quotes and % placeholders add an <em> tag, so the model read text like this:
Successfully deleted node entity "Torture "quoted" title" (ID: 70)This MR adds a plainText() helper. It runs PlainTextOutput::renderFromHtml() on markup, the same way tool:run and tool_ai_connector do since tool#3583042 (closed). Plain strings pass through unchanged, because rendering would strip text that looks like a tag and decode literal entities.
- The result message from
getFormattedResult()is alwaysTranslatableMarkup, so it is rendered. - Each violation message from
validateInputs()is converted on its own and sent one per line. Tool API wraps each one asInput @name: @message, and core constraint messages use%value. This also drops the typed data root prefix that #3618731 (closed) tracks, so !25 (closed) keeps only its tests after a rebase. - The access denial reason is sent as the tool gave it.
getReason()always returns a string, andtool:rundoes the same.
Exception messages stay as they are.
Testing
A new mcp_server_test:quoted_message fixture puts its title input in the violation message, the access reason, and the result message. ToolApiFailureResultTest checks:
- Violation and result messages arrive with literal quotes and no
<em>tag. These fail on 1.x. - An access reason of
About <us> & "team" is locked.arrives unchanged. This fails if the reason is rendered from HTML.
Edited by Matt Glaman