Skip to content

Added missing stored procedure parameters in describe_entities response.#3425

Open
anushakolan wants to merge 3 commits intomainfrom
dev/anushakolan/describe_entities_missing_sp_params
Open

Added missing stored procedure parameters in describe_entities response.#3425
anushakolan wants to merge 3 commits intomainfrom
dev/anushakolan/describe_entities_missing_sp_params

Conversation

@anushakolan
Copy link
Copy Markdown
Contributor

Why make this change?

Closes #3400.

describe_entities could return stored procedure entities with empty or partial parameters metadata when parameters were not fully listed in config. This caused MCP clients/agents to miss required inputs and fail execute_entity calls.

Additional discussion: #3400 issue thread.

What is this change?

  • Updated DescribeEntitiesTool to include stored procedure parameters from runtime DB metadata.
  • Merged DB metadata with config metadata so config values override matching fields (required, default, description).
  • Preserved fallback behavior: if metadata resolution fails, config-defined parameters are still returned.
  • Added focused MCP tests for:
    • metadata-only parameter discovery
    • config-overrides-DB merge behavior

How was this tested?

  • Integration Tests
  • Unit Tests

Ran:

  • dotnet test src/Service.Tests/Azure.DataApiBuilder.Service.Tests.csproj --filter "FullyQualifiedName~DescribeEntitiesStoredProcedureParametersTests"

Sample Request(s)

MCP request example:

  • describe_entities with full metadata:

    • {"name":"describe_entities","arguments":{}}
  • execute_entity using discovered parameters:

    • {"name":"execute_entity","arguments":{"entity":"GetBook","parameters":{"id":1}}}

Copy link
Copy Markdown
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

Updates MCP describe_entities to reliably include complete stored procedure parameter metadata by augmenting/merging config-defined parameters with runtime database metadata, and adds targeted tests to validate the behavior.

Changes:

  • Resolve stored procedure parameter metadata from runtime DB metadata when config parameters are missing/partial.
  • Merge config + DB parameter metadata, preferring config values for overlapping fields.
  • Add MCP unit tests covering metadata-only discovery and config-overrides-DB merging.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs Adds metadata resolution for stored procedure entities and merges DB/config parameter metadata in describe_entities output.
src/Service.Tests/Mcp/DescribeEntitiesStoredProcedureParametersTests.cs Adds unit tests validating parameter discovery from DB metadata and config-overrides behavior.

Comment thread src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs Outdated
Comment thread src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
Comment thread src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs Outdated
Copy link
Copy Markdown
Collaborator

@Aniruddh25 Aniruddh25 left a comment

Choose a reason for hiding this comment

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

Want to know reasoning behind why the bug happened.

Comment thread src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs Outdated

