MCP tool string parameters containing HTML are stripped before reaching MCP server
Description
When the Copilot CLI invokes an MCP tool with a string parameter containing HTML (e.g., <h2>, <ul>, <code> tags), the HTML is stripped before the JSON-RPC request reaches the MCP server. The server receives plain text instead of the original HTML.
Reproduction
- Register an MCP server with a tool that accepts a
string parameter (e.g., description)
- The AI generates a tool call with HTML content in that parameter:
{
"name": "CreateWorkItem",
"arguments": {
"title": "Test",
"description": "<h2>Summary</h2><p>Details about <code>SomeClass</code></p><ul><li>Item 1</li></ul>"
}
}
- The MCP server receives the
description parameter with all HTML tags removed, content wrapped in a single <p> tag
Expected Behavior
The HTML string should be passed through to the MCP server unchanged. It is a valid JSON string value and the MCP protocol has no reason to sanitize it.
Evidence
We built integration tests (ASP.NET TestServer + MCP SDK v0.5.0-preview.1) that prove the MCP SDK itself preserves HTML correctly through client→HTTP→server→parameter binding:
- ✅
McpSdk_PreservesHtmlInStringParameters — HTML tags preserved
- ✅
McpSdk_PreservesComplexHtmlWithEntities — entities and code blocks preserved
- ✅
McpSdk_PreservesHtmlWhenPassedAsJsonElement — boxed JsonElement values preserved
- ✅
McpSdk_PreservesMultiLineHtml — multi-line HTML preserved
All tests pass, confirming the issue is upstream of the MCP server — in the Copilot CLI's tool call parameter serialization layer.
We also verified the Fleet MCP Gateway proxy layer (which converts JsonElement → object and forwards to the MCP server) preserves HTML with 7 additional unit tests.
Impact
Any MCP tool that needs to pass HTML or structured markup in string parameters is affected. In our case, Azure DevOps work item descriptions (which natively support HTML) are always created as unformatted plain text, requiring a REST API workaround to set them properly.
Workaround
Bypass the MCP tool for HTML-bearing fields and use direct REST API calls instead (two-step: create via MCP, then patch description via REST).
Environment
- Copilot CLI version: 1.0.23
- MCP SDK: ModelContextProtocol v0.5.0-preview.1
- OS: Windows 11
MCP tool string parameters containing HTML are stripped before reaching MCP server
Description
When the Copilot CLI invokes an MCP tool with a string parameter containing HTML (e.g.,
<h2>,<ul>,<code>tags), the HTML is stripped before the JSON-RPC request reaches the MCP server. The server receives plain text instead of the original HTML.Reproduction
stringparameter (e.g.,description){ "name": "CreateWorkItem", "arguments": { "title": "Test", "description": "<h2>Summary</h2><p>Details about <code>SomeClass</code></p><ul><li>Item 1</li></ul>" } }descriptionparameter with all HTML tags removed, content wrapped in a single<p>tagExpected Behavior
The HTML string should be passed through to the MCP server unchanged. It is a valid JSON string value and the MCP protocol has no reason to sanitize it.
Evidence
We built integration tests (ASP.NET TestServer + MCP SDK v0.5.0-preview.1) that prove the MCP SDK itself preserves HTML correctly through client→HTTP→server→parameter binding:
McpSdk_PreservesHtmlInStringParameters— HTML tags preservedMcpSdk_PreservesComplexHtmlWithEntities— entities and code blocks preservedMcpSdk_PreservesHtmlWhenPassedAsJsonElement— boxed JsonElement values preservedMcpSdk_PreservesMultiLineHtml— multi-line HTML preservedAll tests pass, confirming the issue is upstream of the MCP server — in the Copilot CLI's tool call parameter serialization layer.
We also verified the Fleet MCP Gateway proxy layer (which converts
JsonElement→objectand forwards to the MCP server) preserves HTML with 7 additional unit tests.Impact
Any MCP tool that needs to pass HTML or structured markup in string parameters is affected. In our case, Azure DevOps work item descriptions (which natively support HTML) are always created as unformatted plain text, requiring a REST API workaround to set them properly.
Workaround
Bypass the MCP tool for HTML-bearing fields and use direct REST API calls instead (two-step: create via MCP, then patch description via REST).
Environment