Skip to content

Python: Updating MCP endpoint parameters to use snake case#3543

Open
gavin-aguiar wants to merge 1 commit intomainfrom
gaaguiar/mcp_case_fix
Open

Python: Updating MCP endpoint parameters to use snake case#3543
gavin-aguiar wants to merge 1 commit intomainfrom
gaaguiar/mcp_case_fix

Conversation

@gavin-aguiar
Copy link
Copy Markdown
Contributor

Motivation and Context

Fixes: #3031

Description

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

@gavin-aguiar gavin-aguiar requested a review from a team as a code owner January 30, 2026 21:40
Copilot AI review requested due to automatic review settings January 30, 2026 21:40
@github-actions github-actions Bot changed the title Updating MCP endpoint parameters to use snake case Python: Updating MCP endpoint parameters to use snake case Jan 30, 2026
@markwallace-microsoft
Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/azurefunctions/agent_framework_azurefunctions
   _app.py3688576%202–203, 208–209, 320–321, 429, 437–438, 458–460, 466–468, 474–476, 509–510, 570–571, 620–621, 626, 708, 711, 720–722, 724–726, 728, 730, 741, 743–746, 748, 750–751, 753, 760–761, 763–764, 766–767, 769, 773, 783–785, 787–788, 790–792, 799, 801–802, 804, 825, 830, 842, 917, 927, 934–936, 981, 995, 1006–1008, 1010–1013, 1038, 1045, 1047, 1050
TOTAL16249202487% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
3720 221 💤 0 ❌ 0 🔥 1m 7s ⏱️

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Azure Functions MCP tool trigger to use snake_case for the thread identifier parameter, aligning MCP parameter naming with other endpoints and addressing #3031.

Changes:

  • Renamed MCP tool parameter from threadId to thread_id in the MCP tool properties schema.
  • Updated MCP invocation handling to read thread_id from the MCP context arguments.
  • Updated unit tests to send thread_id in MCP invocation contexts.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
python/packages/azurefunctions/agent_framework_azurefunctions/_app.py Changes MCP tool schema + argument parsing to use thread_id instead of threadId.
python/packages/azurefunctions/tests/test_app.py Updates MCP tool invocation tests to pass thread_id.

Comment on lines +613 to +614
# Extract optional thread_id
thread_id = arguments.get("thread_id")
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching the MCP argument name from threadId to thread_id means existing MCP clients still sending threadId will silently lose conversation continuity (a breaking API behavior change). Consider accepting both keys during a transition period (e.g., read thread_id and fall back to threadId, optionally with a deprecation warning), or explicitly mark/document this as a breaking change for consumers.

Suggested change
# Extract optional thread_id
thread_id = arguments.get("thread_id")
# Extract optional thread_id (prefer snake_case, but support legacy camelCase 'threadId')
thread_id = arguments.get("thread_id")
if thread_id is None:
legacy_thread_id = arguments.get("threadId")
if legacy_thread_id is not None:
logger.warning(
"MCP argument 'threadId' is deprecated; please use 'thread_id' instead."
)
thread_id = legacy_thread_id

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@sphenry sphenry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 92%

✓ Correctness

This PR consistently renames the MCP tool property from camelCase threadId to snake_case thread_id across the property definition, argument extraction, comments/docstrings, and all relevant tests. The change is complete within the affected scope — all 4 occurrences in the source file and all 4 test references are updated in lockstep. No correctness bugs are introduced.

✓ Security Reliability

This PR renames the MCP tool property from threadId (camelCase) to thread_id (snake_case), aligning it with the HTTP endpoint convention already used elsewhere in the codebase (e.g., line 718). The change is purely a rename across the tool property schema definition, the argument extraction in _handle_mcp_tool_invocation, and all corresponding tests. No security or reliability issues are introduced: input validation logic, JSON parsing, error handling, and session ID creation remain unchanged. The rename is consistent and complete across all modified files.

✓ Test Coverage

This PR renames the MCP tool property from threadId (camelCase) to thread_id (snake_case) in the property definition, docstring, and argument extraction, with corresponding test updates. All four existing tests that pass threadId in the MCP context payload are correctly updated to use thread_id. However, the test test_setup_mcp_tool_trigger_registers_decorators uses ANY for tool_properties, so it does not actually verify the property name rename in the MCP tool definition. Additionally, there is no backward-compatibility test verifying behavior when a client sends the old threadId key (which would silently fall back to generating a new session ID).

✗ Design Approach

The diff renames the MCP tool property from threadId (camelCase) to thread_id (snake_case) in three places: the external tool_properties definition, the internal arguments.get() lookup, and the tests. The internal Python variable name thread_id is fine and consistent with the rest of the codebase, but the change also renames the externally-advertised propertyName in the MCP tool schema from "threadId" to "thread_id". This conflates internal Python naming conventions with the external MCP interface contract. The propertyName field in tool_properties is what gets sent to Azure Functions MCP trigger and ultimately what MCP clients must pass as argument names — it is a public API. Changing it is a breaking change for any existing MCP client already sending threadId, and it deviates from JSON/MCP's conventional camelCase naming. The internal arguments.get() key must match whatever propertyName the schema declares, so these two must always stay in sync; changing both together without acknowledging the external breakage is the root design problem.


Automated review by sphenry's agents

@@ -536,7 +536,7 @@ def _setup_mcp_tool_trigger(self, agent_name: str, agent_description: str | None
"isArray": False,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

propertyName is the external MCP tool schema field that MCP clients must pass as an argument key. Changing it from "threadId" to "thread_id" breaks existing callers and diverges from JSON/MCP camelCase conventions. Keep this as "threadId" and update arguments.get() to match (arguments.get("threadId")). The Python local variable can remain thread_id regardless.

Suggested change
"isArray": False,
"propertyName": "threadId",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Modify MCP endpoint to use snake_case for parameters

4 participants