From b5578ffeb0cf67d84e0902a15595f9329557461d Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Thu, 24 Jul 2025 15:52:09 -0400 Subject: [PATCH 1/2] feat: add destructive hints, titles, and readonly hints to mcp tools --- src/mcp/tools/customPropertiesTools.ts | 15 ++++++++ src/mcp/tools/environmentTools.ts | 14 ++++++++ src/mcp/tools/featureTools.ts | 49 ++++++++++++++++++++++++++ src/mcp/tools/projectTools.ts | 14 ++++++++ src/mcp/tools/resultsTools.ts | 8 +++++ src/mcp/tools/selfTargetingTools.ts | 21 +++++++++++ src/mcp/tools/variableTools.ts | 15 ++++++++ 7 files changed, 136 insertions(+) diff --git a/src/mcp/tools/customPropertiesTools.ts b/src/mcp/tools/customPropertiesTools.ts index c90786d7d..84dea71ff 100644 --- a/src/mcp/tools/customPropertiesTools.ts +++ b/src/mcp/tools/customPropertiesTools.ts @@ -208,6 +208,10 @@ export const customPropertiesToolDefinitions: Tool[] = [ name: 'list_custom_properties', description: 'List custom properties in the current project. Include dashboard link in the response.', + annotations: { + title: 'List Custom Properties', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: CUSTOM_PROPERTY_PAGINATION_PROPERTIES, @@ -230,6 +234,9 @@ export const customPropertiesToolDefinitions: Tool[] = [ name: 'create_custom_property', description: 'Create a new custom property. Include dashboard link in the response.', + annotations: { + title: 'Create Custom Property', + }, inputSchema: { type: 'object', properties: CUSTOM_PROPERTY_COMMON_PROPERTIES, @@ -248,6 +255,10 @@ export const customPropertiesToolDefinitions: Tool[] = [ name: 'update_custom_property', description: 'Update an existing custom property. ⚠️ IMPORTANT: Custom property changes can affect feature flags in production environments. Always confirm with the user before updating custom properties for features that are active in production. Include dashboard link in the response.', + annotations: { + title: 'Update Custom Property', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: CUSTOM_PROPERTY_COMMON_PROPERTIES, @@ -266,6 +277,10 @@ export const customPropertiesToolDefinitions: Tool[] = [ name: 'delete_custom_property', description: 'Delete a custom property. ⚠️ CRITICAL: Deleting a custom property will remove it from ALL environments including production. ALWAYS confirm with the user before deleting any custom property. Include dashboard link in the response.', + annotations: { + title: 'Delete Custom Property', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { diff --git a/src/mcp/tools/environmentTools.ts b/src/mcp/tools/environmentTools.ts index d588af994..57f360e7f 100644 --- a/src/mcp/tools/environmentTools.ts +++ b/src/mcp/tools/environmentTools.ts @@ -182,6 +182,10 @@ export const environmentToolDefinitions: Tool[] = [ name: 'list_environments', description: 'List environments in the current project. Include dashboard link in the response.', + annotations: { + title: 'List Environments', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: ENVIRONMENT_PAGINATION_PROPERTIES, @@ -205,6 +209,10 @@ export const environmentToolDefinitions: Tool[] = [ name: 'get_sdk_keys', description: 'Get SDK keys for an environment. Include dashboard link in the response.', + annotations: { + title: 'Get SDK Keys', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: { @@ -236,6 +244,9 @@ export const environmentToolDefinitions: Tool[] = [ name: 'create_environment', description: 'Create a new environment. Include dashboard link in the response.', + annotations: { + title: 'Create Environment', + }, inputSchema: { type: 'object', properties: ENVIRONMENT_COMMON_PROPERTIES, @@ -247,6 +258,9 @@ export const environmentToolDefinitions: Tool[] = [ name: 'update_environment', description: 'Update an existing environment. Include dashboard link in the response.', + annotations: { + title: 'Update Environment', + }, inputSchema: { type: 'object', properties: ENVIRONMENT_COMMON_PROPERTIES, diff --git a/src/mcp/tools/featureTools.ts b/src/mcp/tools/featureTools.ts index 1ca469dbc..3184f8658 100644 --- a/src/mcp/tools/featureTools.ts +++ b/src/mcp/tools/featureTools.ts @@ -290,6 +290,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'list_features', description: 'List features in the current project. Include dashboard link in the response.', + annotations: { + title: 'List Feature Flags', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: FEATURE_PAGINATION_PROPERTIES, @@ -311,6 +315,9 @@ export const featureToolDefinitions: Tool[] = [ name: 'create_feature', description: 'Create a new feature flag. Include dashboard link in the response.', + annotations: { + title: 'Create Feature Flag', + }, inputSchema: { type: 'object', properties: { @@ -368,6 +375,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'update_feature', description: 'Update an existing feature flag. ⚠️ IMPORTANT: Changes to feature flags may affect production environments. Always confirm with the user before making changes to features that are active in production. Include dashboard link in the response.', + annotations: { + title: 'Update Feature Flag', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -411,6 +422,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'update_feature_status', description: 'Update the status of an existing feature flag. ⚠️ IMPORTANT: Changes to feature status may affect production environments. Always confirm with the user before making changes to features that are active in production. Include dashboard link in the response.', + annotations: { + title: 'Update Feature Flag Status', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -437,6 +452,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'delete_feature', description: 'Delete an existing feature flag. ⚠️ CRITICAL: Deleting a feature flag will remove it from ALL environments including production. ALWAYS confirm with the user before deleting any feature flag. Include dashboard link in the response.', + annotations: { + title: 'Delete Feature Flag', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -460,6 +479,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'fetch_feature_variations', description: 'Get a list of variations for a feature. Include dashboard link in the response.', + annotations: { + title: 'Get Feature Variations', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: { @@ -484,6 +507,9 @@ export const featureToolDefinitions: Tool[] = [ name: 'create_feature_variation', description: 'Create a new variation within a feature. Include dashboard link in the response.', + annotations: { + title: 'Create Feature Variation', + }, inputSchema: { type: 'object', properties: { @@ -512,6 +538,9 @@ export const featureToolDefinitions: Tool[] = [ name: 'update_feature_variation', description: 'Update an existing variation by key. Include dashboard link in the response.', + annotations: { + title: 'Update Feature Variation', + }, inputSchema: { type: 'object', properties: { @@ -540,6 +569,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'enable_feature_targeting', description: 'Enable targeting for a feature in an environment. ⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Enable Feature Targeting', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -561,6 +594,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'disable_feature_targeting', description: 'Disable targeting for a feature in an environment. ⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Disable Feature Targeting', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -582,6 +619,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'list_feature_targeting', description: 'List feature configurations (targeting rules) for a feature. Include dashboard link in the response.', + annotations: { + title: 'List Feature Targeting Rules', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: { @@ -606,6 +647,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'update_feature_targeting', description: 'Update feature configuration (targeting rules) for a feature in an environment. ⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Update Feature Targeting Rules', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { @@ -740,6 +785,10 @@ export const featureToolDefinitions: Tool[] = [ name: 'get_feature_audit_log_history', description: 'Get timeline of feature flag changes from DevCycle audit log. Include dashboard link in the response.', + annotations: { + title: 'Get Feature Audit Log History', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: { diff --git a/src/mcp/tools/projectTools.ts b/src/mcp/tools/projectTools.ts index 40fb1e178..db444c564 100644 --- a/src/mcp/tools/projectTools.ts +++ b/src/mcp/tools/projectTools.ts @@ -149,6 +149,10 @@ export const projectToolDefinitions: Tool[] = [ name: 'list_projects', description: 'List all projects in the current organization. Include dashboard link in the response.', + annotations: { + title: 'List Projects', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: PROJECT_PAGINATION_PROPERTIES, @@ -170,6 +174,10 @@ export const projectToolDefinitions: Tool[] = [ name: 'get_current_project', description: 'Get the currently selected project. Include dashboard link in the response.', + annotations: { + title: 'Get Current Project', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: {}, @@ -180,6 +188,9 @@ export const projectToolDefinitions: Tool[] = [ name: 'create_project', description: 'Create a new project. Include dashboard link in the response.', + annotations: { + title: 'Create Project', + }, inputSchema: { type: 'object', properties: PROJECT_COMMON_PROPERTIES, @@ -191,6 +202,9 @@ export const projectToolDefinitions: Tool[] = [ name: 'update_project', description: 'Update an existing project. Include dashboard link in the response.', + annotations: { + title: 'Update Project', + }, inputSchema: { type: 'object', properties: PROJECT_COMMON_PROPERTIES, diff --git a/src/mcp/tools/resultsTools.ts b/src/mcp/tools/resultsTools.ts index e0c44c861..6e5235cf6 100644 --- a/src/mcp/tools/resultsTools.ts +++ b/src/mcp/tools/resultsTools.ts @@ -117,6 +117,10 @@ export const resultsToolDefinitions: Tool[] = [ name: 'get_feature_total_evaluations', description: 'Get total variable evaluations per time period for a specific feature. Include dashboard link in the response.', + annotations: { + title: 'Get Feature Total Evaluations', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: FEATURE_EVALUATION_QUERY_PROPERTIES, @@ -128,6 +132,10 @@ export const resultsToolDefinitions: Tool[] = [ name: 'get_project_total_evaluations', description: 'Get total variable evaluations per time period for the entire project. Include dashboard link in the response.', + annotations: { + title: 'Get Project Total Evaluations', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: PROJECT_EVALUATION_QUERY_PROPERTIES, diff --git a/src/mcp/tools/selfTargetingTools.ts b/src/mcp/tools/selfTargetingTools.ts index e67056d74..bec986724 100644 --- a/src/mcp/tools/selfTargetingTools.ts +++ b/src/mcp/tools/selfTargetingTools.ts @@ -96,6 +96,10 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'get_self_targeting_identity', description: 'Get current DevCycle identity for self-targeting. Include dashboard link in the response.', + annotations: { + title: 'Get Self-Targeting Identity', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: {}, @@ -106,6 +110,9 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'update_self_targeting_identity', description: 'Update DevCycle identity for self-targeting and overrides. Include dashboard link in the response.', + annotations: { + title: 'Update Self-Targeting Identity', + }, inputSchema: { type: 'object', properties: { @@ -119,6 +126,10 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'list_self_targeting_overrides', description: 'List all self-targeting overrides for the current project. Include dashboard link in the response.', + annotations: { + title: 'List Self-Targeting Overrides', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: {}, @@ -140,6 +151,9 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'set_self_targeting_override', description: 'Set a self-targeting override for a feature variation. ⚠️ IMPORTANT: Always confirm with the user before setting overrides for production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Set Self-Targeting Override', + }, inputSchema: { type: 'object', properties: OVERRIDE_COMMON_PROPERTIES, @@ -158,6 +172,9 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'clear_feature_self_targeting_overrides', description: 'Clear self-targeting overrides for a specific feature/environment. ⚠️ IMPORTANT: Always confirm with the user before clearing overrides for production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Clear Feature Self-Targeting Overrides', + }, inputSchema: { type: 'object', properties: { @@ -179,6 +196,10 @@ export const selfTargetingToolDefinitions: Tool[] = [ name: 'clear_all_self_targeting_overrides', description: 'Clear all self-targeting overrides for the current project. ⚠️ IMPORTANT: Always confirm with the user before clearing all overrides as it can clear production environments (environments where type = "production"). Include dashboard link in the response.', + annotations: { + title: 'Clear All Self-Targeting Overrides', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: {}, diff --git a/src/mcp/tools/variableTools.ts b/src/mcp/tools/variableTools.ts index 97cdaad58..0a736cbd8 100644 --- a/src/mcp/tools/variableTools.ts +++ b/src/mcp/tools/variableTools.ts @@ -213,6 +213,10 @@ export const variableToolDefinitions: Tool[] = [ name: 'list_variables', description: 'List variables in the current project. Include dashboard link in the response.', + annotations: { + title: 'List Variables', + readOnlyHint: true, + }, inputSchema: { type: 'object', properties: VARIABLE_PAGINATION_PROPERTIES, @@ -234,6 +238,9 @@ export const variableToolDefinitions: Tool[] = [ name: 'create_variable', description: 'Create a new variable. Include dashboard link in the response.', + annotations: { + title: 'Create Variable', + }, inputSchema: { type: 'object', properties: VARIABLE_COMMON_PROPERTIES, @@ -252,6 +259,10 @@ export const variableToolDefinitions: Tool[] = [ name: 'update_variable', description: 'Update an existing variable. ⚠️ IMPORTANT: Variable changes can affect feature flags in production environments. Always confirm with the user before updating variables for features that are active in production. Include dashboard link in the response.', + annotations: { + title: 'Update Variable', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: UPDATE_VARIABLE_PROPERTIES, @@ -270,6 +281,10 @@ export const variableToolDefinitions: Tool[] = [ name: 'delete_variable', description: 'Delete a variable. ⚠️ CRITICAL: Deleting a variable will remove it from ALL environments including production. ALWAYS confirm with the user before deleting any variable. Include dashboard link in the response.', + annotations: { + title: 'Delete Variable', + destructiveHint: true, + }, inputSchema: { type: 'object', properties: { From bb9794100f8e1cf002dae3fc785739d652ff9475 Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Fri, 25 Jul 2025 10:39:48 -0400 Subject: [PATCH 2/2] fix: update tool descriptions --- src/mcp/tools/featureTools.ts | 3 ++- src/mcp/tools/selfTargetingTools.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mcp/tools/featureTools.ts b/src/mcp/tools/featureTools.ts index 3184f8658..2647ccc1d 100644 --- a/src/mcp/tools/featureTools.ts +++ b/src/mcp/tools/featureTools.ts @@ -537,9 +537,10 @@ export const featureToolDefinitions: Tool[] = [ { name: 'update_feature_variation', description: - 'Update an existing variation by key. Include dashboard link in the response.', + 'Update an existing variation by key. ⚠️ WARNING: Updating a feature variation may affect production environments. Include dashboard link in the response.', annotations: { title: 'Update Feature Variation', + destructiveHint: true, }, inputSchema: { type: 'object', diff --git a/src/mcp/tools/selfTargetingTools.ts b/src/mcp/tools/selfTargetingTools.ts index bec986724..e4ae44ec0 100644 --- a/src/mcp/tools/selfTargetingTools.ts +++ b/src/mcp/tools/selfTargetingTools.ts @@ -152,7 +152,7 @@ export const selfTargetingToolDefinitions: Tool[] = [ description: 'Set a self-targeting override for a feature variation. ⚠️ IMPORTANT: Always confirm with the user before setting overrides for production environments (environments where type = "production"). Include dashboard link in the response.', annotations: { - title: 'Set Self-Targeting Override', + title: 'Set Self-Targeting Override For Feature/Environment', }, inputSchema: { type: 'object', @@ -173,7 +173,7 @@ export const selfTargetingToolDefinitions: Tool[] = [ description: 'Clear self-targeting overrides for a specific feature/environment. ⚠️ IMPORTANT: Always confirm with the user before clearing overrides for production environments (environments where type = "production"). Include dashboard link in the response.', annotations: { - title: 'Clear Feature Self-Targeting Overrides', + title: 'Clear Self-Targeting Override For Feature/Environment', }, inputSchema: { type: 'object',