Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 12, 2026

Takes over #7104 and augments it by making McpServerToolCallContent and McpServerToolResultContent inherit from FunctionCallContent and FunctionResultContent respectively, enabling unified approval handling for both regular functions and MCP server tools.

Changes

Core type hierarchy

  • Unsealed FunctionCallContent and FunctionResultContent to allow inheritance
  • McpServerToolCallContent extends FunctionCallContent, adding ServerName property (uses base Arguments property directly)
  • McpServerToolResultContent extends FunctionResultContent (uses base Result property directly)

Unified approval types (from #7104)

  • FunctionApprovalRequestContent accepts FunctionCallContent via FunctionCall property
  • FunctionApprovalResponseContent accepts FunctionCallContent via FunctionCall property
  • Deleted McpServerToolApprovalRequestContent and McpServerToolApprovalResponseContent

Client updates

  • FunctionInvokingChatClient: Direct access to FunctionCall property
  • OpenAIResponsesChatClient: Reordered switch cases (derived types before base types to avoid unreachable code)
  • Simplified idToContentMapping to use Dictionary<string, McpServerToolCallContent>

Breaking Changes

  • McpServerToolCallContent.Arguments changed from IReadOnlyDictionary<string, object?> to IDictionary<string, object?>
  • McpServerToolResultContent now uses Result property instead of Output

Compatibility

  • Added CP0008 suppressions for unsealing across all target frameworks

Tests

Example

// Before: Separate approval types for MCP and functions
var mcpApproval = new McpServerToolApprovalRequestContent(id, mcpToolCall);
var funcApproval = new FunctionApprovalRequestContent(id, functionCall);

// After: Unified approval type works with both
var mcpApproval = new FunctionApprovalRequestContent(id, mcpToolCall);  // mcpToolCall is FunctionCallContent
var funcApproval = new FunctionApprovalRequestContent(id, functionCall);
Original prompt

Can you take over #7104, augment it with implementing McpServerToolCallContent and McpServerToolResultContent by unsealing and extending FunctionCallContent and FunctionResultContent, add the necessary compatibility suppressions, update the branch and resolve conflicts.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Microsoft Reviewers: Open in CodeFlow

Copilot AI and others added 6 commits January 12, 2026 19:11
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
…ew approval types

Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
…ypes

Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement McpServerToolCallContent and McpServerToolResultContent Unseal FunctionCallContent/FunctionResultContent; make MCP types extend them Jan 12, 2026
Copilot AI requested a review from jozkee January 12, 2026 19:39
Copy link
Member

@jozkee jozkee left a comment

Choose a reason for hiding this comment

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

@copilot please fix errors and address feedback.

/// Gets the call content that pre-invoke approval is required for.
/// </summary>
public FunctionCallContent FunctionCall { get; }
public AIContent CallContent { get; }
Copy link
Member

Choose a reason for hiding this comment

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

CallContent can go back to be FunctionCallContent FunctionCall.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Changed CallContent back to FunctionCallContent FunctionCall.

/// Gets the call content for which approval was requested.
/// </summary>
public FunctionCallContent FunctionCall { get; }
public AIContent CallContent { get; }
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Changed CallContent back to FunctionCallContent FunctionCall.

/// </summary>
public IReadOnlyDictionary<string, object?>? Arguments { get; set; }
[JsonIgnore]
public new IReadOnlyDictionary<string, object?>? Arguments
Copy link
Member

Choose a reason for hiding this comment

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

instead of adding a new property, let's use the one in base, let's take the breaking change of switching from IReadOnlyDictionary<string, object?>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Removed the new property and using base class Arguments property directly (breaking change from IReadOnlyDictionary to IDictionary accepted).

Comment on lines 36 to 41
[JsonIgnore]
public IList<AIContent>? Output
{
get => Result as IList<AIContent>;
set => Result = value;
}
Copy link
Member

Choose a reason for hiding this comment

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

Let's take the breaking change and use base.Result instead of Output and update the call sites as needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Removed Output property and using base.Result instead (breaking change accepted). Updated all call sites in commits 29454f9.

Comment on lines 220 to 223
case McpToolCallApprovalResponseItem mtcari:
message.Contents.Add(new McpServerToolApprovalResponseContent(mtcari.ApprovalRequestId, mtcari.Approved) { RawRepresentation = mtcari });
// Approval responses are processed separately when converting tool messages (see ConvertToResponseItems).
// They are not included in assistant message contents.
break;
Copy link
Member

Choose a reason for hiding this comment

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

This should be removed and let the code use the default case for McpToolCallApprovalResponseItem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Removed the case for McpToolCallApprovalResponseItem and letting it use the default case processing.


case McpServerToolResultContent mstrc:
if (idToContentMapping?.TryGetValue(mstrc.CallId, out AIContent? callContentFromMapping) is true &&
callContentFromMapping is McpServerToolCallContent associatedCall)
Copy link
Member

Choose a reason for hiding this comment

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

Not related to this change but can you change idToContentMapping to Dictionary<string, McpServerToolCallContent> and remove this condition, it should be fine since we are storing only one concrete type in it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 598f78b. Changed idToContentMapping from Dictionary<string, AIContent> to Dictionary<string, McpServerToolCallContent> and removed the condition check.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in commits 598f78b and 23d5d20. Changed namespace to Microsoft.Extensions.AI and added all three missing tests:

  • FunctionCallReplacedWithApproval_MixedWithMcpApprovalAsync
  • ApprovedApprovalResponseIsExecuted_MixedWithMcpApprovalAsync
  • RejectedApprovalResponses_MixedWithMcpApprovalAsync

All tests updated to use Result property instead of Output.

@dotnet-policy-service dotnet-policy-service bot added the waiting-author-feedback 📭 The author of this issue needs to respond in order for us to continue investigating this issue. label Jan 12, 2026
…nts properties, fix idToContentMapping

Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
@dotnet-policy-service dotnet-policy-service bot removed the waiting-author-feedback 📭 The author of this issue needs to respond in order for us to continue investigating this issue. label Jan 12, 2026
Copilot AI and others added 2 commits January 12, 2026 22:01
Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
…Dictionary, use Result instead of Output

Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 12, 2026

@copilot please fix errors and address feedback.

All feedback addressed in commits 598f78b, 23d5d20, and 29454f9. Changes include:

  • Reverted to FunctionCallContent FunctionCall in approval types
  • Removed wrapper properties from MCP types (breaking changes accepted)
  • Fixed idToContentMapping type and simplified logic
  • Added missing tests from PR Replace Mcp approvals with Function approvals #7104
  • Fixed all build errors (unused usings, type conversions, property renames)

Copilot AI requested a review from jozkee January 12, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants