Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidArguments", parseError, logger);
}

// Check entity-level DML tool configuration
if (runtimeConfig.Entities?.TryGetValue(entityName, out Entity? entity) == true &&
entity.Mcp?.DmlToolEnabled == false)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"DML tools are disabled for entity '{entityName}'.");
}

if (!McpMetadataHelper.TryResolveMetadata(
entityName,
runtimeConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidArguments", parseError, logger);
}

// Check entity-level DML tool configuration
if (config.Entities?.TryGetValue(entityName, out Entity? entity) == true &&
entity.Mcp?.DmlToolEnabled == false)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"DML tools are disabled for entity '{entityName}'.");
}

// 4) Resolve metadata for entity existence
if (!McpMetadataHelper.TryResolveMetadata(
entityName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,18 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidArguments", "Entity is required", logger);
}

// Check entity-level DML tool configuration early (before metadata resolution)
if (config.Entities?.TryGetValue(entity, out Entity? entityForCheck) == true &&
entityForCheck.Mcp?.DmlToolEnabled == false)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"DML tools are disabled for entity '{entity}'.");
}

IMetadataProviderFactory metadataProviderFactory = serviceProvider.GetRequiredService<IMetadataProviderFactory>();
IQueryEngineFactory queryEngineFactory = serviceProvider.GetRequiredService<IQueryEngineFactory>();

// 4) Validate entity exists and is a stored procedure
if (!config.Entities.TryGetValue(entity, out Entity? entityConfig))
if (config.Entities is null || !config.Entities.TryGetValue(entity, out Entity? entityConfig))
{
return McpResponseBuilder.BuildErrorResult(toolName, "EntityNotFound", $"Entity '{entity}' not found in configuration.", logger);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidArguments", parseError, logger);
}

// Check entity-level DML tool configuration
if (runtimeConfig.Entities?.TryGetValue(entityName, out Entity? entity) == true &&
entity.Mcp?.DmlToolEnabled == false)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"DML tools are disabled for entity '{entityName}'.");
}

if (root.TryGetProperty("select", out JsonElement selectElement))
{
select = selectElement.GetString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidArguments", parseError, logger);
}

// Check entity-level DML tool configuration
if (config.Entities?.TryGetValue(entityName, out Entity? entity) == true &&
entity.Mcp?.DmlToolEnabled == false)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"DML tools are disabled for entity '{entityName}'.");
}

IMetadataProviderFactory metadataProviderFactory = serviceProvider.GetRequiredService<IMetadataProviderFactory>();
IMutationEngineFactory mutationEngineFactory = serviceProvider.GetRequiredService<IMutationEngineFactory>();

Expand Down
6 changes: 6 additions & 0 deletions src/Azure.DataApiBuilder.Mcp/Core/DynamicCustomTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ public async Task<CallToolResult> ExecuteAsync(
return McpResponseBuilder.BuildErrorResult(toolName, "InvalidEntity", $"Entity {_entityName} is not a stored procedure.", logger);
}

// Check if custom tool is still enabled for this entity
if (entityConfig.Mcp?.CustomToolEnabled != true)
{
return McpErrorHelpers.ToolDisabled(toolName, logger, $"Custom tool is disabled for entity '{_entityName}'.");
}

// 4) Resolve metadata
if (!McpMetadataHelper.TryResolveMetadata(
_entityName,
Expand Down
4 changes: 2 additions & 2 deletions src/Azure.DataApiBuilder.Mcp/Utils/McpErrorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public static CallToolResult PermissionDenied(string toolName, string entityName
}

// Centralized language for 'tool disabled' errors. Pass the tool name, e.g. "read_records".
public static CallToolResult ToolDisabled(string toolName, ILogger? logger)
public static CallToolResult ToolDisabled(string toolName, ILogger? logger, string? customMessage = null)
{
string message = $"The {toolName} tool is disabled in the configuration.";
string message = customMessage ?? $"The {toolName} tool is disabled in the configuration.";
return McpResponseBuilder.BuildErrorResult(toolName, Model.McpErrorCode.ToolDisabled.ToString(), message, logger);
}
}
Expand Down
Loading