Add x-ms-usermessage header to MCP tools/call requests#217
Add x-ms-usermessage header to MCP tools/call requests#217akashjindal123 wants to merge 3 commits intomainfrom
Conversation
Pass the user's original message as an HTTP header during MCP tool execution, matching the .NET implementation in HttpContextHeadersHandler.SanitizeTextForHeader(). The header is added centrally in Utility.GetToolRequestHeaders() with ASCII-safe sanitization (diacritics removal, smart punctuation conversion, whitespace normalization). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@akashjindal123 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
There was a problem hiding this comment.
Pull request overview
This PR adds propagation of the user’s original message to MCP-related HTTP requests via a new x-ms-usermessage header, with ASCII-safe sanitization to make the value safe for transport as an HTTP header.
Changes:
- Add
x-ms-usermessageheader generation toUtility.GetToolRequestHeaders(). - Implement
Utility.sanitizeTextForHeader()to normalize/sanitize user text for header safety. - Add Jest coverage validating header presence/absence and sanitization behaviors.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tests/tooling/utility.test.ts | Adds unit tests covering x-ms-usermessage header behavior and sanitization outcomes. |
| packages/agents-a365-tooling/src/Utility.ts | Adds the new header constant, wires header injection into GetToolRequestHeaders(), and introduces sanitization helper. |
|
|
||
| const userMessage = turnContext?.activity?.text as string | undefined; | ||
| if (userMessage) { | ||
| headers[Utility.HEADER_USER_MESSAGE] = Utility.sanitizeTextForHeader(userMessage); |
There was a problem hiding this comment.
GetToolRequestHeaders sets x-ms-usermessage whenever activity.text is truthy, but sanitizeTextForHeader() can return an empty string (e.g., whitespace-only input or strings that sanitize down to nothing). This will send an empty header value; instead, compute the sanitized value first and only add the header when the sanitized result is non-empty.
| headers[Utility.HEADER_USER_MESSAGE] = Utility.sanitizeTextForHeader(userMessage); | |
| const sanitizedUserMessage = Utility.sanitizeTextForHeader(userMessage); | |
| if (sanitizedUserMessage) { | |
| headers[Utility.HEADER_USER_MESSAGE] = sanitizedUserMessage; | |
| } |
|
|
||
| return result; | ||
| } catch { | ||
| return input; |
There was a problem hiding this comment.
The catch clause in sanitizeTextForHeader() returns the original input, which can violate the method’s own contract/documentation (“ASCII-safe text suitable for HTTP header values”). If an error occurs, prefer returning a conservative sanitized fallback (e.g., strip/replace non-ASCII/control chars and collapse whitespace) or omit the header entirely, rather than returning unsanitized text.
| return input; | |
| // Conservative fallback: avoid returning unsanitized text if normalization fails. | |
| return input | |
| .replace(/[\u00A0\u202F]/g, ' ') | |
| .replace(/[^\x20-\x7E]/g, ' ') | |
| .replace(/\s+/g, ' ') | |
| .trim(); |
| const userMessage = turnContext?.activity?.text as string | undefined; | ||
| if (userMessage) { | ||
| headers[Utility.HEADER_USER_MESSAGE] = Utility.sanitizeTextForHeader(userMessage); | ||
| } |
There was a problem hiding this comment.
PR description says the header is added to MCP tools/call requests, but this implementation adds x-ms-usermessage for any request that uses Utility.GetToolRequestHeaders() (including tooling gateway discovery and chat history calls). If the intent is truly scoped to tool execution, consider gating this behind an explicit ToolOptions flag (or a dedicated header builder for tool calls) or update the PR description to reflect the broader behavior.
Summary
x-ms-usermessageHTTP header to MCPtools/callrequests, passing the user's original message to MCP servers during tool executionUtility.sanitizeTextForHeader(), matching the .NETHttpContextHeadersHandler.SanitizeTextForHeader()implementation (diacritics removal, smart punctuation conversion, non-breaking space normalization, whitespace collapsing)Utility.GetToolRequestHeaders()— zero changes needed in Claude, OpenAI, or LangChain extension packagesTest plan
pnpm build— clean compilation across all packagespnpm test— all 1061 tests pass (56 suites)🤖 Generated with Claude Code