Skip to content

Explicitly reject unknown tool call parameters - #3282

Merged
Alan Zimmer (alzimmermsft) merged 8 commits into
microsoft:mainfrom
alzimmermsft:PreventAdditionalProperties
Aug 17, 2026
Merged

Alan Zimmer (alzimmermsft) merged 8 commits into
microsoft:mainfrom
alzimmermsft:PreventAdditionalProperties

Conversation

@alzimmermsft

@alzimmermsft Alan Zimmer (alzimmermsft) commented Aug 13, 2026 •

Copy link
Copy Markdown
Member

What does this PR do?

Tool calls with unknown parameters are now explicitly rejected, rather than implicitly dropping unknown parameters.

After enforcing unknown parameters to be an error a few bugs were found and fixed:

  • Many tests were using invalid or incorrect parameter names, those have been fixed to remove invalid parameter usage and to update incorrect parameter names.

GitHub issue number?

[Link to the GitHub issue this PR addresses]

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Created a changelog entry if the change falls among the following: new feature, bug fix, UI/UX update, breaking change, or updated dependencies. Follow the changelog entry guide
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes running the script ./eng/scripts/Process-PackageReadMe.ps1. See Package README
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For tools with new names, including new tools or renamed tools, update consolidated-tools.json
    • For renamed tools, follow the Tool Rename Checklist and tag the PR with the breaking-change label
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated command list in servers/Azure.Mcp.Server/docs/azmcp-commands.md
    • Ran ./eng/scripts/Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • Updated test prompts in servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR changes the MCP tool-call argument parsing behavior so that unknown/unsupported parameters are explicitly rejected instead of being silently ignored, and updates test coverage + changelog entries to reflect the breaking change.

Changes:

  • Updated CommandExtensions.ParseFromDictionary to detect unknown keys and reject requests.
  • Consolidated/expanded parsing tests under Microsoft.Mcp.Core.Tests (and removed the now-redundant Azure core test file).
  • Added breaking-change changelog entries for both Azure and Fabric servers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
servers/Fabric.Mcp.Server/changelog-entries/1786656227003.yaml Adds a Fabric server changelog entry documenting the breaking change.
servers/Azure.Mcp.Server/changelog-entries/1786656221076.yaml Adds an Azure server changelog entry documenting the breaking change.
core/Microsoft.Mcp.Core/src/Commands/CommandExtensions.cs Implements unknown-parameter rejection in dictionary-based command parsing.
core/Microsoft.Mcp.Core/tests/Microsoft.Mcp.Core.Tests/Areas/Server/Commands/CommandExtensionsTests.cs Expands parsing tests and adds coverage for invalid-key rejection.
core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Commands/Extensions/CommandExtensionsTests.cs Removes duplicate tests now covered in Microsoft.Mcp.Core.Tests.
Suppressed comments (1)

core/Microsoft.Mcp.Core/tests/Microsoft.Mcp.Core.Tests/Areas/Server/Commands/CommandExtensionsTests.cs:382

  • Same issue here: // Assert is appended to the end of the Act line, making the test harder to scan and maintain.
        // Act
        var result = command.ParseFromRawMcpToolInput(arguments);        // Assert
        Assert.NotNull(result);
        Assert.Empty(result.Errors);
        Assert.Equal("{\"name\":\"abc\",\"path\":\"123\"}", result.GetValue(scriptOption));

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@g2vinay Vinay Gera (g2vinay) left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Leaving my comment in-line

@g2vinay Vinay Gera (g2vinay) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Follow up review.

@alzimmermsft

Copy link
Copy Markdown
Member Author

/azp run mcp - pullrequest

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@alzimmermsft
Alan Zimmer (alzimmermsft) merged commit f76110f into microsoft:main Aug 17, 2026
18 of 19 checks passed
@alzimmermsft
Alan Zimmer (alzimmermsft) deleted the PreventAdditionalProperties branch August 17, 2026 21:07
Steven Vukelich (vukelich) added a commit that referenced this pull request Oct 12, 2026
…olution SSRF protections. Introduce IEndpointValidator for improved unit testing and parallel test execution. Update documentation accordingly.

And a bunch of follow up squashed commits below...

Fix Fabric test compilation errors

Remove added difficulty around ServiceStartCommand testing.

Slight tinkering to HttpClientFactoryConfigurator.

Fix using sorting in NamespaceUpdateCommandTests.cs

