Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 1, 2025

  • Understand the issue: When UseStructuredContent is false (default), [return: Description] attributes are ignored
  • Locate relevant code: AIFunctionMcpServerTool.Create() in src/ModelContextProtocol.Core/Server/AIFunctionMcpServerTool.cs
  • Understand the flow: ReturnJsonSchema contains the description in a "description" property
  • Implement fix: When UseStructuredContent is NOT true and function.ReturnJsonSchema has a description, synthesize a combined tool description
  • Add tests to verify the behavior
  • Build and run tests
  • Code review (addressed feedback: use \n separator, IsNullOrWhiteSpace, and is not pattern)
  • CodeQL security check (no issues found)
Original prompt

A [return: Description] attribute on an McpServerTool is used to populate the outputSchema, but that schema is only generated when UseStructuredOutput is set. When it's not set, any return description will end up being ignored. Please update the McpServerTool.Create implementation such that if UseStructuredOutput is not true and there's a description attribute on the return parameter, the implementation will synthesize a description string from the description and the return description, so that the information is available to a consumer regardless, either in the tool description if UseStructuredOutput isn't true or in the outputSchema if it is true.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Update McpServerTool.Create to handle return description Synthesize return description into tool description when UseStructuredContent is false Dec 1, 2025
Copilot AI requested a review from stephentoub December 1, 2025 13:52
Copilot finished work on behalf of stephentoub December 1, 2025 13:52
return $"Returns: {returnDescription}";
}

return $"{description} Returns: {returnDescription}";
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot, let's add a \n newline rather than a space as the separator before Returns

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 bb7a8ec - now using \n newline as separator.

Comment on lines 430 to 436
if (returnDescription is null)
{
return description;
}

// Synthesize a combined description
if (string.IsNullOrEmpty(description))
Copy link
Contributor

Choose a reason for hiding this comment

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

Both of these checks should probably be via string.IsNullOrWhitespace

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 bb7a8ec - updated both checks to use string.IsNullOrWhiteSpace.

private static string? GetReturnDescription(JsonElement? returnJsonSchema)
{
if (returnJsonSchema is not JsonElement schema ||
schema.ValueKind != JsonValueKind.Object ||
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be is not for consistency

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 bb7a8ec - changed to is not.

if (returnJsonSchema is not JsonElement schema ||
schema.ValueKind != JsonValueKind.Object ||
!schema.TryGetProperty("description", out JsonElement descriptionElement) ||
descriptionElement.ValueKind != JsonValueKind.String)
Copy link
Contributor

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 bb7a8ec - changed to is not.

@stephentoub stephentoub marked this pull request as ready for review December 1, 2025 20:43
Copilot AI requested a review from stephentoub December 1, 2025 20:49
Copilot finished work on behalf of stephentoub December 1, 2025 20:49
@stephentoub
Copy link
Contributor

I might be mistaken, but this looks like it's automatic?

It's ensuring that a [return: Description] isn't dropped. If you don't provide a [return: Description], this is a nop. If you do provide a [return: Description], and you've opted-into structured output, this is a nop. But if you do provide a [return: Description] and you don't opt-into structured output, then the [return: Description] is being completely ignored today; this change makes it so that it's instead included in the description. Why would that be undesirable? If you don't want that, why are you providing a return description?

@PederHP
Copy link
Member

PederHP commented Dec 1, 2025

I might be mistaken, but this looks like it's automatic?

It's ensuring that a [return: Description] isn't dropped. If you don't provide a [return: Description], this is a nop. If you do provide a [return: Description], and you've opted-into structured output, this is a nop. But if you do provide a [return: Description] and you don't opt-into structured output, then the [return: Description] is being completely ignored today; this change makes it so that it's instead included in the description. Why would that be undesirable? If you don't want that, why are you providing a return description?

Yes, my bad. Deleted my comment shortly after writing it.

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.

3 participants