You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An MCP tool's published metadata can change while an approval is pending. Revalidate that metadata before invoking the approved tool, and request a new approval when it has changed.
Description & Review Guide
What are the major changes? Request consent before discovery, then request a separate tool approval bound to a canonical fingerprint of its published definition. Revalidate before invocation and reissue approval when the definition changes. Serialize the protocol tool metadata, including annotations and _meta.
What is the impact of these changes? Approval-gated tool calls now require discovery consent followed by tool approval; tools/list itself needs only discovery consent. Configured headers are not sent before discovery consent. Handlers must return a structured tool list with complete SDK-supported definitions, or approval fails closed. Older checkpoints restart discovery approval. Refreshed requests do not embed the definition; comparison covers published metadata, not the server implementation's identity or changes between discovery and invocation.
What do you want reviewers to focus on? The two-stage consent and restored-checkpoint behavior, handler compatibility, and metadata comparison.
Validation with the locally installed .NET SDK 10.0.403:
dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests -f net10.0 --no-restore: passed (1,388 tests).
dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests -f net10.0 --no-restore: passed (58 tests).
dotnet build src\Microsoft.Agents.AI.Workflows.Declarative.Mcp --no-restore --tl:off: passed for all targeted frameworks, including netstandard2.0 and net472 (zero warnings and errors).
dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests -f net472 --no-restore --filter-query "/*/Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel/InvokeMcpToolExecutorTest/*": passed (101 tests, on .NET Framework 4.8.1).
dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests -f net472 --no-restore: passed (58 tests, on .NET Framework 4.8.1).
dotnet format src\Microsoft.Agents.AI.Workflows.Declarative --no-restore --include src\Microsoft.Agents.AI.Workflows.Declarative\ObjectModel\InvokeMcpToolExecutor.cs src\Microsoft.Agents.AI.Workflows.Declarative\IMcpToolHandler.cs --verbosity minimal: passed.
dotnet format src\Microsoft.Agents.AI.Workflows.Declarative.Mcp --no-restore --include src\Microsoft.Agents.AI.Workflows.Declarative.Mcp\DefaultMcpToolHandler.cs --verbosity minimal: passed.
dotnet format tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests --no-restore --include tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests\ObjectModel\InvokeMcpToolExecutorTest.cs --verbosity minimal: passed.
dotnet format tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests --no-restore --include tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests\DefaultMcpToolHandlerTests.cs --verbosity minimal: passed.
Full-solution tests were not run.
Related Issue
N/A - maintainer-directed change; no linked issue.
AI Assistance
No material AI assistance was used.
This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.
AI assistance details: implementation, tests, documentation, and PR description.
Contribution Checklist
The code builds clean without any errors or warnings
All unit tests pass, and I have added new tests where possible
This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The default handler omits annotations from the metadata used for fingerprinting, allowing a tool to change from read-only to destructive without invalidating pending approval.
This PR adds metadata revalidation to approval-gated MCP tool calls in .NET declarative workflows, preventing pending approvals from being reused when discovered tool definitions change.
Changes:
Persist tool-definition fingerprints and compare them before approved invocation.
Request fresh approval for changed metadata or legacy snapshots without fingerprints, and fail closed when discovery cannot verify the tool.
Document the handler discovery requirement and expand approval and checkpoint tests.
The reason will be displayed to describe this comment to others. Learn more.
MAF Automated Review — Iteration 1
Result: Findings reported Scope: full PR (1 commit(s)): 927bbe96c1be Model:gpt-5.6-sol
Overview
The change snapshots a tool-definition fingerprint and revalidates it before invoking an approved MCP tool, with strong fail-closed handling for missing, malformed, ambiguous, legacy, and changed definitions. Pending-response matching, replay prevention, header redaction, and restore-time reapproval provide useful guardrails. The implementation nevertheless breaks legacy target builds, sends configured credentials before approval, permits incomplete tool representations to bypass metadata-change detection, and compares JSON representation rather than semantic metadata.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
4 verified findings remained after source verification (3 high, 1 medium) across 2 files. Details are attached to the affected lines below.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Name-only tool definitions can receive fingerprints and authorize invocation without an inputSchema, violating the required fail-closed validation contract.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Restoring between approvals can indefinitely restart tool discovery when workflow headers are configured, and WorkflowSession omits the discovery explanation and changed-definition warning from delivered approval content.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Restore workflow approval state across discovery consent and invocation
With workflow headers configured, restoring between discovery consent and the new invocation approval clears _approvalHeaderSnapshots, so approving the tool restarts discovery instead of invoking it. Hosts such as WorkflowSession that restore on every turn repeat this indefinitely. Make the two-stage flow resume safely without persisting credentials, and add a regression that restores before each approval response.
Include discovery notices in delivered approval content
When consumed through WorkflowSession, these sibling notices are omitted from the delivered approval content because ExternalInputRequest.GetInnerRequestContent() selects only ToolApprovalRequestContent. Approval consumers therefore lose the discovery explanation and changed-definition warning. Preserve the accompanying text through the approval delivery contract and add a regression at the WorkflowSession boundary.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
breaking changeUsage: [PRs], Target: all PRs that introduce changes that are not backward compatibledocumentationUsage: [Issues, PRs], Target: documentation in the code base and learn docs.NETUsage: [Issues, PRs], Target: .NetworkflowsUsage: [Issues, PRs], Target: Workflows
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
An MCP tool's published metadata can change while an approval is pending. Revalidate that metadata before invoking the approved tool, and request a new approval when it has changed.
Description & Review Guide
_meta.tools/listitself needs only discovery consent. Configured headers are not sent before discovery consent. Handlers must return a structured tool list with complete SDK-supported definitions, or approval fails closed. Older checkpoints restart discovery approval. Refreshed requests do not embed the definition; comparison covers published metadata, not the server implementation's identity or changes between discovery and invocation.Validation with the locally installed .NET SDK 10.0.403:
dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests -f net10.0 --no-restore: passed (1,388 tests).dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests -f net10.0 --no-restore: passed (58 tests).dotnet build src\Microsoft.Agents.AI.Workflows.Declarative.Mcp --no-restore --tl:off: passed for all targeted frameworks, includingnetstandard2.0andnet472(zero warnings and errors).dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests -f net472 --no-restore --filter-query "/*/Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel/InvokeMcpToolExecutorTest/*": passed (101 tests, on .NET Framework 4.8.1).dotnet test --project tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests -f net472 --no-restore: passed (58 tests, on .NET Framework 4.8.1).dotnet format src\Microsoft.Agents.AI.Workflows.Declarative --no-restore --include src\Microsoft.Agents.AI.Workflows.Declarative\ObjectModel\InvokeMcpToolExecutor.cs src\Microsoft.Agents.AI.Workflows.Declarative\IMcpToolHandler.cs --verbosity minimal: passed.dotnet format src\Microsoft.Agents.AI.Workflows.Declarative.Mcp --no-restore --include src\Microsoft.Agents.AI.Workflows.Declarative.Mcp\DefaultMcpToolHandler.cs --verbosity minimal: passed.dotnet format tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests --no-restore --include tests\Microsoft.Agents.AI.Workflows.Declarative.UnitTests\ObjectModel\InvokeMcpToolExecutorTest.cs --verbosity minimal: passed.dotnet format tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests --no-restore --include tests\Microsoft.Agents.AI.Workflows.Declarative.Mcp.UnitTests\DefaultMcpToolHandlerTests.cs --verbosity minimal: passed.Full-solution tests were not run.
Related Issue
N/A - maintainer-directed change; no linked issue.
AI Assistance
AI assistance details: implementation, tests, documentation, and PR description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.