Fix Speech live test regression caused by #3282.

Stabilize LoopbackHttpServer on macOS.

Application of IP address vs DefaultProxy is now calculated per-request due to dynamic nature of DefaultProxy, PACs, etc. Also other PR feedback.

More doc updates for using a proxy vs not and IP address filtering applied.

Remove NoSsrfClientName and disable auto-redirect for _all_ HttpClient instances of DI.

Enable NO_PROXY to hit the IP address filtering logic just like if a system/PAC proxy allows for bypassing a destination.

Clarify known limitation around a system-level dynamic proxies that change bypassing answers mid-request.

Fix networking unit tests by adding explicit proxy in DI. CI builds were picking up proxy setting from the host machine which prevented code paths related to our IP address filtering tests.
Vinay Gera (g2vinay) added a commit that referenced this pull request Oct 12, 2026
…olution SSRF protections. (#3884)

* Add URL validation for all ArmClient uses and add DNS->IP address resolution SSRF protections. Introduce IEndpointValidator for improved unit testing and parallel test execution. Update documentation accordingly.

And a bunch of follow up squashed commits below...

Fix Fabric test compilation errors

Remove added difficulty around ServiceStartCommand testing.

Slight tinkering to HttpClientFactoryConfigurator.

Fix using sorting in NamespaceUpdateCommandTests.cs

Fix Speech live test regression caused by #3282.

Stabilize LoopbackHttpServer on macOS.

Application of IP address vs DefaultProxy is now calculated per-request due to dynamic nature of DefaultProxy, PACs, etc. Also other PR feedback.

More doc updates for using a proxy vs not and IP address filtering applied.

Remove NoSsrfClientName and disable auto-redirect for _all_ HttpClient instances of DI.

Enable NO_PROXY to hit the IP address filtering logic just like if a system/PAC proxy allows for bypassing a destination.

Clarify known limitation around a system-level dynamic proxies that change bypassing answers mid-request.

Fix networking unit tests by adding explicit proxy in DI. CI builds were picking up proxy setting from the host machine which prevented code paths related to our IP address filtering tests.

* Fix spelling error in FabricCoreSetupTests comment (rquests -> requests)

---------

Co-authored-by: Vinay Gera <vigera@microsoft.com>
msalaman added a commit that referenced this pull request Oct 12, 2026
* Fix advisor remediation deserialization for double version (#3880)

* Update export tool discovery description for Azure Terraform tools (#3737)

* fix(azureterraform): clarify export tool discovery

Make export intent visible in namespace and individual tool descriptions while preserving local command generation. Cover discovery, routing, provider forwarding, installation help, and HTTP restrictions with regression tests.

Disambiguate tools that competed for the same prompts by keying each description on its distinguishing selection signal. The aztfexport resource tool leads with the full Azure resource ID shape and states it exports only that resource, while the resourcegroup tool keys on a named resource group. The azurerm and azapi documentation tools state that they read reference documentation rather than querying live Azure resources, and identify their inputs by the azurerm_ prefix and the ARM namespace format respectively. The conftest workspace and plan tools distinguish a folder of Terraform .tf source files from an already generated tfplan.json.

Validated with the tool description evaluator against the azureterraform prompts, which improved top-choice selection from 70.0% to 93.3%, with all prompts remaining above the 0.40 confidence bar.

Add a checked-in Vally specification covering the prompts reported in the issue plus the tool pairs that compete for similar prompts. The conftest prompts in e2eTestPrompts.md are marked context-required and are therefore skipped by generated specifications, so the checked-in specification is the only Vally coverage for them.

Pin the disambiguating phrases with unit tests so that rewording a description cannot silently regress tool selection.

Addresses #3553

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Clarify AzAPI docs API version wording

Replace the ambiguous 'optionally for a specific API version' phrase with an explicit statement that the tool returns the latest stable API version schema unless a specific API version is requested.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add read-only core_get-item tool (#3701)

* feat(fabric): add read-only core get-item tool

## Summary
Add core_get-item to retrieve generic Fabric item metadata using known workspace and item IDs. Include input validation, typed results, safe retry guidance, registration, tests, documentation, prompts, and a changelog entry.

## Prompting Intent
The contributor requested one focused Fabric MCP tool, aligned with existing repository patterns, with no item data or definition access and no authentication changes. Preserve the existing creation and catalog-search behavior, address review findings, and submit a draft PR with incomplete validation explicitly identified.

## Linked Sources
- Fabric Get Item API: https://learn.microsoft.com/rest/api/fabric/core/items/get-item
- Contribution guide: https://github.com/microsoft/mcp/blob/main/CONTRIBUTING.md
- Command options guide: https://github.com/microsoft/mcp/blob/main/docs/option-conversion.md
- Recorded test guide: https://github.com/microsoft/mcp/blob/main/docs/recorded-tests.md
- Description evaluator: https://github.com/microsoft/mcp/blob/main/eng/tools/ToolDescriptionEvaluator/Quickstart.md
- Fabric test infrastructure: #3686

## Rationale
Keep string service inputs consistent with existing Core operations while validating and normalizing UUIDs before authentication. Use a dedicated metadata projection so definitions and workload-specific fields cannot leak into the result. Factor HTTP sending only to let the new read inspect status and Retry-After while preserving existing create/search handling. Use source-generated JSON and the shared MCP loader rather than another schema or execution path. Keep backend bodies out of errors and validate the registered tool with offline HTTP and credential substitutes.

All 118 Core tests, owning-project formatting, the Fabric host build, XML documentation compilation, and spelling passed. Native validation and bounded manual live reads also passed before the documentation-only follow-up. Description scoring and the required Fabric integration coverage remain pending maintainer coordination.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(ci): keep tool catalog stderr out of JSON

## Summary
Stop merging native stderr into the JSON consumed by the tool-selection prompt validator. Add four Pester regression tests for stdout parsing, visible stderr diagnostics, and rejection of invalid or contaminated stdout.

## Prompting Intent
The contributor asked to fix the failed Analyze check in PR #3701 and update the existing PR. Keep the change limited to the validator and regression coverage, preserve strict prompt validation, and do not change the Fabric tool or suppress validation errors.

## Linked Sources
- PR: #3701
- Failing Analyze check: https://github.com/microsoft/mcp/runs/105130046877
- Validator: https://github.com/microsoft/mcp/blob/3acf0c58036a14e9be308898153053fc98a33019/eng/scripts/Test-ToolSelectionPrompts.ps1

## Rationale
Fabric correctly writes its tool catalog to stdout and startup diagnostics to stderr. The validator's merged capture made valid JSON unparseable. Removing the redirection preserves diagnostics and existing exit handling while parsing only stdout. The regression tests execute the actual capture and parse statements rather than a duplicate implementation.

All four Pester tests passed. Build-Local.ps1 -ServerName Fabric.Mcp.Server -VerifyNpx passed in a non-interactive process. The full Fabric prompt validator passed with 49 tools, one server tested, zero skips, and zero violations. The negative check still rejected prompts for tools outside the Fabric catalog. Spelling and whitespace checks passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add read-only core_get-workspace tool

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add read-only core_list-workspaces tool

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add read-only core_list-items tool

Add paginated workspace and folder inventory with typed metadata, safe continuation encoding, and sanitized failures. Cover the command, service, MCP pipeline, and local discovery without live Fabric requests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add core_create-workspace with capacity support

Create Fabric workspaces in one synchronous request with optional capacity and domain assignment, typed metadata, guarded inputs, sanitized errors, and offline coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add core_update-workspace tool

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add core_update-item tool

Add validated metadata-only item updates with omitted and empty description semantics, source-generated output, and offline command/service/MCP coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add core_delete-item with explicit hard-delete opt-in

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* feat(fabric): add core_delete-workspace tool

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add submit-only Fabric workspace capacity assignment

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Format assignment registration coverage

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(fabric): preserve create and catalog search HTTP errors

Preserve response status in EnsureSuccessAsync and add operation-local HTTP guidance without changing shared error handling, result shapes, or retries. Cover service and command regressions, update old status-loss assertions, and add a Fabric bug-fix changelog entry.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(fabric): sanitize errors and validate creation and paging

Sanitize Create Item and Catalog Search public errors without changing status mappings or success contracts. Validate workspace UUIDs with the compatible alias, reject mixed catalog continuation criteria, document verified requirements, and correct Update Item error punctuation. Cover serialized Debug/Release errors and command/service validation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(fabric): honor workspace contracts and deletion safety

Make workspace type optional across get, list, create, and update; retain configured HTTP transports while disabling automatic redirects; preserve confirmed delete responses during late cancellation and improve upstream 400 guidance. Correct all 23 invalid prompt interaction cells without changing 37 prompts, and add regression coverage and documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(fabric): share sanitized errors and retain missing-option guidance

Report only registered required option names for Create Item validation failures while keeping parser details private. Centralize null exception results in an AOT-safe Fabric command base and consolidate five identical throttling exceptions without changing operation-specific errors, retry contracts, or deletion modes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(fabric): sanitize shared Core parser errors

Sanitize structured parser failures after the framework handler while preserving required-option guidance and command-specific overrides. Cover real Boolean binding, unknown options, required-name allowlisting, and blank workspace-name parser failures without changing services or legacy creation behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(fabric): centralize Core catalog expectations

Keep one independent expected catalog for exact command and MCP discovery, read-only membership, singleton registration, and schema consistency. Preserve operation-specific tests while removing unrelated catalog copies and fragile host totals. Cover missing, extra, duplicate, and misclassified entries in both catalog modes and document the one-entry workflow for future tools.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Amos Hersch <amhersch@microsoft.com>

* Add Fabric LRO tracking and bounded Create Item polling (#3892)

Add Fabric operation-state and operation-result tools, shared hybrid LRO handling, and optional bounded Create Item polling.

Keep a 120-second default with a server-enforced 600-second maximum, resumable receipts, and no automatic resubmission of the initiating mutation. Integrate the merged Get Item tooling and centralized catalog coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Update Fabric REST API specifications and item definition documentation (#3914)

* Refresh Fabric static resources with a reusable updater

Refresh pinned REST API specifications and item-definition articles, preserve source bytes and attribution, and add a guarded two-step manual refresh with focused regression coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Remove generated Fabric resource metadata

Keep source revisions in refresh results and required attribution in the existing Docs README. Stop embedding license and source manifests without changing API specifications or article content.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Limit Fabric refresh PR to updated resources

Remove repository maintenance tooling and restore baseline attributes and tests. Exclude the legacy Ontology article while preserving all remaining resource blobs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add URL validation for all ArmClient uses and add DNS->IP address resolution SSRF protections. (#3884)

* Add URL validation for all ArmClient uses and add DNS->IP address resolution SSRF protections. Introduce IEndpointValidator for improved unit testing and parallel test execution. Update documentation accordingly.

And a bunch of follow up squashed commits below...

Fix Fabric test compilation errors

Remove added difficulty around ServiceStartCommand testing.

Slight tinkering to HttpClientFactoryConfigurator.

Fix using sorting in NamespaceUpdateCommandTests.cs

Fix Speech live test regression caused by #3282.

Stabilize LoopbackHttpServer on macOS.

Application of IP address vs DefaultProxy is now calculated per-request due to dynamic nature of DefaultProxy, PACs, etc. Also other PR feedback.

More doc updates for using a proxy vs not and IP address filtering applied.

Remove NoSsrfClientName and disable auto-redirect for _all_ HttpClient instances of DI.

Enable NO_PROXY to hit the IP address filtering logic just like if a system/PAC proxy allows for bypassing a destination.

Clarify known limitation around a system-level dynamic proxies that change bypassing answers mid-request.

Fix networking unit tests by adding explicit proxy in DI. CI builds were picking up proxy setting from the host machine which prevented code paths related to our IP address filtering tests.

* Fix spelling error in FabricCoreSetupTests comment (rquests -> requests)

---------

Co-authored-by: Vinay Gera <vigera@microsoft.com>

* Sync skill references from GitHub-Copilot-for-Azure (#3901)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Sync eng/common directory with azure-sdk-tools for PR 17165 (#3919)

* Remove only the DevOps release work item update functionality

---------

Co-authored-by: Jigyasa Chopra <83654498+jigyasachopra742@users.noreply.github.com>
Co-authored-by: Yun Liu <17947406+liuwuliuyun@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Hasan Abo-Shally <HasanAboShally@gmail.com>
Co-authored-by: Amos Hersch <amhersch@microsoft.com>
Co-authored-by: Amos Hersch <39293413+AmosHersch@users.noreply.github.com>
Co-authored-by: Steven Vukelich <svukel@microsoft.com>
Co-authored-by: Vinay Gera <vigera@microsoft.com>
Co-authored-by: ghcp4a-bot[bot] <288718659+ghcp4a-bot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: azure-sdk-automation[bot] <191533747+azure-sdk-automation[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

server-Azure.Mcp Azure.Mcp.Server server-Fabric.Mcp Microsoft Fabric MCP Server

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants