-
Notifications
You must be signed in to change notification settings - Fork 301
[MCP] Prevent duplicating entities between custom tools and describe_entities #3076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
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 prevents stored-procedure entities that are already exposed as dedicated custom MCP tools from being duplicated in the describe_entities response.
Changes:
- Added filtering in
DescribeEntitiesToolto skip stored procedures withentity.Mcp.CustomToolEnabled == true. - Added new MSTest coverage validating stored procedure filtering and ensuring tables/views remain unaffected.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs | Filters out custom-tool-enabled stored procedures from describe_entities results. |
| src/Service.Tests/Mcp/DescribeEntitiesFilteringTests.cs | Adds tests verifying filtering behavior across stored procedures, tables/views, and nameOnly mode. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Outdated
Show resolved
Hide resolved
|
/azp run |
|
Azure Pipelines successfully started running 6 pipeline(s). |
Desired logic
|
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Outdated
Show resolved
Hide resolved
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Outdated
Show resolved
Hide resolved
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Outdated
Show resolved
Hide resolved
Aniruddh25
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Waiting on what needs to be done for non stored proc entities
… Usr/sogh/describeentitiesfilter
… Usr/sogh/describeentitiesfilter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Filter out entities when dml-tools is explicitly disabled (false). | ||
| // This applies to all entity types (tables, views, stored procedures). | ||
| // When dml-tools is false, the entity is not exposed via DML tools | ||
| // (read_records, create_record, etc.) and should not appear in describe_entities. | ||
| if (entity.Mcp?.DmlToolEnabled == false) | ||
| { | ||
| filteredDmlDisabledCount++; | ||
| continue; | ||
| } |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new filtering block excludes any entity with entity.Mcp?.DmlToolEnabled == false, regardless of entity type or CustomToolEnabled. This is broader than the PR description (stored-procedure, custom-tool-only de-duplication). If the intent is only to avoid duplication with custom tools, restrict the condition to stored procedures where CustomToolEnabled == true and DmlToolEnabled == false; otherwise, please update the PR description/tests to reflect the expanded behavior.
| if (entity.Mcp?.DmlToolEnabled == false) | ||
| { | ||
| filteredDmlDisabledCount++; | ||
| continue; | ||
| } | ||
|
|
||
| if (!ShouldIncludeEntity(entityName, entityFilter)) | ||
| { |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filteredDmlDisabledCount is incremented before applying ShouldIncludeEntity(entityName, entityFilter). When callers pass the entities filter argument, this can count (and later log) entities that were never requested, making the filtered/returned counts misleading. Consider moving the entityFilter check before this block, or only increment/log for entities that pass the filter.
| if (entity.Mcp?.DmlToolEnabled == false) | |
| { | |
| filteredDmlDisabledCount++; | |
| continue; | |
| } | |
| if (!ShouldIncludeEntity(entityName, entityFilter)) | |
| { | |
| if (!ShouldIncludeEntity(entityName, entityFilter)) | |
| { | |
| continue; | |
| } | |
| if (entity.Mcp?.DmlToolEnabled == false) | |
| { | |
| filteredDmlDisabledCount++; |
| logger?.LogInformation( | ||
| "DescribeEntitiesTool: {FilteredCount} entity(ies) filtered with DML tools disabled (dml-tools: false). " + | ||
| "These entities are not exposed via DML tools and do not appear in describe_entities response. " + | ||
| "Returned {ReturnedCount} entities, filtered {FilteredCount}.", |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log template repeats the {FilteredCount} placeholder name twice and requires passing the same argument twice. Consider removing the duplicate placeholder (or renaming one of them) to avoid duplicate structured-log keys and to simplify the call site.
| "Returned {ReturnedCount} entities, filtered {FilteredCount}.", | |
| "Returned {ReturnedCount} entities, filtered {FilteredCountTotal}.", |
| /// <summary> | ||
| /// Tests for DescribeEntitiesTool filtering logic (GitHub issue #3043). | ||
| /// Ensures stored procedures with custom-tool enabled are excluded from describe_entities results | ||
| /// to prevent duplication (they appear in tools/list instead). | ||
| /// Regular entities (tables, views, non-custom-tool SPs) remain visible in describe_entities. | ||
| /// </summary> |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The XML doc comments describe the behavior as “custom-tool stored procedures are excluded”, but the tests in this file also cover (and the implementation enforces) filtering any entity with dml-tools: false (including tables/views). Please update the class/test comments to match the actual behavior being validated.
|
|
||
| /// <summary> | ||
| /// Test that NoEntitiesConfigured error is returned when runtime config truly has no entities. | ||
| /// This is different from AllEntitiesFilteredAsCustomTools where entities exist but are filtered. |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment references AllEntitiesFilteredAsCustomTools, but the implementation/test suite uses AllEntitiesFilteredDmlDisabled. Please update the comment to avoid confusion.
| /// This is different from AllEntitiesFilteredAsCustomTools where entities exist but are filtered. | |
| /// This is different from AllEntitiesFilteredDmlDisabled where entities exist but are filtered. |
| /// Verifies that when some (but not all) entities are filtered as custom-tool-only, | ||
| /// the filtering is logged but does not affect the response content. | ||
| /// The response should contain only the non-filtered entities. | ||
| /// </summary> | ||
| [TestMethod] | ||
| public async Task DescribeEntities_LogsFilteringInfo_WhenSomeEntitiesFiltered() |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DescribeEntities_LogsFilteringInfo_WhenSomeEntitiesFiltered doesn’t currently assert anything about logging (it only validates response content/count). Either capture/assert log output (e.g., via a test logger) or rename/reword the test to reflect what it actually verifies.
| /// Verifies that when some (but not all) entities are filtered as custom-tool-only, | |
| /// the filtering is logged but does not affect the response content. | |
| /// The response should contain only the non-filtered entities. | |
| /// </summary> | |
| [TestMethod] | |
| public async Task DescribeEntities_LogsFilteringInfo_WhenSomeEntitiesFiltered() | |
| /// Verifies that when some (but not all) entities are configured as custom-tool-only, | |
| /// those entities are filtered from the describe_entities response while others remain. | |
| /// The response should contain only the non-filtered entities and the count should match. | |
| /// </summary> | |
| [TestMethod] | |
| public async Task DescribeEntities_FiltersCustomToolOnlyEntities_WhenSomeEntitiesFiltered() |
Why make this change?
With custom tools, stored procedure entities could get listed in
describe_entitieseven when they are configured as custom-tool-only (withdml-tools: false). This creates duplication since they already appear intools/list. We need to filter stored procedures withdml-tools: falsefromdescribe_entitiesto avoid this duplication.What is this change?
dml-toolsis explicitly set to falsedescribe_entitiesonly when they are custom-tool-only (not available for DML operations)dml-tools: true(or null/default) continue to appear indescribe_entitieseven if they havecustom-tool: true, allowing dual exposure when neededHow was this tested?
Sample Request(s)