Skip to content

Conversation

@souvikghosh04
Copy link
Contributor

@souvikghosh04 souvikghosh04 commented Jan 28, 2026

Why make this change?

The entity-level MCP configuration (Entity.Mcp.DmlToolEnabled or Entity.Mcp.CustomToolEnabled) can override runtime-level settings. DmlToolEnabled defaults to true when unspecified, while CustomToolEnabled defaults to false.
However, this entity-level configuration was not being checked by the MCP tools when they execute. The tools only checked the runtime-level configuration (e.g. RuntimeConfig.McpDmlTools.ReadRecords, etc.).
This change addresses this gap for both built-in/DML tools and custom tools by adding entity-level validation before tool execution.

What is this change?

  • Added entity-level configuration checks to all 6 MCP tools (5 DML tools + 1 custom tool) that validate entity-specific flags before executing operations
  • DML tools (read_records, create_record, update_record, delete_record, execute_entity) now check entity.Mcp.DmlToolEnabled and return a ToolDisabled error when disabled at the entity level.
  • DynamicCustomTool checks entity.Mcp.CustomToolEnabled and return a ToolDisabled error
  • Tests covering various scenarios

How was this tested?

  • Integration Tests
  • Unit Tests

Sample Request(s)

Not applicable since it's a config level change and have been tested based on config settings.

@souvikghosh04 souvikghosh04 self-assigned this Jan 28, 2026
@souvikghosh04 souvikghosh04 added mssql an issue thats specific to mssql mcp-server labels Jan 28, 2026
@souvikghosh04 souvikghosh04 added this to the Jan 2026 milestone Jan 28, 2026
@souvikghosh04 souvikghosh04 linked an issue Jan 28, 2026 that may be closed by this pull request
@souvikghosh04 souvikghosh04 requested a review from Copilot January 28, 2026 09:34
@souvikghosh04 souvikghosh04 moved this from Todo to In Progress in Data API builder Jan 28, 2026
@souvikghosh04
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

Copy link
Contributor

Copilot AI left a 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 wires entity-level MCP configuration into the MCP tools so that both global runtime and per-entity flags are honored when deciding if a tool is enabled. It also introduces tests to validate behavior for enabled/disabled states, missing MCP config, and custom tools under hot-reload scenarios.

Changes:

  • Added DmlToolEnabled checks to all DML MCP tools (read_records, create_record, update_record, delete_record, execute_entity) so they return a ToolDisabled error when disabled at the entity level.
  • Added a CustomToolEnabled runtime check in DynamicCustomTool to ensure stored-proc tools are disabled when entity-level config turns them off, even after hot reload.
  • Extended MCP error helper to support custom tool-disabled messages and added a dedicated test suite validating entity-level MCP behavior across DML and custom tools.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/Service.Tests/Mcp/EntityLevelDmlToolConfigurationTests.cs New MSTest suite validating entity-level Mcp.DmlToolEnabled and Mcp.CustomToolEnabled handling across DML tools and dynamic custom tools, including disabled entities, enabled/default cases, and missing MCP config.
src/Azure.DataApiBuilder.Mcp/Utils/McpErrorHelpers.cs Extends ToolDisabled helper with an optional custom message parameter to support more specific error messages while preserving existing call sites.
src/Azure.DataApiBuilder.Mcp/Core/DynamicCustomTool.cs Adds a runtime check against entityConfig.Mcp.CustomToolEnabled before metadata/authorization, returning a ToolDisabled error when the custom tool is disabled in the current config.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/UpdateRecordTool.cs After parsing entity/keys/fields, adds an entity-level DmlToolEnabled check that returns ToolDisabled when the entity’s DML tools are disabled.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/ReadRecordsTool.cs After parsing the entity argument, adds an entity-level DmlToolEnabled check to gate the read_records tool per entity.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/ExecuteEntityTool.cs Adds an early entity-level DmlToolEnabled check and hardens entity lookup against config.Entities being null before resolving metadata and executing.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DeleteRecordTool.cs Adds an entity-level DmlToolEnabled check after parsing entity/keys to prevent deletes when the entity’s DML tools are disabled.
src/Azure.DataApiBuilder.Mcp/BuiltInTools/CreateRecordTool.cs Adds an entity-level DmlToolEnabled check after parsing entity/data so create operations respect per-entity MCP configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@souvikghosh04 souvikghosh04 changed the title Entity level check if Tool is enabled Entity level check if MCP Tool is enabled Jan 28, 2026
@anushakolan anushakolan self-assigned this Jan 28, 2026
JsonDocument arguments = JsonDocument.Parse("{\"entity\": \"Book\"}");

// Act
CallToolResult result = await tool.ExecuteAsync(arguments, serviceProvider, CancellationToken.None);
Copy link
Contributor

Choose a reason for hiding this comment

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

`private static async Task RunAsync(
IMcpTool tool,
string json,
IServiceProvider sp)
{
CallToolResult result = await tool.ExecuteAsync(
JsonDocument.Parse(json),
sp,
CancellationToken.None);

return JsonDocument.Parse(((TextContentBlock)result.Content[0]).Text).RootElement;

}`

we can create a function like this and just reuse it.

Copy link
Contributor

@anushakolan anushakolan left a comment

Choose a reason for hiding this comment

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

The tests code can be refactored to reduce duplicate logic, apart from that rest LGTM. Will re-review once the test code is refactored.

TextContentBlock firstContent = (TextContentBlock)result.Content[0];
JsonElement content = JsonDocument.Parse(firstContent.Text).RootElement;

Assert.IsTrue(content.TryGetProperty("error", out JsonElement error));
Copy link
Contributor

Choose a reason for hiding this comment

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

These assertions can also be extracted into a function and reused.

/// Verifies that CreateRecordTool respects entity-level DmlToolEnabled=false.
/// </summary>
[TestMethod]
public async Task CreateRecord_RespectsEntityLevelDmlToolDisabled()
Copy link
Contributor

Choose a reason for hiding this comment

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

The following tests differ only by which tool is used:

ReadRecords_RespectsEntityLevelDmlToolDisabled CreateRecord_RespectsEntityLevelDmlToolDisabled UpdateRecord_RespectsEntityLevelDmlToolDisabled DeleteRecord_RespectsEntityLevelDmlToolDisabled ExecuteEntity_RespectsEntityLevelDmlToolDisabled

You can collapse these into an MSTest DataRow test:

/// Verifies that entity-level check is skipped when entity has no MCP configuration.
/// When entity.Mcp is null, DmlToolEnabled defaults to true.
/// </summary>
[TestMethod]
Copy link
Contributor

Choose a reason for hiding this comment

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

These two:

ReadRecords_WorksWhenEntityLevelDmlToolEnabled
ReadRecords_WorksWhenEntityHasNoMcpConfig

can also be merged

@github-project-automation github-project-automation bot moved this from In Progress to Review In Progress in Data API builder Jan 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mcp-server mssql an issue thats specific to mssql

Projects

Status: Review In Progress

Development

Successfully merging this pull request may close these issues.

Wire up Entity level MCP config to check if Tool Enabled

3 participants