-
Notifications
You must be signed in to change notification settings - Fork 296
Cherry pick MCP fixes and improvements for 1.7 #2960
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
Conversation
MCP `list_tools` descriptions were insufficiently clear for ChatGPT to
understand tool usage patterns and workflows, while Claude handled them
adequately.
## Changes
Updated descriptions and input schemas for all 6 MCP tools:
- **describe_entities**: Added "ALWAYS CALL FIRST" directive and
clarified permissions structure (`'ALL'` expands by type: data→CREATE,
READ, UPDATE, DELETE). Expanded `nameOnly` and `entities` parameter
descriptions to include detailed usage guidance:
- `nameOnly`: Explains when to use it (for discovery with many
entities), the two-call strategy (first with `nameOnly=true`, then with
specific entities), and warns that it doesn't provide enough detail for
CRUD/EXECUTE operations
- `entities`: Clarifies its purpose for targeted metadata retrieval and
explicitly warns against combining it with `nameOnly=true`
- **CRUD tools** (create_record, read_records, update_record,
delete_record): Added explicit STEP 1→STEP 2 workflow (describe_entities
first, then call with matching permissions/fields)
- **execute_entity**: Added workflow guidance and clarified use case
(actions/computed results)
- **All tools**: Condensed parameter descriptions (e.g.,
"Comma-separated field names" vs. "A comma-separated list of field names
to include in the response. If omitted, all fields are returned.
Optional.")
## Example
Before:
```csharp
Description = "Creates a new record in the specified entity."
```
After:
```csharp
Description = "STEP 1: describe_entities -> find entities with CREATE permission and their fields. STEP 2: call this tool with matching field names and values."
```
All changes are metadata-only; no functional code modified.
<!-- START COPILOT CODING AGENT SUFFIX -->
<details>
<summary>Original prompt</summary>
----
*This section details on the original issue you should resolve*
<issue_title>[BUG]: MCP `list_tools` need more comprehensive
descriptions.</issue_title>
<issue_description>## What?
Our tools have descriptions already. They need better to help models.
> Claude works but ChatGPT struggles to understand with our current
descriptions.
## New descriptions
```json
{
"tools": [
{
"name": "describe_entities",
"description": "Lists all entities and metadata. ALWAYS CALL FIRST. Each entity includes: name, type, fields, parameters, and permissions. The permissions array defines which tools are allowed. 'ALL' expands by type: data->CREATE, READ, UPDATE, DELETE.",
"inputSchema": {
"type": "object",
"properties": {
"nameOnly": {
"type": "boolean",
"description": "True: names and summaries only. False (default): full metadata."
},
"entities": {
"type": "array",
"items": { "type": "string" },
"description": "Optional: specific entity names. Omit for all."
}
}
}
},
{
"name": "create_record",
"description": "STEP 1: describe_entities -> find entities with CREATE permission and their fields. STEP 2: call this tool with matching field names and values.",
"inputSchema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Entity name with CREATE permission."
},
"data": {
"type": "object",
"description": "Required fields and values for the new record."
}
},
"required": ["entity", "data"]
}
},
{
"name": "read_records",
"description": "STEP 1: describe_entities -> find entities with READ permission and their fields. STEP 2: call this tool with select, filter, sort, or pagination options.",
"inputSchema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Entity name with READ permission."
},
"select": {
"type": "string",
"description": "Comma-separated field names."
},
"filter": {
"type": "string",
"description": "OData expression: eq, ne, gt, ge, lt, le, and, or, not."
},
"orderby": {
"type": "array",
"items": { "type": "string" },
"description": "Sort fields and directions, e.g., ['name asc', 'year desc']."
},
"first": {
"type": "integer",
"description": "Max number of records (page size)."
},
"after": {
"type": "string",
"description": "Cursor token for next page."
}
},
"required": ["entity"]
}
},
{
"name": "update_record",
"description": "STEP 1: describe_entities -> find entities with UPDATE permission and their key fields. STEP 2: call this tool with keys and new field values.",
"inputSchema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Entity name with UPDATE permission."
},
"keys": {
"type": "object",
"description": "Primary or composite keys identifying the record."
},
"fields": {
"type": "object",
"description": "Fields and their new values."
}
},
"required": ["entity", "keys", "fields"]
}
},
{
"name": "delete_record",
"description": "STEP 1: describe_entities -> find entities with DELETE permission and their key fields. STEP 2: call this tool with full key values.",
"inputSchema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Entity name with DELETE permission."
},
"keys": {
"type": "object",
"description": "All key fields identifying the record."
}
},
"required": ["entity", "keys"]
}
},
{
"name": "execute_entity",
"description": "STEP 1: describe_entities -> find entities with EXECUTE permission and their parameters. STEP 2: call this tool with matching parameter values. Used for entities that perform actions or return computed results.",
"inputSchema": {
"type": "object",
"properties": {
"entity": {
"type": "string",
"description": "Entity name with EXECUTE permission."
},
"parameters": {
"type": "object",
"description": "Optional parameter names and values."
}
},
"required": ["entity"]
}
}
]
}
```
</issue_description>
<agent_instruction...
</details>
- Fixes #2936
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for
you](https://github.com/Azure/data-api-builder/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
…2927) ## Why make this change? Bug fix for setting dml tools correctly. Closes on - #2942 ## What is this change? This fix addresses the inconsistency in config where `dml-tools` can be either set as bool or a dictionary object containing individual tool names and their bool values. Without this fix, we need to individually set each `dml-tools` to true currently. With this change, we will have the following scenarios- - set `dml-tools` to `true` will enable all dml tools (default is true) Sample- ```"dml-tools": true``` - set `dml-tools` to `false` will disable all dml tools Sample-```"dml-tools": false``` - individual tool names can be specified as dictionary object for `dml-tools` to turn them on (default is true if a tool is not specified). ## How was this tested? - [ ] Integration Tests - [ ] Unit Tests - [x] Manual testing using various combinations and scenarios **Scenario 1:** Enable all tools using a single boolean value `"dml-tools": true` Note: default is true so even if `dml-tools` unspecified it will default to true. **Scenario 2:** Disable `execute-entities` only and keep other tools enabled as default. ``` "dml-tools": { "execute-entities": false } ``` **Scenario 3:** Use full list of tools and enable or disable them ``` "dml-tools": { "execute-entity": true, "delete-record": false, "update-record": false, "read-records": false, "describe-entities": true } ``` --------- Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
#2951) The MCP `describe_entities` tool returns `"ALL"` for wildcard permissions, which confuses LLM consumers that need explicit operation lists. ### Changes Modified `DescribeEntitiesTool.BuildPermissionsInfo()` to expand `EntityActionOperation.All`: - **Tables/Views**: Expands to `["CREATE", "DELETE", "READ", "UPDATE"]` via `EntityAction.ValidPermissionOperations` - **Stored Procedures**: Expands to `["EXECUTE"]` via `EntityAction.ValidStoredProcedurePermissionOperations` ### Example **Before:** ```json { "name": "Todo", "permissions": ["ALL"] } ``` **After:** ```json { "name": "Todo", "permissions": ["CREATE", "DELETE", "READ", "UPDATE"] } ``` <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[Bug]: MCP `describe_entities` permissions value `ALL` needs to be expanded.</issue_title> > <issue_description>## What? > > Models are confused by `ALL`. > > ```json > { > "entities": [ > { > "name": "Todo", > "description": "This table contains the list of todo items.", > "fields": [ ], > "permissions": [ > "ALL" // this is the problem > ] > } > ], > "count": 1, > "mode": "full", > "status": "success" > } > ``` > > ## Solution > > When table/view. > > ```json > { > "permissions: [ > "CREATE", > "DELETE", > "READ", > "UPDATE" > ] > } > ``` > > When stored procedure. > > ```json > { > "permissions: [ > "EXECUTE" > ] > } > ``` > </issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> - Fixes #2935 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JerryNixon <1749983+JerryNixon@users.noreply.github.com>
## Why make this change? This PR addresses the issue where with serialization of `dml-tools` property for user-provided (non-default) values. This is a follow up to the fix made for the functionality of `dml-tools` property- #2927 ## What is this change? If `dml-tools` is not configured, this property should not be serialized. Serialization should only be done for user provided configuration. So, any value explicitly set or configured by the user for `dml-tools` will be serialized. `dml-tools` can either have either of the below values- - A boolean value- true or false. This is a global value to enable or disable all DML tools and `UserProvidedAllTools` is written in JSON - A dictionary object of individual tool name and boolean values. This contains individual tool specific values and only the specified tools will be taken for JSON writing and unspecified tool names will be ignored. ## How was this tested? - [x] Integration Tests - [x] Unit Tests - [x] Manual Tests Sample scenarios for testing- **Scenario 1:** Enable all tools using a single boolean value `"dml-tools": true` Note: default is true so even if `dml-tools` unspecified it will default to true. **Scenario 2:** Disable `execute-entities` only and keep other tools enabled as default. ``` "dml-tools": { "execute-entities": false } ``` **Scenario 3:** Use full list of tools and enable or disable them ``` "dml-tools": { "execute-entity": true, "delete-record": false, "update-record": false, "read-records": false, "describe-entities": true } ``` --------- Co-authored-by: Aniruddh Munde <anmunde@microsoft.com>
… describe-entities MCP tool (#2956) ## Why make this change? - Addresses follow ups to PR #2900 The `describe_entities` tool response format needed improvements to better align with MCP specifications and provide more accurate, user-scoped information. Key issues included non-specification compliant response fields, overly broad permission reporting across all roles, and inconsistent entity/field naming conventions that didn't prioritize user-friendly aliases. ## What is this change? - **Removed non-spec fields from response**: Eliminated `mode` and `filter` fields that were not part of the MCP specification - **Scoped permissions to current user's role**: Modified permissions logic to only return permissions available to the requesting user's role instead of all permissions across all roles - **Implemented entity alias support**: Updated entity name resolution to prefer GraphQL singular names (aliases) over configuration names, falling back to entity name only when alias is absent - **Fixed parameter metadata format**: Changed parameter default value key from `@default` to `default` in JSON response - **Enhanced field name resolution**: Updated field metadata to use field aliases when available, falling back to field names when aliases are absent - **Added proper authorization context**: Integrated HTTP context and authorization resolver to determine current user's role for permission filtering ## How was this tested? - [x] Manual Tests ## Sample Request(s) ``` POST http://localhost:5000/mcp { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "describe_entities" }, "id": 1 } ``` ``` POST http://localhost:5000/mcp { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "describe_entities", "arguments": { "nameOnly": true } }, "id": 2 } ``` ``` POST http://localhost:5000/mcp { "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "describe_entities", "arguments": { "entities": ["Book", "Publisher"] } }, "id": 1 } ```
|
/azp run |
|
Azure Pipelines successfully started running 6 pipeline(s). |
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 enhances the MCP (Model Context Protocol) configuration and tool descriptions by adding granular DML tool configuration support and improving role-based permission filtering.
Key changes include:
- Addition of
DmlToolsConfigstructure with individual tool enable/disable flags and user-provided tracking - Enhanced tool descriptions with step-by-step usage instructions for AI models
- Role-based permission filtering in
describe_entitiestool to show only permissions relevant to the current user's role - Default initialization of
DmlToolsconfiguration when not specified
Reviewed Changes
Copilot reviewed 50 out of 51 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Config/ObjectModel/DmlToolsConfig.cs | Refactored constructor to handle default values and track user-provided configuration flags; renamed UserProvidedAllToolsEnabled to UserProvidedAllTools |
| src/Config/ObjectModel/McpRuntimeOptions.cs | Changed Enabled parameter to nullable and added default initialization of DmlTools config when null |
| src/Config/Converters/DmlToolsConfigConverter.cs | Updated to reference renamed UserProvidedAllTools property and improved write logic |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs | Added role-based permission filtering, expanded GraphQL aliases support, improved parameter metadata handling |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/CreateRecordTool.cs | Updated tool description with step-by-step instructions for AI models |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/ReadRecordsTool.cs | Updated tool description and parameter ordering, simplified field descriptions |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/UpdateRecordTool.cs | Updated tool description with step-by-step instructions for AI models |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/DeleteRecordTool.cs | Updated tool description with step-by-step instructions for AI models |
| src/Azure.DataApiBuilder.Mcp/BuiltInTools/ExecuteEntityTool.cs | Updated tool description with step-by-step instructions for AI models |
| src/Cli.Tests/ConfigGeneratorTests.cs | Fixed JSON formatting to add comma after mcp path property |
| Test snapshot files (various) | Updated to reflect new DmlTools section with default configuration values |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Why make this change?
Cherry pick MCP fixes and improvements for 1.7.
What is this change?
The PR contains cherry picks from main branch.
Following commits from main are taken-
How was this tested?