Repository navigation
Fixed nested value envelope in MCP stored procedure responses - #3868
Vaishali123t wants to merge 3 commits into
Conversation
Unwrap DAB’s { "value": [...] } response in built-in and custom MCP tools, and add regression tests for both paths.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
There was a problem hiding this comment.
🟢 Approval recommended
The focused fix covers both execution paths with regression tests and no blocking issues identified; tests were not executed.
No open issues 🎉
What changed in this PR
Fixes nested value envelopes in DAB’s built-in and custom MCP stored procedure responses.
Changes:
- Centralizes envelope unwrapping and array normalization.
- Applies the shared helper to both execution paths.
- Adds regression tests and tightens SQL Server integration assertions.
| File | Description |
|---|---|
| src/Service.Tests/Mcp/ExecuteEntityToolTests.cs | Tests built-in envelope unwrapping. |
| src/Service.Tests/Mcp/ExecuteEntityToolMsSqlIntegrationTests.cs | Requires a direct result array. |
| src/Service.Tests/Mcp/DynamicCustomToolTests.cs | Tests custom-tool envelope unwrapping. |
| src/Service.Tests/Mcp/DynamicCustomToolMsSqlIntegrationTests.cs | Requires a direct result array. |
| src/Azure.DataApiBuilder.Mcp/Utils/McpResponseBuilder.cs | Adds shared result normalization. |
| src/Azure.DataApiBuilder.Mcp/Core/DynamicCustomTool.cs | Uses shared normalization. |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/ExecuteEntityTool.cs | Uses shared normalization. |
Review effort: Balanced
|
@microsoft-github-policy-service-agree |
|
Vaishali123t please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
Unwrap DAB’s { "value": [...] } response in built-in and custom MCP tools, and add regression tests for both paths.
Why make this change?
What is this change?
{
"entity": "GetBook",
"value": {
"value": [{ "id": 1 }]
},
"status": "success"
}
After:
{
"entity": "GetBook",
"value": [{ "id": 1 }],
"status": "success"
}
How was this tested?
Build
powershell
dotnet build src\Azure.DataApiBuilder.Mcp\Azure.DataApiBuilder.Mcp.csproj --no-restore --verbosity quiet
Result: passed with zero warnings and zero errors.
Focused unit tests
powershell
dotnet test src\Service.Tests\Azure.DataApiBuilder.Service.Tests.csproj --no-build --no-restore --filter "FullyQualifiedName
Azure.DataApiBuilder.Service.Tests.Mcp.ExecuteEntityToolTests|FullyQualifiedNameAzure.DataApiBuilder.Service.Tests.Mcp.DynamicCustomToolTests" --verbosity quietResult: 106 passed, 0 failed, 0 skipped.
The six new regression cases were also run against the original adapter
implementation: all six failed before the fix and passed with the fix.
They verify empty results, multiple rows, and preservation of a legitimate
array-valued column named value through both tools.
SQL-backed integration tests
The following classes were run separately against an isolated local
SQL Server 2022 database:
powershell
dotnet test src\Service.Tests\Azure.DataApiBuilder.Service.Tests.csproj --no-build --no-restore --filter "FullyQualifiedName~ExecuteEntityToolMsSqlIntegrationTests" --verbosity quiet
dotnet test src\Service.Tests\Azure.DataApiBuilder.Service.Tests.csproj --no-build --no-restore --filter "FullyQualifiedName~DynamicCustomToolMsSqlIntegrationTests" --verbosity quiet
Results: 8/8 built-in-tool tests and 16/16 custom-tool tests passed.
Environment qualification: the unmodified shared fixture requires newer
SQL vector/native JSON types unavailable on this local SQL Server 2022
instance. A reviewer-only setup configured the isolated database and used
nvarchar(max) for those unrelated fixture columns. The stored procedures,
PR implementation, and PR test assertions were unchanged. These results
are not an unmodified full-suite or CI pass.
Additional reviewer-only HTTP validation
Seven additional checks passed through DAB's in-process HTTP test server
against the real SQL database:
These checks used a temporary review harness, not tests included in this PR.
No full cross-database suite or CI pass is claimed.
Sample Request(s)
Using the repository's MSSQL test configuration, after initializing an MCP
session, send these tools/call requests to /mcp with the negotiated
protocol version, session header, and appropriate authentication.
Built-in tool:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "execute_entity",
"arguments": {
"entity": "GetBook",
"parameters": { "id": 1 }
}
}
}
Equivalent custom tool:
json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_book",
"arguments": { "id": 1 }
}
}
For both tools, the decoded JSON inside MCP result.content[0].text
contains a single value array holding the actual book rows. The first
row has id: 1; the engine's additional value envelope is absent.
A nonexistent ID returns "value": [].
REST compatibility control:
http
GET /api/GetBook?id=1
The REST response retains its established {"value":[...]} envelope.
No CLI behavior changes are introduced.