if (databaseObject is DatabaseStoredProcedure storedProcedure)
{
foreach ((string parameterName, ParameterDefinition parameterDefinition) in storedProcedure.StoredProcedureDefinition.Parameters)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What was the reason again to have two different data structures? ParameterDefinitionand ParameterMetadata? why couldnt we have used ParameterDefinition for the config parameters?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ParameterDefinition is runtime metadata discovered from the database. ParameterMetadata is user-specified config overrides. Both exist because DB metadata provides the source of truth for parameters, while config allows users to enrich with descriptions/defaults.

Copy link
Copy Markdown
Collaborator

@Aniruddh25 Aniruddh25 Apr 20, 2026

Choose a reason for hiding this comment

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

I understand we need both the objects. My question is - why couldnt we have expanded ParameterDefinition - the same data structure to support user specified config overrides? Why did we introduce a new class ParameterMetadata = also, the name is confusing.

Parameter information from DB metadata is called ParameterDefinition and not ParameterMetadata.

@RubenCerna2079
Copy link
Copy Markdown
Contributor

Hey just wanted to let you know that it seems this PR is related to a bug that I created for 2.0. Might be a good idea to check it and see if it can be fixed on this PR or as a follow up. #3435

@anushakolan
Copy link
Copy Markdown
Contributor Author

Hey just wanted to let you know that it seems this PR is related to a bug that I created for 2.0. Might be a good idea to check it and see if it can be fixed on this PR or as a follow up. #3435

Thanks for linking these! They share the same root cause: parameter metadata is read only from config, not from runtime DB metadata.

PR #3425 fixes describe_entities (AI agents can now discover parameters).

Bug #3435 needs a follow-up PR to fix DynamicCustomTool.BuildInputSchema() the same way - it currently only reads Entity.Source.Parameters from config, not from IMetadataProviderFactory.

The fix requires passing IServiceProvider through CustomMcpToolFactory to DynamicCustomTool so it can access runtime metadata for schema building.

@anushakolan
Copy link
Copy Markdown
Contributor Author

anushakolan commented Apr 17, 2026

Want to know reasoning behind why the bug happened.

Original implementation only read config (Entity.Source.Parameters), ignoring runtime-discovered parameters from IMetadataProviderFactory. The fix merges both: DB metadata as base, config as overrides. May be @souvikghosh04 can add anything I missed.

@souvikghosh04
Copy link
Copy Markdown
Contributor

souvikghosh04 commented Apr 20, 2026

Want to know reasoning behind why the bug happened.

Original implementation only read config (Entity.Source.Parameters), ignoring runtime-discovered parameters from IMetadataProviderFactory. The fix merges both: DB metadata as base, config as overrides. May be @souvikghosh04 can add anything I missed.

I think we are discussing two separate things-

  1. This PR: based on what I see the PR is trying to achieve is its merging the DB metadata (a new and additional pull) and the config defined metadata. but this creates inconsistency- discovery will surface DB-discovered params that tools still reject/don't advertise (since they validate against config only).
  2. Issue [Bug]: Custom-tools that require parameters cannot be run #3435: It is mentioned in the description that the custom tool cannot be run for stored procedures which requires parameters. This is not correct. custom tool implementation (PR Implementation of Custom Tool in MCP #3048) correctly handles dynamic parameters when they're passed. Please refer to the sample JSON requests in the mentioned PR and see if those are supported in MCP Inspector. If not, you can use Insomnia client or stdio (GHCP) to test.

so for point 1- we might not need this PR unless we want to move completely to DB based discoverability to avoid split brain or incosistent behaviour.
for point 2- seems unrelated to this and probably should be closed since custom tool already support dynamic parameters based on what is configured in config during elevation of a stored proc as custom tool.

foreach (ParameterMetadata configParameter in configParameters.Values)
{
if (!storedProcedure.StoredProcedureDefinition.Parameters.ContainsKey(configParameter.Name))
if (!storedProcedureParameters.ContainsKey(configParameter.Name) &&
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why cant the ContainsKey comparison itself be case insensitive instead of adding another && condition?

Copy link
Copy Markdown
Collaborator

@Aniruddh25 Aniruddh25 Apr 20, 2026

Choose a reason for hiding this comment

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

On second thought, all configParameters should be present in the metadata retrieved from the database. In fact, config parameters should be a subset of database parameters.

There might a validation check to ensure this.


foreach ((string parameterName, ParameterDefinition parameterDefinition) in storedProcedureParameters)
{
configParameters.TryGetValue(parameterName, out ParameterMetadata? configParameter);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR description says -

Merged DB metadata with config metadata so config values override matching fields (required, default, description).

However, this is not what is implemented.

With the current implementation, config values will never be added to the result since ALL config parameters should be discoverable in storedProcedureParameters by definition.
But the current check !storedProcedureParameters.ContainsKey(configParameter.Name) tries to identify the missing ones.

Config metadata should only be used to override, which means after reading params from DB metadata, the config values should be used to replace the values from DB.

Assert.AreEqual(2, parameters.GetArrayLength());

JsonElement idParam = parameters.EnumerateArray().Single(p => p.GetProperty("name").GetString() == "id");
Assert.IsFalse(idParam.GetProperty("required").GetBoolean(), "DB required metadata should be preferred when config cannot indicate whether 'required' was explicitly set.");
Copy link
Copy Markdown
Collaborator

@Aniruddh25 Aniruddh25 Apr 20, 2026

Choose a reason for hiding this comment

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

The test is titled DescribeEntities_ConfigParameterMetadataOverridesDatabaseParameterMetadata
whereas this assert is doing exactly the opposite - DB is overriding config?

Assert should be Assert.IsTrue

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.

[Bug]: describe_entities missing stored procedure parameters

6 participants