Add ElicitationRequired to ToolMetadata#1969
Add ElicitationRequired to ToolMetadata#1969alzimmermsft wants to merge 1 commit intomicrosoft:mainfrom
Conversation
|
Up up Up |
| @@ -335,7 +335,7 @@ private async Task<CallToolResult> InvokeChildToolAsync( | |||
|
|
|||
| // Check if this tool requires elicitation for sensitive data | |||
There was a problem hiding this comment.
Update comment as well.
| // Check if this tool requires elicitation for sensitive data | |
| // Check if this tool accesses sensitive data or explicitly requires elicitation. |
jongio
left a comment
There was a problem hiding this comment.
Clean feature addition - the field keyword refactoring and new ElicitationRequired property follow existing patterns well. But there are a couple things that should get addressed before merge.
CommandFactoryToolLoader wasn't updated. At CommandFactoryToolLoader.cs:153, it still only checks metadata.Secret for triggering elicitation. You updated NamespaceToolLoader but missed this parallel code path. Tools loaded through CommandFactoryToolLoader with ElicitationRequired = true (but Secret = false) will silently skip elicitation. That's a bug.
Neither loader adds an ElicitationRequiredHint to Tool.Meta. Both loaders populate SecretHint and LocalRequiredHint for MCP client consumption, but there's no equivalent for the new flag. The ShouldTriggerElicitation extension method checks for "ElicitationRequired" in the JsonObject metadata, but nothing ever puts that key there - so that code path is unreachable for the new flag.
No tests cover the new behavior. McpServerElicitationExtensionsTests needs cases for ElicitationRequired in ShouldTriggerElicitation, and the converter/construction path should verify round-trip serialization of the new field.
On the plus side - the backing fields to field keyword refactoring cuts ~13 lines of boilerplate while keeping lazy init intact. The property follows existing patterns exactly (XML doc, [JsonIgnore] + MetadataDefinition, default value, constructor handling). Namespace fix in ToolMetadataJsonConverter.cs aligns it with its directory. The expression-body refactoring of SupportsElicitation and local variable decomposition in ShouldTriggerElicitation are both solid improvements.
NOTE: @srnagar's existing comment about updating the code comment in NamespaceToolLoader.cs is valid - not repeating it here.
| // Check if this tool requires elicitation for sensitive data | ||
| var metadata = cmd.Metadata; | ||
| if (metadata.Secret) | ||
| if (metadata.Secret || metadata.ElicitationRequired) |
There was a problem hiding this comment.
This check was correctly updated here, but the identical pattern in CommandFactoryToolLoader.cs:153 was not:
// CommandFactoryToolLoader.cs:153 (not in this PR's diff)
if (metadata.Secret) // ← missing || metadata.ElicitationRequiredBoth tool loaders independently check metadata before calling HandleSecretElicitationAsync. If a tool is loaded via CommandFactoryToolLoader with ElicitationRequired = true and Secret = false, elicitation will be silently skipped.
Please update CommandFactoryToolLoader.cs:153 to match:
if (metadata.Secret || metadata.ElicitationRequired)|
|
||
| var elicitationRequired = jsonMetadata.TryGetPropertyValue("ElicitationRequired", out var elicitationValue) && | ||
| elicitationValue is JsonValue elicitationJsonValue && | ||
| elicitationJsonValue.TryGetValue(out bool isElicitationRequired) && |
There was a problem hiding this comment.
The ShouldTriggerElicitation extension now checks "ElicitationRequired" in the JsonObject metadata, but nothing populates this key in Tool.Meta.
Both NamespaceToolLoader (line 589-601) and CommandFactoryToolLoader (line 242-254) add SecretHint and LocalRequiredHint to Tool.Meta when those flags are set, but neither adds an ElicitationRequiredHint. This makes the new ElicitationRequired branch in this method unreachable via Tool.Meta.
Consider adding to both loaders' meta-building sections:
if (metadata.ElicitationRequired)
{
meta ??= new();
meta["ElicitationRequiredHint"] = metadata.ElicitationRequired;
}Alternatively, if Tool.Meta exposure is intentionally omitted for this flag, a comment explaining that would help future readers.
| /// <para> | ||
| /// The default is <see langword="false"/>. | ||
| /// </para> | ||
| /// </remarks> |
There was a problem hiding this comment.
The new ElicitationRequired property and its integration points (constructor, converter, ShouldTriggerElicitation, NamespaceToolLoader) should have unit test coverage. Specifically:
McpServerElicitationExtensionsTests: Add cases forShouldTriggerElicitationwithElicitationRequired = true(both alone and combined withSecret)- ToolMetadata construction: Verify
ElicitationRequiredis correctly initialized fromMetadataDefinition - Converter round-trip: Verify
"elicitationRequired"serializes/deserializes correctly
The existing McpServerElicitationExtensionsTests has good patterns to follow (10 existing test cases for Secret).
What does this PR do?
Adds
ElicitationRequiredtoToolMetadatato allow tools to denote that they require elicitation before the tool can run. This allows for tools to elicit without needing to be marked asSecret, which affects other areas of the server other than the elicitation requirement before running the tool.GitHub issue number?
[Link to the GitHub issue this PR addresses]Pre-merge Checklist
servers/Azure.Mcp.Server/CHANGELOG.mdand/orservers/Fabric.Mcp.Server/CHANGELOG.mdfor product changes (features, bug fixes, UI/UX, updated dependencies)servers/Azure.Mcp.Server/README.mdand/orservers/Fabric.Mcp.Server/README.mddocumentationeng/scripts/Process-PackageReadMe.ps1. See Package README/servers/Azure.Mcp.Server/docs/azmcp-commands.mdand/or/docs/fabric-commands.md.\eng\scripts\Update-AzCommandsMetadata.ps1to update tool metadata in azmcp-commands.md (required for CI)ToolDescriptionEvaluatorand obtained a score of0.4or more and a top 3 ranking for all related test promptsconsolidated-tools.json/servers/Azure.Mcp.Server/docs/e2eTestPrompts.mdcrypto mining, spam, data exfiltration, etc.)/azp run mcp - pullrequest - liveto run Live Test Pipeline